vulkan/wsi/wayland: don't expose surface formats not fully supported

Depending on whether an application creates a swapchain with
VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR or not, we might use 2
different formats with the compositor.

This change makes sure that we support all the underlying formats
before exposing the corresponding VkFormat to the application.

v2: Don't forget get_formats2() (Ivan)

v3: Replace formats with availability boolean (Simon)

Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Fixes: 151b65b211 ("vulkan/wsi/wayland: generalize modifier handling")
Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/5522
Reviewed-by: Ivan Briano <ivan.briano@intel.com> (v2)
Reviewed-by: Simon Ser <contact@emersion.fr>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/13453>
This commit is contained in:
Lionel Landwerlin 2021-10-20 11:08:34 +03:00
parent 1c4f1c2290
commit d944136f36

View file

@ -52,6 +52,8 @@ struct wsi_wayland;
struct wsi_wl_format { struct wsi_wl_format {
VkFormat vk_format; VkFormat vk_format;
uint32_t has_alpha_format;
uint32_t has_opaque_format;
struct u_vector modifiers; struct u_vector modifiers;
}; };
@ -99,12 +101,20 @@ find_format(struct u_vector *formats, VkFormat format)
static struct wsi_wl_format * static struct wsi_wl_format *
wsi_wl_display_add_vk_format(struct wsi_wl_display *display, wsi_wl_display_add_vk_format(struct wsi_wl_display *display,
struct u_vector *formats, VkFormat format) struct u_vector *formats,
VkFormat format,
bool has_alpha_format,
bool has_opaque_format)
{ {
/* Don't add a format that's already in the list */ /* Don't add a format that's already in the list */
struct wsi_wl_format *f = find_format(formats, format); struct wsi_wl_format *f = find_format(formats, format);
if (f) if (f) {
if (has_alpha_format)
f->has_alpha_format = true;
if (has_opaque_format)
f->has_opaque_format = true;
return f; return f;
}
/* Don't add formats that aren't renderable. */ /* Don't add formats that aren't renderable. */
VkFormatProperties props; VkFormatProperties props;
@ -125,6 +135,8 @@ wsi_wl_display_add_vk_format(struct wsi_wl_display *display,
} }
f->vk_format = format; f->vk_format = format;
f->has_alpha_format = has_alpha_format;
f->has_opaque_format = has_opaque_format;
f->modifiers = modifiers; f->modifiers = modifiers;
return f; return f;
@ -159,14 +171,24 @@ wsi_wl_display_add_drm_format_modifier(struct wsi_wl_display *display,
/* TODO: These are only available when VK_EXT_4444_formats is enabled, so /* TODO: These are only available when VK_EXT_4444_formats is enabled, so
* we probably need to make their use conditional on this extension. */ * we probably need to make their use conditional on this extension. */
case DRM_FORMAT_ARGB4444: case DRM_FORMAT_ARGB4444:
format = wsi_wl_display_add_vk_format(display, formats,
VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT,
true, false);
break;
case DRM_FORMAT_XRGB4444: case DRM_FORMAT_XRGB4444:
format = wsi_wl_display_add_vk_format(display, formats, format = wsi_wl_display_add_vk_format(display, formats,
VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT); VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT,
false, true);
break; break;
case DRM_FORMAT_ABGR4444: case DRM_FORMAT_ABGR4444:
format = wsi_wl_display_add_vk_format(display, formats,
VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT,
true, false);
break;
case DRM_FORMAT_XBGR4444: case DRM_FORMAT_XBGR4444:
format = wsi_wl_display_add_vk_format(display, formats, format = wsi_wl_display_add_vk_format(display, formats,
VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT); VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT,
false, true);
break; break;
#endif #endif
@ -174,47 +196,84 @@ wsi_wl_display_add_drm_format_modifier(struct wsi_wl_display *display,
* on little endian systems, on big endian there exists no analog. */ * on little endian systems, on big endian there exists no analog. */
#if MESA_LITTLE_ENDIAN #if MESA_LITTLE_ENDIAN
case DRM_FORMAT_RGBA4444: case DRM_FORMAT_RGBA4444:
format = wsi_wl_display_add_vk_format(display, formats,
VK_FORMAT_R4G4B4A4_UNORM_PACK16,
true, false);
break;
case DRM_FORMAT_RGBX4444: case DRM_FORMAT_RGBX4444:
format = wsi_wl_display_add_vk_format(display, formats, format = wsi_wl_display_add_vk_format(display, formats,
VK_FORMAT_R4G4B4A4_UNORM_PACK16); VK_FORMAT_R4G4B4A4_UNORM_PACK16,
false, true);
break; break;
case DRM_FORMAT_BGRA4444: case DRM_FORMAT_BGRA4444:
format = wsi_wl_display_add_vk_format(display, formats,
VK_FORMAT_B4G4R4A4_UNORM_PACK16,
true, false);
break;
case DRM_FORMAT_BGRX4444: case DRM_FORMAT_BGRX4444:
format = wsi_wl_display_add_vk_format(display, formats, format = wsi_wl_display_add_vk_format(display, formats,
VK_FORMAT_B4G4R4A4_UNORM_PACK16); VK_FORMAT_B4G4R4A4_UNORM_PACK16,
false, true);
break; break;
case DRM_FORMAT_RGB565: case DRM_FORMAT_RGB565:
format = wsi_wl_display_add_vk_format(display, formats, format = wsi_wl_display_add_vk_format(display, formats,
VK_FORMAT_R5G6B5_UNORM_PACK16); VK_FORMAT_R5G6B5_UNORM_PACK16,
true, true);
break; break;
case DRM_FORMAT_BGR565: case DRM_FORMAT_BGR565:
format = wsi_wl_display_add_vk_format(display, formats, format = wsi_wl_display_add_vk_format(display, formats,
VK_FORMAT_B5G6R5_UNORM_PACK16); VK_FORMAT_B5G6R5_UNORM_PACK16,
true, true);
break; break;
case DRM_FORMAT_ARGB1555: case DRM_FORMAT_ARGB1555:
format = wsi_wl_display_add_vk_format(display, formats,
VK_FORMAT_A1R5G5B5_UNORM_PACK16,
true, false);
break;
case DRM_FORMAT_XRGB1555: case DRM_FORMAT_XRGB1555:
format = wsi_wl_display_add_vk_format(display, formats, format = wsi_wl_display_add_vk_format(display, formats,
VK_FORMAT_A1R5G5B5_UNORM_PACK16); VK_FORMAT_A1R5G5B5_UNORM_PACK16,
false, true);
break; break;
case DRM_FORMAT_RGBA5551: case DRM_FORMAT_RGBA5551:
format = wsi_wl_display_add_vk_format(display, formats,
VK_FORMAT_R5G5B5A1_UNORM_PACK16,
true, false);
break;
case DRM_FORMAT_RGBX5551: case DRM_FORMAT_RGBX5551:
format = wsi_wl_display_add_vk_format(display, formats, format = wsi_wl_display_add_vk_format(display, formats,
VK_FORMAT_R5G5B5A1_UNORM_PACK16); VK_FORMAT_R5G5B5A1_UNORM_PACK16,
false, true);
break; break;
case DRM_FORMAT_BGRA5551: case DRM_FORMAT_BGRA5551:
format = wsi_wl_display_add_vk_format(display, formats,
VK_FORMAT_B5G5R5A1_UNORM_PACK16,
true, false);
break;
case DRM_FORMAT_BGRX5551: case DRM_FORMAT_BGRX5551:
format = wsi_wl_display_add_vk_format(display, formats, format = wsi_wl_display_add_vk_format(display, formats,
VK_FORMAT_B5G5R5A1_UNORM_PACK16); VK_FORMAT_B5G5R5A1_UNORM_PACK16,
false, true);
break; break;
case DRM_FORMAT_ARGB2101010: case DRM_FORMAT_ARGB2101010:
format = wsi_wl_display_add_vk_format(display, formats,
VK_FORMAT_A2R10G10B10_UNORM_PACK32,
true, false);
break;
case DRM_FORMAT_XRGB2101010: case DRM_FORMAT_XRGB2101010:
format = wsi_wl_display_add_vk_format(display, formats, format = wsi_wl_display_add_vk_format(display, formats,
VK_FORMAT_A2R10G10B10_UNORM_PACK32); VK_FORMAT_A2R10G10B10_UNORM_PACK32,
false, true);
break; break;
case DRM_FORMAT_ABGR2101010: case DRM_FORMAT_ABGR2101010:
format = wsi_wl_display_add_vk_format(display, formats,
VK_FORMAT_A2B10G10R10_UNORM_PACK32,
true, false);
break;
case DRM_FORMAT_XBGR2101010: case DRM_FORMAT_XBGR2101010:
format = wsi_wl_display_add_vk_format(display, formats, format = wsi_wl_display_add_vk_format(display, formats,
VK_FORMAT_A2B10G10R10_UNORM_PACK32); VK_FORMAT_A2B10G10R10_UNORM_PACK32,
false, true);
break; break;
#endif #endif
@ -230,27 +289,35 @@ wsi_wl_display_add_drm_format_modifier(struct wsi_wl_display *display,
* Vulkan interprets the pixel data. */ * Vulkan interprets the pixel data. */
case DRM_FORMAT_XBGR8888: case DRM_FORMAT_XBGR8888:
srgb_format = wsi_wl_display_add_vk_format(display, formats, srgb_format = wsi_wl_display_add_vk_format(display, formats,
VK_FORMAT_R8G8B8_SRGB); VK_FORMAT_R8G8B8_SRGB,
true, true);
format = wsi_wl_display_add_vk_format(display, formats, format = wsi_wl_display_add_vk_format(display, formats,
VK_FORMAT_R8G8B8_UNORM); VK_FORMAT_R8G8B8_UNORM,
true, true);
FALLTHROUGH; FALLTHROUGH;
case DRM_FORMAT_ABGR8888: case DRM_FORMAT_ABGR8888:
srgb_format = wsi_wl_display_add_vk_format(display, formats, srgb_format = wsi_wl_display_add_vk_format(display, formats,
VK_FORMAT_R8G8B8A8_SRGB); VK_FORMAT_R8G8B8A8_SRGB,
true, true);
format = wsi_wl_display_add_vk_format(display, formats, format = wsi_wl_display_add_vk_format(display, formats,
VK_FORMAT_R8G8B8A8_UNORM); VK_FORMAT_R8G8B8A8_UNORM,
true, true);
break; break;
case DRM_FORMAT_XRGB8888: case DRM_FORMAT_XRGB8888:
srgb_format = wsi_wl_display_add_vk_format(display, formats, srgb_format = wsi_wl_display_add_vk_format(display, formats,
VK_FORMAT_B8G8R8_SRGB); VK_FORMAT_B8G8R8_SRGB,
true, true);
format = wsi_wl_display_add_vk_format(display, formats, format = wsi_wl_display_add_vk_format(display, formats,
VK_FORMAT_B8G8R8_UNORM); VK_FORMAT_B8G8R8_UNORM,
true, true);
FALLTHROUGH; FALLTHROUGH;
case DRM_FORMAT_ARGB8888: case DRM_FORMAT_ARGB8888:
srgb_format = wsi_wl_display_add_vk_format(display, formats, srgb_format = wsi_wl_display_add_vk_format(display, formats,
VK_FORMAT_B8G8R8A8_SRGB); VK_FORMAT_B8G8R8A8_SRGB,
true, true);
format = wsi_wl_display_add_vk_format(display, formats, format = wsi_wl_display_add_vk_format(display, formats,
VK_FORMAT_B8G8R8A8_UNORM); VK_FORMAT_B8G8R8A8_UNORM,
true, true);
break; break;
} }
@ -268,27 +335,35 @@ wsi_wl_display_add_wl_shm_format(struct wsi_wl_display *display,
switch (wl_shm_format) { switch (wl_shm_format) {
case WL_SHM_FORMAT_XBGR8888: case WL_SHM_FORMAT_XBGR8888:
wsi_wl_display_add_vk_format(display, formats, wsi_wl_display_add_vk_format(display, formats,
VK_FORMAT_R8G8B8_SRGB); VK_FORMAT_R8G8B8_SRGB,
false, true);
wsi_wl_display_add_vk_format(display, formats, wsi_wl_display_add_vk_format(display, formats,
VK_FORMAT_R8G8B8_UNORM); VK_FORMAT_R8G8B8_UNORM,
false, true);
FALLTHROUGH; FALLTHROUGH;
case WL_SHM_FORMAT_ABGR8888: case WL_SHM_FORMAT_ABGR8888:
wsi_wl_display_add_vk_format(display, formats, wsi_wl_display_add_vk_format(display, formats,
VK_FORMAT_R8G8B8A8_SRGB); VK_FORMAT_R8G8B8A8_SRGB,
true, false);
wsi_wl_display_add_vk_format(display, formats, wsi_wl_display_add_vk_format(display, formats,
VK_FORMAT_R8G8B8A8_UNORM); VK_FORMAT_R8G8B8A8_UNORM,
true, false);
break; break;
case WL_SHM_FORMAT_XRGB8888: case WL_SHM_FORMAT_XRGB8888:
wsi_wl_display_add_vk_format(display, formats, wsi_wl_display_add_vk_format(display, formats,
VK_FORMAT_B8G8R8_SRGB); VK_FORMAT_B8G8R8_SRGB,
false, true);
wsi_wl_display_add_vk_format(display, formats, wsi_wl_display_add_vk_format(display, formats,
VK_FORMAT_B8G8R8_UNORM); VK_FORMAT_B8G8R8_UNORM,
false, true);
FALLTHROUGH; FALLTHROUGH;
case WL_SHM_FORMAT_ARGB8888: case WL_SHM_FORMAT_ARGB8888:
wsi_wl_display_add_vk_format(display, formats, wsi_wl_display_add_vk_format(display, formats,
VK_FORMAT_B8G8R8A8_SRGB); VK_FORMAT_B8G8R8A8_SRGB,
true, false);
wsi_wl_display_add_vk_format(display, formats, wsi_wl_display_add_vk_format(display, formats,
VK_FORMAT_B8G8R8A8_UNORM); VK_FORMAT_B8G8R8A8_UNORM,
true, false);
break; break;
} }
} }
@ -698,6 +773,13 @@ wsi_wl_surface_get_formats(VkIcdSurfaceBase *icd_surface,
struct wsi_wl_format *disp_fmt; struct wsi_wl_format *disp_fmt;
u_vector_foreach(disp_fmt, &display.formats) { u_vector_foreach(disp_fmt, &display.formats) {
/* Skip formats for which we can't support both alpha & opaque
* formats.
*/
if (!disp_fmt->has_opaque_format ||
!disp_fmt->has_alpha_format)
continue;
vk_outarray_append(&out, out_fmt) { vk_outarray_append(&out, out_fmt) {
out_fmt->format = disp_fmt->vk_format; out_fmt->format = disp_fmt->vk_format;
out_fmt->colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR; out_fmt->colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
@ -729,6 +811,13 @@ wsi_wl_surface_get_formats2(VkIcdSurfaceBase *icd_surface,
struct wsi_wl_format *disp_fmt; struct wsi_wl_format *disp_fmt;
u_vector_foreach(disp_fmt, &display.formats) { u_vector_foreach(disp_fmt, &display.formats) {
/* Skip formats for which we can't support both alpha & opaque
* formats.
*/
if (!disp_fmt->has_opaque_format ||
!disp_fmt->has_alpha_format)
continue;
vk_outarray_append(&out, out_fmt) { vk_outarray_append(&out, out_fmt) {
out_fmt->surfaceFormat.format = disp_fmt->vk_format; out_fmt->surfaceFormat.format = disp_fmt->vk_format;
out_fmt->surfaceFormat.colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR; out_fmt->surfaceFormat.colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;