summaryrefslogtreecommitdiffstats
path: root/src/glx
diff options
context:
space:
mode:
Diffstat (limited to 'src/glx')
-rw-r--r--src/glx/dri2_glx.c9
-rw-r--r--src/glx/glxclient.h4
-rw-r--r--src/glx/glxcmds.c8
-rw-r--r--src/glx/glxcurrent.c55
-rw-r--r--src/glx/glxextensions.c1
-rw-r--r--src/glx/glxextensions.h1
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,