win32: Delay using dispatch tables until the second MakeCurrent.

Fixes #11.
macos/v1.5.9
Eric Anholt 11 years ago
parent 370c49d5cd
commit 3e09de7550
  1. 6
      README.md
  2. 39
      src/dispatch_common.h
  3. 25
      src/dispatch_wgl.c
  4. 24
      src/gen_dispatch.py

@ -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 needs to be notified of the change using the
```epoxy_handle_external_wglMakeCurrent()``` function. ```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 because they should be caching the resolved dispatch tables instead of
resetting an entire thread-local dispatch table every time. resetting an entire thread-local dispatch table every time.

@ -76,10 +76,23 @@
#define WRAPPER_VISIBILITY static GLAPIENTRY #define WRAPPER_VISIBILITY static GLAPIENTRY
#define WRAPPER(x) x ## _wrapped #define WRAPPER(x) x ## _wrapped
#if USING_DISPATCH_TABLE #define GEN_GLOBAL_REWRITE_PTR(name, args, passthrough) \
#define GEN_GLOBAL_REWRITE_PTR(name, args, passthrough) static EPOXYCALL void \
#define GEN_GLOBAL_REWRITE_PTR_RET(ret, name, args, passthrough) 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) \ #define GEN_DISPATCH_TABLE_REWRITE_PTR(name, args, passthrough) \
static EPOXYCALL void \ static EPOXYCALL void \
name##_dispatch_table_rewrite_ptr args \ name##_dispatch_table_rewrite_ptr args \
@ -115,21 +128,6 @@
} }
#else #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(name, args, passthrough)
#define GEN_DISPATCH_TABLE_REWRITE_PTR_RET(ret, name, args, passthrough) #define GEN_DISPATCH_TABLE_REWRITE_PTR_RET(ret, name, args, passthrough)
#define GEN_DISPATCH_TABLE_THUNK(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 #if USING_DISPATCH_TABLE
void gl_init_dispatch_table(void); void gl_init_dispatch_table(void);
void gl_switch_to_dispatch_table(void);
void wgl_init_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 gl_tls_index, gl_tls_size;
extern uint32_t wgl_tls_index, wgl_tls_size; extern uint32_t wgl_tls_index, wgl_tls_size;
#define wglMakeCurrent_unwrapped epoxy_wglMakeCurrent_unwrapped #define wglMakeCurrent_unwrapped epoxy_wglMakeCurrent_unwrapped
#define wglMakeContextCurrentARB_unwrapped epoxy_wglMakeContextCurrentARB_unwrapped #define wglMakeContextCurrentARB_unwrapped epoxy_wglMakeContextCurrentARB_unwrapped
#define wglMakeContextCurrentEXT_unwrapped epoxy_wglMakeContextCurrentEXT_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(wglMakeContextCurrentARB_unwrapped)(HDC hDrawDC, HDC hReadDC, HGLRC hglrc);
extern BOOL UNWRAPPED_PROTO(wglMakeContextCurrentEXT_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); extern BOOL UNWRAPPED_PROTO(wglMakeAssociatedContextCurrentAMD_unwrapped)(HGLRC hglrc);
#endif #endif /* _WIN32_ */

@ -27,6 +27,9 @@
#include "dispatch_common.h" #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 * If we can determine the WGL extension support from the current
* context, then return that, otherwise give the answer that will just * context, then return that, otherwise give the answer that will just
@ -63,17 +66,28 @@ epoxy_has_wgl_extension(HDC hdc, const char *ext)
* Does the work necessary to update the win32 per-thread dispatch * Does the work necessary to update the win32 per-thread dispatch
* tables when wglMakeCurrent() is called. * tables when wglMakeCurrent() is called.
* *
* Right now, we just reset everything to "do wglGetProcAddress() * Right now, we use global function pointers until the second
* again". This could be improved in the future to track a resolved * MakeCurrent occurs, at which point we switch to dispatch tables.
* dispatch table per context and reuse it when the context is made * This could be improved in the future to track a resolved dispatch
* current again. * table per context and reuse it when the context is made current
* again.
*/ */
PUBLIC void PUBLIC void
epoxy_handle_external_wglMakeCurrent(void) epoxy_handle_external_wglMakeCurrent(void)
{ {
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(); gl_init_dispatch_table();
wgl_init_dispatch_table(); wgl_init_dispatch_table();
} }
}
/** /**
* This global symbol is apparently looked up by Windows when loading * This global symbol is apparently looked up by Windows when loading
@ -96,6 +110,8 @@ DllMain(HINSTANCE dll, DWORD reason, LPVOID reserved)
if (wgl_tls_index == TLS_OUT_OF_INDEXES) if (wgl_tls_index == TLS_OUT_OF_INDEXES)
return FALSE; return FALSE;
first_context_current = false;
/* FALLTHROUGH */ /* FALLTHROUGH */
case DLL_THREAD_ATTACH: case DLL_THREAD_ATTACH:
@ -105,7 +121,6 @@ DllMain(HINSTANCE dll, DWORD reason, LPVOID reserved)
data = LocalAlloc(LPTR, wgl_tls_size); data = LocalAlloc(LPTR, wgl_tls_size);
TlsSetValue(wgl_tls_index, data); TlsSetValue(wgl_tls_index, data);
epoxy_handle_external_wglMakeCurrent();
break; break;
case DLL_THREAD_DETACH: case DLL_THREAD_DETACH:

@ -611,18 +611,12 @@ class Generator(object):
func.args_decl, func.args_decl,
func.args_list)) 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, self.outln('{0}{1} epoxy_{2} = epoxy_{2}_global_rewrite_ptr;'.format(func.public,
func.ptr_type, func.ptr_type,
func.wrapped_name)) func.wrapped_name))
self.outln('') 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): def write_provider_enums(self):
# Writes the enum declaration for the list of providers # Writes the enum declaration for the list of providers
# supported by gl_provider_resolver() # supported by gl_provider_resolver()
@ -728,6 +722,7 @@ class Generator(object):
self.outln(' */') self.outln(' */')
self.outln('') self.outln('')
self.outln('#include <stdlib.h>') self.outln('#include <stdlib.h>')
self.outln('#include <string.h>')
self.outln('#include <stdio.h>') self.outln('#include <stdio.h>')
self.outln('') self.outln('')
self.outln('#include "dispatch_common.h"') self.outln('#include "dispatch_common.h"')
@ -788,16 +783,21 @@ class Generator(object):
self.outln('}') self.outln('}')
self.outln('') self.outln('')
for func in self.sorted_functions: self.outln('void')
self.write_win32_function_pointer(func) self.outln('{0}_switch_to_dispatch_table(void)'.format(self.target))
self.outln('{')
self.outln('#else /* !USING_DISPATCH_TABLE */')
for func in self.sorted_functions: 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 */') 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 = 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('files', metavar='file.xml', nargs='+', help='GL API XML files to be parsed')
argparser.add_argument('--dir', metavar='dir', required=True, help='Destination directory') argparser.add_argument('--dir', metavar='dir', required=True, help='Destination directory')

Loading…
Cancel
Save