diff options
author | Kyle Brenneman <kbrenneman@nvidia.com> | 2016-01-21 15:08:26 -0700 |
---|---|---|
committer | Kyle Brenneman <kbrenneman@nvidia.com> | 2016-01-21 15:19:57 -0700 |
commit | ba0b05a5691006b8e954af6494a58c057514bb6e (patch) | |
tree | 49e16f8ed065f0e30c9c47f5d8c42f9bfb617e60 | |
parent | 7c4076ddc82896c7186b1176ceb7422bc8488c7b (diff) |
GLDispatch: Initialize the dispatch table from __glDispatchCheckMultithreaded.
__glDispatchCheckMultithreaded will now check if the thread's current dispatch
table is NULL, and if it is, it will plug in the no-op table.
This is a workaround for some broken applications which try to call OpenGL
functions without a current context. As long as the thread calls a GLX function
first, any OpenGL calls it makes later will call a no-op stub instead of just
crashing.
Added calls to __glXThreadInitialize to some of the functions in
__GLXapiExports, so that GLX extension functions will still call
__glXThreadInitialize.
-rw-r--r-- | src/GLX/libglx.c | 2 | ||||
-rw-r--r-- | src/GLX/libglxmapping.c | 6 | ||||
-rw-r--r-- | src/GLdispatch/GLdispatch.c | 12 |
3 files changed, 20 insertions, 0 deletions
diff --git a/src/GLX/libglx.c b/src/GLX/libglx.c index 5e5f01a..ba898fd 100644 --- a/src/GLX/libglx.c +++ b/src/GLX/libglx.c @@ -473,6 +473,8 @@ PUBLIC Display *glXGetCurrentDisplay(void) __GLXvendorInfo *__glXGetCurrentDynDispatch(void) { + __glXThreadInitialize(); + __GLXAPIState *apiState = __glXGetCurrentAPIState(); if (apiState != NULL) { diff --git a/src/GLX/libglxmapping.c b/src/GLX/libglxmapping.c index daffa0a..a68801f 100644 --- a/src/GLX/libglxmapping.c +++ b/src/GLX/libglxmapping.c @@ -911,6 +911,8 @@ static int VendorFromPointer(__GLXvendorPointerHashtable *table, void *ptr, __GLXvendorPointerMappingHash *pEntry; __GLXvendorInfo *vendor = NULL; + __glXThreadInitialize(); + LKDHASH_RDLOCK(__glXPthreadFuncs, *table); HASH_FIND_PTR(_LH(*table), &ptr, pEntry); @@ -975,6 +977,8 @@ void __glXRemoveScreenVisualMapping(Display *dpy, const XVisualInfo *visual) } int __glXVendorFromVisual(Display *dpy, const XVisualInfo *visual, __GLXvendorInfo **retVendor) { + __glXThreadInitialize(); + if (retVendor != NULL) { *retVendor = __glXLookupVendorByScreen(dpy, visual->screen); } @@ -1094,6 +1098,8 @@ void __glXRemoveVendorDrawableMapping(Display *dpy, GLXDrawable drawable) int __glXVendorFromDrawable(Display *dpy, GLXDrawable drawable, __GLXvendorInfo **retVendor) { + __glXThreadInitialize(); + __GLXdisplayInfo *dpyInfo = __glXLookupDisplay(dpy); __GLXvendorInfo *vendor = NULL; if (dpyInfo != NULL) { diff --git a/src/GLdispatch/GLdispatch.c b/src/GLdispatch/GLdispatch.c index e9948c2..1c54a29 100644 --- a/src/GLdispatch/GLdispatch.c +++ b/src/GLdispatch/GLdispatch.c @@ -810,6 +810,18 @@ void __glDispatchCheckMultithreaded(void) { if (!pthreadFuncs.is_singlethreaded) { + // Check to see if the current thread has a dispatch table assigned to + // it, and if it doesn't, then plug in the no-op table. + // This is a partial workaround to broken applications that try to call + // OpenGL functions without a current context, without adding any + // additional overhead to the dispatch stubs themselves. As long as the + // thread calls at least one GLX function first, any OpenGL calls will + // go to the no-op stubs instead of crashing. + if (_glapi_get_current() == NULL) { + // Calling _glapi_set_current(NULL) will plug in the no-op table. + _glapi_set_current(NULL); + } + LockDispatch(); if (!isMultiThreaded) { glvnd_thread_t tid = pthreadFuncs.self(); |