summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEric Anholt <[email protected]>2011-02-03 17:26:02 -0800
committerEric Anholt <[email protected]>2011-02-26 12:43:15 -0800
commit49d7e48b33264d94e30af6129c281b6acafa9427 (patch)
tree48f510037ec7c76e833d213d4706ae043484192a /src
parent132dc0b6d2aef79920d750d8f4f3852f7e2d599a (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')
-rw-r--r--src/glx/glxclient.h4
-rw-r--r--src/glx/glxcurrent.c55
-rw-r--r--src/glx/glxextensions.c1
-rw-r--r--src/glx/glxextensions.h1
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,