From 4364860d389bf273bcfce9c5286cc7a3642469c9 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jos=C3=A9=20Fonseca?= Date: Sun, 15 May 2011 12:56:59 +0100 Subject: [PATCH] Basic MacOSX tracing support (WIP). --- CMakeLists.txt | 41 +++++++++++++++--- README | 18 +++++++- cglapi.py | 63 +++++++++++++++++++++++++++ cgltrace.py | 115 +++++++++++++++++++++++++++++++++++++++++++++++++ glimports.hpp | 6 +++ glproc.py | 13 +++++- 6 files changed, 247 insertions(+), 9 deletions(-) create mode 100644 cglapi.py create mode 100644 cgltrace.py diff --git a/CMakeLists.txt b/CMakeLists.txt index f76444c..4950f0e 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -150,7 +150,7 @@ endif (PNG_FOUND) add_custom_command ( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/glproc.hpp COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/glproc.py > ${CMAKE_CURRENT_BINARY_DIR}/glproc.hpp - DEPENDS glproc.py dispatch.py wglapi.py glxapi.py glapi.py gltypes.py stdapi.py + DEPENDS glproc.py dispatch.py wglapi.py glxapi.py cglapi.py glapi.py gltypes.py stdapi.py ) if (WIN32) @@ -237,6 +237,37 @@ if (WIN32) endif (MINGW) install (TARGETS wgltrace RUNTIME DESTINATION wrappers) +elseif (APPLE) + include_directories (${X11_INCLUDE_DIR}) + + # libGL.dylib + add_custom_command ( + OUTPUT cgltrace.cpp + COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/cgltrace.py > ${CMAKE_CURRENT_BINARY_DIR}/cgltrace.cpp + DEPENDS cgltrace.py gltrace.py trace.py glxapi.py glapi.py glparams.py gltypes.py stdapi.py + ) + + add_library (cgltrace SHARED cgltrace.cpp trace_write.cpp os_posix.cpp ${CMAKE_CURRENT_BINARY_DIR}/glproc.hpp) + + set_target_properties (cgltrace PROPERTIES + # libGL.dylib + OUTPUT_NAME GL + # match the version + LINK_FLAGS "-compatibility_version 1 -current_version 1.0.0" + RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/wrappers + LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/wrappers + ) + + target_link_libraries (cgltrace dl) + + # Symbolic link from system's libGL.dylib + add_custom_command ( + OUTPUT ${PROJECT_BINARY_DIR}/wrappers/libGL.system.dylib + COMMAND ln -sf /System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib ${PROJECT_BINARY_DIR}/wrappers/libGL.system.dylib + DEPENDS cgltrace + ) + + install (TARGETS cgltrace LIBRARY DESTINATION lib) else () include_directories (${X11_INCLUDE_DIR}) @@ -256,11 +287,9 @@ else () # Prevent symbol relocations internal to our wrapper library to be # overwritten by the application. - if (NOT APPLE) - set_target_properties (glxtrace PROPERTIES - LINK_FLAGS "-Wl,-Bsymbolic -Wl,-Bsymbolic-functions" - ) - endif (NOT APPLE) + set_target_properties (glxtrace PROPERTIES + LINK_FLAGS "-Wl,-Bsymbolic -Wl,-Bsymbolic-functions" + ) target_link_libraries (glxtrace dl) diff --git a/README b/README index 11a47ea..0e9ade3 100644 --- a/README +++ b/README @@ -20,7 +20,7 @@ Requirements to build the GUI (optional): * QJSON (tested with version 0.7.1) -== Linux == +== Linux / Mac OS X == Build as: @@ -101,6 +101,22 @@ LD_LIBRARY_PATH: export TRACE_LIBGL=/path/to/real/libGL.so.1 /path/to/application +See the 'ld.so' man page for more information about LD_PRELOAD and +LD_LIBRARY_PATH environment flags. + + +== Mac OS X == + +Usage on Mac OS X is similar to Linux above, except for the tracing procedure, +which is instead: + + DYLD_LIBRARY_PATH=/path/to/apitrace/wrappers /path/to/application + +Note that although Mac OS X has an LD_PRELOAD equivalent, +DYLD_INSERT_LIBRARIES, it is mostly useless because it only works with +DYLD_FORCE_FLAT_NAMESPACE=1 which breaks most applications. See the 'dyld' man +page for more details about these environment flags. + == Windows == diff --git a/cglapi.py b/cglapi.py new file mode 100644 index 0000000..29ae783 --- /dev/null +++ b/cglapi.py @@ -0,0 +1,63 @@ +########################################################################## +# +# Copyright 2008-2009 VMware, Inc. +# 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. +# +##########################################################################/ + +"""CGL API description.""" + + +from stdapi import * +from glapi import glapi + + +CGLError = Enum("CGLError", [ + "kCGLNoError", # 0 + "kCGLBadAttribute", # 10000 + "kCGLBadProperty", # 10001 + "kCGLBadPixelFormat", # 10002 + "kCGLBadRendererInfo", # 10003 + "kCGLBadContext", # 10004 + "kCGLBadDrawable", # 10005 + "kCGLBadDisplay", # 10006 + "kCGLBadState", # 10007 + "kCGLBadValue", # 10008 + "kCGLBadMatch", # 10009 + "kCGLBadEnumeration", # 10010 + "kCGLBadOffScreen", # 10011 + "kCGLBadFullScreen", # 10012 + "kCGLBadWindow", # 10013 + "kCGLBadAddress", # 10014 + "kCGLBadCodeModule", # 10015 + "kCGLBadAlloc", # 10016 + "kCGLBadConnection", # 10017 +]) + +CGLContextObj = Opaque("CGLContextObj") + +cglapi = API("CGL") + +cglapi.add_functions([ + Function(CGLError, "CGLSetCurrentContext", [(CGLContextObj, "ctx")]), + Function(CGLContextObj, "CGLGetCurrentContext", []), +]) + diff --git a/cgltrace.py b/cgltrace.py new file mode 100644 index 0000000..33765f9 --- /dev/null +++ b/cgltrace.py @@ -0,0 +1,115 @@ +########################################################################## +# +# Copyright 2011 VMware, Inc. +# 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. +# +##########################################################################/ + + +"""Cgl tracing generator.""" + + +from stdapi import API +from glapi import glapi +from cglapi import cglapi +from gltrace import GlTracer + + +class CglTracer(GlTracer): + + def is_public_function(self, function): + # The symbols visible in libGL.dylib can vary, so expose them all + return True + + +if __name__ == '__main__': + print + print '#include ' + print '#include ' + print + print '#ifndef _GNU_SOURCE' + print '#define _GNU_SOURCE // for dladdr' + print '#endif' + print '#include ' + print + print '#include "trace_write.hpp"' + print + print '// To validate our prototypes' + print '#define GL_GLEXT_PROTOTYPES' + print + print '#include "glproc.hpp"' + print '#include "glsize.hpp"' + print + + api = API() + api.add_api(cglapi) + api.add_api(glapi) + tracer = CglTracer() + tracer.trace_api(api) + + print r''' + + +/* + * Handle to the true libGL.so + */ +static void *libgl_handle = NULL; + + +/* + * Lookup a libGL symbol + */ +static void * __dlsym(const char *symbol) +{ + void *result; + if (!libgl_handle) { + const char * libgl_filename; + + /* + * Unfortunately we can't just dlopen + * /System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib + * because DYLD_LIBRARY_PATH takes precedence, even for absolute paths. + */ + libgl_filename = "libGL.system.dylib"; + + libgl_handle = dlopen(libgl_filename, RTLD_LOCAL | RTLD_NOW | RTLD_FIRST); + if (!libgl_handle) { + OS::DebugMessage("error: couldn't load %s\n", libgl_filename); + return NULL; + } + } + + result = dlsym(libgl_handle, symbol); + + if (result == dlsym(RTLD_SELF, symbol)) { + OS::DebugMessage("error: symbol lookup recursion\n"); + OS::Abort(); + return NULL; + } + + return result; +} + + +PUBLIC +void * gll_noop = 0; + +''' diff --git a/glimports.hpp b/glimports.hpp index 5e89938..720e48a 100644 --- a/glimports.hpp +++ b/glimports.hpp @@ -93,4 +93,10 @@ typedef struct _WGLSWAP #endif /* !_WIN32 */ +#ifdef __APPLE__ + +#include + +#endif /* __APPLE__ */ + #endif /* _GLIMPORTS_HPP_ */ diff --git a/glproc.py b/glproc.py index 29031b7..067017b 100644 --- a/glproc.py +++ b/glproc.py @@ -34,6 +34,7 @@ from dispatch import Dispatcher from glapi import glapi from glxapi import glxapi from wglapi import wglapi +from cglapi import cglapi # See http://www.opengl.org/registry/ABI/ @@ -422,9 +423,13 @@ class GlDispatcher(Dispatcher): print ' static inline PROC __stdcall __wglGetProcAddress(const char * lpszProc);' print '# else' print '# define __getPublicProcAddress(name) __dlsym(name)' - print '# define __getPrivateProcAddress(name) __glXGetProcAddressARB((const GLubyte *)(name))' print ' static void * __dlsym(const char *symbol);' - print ' static inline __GLXextFuncPtr __glXGetProcAddressARB(const GLubyte * procName);' + 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 '# define __abort() Trace::Abort()' print '#endif /* !RETRACE */' @@ -453,6 +458,10 @@ if __name__ == '__main__': dispatcher.dispatch_api(glxapi) print '#endif /* !_WIN32 */' print + print '#ifdef __APPLE__' + dispatcher.dispatch_api(cglapi) + print '#endif /* __APPLE__ */' + print dispatcher.dispatch_api(glapi) print print '#endif /* !_GLPROC_HPP_ */' -- 2.45.2