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;
|
return gc->currentDrawable;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Bool
|
/**
|
||||||
SendMakeCurrentRequest(Display * dpy, GLXContextID gc_id,
|
* Make a particular context current.
|
||||||
GLXContextTag gc_tag, GLXDrawable draw,
|
*
|
||||||
GLXDrawable read, GLXContextTag *out_tag)
|
* \note This is in this file so that it can access dummyContext.
|
||||||
{
|
*/
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Bool
|
static Bool
|
||||||
MakeContextCurrent(Display * dpy, GLXDrawable draw,
|
MakeContextCurrent(Display * dpy, GLXDrawable draw,
|
||||||
GLXDrawable read, GLXContext gc_user)
|
GLXDrawable read, GLXContext gc_user)
|
||||||
{
|
{
|
||||||
struct glx_context *gc = (struct glx_context *) gc_user;
|
struct glx_context *gc = (struct glx_context *) gc_user;
|
||||||
struct glx_context *oldGC = __glXGetCurrentContext();
|
struct glx_context *oldGC = __glXGetCurrentContext();
|
||||||
Bool ret = GL_FALSE;
|
|
||||||
|
|
||||||
/* Make sure that the new context has a nonzero ID. In the request,
|
/* 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
|
* 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();
|
_glapi_check_multithread();
|
||||||
|
|
||||||
__glXLock();
|
__glXLock();
|
||||||
|
|
||||||
if (oldGC == gc &&
|
if (oldGC == gc &&
|
||||||
gc->currentDrawable == draw &&
|
gc->currentDrawable == draw && gc->currentReadable == read) {
|
||||||
gc->currentReadable == read) {
|
__glXUnlock();
|
||||||
/* Same context and drawables: no op, just return */
|
return True;
|
||||||
ret = GL_TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (oldGC == gc) {
|
/* can't have only one be 0 */
|
||||||
/* Same context and new drawables: update drawable bindings */
|
if (!!draw != !!read) {
|
||||||
if (should_send(dpy, gc)) {
|
__glXUnlock();
|
||||||
if (!SendMakeCurrentRequest(dpy, gc->xid, gc->currentContextTag,
|
__glXSendError(dpy, BadMatch, None, X_GLXMakeContextCurrent, True);
|
||||||
draw, read, &gc->currentContextTag)) {
|
return False;
|
||||||
goto out;
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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();
|
__glXSetCurrentContextNull();
|
||||||
goto out;
|
__glXUnlock();
|
||||||
|
__glXSendError(dpy, GLXBadContext, None, X_GLXMakeContextCurrent,
|
||||||
|
False);
|
||||||
|
return GL_FALSE;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
else {
|
if (gc->thread_refcount == 0) {
|
||||||
/* Different contexts: release the old, bind the new */
|
gc->currentDpy = dpy;
|
||||||
GLXContextTag oldTag = oldGC->currentContextTag;
|
gc->currentDrawable = draw;
|
||||||
|
gc->currentReadable = read;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
gc->thread_refcount++;
|
||||||
|
__glXSetCurrentContext(gc);
|
||||||
|
} else {
|
||||||
__glXSetCurrentContextNull();
|
__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();
|
__glXUnlock();
|
||||||
return ret;
|
|
||||||
|
return GL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -61,41 +61,135 @@ indirect_destroy_context(struct glx_context *gc)
|
||||||
free((char *) 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
|
static int
|
||||||
indirect_bind_context(struct glx_context *gc, struct glx_context *old,
|
indirect_bind_context(struct glx_context *gc, struct glx_context *old,
|
||||||
GLXDrawable draw, GLXDrawable read)
|
GLXDrawable draw, GLXDrawable read)
|
||||||
{
|
{
|
||||||
__GLXattribute *state = gc->client_state_private;
|
GLXContextTag tag;
|
||||||
|
Display *dpy = gc->psc->dpy;
|
||||||
|
Bool sent;
|
||||||
|
|
||||||
if (!IndirectAPI)
|
if (old != &dummyContext && !old->isDirect && old->psc->dpy == dpy) {
|
||||||
IndirectAPI = __glXNewIndirectAPI();
|
tag = old->currentContextTag;
|
||||||
_glapi_set_dispatch(IndirectAPI);
|
old->currentContextTag = 0;
|
||||||
|
} else {
|
||||||
/* The indirect vertex array state must to be initialised after we
|
tag = 0;
|
||||||
* 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 (state != NULL && state->array_state != NULL)
|
sent = SendMakeCurrentRequest(dpy, gc->xid, tag, draw, read,
|
||||||
return Success;
|
&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
|
static void
|
||||||
indirect_unbind_context(struct glx_context *gc, struct glx_context *new)
|
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
|
static void
|
||||||
|
|
Loading…
Reference in New Issue