diff --git a/docs/relnotes/new_features.txt b/docs/relnotes/new_features.txt index 840409c0864c5..a27b9eff0f9d8 100644 --- a/docs/relnotes/new_features.txt +++ b/docs/relnotes/new_features.txt @@ -19,3 +19,4 @@ VK_KHR_synchronization2 on Intel NGG shader based culling is now enabled by default on GFX10.3 on RADV. VK_KHR_maintenance4 on RADV VK_KHR_format_feature_flags2 on RADV. +EGL_EXT_present_opaque on wayland diff --git a/src/egl/drivers/dri2/platform_wayland.c b/src/egl/drivers/dri2/platform_wayland.c index 574ee3158563f..e37579995e57e 100644 --- a/src/egl/drivers/dri2/platform_wayland.c +++ b/src/egl/drivers/dri2/platform_wayland.c @@ -157,7 +157,8 @@ static_assert(ARRAY_SIZE(dri2_wl_visuals) <= EGL_DRI2_MAX_FORMATS, static int dri2_wl_visual_idx_from_config(struct dri2_egl_display *dri2_dpy, - const __DRIconfig *config) + const __DRIconfig *config, + bool force_opaque) { int shifts[4]; unsigned int sizes[4]; @@ -167,14 +168,14 @@ dri2_wl_visual_idx_from_config(struct dri2_egl_display *dri2_dpy, for (unsigned int i = 0; i < ARRAY_SIZE(dri2_wl_visuals); i++) { const struct dri2_wl_visual *wl_visual = &dri2_wl_visuals[i]; - if (shifts[0] == wl_visual->rgba_shifts[0] && - shifts[1] == wl_visual->rgba_shifts[1] && - shifts[2] == wl_visual->rgba_shifts[2] && - shifts[3] == wl_visual->rgba_shifts[3] && - sizes[0] == wl_visual->rgba_sizes[0] && - sizes[1] == wl_visual->rgba_sizes[1] && - sizes[2] == wl_visual->rgba_sizes[2] && - sizes[3] == wl_visual->rgba_sizes[3]) { + int cmp_rgb_shifts = memcmp(shifts, wl_visual->rgba_shifts, + 3 * sizeof(shifts[0])); + int cmp_rgb_sizes = memcmp(sizes, wl_visual->rgba_sizes, + 3 * sizeof(sizes[0])); + + if (cmp_rgb_shifts == 0 && cmp_rgb_sizes == 0 && + wl_visual->rgba_shifts[3] == (force_opaque ? -1 : shifts[3]) && + wl_visual->rgba_sizes[3] == (force_opaque ? 0 : sizes[3])) { return i; } } @@ -229,7 +230,8 @@ dri2_wl_is_format_supported(void* user_data, uint32_t format) for (int i = 0; dri2_dpy->driver_configs[i]; i++) if (j == dri2_wl_visual_idx_from_config(dri2_dpy, - dri2_dpy->driver_configs[i])) + dri2_dpy->driver_configs[i], + false)) return true; return false; @@ -356,7 +358,42 @@ dri2_wl_create_window_surface(_EGLDisplay *disp, _EGLConfig *conf, dri2_surf->base.Width = window->width; dri2_surf->base.Height = window->height; - visual_idx = dri2_wl_visual_idx_from_config(dri2_dpy, config); +#ifndef NDEBUG + /* Enforce that every visual has an opaque variant (requirement to support + * EGL_EXT_present_opaque) + */ + for (unsigned int i = 0; i < ARRAY_SIZE(dri2_wl_visuals); i++) { + const struct dri2_wl_visual *transparent_visual = &dri2_wl_visuals[i]; + if (transparent_visual->rgba_sizes[3] == 0) { + continue; + } + + bool found_opaque_equivalent = false; + for (unsigned int j = 0; j < ARRAY_SIZE(dri2_wl_visuals); j++) { + const struct dri2_wl_visual *opaque_visual = &dri2_wl_visuals[j]; + if (opaque_visual->rgba_sizes[3] != 0) { + continue; + } + + int cmp_rgb_shifts = memcmp(transparent_visual->rgba_shifts, + opaque_visual->rgba_shifts, + 3 * sizeof(opaque_visual->rgba_shifts[0])); + int cmp_rgb_sizes = memcmp(transparent_visual->rgba_sizes, + opaque_visual->rgba_sizes, + 3 * sizeof(opaque_visual->rgba_sizes[0])); + + if (cmp_rgb_shifts == 0 && cmp_rgb_sizes == 0) { + found_opaque_equivalent = true; + break; + } + } + + assert(found_opaque_equivalent); + } +#endif + + visual_idx = dri2_wl_visual_idx_from_config(dri2_dpy, config, + dri2_surf->base.PresentOpaque); assert(visual_idx != -1); if (dri2_dpy->wl_dmabuf || dri2_dpy->wl_drm) { @@ -1438,7 +1475,8 @@ dri2_wl_add_configs_for_visuals(_EGLDisplay *disp) /* No match for config. Try if we can blitImage convert to a visual */ c = dri2_wl_visual_idx_from_config(dri2_dpy, - dri2_dpy->driver_configs[i]); + dri2_dpy->driver_configs[i], + false); if (c == -1) continue; @@ -1637,6 +1675,8 @@ dri2_initialize_wayland_drm(_EGLDisplay *disp) disp->Extensions.EXT_swap_buffers_with_damage = EGL_TRUE; + disp->Extensions.EXT_present_opaque = EGL_TRUE; + /* Fill vtbl last to prevent accidentally calling virtual function during * initialization. */ diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c index 17e36af22e1ff..437865df0fef9 100644 --- a/src/egl/main/eglapi.c +++ b/src/egl/main/eglapi.c @@ -502,6 +502,7 @@ _eglCreateExtensionsString(_EGLDisplay *disp) _EGL_CHECK_EXTENSION(EXT_image_dma_buf_import); _EGL_CHECK_EXTENSION(EXT_image_dma_buf_import_modifiers); _EGL_CHECK_EXTENSION(EXT_protected_surface); + _EGL_CHECK_EXTENSION(EXT_present_opaque); _EGL_CHECK_EXTENSION(EXT_surface_CTA861_3_metadata); _EGL_CHECK_EXTENSION(EXT_surface_SMPTE2086_metadata); _EGL_CHECK_EXTENSION(EXT_swap_buffers_with_damage); diff --git a/src/egl/main/egldisplay.h b/src/egl/main/egldisplay.h index 66fb5b946e589..0ee06a487c0a7 100644 --- a/src/egl/main/egldisplay.h +++ b/src/egl/main/egldisplay.h @@ -109,6 +109,7 @@ struct _egl_extensions EGLBoolean EXT_image_dma_buf_import_modifiers; EGLBoolean EXT_pixel_format_float; EGLBoolean EXT_protected_surface; + EGLBoolean EXT_present_opaque; EGLBoolean EXT_surface_CTA861_3_metadata; EGLBoolean EXT_surface_SMPTE2086_metadata; EGLBoolean EXT_swap_buffers_with_damage; diff --git a/src/egl/main/eglsurface.c b/src/egl/main/eglsurface.c index aee52178995bc..9167b9b7eed0a 100644 --- a/src/egl/main/eglsurface.c +++ b/src/egl/main/eglsurface.c @@ -216,6 +216,21 @@ _eglParseSurfaceAttribList(_EGLSurface *surf, const EGLint *attrib_list) surf->ActiveRenderBuffer = val; } break; + case EGL_PRESENT_OPAQUE_EXT: + if (!disp->Extensions.EXT_present_opaque) { + err = EGL_BAD_ATTRIBUTE; + break; + } + if (type != EGL_WINDOW_BIT) { + err = EGL_BAD_ATTRIBUTE; + break; + } + if (val != EGL_TRUE && val != EGL_FALSE) { + err = EGL_BAD_PARAMETER; + break; + } + surf->PresentOpaque = val; + break; case EGL_POST_SUB_BUFFER_SUPPORTED_NV: if (!disp->Extensions.NV_post_sub_buffer || type != EGL_WINDOW_BIT) { @@ -392,6 +407,7 @@ _eglInitSurface(_EGLSurface *surf, _EGLDisplay *disp, EGLint type, surf->VGColorspace = EGL_VG_COLORSPACE_sRGB; surf->GLColorspace = EGL_GL_COLORSPACE_LINEAR_KHR; surf->ProtectedContent = EGL_FALSE; + surf->PresentOpaque = EGL_FALSE; surf->MipmapLevel = 0; surf->MultisampleResolve = EGL_MULTISAMPLE_RESOLVE_DEFAULT; @@ -595,6 +611,11 @@ _eglQuerySurface(_EGLDisplay *disp, _EGLSurface *surface, return _eglError(EGL_BAD_ATTRIBUTE, "eglQuerySurface"); *value = surface->ProtectedContent; break; + case EGL_PRESENT_OPAQUE_EXT: + if (!disp->Extensions.EXT_present_opaque) + return _eglError(EGL_BAD_ATTRIBUTE, "eglQuerySurface"); + *value = surface->PresentOpaque; + break; default: return _eglError(EGL_BAD_ATTRIBUTE, "eglQuerySurface"); } diff --git a/src/egl/main/eglsurface.h b/src/egl/main/eglsurface.h index 7f419cbf7e38b..b26768363d93e 100644 --- a/src/egl/main/eglsurface.h +++ b/src/egl/main/eglsurface.h @@ -171,6 +171,8 @@ struct _egl_surface EGLBoolean ProtectedContent; + EGLBoolean PresentOpaque; + struct _egl_hdr_metadata HdrMetadata; void *NativeSurface;