diff options
Diffstat (limited to 'src/glx/x11/glxext.c')
-rw-r--r-- | src/glx/x11/glxext.c | 511 |
1 files changed, 16 insertions, 495 deletions
diff --git a/src/glx/x11/glxext.c b/src/glx/x11/glxext.c index cd5c3196e36..75b7374a3fb 100644 --- a/src/glx/x11/glxext.c +++ b/src/glx/x11/glxext.c @@ -45,26 +45,13 @@ */ #include "glxclient.h" -#include <stdio.h> #include <X11/extensions/Xext.h> #include <X11/extensions/extutil.h> -#include <X11/extensions/Xfixes.h> -#include <X11/extensions/Xdamage.h> -#include <assert.h> -#include "indirect_init.h" #include "glapi.h" #include "glxextensions.h" #include "glcontextmodes.h" #include "glheader.h" -#ifdef GLX_DIRECT_RENDERING -#include <inttypes.h> -#include <sys/mman.h> -#include "xf86dri.h" -#include "xf86drm.h" -#include "sarea.h" -#endif - #ifdef USE_XCB #include <X11/Xlib-xcb.h> #include <xcb/xcb.h> @@ -77,24 +64,6 @@ void __glXDumpDrawBuffer(__GLXcontext *ctx); #endif #ifdef USE_SPARC_ASM -/* - * This is where our dispatch table's bounds are. - * And the static mesa_init is taken directly from - * Mesa's 'sparc.c' initializer. - * - * We need something like this here, because this version - * of openGL/glx never initializes a Mesa context, and so - * the address of the dispatch table pointer never gets stuffed - * into the dispatch jump table otherwise. - * - * It matters only on SPARC, and only if you are using assembler - * code instead of C-code indirect dispatch. - * - * -- FEM, 04.xii.03 - */ -extern unsigned int _mesa_sparc_glapi_begin; -extern unsigned int _mesa_sparc_glapi_end; -extern void __glapi_sparc_icache_flush(unsigned int *); static void _glx_mesa_init_sparc_glapi_relocs(void); static int _mesa_sparc_needs_init = 1; #define INIT_MESA_SPARC { \ @@ -108,153 +77,6 @@ static int _mesa_sparc_needs_init = 1; #endif /* -** We setup some dummy structures here so that the API can be used -** even if no context is current. -*/ - -static GLubyte dummyBuffer[__GLX_BUFFER_LIMIT_SIZE]; - -/* -** 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 = { - &dummyBuffer[0], - &dummyBuffer[0], - &dummyBuffer[0], - &dummyBuffer[__GLX_BUFFER_LIMIT_SIZE], - sizeof(dummyBuffer), -}; - - -/* -** All indirect rendering contexts will share the same indirect dispatch table. -*/ -static __GLapi *IndirectAPI = NULL; - - -/* - * Current context management and locking - */ - -#if defined( USE_XTHREADS ) - -/* thread safe */ -static GLboolean TSDinitialized = GL_FALSE; -static xthread_key_t ContextTSD; - -_X_HIDDEN __GLXcontext *__glXGetCurrentContext(void) -{ - if (!TSDinitialized) { - xthread_key_create(&ContextTSD, NULL); - TSDinitialized = GL_TRUE; - return &dummyContext; - } - else { - void *p; - xthread_get_specific(ContextTSD, &p); - if (!p) - return &dummyContext; - else - return (__GLXcontext *) p; - } -} - -_X_HIDDEN void __glXSetCurrentContext(__GLXcontext *c) -{ - if (!TSDinitialized) { - xthread_key_create(&ContextTSD, NULL); - TSDinitialized = GL_TRUE; - } - xthread_set_specific(ContextTSD, c); -} - - -/* Used by the __glXLock() and __glXUnlock() macros */ -_X_HIDDEN xmutex_rec __glXmutex; - -#elif defined( PTHREADS ) - -_X_HIDDEN pthread_mutex_t __glXmutex = PTHREAD_MUTEX_INITIALIZER; - -# if defined( GLX_USE_TLS ) - -/** - * Per-thread GLX context pointer. - * - * \c __glXSetCurrentContext is written is such a way that this pointer can - * \b never be \c NULL. This is important! Because of this - * \c __glXGetCurrentContext can be implemented as trivial macro. - */ -__thread void * __glX_tls_Context __attribute__((tls_model("initial-exec"))) - = &dummyContext; - -_X_HIDDEN void __glXSetCurrentContext( __GLXcontext * c ) -{ - __glX_tls_Context = (c != NULL) ? c : &dummyContext; -} - -# else - -static pthread_once_t once_control = PTHREAD_ONCE_INIT; - -/** - * Per-thread data key. - * - * Once \c init_thread_data has been called, the per-thread data key will - * take a value of \c NULL. As each new thread is created the default - * value, in that thread, will be \c NULL. - */ -static pthread_key_t ContextTSD; - -/** - * Initialize the per-thread data key. - * - * This function is called \b exactly once per-process (not per-thread!) to - * initialize the per-thread data key. This is ideally done using the - * \c pthread_once mechanism. - */ -static void init_thread_data( void ) -{ - if ( pthread_key_create( & ContextTSD, NULL ) != 0 ) { - perror( "pthread_key_create" ); - exit( -1 ); - } -} - -_X_HIDDEN void __glXSetCurrentContext( __GLXcontext * c ) -{ - pthread_once( & once_control, init_thread_data ); - pthread_setspecific( ContextTSD, c ); -} - -_X_HIDDEN __GLXcontext * __glXGetCurrentContext( void ) -{ - void * v; - - pthread_once( & once_control, init_thread_data ); - - v = pthread_getspecific( ContextTSD ); - return (v == NULL) ? & dummyContext : (__GLXcontext *) v; -} - -# endif /* defined( GLX_USE_TLS ) */ - -#elif defined( THREADS ) - -#error Unknown threading method specified. - -#else - -/* not thread safe */ -_X_HIDDEN __GLXcontext *__glXcurrentContext = &dummyContext; - -#endif - - -/* ** You can set this cell to 1 to force the gl drawing stuff to be ** one command per packet */ @@ -287,10 +109,7 @@ static int __glXCloseDisplay(Display *dpy, XExtCodes *codes) gc = __glXGetCurrentContext(); if (dpy == gc->currentDpy) { - __glXSetCurrentContext(&dummyContext); -#ifdef GLX_DIRECT_RENDERING - _glapi_set_dispatch(NULL); /* no-op functions */ -#endif + __glXSetCurrentContextNull(); __glXFreeContext(gc); } @@ -1086,318 +905,6 @@ _X_HIDDEN void __glXSendLargeCommand(__GLXcontext *ctx, /************************************************************************/ -PUBLIC GLXContext glXGetCurrentContext(void) -{ - GLXContext cx = __glXGetCurrentContext(); - - if (cx == &dummyContext) { - return NULL; - } else { - return cx; - } -} - -PUBLIC GLXDrawable glXGetCurrentDrawable(void) -{ - GLXContext gc = __glXGetCurrentContext(); - return gc->currentDrawable; -} - - -/************************************************************************/ - -static Bool SendMakeCurrentRequest( Display *dpy, CARD8 opcode, - GLXContextID gc, GLXContextTag old_gc, GLXDrawable draw, GLXDrawable read, - xGLXMakeCurrentReply * reply ); - -/** - * 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; -} - - -#ifdef GLX_DIRECT_RENDERING -static __GLXDRIdrawable * -FetchDRIDrawable(Display *dpy, - GLXDrawable glxDrawable, GLXContext gc, Bool pre13) -{ - __GLXdisplayPrivate * const priv = __glXInitialize(dpy); - __GLXDRIdrawable *pdraw; - __GLXscreenConfigs *psc; - XID drawable; - - 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; - - /* If this is glXMakeCurrent (pre GLX 1.3) we allow creating the - * GLX drawable on the fly. Otherwise we pass None as the X - * drawable */ - if (pre13) - drawable = glxDrawable; - else - drawable = None; - - pdraw = psc->driScreen->createDrawable(psc, drawable, - glxDrawable, gc->mode); - if (__glxHashInsert(psc->drawHash, glxDrawable, pdraw)) { - (*pdraw->destroyDrawable)(pdraw); - return NULL; - } - - return pdraw; -} -#endif /* GLX_DIRECT_RENDERING */ - - -/** - * 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, - Bool pre13) -{ - xGLXMakeCurrentReply reply; - const GLXContext oldGC = __glXGetCurrentContext(); - const CARD8 opcode = __glXSetupForCommand(dpy); - const CARD8 oldOpcode = ((gc == oldGC) || (oldGC == &dummyContext)) - ? opcode : __glXSetupForCommand(oldGC->currentDpy); - Bool bindReturnValue; - - - if (!opcode || !oldOpcode) { - return 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 - * context. - */ - if ((gc != NULL) && (gc->xid == None)) { - return GL_FALSE; - } - - _glapi_check_multithread(); - -#ifdef GLX_DIRECT_RENDERING - /* Bind the direct rendering context to the drawable */ - if (gc && gc->driContext) { - __GLXDRIdrawable *pdraw = FetchDRIDrawable(dpy, draw, gc, pre13); - __GLXDRIdrawable *pread = FetchDRIDrawable(dpy, read, gc, pre13); - - bindReturnValue = - (gc->driContext->bindContext) (gc->driContext, pdraw, pread); - } 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 (!bindReturnValue) { - return False; - } - - if ((dpy != oldGC->currentDpy || (gc && gc->driContext)) && - !oldGC->isDirect && oldGC != &dummyContext) { - 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); - } -#ifdef GLX_DIRECT_RENDERING - else if (oldGC->driContext) { - oldGC->driContext->unbindContext(oldGC->driContext); - } -#endif - - - /* 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. - */ - 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; - - 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. - */ -#ifdef GLX_DIRECT_RENDERING - /* Destroy the old direct rendering context */ - if (oldGC->driContext) { - oldGC->driContext->destroyContext(oldGC->driContext, - oldGC->psc, - oldGC->createDpy); - oldGC->driContext = NULL; - } -#endif - __glXFreeContext(oldGC); - } - } - if (gc) { - __glXSetCurrentContext(gc); - - gc->currentDpy = dpy; - gc->currentDrawable = draw; - gc->currentReadable = read; - - if (!gc->driContext) { - if (!IndirectAPI) - IndirectAPI = __glXNewIndirectAPI(); - _glapi_set_dispatch(IndirectAPI); - -#ifdef GLX_USE_APPLEGL - do { - extern void XAppleDRIUseIndirectDispatch(void); - XAppleDRIUseIndirectDispatch(); - } while (0); -#endif - - __GLXattribute *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); - } - } - else { - gc->currentContextTag = -1; - } - } else { - __glXSetCurrentContext(&dummyContext); -#ifdef GLX_DIRECT_RENDERING - _glapi_set_dispatch(NULL); /* no-op functions */ -#endif - } - } - __glXUnlock(); - return GL_TRUE; -} - - -PUBLIC Bool glXMakeCurrent(Display *dpy, GLXDrawable draw, GLXContext gc) -{ - return MakeContextCurrent(dpy, draw, draw, gc, True); -} - -PUBLIC GLX_ALIAS(Bool, glXMakeCurrentReadSGI, - (Display *dpy, GLXDrawable d, GLXDrawable r, GLXContext ctx), - (dpy, d, r, ctx, False), MakeContextCurrent) - -PUBLIC GLX_ALIAS(Bool, glXMakeContextCurrent, - (Display *dpy, GLXDrawable d, GLXDrawable r, GLXContext ctx), - (dpy, d, r, ctx, False), MakeContextCurrent) - - #ifdef DEBUG _X_HIDDEN void __glXDumpDrawBuffer(__GLXcontext *ctx) { @@ -1424,9 +931,23 @@ _X_HIDDEN void __glXDumpDrawBuffer(__GLXcontext *ctx) #ifdef USE_SPARC_ASM /* - * Used only when we are sparc, using sparc assembler. + * This is where our dispatch table's bounds are. + * And the static mesa_init is taken directly from + * Mesa's 'sparc.c' initializer. * + * We need something like this here, because this version + * of openGL/glx never initializes a Mesa context, and so + * the address of the dispatch table pointer never gets stuffed + * into the dispatch jump table otherwise. + * + * It matters only on SPARC, and only if you are using assembler + * code instead of C-code indirect dispatch. + * + * -- FEM, 04.xii.03 */ +extern unsigned int _mesa_sparc_glapi_begin; +extern unsigned int _mesa_sparc_glapi_end; +extern void __glapi_sparc_icache_flush(unsigned int *); static void _glx_mesa_init_sparc_glapi_relocs(void) |