win32: Convert the API to being based on function pointers, like Linux.

For performance, I want to be able to make single-context (well,
single-pixel-format-and-device) apps be able to directly call GL
functions through function pointers.  Bake that into the ABI now so I
can get a release out the door and fix this up later.

This also fixes the lack of __stdcall annotation on the
PFNWHATEVERPROC typedefs.
macos/v1.5.9
Eric Anholt 11 years ago
parent 3ae4726cdb
commit 9bc909f5a7
  1. 10
      README.md
  2. 2
      include/epoxy/gl.h
  3. 2
      src/dispatch_common.c
  4. 12
      src/dispatch_common.h
  5. 4
      src/dispatch_wgl.c
  6. 36
      src/gen_dispatch.py

@ -119,3 +119,13 @@ pixel format. If ```wglMakeCurrent()``` is called from outside of
epoxy (in a way that might change the device or pixel format), then epoxy (in a way that might change the device or pixel format), then
epoxy needs to be notified of the change using epoxy needs to be notified of the change using
```epoxy_handle_external_wglMakeCurrent()```. ```epoxy_handle_external_wglMakeCurrent()```.
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,
because they should be caching the resolved dispatch tables instead of
resetting an entire thread-local dispatch table every time.

@ -59,7 +59,7 @@ extern "C" {
#endif #endif
#ifndef EPOXYAPIENTRY #ifndef EPOXYAPIENTRY
#define EPOXYAPIENTRY __declspec(dllimport) #define EPOXYAPIENTRY __declspec(dllimport) __stdcall
#endif #endif
#ifndef GLAPI #ifndef GLAPI

@ -503,7 +503,5 @@ WRAPPER(epoxy_glEnd)(void)
#endif #endif
} }
#ifndef _WIN32
PUBLIC PFNGLBEGINPROC epoxy_glBegin = epoxy_glBegin_wrapped; PUBLIC PFNGLBEGINPROC epoxy_glBegin = epoxy_glBegin_wrapped;
PUBLIC PFNGLENDPROC epoxy_glEnd = epoxy_glEnd_wrapped; PUBLIC PFNGLENDPROC epoxy_glEnd = epoxy_glEnd_wrapped;
#endif

@ -27,7 +27,7 @@
#define PLATFORM_HAS_EGL 0 #define PLATFORM_HAS_EGL 0
#define PLATFORM_HAS_GLX 0 #define PLATFORM_HAS_GLX 0
#define PLATFORM_HAS_WGL 1 #define PLATFORM_HAS_WGL 1
#define EPOXYAPIENTRY __declspec(dllexport) #define EPOXYAPIENTRY __declspec(dllexport) __stdcall
#elif defined(__APPLE__) #elif defined(__APPLE__)
#define PLATFORM_HAS_EGL 0 #define PLATFORM_HAS_EGL 0
#define PLATFORM_HAS_GLX 1 #define PLATFORM_HAS_GLX 1
@ -65,16 +65,14 @@
*/ */
#if defined(_WIN32) #if defined(_WIN32)
#define USING_DISPATCH_TABLE 1 #define USING_DISPATCH_TABLE 1
#define UNWRAPPED_PROTO(x) x
#define WRAPPER_VISIBILITY PUBLIC
#define WRAPPER(x) x
#else #else
#define USING_DISPATCH_TABLE 0 #define USING_DISPATCH_TABLE 0
#define UNWRAPPED_PROTO(x) (*x)
#define WRAPPER_VISIBILITY static
#define WRAPPER(x) x ## _wrapped
#endif #endif
#define UNWRAPPED_PROTO(x) (GLAPIENTRY *x)
#define WRAPPER_VISIBILITY static GLAPIENTRY
#define WRAPPER(x) x ## _wrapped
void *epoxy_egl_dlsym(const char *name); void *epoxy_egl_dlsym(const char *name);
void *epoxy_glx_dlsym(const char *name); void *epoxy_glx_dlsym(const char *name);
void *epoxy_gl_dlsym(const char *name); void *epoxy_gl_dlsym(const char *name);

@ -176,3 +176,7 @@ WRAPPER(epoxy_wglMakeAssociatedContextCurrentAMD)(HGLRC hglrc)
return ret; return ret;
} }
PUBLIC PFNWGLMAKECURRENTPROC epoxy_wglMakeCurrent = epoxy_wglMakeCurrent_wrapped;
PUBLIC PFNWGLMAKECONTEXTCURRENTEXTPROC epoxy_wglMakeContextCurrentEXT = epoxy_wglMakeContextCurrentEXT_wrapped;
PUBLIC PFNWGLMAKECONTEXTCURRENTARBPROC epoxy_wglMakeContextCurrentARB = epoxy_wglMakeContextCurrentARB_wrapped;
PUBLIC PFNWGLMAKEASSOCIATEDCONTEXTCURRENTAMDPROC epoxy_wglMakeAssociatedContextCurrentEXT = epoxy_wglMakeAssociatedContextCurrentAMD_wrapped;

