mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-02-25 02:50:29 +01:00
egl: Only expose 565 pbuffer configs if X can export them as DRI3 images
Glamor in xorg-server 1.20 cannot expose 16bpp pixmaps when running in
the usual 24bpp mode. This meant our 565 pbuffer configs would
ultimately fail to create a backing pixmap, leading to crashes.
To hack around this, make a 16bpp pixmap and try and export it.
If it works, expose the configs. Otherwise, just skip them.
This also disables them on DRI2. These configs were only added to pass
conformance requirements, and I doubt anybody cares about testing out
565 pbuffer visuals on DRI2-only drivers.
v2: Don't leak the fds (caught by Eric Anholt)
v3: Don't free(fds), it's not malloc'd
Fixes: dacb11a585 ("egl: Add a 565 pbuffer-only EGL config under X11.")
Reviewed-by: Eric Anholt <eric@anholt.net>
This commit is contained in:
parent
6ad31c4ff3
commit
82607f8a90
1 changed files with 77 additions and 35 deletions
|
|
@ -766,9 +766,49 @@ dri2_x11_config_match_attrib(struct dri2_egl_display *dri2_dpy,
|
|||
return config_val == value;
|
||||
}
|
||||
|
||||
/**
|
||||
* See if the X server can export a pixmap with the given color depth.
|
||||
*
|
||||
* Glamor in xorg-server 1.20 can't export pixmaps which have a different
|
||||
* color depth than the root window as a DRI image. This makes it impossible
|
||||
* to expose pbuffer-only visuals with, say, 16bpp on a 24bpp X display.
|
||||
*/
|
||||
static bool
|
||||
x11_can_export_pixmap_with_bpp(struct dri2_egl_display *dri2_dpy, int bpp)
|
||||
{
|
||||
bool supported = false;
|
||||
|
||||
#ifdef HAVE_DRI3
|
||||
xcb_dri3_buffer_from_pixmap_cookie_t cookie;
|
||||
xcb_dri3_buffer_from_pixmap_reply_t *reply;
|
||||
|
||||
xcb_pixmap_t pixmap = xcb_generate_id(dri2_dpy->conn);
|
||||
xcb_create_pixmap(dri2_dpy->conn, bpp, pixmap, dri2_dpy->screen->root, 1, 1);
|
||||
cookie = xcb_dri3_buffer_from_pixmap(dri2_dpy->conn, pixmap);
|
||||
reply = xcb_dri3_buffer_from_pixmap_reply(dri2_dpy->conn, cookie, NULL);
|
||||
|
||||
if (reply) {
|
||||
int *fds = xcb_dri3_buffer_from_pixmap_reply_fds(dri2_dpy->conn, reply);
|
||||
|
||||
for (int i = 0; i < reply->nfd; i++) {
|
||||
close(fds[i]);
|
||||
}
|
||||
|
||||
supported = true;
|
||||
|
||||
free(reply);
|
||||
}
|
||||
|
||||
xcb_free_pixmap(dri2_dpy->conn, pixmap);
|
||||
#endif
|
||||
|
||||
return supported;
|
||||
}
|
||||
|
||||
static EGLBoolean
|
||||
dri2_x11_add_configs_for_visuals(struct dri2_egl_display *dri2_dpy,
|
||||
_EGLDisplay *disp, bool supports_preserved)
|
||||
_EGLDisplay *disp, bool supports_preserved,
|
||||
bool add_pbuffer_configs)
|
||||
{
|
||||
xcb_depth_iterator_t d;
|
||||
xcb_visualtype_t *visuals;
|
||||
|
|
@ -847,39 +887,41 @@ dri2_x11_add_configs_for_visuals(struct dri2_egl_display *dri2_dpy,
|
|||
/* Add a 565-no-depth-no-stencil pbuffer-only config. If X11 is depth 24,
|
||||
* we wouldn't have 565 available, which the CTS demands.
|
||||
*/
|
||||
for (int j = 0; dri2_dpy->driver_configs[j]; j++) {
|
||||
const __DRIconfig *config = dri2_dpy->driver_configs[j];
|
||||
const EGLint config_attrs[] = {
|
||||
EGL_NATIVE_VISUAL_ID, 0,
|
||||
EGL_NATIVE_VISUAL_TYPE, EGL_NONE,
|
||||
EGL_NONE
|
||||
};
|
||||
EGLint surface_type = EGL_PBUFFER_BIT;
|
||||
unsigned int rgba_masks[4] = {
|
||||
0x1f << 11,
|
||||
0x3f << 5,
|
||||
0x1f << 0,
|
||||
0,
|
||||
};
|
||||
if (add_pbuffer_configs && x11_can_export_pixmap_with_bpp(dri2_dpy, 16)) {
|
||||
for (int j = 0; dri2_dpy->driver_configs[j]; j++) {
|
||||
const __DRIconfig *config = dri2_dpy->driver_configs[j];
|
||||
const EGLint config_attrs[] = {
|
||||
EGL_NATIVE_VISUAL_ID, 0,
|
||||
EGL_NATIVE_VISUAL_TYPE, EGL_NONE,
|
||||
EGL_NONE
|
||||
};
|
||||
EGLint surface_type = EGL_PBUFFER_BIT;
|
||||
unsigned int rgba_masks[4] = {
|
||||
0x1f << 11,
|
||||
0x3f << 5,
|
||||
0x1f << 0,
|
||||
0,
|
||||
};
|
||||
|
||||
/* Check that we've found single-sample, no depth, no stencil,
|
||||
* and single-buffered.
|
||||
*/
|
||||
if (!dri2_x11_config_match_attrib(dri2_dpy, config,
|
||||
__DRI_ATTRIB_DEPTH_SIZE, 0) ||
|
||||
!dri2_x11_config_match_attrib(dri2_dpy, config,
|
||||
__DRI_ATTRIB_STENCIL_SIZE, 0) ||
|
||||
!dri2_x11_config_match_attrib(dri2_dpy, config,
|
||||
__DRI_ATTRIB_SAMPLES, 0) ||
|
||||
!dri2_x11_config_match_attrib(dri2_dpy, config,
|
||||
__DRI_ATTRIB_DOUBLE_BUFFER, 0)) {
|
||||
continue;
|
||||
}
|
||||
/* Check that we've found single-sample, no depth, no stencil,
|
||||
* and single-buffered.
|
||||
*/
|
||||
if (!dri2_x11_config_match_attrib(dri2_dpy, config,
|
||||
__DRI_ATTRIB_DEPTH_SIZE, 0) ||
|
||||
!dri2_x11_config_match_attrib(dri2_dpy, config,
|
||||
__DRI_ATTRIB_STENCIL_SIZE, 0) ||
|
||||
!dri2_x11_config_match_attrib(dri2_dpy, config,
|
||||
__DRI_ATTRIB_SAMPLES, 0) ||
|
||||
!dri2_x11_config_match_attrib(dri2_dpy, config,
|
||||
__DRI_ATTRIB_DOUBLE_BUFFER, 0)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (dri2_add_config(disp, config, config_count + 1, surface_type,
|
||||
config_attrs, rgba_masks)) {
|
||||
config_count++;
|
||||
break;
|
||||
if (dri2_add_config(disp, config, config_count + 1, surface_type,
|
||||
config_attrs, rgba_masks)) {
|
||||
config_count++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1360,7 +1402,7 @@ dri2_initialize_x11_swrast(_EGLDriver *drv, _EGLDisplay *disp)
|
|||
|
||||
dri2_setup_screen(disp);
|
||||
|
||||
if (!dri2_x11_add_configs_for_visuals(dri2_dpy, disp, true))
|
||||
if (!dri2_x11_add_configs_for_visuals(dri2_dpy, disp, true, false))
|
||||
goto cleanup;
|
||||
|
||||
/* Fill vtbl last to prevent accidentally calling virtual function during
|
||||
|
|
@ -1458,7 +1500,7 @@ dri2_initialize_x11_dri3(_EGLDriver *drv, _EGLDisplay *disp)
|
|||
|
||||
dri2_set_WL_bind_wayland_display(drv, disp);
|
||||
|
||||
if (!dri2_x11_add_configs_for_visuals(dri2_dpy, disp, false))
|
||||
if (!dri2_x11_add_configs_for_visuals(dri2_dpy, disp, false, true))
|
||||
goto cleanup;
|
||||
|
||||
dri2_dpy->loader_dri3_ext.core = dri2_dpy->core;
|
||||
|
|
@ -1568,7 +1610,7 @@ dri2_initialize_x11_dri2(_EGLDriver *drv, _EGLDisplay *disp)
|
|||
|
||||
dri2_set_WL_bind_wayland_display(drv, disp);
|
||||
|
||||
if (!dri2_x11_add_configs_for_visuals(dri2_dpy, disp, true))
|
||||
if (!dri2_x11_add_configs_for_visuals(dri2_dpy, disp, true, false))
|
||||
goto cleanup;
|
||||
|
||||
/* Fill vtbl last to prevent accidentally calling virtual function during
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue