diff options
author | Daniel Stone <[email protected]> | 2018-02-06 17:59:05 +0000 |
---|---|---|
committer | Daniel Stone <[email protected]> | 2018-02-09 16:17:16 +0000 |
commit | 37a8d907cc167279f44e2e15f980cd93869a51f9 (patch) | |
tree | 1f8dcfc116c45b109c35aa5d2c033a76948c9055 /src | |
parent | 8174e5b49e96a98a585b13074d6f1a68e70629d7 (diff) |
egl/gbm: Ensure EGLConfigs match GBM surface format
When we create an EGL window surface on a GBM surface, ensure that the
EGLConfig is compatible with the GBM format, notwithstanding XRGB/ARGB
interchange.
For example, rendering with an XRGB8888 EGLConfig on to an ARGB8888
gbm_surface (and vice-versa) are acceptable, but rendering with an
XRGB2101010 EGLConfig on to an XRGB8888 gbm_surface will now be
rejected.
This was previously allowed through; when 10bpc formats were enabled,
clients which picked a completely random EGL config and hoped/assumed
they were XRGB8888 would break.
If you have bisected a failure to start a GBM/KMS client to this commit,
please look at its EGLConfig selection (e.g. through eglChooseConfigs),
and add an EGL_NATIVE_VISUAL_ID == gbm_surface format match to the
attribs for config selection.
Signed-off-by: Daniel Stone <[email protected]>
Reviewed-by: Emil Velikov <[email protected]>
Tested-by: Ilia Mirkin <[email protected]>
Diffstat (limited to 'src')
-rw-r--r-- | src/egl/drivers/dri2/platform_drm.c | 52 |
1 files changed, 48 insertions, 4 deletions
diff --git a/src/egl/drivers/dri2/platform_drm.c b/src/egl/drivers/dri2/platform_drm.c index 94b5be026c8..3eabd678e92 100644 --- a/src/egl/drivers/dri2/platform_drm.c +++ b/src/egl/drivers/dri2/platform_drm.c @@ -90,6 +90,44 @@ has_free_buffers(struct gbm_surface *_surf) return 0; } +static bool +dri2_drm_config_is_compatible(struct dri2_egl_display *dri2_dpy, + const __DRIconfig *config, + struct gbm_surface *surface) +{ + const struct gbm_dri_visual *visual; + unsigned int red, green, blue, alpha; + int i; + + /* Check that the EGLConfig being used to render to the surface is + * compatible with the surface format. Since mixing ARGB and XRGB of + * otherwise-compatible formats is relatively common, explicitly allow + * this. + */ + dri2_dpy->core->getConfigAttrib(config, __DRI_ATTRIB_RED_MASK, &red); + dri2_dpy->core->getConfigAttrib(config, __DRI_ATTRIB_GREEN_MASK, &green); + dri2_dpy->core->getConfigAttrib(config, __DRI_ATTRIB_BLUE_MASK, &blue); + dri2_dpy->core->getConfigAttrib(config, __DRI_ATTRIB_ALPHA_MASK, &alpha); + + for (i = 0; i < dri2_dpy->gbm_dri->num_visuals; i++) { + visual = &dri2_dpy->gbm_dri->visual_table[i]; + if (visual->gbm_format == surface->format) + break; + } + + if (i == dri2_dpy->gbm_dri->num_visuals) + return false; + + if (red != visual->rgba_masks[0] || + green != visual->rgba_masks[1] || + blue != visual->rgba_masks[2] || + (alpha && visual->rgba_masks[3] && alpha != visual->rgba_masks[3])) { + return false; + } + + return true; +} + static _EGLSurface * dri2_drm_create_window_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf, void *native_surface, @@ -110,18 +148,24 @@ dri2_drm_create_window_surface(_EGLDriver *drv, _EGLDisplay *disp, return NULL; } - if (!dri2_init_surface(&dri2_surf->base, disp, EGL_WINDOW_BIT, conf, attrib_list, false)) + if (!dri2_init_surface(&dri2_surf->base, disp, EGL_WINDOW_BIT, conf, + attrib_list, false)) goto cleanup_surf; + config = dri2_get_dri_config(dri2_conf, EGL_WINDOW_BIT, + dri2_surf->base.GLColorspace); + + if (!dri2_drm_config_is_compatible(dri2_dpy, config, surface)) { + _eglError(EGL_BAD_MATCH, "EGL config not compatible with GBM format"); + goto cleanup_surf; + } + surf = gbm_dri_surface(surface); dri2_surf->gbm_surf = surf; dri2_surf->base.Width = surf->base.width; dri2_surf->base.Height = surf->base.height; surf->dri_private = dri2_surf; - config = dri2_get_dri_config(dri2_conf, EGL_WINDOW_BIT, - dri2_surf->base.GLColorspace); - if (dri2_dpy->dri2) { dri2_surf->dri_drawable = dri2_dpy->dri2->createNewDrawable(dri2_dpy->dri_screen, config, |