diff options
author | Eric Anholt <[email protected]> | 2011-02-03 17:26:02 -0800 |
---|---|---|
committer | Eric Anholt <[email protected]> | 2011-02-26 12:43:15 -0800 |
commit | 49d7e48b33264d94e30af6129c281b6acafa9427 (patch) | |
tree | 48f510037ec7c76e833d213d4706ae043484192a /src/glx | |
parent | 132dc0b6d2aef79920d750d8f4f3852f7e2d599a (diff) |
mesa: Add new MESA_multithread_makecurrent extension.
This extension allows a client to bind one context in multiple threads
simultaneously. It is then up to the client to manage synchronization of
access to the GL, just as normal multithreaded GL from multiple contexts
requires synchronization management to shared objects.
Diffstat (limited to 'src/glx')
-rw-r--r-- | src/glx/glxclient.h | 4 | ||||
-rw-r--r-- | src/glx/glxcurrent.c | 55 | ||||
-rw-r--r-- | src/glx/glxextensions.c | 1 | ||||
-rw-r--r-- | src/glx/glxextensions.h | 1 |
4 files changed, 37 insertions, 24 deletions
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/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, |