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 999c2aed88
.
Gitlab: https://gitlab.freedesktop.org/mesa/mesa/issues/1207
This commit is contained in:
parent
a14e3b43be
commit
8b6d3f2c78
|
@ -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();
|
||||
|
||||
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 (gc->vtable->bind(gc, gc, draw, read) != Success) {
|
||||
if (oldGC != &dummyContext) {
|
||||
if (--oldGC->thread_refcount == 0) {
|
||||
oldGC->vtable->unbind(oldGC, gc);
|
||||
oldGC->currentDpy = 0;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
ret = GL_TRUE;
|
||||
|
||||
out:
|
||||
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);
|
||||
}
|
||||
|
||||
__glXUnlock();
|
||||
return ret;
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
GLXContextTag tag;
|
||||
Display *dpy = gc->psc->dpy;
|
||||
Bool 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.
|
||||
*/
|
||||
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);
|
||||
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);
|
||||
|
||||
return BadAlloc;
|
||||
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 !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
|
||||
|
|
Loading…
Reference in New Issue