summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKyle Brenneman <kbrenneman@nvidia.com>2016-01-21 15:08:26 -0700
committerKyle Brenneman <kbrenneman@nvidia.com>2016-01-21 15:19:57 -0700
commitba0b05a5691006b8e954af6494a58c057514bb6e (patch)
tree49e16f8ed065f0e30c9c47f5d8c42f9bfb617e60
parent7c4076ddc82896c7186b1176ceb7422bc8488c7b (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.c2
-rw-r--r--src/GLX/libglxmapping.c6
-rw-r--r--src/GLdispatch/GLdispatch.c12
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();