dri: Try harder to infer the drawable fbconfig if needed
authorAdam Jackson <ajax@redhat.com>
Fri, 16 Apr 2021 17:59:29 +0000 (13:59 -0400)
committerMarge Bot <eric+marge@anholt.net>
Thu, 22 Apr 2021 18:11:52 +0000 (18:11 +0000)
This code would work for GLXWindows but not for bare Windows, which I
guess you could argue is a server bug but which we can fix on the client
side with a little effort. We change __glXGetDrawableAttribute to
additionally return false if we failed to find the requested attribute
(which is safe, all the other callers discard the return value). Then
when inferring the fbconfig, if the attribute wasn't found, we ask for
the window attributes to find the visual ID and use that to find the
fbconfig.

Reviewed-by: Eric Anholt <eric@anholt.net>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/10381>

src/glx/dri_common.c
src/glx/glx_pbuffer.c

index 78bd074..8d2590a 100644 (file)
@@ -41,6 +41,8 @@
 #include "glxclient.h"
 #include "dri_common.h"
 #include "loader.h"
+#include <X11/Xlib-xcb.h>
+#include <xcb/xproto.h>
 
 #ifndef RTLD_NOW
 #define RTLD_NOW 0
@@ -344,11 +346,32 @@ static struct glx_config *
 driInferDrawableConfig(struct glx_screen *psc, GLXDrawable draw)
 {
    unsigned int fbconfig = 0;
-
+   xcb_get_window_attributes_cookie_t cookie = { 0 };
+   xcb_get_window_attributes_reply_t *attr = NULL;
+   xcb_connection_t *conn = XGetXCBConnection(psc->dpy);
+
+   /* In practice here, either the XID is a bare Window or it was created
+    * by some other client. First let's see if the X server can tell us
+    * the answer. Xorg first added GLX_EXT_no_config_context in 1.20, where
+    * this usually works except for bare Windows that haven't been made
+    * current yet.
+    */
    if (__glXGetDrawableAttribute(psc->dpy, draw, GLX_FBCONFIG_ID, &fbconfig)) {
       return glx_config_find_fbconfig(psc->configs, fbconfig);
    }
 
+   /* Well this had better be a Window then. Figure out its visual and
+    * then find the corresponding GLX visual.
+    */
+   cookie = xcb_get_window_attributes(conn, draw);
+   attr = xcb_get_window_attributes_reply(conn, cookie, NULL);
+
+   if (attr) {
+      uint32_t vid = attr->visual;
+      free(attr);
+      return glx_config_find_visual(psc->visuals, vid);
+   }
+
    return NULL;
 }
 
@@ -375,6 +398,7 @@ driFetchDrawable(struct glx_context *gc, GLXDrawable glxDrawable)
       return pdraw;
    }
 
+   /* if this is a no-config context, infer the fbconfig from the drawable */
    if (config == NULL)
       config = driInferDrawableConfig(gc->psc, glxDrawable);
    if (config == NULL)
index 74b9b55..7de6430 100644 (file)
@@ -273,6 +273,7 @@ __glXGetDrawableAttribute(Display * dpy, GLXDrawable drawable,
    unsigned int i;
    unsigned int num_attributes;
    GLboolean use_glx_1_3;
+   int found = 0;
 
 #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
    __GLXDRIdrawable *pdraw;
@@ -394,6 +395,7 @@ __glXGetDrawableAttribute(Display * dpy, GLXDrawable drawable,
           */
          for (i = 0; i < num_attributes; i++) {
             if (data[i * 2] == attribute) {
+               found = 1;
                *value = data[(i * 2) + 1];
                break;
             }
@@ -417,7 +419,7 @@ __glXGetDrawableAttribute(Display * dpy, GLXDrawable drawable,
    UnlockDisplay(dpy);
    SyncHandle();
 
-   return 1;
+   return found;
 }
 
 static void