@ -451,8 +451,9 @@ class Generator(object):
def write_function_ptr_typedefs(self): def write_function_ptr_typedefs(self):
for func in self.sorted_functions: for func in self.sorted_functions:
self.outln('typedef {0} (*{1})({2});'.format(func.ret_type, func.ptr_type, self.outln('typedef {0} (GLAPIENTRY *{1})({2});'.format(func.ret_type,
func.args_decl)) func.ptr_type,
func.args_decl))
def write_header_header(self, file): def write_header_header(self, file):
self.out_file = open(file, 'w') self.out_file = open(file, 'w')
@ -503,18 +504,8 @@ class Generator(object):
self.outln('') self.outln('')
self.write_function_ptr_typedefs() self.write_function_ptr_typedefs()
self.outln('/* The library ABI is a set of functions on win32 (where')
self.outln(' * we have to use per-thread dispatch tables) and a set')
self.outln(' * of function pointers, otherwise.')
self.outln(' */')
self.outln('#ifdef _WIN32')
self.outln('#define EPOXY_FPTR(x) x')
self.outln('#else')
self.outln('#define EPOXY_FPTR(x) (*x)')
self.outln('#endif')
for func in self.sorted_functions: for func in self.sorted_functions:
self.outln('extern EPOXYAPIENTRY {0} EPOXY_FPTR(epoxy_{1})({2});'.format(func.ret_type, self.outln('extern EPOXYAPIENTRY {0} (*epoxy_{1})({2});'.format(func.ret_type,
func.name, func.name,
func.args_decl)) func.args_decl))
self.outln('') self.outln('')
@ -582,8 +573,8 @@ class Generator(object):
dispatch_table_entry = 'dispatch_table->p{0}'.format(func.alias_name) dispatch_table_entry = 'dispatch_table->p{0}'.format(func.alias_name)
self.outln('{0}{1}'.format(func.public, func.ret_type)) self.outln('static __stdcall {0}'.format(func.ret_type))
self.outln('epoxy_{0}({1})'.format(func.wrapped_name, func.args_decl)) self.outln('epoxy_{0}_dispatch_table_thunk({1})'.format(func.wrapped_name, func.args_decl))
self.outln('{') self.outln('{')
self.outln(' struct dispatch_table *dispatch_table = get_dispatch_table();') self.outln(' struct dispatch_table *dispatch_table = get_dispatch_table();')
self.outln('') self.outln('')
@ -601,7 +592,7 @@ class Generator(object):
dispatch_table_entry = 'dispatch_table->p{0}'.format(func.name) dispatch_table_entry = 'dispatch_table->p{0}'.format(func.name)
self.outln('static {0}'.format(func.ret_type)) self.outln('static GLAPIENTRY {0}'.format(func.ret_type))
self.outln('epoxy_{0}_rewrite_stub({1})'.format(func.name, func.args_decl)) self.outln('epoxy_{0}_rewrite_stub({1})'.format(func.name, func.args_decl))
self.outln('{') self.outln('{')
self.outln(' struct dispatch_table *dispatch_table = get_dispatch_table();') self.outln(' struct dispatch_table *dispatch_table = get_dispatch_table();')
@ -616,7 +607,7 @@ class Generator(object):
self.outln('}') self.outln('}')
self.outln('') self.outln('')
def write_function_pointer(self, func): def write_linux_function_pointer(self, func):
# Writes out the function for resolving and updating the # Writes out the function for resolving and updating the
# global function pointer, plus the actual global function # global function pointer, plus the actual global function
# pointer initializer. # pointer initializer.
@ -642,6 +633,12 @@ class Generator(object):
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()
@ -816,10 +813,13 @@ class Generator(object):
self.outln('}') self.outln('}')
self.outln('') self.outln('')
for func in self.sorted_functions:
self.write_win32_function_pointer(func)
self.outln('#else /* !USING_DISPATCH_TABLE */') self.outln('#else /* !USING_DISPATCH_TABLE */')
for func in self.sorted_functions: for func in self.sorted_functions:
self.write_function_pointer(func) self.write_linux_function_pointer(func)
self.outln('#endif /* !USING_DISPATCH_TABLE */') self.outln('#endif /* !USING_DISPATCH_TABLE */')

Loading…
Cancel
Save