From: José Fonseca Date: Fri, 27 May 2011 19:14:31 +0000 (+0100) Subject: Trace the whole OpenGL framework on Mac OS X. X-Git-Url: https://git.cworth.org/git?a=commitdiff_plain;h=3bcb33ca2c47bdb70d91d9988664d744f4146855;p=apitrace Trace the whole OpenGL framework on Mac OS X. --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 2e6f1a3..9696746 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -259,32 +259,26 @@ if (WIN32) elseif (APPLE) include_directories (${X11_INCLUDE_DIR}) - # libGL.dylib + # OpenGL framework 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 + DEPENDS cgltrace.py gltrace.py trace.py cglapi.py glapi.py glparams.py gltypes.py stdapi.py ) add_library (cgltrace SHARED cgltrace.cpp trace_writer.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" + # For + PREFIX "" OUTPUT_NAME "OpenGL" SUFFIX "" + # Specificy the version and reexport GLU symbols + LINK_FLAGS "-compatibility_version 1 -current_version 1.0.0 -Wl,-reexport_library,/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGLU.dylib" 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 ( - TARGET cgltrace - COMMAND ln -sf /System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib ${PROJECT_BINARY_DIR}/wrappers/libGL.system.dylib - ) - install (TARGETS cgltrace LIBRARY DESTINATION lib) else () include_directories (${X11_INCLUDE_DIR}) diff --git a/cglapi.py b/cglapi.py index 29ae783..81b7730 100644 --- a/cglapi.py +++ b/cglapi.py @@ -27,29 +27,148 @@ from stdapi import * +from glapi import * from glapi import glapi +IOSurfaceRef = Opaque("IOSurfaceRef") +CGLContextObj = Opaque("CGLContextObj") +CGLPixelFormatObj = Opaque("CGLPixelFormatObj") +CGLRendererInfoObj = Opaque("CGLRendererInfoObj") +CGLPBufferObj = Opaque("CGLPBufferObj") +CGLShareGroup = Opaque("CGLShareGroup") +CGLShareGroupObj = Opaque("CGLShareGroupObj") +CGSConnectionID = Alias("CGSConnectionID", Int) +CGSWindowID = Alias("CGSWindowID", Int) +CGSSurfaceID = Alias("CGSSurfaceID", Int) + +CGLPixelFormatAttribute = Enum("CGLPixelFormatAttribute", [ + "kCGLPFAAllRenderers", + "kCGLPFADoubleBuffer", + "kCGLPFAStereo", + "kCGLPFAAuxBuffers", + "kCGLPFAColorSize", + "kCGLPFAAlphaSize", + "kCGLPFADepthSize", + "kCGLPFAStencilSize", + "kCGLPFAAccumSize", + "kCGLPFAMinimumPolicy", + "kCGLPFAMaximumPolicy", + "kCGLPFAOffScreen", + "kCGLPFAFullScreen", + "kCGLPFASampleBuffers", + "kCGLPFASamples", + "kCGLPFAAuxDepthStencil", + "kCGLPFAColorFloat", + "kCGLPFAMultisample", + "kCGLPFASupersample", + "kCGLPFASampleAlpha", + "kCGLPFARendererID", + "kCGLPFASingleRenderer", + "kCGLPFANoRecovery", + "kCGLPFAAccelerated", + "kCGLPFAClosestPolicy", + "kCGLPFABackingStore", + "kCGLPFAWindow", + "kCGLPFACompliant", + "kCGLPFADisplayMask", + "kCGLPFAPBuffer", + "kCGLPFARemotePBuffer", + "kCGLPFAAllowOfflineRenderers", + "kCGLPFAAcceleratedCompute", + "kCGLPFAVirtualScreenCount", + "kCGLPFARobust", + "kCGLPFAMPSafe", + "kCGLPFAMultiScreen", +]) + +CGLRendererProperty = Enum("CGLRendererProperty", [ + "kCGLRPOffScreen", + "kCGLRPFullScreen", + "kCGLRPRendererID", + "kCGLRPAccelerated", + "kCGLRPRobust", + "kCGLRPBackingStore", + "kCGLRPMPSafe", + "kCGLRPWindow", + "kCGLRPMultiScreen", + "kCGLRPCompliant", + "kCGLRPDisplayMask", + "kCGLRPBufferModes", + "kCGLRPColorModes", + "kCGLRPAccumModes", + "kCGLRPDepthModes", + "kCGLRPStencilModes", + "kCGLRPMaxAuxBuffers", + "kCGLRPMaxSampleBuffers", + "kCGLRPMaxSamples", + "kCGLRPSampleModes", + "kCGLRPSampleAlpha", + "kCGLRPVideoMemory", + "kCGLRPTextureMemory", + "kCGLRPGPUVertProcCapable", + "kCGLRPGPUFragProcCapable", + "kCGLRPRendererCount", + "kCGLRPOnline", + "kCGLRPAcceleratedCompute", +]) + +CGLContextEnable = Enum("CGLContextEnable", [ + "kCGLCESwapRectangle", + "kCGLCESwapLimit", + "kCGLCERasterization", + "kCGLCEStateValidation", + "kCGLCESurfaceBackingSize", + "kCGLCEDisplayListOptimization", + "kCGLCEMPEngine", +]) + +CGLContextParameter = Enum("CGLContextParameter", [ + "kCGLCPSwapRectangle", + "kCGLCPSwapInterval", + "kCGLCPDispatchTableSize", + "kCGLCPClientStorage", + "kCGLCPSurfaceTexture", + "kCGLCPSurfaceOrder", + "kCGLCPSurfaceOpacity", + "kCGLCPSurfaceBackingSize", + "kCGLCPSurfaceSurfaceVolatile", + "kCGLCPReclaimResources", + "kCGLCPCurrentRendererID", + "kCGLCPGPUVertexProcessing", + "kCGLCPGPUFragmentProcessing", + "kCGLCPHasDrawable", + "kCGLCPMPSwapsInFlight", +]) + +CGLGlobalOption = Enum("CGLGlobalOption", [ + "kCGLGOFormatCacheSize", + "kCGLGOClearFormatCache", + "kCGLGORetainRenderers", + "kCGLGOResetLibrary", + "kCGLGOUseErrorHandler", + "kCGLGOUseBuildCache", +]) 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 + "kCGLNoError", + "kCGLBadAttribute", + "kCGLBadProperty", + "kCGLBadPixelFormat", + "kCGLBadRendererInfo", + "kCGLBadContext", + "kCGLBadDrawable", + "kCGLBadDisplay", + "kCGLBadState", + "kCGLBadValue", + "kCGLBadMatch", + "kCGLBadEnumeration", + "kCGLBadOffScreen", + "kCGLBadFullScreen", + "kCGLBadWindow", + "kCGLBadAddress", + "kCGLBadCodeModule", + "kCGLBadAlloc", + "kCGLBadConnection", ]) CGLContextObj = Opaque("CGLContextObj") @@ -57,7 +176,79 @@ CGLContextObj = Opaque("CGLContextObj") cglapi = API("CGL") cglapi.add_functions([ + # CGLCurrent.h, libGL.dylib Function(CGLError, "CGLSetCurrentContext", [(CGLContextObj, "ctx")]), Function(CGLContextObj, "CGLGetCurrentContext", []), + + # OpenGL.h, OpenGL framework + Function(CGLError, "CGLChoosePixelFormat", [(Const(OpaquePointer(CGLPixelFormatAttribute)), "attribs"), (OpaquePointer(CGLPixelFormatObj), "pix"), (OpaquePointer(GLint), "npix")]), + Function(CGLError, "CGLDestroyPixelFormat", [(CGLPixelFormatObj, "pix")]), + Function(CGLError, "CGLDescribePixelFormat", [(CGLPixelFormatObj, "pix"), (GLint, "pix_num"), (CGLPixelFormatAttribute, "attrib"), (OpaquePointer(GLint), "value")]), + Function(Void, "CGLReleasePixelFormat", [(CGLPixelFormatObj, "pix")]), + Function(CGLPixelFormatObj, "CGLRetainPixelFormat", [(CGLPixelFormatObj, "pix")]), + Function(GLuint, "CGLGetPixelFormatRetainCount", [(CGLPixelFormatObj, "pix")]), + Function(CGLError, "CGLQueryRendererInfo", [(GLuint, "display_mask"), (OpaquePointer(CGLRendererInfoObj), "rend"), (OpaquePointer(GLint), "nrend")]), + Function(CGLError, "CGLDestroyRendererInfo", [(CGLRendererInfoObj, "rend")]), + Function(CGLError, "CGLDescribeRenderer", [(CGLRendererInfoObj, "rend"), (GLint, "rend_num"), (CGLRendererProperty, "prop"), (OpaquePointer(GLint), "value")]), + Function(CGLError, "CGLCreateContext", [(CGLPixelFormatObj, "pix"), (CGLContextObj, "share"), (OpaquePointer(CGLContextObj), "ctx")]), + Function(CGLError, "CGLDestroyContext", [(CGLContextObj, "ctx")]), + Function(CGLError, "CGLCopyContext", [(CGLContextObj, "src"), (CGLContextObj, "dst"), (GLbitfield, "mask")]), + Function(CGLContextObj, "CGLRetainContext", [(CGLContextObj, "ctx")]), + Function(Void, "CGLReleaseContext", [(CGLContextObj, "ctx")]), + Function(GLuint, "CGLGetContextRetainCount", [(CGLContextObj, "ctx")]), + Function(CGLPixelFormatObj, "CGLGetPixelFormat", [(CGLContextObj, "ctx")]), + Function(CGLError, "CGLCreatePBuffer", [(GLsizei, "width"), (GLsizei, "height"), (GLenum, "target"), (GLenum, "internalFormat"), (GLint, "max_level"), (OpaquePointer(CGLPBufferObj), "pbuffer")]), + Function(CGLError, "CGLDestroyPBuffer", [(CGLPBufferObj, "pbuffer")]), + Function(CGLError, "CGLDescribePBuffer", [(CGLPBufferObj, "obj"), (OpaquePointer(GLsizei), "width"), (OpaquePointer(GLsizei), "height"), (OpaquePointer(GLenum), "target"), (OpaquePointer(GLenum), "internalFormat"), (OpaquePointer(GLint), "mipmap")]), + Function(CGLError, "CGLTexImagePBuffer", [(CGLContextObj, "ctx"), (CGLPBufferObj, "pbuffer"), (GLenum, "source")]), + Function(CGLPBufferObj, "CGLRetainPBuffer", [(CGLPBufferObj, "pbuffer")]), + Function(Void, "CGLReleasePBuffer", [(CGLPBufferObj, "pbuffer")]), + Function(GLuint, "CGLGetPBufferRetainCount", [(CGLPBufferObj, "pbuffer")]), + Function(CGLError, "CGLSetOffScreen", [(CGLContextObj, "ctx"), (GLsizei, "width"), (GLsizei, "height"), (GLint, "rowbytes"), (OpaquePointer(Void), "baseaddr")]), + Function(CGLError, "CGLGetOffScreen", [(CGLContextObj, "ctx"), (OpaquePointer(GLsizei), "width"), (OpaquePointer(GLsizei), "height"), (OpaquePointer(GLint), "rowbytes"), (OpaquePointer(OpaquePointer(Void)), "baseaddr")]), + Function(CGLError, "CGLSetFullScreen", [(CGLContextObj, "ctx")]), + Function(CGLError, "CGLSetFullScreenOnDisplay", [(CGLContextObj, "ctx"), (GLuint, "display_mask")]), + Function(CGLError, "CGLSetPBuffer", [(CGLContextObj, "ctx"), (CGLPBufferObj, "pbuffer"), (GLenum, "face"), (GLint, "level"), (GLint, "screen")]), + Function(CGLError, "CGLGetPBuffer", [(CGLContextObj, "ctx"), (OpaquePointer(CGLPBufferObj), "pbuffer"), (OpaquePointer(GLenum), "face"), (OpaquePointer(GLint), "level"), (OpaquePointer(GLint), "screen")]), + Function(CGLError, "CGLClearDrawable", [(CGLContextObj, "ctx")]), + Function(CGLError, "CGLFlushDrawable", [(CGLContextObj, "ctx")]), + Function(CGLError, "CGLEnable", [(CGLContextObj, "ctx"), (CGLContextEnable, "pname")]), + Function(CGLError, "CGLDisable", [(CGLContextObj, "ctx"), (CGLContextEnable, "pname")]), + Function(CGLError, "CGLIsEnabled", [(CGLContextObj, "ctx"), (CGLContextEnable, "pname"), (OpaquePointer(GLint), "enable")]), + Function(CGLError, "CGLSetParameter", [(CGLContextObj, "ctx"), (CGLContextParameter, "pname"), (Const(OpaquePointer(GLint)), "params")]), + Function(CGLError, "CGLGetParameter", [(CGLContextObj, "ctx"), (CGLContextParameter, "pname"), (OpaquePointer(GLint), "params")]), + Function(CGLError, "CGLSetVirtualScreen", [(CGLContextObj, "ctx"), (GLint, "screen")]), + Function(CGLError, "CGLGetVirtualScreen", [(CGLContextObj, "ctx"), (OpaquePointer(GLint), "screen")]), + Function(CGLError, "CGLSetGlobalOption", [(CGLGlobalOption, "pname"), (Const(OpaquePointer(GLint)), "params")]), + Function(CGLError, "CGLGetGlobalOption", [(CGLGlobalOption, "pname"), (OpaquePointer(GLint), "params")]), + Function(CGLError, "CGLSetOption", [(CGLGlobalOption, "pname"), (GLint, "param")]), + Function(CGLError, "CGLGetOption", [(CGLGlobalOption, "pname"), (OpaquePointer(GLint), "param")]), + Function(CGLError, "CGLLockContext", [(CGLContextObj, "ctx")]), + Function(CGLError, "CGLUnlockContext", [(CGLContextObj, "ctx")]), + Function(Void, "CGLGetVersion", [(OpaquePointer(GLint), "majorvers"), (OpaquePointer(GLint), "minorvers")]), + Function(Const(CString), "CGLErrorString", [(CGLError, "error")]), + + # CGLIOSurface.h, OpenGL framework + Function(CGLError, "CGLTexImageIOSurface2D", [(CGLContextObj, "ctx"), (GLenum, "target"), (GLenum, "internal_format"), (GLsizei, "width"), (GLsizei, "height"), (GLenum, "format"), (GLenum, "type"), (IOSurfaceRef, "ioSurface"), (GLuint, "plane")]), + + # CGLDevice.h, OpenGL framework + Function(CGLShareGroupObj, "CGLGetShareGroup", [(CGLContextObj, "ctx")]), + + # Undocumented, OpenGL framework + Function(CGLError, "CGLSetSurface", [(CGLContextObj, "ctx"), (CGSConnectionID, "cid"), (CGSWindowID, "wid"), (CGSSurfaceID, "sid")]), + Function(CGLError, "CGLGetSurface", [(CGLContextObj, "ctx"), (OpaquePointer(CGSConnectionID), "cid"), (OpaquePointer(CGSWindowID), "wid"), (OpaquePointer(CGSSurfaceID), "sid")]), + Function(CGLError, "CGLUpdateContext", [(CGLContextObj, "ctx")]), + # XXX: Confirm CGLOpenCLMuxLockDown + Function(CGLError, "CGLOpenCLMuxLockDown", []), + # FIXME: CGLAreContextsShared + # FIXME: CGLBackDispatch + # FIXME: CGLFrontDispatch + # FIXME: CGLGetNextContext + # FIXME: CGLRestoreDispatch + # FIXME: CGLRestoreDispatchFunction + # FIXME: CGLSelectDispatch + # FIXME: CGLSelectDispatchBounded + # FIXME: CGLSelectDispatchFunction + # FIXME: CGLSetPBufferVolatileState ]) diff --git a/cgltrace.py b/cgltrace.py index f850435..86e8a29 100644 --- a/cgltrace.py +++ b/cgltrace.py @@ -44,6 +44,7 @@ if __name__ == '__main__': print print '#include ' print '#include ' + print '#include ' print print '#ifndef _GNU_SOURCE' print '#define _GNU_SOURCE // for dladdr' @@ -69,7 +70,13 @@ if __name__ == '__main__': /* - * Handle to the true libGL.so + * 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; @@ -80,19 +87,27 @@ static void *libgl_handle = NULL; static void * __dlsym(const char *symbol) { void *result; - if (!libgl_handle) { - const char * libgl_filename; + if (!libgl_handle) { /* - * Unfortunately we can't just dlopen - * /System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib - * because DYLD_LIBRARY_PATH takes precedence, even for absolute paths. + * 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. */ - libgl_filename = "libGL.system.dylib"; - libgl_handle = dlopen(libgl_filename, RTLD_LOCAL | RTLD_NOW | RTLD_FIRST); + 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::DebugMessage("error: couldn't load %s\n", libgl_filename); + OS::Abort(); return NULL; } } diff --git a/glimports.hpp b/glimports.hpp index 5cb276d..ad248e1 100644 --- a/glimports.hpp +++ b/glimports.hpp @@ -91,6 +91,20 @@ typedef struct _WGLSWAP #elif defined(__APPLE__) #include +#include +#include + +extern "C" { + +typedef int CGSConnectionID; +typedef int CGSWindowID; +typedef int CGSSurfaceID; + +CGLError CGLSetSurface(CGLContextObj ctx, CGSConnectionID cid, CGSWindowID wid, CGSSurfaceID sid); +CGLError CGLGetSurface(CGLContextObj ctx, CGSConnectionID* cid, CGSWindowID* wid, CGSSurfaceID* sid); +CGLError CGLUpdateContext(CGLContextObj ctx); + +} #else diff --git a/glproc.py b/glproc.py index b036b35..64ea360 100644 --- a/glproc.py +++ b/glproc.py @@ -439,7 +439,7 @@ class GlDispatcher(Dispatcher): print def is_public_function(self, function): - return function.name in public_symbols + return function.name in public_symbols or function.name.startswith('CGL') if __name__ == '__main__': diff --git a/glretrace_cgl.cpp b/glretrace_cgl.cpp index 2d6d882..c42dd81 100644 --- a/glretrace_cgl.cpp +++ b/glretrace_cgl.cpp @@ -47,6 +47,9 @@ getDrawable(unsigned long drawable_id) { return NULL; } + /* XXX: Support multiple drawables. */ + drawable_id = 1; + DrawableMap::const_iterator it; it = drawable_map.find(drawable_id); if (it == drawable_map.end()) { @@ -77,23 +80,10 @@ getContext(unsigned long long ctx) { return it->second; } + static void retrace_CGLSetCurrentContext(Trace::Call &call) { unsigned long long ctx = call.arg(0).toUIntPtr(); - /* - * XXX: Frame termination is mostly a guess, because we don't trace enough - * of the CGL API to know that. - */ - if (drawable && context) { - if (double_buffer) { - drawable->swapBuffers(); - } else { - glFlush(); - } - - frame_complete(call.no); - } - glws::Drawable *new_drawable = getDrawable(ctx); glws::Context *new_context = getContext(ctx); @@ -109,6 +99,19 @@ static void retrace_CGLSetCurrentContext(Trace::Call &call) { } +static void retrace_CGLFlushDrawable(Trace::Call &call) { + if (drawable && context) { + if (double_buffer) { + drawable->swapBuffers(); + } else { + glFlush(); + } + + frame_complete(call.no); + } +} + + void glretrace::retrace_call_cgl(Trace::Call &call) { const char *name = call.name().c_str(); @@ -117,10 +120,11 @@ void glretrace::retrace_call_cgl(Trace::Call &call) { return; } - if (strcmp(name, "CGLGetCurrentContext") == 0) { + if (strcmp(name, "CGLFlushDrawable") == 0) { + retrace_CGLFlushDrawable(call); return; } - retrace::retrace_unknown(call); + return; } diff --git a/glstate.cpp b/glstate.cpp index 71aad7d..59d28c9 100644 --- a/glstate.cpp +++ b/glstate.cpp @@ -43,11 +43,6 @@ extern "C" { #endif -typedef int CGSConnectionID; -typedef int CGSWindowID; -typedef int CGSSurfaceID; - -CGLError CGLGetSurface(CGLContextObj, CGSConnectionID*, CGSWindowID*, CGSSurfaceID*); OSStatus CGSGetSurfaceBounds(CGSConnectionID, CGWindowID, CGSSurfaceID, CGRect *); #ifdef __cplusplus diff --git a/gltrace.py b/gltrace.py index 8114800..d4adf92 100644 --- a/gltrace.py +++ b/gltrace.py @@ -498,7 +498,9 @@ class GlTracer(Tracer): # Several GL state functions take GLenum symbolic names as # integer/floats; so dump the symbolic name whenever possible - if arg.type in (glapi.GLint, glapi.GLfloat) and arg.name == 'param': + if function.name.startswith('gl') \ + and arg.type in (glapi.GLint, glapi.GLfloat) \ + and arg.name == 'param': assert arg.index > 0 assert function.args[arg.index - 1].name == 'pname' assert function.args[arg.index - 1].type == glapi.GLenum