glx: Fix error handling yet again in CreateContextAttribs
authorAdam Jackson <ajax@redhat.com>
Wed, 21 Jul 2021 16:02:35 +0000 (12:02 -0400)
committerMarge Bot <emma+marge@anholt.net>
Thu, 6 Apr 2023 21:29:54 +0000 (21:29 +0000)
Unlike the legacy CreateContext path, we would try to send the
GLXCreateContextAttribs request regardless of whether we'd successfully
created the client context state. And there's not a lot on the server
side to go wrong besides BadAlloc, so if the request succeeded but
the client side didn't we'd need to destroy the server context and
synthesize an X error. Since that itself involves more X protocol it's
tricky to get the request number right in the error, and tests and apps
can notice when you get it wrong.

Since we have now fixed client-side validation to generate the right
errors at the right times, this patch does something simpler, we match
CreateContext and fail early if the client-side setup fails. Now there's
no question of what request number to use, because we haven't sent any
protocol, the error is for the request as if it'd been sent.

Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/4763
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12006>

src/glx/create_context.c

index fcf468f..f89ceec 100644 (file)
@@ -54,7 +54,7 @@ glXCreateContextAttribsARB(Display *dpy, GLXFBConfig config,
    struct glx_screen *psc;
    xcb_generic_error_t *err;
    xcb_void_cookie_t cookie;
-   unsigned dummy_err = 0;
+   unsigned error = BadImplementation;
    uint32_t xid, share_xid;
    int screen = -1;
 
@@ -100,25 +100,30 @@ glXCreateContextAttribsARB(Display *dpy, GLXFBConfig config,
       direct = true;
    }
 
-
+#ifdef GLX_USE_APPLEGL
+   gc = applegl_create_context(psc, cfg, share, 0);
+#else
    if (direct && psc->vtable->create_context_attribs) {
-      /* GLX drops the error returned by the driver.  The expectation is that
-       * an error will also be returned by the server.  The server's error
-       * will be delivered to the application.
-       */
       gc = psc->vtable->create_context_attribs(psc, cfg, share, num_attribs,
-                                               (const uint32_t *) attrib_list,
-                                               &dummy_err);
-   } 
-#ifdef GLX_USE_APPLEGL
-   else if (gc == NULL) {
-      gc = applegl_create_context(psc, cfg, share, 0);
-   }
-#endif
-   else if (!direct) {
+                                              (const uint32_t *) attrib_list,
+                                              &error);
+   } else if (!direct) {
       gc = indirect_create_context_attribs(psc, cfg, share, num_attribs,
                                            (const uint32_t *) attrib_list,
-                                           &dummy_err);
+                                           &error);
+   }
+#endif
+
+   if (gc == NULL) {
+      /* -1 isn't a legal XID, which is sort of the point, we've failed
+       * before we even got to XID allocation.
+       */
+      if (error == GLXBadContext || error == GLXBadFBConfig ||
+          error == GLXBadProfileARB)
+         __glXSendError(dpy, error, -1, 0, False);
+      else
+         __glXSendError(dpy, error, -1, 0, True);
+      return NULL;
    }
 
    xid = xcb_generate_id(c);
@@ -150,15 +155,6 @@ glXCreateContextAttribsARB(Display *dpy, GLXFBConfig config,
 
       __glXSendErrorForXcb(dpy, err);
       free(err);
-   } else if (!gc) {
-      /* the server thought the context description was okay, but we failed
-       * somehow on the client side. clean up the server resource and panic.
-       */
-      xcb_glx_destroy_context(c, xid);
-      /* increment dpy->request in order to give a unique serial number to the
-       * error */
-      XNoOp(dpy);
-      __glXSendError(dpy, GLXBadFBConfig, xid, 0, False);
    } else {
       gc->xid = xid;
       gc->share_xid = share_xid;