X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fglx%2Fglxcurrent.c;h=2b9c708c3ee6fc97fd11fa503bbdbbce54a21eb6;hb=b344e32cdf7064a1f2ff7ef37027edda6589404f;hp=e8649b67655ff6a91fd6456c371b50233f4be227;hpb=afe125e0a18ac3886c45c7e6b02b122fb2d327b5;p=mesa.git diff --git a/src/glx/glxcurrent.c b/src/glx/glxcurrent.c index e8649b67655..2b9c708c3ee 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,35 +45,26 @@ */ 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 ) @@ -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,189 +129,42 @@ __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 - _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) -{ - Bool ret; - - - 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 { - __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. - */ - - 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); - - UnlockDisplay(dpy); - SyncHandle(); - - return ret; -} - - -#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) -static __GLXDRIdrawable * -FetchDRIDrawable(Display * dpy, GLXDrawable glxDrawable, GLXContext gc) -{ - __GLXdisplayPrivate *const priv = __glXInitialize(dpy); - __GLXDRIdrawable *pdraw; - __GLXscreenConfigs *psc; - - if (priv == NULL) - return NULL; - - psc = priv->screenConfigs[gc->screen]; - if (priv->drawHash == NULL) - return NULL; - - if (__glxHashLookup(priv->drawHash, glxDrawable, (void *) &pdraw) == 0) - return pdraw; - - pdraw = psc->driScreen->createDrawable(psc, glxDrawable, - glxDrawable, gc->mode); - if (__glxHashInsert(priv->drawHash, glxDrawable, pdraw)) { - (*pdraw->destroyDrawable) (pdraw); - return NULL; - } - - return pdraw; -} -#endif /* GLX_DIRECT_RENDERING */ - -static void -__glXGenerateError(Display * dpy, GLXContext gc, XID resource, - BYTE errorCode, CARD16 minorCode) -{ - 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); -} - -#endif /* GLX_USE_APPLEGL */ - /** * Make a particular context current. * @@ -337,28 +172,10 @@ __glXGenerateError(Display * dpy, GLXContext gc, XID resource, */ 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(); /* 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,168 +185,94 @@ 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(); - if (gc != NULL && gc->thread_id != 0 && gc->thread_id != _glthread_GetID()) { - __glXGenerateError(dpy, gc, gc->xid, - BadAccess, X_GLXMakeContextCurrent); - return False; - } - -#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; - } - - bindReturnValue = - (gc->driContext->bindContext) (gc, 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); + __glXLock(); + if (oldGC == gc && + gc->currentDrawable == draw && gc->currentReadable == read) { + __glXUnlock(); + return True; } - - if (!bindReturnValue) { + /* can't have only one be 0 */ + if (!!draw != !!read) { + __glXUnlock(); + __glXSendError(dpy, BadMatch, None, X_GLXMakeContextCurrent, True); return False; } -#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); + if (oldGC != &dummyContext) { + if (--oldGC->thread_refcount == 0) { + oldGC->vtable->unbind(oldGC, gc); + oldGC->currentDpy = 0; + } } -#endif -#endif /* GLX_USE_APPLEGL */ - - /* 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) { + /* 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) { - gc->currentDrawable = draw; - gc->currentReadable = read; - } - } - 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; - - 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. - */ - oldGC->vtable->destroy(oldGC); - } + if (gc->vtable->bind(gc, oldGC, draw, read) != Success) { + __glXSetCurrentContextNull(); + __glXUnlock(); + __glXSendError(dpy, GLXBadContext, None, X_GLXMakeContextCurrent, + False); + return GL_FALSE; } - if (gc) { - __glXSetCurrentContext(gc); + if (gc->thread_refcount == 0) { 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) - } - else { - gc->currentContextTag = -1; - } -#endif -#endif /* GLX_USE_APPLEGL */ - } - else { - __glXSetCurrentContextNull(); } + gc->thread_refcount++; + __glXSetCurrentContext(gc); + } else { + __glXSetCurrentContextNull(); + } + + 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(); + + /* The indirect vertex array state must to be initialised after we + * have setup the context, as it needs to query server attributes. + */ + if (gc && !gc->isDirect) { + __GLXattribute *state = gc->client_state_private; + if (state && state->array_state == NULL) { + glGetString(GL_EXTENSIONS); + glGetString(GL_VERSION); + __glXInitVertexArrayState(gc); + } + } + return GL_TRUE; } -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)