From: Adam Jackson Date: Thu, 26 Sep 2019 15:07:42 +0000 (-0400) Subject: Revert "glx: Lift sending the MakeCurrent request to top-level code" X-Git-Url: https://git.libre-soc.org/?p=mesa.git;a=commitdiff_plain;h=8b6d3f2c782b1e6559b49f106f24d2d586f0d71d Revert "glx: Lift sending the MakeCurrent request to top-level code" Apparently this provokes crashes elsewhere in code unrelated to MakeCurrent. I hate GLX so very very much. This reverts commit 999c2aed8826f403b071f52b040ce25b56d35f9d. Gitlab: https://gitlab.freedesktop.org/mesa/mesa/issues/1207 --- diff --git a/src/glx/glxcurrent.c b/src/glx/glxcurrent.c index 7172009c34c..a388df7a78d 100644 --- a/src/glx/glxcurrent.c +++ b/src/glx/glxcurrent.c @@ -165,100 +165,17 @@ glXGetCurrentDrawable(void) return gc->currentDrawable; } -static Bool -SendMakeCurrentRequest(Display * dpy, GLXContextID gc_id, - GLXContextTag gc_tag, GLXDrawable draw, - GLXDrawable read, GLXContextTag *out_tag) -{ - xGLXMakeCurrentReply reply; - Bool ret; - int opcode = __glXSetupForCommand(dpy); - - LockDisplay(dpy); - - if (draw == read) { - xGLXMakeCurrentReq *req; - - GetReq(GLXMakeCurrent, req); - req->reqType = opcode; - req->glxCode = X_GLXMakeCurrent; - req->drawable = draw; - req->context = gc_id; - req->oldContextTag = gc_tag; - } - else { - struct glx_display *priv = __glXInitialize(dpy); - - if ((priv->majorVersion > 1) || (priv->minorVersion >= 3)) { - xGLXMakeContextCurrentReq *req; - - GetReq(GLXMakeContextCurrent, req); - req->reqType = opcode; - req->glxCode = X_GLXMakeContextCurrent; - req->drawable = draw; - req->readdrawable = read; - req->context = gc_id; - req->oldContextTag = gc_tag; - } - else { - xGLXVendorPrivateWithReplyReq *vpreq; - xGLXMakeCurrentReadSGIReq *req; - - GetReqExtra(GLXVendorPrivateWithReply, - sz_xGLXMakeCurrentReadSGIReq - - sz_xGLXVendorPrivateWithReplyReq, vpreq); - req = (xGLXMakeCurrentReadSGIReq *) vpreq; - req->reqType = opcode; - req->glxCode = X_GLXVendorPrivateWithReply; - req->vendorCode = X_GLXvop_MakeCurrentReadSGI; - req->drawable = draw; - req->readable = read; - req->context = gc_id; - req->oldContextTag = gc_tag; - } - } - - ret = _XReply(dpy, (xReply *) &reply, 0, False); - - - if (ret == 1) - *out_tag = reply.contextTag; - - UnlockDisplay(dpy); - SyncHandle(); - - return ret; -} - -static void -SetGC(struct glx_context *gc, Display *dpy, GLXDrawable draw, GLXDrawable read) -{ - gc->currentDpy = dpy; - gc->currentDrawable = draw; - gc->currentReadable = read; -} - -static Bool -should_send(Display *dpy, struct glx_context *gc) -{ - /* always send for indirect contexts */ - if (!gc->isDirect) - return 1; - - /* don't send for broken servers. */ - if (VendorRelease(dpy) < 12006000 || VendorRelease(dpy) >= 40000000) - return 0; - - return 1; -} - +/** + * Make a particular context current. + * + * \note This is in this file so that it can access dummyContext. + */ static Bool MakeContextCurrent(Display * dpy, GLXDrawable draw, GLXDrawable read, GLXContext gc_user) { struct glx_context *gc = (struct glx_context *) gc_user; struct glx_context *oldGC = __glXGetCurrentContext(); - Bool ret = GL_FALSE; /* Make sure that the new context has a nonzero ID. In the request, * a zero context ID is used only to mean that we bind to no current @@ -269,97 +186,66 @@ MakeContextCurrent(Display * dpy, GLXDrawable draw, } _glapi_check_multithread(); - __glXLock(); + __glXLock(); if (oldGC == gc && - gc->currentDrawable == draw && - gc->currentReadable == read) { - /* Same context and drawables: no op, just return */ - ret = GL_TRUE; + gc->currentDrawable == draw && gc->currentReadable == read) { + __glXUnlock(); + return True; } - else if (oldGC == gc) { - /* Same context and new drawables: update drawable bindings */ - if (should_send(dpy, gc)) { - if (!SendMakeCurrentRequest(dpy, gc->xid, gc->currentContextTag, - draw, read, &gc->currentContextTag)) { - goto out; - } + /* can't have only one be 0 */ + if (!!draw != !!read) { + __glXUnlock(); + __glXSendError(dpy, BadMatch, None, X_GLXMakeContextCurrent, True); + return False; + } + + if (oldGC != &dummyContext) { + if (--oldGC->thread_refcount == 0) { + oldGC->vtable->unbind(oldGC, gc); + oldGC->currentDpy = 0; } + } - if (gc->vtable->bind(gc, gc, draw, read) != Success) { + if (gc) { + /* Attempt to bind the context. We do this before mucking with + * gc and __glXSetCurrentContext to properly handle our state in + * case of an error. + * + * If an error occurs, set the Null context since we've already + * blown away our old context. The caller is responsible for + * figuring out how to handle setting a valid context. + */ + if (gc->vtable->bind(gc, oldGC, draw, read) != Success) { __glXSetCurrentContextNull(); - goto out; + __glXUnlock(); + __glXSendError(dpy, GLXBadContext, None, X_GLXMakeContextCurrent, + False); + return GL_FALSE; } - } - else { - /* Different contexts: release the old, bind the new */ - GLXContextTag oldTag = oldGC->currentContextTag; - - if (oldGC != &dummyContext) { - - if (--oldGC->thread_refcount == 0) { - if (oldGC->xid != None && - should_send(dpy, oldGC) && - !SendMakeCurrentRequest(dpy, None, oldTag, None, None, - &oldGC->currentContextTag)) { - goto out; - } - - oldGC->vtable->unbind(oldGC, gc); - - if (oldGC->xid == None) { - /* destroyed context, free it */ - oldGC->vtable->destroy(oldGC); - oldTag = 0; - } else { - SetGC(oldGC, NULL, None, None); - oldTag = oldGC->currentContextTag; - } - } + if (gc->thread_refcount == 0) { + gc->currentDpy = dpy; + gc->currentDrawable = draw; + gc->currentReadable = read; } + gc->thread_refcount++; + __glXSetCurrentContext(gc); + } else { __glXSetCurrentContextNull(); + } - if (gc) { - /* - * MESA_multithread_makecurrent makes this complicated. We need to - * send the request if the new context is - * - * a) indirect (may be current to another client), or - * b) (direct and) newly being made current, or - * c) (direct and) being bound to new drawables - */ - Bool new_drawables = gc->currentReadable != read || - gc->currentDrawable != draw; - - if (should_send(dpy, gc)) { - if (!gc->isDirect || !gc->thread_refcount || new_drawables) { - if (!SendMakeCurrentRequest(dpy, gc->xid, oldTag, draw, read, - &gc->currentContextTag)) { - goto out; - } - } - } - - if (gc->vtable->bind(gc, oldGC, draw, read) != Success) { - __glXSendError(dpy, GLXBadContext, None, X_GLXMakeContextCurrent, - False); - goto out; - } - - if (gc->thread_refcount == 0) { - SetGC(gc, dpy, draw, read); - } - gc->thread_refcount++; - __glXSetCurrentContext(gc); - } + if (oldGC->thread_refcount == 0 && oldGC != &dummyContext && oldGC->xid == None) { + /* We are switching away from a context that was + * previously destroyed, so we need to free the memory + * for the old handle. */ + oldGC->vtable->destroy(oldGC); } - ret = GL_TRUE; -out: __glXUnlock(); - return ret; + + return GL_TRUE; } diff --git a/src/glx/indirect_glx.c b/src/glx/indirect_glx.c index c23db139165..f370daf8bb6 100644 --- a/src/glx/indirect_glx.c +++ b/src/glx/indirect_glx.c @@ -61,41 +61,135 @@ indirect_destroy_context(struct glx_context *gc) free((char *) gc); } +static Bool +SendMakeCurrentRequest(Display * dpy, GLXContextID gc_id, + GLXContextTag gc_tag, GLXDrawable draw, + GLXDrawable read, GLXContextTag *out_tag) +{ + xGLXMakeCurrentReply reply; + Bool ret; + int opcode = __glXSetupForCommand(dpy); + + LockDisplay(dpy); + + if (draw == read) { + xGLXMakeCurrentReq *req; + + GetReq(GLXMakeCurrent, req); + req->reqType = opcode; + req->glxCode = X_GLXMakeCurrent; + req->drawable = draw; + req->context = gc_id; + req->oldContextTag = gc_tag; + } + else { + struct glx_display *priv = __glXInitialize(dpy); + + /* If the server can support the GLX 1.3 version, we should + * perfer that. Not only that, some servers support GLX 1.3 but + * not the SGI extension. + */ + + if ((priv->majorVersion > 1) || (priv->minorVersion >= 3)) { + xGLXMakeContextCurrentReq *req; + + GetReq(GLXMakeContextCurrent, req); + req->reqType = opcode; + req->glxCode = X_GLXMakeContextCurrent; + req->drawable = draw; + req->readdrawable = read; + req->context = gc_id; + req->oldContextTag = gc_tag; + } + else { + xGLXVendorPrivateWithReplyReq *vpreq; + xGLXMakeCurrentReadSGIReq *req; + + GetReqExtra(GLXVendorPrivateWithReply, + sz_xGLXMakeCurrentReadSGIReq - + sz_xGLXVendorPrivateWithReplyReq, vpreq); + req = (xGLXMakeCurrentReadSGIReq *) vpreq; + req->reqType = opcode; + req->glxCode = X_GLXVendorPrivateWithReply; + req->vendorCode = X_GLXvop_MakeCurrentReadSGI; + req->drawable = draw; + req->readable = read; + req->context = gc_id; + req->oldContextTag = gc_tag; + } + } + + ret = _XReply(dpy, (xReply *) &reply, 0, False); + + if (out_tag) + *out_tag = reply.contextTag; + + UnlockDisplay(dpy); + SyncHandle(); + + return ret; +} + static int indirect_bind_context(struct glx_context *gc, struct glx_context *old, GLXDrawable draw, GLXDrawable read) { - __GLXattribute *state = gc->client_state_private; - - if (!IndirectAPI) - IndirectAPI = __glXNewIndirectAPI(); - _glapi_set_dispatch(IndirectAPI); - - /* The indirect vertex array state must to be initialised after we - * have setup the context, as it needs to query server attributes. - * - * At the point this is called gc->currentDpy is not initialized - * nor is the thread's current context actually set. Hence the - * cleverness before the GetString calls. - */ - if (state && state->array_state == NULL) { - gc->currentDpy = gc->psc->dpy; - __glXSetCurrentContext(gc); - __glXSetCurrentContext(gc); - __indirect_glGetString(GL_EXTENSIONS); - __indirect_glGetString(GL_VERSION); - __glXInitVertexArrayState(gc); + GLXContextTag tag; + Display *dpy = gc->psc->dpy; + Bool sent; + + if (old != &dummyContext && !old->isDirect && old->psc->dpy == dpy) { + tag = old->currentContextTag; + old->currentContextTag = 0; + } else { + tag = 0; } - if (state != NULL && state->array_state != NULL) - return Success; + sent = SendMakeCurrentRequest(dpy, gc->xid, tag, draw, read, + &gc->currentContextTag); + + if (sent) { + if (!IndirectAPI) + IndirectAPI = __glXNewIndirectAPI(); + _glapi_set_dispatch(IndirectAPI); + + /* The indirect vertex array state must to be initialised after we + * have setup the context, as it needs to query server attributes. + * + * At the point this is called gc->currentDpy is not initialized + * nor is the thread's current context actually set. Hence the + * cleverness before the GetString calls. + */ + __GLXattribute *state = gc->client_state_private; + if (state && state->array_state == NULL) { + gc->currentDpy = gc->psc->dpy; + __glXSetCurrentContext(gc); + __indirect_glGetString(GL_EXTENSIONS); + __indirect_glGetString(GL_VERSION); + __glXInitVertexArrayState(gc); + } + } - return BadAlloc; + return !sent; } static void indirect_unbind_context(struct glx_context *gc, struct glx_context *new) { + Display *dpy = gc->psc->dpy; + + if (gc == new) + return; + + /* We are either switching to no context, away from an indirect + * context to a direct context or from one dpy to another and have + * to send a request to the dpy to unbind the previous context. + */ + if (!new || new->isDirect || new->psc->dpy != dpy) { + SendMakeCurrentRequest(dpy, None, gc->currentContextTag, None, None, + NULL); + gc->currentContextTag = 0; + } } static void