summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Anholt <eric@anholt.net>2014-03-19 14:18:26 -0700
committerEric Anholt <eric@anholt.net>2014-03-28 16:45:26 -0700
commit3e09de7550cd901b8d3ecbf27e0128f0dc0f0b99 (patch)
tree07a11826a31ddba7a89b37e2de98def1859bbadb
parent370c49d5cdd8060ea2fee1e777311f86b495aa94 (diff)
downloadlibepoxy-3e09de7550cd901b8d3ecbf27e0128f0dc0f0b99.tar.gz
win32: Delay using dispatch tables until the second MakeCurrent.
Fixes #11.
-rw-r--r--README.md8
-rw-r--r--src/dispatch_common.h39
-rw-r--r--src/dispatch_wgl.c29
-rwxr-xr-xsrc/gen_dispatch.py24
4 files changed, 55 insertions, 45 deletions
diff --git a/README.md b/README.md
index 0beb63c..5d10539 100644
--- a/README.md
+++ b/README.md
@@ -120,12 +120,6 @@ epoxy (in a way that might change the device or pixel format), then
epoxy needs to be notified of the change using the
```epoxy_handle_external_wglMakeCurrent()``` function.
-The win32 dispatch layer is currently slower than it should be in the
-single-context (or multi-context, but same device and pixel format)
-case. We need to switch to using the linux-like function pointer
-stubs, and detect when transitioning to multi-device/format and hook
-in the per-thread dispatch table at that point.
-
-The win32 wglMakeCurrent () variants are slower than they should be,
+The win32 wglMakeCurrent() variants are slower than they should be,
because they should be caching the resolved dispatch tables instead of
resetting an entire thread-local dispatch table every time.
diff --git a/src/dispatch_common.h b/src/dispatch_common.h
index aa8d04e..5974aa0 100644
--- a/src/dispatch_common.h
+++ b/src/dispatch_common.h
@@ -76,10 +76,23 @@
#define WRAPPER_VISIBILITY static GLAPIENTRY
#define WRAPPER(x) x ## _wrapped
-#if USING_DISPATCH_TABLE
-#define GEN_GLOBAL_REWRITE_PTR(name, args, passthrough)
-#define GEN_GLOBAL_REWRITE_PTR_RET(ret, name, args, passthrough)
+#define GEN_GLOBAL_REWRITE_PTR(name, args, passthrough) \
+ static EPOXYCALL void \
+ name##_global_rewrite_ptr args \
+ { \
+ name = (void *)name##_resolver(); \
+ name passthrough; \
+ }
+#define GEN_GLOBAL_REWRITE_PTR_RET(ret, name, args, passthrough) \
+ static EPOXYCALL ret \
+ name##_global_rewrite_ptr args \
+ { \
+ name = (void *)name##_resolver(); \
+ return name passthrough; \
+ }
+
+#if USING_DISPATCH_TABLE
#define GEN_DISPATCH_TABLE_REWRITE_PTR(name, args, passthrough) \
static EPOXYCALL void \
name##_dispatch_table_rewrite_ptr args \
@@ -115,21 +128,6 @@
}
#else
-#define GEN_GLOBAL_REWRITE_PTR(name, args, passthrough) \
- static EPOXYCALL void \
- name##_global_rewrite_ptr args \
- { \
- name = (void *)name##_resolver(); \
- name passthrough; \
- }
-
-#define GEN_GLOBAL_REWRITE_PTR_RET(ret, name, args, passthrough) \
- static EPOXYCALL ret \
- name##_global_rewrite_ptr args \
- { \
- name = (void *)name##_resolver(); \
- return name passthrough; \
- }
#define GEN_DISPATCH_TABLE_REWRITE_PTR(name, args, passthrough)
#define GEN_DISPATCH_TABLE_REWRITE_PTR_RET(ret, name, args, passthrough)
#define GEN_DISPATCH_TABLE_THUNK(name, args, passthrough)
@@ -176,9 +174,12 @@ extern void UNWRAPPED_PROTO(glEnd_unwrapped)(void);
#if USING_DISPATCH_TABLE
void gl_init_dispatch_table(void);
+void gl_switch_to_dispatch_table(void);
void wgl_init_dispatch_table(void);
+void wgl_switch_to_dispatch_table(void);
extern uint32_t gl_tls_index, gl_tls_size;
extern uint32_t wgl_tls_index, wgl_tls_size;
+
#define wglMakeCurrent_unwrapped epoxy_wglMakeCurrent_unwrapped
#define wglMakeContextCurrentARB_unwrapped epoxy_wglMakeContextCurrentARB_unwrapped
#define wglMakeContextCurrentEXT_unwrapped epoxy_wglMakeContextCurrentEXT_unwrapped
@@ -187,4 +188,4 @@ extern BOOL UNWRAPPED_PROTO(wglMakeCurrent_unwrapped)(HDC hdc, HGLRC hglrc);
extern BOOL UNWRAPPED_PROTO(wglMakeContextCurrentARB_unwrapped)(HDC hDrawDC, HDC hReadDC, HGLRC hglrc);
extern BOOL UNWRAPPED_PROTO(wglMakeContextCurrentEXT_unwrapped)(HDC hDrawDC, HDC hReadDC, HGLRC hglrc);
extern BOOL UNWRAPPED_PROTO(wglMakeAssociatedContextCurrentAMD_unwrapped)(HGLRC hglrc);
-#endif
+#endif /* _WIN32_ */
diff --git a/src/dispatch_wgl.c b/src/dispatch_wgl.c
index 1156419..5b3a8ef 100644
--- a/src/dispatch_wgl.c
+++ b/src/dispatch_wgl.c
@@ -27,6 +27,9 @@
#include "dispatch_common.h"
+static bool first_context_current = false;
+static bool already_switched_to_dispatch_table = false;
+
/**
* If we can determine the WGL extension support from the current
* context, then return that, otherwise give the answer that will just
@@ -63,16 +66,27 @@ epoxy_has_wgl_extension(HDC hdc, const char *ext)
* Does the work necessary to update the win32 per-thread dispatch
* tables when wglMakeCurrent() is called.
*
- * Right now, we just reset everything to "do wglGetProcAddress()
- * again". This could be improved in the future to track a resolved
- * dispatch table per context and reuse it when the context is made
- * current again.
+ * Right now, we use global function pointers until the second
+ * MakeCurrent occurs, at which point we switch to dispatch tables.
+ * This could be improved in the future to track a resolved dispatch
+ * table per context and reuse it when the context is made current
+ * again.
*/
PUBLIC void
epoxy_handle_external_wglMakeCurrent(void)
{
- gl_init_dispatch_table();
- wgl_init_dispatch_table();
+ if (!first_context_current) {
+ first_context_current = true;
+ } else {
+ if (!already_switched_to_dispatch_table) {
+ already_switched_to_dispatch_table = true;
+ gl_switch_to_dispatch_table();
+ wgl_switch_to_dispatch_table();
+ }
+
+ gl_init_dispatch_table();
+ wgl_init_dispatch_table();
+ }
}
/**
@@ -96,6 +110,8 @@ DllMain(HINSTANCE dll, DWORD reason, LPVOID reserved)
if (wgl_tls_index == TLS_OUT_OF_INDEXES)
return FALSE;
+ first_context_current = false;
+
/* FALLTHROUGH */
case DLL_THREAD_ATTACH:
@@ -105,7 +121,6 @@ DllMain(HINSTANCE dll, DWORD reason, LPVOID reserved)
data = LocalAlloc(LPTR, wgl_tls_size);
TlsSetValue(wgl_tls_index, data);
- epoxy_handle_external_wglMakeCurrent();
break;
case DLL_THREAD_DETACH:
diff --git a/src/gen_dispatch.py b/src/gen_dispatch.py
index 5af23d6..072a0fe 100755
--- a/src/gen_dispatch.py
+++ b/src/gen_dispatch.py
@@ -611,18 +611,12 @@ class Generator(object):
func.args_decl,
func.args_list))
- def write_linux_function_pointer(self, func):
+ def write_function_pointer(self, func):
self.outln('{0}{1} epoxy_{2} = epoxy_{2}_global_rewrite_ptr;'.format(func.public,
func.ptr_type,
func.wrapped_name))
self.outln('')
- def write_win32_function_pointer(self, func):
- self.outln('{0}{1} epoxy_{2} = epoxy_{2}_dispatch_table_thunk;'.format(func.public,
- func.ptr_type,
- func.wrapped_name))
- self.outln('')
-
def write_provider_enums(self):
# Writes the enum declaration for the list of providers
# supported by gl_provider_resolver()
@@ -728,6 +722,7 @@ class Generator(object):
self.outln(' */')
self.outln('')
self.outln('#include <stdlib.h>')
+ self.outln('#include <string.h>')
self.outln('#include <stdio.h>')
self.outln('')
self.outln('#include "dispatch_common.h"')
@@ -788,16 +783,21 @@ class Generator(object):
self.outln('}')
self.outln('')
- for func in self.sorted_functions:
- self.write_win32_function_pointer(func)
-
- self.outln('#else /* !USING_DISPATCH_TABLE */')
+ self.outln('void')
+ self.outln('{0}_switch_to_dispatch_table(void)'.format(self.target))
+ self.outln('{')
for func in self.sorted_functions:
- self.write_linux_function_pointer(func)
+ self.outln(' epoxy_{0} = epoxy_{0}_dispatch_table_thunk;'.format(func.wrapped_name))
+
+ self.outln('}')
+ self.outln('')
self.outln('#endif /* !USING_DISPATCH_TABLE */')
+ for func in self.sorted_functions:
+ self.write_function_pointer(func)
+
argparser = argparse.ArgumentParser(description='Generate GL dispatch wrappers.')
argparser.add_argument('files', metavar='file.xml', nargs='+', help='GL API XML files to be parsed')
argparser.add_argument('--dir', metavar='dir', required=True, help='Destination directory')