diff options
Diffstat (limited to 'src/glx')
-rw-r--r-- | src/glx/dri2_glx.c | 9 | ||||
-rw-r--r-- | src/glx/glxclient.h | 4 | ||||
-rw-r--r-- | src/glx/glxcmds.c | 8 | ||||
-rw-r--r-- | src/glx/glxcurrent.c | 55 | ||||
-rw-r--r-- | src/glx/glxextensions.c | 1 | ||||
-rw-r--r-- | src/glx/glxextensions.h | 1 |
6 files changed, 50 insertions, 28 deletions
diff --git a/src/glx/dri2_glx.c b/src/glx/dri2_glx.c index a275ba5b9fe..2c28bc27150 100644 --- a/src/glx/dri2_glx.c +++ b/src/glx/dri2_glx.c @@ -535,8 +535,13 @@ dri2SwapBuffers(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor, CARD64 ret = 0; #ifdef __DRI2_FLUSH - if (psc->f) - (*psc->f->flush)(priv->driDrawable); + if (psc->f) { + struct glx_context *gc = __glXGetCurrentContext(); + + if (gc) { + (*psc->f->flush)(priv->driDrawable); + } + } #endif /* Old servers don't send invalidate events */ diff --git a/src/glx/glxclient.h b/src/glx/glxclient.h index fdcef8075a8..2b6966f2e08 100644 --- a/src/glx/glxclient.h +++ b/src/glx/glxclient.h @@ -419,9 +419,9 @@ struct glx_context /*@} */ /** - * Thread ID we're currently current in. Zero if none. + * Number of threads we're currently current in. */ - unsigned long thread_id; + unsigned long thread_refcount; char gl_extension_bits[__GL_EXT_BYTES]; }; diff --git a/src/glx/glxcmds.c b/src/glx/glxcmds.c index 80eaf72b7d5..22bebab26bc 100644 --- a/src/glx/glxcmds.c +++ b/src/glx/glxcmds.c @@ -727,11 +727,16 @@ glXSwapBuffers(Display * dpy, GLXDrawable drawable) xGLXSwapBuffersReq *req; #endif + gc = __glXGetCurrentContext(); + #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable); if (pdraw != NULL) { - glFlush(); + if (gc && drawable == gc->currentDrawable) { + glFlush(); + } + (*pdraw->psc->driScreen->swapBuffers)(pdraw, 0, 0, 0); return; } @@ -746,7 +751,6 @@ glXSwapBuffers(Display * dpy, GLXDrawable drawable) ** The calling thread may or may not have a current context. If it ** does, send the context tag so the server can do a flush. */ - gc = __glXGetCurrentContext(); if ((gc != NULL) && (dpy == gc->currentDpy) && ((drawable == gc->currentDrawable) || (drawable == gc->currentReadable))) { diff --git a/src/glx/glxcurrent.c b/src/glx/glxcurrent.c index 36317383544..9a6499037b1 100644 --- a/src/glx/glxcurrent.c +++ b/src/glx/glxcurrent.c @@ -216,6 +216,16 @@ MakeContextCurrent(Display * dpy, GLXDrawable draw, struct glx_context *oldGC = __glXGetCurrentContext(); int ret = Success; + /* XXX: If this is left out, then libGL ends up not having this + * symbol, and drivers using it fail to load. Compare the + * implementation of this symbol to _glapi_noop_enable_warnings(), + * though, which gets into the library despite no callers, the same + * prototypes, and the same compile flags to the files containing + * them. Moving the definition to glapi_nop.c gets it into the + * library, though. + */ + (void)_glthread_GetID(); + /* 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. @@ -236,41 +246,42 @@ MakeContextCurrent(Display * dpy, GLXDrawable draw, _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; - } - + __glXLock(); if (oldGC == gc && - gc->currentDrawable == draw && gc->currentReadable == read) + gc->currentDrawable == draw && gc->currentReadable == read) { + __glXUnlock(); return True; + } if (oldGC != &dummyContext) { - oldGC->vtable->unbind(oldGC, gc); - oldGC->currentDpy = 0; - oldGC->currentDrawable = None; - oldGC->currentReadable = None; - oldGC->thread_id = 0; + if (--oldGC->thread_refcount == 0) { + oldGC->vtable->unbind(oldGC, gc); + oldGC->currentDpy = 0; + oldGC->currentDrawable = None; + oldGC->currentReadable = None; + + if (oldGC->xid == None && oldGC != gc) { + /* 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) { - gc->currentDpy = dpy; - gc->currentDrawable = draw; - gc->currentReadable = read; - gc->thread_id = _glthread_GetID(); + if (gc->thread_refcount++ == 0) { + gc->currentDpy = dpy; + gc->currentDrawable = draw; + gc->currentReadable = read; + } __glXSetCurrentContext(gc); ret = gc->vtable->bind(gc, oldGC, draw, read); } else { __glXSetCurrentContextNull(); } - if (oldGC != &dummyContext && oldGC->xid == None && oldGC != gc) { - /* 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(); if (ret) { __glXGenerateError(dpy, gc, None, ret, X_GLXMakeContextCurrent); diff --git a/src/glx/glxextensions.c b/src/glx/glxextensions.c index 3a0e64c46d1..ffd466479b4 100644 --- a/src/glx/glxextensions.c +++ b/src/glx/glxextensions.c @@ -90,6 +90,7 @@ static const struct extension_info known_glx_extensions[] = { { GLX(MESA_agp_offset), VER(0,0), N, N, N, Y }, /* Deprecated */ { GLX(MESA_copy_sub_buffer), VER(0,0), Y, N, N, N }, #endif + { GLX(MESA_multithread_makecurrent),VER(0,0), Y, N, Y, N }, { GLX(MESA_pixmap_colormap), VER(0,0), N, N, N, N }, /* Deprecated */ { GLX(MESA_release_buffers), VER(0,0), N, N, N, N }, /* Deprecated */ #ifdef GLX_USE_APPLEGL diff --git a/src/glx/glxextensions.h b/src/glx/glxextensions.h index 78776618338..333b3f9adbd 100644 --- a/src/glx/glxextensions.h +++ b/src/glx/glxextensions.h @@ -43,6 +43,7 @@ enum MESA_agp_offset_bit, MESA_copy_sub_buffer_bit, MESA_depth_float_bit, + MESA_multithread_makecurrent_bit, MESA_pixmap_colormap_bit, MESA_release_buffers_bit, MESA_swap_control_bit, |