From 1cfd89b2bb73c94340d61936a72bec346c3ca22d Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jos=C3=A9=20Fonseca?= Date: Thu, 1 Dec 2011 21:09:57 +0000 Subject: [PATCH] Cleanup glproc. Based on some of Alexandros Frantzis code/ideas. --- CMakeLists.txt | 16 ++-- cgltrace.py | 61 --------------- egltrace.py | 20 ----- glproc.py | 42 +++------- glproc_egl.cpp | 90 +++++++++++++++++++++ glproc_gl.cpp | 230 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ glws_egl_xlib.cpp | 10 ++- glws_glx.cpp | 3 +- glws_wgl.cpp | 6 +- glxtrace.py | 54 +------------ wgltrace.py | 25 ------ 11 files changed, 355 insertions(+), 202 deletions(-) create mode 100644 glproc_egl.cpp create mode 100644 glproc_gl.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 93ab8d1..7090a34 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,15 +40,14 @@ if (ENABLE_GUI) find_package (QJSON ${REQUIRE_GUI}) endif () +include_directories (${OPENGL_INCLUDE_DIR}) + if (WIN32) find_package (DirectX) elseif (APPLE) else () find_package (X11 REQUIRED) - set (X11_INCLUDE_DIR ${X11_INCLUDE_DIR} ${OPENGL_INCLUDE_DIR}) - set (X11_GL_LIB ${OPENGL_gl_LIBRARY}) - include_directories (${X11_INCLUDE_DIR}) if (ENABLE_EGL) @@ -377,6 +376,7 @@ if (WIN32) add_library (wgltrace MODULE specs/opengl32.def wgltrace.cpp glcaps.cpp + glproc_gl.cpp ${CMAKE_CURRENT_BINARY_DIR}/glproc.hpp ) set_target_properties (wgltrace PROPERTIES @@ -398,6 +398,7 @@ elseif (APPLE) add_library (cgltrace SHARED cgltrace.cpp glcaps.cpp + glproc_gl.cpp ${CMAKE_CURRENT_BINARY_DIR}/glproc.hpp ) @@ -425,6 +426,7 @@ else () ${CMAKE_CURRENT_BINARY_DIR}/glproc.hpp glxtrace.cpp glcaps.cpp + glproc_gl.cpp ) set_target_properties (glxtrace PROPERTIES @@ -455,6 +457,7 @@ if (EGL_FOUND) ${CMAKE_CURRENT_BINARY_DIR}/glproc.hpp egltrace.cpp glcaps.cpp + glproc_egl.cpp ) set_property ( @@ -516,6 +519,7 @@ set (retrace_sources add_executable (glretrace ${retrace_sources} ${glws_os} + glproc_gl.cpp ) set_property ( @@ -529,7 +533,6 @@ target_link_libraries (glretrace ) if (WIN32) - target_link_libraries (glretrace ${OPENGL_gl_LIBRARY}) elseif (APPLE) target_link_libraries (glretrace "-framework Cocoa" @@ -537,7 +540,7 @@ elseif (APPLE) ${OPENGL_gl_LIBRARY} # CGL* ) else () - target_link_libraries (glretrace ${OPENGL_gl_LIBRARY} ${X11_X11_LIB}) + target_link_libraries (glretrace ${X11_X11_LIB}) endif () install (TARGETS glretrace RUNTIME DESTINATION bin) @@ -546,6 +549,7 @@ if (EGL_FOUND AND NOT WIN32 AND NOT APPLE) add_executable (eglretrace ${retrace_sources} glws_egl_xlib.cpp + glproc_egl.cpp ) set_property ( @@ -560,8 +564,6 @@ if (EGL_FOUND AND NOT WIN32 AND NOT APPLE) ) target_link_libraries (eglretrace - ${EGL_LIBRARIES} - ${OPENGL_gl_LIBRARY} ${X11_X11_LIB} ) diff --git a/cgltrace.py b/cgltrace.py index b6a6fd0..1b31419 100644 --- a/cgltrace.py +++ b/cgltrace.py @@ -46,11 +46,6 @@ if __name__ == '__main__': print '#include ' print '#include ' print - print '#ifndef _GNU_SOURCE' - print '#define _GNU_SOURCE // for dladdr' - print '#endif' - print '#include ' - print print '#include "trace_writer.hpp"' print print '// To validate our prototypes' @@ -68,62 +63,6 @@ if __name__ == '__main__': print r''' - -/* - * Path to the true OpenGL framework - */ -static const char *libgl_filename = "/System/Library/Frameworks/OpenGL.framework/OpenGL"; - - -/* - * Handle to the true OpenGL framework. - */ -static void *libgl_handle = NULL; - - -/* - * Lookup a libGL symbol - */ -void * __libgl_sym(const char *symbol) -{ - void *result; - - if (!libgl_handle) { - /* - * Unfortunately we can't just dlopen the true dynamic library because - * DYLD_LIBRARY_PATH/DYLD_FRAMEWORK_PATH take precedence, even for - * absolute paths. So we create a temporary symlink, and dlopen that - * instead. - */ - - char temp_filename[] = "/tmp/tmp.XXXXXX"; - - if (mktemp(temp_filename) != NULL) { - if (symlink(libgl_filename, temp_filename) == 0) { - libgl_handle = dlopen(temp_filename, RTLD_LOCAL | RTLD_NOW | RTLD_FIRST); - remove(temp_filename); - } - } - - if (!libgl_handle) { - os::log("apitrace: error: couldn't load %s\n", libgl_filename); - os::abort(); - return NULL; - } - } - - result = dlsym(libgl_handle, symbol); - - if (result == dlsym(RTLD_SELF, symbol)) { - os::log("apitrace: error: symbol lookup recursion\n"); - os::abort(); - return NULL; - } - - return result; -} - - PUBLIC void * gll_noop = 0; diff --git a/egltrace.py b/egltrace.py index 1148924..de90799 100644 --- a/egltrace.py +++ b/egltrace.py @@ -110,23 +110,3 @@ if __name__ == '__main__': print ' return procPtr;' print '}' print - print r''' - -/* - * Lookup a EGL or GLES symbol - */ -void * __libegl_sym(const char *symbol) -{ - void *proc; - - /* Always try dlsym before eglGetProcAddress as spec 3.10 says - * implementation may choose to also export extension functions - * publicly. - */ - proc = dlsym(RTLD_NEXT, symbol); - if (!proc && symbol[0] == 'g' && symbol[1] == 'l') - proc = (void *) __eglGetProcAddress(symbol); - - return proc; -} -''' diff --git a/glproc.py b/glproc.py index 67079e4..26df9df 100644 --- a/glproc.py +++ b/glproc.py @@ -492,38 +492,16 @@ public_symbols.update([ class GlDispatcher(Dispatcher): def header(self): - print '#ifdef RETRACE' - print '# if defined(TRACE_EGL)' - print '# define __getPrivateProcAddress(name) eglGetProcAddress(name)' - print '# elif defined(_WIN32)' - print '# define __getPrivateProcAddress(name) wglGetProcAddress(name)' - print '# elif defined(__APPLE__)' - print '# include ' - print '# define __getPrivateProcAddress(name) dlsym(RTLD_DEFAULT, name)' - print '# else' - print '# define __getPrivateProcAddress(name) glXGetProcAddressARB((const GLubyte *)(name))' - print '# endif' - print '#else /* !RETRACE */' - print '# if defined(TRACE_EGL)' - print '# define __getPublicProcAddress(name) __libegl_sym(name)' - print '# define __getPrivateProcAddress(name) __libegl_sym(name)' - print ' void * __libegl_sym(const char *symbol);' - print '# elif defined(_WIN32)' - print ' PROC __getPublicProcAddress(LPCSTR lpProcName);' - print '# define __getPrivateProcAddress(name) __wglGetProcAddress(name)' - print ' static inline PROC __stdcall __wglGetProcAddress(const char * lpszProc);' - print '# else' - print '# define __getPublicProcAddress(name) __libgl_sym(name)' - print ' void * __libgl_sym(const char *symbol);' - print '# ifdef __APPLE__' - print '# define __getPrivateProcAddress(name) __getPublicProcAddress(name)' - print '# else' - print '# define __getPrivateProcAddress(name) __glXGetProcAddressARB((const GLubyte *)(name))' - print ' static inline __GLXextFuncPtr __glXGetProcAddressARB(const GLubyte * procName);' - print '# endif' - print '# endif' - print '#endif /* !RETRACE */' - print + print ''' +#if defined(_WIN32) +extern HINSTANCE __libGlHandle; +#else +extern void * __libGlHandle; +#endif + +void * __getPublicProcAddress(const char *procName); +void * __getPrivateProcAddress(const char *procName); +''' def is_public_function(self, function): return function.name in public_symbols or function.name.startswith('CGL') diff --git a/glproc_egl.cpp b/glproc_egl.cpp new file mode 100644 index 0000000..08556ec --- /dev/null +++ b/glproc_egl.cpp @@ -0,0 +1,90 @@ +/************************************************************************** + * + * Copyright 2011 Jose Fonseca + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + **************************************************************************/ + + +#include "glproc.hpp" + + +#if !defined(_WIN32) +#ifndef _GNU_SOURCE +#define _GNU_SOURCE // for dladdr +#endif +#include +#endif + + +/* + * Handle to the true OpenGL library. + */ +#if defined(_WIN32) +HINSTANCE __libGlHandle = NULL; +#else +void *__libGlHandle = RTLD_NEXT; +#endif + + + +#if defined(_WIN32) + +#error Unsupported + +#elif defined(__APPLE__) + +#error Unsupported + +#else + +/* + * Lookup a EGL or GLES symbol + */ +static inline void * +__libegl_sym(const char *symbol) +{ + void *proc; + + /* Always try dlsym before eglGetProcAddress as spec 3.10 says + * implementation may choose to also export extension functions + * publicly. + */ + proc = dlsym(__libGlHandle, symbol); + if (!proc && symbol[0] == 'g' && symbol[1] == 'l') + proc = (void *) __eglGetProcAddress(symbol); + + return proc; +} + +void * +__getPublicProcAddress(const char *procName) +{ + return __libegl_sym(procName); +} + +void * +__getPrivateProcAddress(const char *procName) +{ + return __libegl_sym(procName); +} + +#endif diff --git a/glproc_gl.cpp b/glproc_gl.cpp new file mode 100644 index 0000000..18314dc --- /dev/null +++ b/glproc_gl.cpp @@ -0,0 +1,230 @@ +/************************************************************************** + * + * Copyright 2011 Jose Fonseca + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + **************************************************************************/ + + +#include "glproc.hpp" + + +#if !defined(_WIN32) +#ifndef _GNU_SOURCE +#define _GNU_SOURCE // for dladdr +#endif +#include +#endif + + +/* + * Handle to the true OpenGL library. + */ +#if defined(_WIN32) +HINSTANCE __libGlHandle = NULL; +#else +void *__libGlHandle = NULL; +#endif + + + +#if defined(_WIN32) + +void * +__getPublicProcAddress(const char *procName) +{ + if (!__libGlHandle) { + char szDll[MAX_PATH] = {0}; + + if (!GetSystemDirectoryA(szDll, MAX_PATH)) { + return NULL; + } + + strcat(szDll, "\\\\opengl32.dll"); + + __libGlHandle = LoadLibraryA(szDll); + if (!__libGlHandle) { + os::log("apitrace: error: couldn't load %s\n", szDll); + return NULL; + } + } + + return (void *)GetProcAddress(__libGlHandle, procName); +} + + +void * +__getPrivateProcAddress(const char *procName) { + return (void *)__wglGetProcAddress(procName); +} + + +#elif defined(__APPLE__) + + +/* + * Path to the true OpenGL framework + */ +static const char *libgl_filename = "/System/Library/Frameworks/OpenGL.framework/OpenGL"; + + +/* + * Lookup a libGL symbol + */ +void * __libgl_sym(const char *symbol) +{ + void *result; + + if (!__libGlHandle) { + /* + * Unfortunately we can't just dlopen the true dynamic library because + * DYLD_LIBRARY_PATH/DYLD_FRAMEWORK_PATH take precedence, even for + * absolute paths. So we create a temporary symlink, and dlopen that + * instead. + */ + + char temp_filename[] = "/tmp/tmp.XXXXXX"; + + if (mktemp(temp_filename) != NULL) { + if (symlink(libgl_filename, temp_filename) == 0) { + __libGlHandle = dlopen(temp_filename, RTLD_LOCAL | RTLD_NOW | RTLD_FIRST); + remove(temp_filename); + } + } + + if (!__libGlHandle) { + os::log("apitrace: error: couldn't load %s\n", libgl_filename); + os::abort(); + return NULL; + } + } + + result = dlsym(__libGlHandle, symbol); + + if (result == dlsym(RTLD_SELF, symbol)) { + os::log("apitrace: error: symbol lookup recursion\n"); + os::abort(); + return NULL; + } + + return result; +} + + +void * +__getPublicProcAddress(const char *procName) +{ + return __libgl_sym(procName); +} + +void * +__getPrivateProcAddress(const char *procName) +{ + return __libgl_sym(procName); +} + + +#else + + +/* + * Invoke the true dlopen() function. + */ +static void * +__dlopen(const char *filename, int flag) +{ + typedef void * (*PFNDLOPEN)(const char *, int); + static PFNDLOPEN dlopen_ptr = NULL; + + if (!dlopen_ptr) { + dlopen_ptr = (PFNDLOPEN)dlsym(RTLD_NEXT, "dlopen"); + if (!dlopen_ptr) { + os::log("apitrace: error: dlsym(RTLD_NEXT, \"dlopen\") failed\n"); + return NULL; + } + } + + return dlopen_ptr(filename, flag); +} + + +/* + * Lookup a libGL symbol + */ +void * __libgl_sym(const char *symbol) +{ + void *result; + + if (!__libGlHandle) { + /* + * The app doesn't directly link against libGL.so, nor does it directly + * dlopen it. So we have to load it ourselves. + */ + + const char * libgl_filename = getenv("TRACE_LIBGL"); + + if (!libgl_filename) { + /* + * Try to use whatever libGL.so the library is linked against. + */ + + result = dlsym(RTLD_NEXT, symbol); + if (result) { + __libGlHandle = RTLD_NEXT; + return result; + } + + libgl_filename = "libGL.so.1"; + } + + /* + * It would have been preferable to use RTLD_LOCAL to ensure that the + * application can never access libGL.so symbols directly, but this + * won't work, given libGL.so often loads a driver specific SO and + * exposes symbols to it. + */ + + __libGlHandle = __dlopen(libgl_filename, RTLD_GLOBAL | RTLD_LAZY); + if (!__libGlHandle) { + os::log("apitrace: error: couldn't find libGL.so\n"); + return NULL; + } + } + + return dlsym(__libGlHandle, symbol); +} + + +void * +__getPublicProcAddress(const char *procName) +{ + return __libgl_sym(procName); +} + +void * +__getPrivateProcAddress(const char *procName) +{ + return (void *)__glXGetProcAddressARB((const GLubyte *)procName); +} + + +#endif + diff --git a/glws_egl_xlib.cpp b/glws_egl_xlib.cpp index 958e951..eb284ab 100644 --- a/glws_egl_xlib.cpp +++ b/glws_egl_xlib.cpp @@ -29,9 +29,10 @@ #include -#include "glws.hpp" +#include #include "glproc.hpp" +#include "glws.hpp" namespace glws { @@ -229,6 +230,13 @@ init(void) { screen = DefaultScreen(display); + __libGlHandle = dlopen("libEGL.so", RTLD_GLOBAL | RTLD_LAZY); + if (!__libGlHandle) { + std::cerr << "error: unable to open libEGL.so\n"; + XCloseDisplay(display); + exit(1); + } + eglDisplay = eglGetDisplay(display); if (eglDisplay == EGL_NO_DISPLAY) { std::cerr << "error: unable to get EGL display\n"; diff --git a/glws_glx.cpp b/glws_glx.cpp index 8a0b403..db24b7f 100644 --- a/glws_glx.cpp +++ b/glws_glx.cpp @@ -28,9 +28,8 @@ #include -#include "glws.hpp" - #include "glproc.hpp" +#include "glws.hpp" namespace glws { diff --git a/glws_wgl.cpp b/glws_wgl.cpp index 2487eb0..63ce5fe 100644 --- a/glws_wgl.cpp +++ b/glws_wgl.cpp @@ -23,7 +23,7 @@ * **************************************************************************/ -#include "glimports.hpp" +#include "glproc.hpp" #include "glws.hpp" @@ -188,6 +188,10 @@ public: void init(void) { + /* + * OpenGL library must be loaded by the time we call GDI. + */ + __libGlHandle = LoadLibraryA("OPENGL32"); } void diff --git a/glxtrace.py b/glxtrace.py index be577cb..c9e9518 100644 --- a/glxtrace.py +++ b/glxtrace.py @@ -95,12 +95,6 @@ if __name__ == '__main__': /* - * Handle to the true libGL.so - */ -static void *libgl_handle = NULL; - - -/* * Invoke the true dlopen() function. */ static void *__dlopen(const char *filename, int flag) @@ -145,7 +139,7 @@ void * dlopen(const char *filename, int flag) strcmp(filename, "libGL.so.1") == 0) { // Use the true libGL.so handle instead of RTLD_NEXT from now on - libgl_handle = handle; + __libGlHandle = handle; // Get the file path for our shared object, and use it instead static int dummy = 0xdeedbeef; @@ -163,51 +157,5 @@ void * dlopen(const char *filename, int flag) } -/* - * Lookup a libGL symbol - */ -void * __libgl_sym(const char *symbol) -{ - void *result; - - if (!libgl_handle) { - /* - * The app doesn't directly link against libGL.so, nor does it directly - * dlopen it. So we have to load it ourselves. - */ - - const char * libgl_filename = getenv("TRACE_LIBGL"); - - if (!libgl_filename) { - /* - * Try to use whatever libGL.so the library is linked against. - */ - - result = dlsym(RTLD_NEXT, symbol); - if (result) { - libgl_handle = RTLD_NEXT; - return result; - } - - libgl_filename = "libGL.so.1"; - } - - /* - * It would have been preferable to use RTLD_LOCAL to ensure that the - * application can never access libGL.so symbols directly, but this - * won't work, given libGL.so often loads a driver specific SO and - * exposes symbols to it. - */ - - libgl_handle = __dlopen(libgl_filename, RTLD_GLOBAL | RTLD_LAZY); - if (!libgl_handle) { - os::log("apitrace: error: couldn't find libGL.so\n"); - return NULL; - } - } - - return dlsym(libgl_handle, symbol); -} - ''' diff --git a/wgltrace.py b/wgltrace.py index cf2cc97..d5a5248 100644 --- a/wgltrace.py +++ b/wgltrace.py @@ -69,31 +69,6 @@ if __name__ == '__main__': print '#include "trace_writer.hpp"' print '#include "os.hpp"' print - print ''' -static HINSTANCE g_hDll = NULL; - -PROC -__getPublicProcAddress(LPCSTR lpProcName) -{ - if (!g_hDll) { - char szDll[MAX_PATH] = {0}; - - if (!GetSystemDirectoryA(szDll, MAX_PATH)) { - return NULL; - } - - strcat(szDll, "\\\\opengl32.dll"); - - g_hDll = LoadLibraryA(szDll); - if (!g_hDll) { - return NULL; - } - } - - return GetProcAddress(g_hDll, lpProcName); -} - - ''' print '// To validate our prototypes' print '#define GL_GLEXT_PROTOTYPES' print '#define WGL_GLXEXT_PROTOTYPES' -- 2.7.4