From 9bc909f5a7024ca3c2b5aa2fc26b19e8de9c7cf0 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 17 Dec 2013 14:32:18 -0800 Subject: [PATCH] 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. --- README.md | 10 ++++++++++ include/epoxy/gl.h | 2 +- src/dispatch_common.c | 2 -- src/dispatch_common.h | 12 +++++------- src/dispatch_wgl.c | 4 ++++ src/gen_dispatch.py | 36 ++++++++++++++++++------------------ 6 files changed, 38 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index b52faed..a0fab31 100644 --- a/README.md +++ b/README.md @@ -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 needs to be notified of the change using ```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. diff --git a/include/epoxy/gl.h b/include/epoxy/gl.h index c70a8d6..023810c 100644 --- a/include/epoxy/gl.h +++ b/include/epoxy/gl.h @@ -59,7 +59,7 @@ extern "C" { #endif #ifndef EPOXYAPIENTRY -#define EPOXYAPIENTRY __declspec(dllimport) +#define EPOXYAPIENTRY __declspec(dllimport) __stdcall #endif #ifndef GLAPI diff --git a/src/dispatch_common.c b/src/dispatch_common.c index 0ac5d23..8c04526 100644 --- a/src/dispatch_common.c +++ b/src/dispatch_common.c @@ -503,7 +503,5 @@ WRAPPER(epoxy_glEnd)(void) #endif } -#ifndef _WIN32 PUBLIC PFNGLBEGINPROC epoxy_glBegin = epoxy_glBegin_wrapped; PUBLIC PFNGLENDPROC epoxy_glEnd = epoxy_glEnd_wrapped; -#endif diff --git a/src/dispatch_common.h b/src/dispatch_common.h index 02599bd..1274b49 100644 --- a/src/dispatch_common.h +++ b/src/dispatch_common.h @@ -27,7 +27,7 @@ #define PLATFORM_HAS_EGL 0 #define PLATFORM_HAS_GLX 0 #define PLATFORM_HAS_WGL 1 -#define EPOXYAPIENTRY __declspec(dllexport) +#define EPOXYAPIENTRY __declspec(dllexport) __stdcall #elif defined(__APPLE__) #define PLATFORM_HAS_EGL 0 #define PLATFORM_HAS_GLX 1 @@ -65,16 +65,14 @@ */ #if defined(_WIN32) #define USING_DISPATCH_TABLE 1 -#define UNWRAPPED_PROTO(x) x -#define WRAPPER_VISIBILITY PUBLIC -#define WRAPPER(x) x #else #define USING_DISPATCH_TABLE 0 -#define UNWRAPPED_PROTO(x) (*x) -#define WRAPPER_VISIBILITY static -#define WRAPPER(x) x ## _wrapped #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_glx_dlsym(const char *name); void *epoxy_gl_dlsym(const char *name); diff --git a/src/dispatch_wgl.c b/src/dispatch_wgl.c index a0b7277..1156419 100644 --- a/src/dispatch_wgl.c +++ b/src/dispatch_wgl.c @@ -176,3 +176,7 @@ WRAPPER(epoxy_wglMakeAssociatedContextCurrentAMD)(HGLRC hglrc) 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; diff --git a/src/gen_dispatch.py b/src/gen_dispatch.py index 7a2d2df..9b53fc2 100755 --- a/src/gen_dispatch.py +++ b/src/gen_dispatch.py @@ -451,8 +451,9 @@ class Generator(object): def write_function_ptr_typedefs(self): for func in self.sorted_functions: - self.outln('typedef {0} (*{1})({2});'.format(func.ret_type, func.ptr_type, - func.args_decl)) + self.outln('typedef {0} (GLAPIENTRY *{1})({2});'.format(func.ret_type, + func.ptr_type, + func.args_decl)) def write_header_header(self, file): self.out_file = open(file, 'w') @@ -503,18 +504,8 @@ class Generator(object): self.outln('') 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: - 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.args_decl)) self.outln('') @@ -582,8 +573,8 @@ class Generator(object): dispatch_table_entry = 'dispatch_table->p{0}'.format(func.alias_name) - self.outln('{0}{1}'.format(func.public, func.ret_type)) - self.outln('epoxy_{0}({1})'.format(func.wrapped_name, func.args_decl)) + self.outln('static __stdcall {0}'.format(func.ret_type)) + self.outln('epoxy_{0}_dispatch_table_thunk({1})'.format(func.wrapped_name, func.args_decl)) self.outln('{') self.outln(' struct dispatch_table *dispatch_table = get_dispatch_table();') self.outln('') @@ -601,7 +592,7 @@ class Generator(object): 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('{') self.outln(' struct dispatch_table *dispatch_table = get_dispatch_table();') @@ -616,7 +607,7 @@ class Generator(object): 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 # global function pointer, plus the actual global function # pointer initializer. @@ -642,6 +633,12 @@ class Generator(object): 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() @@ -816,10 +813,13 @@ 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 */') for func in self.sorted_functions: - self.write_function_pointer(func) + self.write_linux_function_pointer(func) self.outln('#endif /* !USING_DISPATCH_TABLE */')