summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEric Anholt <eric@anholt.net>2013-12-17 09:31:39 -0800
committerEric Anholt <eric@anholt.net>2013-12-17 12:11:05 -0800
commit9a7be0784faba0d97a32051a873d7feb47981a37 (patch)
treeab1e3ff4bb950aee5dd0c1844c0389b06236bd71 /src
parent8022cda75d65f537c48d4b43b44879abe558c1b7 (diff)
win32: Use thread local storage to get us a dispatch table per thread.
Diffstat (limited to 'src')
-rw-r--r--src/dispatch_common.h7
-rw-r--r--src/dispatch_wgl.c59
-rwxr-xr-xsrc/gen_dispatch.py15
3 files changed, 79 insertions, 2 deletions
diff --git a/src/dispatch_common.h b/src/dispatch_common.h
index 7f317a4..5170239 100644
--- a/src/dispatch_common.h
+++ b/src/dispatch_common.h
@@ -94,3 +94,10 @@ bool epoxy_extension_in_string(const char *extension_list, const char *ext);
extern void UNWRAPPED_PROTO(epoxy_glBegin_unwrapped)(GLenum primtype);
extern void UNWRAPPED_PROTO(epoxy_glEnd_unwrapped)(void);
+
+#if USING_DISPATCH_TABLE
+void gl_init_dispatch_table(void);
+void wgl_init_dispatch_table(void);
+extern uint32_t gl_tls_index, gl_tls_size;
+extern uint32_t wgl_tls_index, wgl_tls_size;
+#endif
diff --git a/src/dispatch_wgl.c b/src/dispatch_wgl.c
index fe871d9..0161ad4 100644
--- a/src/dispatch_wgl.c
+++ b/src/dispatch_wgl.c
@@ -58,3 +58,62 @@ epoxy_has_wgl_extension(HDC hdc, const char *ext)
return epoxy_extension_in_string(getext(hdc), ext);
}
+
+static void
+reset_dispatch_table(void)
+{
+ gl_init_dispatch_table();
+ wgl_init_dispatch_table();
+}
+
+/**
+ * This global symbol is apparently looked up by Windows when loading
+ * a DLL, but it doesn't declare the prototype.
+ */
+BOOL WINAPI
+DllMain(HINSTANCE dll, DWORD reason, LPVOID reserved);
+
+BOOL WINAPI
+DllMain(HINSTANCE dll, DWORD reason, LPVOID reserved)
+{
+ void *data;
+
+ switch (reason) {
+ case DLL_PROCESS_ATTACH:
+ gl_tls_index = TlsAlloc();
+ if (gl_tls_index == TLS_OUT_OF_INDEXES)
+ return FALSE;
+ wgl_tls_index = TlsAlloc();
+ if (wgl_tls_index == TLS_OUT_OF_INDEXES)
+ return FALSE;
+
+ /* FALLTHROUGH */
+
+ case DLL_THREAD_ATTACH:
+ data = LocalAlloc(LPTR, gl_tls_size);
+ TlsSetValue(gl_tls_index, data);
+
+ data = LocalAlloc(LPTR, wgl_tls_size);
+ TlsSetValue(wgl_tls_index, data);
+
+ reset_dispatch_table();
+ break;
+
+ case DLL_THREAD_DETACH:
+ case DLL_PROCESS_DETACH:
+ data = TlsGetValue(gl_tls_index);
+ LocalFree(data);
+
+ data = TlsGetValue(wgl_tls_index);
+ LocalFree(data);
+ break;
+
+ if (reason == DLL_PROCESS_DETACH) {
+ TlsFree(gl_tls_index);
+ TlsFree(wgl_tls_index);
+ }
+ break;
+ }
+
+ return TRUE;
+}
diff --git a/src/gen_dispatch.py b/src/gen_dispatch.py
index 4da840a..35c74de 100755
--- a/src/gen_dispatch.py
+++ b/src/gen_dispatch.py
@@ -794,11 +794,22 @@ class Generator(object):
self.outln('};')
self.outln('')
+ self.outln('uint32_t {0}_tls_index;'.format(self.target))
+ self.outln('uint32_t {0}_tls_size = sizeof(struct dispatch_table);'.format(self.target))
+ self.outln('')
+
self.outln('static inline struct dispatch_table *')
self.outln('get_dispatch_table(void)')
self.outln('{')
- self.outln(' /* XXX: Make this thread-local and swapped on makecurrent on win32. */')
- self.outln(' return &resolver_table;')
+ self.outln(' return TlsGetValue({0}_tls_index);'.format(self.target))
+ self.outln('}')
+ self.outln('')
+
+ self.outln('void')
+ self.outln('{0}_init_dispatch_table(void)'.format(self.target))
+ self.outln('{')
+ self.outln(' struct dispatch_table *dispatch_table = get_dispatch_table();')
+ self.outln(' memcpy(dispatch_table, &resolver_table, sizeof(resolver_table));')
self.outln('}')
self.outln('')