[Mesa-dev] [PATCH] glx: Demand success from CreateContext requests

Olivier Fourdan ofourdan at redhat.com
Mon Aug 6 07:38:29 UTC 2018


Hey

On Fri, Aug 3, 2018 at 7:44 PM Adam Jackson <ajax at redhat.com> wrote:
>
> GLXCreate{,New}Context, like most X resource creation requests, does not
> emit a reply and therefore is emitted into the X stream asynchronously.
> However, unlike most resource creation requests, the GLXContext we
> return is a handle to library state instead of an XID. So if context
> creation fails for any reason - say, the server doesn't support indirect
> contexts - then we will fail in strange places for strange reasons.
>
> We could make every GLX entrypoint robust against half-created contexts,
> or we could just verify that context creation worked. Reuse the
> __glXIsDirect code to do this, as a cheap way of verifying that the
> XID is real.
>
> glXCreateContextAttribsARB solves this by using the _checked version of
> the xcb command, so effectively this change makes the classic context
> creation paths as robust as CreateContextAttribs.
>
> Signed-off-by: Adam Jackson <ajax at redhat.com>
> ---
>  src/glx/glxcmds.c | 92 +++++++++++++++++++++++++++--------------------
>  1 file changed, 54 insertions(+), 38 deletions(-)
>
> diff --git a/src/glx/glxcmds.c b/src/glx/glxcmds.c
> index 4db0228eaba..3789f55d038 100644
> --- a/src/glx/glxcmds.c
> +++ b/src/glx/glxcmds.c
> @@ -272,6 +272,43 @@ glx_context_init(struct glx_context *gc,
>     return True;
>  }
>
> +/**
> + * Determine if a context uses direct rendering.
> + *
> + * \param dpy        Display where the context was created.
> + * \param contextID  ID of the context to be tested.
> + * \param error      Out parameter, set to True on error if not NULL
> + *
> + * \returns \c True if the context is direct rendering or not.
> + */
> +static Bool
> +__glXIsDirect(Display * dpy, GLXContextID contextID, int *error)

Nitpicking, maybe a Bool would be more explicit here (even if it's the
same), it's set to “None” and later set to “True”.

> +{
> +   CARD8 opcode;
> +   xcb_connection_t *c;
> +   xcb_generic_error_t *err;
> +   xcb_glx_is_direct_reply_t *reply;
> +   Bool is_direct;
> +
> +   opcode = __glXSetupForCommand(dpy);
> +   if (!opcode) {
> +      return False;
> +   }
> +
> +   c = XGetXCBConnection(dpy);
> +   reply = xcb_glx_is_direct_reply(c, xcb_glx_is_direct(c, contextID), &err);
> +   is_direct = (reply != NULL && reply->is_direct) ? True : False;
> +
> +   if (err != NULL) {
> +      *error = True;

glXIsDirect() passes “NULL” as “error”, but it's set unconditionally here.

> +      __glXSendErrorForXcb(dpy, err);
> +      free(err);
> +   }
> +
> +   free(reply);
> +
> +   return is_direct;
> +}
>
>  /**
>   * Create a new context.
> @@ -376,6 +413,21 @@ CreateContext(Display *dpy, int generic_id, struct glx_config *config,
>     gc->share_xid = shareList ? shareList->xid : None;
>     gc->imported = GL_FALSE;
>
> +   /* Unlike most X resource creation requests, we're about to return a handle
> +    * with client-side state, not just an XID. To simplify error handling
> +    * elsewhere in libGL, force a round-trip here to ensure the CreateContext
> +    * request above succeeded.
> +    */
> +   {
> +      int error = None;
> +      int isDirect = __glXIsDirect(dpy, gc->xid, &error);
> +
> +      if (error != None || isDirect != gc->isDirect) {
> +         gc->vtable->destroy(gc);
> +         gc = NULL;
> +      }
> +   }
> +
>     return (GLXContext) gc;
>  }
>
> @@ -612,42 +664,6 @@ glXCopyContext(Display * dpy, GLXContext source_user,
>  }
>
>
> -/**
> - * Determine if a context uses direct rendering.
> - *
> - * \param dpy        Display where the context was created.
> - * \param contextID  ID of the context to be tested.
> - *
> - * \returns \c True if the context is direct rendering or not.
> - */
> -static Bool
> -__glXIsDirect(Display * dpy, GLXContextID contextID)
> -{
> -   CARD8 opcode;
> -   xcb_connection_t *c;
> -   xcb_generic_error_t *err;
> -   xcb_glx_is_direct_reply_t *reply;
> -   Bool is_direct;
> -
> -   opcode = __glXSetupForCommand(dpy);
> -   if (!opcode) {
> -      return False;
> -   }
> -
> -   c = XGetXCBConnection(dpy);
> -   reply = xcb_glx_is_direct_reply(c, xcb_glx_is_direct(c, contextID), &err);
> -   is_direct = (reply != NULL && reply->is_direct) ? True : False;
> -
> -   if (err != NULL) {
> -      __glXSendErrorForXcb(dpy, err);
> -      free(err);
> -   }
> -
> -   free(reply);
> -
> -   return is_direct;
> -}
> -
>  /**
>   * \todo
>   * Shouldn't this function \b always return \c False when
> @@ -668,7 +684,7 @@ glXIsDirect(Display * dpy, GLXContext gc_user)
>  #ifdef GLX_USE_APPLEGL  /* TODO: indirect on darwin */
>     return False;
>  #else
> -   return __glXIsDirect(dpy, gc->xid);
> +   return __glXIsDirect(dpy, gc->xid, NULL);
>  #endif
>  }
>
> @@ -1428,7 +1444,7 @@ glXImportContextEXT(Display *dpy, GLXContextID contextID)
>        return NULL;
>     }
>
> -   if (__glXIsDirect(dpy, contextID))
> +   if (__glXIsDirect(dpy, contextID, NULL))
>        return NULL;
>
>     opcode = __glXSetupForCommand(dpy);
> --
> 2.17.0

OIther than the two points above, it works in my test case and avoids
the [xcb] “Unknown sequence number while processing queue” when trying
to catch the XError is IsDirect().


Cheers,
Olivier


More information about the mesa-dev mailing list