X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fglx%2Fglxcurrent.c;h=7172009c34c0fc9451fc6439f04850ae5fb6121e;hb=0d635ccc912d7122f35f81eec27d8b2c0a2a7a28;hp=691e8dfadf2ca1ceaba5eb895794220cab51ba6d;hpb=80b280db883edc9550484dba03bd5c124b6a9bf9;p=mesa.git diff --git a/src/glx/glxcurrent.c b/src/glx/glxcurrent.c index 691e8dfadf2..7172009c34c 100644 --- a/src/glx/glxcurrent.c +++ b/src/glx/glxcurrent.c @@ -33,20 +33,11 @@ * Client-side GLX interface for current context management. */ -#ifdef PTHREADS #include -#endif #include "glxclient.h" -#ifdef GLX_USE_APPLEGL -#include - -#include "apple_glx.h" -#include "apple_glx_context.h" -#else #include "glapi.h" -#include "indirect_init.h" -#endif +#include "glx_error.h" /* ** We setup some dummy structures here so that the API can be used @@ -54,38 +45,29 @@ */ static GLubyte dummyBuffer[__GLX_BUFFER_LIMIT_SIZE]; - +static struct glx_context_vtable dummyVtable; /* ** Dummy context used by small commands when there is no current context. ** All the ** gl and glx entry points are designed to operate as nop's when using ** the dummy context structure. */ -static __GLXcontext dummyContext = { +struct glx_context dummyContext = { &dummyBuffer[0], &dummyBuffer[0], &dummyBuffer[0], &dummyBuffer[__GLX_BUFFER_LIMIT_SIZE], sizeof(dummyBuffer), + &dummyVtable }; - -#ifndef GLX_USE_APPLEGL -/* -** All indirect rendering contexts will share the same indirect dispatch table. -*/ -static __GLapi *IndirectAPI = NULL; -#endif - /* * Current context management and locking */ -#if defined( PTHREADS ) - _X_HIDDEN pthread_mutex_t __glXmutex = PTHREAD_MUTEX_INITIALIZER; -# if defined( GLX_USE_TLS ) +# if defined( USE_ELF_TLS ) /** * Per-thread GLX context pointer. @@ -98,7 +80,7 @@ __thread void *__glX_tls_Context __attribute__ ((tls_model("initial-exec"))) = &dummyContext; _X_HIDDEN void -__glXSetCurrentContext(__GLXcontext * c) +__glXSetCurrentContext(struct glx_context * c) { __glX_tls_Context = (c != NULL) ? c : &dummyContext; } @@ -133,13 +115,13 @@ init_thread_data(void) } _X_HIDDEN void -__glXSetCurrentContext(__GLXcontext * c) +__glXSetCurrentContext(struct glx_context * c) { pthread_once(&once_control, init_thread_data); pthread_setspecific(ContextTSD, c); } -_X_HIDDEN __GLXcontext * +_X_HIDDEN struct glx_context * __glXGetCurrentContext(void) { void *v; @@ -147,84 +129,50 @@ __glXGetCurrentContext(void) pthread_once(&once_control, init_thread_data); v = pthread_getspecific(ContextTSD); - return (v == NULL) ? &dummyContext : (__GLXcontext *) v; + return (v == NULL) ? &dummyContext : (struct glx_context *) v; } -# endif /* defined( GLX_USE_TLS ) */ - -#elif defined( THREADS ) - -#error Unknown threading method specified. - -#else - -/* not thread safe */ -_X_HIDDEN __GLXcontext *__glXcurrentContext = &dummyContext; - -#endif +# endif /* defined( USE_ELF_TLS ) */ _X_HIDDEN void __glXSetCurrentContextNull(void) { __glXSetCurrentContext(&dummyContext); -#ifndef GLX_USE_APPLEGL -#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) +#if defined(GLX_DIRECT_RENDERING) _glapi_set_dispatch(NULL); /* no-op functions */ _glapi_set_context(NULL); #endif -#endif } - -/************************************************************************/ - -PUBLIC GLXContext +_GLX_PUBLIC GLXContext glXGetCurrentContext(void) { - GLXContext cx = __glXGetCurrentContext(); + struct glx_context *cx = __glXGetCurrentContext(); if (cx == &dummyContext) { return NULL; } else { - return cx; + return (GLXContext) cx; } } -PUBLIC GLXDrawable +_GLX_PUBLIC GLXDrawable glXGetCurrentDrawable(void) { - GLXContext gc = __glXGetCurrentContext(); + struct glx_context *gc = __glXGetCurrentContext(); return gc->currentDrawable; } - -#ifndef GLX_USE_APPLEGL -/************************************************************************/ - -/** - * Sends a GLX protocol message to the specified display to make the context - * and the drawables current. - * - * \param dpy Display to send the message to. - * \param opcode Major opcode value for the display. - * \param gc_id Context tag for the context to be made current. - * \param draw Drawable ID for the "draw" drawable. - * \param read Drawable ID for the "read" drawable. - * \param reply Space to store the X-server's reply. - * - * \warning - * This function assumes that \c dpy is locked with \c LockDisplay on entry. - */ static Bool -SendMakeCurrentRequest(Display * dpy, CARD8 opcode, - GLXContextID gc_id, GLXContextTag gc_tag, - GLXDrawable draw, GLXDrawable read, - xGLXMakeCurrentReply * reply) +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); @@ -239,12 +187,7 @@ SendMakeCurrentRequest(Display * dpy, CARD8 opcode, req->oldContextTag = gc_tag; } else { - __GLXdisplayPrivate *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. - */ + struct glx_display *priv = __glXInitialize(dpy); if ((priv->majorVersion > 1) || (priv->minorVersion >= 3)) { xGLXMakeContextCurrentReq *req; @@ -275,7 +218,11 @@ SendMakeCurrentRequest(Display * dpy, CARD8 opcode, } } - ret = _XReply(dpy, (xReply *) reply, 0, False); + ret = _XReply(dpy, (xReply *) &reply, 0, False); + + + if (ret == 1) + *out_tag = reply.contextTag; UnlockDisplay(dpy); SyncHandle(); @@ -283,82 +230,35 @@ SendMakeCurrentRequest(Display * dpy, CARD8 opcode, return ret; } - -#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) -static __GLXDRIdrawable * -FetchDRIDrawable(Display * dpy, GLXDrawable glxDrawable, GLXContext gc) +static void +SetGC(struct glx_context *gc, Display *dpy, GLXDrawable draw, GLXDrawable read) { - __GLXdisplayPrivate *const priv = __glXInitialize(dpy); - __GLXDRIdrawable *pdraw; - __GLXscreenConfigs *psc; - - if (priv == NULL) - return NULL; - - psc = &priv->screenConfigs[gc->screen]; - if (psc->drawHash == NULL) - return NULL; - - if (__glxHashLookup(psc->drawHash, glxDrawable, (void *) &pdraw) == 0) - return pdraw; - - pdraw = psc->driScreen->createDrawable(psc, glxDrawable, - glxDrawable, gc->mode); - if (__glxHashInsert(psc->drawHash, glxDrawable, pdraw)) { - (*pdraw->destroyDrawable) (pdraw); - return NULL; - } - - return pdraw; + gc->currentDpy = dpy; + gc->currentDrawable = draw; + gc->currentReadable = read; } -#endif /* GLX_DIRECT_RENDERING */ -static void -__glXGenerateError(Display * dpy, GLXContext gc, XID resource, - BYTE errorCode, CARD16 minorCode) +static Bool +should_send(Display *dpy, struct glx_context *gc) { - xError error; - - error.errorCode = errorCode; - error.resourceID = resource; - error.sequenceNumber = dpy->request; - error.type = X_Error; - error.majorCode = gc->majorOpcode; - error.minorCode = minorCode; - _XError(dpy, &error); -} + /* always send for indirect contexts */ + if (!gc->isDirect) + return 1; -#endif /* GLX_USE_APPLEGL */ + /* 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) + GLXDrawable read, GLXContext gc_user) { - const GLXContext oldGC = __glXGetCurrentContext(); -#ifdef GLX_USE_APPLEGL - bool error = apple_glx_make_current_context(dpy, - (oldGC && oldGC != &dummyContext) ? oldGC->driContext : NULL, - gc ? gc->driContext : NULL, draw); - - apple_glx_diagnostic("%s: error %s\n", __func__, error ? "YES" : "NO"); - if(error) - return GL_FALSE; -#else - xGLXMakeCurrentReply reply; - const CARD8 opcode = __glXSetupForCommand(dpy); - const CARD8 oldOpcode = ((gc == oldGC) || (oldGC == &dummyContext)) - ? opcode : __glXSetupForCommand(oldGC->currentDpy); - Bool bindReturnValue; - __GLXattribute *state; - - if (!opcode || !oldOpcode) { - return GL_FALSE; - } + 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 @@ -368,189 +268,113 @@ MakeContextCurrent(Display * dpy, GLXDrawable draw, return GL_FALSE; } - if (gc == NULL && (draw != None || read != None)) { - __glXGenerateError(dpy, gc, (draw != None) ? draw : read, - BadMatch, X_GLXMakeContextCurrent); - return False; - } - if (gc != NULL && (draw == None || read == None)) { - __glXGenerateError(dpy, gc, None, BadMatch, X_GLXMakeContextCurrent); - return False; - } - _glapi_check_multithread(); + __glXLock(); - if (gc != NULL && gc->thread_id != 0 && gc->thread_id != _glthread_GetID()) { - __glXGenerateError(dpy, gc, gc->xid, - BadAccess, X_GLXMakeContextCurrent); - return False; + if (oldGC == gc && + gc->currentDrawable == draw && + gc->currentReadable == read) { + /* Same context and drawables: no op, just return */ + ret = GL_TRUE; } -#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) - /* Bind the direct rendering context to the drawable */ - if (gc && gc->driContext) { - __GLXDRIdrawable *pdraw = FetchDRIDrawable(dpy, draw, gc); - __GLXDRIdrawable *pread = FetchDRIDrawable(dpy, read, gc); - - if ((pdraw == NULL) || (pread == NULL)) { - __glXGenerateError(dpy, gc, (pdraw == NULL) ? draw : read, - GLXBadDrawable, X_GLXMakeContextCurrent); - return False; + 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; + } } - bindReturnValue = - (gc->driContext->bindContext) (gc->driContext, pdraw, pread); - } - else if (!gc && oldGC && oldGC->driContext) { - bindReturnValue = True; - } - else -#endif - { - /* Send a glXMakeCurrent request to bind the new context. */ - bindReturnValue = - SendMakeCurrentRequest(dpy, opcode, gc ? gc->xid : None, - ((dpy != oldGC->currentDpy) - || oldGC->isDirect) - ? None : oldGC->currentContextTag, draw, read, - &reply); + if (gc->vtable->bind(gc, gc, draw, read) != Success) { + __glXSetCurrentContextNull(); + goto out; + } } + else { + /* Different contexts: release the old, bind the new */ + GLXContextTag oldTag = oldGC->currentContextTag; - if (!bindReturnValue) { - return False; - } + if (oldGC != &dummyContext) { -#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) - if ((dpy != oldGC->currentDpy || (gc && gc->driContext)) && - !oldGC->isDirect && oldGC != &dummyContext) { -#else - if ((dpy != oldGC->currentDpy) && oldGC != &dummyContext) { -#endif - xGLXMakeCurrentReply dummy_reply; - - /* We are either switching from one dpy to another and have to - * send a request to the previous dpy to unbind the previous - * context, or we are switching away from a indirect context to - * a direct context and have to send a request to the dpy to - * unbind the previous context. - */ - (void) SendMakeCurrentRequest(oldGC->currentDpy, oldOpcode, None, - oldGC->currentContextTag, None, None, - &dummy_reply); - } -#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) - else if (oldGC->driContext && oldGC != gc) { - oldGC->driContext->unbindContext(oldGC->driContext); - } -#endif + if (--oldGC->thread_refcount == 0) { + if (oldGC->xid != None && + should_send(dpy, oldGC) && + !SendMakeCurrentRequest(dpy, None, oldTag, None, None, + &oldGC->currentContextTag)) { + goto out; + } -#endif /* GLX_USE_APPLEGL */ + oldGC->vtable->unbind(oldGC, gc); - /* Update our notion of what is current */ - __glXLock(); - if (gc == oldGC) { - /* Even though the contexts are the same the drawable might have - * changed. Note that gc cannot be the dummy, and that oldGC - * cannot be NULL, therefore if they are the same, gc is not - * NULL and not the dummy. - */ - if(gc) { - gc->currentDrawable = draw; - gc->currentReadable = read; + if (oldGC->xid == None) { + /* destroyed context, free it */ + oldGC->vtable->destroy(oldGC); + oldTag = 0; + } else { + SetGC(oldGC, NULL, None, None); + oldTag = oldGC->currentContextTag; + } + } } - } - else { - if (oldGC != &dummyContext) { - /* Old current context is no longer current to anybody */ - oldGC->currentDpy = 0; - oldGC->currentDrawable = None; - oldGC->currentReadable = None; - oldGC->currentContextTag = 0; - oldGC->thread_id = 0; -#ifdef GLX_USE_APPLEGL - + __glXSetCurrentContextNull(); + + if (gc) { /* - * At this point we should check if the context has been - * through glXDestroyContext, and redestroy it if so. + * 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 */ - if(oldGC->do_destroy) { - __glXUnlock(); - /* glXDestroyContext uses the same global lock. */ - glXDestroyContext(dpy, oldGC); - __glXLock(); -#else - if (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. - */ -#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) - /* Destroy the old direct rendering context */ - if (oldGC->driContext) { - oldGC->driContext->destroyContext(oldGC->driContext, - oldGC->psc, - oldGC->createDpy); - oldGC->driContext = NULL; + 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; + } } -#endif - __glXFreeContext(oldGC); -#endif /* GLX_USE_APPLEGL */ } - } - if (gc) { - __glXSetCurrentContext(gc); - - gc->currentDpy = dpy; - gc->currentDrawable = draw; - gc->currentReadable = read; -#ifndef GLX_USE_APPLEGL - gc->thread_id = _glthread_GetID(); -#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) - if (!gc->driContext) { -#endif - if (!IndirectAPI) - IndirectAPI = __glXNewIndirectAPI(); - _glapi_set_dispatch(IndirectAPI); - - state = (__GLXattribute *) (gc->client_state_private); - - gc->currentContextTag = reply.contextTag; - if (state->array_state == NULL) { - (void) glGetString(GL_EXTENSIONS); - (void) glGetString(GL_VERSION); - __glXInitVertexArrayState(gc); - } -#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) + if (gc->vtable->bind(gc, oldGC, draw, read) != Success) { + __glXSendError(dpy, GLXBadContext, None, X_GLXMakeContextCurrent, + False); + goto out; } - else { - gc->currentContextTag = -1; + + if (gc->thread_refcount == 0) { + SetGC(gc, dpy, draw, read); } -#endif -#endif /* GLX_USE_APPLEGL */ - } - else { - __glXSetCurrentContextNull(); + gc->thread_refcount++; + __glXSetCurrentContext(gc); } } + ret = GL_TRUE; + +out: __glXUnlock(); - return GL_TRUE; + return ret; } -PUBLIC Bool +_GLX_PUBLIC Bool glXMakeCurrent(Display * dpy, GLXDrawable draw, GLXContext gc) { return MakeContextCurrent(dpy, draw, draw, gc); } -PUBLIC +_GLX_PUBLIC GLX_ALIAS(Bool, glXMakeCurrentReadSGI, (Display * dpy, GLXDrawable d, GLXDrawable r, GLXContext ctx), (dpy, d, r, ctx), MakeContextCurrent) -PUBLIC +_GLX_PUBLIC GLX_ALIAS(Bool, glXMakeContextCurrent, (Display * dpy, GLXDrawable d, GLXDrawable r, GLXContext ctx), (dpy, d, r, ctx), MakeContextCurrent)