egl: Configs w/o double buffering support have no `EGL_WINDOW_BIT`.
authorHal Gentz <zegentzy@protonmail.com>
Fri, 11 Oct 2019 00:35:50 +0000 (18:35 -0600)
committerAdam Jackson <ajax@nwnk.net>
Fri, 11 Oct 2019 21:57:21 +0000 (21:57 +0000)
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 <ajax@redhat.com>
Signed-off-by: Hal Gentz <zegentzy@protonmail.com>
src/egl/drivers/dri2/egl_dri2.c
src/egl/drivers/dri2/egl_dri2.h
src/egl/drivers/dri2/platform_android.c
src/egl/drivers/dri2/platform_device.c
src/egl/drivers/dri2/platform_drm.c
src/egl/drivers/dri2/platform_surfaceless.c
src/egl/drivers/dri2/platform_wayland.c
src/egl/drivers/dri2/platform_x11.c
src/egl/main/eglconfig.c
src/egl/main/eglconfig.h

index 63864346594bd6ead832d92ffe970d97b006a6a2..3d17c8f11cde810949f77efa8cfc3159b83d1dd0 100644 (file)
@@ -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)
 {
index 146f954eacf5ecd22727d7ae1128b0184d2f2696..9bd859869f87d43f2a3248bbd86282fd43e516fc 100644 (file)
@@ -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,
index 35d40e567dc652e684d82d0369361ab64cfb1e6b..e395bb27cb21147540de8e2003d81e0da22b69f2 100644 (file)
@@ -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",
index 9bd7a93270de144324f194f2624a09e85686bcef..b36033ba5041dc0494cb45e52a683ca6d4e66ce6 100644 (file)
@@ -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",
index d0ab172d65901d11e8b672c5e1054ce6f6e8d2bc..551b939212539786ced19db872d200b7d10006db 100644 (file)
@@ -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;
index 1a2d3be0aad76887cd37ae687a27829524cbb3ac..8361b9ade47d726e98487df09a69a125a323e4d0 100644 (file)
@@ -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",
index 71bcb04a77b9d8230947bb5858a0c1e646fe034d..3de9695f45ef6d98b1a5d06e148360a26c82cebc 100644 (file)
@@ -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",
index b3ed7b943da14c5cca1607db6aee09014e31ef89..45c06ae04b3b16a7826e637b980ff058764ddc9b 100644 (file)
@@ -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;
index b3362363664916f8dd3ba35469f87e106fbe9141..b15ba758278cf9e69b56647d00edf0b3e46a85b7 100644 (file)
@@ -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.
index 064187ff1dd063d6ce4b9f9b831b4aa800b21460..e9b87d98a9d242a795cd17925421f5fc6dbe5b92 100644 (file)
@@ -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);