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. 8
      README.md
  2. 39
      src/dispatch_common.h
  3. 29
      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_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.

@ -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_ */

@ -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:

@ -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')

Loading…
Cancel
Save