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 ') + self.outln('#include ') self.outln('#include ') 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')