From 075a96aa926e6e89795f95a6a59693f44d9ac970 Mon Sep 17 00:00:00 2001 From: Hal Gentz Date: Thu, 10 Oct 2019 18:35:50 -0600 Subject: [PATCH] egl: Configs w/o double buffering support have no `EGL_WINDOW_BIT`. When users pass a config to `eglCreateWindowSurface` it requests double buffering, but if the config doesn't have the appropriate `__DRIconfig`, `eglCreateWindowSurface` fails with a `EGL_BAD_MATCH`. Given that such behaviour is completely unacceptable, we drop the `EGL_WINDOW_BIT` if we don't have at least one `__DRIconfig` supporting double buffering, otherwise dropping the `EGL_PIXMAP_BIT`. Fixes: 049f343e8ac "egl: Allow 24-bit visuals for 32-bit RGBA8888 configs" Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=67676 Cc: mesa-stable@lists.freedesktop.org Reviewed-by: Adam Jackson Signed-off-by: Hal Gentz --- src/egl/drivers/dri2/egl_dri2.c | 57 ++++++++++++++++++--- src/egl/drivers/dri2/egl_dri2.h | 3 ++ src/egl/drivers/dri2/platform_android.c | 2 + src/egl/drivers/dri2/platform_device.c | 2 + src/egl/drivers/dri2/platform_drm.c | 2 + src/egl/drivers/dri2/platform_surfaceless.c | 2 + src/egl/drivers/dri2/platform_wayland.c | 2 + src/egl/drivers/dri2/platform_x11.c | 2 + src/egl/main/eglconfig.c | 10 ++++ src/egl/main/eglconfig.h | 3 ++ 10 files changed, 78 insertions(+), 7 deletions(-) diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c index 63864346594..3d17c8f11cd 100644 --- a/src/egl/drivers/dri2/egl_dri2.c +++ b/src/egl/drivers/dri2/egl_dri2.c @@ -425,10 +425,6 @@ dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id, base.BindToTextureRGBA = bind_to_texture_rgba; } - if (double_buffer) { - surface_type &= ~EGL_PIXMAP_BIT; - } - /* No support for pbuffer + MSAA for now. * * XXX TODO: pbuffer + MSAA does not work and causes crashes. @@ -438,9 +434,6 @@ dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id, surface_type &= ~EGL_PBUFFER_BIT; } - if (!surface_type) - return NULL; - base.RenderableType = disp->ClientAPIs; base.Conformant = disp->ClientAPIs; @@ -490,6 +483,56 @@ dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id, return conf; } +/* + * We finalize the set of `SurfaceType`s supported by a config, and only + * reinsert it if it actually supports something. + */ +void +dri2_finalize_config_surface_types(_EGLDisplay *disp) +{ + _EGLArray *configs = _eglWipeConfigs(disp); + + for (int i = 0; i < configs->Size; ++i) + { + // Since `base` is the first member of `dri2_egl_config`, `base`'s ptr + // should equal `dri2_egl_config`'s. This is why this cast is safe. + struct dri2_egl_config *conf + = (struct dri2_egl_config *) configs->Elements[i]; + + const bool double_buffer = conf->dri_config[true][false] + || conf->dri_config[true][true]; + + const bool single_buffer = conf->dri_config[false][false] + || conf->dri_config[false][true]; + + /* No support for pixmaps without single buffered dri configs. + * + * When users pass a config to `eglCreateWindowSurface` it requests + * double buffering, but if the config doesn't have the appropriate + * `__DRIconfig`, `eglCreateWindowSurface` fails with a `EGL_BAD_MATCH`. + * + * Given that such behaviour is completely unacceptable, we drop the + * `EGL_WINDOW_BIT` if we don't have at least one `__DRIconfig` + * supporting double buffering. + */ + if (!single_buffer) { + conf->base.SurfaceType &= ~EGL_PIXMAP_BIT; + } + + if (!double_buffer) { + conf->base.SurfaceType &= ~EGL_WINDOW_BIT; + } + + // Dont reinsert configs without some supported surface type. + if (!conf->base.SurfaceType) { + free(conf); + continue; + } + + _eglLinkConfig(&conf->base); + } +} + __DRIimage * dri2_lookup_egl_image(__DRIscreen *screen, void *image, void *data) { diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h index 146f954eacf..9bd859869f8 100644 --- a/src/egl/drivers/dri2/egl_dri2.h +++ b/src/egl/drivers/dri2/egl_dri2.h @@ -419,6 +419,9 @@ dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id, EGLint surface_type, const EGLint *attr_list, const int *rgba_shifts, const unsigned int *rgba_sizes); +void +dri2_finalize_config_surface_types(_EGLDisplay *disp); + _EGLImage * dri2_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp, _EGLContext *ctx, EGLenum target, diff --git a/src/egl/drivers/dri2/platform_android.c b/src/egl/drivers/dri2/platform_android.c index 35d40e567dc..e395bb27cb2 100644 --- a/src/egl/drivers/dri2/platform_android.c +++ b/src/egl/drivers/dri2/platform_android.c @@ -1225,6 +1225,8 @@ droid_add_configs_for_visuals(_EGLDriver *drv, _EGLDisplay *disp) has_rgba = true; } + dri2_finalize_config_surface_types(disp); + for (int i = 0; i < ARRAY_SIZE(format_count); i++) { if (!format_count[i]) { _eglLog(_EGL_DEBUG, "No DRI config supports native format 0x%x", diff --git a/src/egl/drivers/dri2/platform_device.c b/src/egl/drivers/dri2/platform_device.c index 9bd7a93270d..b36033ba504 100644 --- a/src/egl/drivers/dri2/platform_device.c +++ b/src/egl/drivers/dri2/platform_device.c @@ -216,6 +216,8 @@ device_add_configs_for_visuals(_EGLDriver *drv, _EGLDisplay *disp) } } + dri2_finalize_config_surface_types(disp); + for (unsigned i = 0; i < ARRAY_SIZE(format_count); i++) { if (!format_count[i]) { _eglLog(_EGL_DEBUG, "No DRI config supports native format %s", diff --git a/src/egl/drivers/dri2/platform_drm.c b/src/egl/drivers/dri2/platform_drm.c index d0ab172d659..551b9392125 100644 --- a/src/egl/drivers/dri2/platform_drm.c +++ b/src/egl/drivers/dri2/platform_drm.c @@ -658,6 +658,8 @@ drm_add_configs_for_visuals(_EGLDriver *drv, _EGLDisplay *disp) } } + dri2_finalize_config_surface_types(disp); + for (unsigned i = 0; i < ARRAY_SIZE(format_count); i++) { if (!format_count[i]) { struct gbm_format_name_desc desc; diff --git a/src/egl/drivers/dri2/platform_surfaceless.c b/src/egl/drivers/dri2/platform_surfaceless.c index 1a2d3be0aad..8361b9ade47 100644 --- a/src/egl/drivers/dri2/platform_surfaceless.c +++ b/src/egl/drivers/dri2/platform_surfaceless.c @@ -212,6 +212,8 @@ surfaceless_add_configs_for_visuals(_EGLDriver *drv, _EGLDisplay *disp) } } + dri2_finalize_config_surface_types(disp); + for (unsigned i = 0; i < ARRAY_SIZE(format_count); i++) { if (!format_count[i]) { _eglLog(_EGL_DEBUG, "No DRI config supports native format %s", diff --git a/src/egl/drivers/dri2/platform_wayland.c b/src/egl/drivers/dri2/platform_wayland.c index 71bcb04a77b..3de9695f45e 100644 --- a/src/egl/drivers/dri2/platform_wayland.c +++ b/src/egl/drivers/dri2/platform_wayland.c @@ -1445,6 +1445,8 @@ dri2_wl_add_configs_for_visuals(_EGLDriver *drv, _EGLDisplay *disp) } } + dri2_finalize_config_surface_types(disp); + for (unsigned i = 0; i < ARRAY_SIZE(format_count); i++) { if (!format_count[i]) { _eglLog(_EGL_DEBUG, "No DRI config supports native format %s", diff --git a/src/egl/drivers/dri2/platform_x11.c b/src/egl/drivers/dri2/platform_x11.c index b3ed7b943da..45c06ae04b3 100644 --- a/src/egl/drivers/dri2/platform_x11.c +++ b/src/egl/drivers/dri2/platform_x11.c @@ -848,6 +848,8 @@ dri2_x11_add_configs_for_visuals(struct dri2_egl_display *dri2_dpy, xcb_depth_next(&d); } + dri2_finalize_config_surface_types(disp); + if (!config_count) { _eglLog(_EGL_WARNING, "DRI2: failed to create any config"); return EGL_FALSE; diff --git a/src/egl/main/eglconfig.c b/src/egl/main/eglconfig.c index b3362363664..b15ba758278 100644 --- a/src/egl/main/eglconfig.c +++ b/src/egl/main/eglconfig.c @@ -71,6 +71,16 @@ _eglInitConfig(_EGLConfig *conf, _EGLDisplay *disp, EGLint id) conf->ComponentType = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT; } +/* + * Wipe the configs list and return the old list + */ +_EGLArray * +_eglWipeConfigs(_EGLDisplay *disp) +{ + _EGLArray *configs = disp->Configs; + disp->Configs = NULL; + return configs; +} /** * Link a config to its display and return the handle of the link. diff --git a/src/egl/main/eglconfig.h b/src/egl/main/eglconfig.h index 064187ff1dd..e9b87d98a9d 100644 --- a/src/egl/main/eglconfig.h +++ b/src/egl/main/eglconfig.h @@ -179,6 +179,9 @@ _eglGetConfigKey(const _EGLConfig *conf, EGLint key) extern void _eglInitConfig(_EGLConfig *config, _EGLDisplay *disp, EGLint id); +extern _EGLArray * +_eglWipeConfigs(_EGLDisplay *disp); + extern EGLConfig _eglLinkConfig(_EGLConfig *conf); -- 2.30.2