From: José Fonseca Date: Sat, 14 Apr 2012 14:55:40 +0000 (+0100) Subject: Move tracers to wrappers subdirectory. X-Git-Url: https://git.cworth.org/git?p=apitrace;a=commitdiff_plain;h=452d3256a3ba7f249222ef857d69c8caaaa753f3 Move tracers to wrappers subdirectory. --- diff --git a/.gitignore b/.gitignore index e16a1f7..25f71f6 100644 --- a/.gitignore +++ b/.gitignore @@ -30,20 +30,12 @@ CMakeFiles Makefile apitrace build -cgltrace.cpp -d3d10trace.cpp -d3d8trace.cpp -d3d9trace.cpp -ddrawtrace.cpp dxsdk -egltrace.cpp eglretrace glproc.hpp glretrace glretrace_gl.cpp glstate_params.cpp -glxtrace.cpp install_manifest.txt qapitrace traces -wgltrace.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt old mode 100755 new mode 100644 index 7c42200..855d73f --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -298,278 +298,8 @@ endif () ############################################################################## # API tracers -if (WIN32) - if (MINGW) - # Silence warnings about @nn suffix mismatch - set (CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,--enable-stdcall-fixup") - endif () - - # ddraw.dll - if (DirectX_D3D_INCLUDE_DIR) - include_directories (SYSTEM ${DirectX_D3D_INCLUDE_DIR}) - add_custom_command ( - OUTPUT ddrawtrace.cpp - COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/ddrawtrace.py > ${CMAKE_CURRENT_BINARY_DIR}/ddrawtrace.cpp - DEPENDS ddrawtrace.py trace.py specs/d3d.py specs/d3dtypes.py specs/d3dcaps.py specs/ddraw.py specs/winapi.py specs/stdapi.py - ) - add_library (ddraw MODULE specs/ddraw.def ddrawtrace.cpp) - target_link_libraries (ddraw - common - ${ZLIB_LIBRARIES} - ${SNAPPY_LIBRARIES} - ) - set_target_properties (ddraw - PROPERTIES PREFIX "" - RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/wrappers - LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/wrappers - ) - install (TARGETS ddraw LIBRARY DESTINATION ${WRAPPER_INSTALL_DIR}) - endif () - - # d3d8.dll - if (DirectX_D3D8_INCLUDE_DIR AND DirectX_D3DX9_INCLUDE_DIR) - include_directories (SYSTEM ${DirectX_D3D8_INCLUDE_DIR} ${DirectX_D3DX9_INCLUDE_DIR}) - add_custom_command ( - OUTPUT d3d8trace.cpp - COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/d3d8trace.py > ${CMAKE_CURRENT_BINARY_DIR}/d3d8trace.cpp - DEPENDS d3d8trace.py trace.py specs/d3d8.py specs/d3d8types.py specs/d3d8caps.py specs/winapi.py specs/stdapi.py - ) - add_library (d3d8 MODULE specs/d3d8.def d3d8trace.cpp d3dshader.cpp) - target_link_libraries (d3d8 - common - ${ZLIB_LIBRARIES} - ${SNAPPY_LIBRARIES} - ) - set_target_properties (d3d8 - PROPERTIES PREFIX "" - RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/wrappers - LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/wrappers - ) - install (TARGETS d3d8 LIBRARY DESTINATION ${WRAPPER_INSTALL_DIR}) - endif () - - # d3d9.dll - if (DirectX_D3DX9_INCLUDE_DIR) - include_directories (SYSTEM ${DirectX_D3DX9_INCLUDE_DIR}) - add_custom_command ( - OUTPUT d3d9trace.cpp - COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/d3d9trace.py > ${CMAKE_CURRENT_BINARY_DIR}/d3d9trace.cpp - DEPENDS d3d9trace.py trace.py specs/d3d9.py specs/d3d9types.py specs/d3d9caps.py specs/winapi.py specs/stdapi.py - ) - add_library (d3d9 MODULE specs/d3d9.def d3d9trace.cpp d3dshader.cpp) - target_link_libraries (d3d9 - common - ${ZLIB_LIBRARIES} - ${SNAPPY_LIBRARIES} - ) - set_target_properties (d3d9 - PROPERTIES PREFIX "" - RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/wrappers - LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/wrappers - ) - install (TARGETS d3d9 LIBRARY DESTINATION ${WRAPPER_INSTALL_DIR}) - endif () - - # d3d10.dll - if (DirectX_D3DX10_INCLUDE_DIR) - include_directories (SYSTEM ${DirectX_D3DX10_INCLUDE_DIR}) - add_custom_command ( - OUTPUT d3d10trace.cpp - COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/d3d10trace.py > ${CMAKE_CURRENT_BINARY_DIR}/d3d10trace.cpp - DEPENDS d3d10trace.py trace.py specs/d3d10misc.py specs/d3d10.py specs/d3d10sdklayers.py specs/d3dcommon.py specs/dxgi.py specs/dxgitype.py specs/dxgiformat.py specs/winapi.py specs/stdapi.py - ) - add_library (d3d10 MODULE specs/d3d10.def d3d10trace.cpp) - target_link_libraries (d3d10 - common - ${ZLIB_LIBRARIES} - ${SNAPPY_LIBRARIES} - ) - set_target_properties (d3d10 - PROPERTIES PREFIX "" - RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/wrappers - LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/wrappers - ) - install (TARGETS d3d10 LIBRARY DESTINATION ${WRAPPER_INSTALL_DIR}) - endif () - - # d3d10_1.dll - if (DirectX_D3DX10_INCLUDE_DIR AND DirectX_D3D10_1_INCLUDE_DIR) - include_directories (SYSTEM ${DirectX_D3D10_1_INCLUDE_DIR}) - add_custom_command ( - OUTPUT d3d10_1trace.cpp - COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/d3d10_1trace.py > ${CMAKE_CURRENT_BINARY_DIR}/d3d10_1trace.cpp - DEPENDS d3d10_1trace.py trace.py specs/d3d10_1.py specs/d3d10.py specs/d3d10sdklayers.py specs/d3dcommon.py specs/dxgi.py specs/dxgitype.py specs/dxgiformat.py specs/winapi.py specs/stdapi.py - ) - add_library (d3d10_1 MODULE specs/d3d10_1.def d3d10_1trace.cpp) - target_link_libraries (d3d10_1 - common - ${ZLIB_LIBRARIES} - ${SNAPPY_LIBRARIES} - ) - set_target_properties (d3d10_1 - PROPERTIES PREFIX "" - RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/wrappers - LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/wrappers - ) - install (TARGETS d3d10_1 LIBRARY DESTINATION ${WRAPPER_INSTALL_DIR}) - endif () - - # d3d11.dll - if (DirectX_D3DX11_INCLUDE_DIR) - include_directories (SYSTEM ${DirectX_D3DX11_INCLUDE_DIR}) - add_custom_command ( - OUTPUT d3d11trace.cpp - COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/d3d11trace.py > ${CMAKE_CURRENT_BINARY_DIR}/d3d11trace.cpp - DEPENDS d3d11trace.py trace.py specs/d3d11.py specs/d3d11sdklayers.py specs/d3dcommon.py specs/dxgi.py specs/dxgitype.py specs/dxgiformat.py specs/winapi.py specs/stdapi.py - ) - add_library (d3d11 MODULE specs/d3d11.def d3d11trace.cpp) - target_link_libraries (d3d11 - common - ${ZLIB_LIBRARIES} - ${SNAPPY_LIBRARIES} - ) - set_target_properties (d3d11 - PROPERTIES PREFIX "" - RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/wrappers - LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/wrappers - ) - install (TARGETS d3d11 LIBRARY DESTINATION ${WRAPPER_INSTALL_DIR}) - endif () - - # opengl32.dll - add_custom_command ( - OUTPUT wgltrace.cpp - COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/wgltrace.py > ${CMAKE_CURRENT_BINARY_DIR}/wgltrace.cpp - DEPENDS wgltrace.py gltrace.py trace.py specs/wglapi.py specs/wglenum.py specs/glapi.py specs/glparams.py specs/gltypes.py specs/winapi.py specs/stdapi.py - ) - add_library (wgltrace MODULE specs/opengl32.def - wgltrace.cpp - glcaps.cpp - glproc_gl.cpp - ) - add_dependencies (wgltrace glproc) - target_link_libraries (wgltrace - common - ${ZLIB_LIBRARIES} - ${SNAPPY_LIBRARIES} - ) - set_target_properties (wgltrace PROPERTIES - PREFIX "" - OUTPUT_NAME opengl32 - RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/wrappers - LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/wrappers - ) - install (TARGETS wgltrace LIBRARY DESTINATION ${WRAPPER_INSTALL_DIR}) - -elseif (APPLE) - # 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 specs/cglapi.py specs/glapi.py specs/glparams.py specs/gltypes.py specs/stdapi.py - ) - - add_library (cgltrace SHARED - cgltrace.cpp - glcaps.cpp - glproc_gl.cpp - ) - - add_dependencies (cgltrace glproc) - - set_target_properties (cgltrace PROPERTIES - # OpenGL framework name - 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 - common - ${ZLIB_LIBRARIES} - ${SNAPPY_LIBRARIES} - ${CMAKE_THREAD_LIBS_INIT} - dl - ) - - install (TARGETS cgltrace LIBRARY DESTINATION ${WRAPPER_INSTALL_DIR}) -elseif (X11_FOUND) - # libGL.so - add_custom_command ( - OUTPUT glxtrace.cpp - COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/glxtrace.py > ${CMAKE_CURRENT_BINARY_DIR}/glxtrace.cpp - DEPENDS glxtrace.py gltrace.py trace.py specs/glxapi.py specs/glapi.py specs/glparams.py specs/gltypes.py specs/stdapi.py - ) - - add_library (glxtrace SHARED - glxtrace.cpp - glcaps.cpp - glproc_gl.cpp - ) - - add_dependencies (glxtrace glproc) - - set_target_properties (glxtrace PROPERTIES - # avoid the default "lib" prefix - PREFIX "" - # Prevent symbol relocations internal to our wrapper library to be - # overwritten by the application. - LINK_FLAGS "-Wl,-Bsymbolic -Wl,-Bsymbolic-functions" - RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/wrappers - LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/wrappers - ) - - target_link_libraries (glxtrace - common - ${ZLIB_LIBRARIES} - ${SNAPPY_LIBRARIES} - ${X11_X11_LIB} - ${CMAKE_THREAD_LIBS_INIT} - dl - ) - - install (TARGETS glxtrace LIBRARY DESTINATION ${WRAPPER_INSTALL_DIR}) -endif () - - -if (ENABLE_EGL AND NOT WIN32 AND NOT APPLE) - # libEGL.so/libGL.so - add_custom_command ( - OUTPUT egltrace.cpp - COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/egltrace.py > ${CMAKE_CURRENT_BINARY_DIR}/egltrace.cpp - DEPENDS egltrace.py gltrace.py trace.py specs/eglapi.py specs/glesapi.py specs/glapi.py specs/glparams.py specs/gltypes.py specs/stdapi.py - ) - - add_library (egltrace SHARED - egltrace.cpp - glcaps.cpp - glproc_egl.cpp - ) - - add_dependencies (egltrace glproc) - - set_target_properties (egltrace PROPERTIES - # avoid the default "lib" prefix - PREFIX "" - LINK_FLAGS "-Wl,-Bsymbolic -Wl,-Bsymbolic-functions" - # Prevent symbol relocations internal to our wrapper library to be - # overwritten by the application. - RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/wrappers - LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/wrappers - ) - - target_link_libraries (egltrace - common - ${ZLIB_LIBRARIES} - ${SNAPPY_LIBRARIES} - ${CMAKE_THREAD_LIBS_INIT} - dl - ) +add_subdirectory (wrappers) - install (TARGETS egltrace LIBRARY DESTINATION ${WRAPPER_INSTALL_DIR}) -endif () ############################################################################## # API retracers diff --git a/cgltrace.py b/cgltrace.py deleted file mode 100644 index 0e40663..0000000 --- a/cgltrace.py +++ /dev/null @@ -1,68 +0,0 @@ -########################################################################## -# -# 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 specs.stdapi import API -from specs.glapi import glapi -from specs.cglapi import cglapi -from gltrace import GlTracer - - -class CglTracer(GlTracer): - - def isFunctionPublic(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 '#include "trace_writer_local.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.addApi(cglapi) - api.addApi(glapi) - tracer = CglTracer() - tracer.trace_api(api) - - print r''' - -PUBLIC -void * gll_noop = 0; - -''' diff --git a/d3d10_1trace.py b/d3d10_1trace.py deleted file mode 100644 index 403ac5d..0000000 --- a/d3d10_1trace.py +++ /dev/null @@ -1,46 +0,0 @@ -########################################################################## -# -# 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. -# -##########################################################################/ - - -from specs.d3d10_1 import d3d10_1 -from dlltrace import DllTracer - - -if __name__ == '__main__': - print '#define INITGUID' - print - print '#include "trace_writer_local.hpp"' - print '#include "os.hpp"' - print - print '#include ' - print '#include ' - print - print '#include "compat.h"' - print - print '#include ' - print '#include ' - print - tracer = DllTracer('d3d10_1.dll') - tracer.trace_api(d3d10_1) diff --git a/d3d10trace.py b/d3d10trace.py deleted file mode 100644 index 527a2f6..0000000 --- a/d3d10trace.py +++ /dev/null @@ -1,46 +0,0 @@ -########################################################################## -# -# 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. -# -##########################################################################/ - - -from specs.d3d10misc import d3d10 -from dlltrace import DllTracer - - -if __name__ == '__main__': - print '#define INITGUID' - print - print '#include "trace_writer_local.hpp"' - print '#include "os.hpp"' - print - print '#include ' - print '#include ' - print - print '#include "compat.h"' - print - print '#include ' - print '#include ' - print - tracer = DllTracer('d3d10.dll') - tracer.trace_api(d3d10) diff --git a/d3d11trace.py b/d3d11trace.py deleted file mode 100644 index e40828b..0000000 --- a/d3d11trace.py +++ /dev/null @@ -1,46 +0,0 @@ -########################################################################## -# -# Copyright 2008-2012 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. -# -##########################################################################/ - - -from specs.d3d11 import d3d11 -from dlltrace import DllTracer - - -if __name__ == '__main__': - print '#define INITGUID' - print - print '#include "trace_writer_local.hpp"' - print '#include "os.hpp"' - print - print '#include ' - print '#include ' - print - print '#include "compat.h"' - print - print '#include ' - print '#include ' - print - tracer = DllTracer('d3d11.dll') - tracer.trace_api(d3d11) diff --git a/d3d8trace.py b/d3d8trace.py deleted file mode 100644 index af87c2d..0000000 --- a/d3d8trace.py +++ /dev/null @@ -1,54 +0,0 @@ -########################################################################## -# -# 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. -# -##########################################################################/ - - -from specs.d3d8 import d3d8 -from dlltrace import DllTracer - - -class D3D8Tracer(DllTracer): - - def serializeArgValue(self, function, arg): - # Dump shaders as strings - if function.name in ('CreateVertexShader', 'CreatePixelShader') and arg.name == 'pFunction': - print ' DumpShader(trace::localWriter, %s);' % (arg.name) - return - - DllTracer.serializeArgValue(self, function, arg) - - -if __name__ == '__main__': - print '#define INITGUID' - print - print '#include ' - print '#include ' - print '#include "d3dshader.hpp"' - print - print '#include "trace_writer_local.hpp"' - print '#include "os.hpp"' - print - tracer = D3D8Tracer('d3d8.dll') - tracer.trace_api(d3d8) - diff --git a/d3d9trace.py b/d3d9trace.py deleted file mode 100644 index 4f40194..0000000 --- a/d3d9trace.py +++ /dev/null @@ -1,94 +0,0 @@ -########################################################################## -# -# 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. -# -##########################################################################/ - - -from dlltrace import DllTracer -from specs.d3d9 import d3d9 - - -class D3D9Tracer(DllTracer): - - def serializeArgValue(self, function, arg): - # Dump shaders as strings - if function.name in ('CreateVertexShader', 'CreatePixelShader') and arg.name == 'pFunction': - print ' DumpShader(trace::localWriter, %s);' % (arg.name) - return - - DllTracer.serializeArgValue(self, function, arg) - - def declareWrapperInterfaceVariables(self, interface): - DllTracer.declareWrapperInterfaceVariables(self, interface) - - if interface.name == 'IDirect3DVertexBuffer9': - print ' UINT m_SizeToLock;' - print ' VOID *m_pbData;' - - def implementWrapperInterfaceMethodBody(self, interface, base, method): - if interface.name == 'IDirect3DVertexBuffer9' and method.name == 'Unlock': - print ' if (m_pbData) {' - self.emit_memcpy('(LPBYTE)m_pbData', '(LPBYTE)m_pbData', 'm_SizeToLock') - print ' }' - - DllTracer.implementWrapperInterfaceMethodBody(self, interface, base, method) - - if interface.name == 'IDirect3DVertexBuffer9' and method.name == 'Lock': - # FIXME: handle recursive locks - print ' if (__result == D3D_OK && !(Flags & D3DLOCK_READONLY)) {' - print ' if (SizeToLock) {' - print ' m_SizeToLock = SizeToLock;' - print ' } else {' - print ' D3DVERTEXBUFFER_DESC Desc;' - print ' m_pInstance->GetDesc(&Desc);' - print ' m_SizeToLock = Desc.Size;' - print ' }' - print ' m_pbData = *ppbData;' - print ' } else {' - print ' m_pbData = NULL;' - print ' }' - - -if __name__ == '__main__': - print '#define INITGUID' - print - print '#include "trace_writer_local.hpp"' - print '#include "os.hpp"' - print - print '#include "d3d9imports.hpp"' - print '#include "d3dshader.hpp"' - print - print ''' -static inline size_t -_declCount(const D3DVERTEXELEMENT9 *pVertexElements) { - size_t count = 0; - if (pVertexElements) { - while (pVertexElements[count++].Stream != 0xff) - ; - } - return count; -} -''' - tracer = D3D9Tracer('d3d9.dll') - tracer.trace_api(d3d9) - diff --git a/d3dshader.cpp b/d3dshader.cpp deleted file mode 100644 index a2d5c12..0000000 --- a/d3dshader.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/************************************************************************** - * - * Copyright 2011 Jose Fonseca - * 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. - * - **************************************************************************/ - - -#include - -#include "d3dshader.hpp" -#include "d3d9imports.hpp" - - -typedef HRESULT -(WINAPI *PD3DXDISASSEMBLESHADER)( - CONST DWORD *pShader, - BOOL EnableColorCode, - LPCSTR pComments, - LPD3DXBUFFER *ppDisassembly -); - - -void DumpShader(trace::Writer &writer, const DWORD *tokens) -{ - static BOOL firsttime = TRUE; - static HMODULE hD3DXModule = NULL; - static PD3DXDISASSEMBLESHADER pfnD3DXDisassembleShader = NULL; - - if (firsttime) { - if (!hD3DXModule) { - unsigned release; - int version; - for (release = 0; release <= 1; ++release) { - /* Version 41 corresponds to Mar 2009 version of DirectX Runtime / SDK */ - for (version = 41; version >= 0; --version) { - char filename[256]; - _snprintf(filename, sizeof(filename), - "d3dx9%s%s%u.dll", release ? "" : "d", version ? "_" : "", version); - hD3DXModule = LoadLibraryA(filename); - if (hD3DXModule) - goto found; - } - } -found: - ; - } - - if (hD3DXModule) { - if (!pfnD3DXDisassembleShader) { - pfnD3DXDisassembleShader = (PD3DXDISASSEMBLESHADER)GetProcAddress(hD3DXModule, "D3DXDisassembleShader"); - } - } - - firsttime = FALSE; - } - - if (pfnD3DXDisassembleShader) { - LPD3DXBUFFER pDisassembly = NULL; - HRESULT hr; - - hr = pfnD3DXDisassembleShader( (DWORD *)tokens, FALSE, NULL, &pDisassembly); - if (hr == D3D_OK) { - writer.writeString((const char *)pDisassembly->GetBufferPointer()); - } - - if (pDisassembly) { - pDisassembly->Release(); - } - - if (hr == D3D_OK) { - return; - } - } - - writer.writeOpaque(tokens); -} diff --git a/d3dshader.hpp b/d3dshader.hpp deleted file mode 100644 index 485df05..0000000 --- a/d3dshader.hpp +++ /dev/null @@ -1,38 +0,0 @@ -/************************************************************************** - * - * Copyright 2011 Jose Fonseca - * 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. - * - **************************************************************************/ - -#ifndef _D3DSHADER_HPP_ -#define _D3DSHADER_HPP_ - - -#include - -#include "trace_writer.hpp" - -void DumpShader(trace::Writer &writer, const DWORD *tokens); - - -#endif /* _D3DSHADER_HPP_ */ diff --git a/ddrawtrace.py b/ddrawtrace.py deleted file mode 100644 index 44d0f6f..0000000 --- a/ddrawtrace.py +++ /dev/null @@ -1,81 +0,0 @@ -########################################################################## -# -# 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. -# -##########################################################################/ - - -from specs.d3d import ddraw, interfaces -from dlltrace import DllTracer - - -class DDrawTracer(DllTracer): - - def traceFunctionImplBody(self, function): - if function.name in ('AcquireDDThreadLock', 'ReleaseDDThreadLock'): - self.invokeFunction(function) - return - - DllTracer.traceFunctionImplBody(self, function) - - def serializeArg(self, function, arg): - if function.name == 'DirectDrawCreateEx' and arg.name == 'lplpDD': - print ' if (*lplpDD) {' - for iface in interfaces: - print ' if (iid == IID_%s) {' % iface.name - print ' *lplpDD = (LPVOID) new Wrap%s((%s *)*lplpDD);' % (iface.name, iface.name) - print ' }' - print ' }' - - DllTracer.serializeArg(self, function, arg) - - -if __name__ == '__main__': - print '#define INITGUID' - print '#include ' - print '#include ' - print '#include ' - print - print ''' - -#ifndef DDBLT_EXTENDED_FLAGS -#define DDBLT_EXTENDED_FLAGS 0x40000000l -#endif - -#ifndef DDBLT_EXTENDED_LINEAR_CONTENT -#define DDBLT_EXTENDED_LINEAR_CONTENT 0x00000004l -#endif - -#ifndef D3DLIGHT_PARALLELPOINT -#define D3DLIGHT_PARALLELPOINT (D3DLIGHTTYPE)4 -#endif - -#ifndef D3DLIGHT_GLSPOT -#define D3DLIGHT_GLSPOT (D3DLIGHTTYPE)5 -#endif - -''' - print '#include "trace_writer_local.hpp"' - print '#include "os.hpp"' - print - tracer = DDrawTracer('ddraw.dll') - tracer.trace_api(ddraw) diff --git a/dlltrace.py b/dlltrace.py deleted file mode 100644 index 647b238..0000000 --- a/dlltrace.py +++ /dev/null @@ -1,69 +0,0 @@ -########################################################################## -# -# Copyright 2008-2010 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. -# -##########################################################################/ - -"""Trace code generation for Windows DLLs.""" - - -from dispatch import Dispatcher -from trace import Tracer - - -class DllTracer(Tracer): - - def __init__(self, dllname): - self.dllname = dllname - - def header(self, api): - print ''' -static HINSTANCE g_hDll = NULL; - -static PROC -__getPublicProcAddress(LPCSTR lpProcName) -{ - if (!g_hDll) { - char szDll[MAX_PATH] = {0}; - - if (!GetSystemDirectoryA(szDll, MAX_PATH)) { - return NULL; - } - - strcat(szDll, "\\\\%s"); - - g_hDll = LoadLibraryA(szDll); - if (!g_hDll) { - return NULL; - } - } - - return GetProcAddress(g_hDll, lpProcName); -} - -''' % self.dllname - - dispatcher = Dispatcher() - dispatcher.dispatch_api(api) - - Tracer.header(self, api) - diff --git a/egltrace.py b/egltrace.py deleted file mode 100644 index 5d5c759..0000000 --- a/egltrace.py +++ /dev/null @@ -1,199 +0,0 @@ -########################################################################## -# -# Copyright 2011 LunarG, Inc. -# All Rights Reserved. -# -# Based on glxtrace.py, which has -# -# Copyright 2011 Jose Fonseca -# Copyright 2008-2010 VMware, Inc. -# -# 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. -# -##########################################################################/ - - -"""EGL tracing generator.""" - - -from specs.stdapi import API -from specs.glapi import glapi -from specs.eglapi import eglapi -from specs.glesapi import glesapi -from gltrace import GlTracer -from dispatch import function_pointer_type, function_pointer_value - - -class EglTracer(GlTracer): - - def isFunctionPublic(self, function): - # The symbols visible in libEGL.so can vary, so expose them all - return True - - def traceFunctionImplBody(self, function): - GlTracer.traceFunctionImplBody(self, function) - - if function.name == 'eglMakeCurrent': - print ' // update the profile' - print ' if (ctx != EGL_NO_CONTEXT) {' - print ' EGLint api = EGL_OPENGL_ES_API, version = 1;' - print ' gltrace::Context *tr = gltrace::getContext();' - print ' __eglQueryContext(dpy, ctx, EGL_CONTEXT_CLIENT_TYPE, &api);' - print ' __eglQueryContext(dpy, ctx, EGL_CONTEXT_CLIENT_VERSION, &version);' - print ' if (api == EGL_OPENGL_API)' - print ' tr->profile = gltrace::PROFILE_COMPAT;' - print ' else if (version == 1)' - print ' tr->profile = gltrace::PROFILE_ES1;' - print ' else' - print ' tr->profile = gltrace::PROFILE_ES2;' - print ' }' - - def wrapRet(self, function, instance): - GlTracer.wrapRet(self, function, instance) - - if function.name == "eglGetProcAddress": - print ' %s = __unwrap_proc_addr(procname, %s);' % (instance, instance) - - -if __name__ == '__main__': - print '#include ' - print '#include ' - print '#include ' - print - print '#include "trace_writer_local.hpp"' - print - print '// To validate our prototypes' - print '#define GL_GLEXT_PROTOTYPES' - print '#define EGL_EGLEXT_PROTOTYPES' - print - print '#include "glproc.hpp"' - print '#include "glsize.hpp"' - print - print 'static __eglMustCastToProperFunctionPointerType __unwrap_proc_addr(const char * procname, __eglMustCastToProperFunctionPointerType procPtr);' - print - - api = API() - api.addApi(eglapi) - api.addApi(glapi) - api.addApi(glesapi) - tracer = EglTracer() - tracer.trace_api(api) - - print 'static __eglMustCastToProperFunctionPointerType __unwrap_proc_addr(const char * procname, __eglMustCastToProperFunctionPointerType procPtr) {' - print ' if (!procPtr) {' - print ' return procPtr;' - print ' }' - for f in api.functions: - ptype = function_pointer_type(f) - pvalue = function_pointer_value(f) - print ' if (!strcmp("%s", procname)) {' % f.name - print ' %s = (%s)procPtr;' % (pvalue, ptype) - print ' return (__eglMustCastToProperFunctionPointerType)&%s;' % (f.name,) - print ' }' - print ' os::log("apitrace: warning: unknown function \\"%s\\"\\n", procname);' - print ' return procPtr;' - print '}' - print - print r''' - - -/* - * Android does not support LD_PRELOAD. - */ -#if !defined(ANDROID) - - -/* - * 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); -} - - -/* - * Several applications, such as Quake3, use dlopen("libGL.so.1"), but - * LD_PRELOAD does not intercept symbols obtained via dlopen/dlsym, therefore - * we need to intercept the dlopen() call here, and redirect to our wrapper - * shared object. - */ -extern "C" PUBLIC -void * dlopen(const char *filename, int flag) -{ - bool intercept = false; - - if (filename) { - intercept = - strcmp(filename, "libEGL.so") == 0 || - strcmp(filename, "libEGL.so.1") == 0 || - strcmp(filename, "libGLESv1_CM.so") == 0 || - strcmp(filename, "libGLESv1_CM.so.1") == 0 || - strcmp(filename, "libGLESv2.so") == 0 || - strcmp(filename, "libGLESv2.so.2") == 0 || - strcmp(filename, "libGL.so") == 0 || - strcmp(filename, "libGL.so.1") == 0; - - if (intercept) { - os::log("apitrace: redirecting dlopen(\"%s\", 0x%x)\n", filename, flag); - - /* The current dispatch implementation relies on core entry-points to be globally available, so force this. - * - * TODO: A better approach would be note down the entry points here and - * use them latter. Another alternative would be to reopen the library - * with RTLD_NOLOAD | RTLD_GLOBAL. - */ - flag &= ~RTLD_LOCAL; - flag |= RTLD_GLOBAL; - } - } - - void *handle = __dlopen(filename, flag); - - if (intercept) { - // Get the file path for our shared object, and use it instead - static int dummy = 0xdeedbeef; - Dl_info info; - if (dladdr(&dummy, &info)) { - handle = __dlopen(info.dli_fname, flag); - } else { - os::log("apitrace: warning: dladdr() failed\n"); - } - } - - return handle; -} - - -#endif /* !ANDROID */ - - - -''' diff --git a/glcaps.cpp b/glcaps.cpp deleted file mode 100644 index f6f70f3..0000000 --- a/glcaps.cpp +++ /dev/null @@ -1,226 +0,0 @@ -/************************************************************************** - * - * 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. - * - **************************************************************************/ - - -/* - * Manipulation of GL extensions. - * - * So far we insert GREMEDY extensions, but in the future we could also clamp - * the GL extensions to core GL versions here. - */ - - -#include -#include -#include - -#include -#include - -#include "glproc.hpp" -#include "gltrace.hpp" - - -namespace gltrace { - - -typedef std::map ExtensionsMap; - -// Cache of the translated extensions strings -static ExtensionsMap extensionsMap; - - -// Additional extensions to be advertised -static const char * -extraExtension_stringsFull[] = { - "GL_GREMEDY_string_marker", - "GL_GREMEDY_frame_terminator", -}; - -static const char * -extraExtension_stringsES[] = { - "GL_EXT_debug_marker", -}; - -// Description of additional extensions we want to advertise -struct ExtensionsDesc -{ - unsigned numStrings; - const char **strings; -}; - -#define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0])) - -const struct ExtensionsDesc -extraExtensionsFull = { - ARRAY_SIZE(extraExtension_stringsFull), - extraExtension_stringsFull -}; - -const struct ExtensionsDesc -extraExtensionsES = { - ARRAY_SIZE(extraExtension_stringsES), - extraExtension_stringsES -}; - - -const struct ExtensionsDesc * -getExtraExtensions(void) -{ - Context *ctx = getContext(); - - switch (ctx->profile) { - case PROFILE_COMPAT: - return &extraExtensionsFull; - case PROFILE_ES1: - case PROFILE_ES2: - return &extraExtensionsES; - default: - assert(0); - return &extraExtensionsFull; - } -} - - -/** - * Translate the GL extensions string, adding new extensions. - */ -static const char * -overrideExtensionsString(const char *extensions) -{ - const ExtensionsDesc *desc = getExtraExtensions(); - size_t i; - - ExtensionsMap::const_iterator it = extensionsMap.find(extensions); - if (it != extensionsMap.end()) { - return it->second; - } - - size_t extensionsLen = strlen(extensions); - - size_t extraExtensionsLen = 0; - for (i = 0; i < desc->numStrings; ++i) { - const char * extraExtension = desc->strings[i]; - size_t extraExtensionLen = strlen(extraExtension); - extraExtensionsLen += extraExtensionLen + 1; - } - - // We use malloc memory instead of a std::string because we need to ensure - // that extensions strings will not move in memory as the extensionsMap is - // updated. - size_t newExtensionsLen = extensionsLen + 1 + extraExtensionsLen + 1; - char *newExtensions = (char *)malloc(newExtensionsLen); - if (!newExtensions) { - return extensions; - } - - if (extensionsLen) { - memcpy(newExtensions, extensions, extensionsLen); - - // Add space separator if necessary - if (newExtensions[extensionsLen - 1] != ' ') { - newExtensions[extensionsLen++] = ' '; - } - } - - for (i = 0; i < desc->numStrings; ++i) { - const char * extraExtension = desc->strings[i]; - size_t extraExtensionLen = strlen(extraExtension); - memcpy(newExtensions + extensionsLen, extraExtension, extraExtensionLen); - extensionsLen += extraExtensionLen; - newExtensions[extensionsLen++] = ' '; - } - newExtensions[extensionsLen++] = '\0'; - assert(extensionsLen <= newExtensionsLen); - - extensionsMap[extensions] = newExtensions; - - return newExtensions; -} - - -const GLubyte * -__glGetString_override(GLenum name) -{ - const GLubyte *result = __glGetString(name); - - if (result) { - switch (name) { - case GL_EXTENSIONS: - result = (const GLubyte *)overrideExtensionsString((const char *)result); - break; - default: - break; - } - } - - return result; -} - - -void -__glGetIntegerv_override(GLenum pname, GLint *params) -{ - __glGetIntegerv(pname, params); - - if (params) { - switch (pname) { - case GL_NUM_EXTENSIONS: - { - const ExtensionsDesc *desc = getExtraExtensions(); - *params += desc->numStrings; - } - break; - default: - break; - } - } -} - - -const GLubyte * -__glGetStringi_override(GLenum name, GLuint index) -{ - switch (name) { - case GL_EXTENSIONS: - { - const ExtensionsDesc *desc = getExtraExtensions(); - GLint numExtensions = 0; - __glGetIntegerv(GL_NUM_EXTENSIONS, &numExtensions); - if ((GLuint)numExtensions <= index && index < (GLuint)numExtensions + desc->numStrings) { - return (const GLubyte *)desc->strings[index - (GLuint)numExtensions]; - } - } - break; - default: - break; - } - - return __glGetStringi(name, index); -} - - -} /* namespace gltrace */ - diff --git a/gltrace.hpp b/gltrace.hpp deleted file mode 100644 index e4fefc3..0000000 --- a/gltrace.hpp +++ /dev/null @@ -1,65 +0,0 @@ -/************************************************************************** - * - * 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. - * - **************************************************************************/ - -#ifndef _GLTRACE_HPP_ -#define _GLTRACE_HPP_ - - -#include "glimports.hpp" - - -namespace gltrace { - - -enum Profile { - PROFILE_COMPAT, - PROFILE_ES1, - PROFILE_ES2, -}; - -struct Context { - enum Profile profile; - bool user_arrays; - bool user_arrays_arb; - bool user_arrays_nv; -}; - -Context * -getContext(void); - -const GLubyte * -__glGetString_override(GLenum name); - -void -__glGetIntegerv_override(GLenum pname, GLint *params); - -const GLubyte * -__glGetStringi_override(GLenum name, GLuint index); - - -} /* namespace gltrace */ - - -#endif /* _GLRETRACE_HPP_ */ diff --git a/gltrace.py b/gltrace.py deleted file mode 100644 index 6fc456c..0000000 --- a/gltrace.py +++ /dev/null @@ -1,1010 +0,0 @@ -########################################################################## -# -# Copyright 2008-2010 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. -# -##########################################################################/ - - -"""GL tracing generator.""" - - -import specs.stdapi as stdapi -import specs.glapi as glapi -import specs.glparams as glparams -from specs.glxapi import glxapi -from trace import Tracer - - -class TypeGetter(stdapi.Visitor): - '''Determine which glGet*v function that matches the specified type.''' - - def __init__(self, prefix = 'glGet', long_suffix = True, ext_suffix = ''): - self.prefix = prefix - self.long_suffix = long_suffix - self.ext_suffix = ext_suffix - - def visitConst(self, const): - return self.visit(const.type) - - def visitAlias(self, alias): - if alias.expr == 'GLboolean': - if self.long_suffix: - suffix = 'Booleanv' - arg_type = alias.expr - else: - suffix = 'iv' - arg_type = 'GLint' - elif alias.expr == 'GLdouble': - if self.long_suffix: - suffix = 'Doublev' - arg_type = alias.expr - else: - suffix = 'dv' - arg_type = alias.expr - elif alias.expr == 'GLfloat': - if self.long_suffix: - suffix = 'Floatv' - arg_type = alias.expr - else: - suffix = 'fv' - arg_type = alias.expr - elif alias.expr in ('GLint', 'GLuint', 'GLsizei'): - if self.long_suffix: - suffix = 'Integerv' - arg_type = 'GLint' - else: - suffix = 'iv' - arg_type = 'GLint' - else: - print alias.expr - assert False - function_name = self.prefix + suffix + self.ext_suffix - return function_name, arg_type - - def visitEnum(self, enum): - return self.visit(glapi.GLint) - - def visitBitmask(self, bitmask): - return self.visit(glapi.GLint) - - def visitOpaque(self, pointer): - return self.prefix + 'Pointerv' + self.ext_suffix, 'GLvoid *' - - -class GlTracer(Tracer): - - arrays = [ - ("Vertex", "VERTEX"), - ("Normal", "NORMAL"), - ("Color", "COLOR"), - ("Index", "INDEX"), - ("TexCoord", "TEXTURE_COORD"), - ("EdgeFlag", "EDGE_FLAG"), - ("FogCoord", "FOG_COORD"), - ("SecondaryColor", "SECONDARY_COLOR"), - ] - arrays.reverse() - - # arrays available in PROFILE_ES1 - arrays_es1 = ("Vertex", "Normal", "Color", "TexCoord") - - def header(self, api): - Tracer.header(self, api) - - print '#include "gltrace.hpp"' - print - - # Which glVertexAttrib* variant to use - print 'enum vertex_attrib {' - print ' VERTEX_ATTRIB,' - print ' VERTEX_ATTRIB_ARB,' - print ' VERTEX_ATTRIB_NV,' - print '};' - print - print 'gltrace::Context *' - print 'gltrace::getContext(void)' - print '{' - print ' // TODO return the context set by other APIs (GLX, EGL, and etc.)' - print ' static gltrace::Context __ctx = { gltrace::PROFILE_COMPAT, false, false, false };' - print ' return &__ctx;' - print '}' - print - print 'static vertex_attrib __get_vertex_attrib(void) {' - print ' gltrace::Context *ctx = gltrace::getContext();' - print ' if (ctx->user_arrays_arb || ctx->user_arrays_nv) {' - print ' GLboolean __vertex_program = GL_FALSE;' - print ' __glGetBooleanv(GL_VERTEX_PROGRAM_ARB, &__vertex_program);' - print ' if (__vertex_program) {' - print ' if (ctx->user_arrays_nv) {' - print ' GLint __vertex_program_binding_nv = 0;' - print ' __glGetIntegerv(GL_VERTEX_PROGRAM_BINDING_NV, &__vertex_program_binding_nv);' - print ' if (__vertex_program_binding_nv) {' - print ' return VERTEX_ATTRIB_NV;' - print ' }' - print ' }' - print ' return VERTEX_ATTRIB_ARB;' - print ' }' - print ' }' - print ' return VERTEX_ATTRIB;' - print '}' - print - - # Whether we need user arrays - print 'static inline bool __need_user_arrays(void)' - print '{' - print ' gltrace::Context *ctx = gltrace::getContext();' - print ' if (!ctx->user_arrays) {' - print ' return false;' - print ' }' - print - - for camelcase_name, uppercase_name in self.arrays: - # in which profile is the array available? - profile_check = 'ctx->profile == gltrace::PROFILE_COMPAT' - if camelcase_name in self.arrays_es1: - profile_check = '(' + profile_check + ' || ctx->profile == gltrace::PROFILE_ES1)'; - - function_name = 'gl%sPointer' % camelcase_name - enable_name = 'GL_%s_ARRAY' % uppercase_name - binding_name = 'GL_%s_ARRAY_BUFFER_BINDING' % uppercase_name - print ' // %s' % function_name - print ' if (%s) {' % profile_check - self.array_prolog(api, uppercase_name) - print ' if (__glIsEnabled(%s)) {' % enable_name - print ' GLint __binding = 0;' - print ' __glGetIntegerv(%s, &__binding);' % binding_name - print ' if (!__binding) {' - self.array_cleanup(api, uppercase_name) - print ' return true;' - print ' }' - print ' }' - self.array_epilog(api, uppercase_name) - print ' }' - print - - print ' // ES1 does not support generic vertex attributes' - print ' if (ctx->profile == gltrace::PROFILE_ES1)' - print ' return false;' - print - print ' vertex_attrib __vertex_attrib = __get_vertex_attrib();' - print - print ' // glVertexAttribPointer' - print ' if (__vertex_attrib == VERTEX_ATTRIB) {' - print ' GLint __max_vertex_attribs = 0;' - print ' __glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &__max_vertex_attribs);' - print ' for (GLint index = 0; index < __max_vertex_attribs; ++index) {' - print ' GLint __enabled = 0;' - print ' __glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &__enabled);' - print ' if (__enabled) {' - print ' GLint __binding = 0;' - print ' __glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &__binding);' - print ' if (!__binding) {' - print ' return true;' - print ' }' - print ' }' - print ' }' - print ' }' - print - print ' // glVertexAttribPointerARB' - print ' if (__vertex_attrib == VERTEX_ATTRIB_ARB) {' - print ' GLint __max_vertex_attribs = 0;' - print ' __glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &__max_vertex_attribs);' - print ' for (GLint index = 0; index < __max_vertex_attribs; ++index) {' - print ' GLint __enabled = 0;' - print ' __glGetVertexAttribivARB(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB, &__enabled);' - print ' if (__enabled) {' - print ' GLint __binding = 0;' - print ' __glGetVertexAttribivARB(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB, &__binding);' - print ' if (!__binding) {' - print ' return true;' - print ' }' - print ' }' - print ' }' - print ' }' - print - print ' // glVertexAttribPointerNV' - print ' if (__vertex_attrib == VERTEX_ATTRIB_NV) {' - print ' for (GLint index = 0; index < 16; ++index) {' - print ' GLint __enabled = 0;' - print ' __glGetIntegerv(GL_VERTEX_ATTRIB_ARRAY0_NV + index, &__enabled);' - print ' if (__enabled) {' - print ' return true;' - print ' }' - print ' }' - print ' }' - print - - print ' return false;' - print '}' - print - - print 'static void __trace_user_arrays(GLuint maxindex);' - print - - # Buffer mappings - print '// whether glMapBufferRange(GL_MAP_WRITE_BIT) has ever been called' - print 'static bool __checkBufferMapRange = false;' - print - print '// whether glBufferParameteriAPPLE(GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE) has ever been called' - print 'static bool __checkBufferFlushingUnmapAPPLE = false;' - print - # Buffer mapping information, necessary for old Mesa 2.1 drivers which - # do not support glGetBufferParameteriv(GL_BUFFER_ACCESS_FLAGS/GL_BUFFER_MAP_LENGTH) - print 'struct buffer_mapping {' - print ' void *map;' - print ' GLint length;' - print ' bool write;' - print ' bool explicit_flush;' - print '};' - print - for target in self.buffer_targets: - print 'struct buffer_mapping __%s_mapping;' % target.lower(); - print - print 'static inline struct buffer_mapping *' - print 'get_buffer_mapping(GLenum target) {' - print ' switch (target) {' - for target in self.buffer_targets: - print ' case GL_%s:' % target - print ' return & __%s_mapping;' % target.lower() - print ' default:' - print ' os::log("apitrace: warning: unknown buffer target 0x%04X\\n", target);' - print ' return NULL;' - print ' }' - print '}' - print - - # Generate a helper function to determine whether a parameter name - # refers to a symbolic value or not - print 'static bool' - print 'is_symbolic_pname(GLenum pname) {' - print ' switch (pname) {' - for function, type, count, name in glparams.parameters: - if type is glapi.GLenum: - print ' case %s:' % name - print ' return true;' - print ' default:' - print ' return false;' - print ' }' - print '}' - print - - # Generate a helper function to determine whether a parameter value is - # potentially symbolic or not; i.e., if the value can be represented in - # an enum or not - print 'template' - print 'static inline bool' - print 'is_symbolic_param(T param) {' - print ' return static_cast(static_cast(param)) == param;' - print '}' - print - - # Generate a helper function to know how many elements a parameter has - print 'static size_t' - print '__gl_param_size(GLenum pname) {' - print ' switch (pname) {' - for function, type, count, name in glparams.parameters: - if type is not None: - print ' case %s: return %u;' % (name, count) - print ' case GL_COMPRESSED_TEXTURE_FORMATS: {' - print ' GLint num_compressed_texture_formats = 0;' - print ' __glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &num_compressed_texture_formats);' - print ' return num_compressed_texture_formats;' - print ' }' - print ' default:' - print r' os::log("apitrace: warning: %s: unknown GLenum 0x%04X\n", __FUNCTION__, pname);' - print ' return 1;' - print ' }' - print '}' - print - - # states such as GL_UNPACK_ROW_LENGTH are not available in GLES - print 'static inline bool' - print 'can_unpack_subimage(void) {' - print ' gltrace::Context *ctx = gltrace::getContext();' - print ' return (ctx->profile == gltrace::PROFILE_COMPAT);' - print '}' - print - - array_pointer_function_names = set(( - "glVertexPointer", - "glNormalPointer", - "glColorPointer", - "glIndexPointer", - "glTexCoordPointer", - "glEdgeFlagPointer", - "glFogCoordPointer", - "glSecondaryColorPointer", - - "glInterleavedArrays", - - "glVertexPointerEXT", - "glNormalPointerEXT", - "glColorPointerEXT", - "glIndexPointerEXT", - "glTexCoordPointerEXT", - "glEdgeFlagPointerEXT", - "glFogCoordPointerEXT", - "glSecondaryColorPointerEXT", - - "glVertexAttribPointer", - "glVertexAttribPointerARB", - "glVertexAttribPointerNV", - "glVertexAttribIPointer", - "glVertexAttribIPointerEXT", - "glVertexAttribLPointer", - "glVertexAttribLPointerEXT", - - #"glMatrixIndexPointerARB", - )) - - draw_function_names = set(( - 'glDrawArrays', - 'glDrawElements', - 'glDrawRangeElements', - 'glMultiDrawArrays', - 'glMultiDrawElements', - 'glDrawArraysInstanced', - "glDrawArraysInstancedBaseInstance", - 'glDrawElementsInstanced', - 'glDrawArraysInstancedARB', - 'glDrawElementsInstancedARB', - 'glDrawElementsBaseVertex', - 'glDrawRangeElementsBaseVertex', - 'glDrawElementsInstancedBaseVertex', - "glDrawElementsInstancedBaseInstance", - "glDrawElementsInstancedBaseVertexBaseInstance", - 'glMultiDrawElementsBaseVertex', - 'glDrawArraysIndirect', - 'glDrawElementsIndirect', - 'glDrawArraysEXT', - 'glDrawRangeElementsEXT', - 'glDrawRangeElementsEXT_size', - 'glMultiDrawArraysEXT', - 'glMultiDrawElementsEXT', - 'glMultiModeDrawArraysIBM', - 'glMultiModeDrawElementsIBM', - 'glDrawArraysInstancedEXT', - 'glDrawElementsInstancedEXT', - )) - - interleaved_formats = [ - 'GL_V2F', - 'GL_V3F', - 'GL_C4UB_V2F', - 'GL_C4UB_V3F', - 'GL_C3F_V3F', - 'GL_N3F_V3F', - 'GL_C4F_N3F_V3F', - 'GL_T2F_V3F', - 'GL_T4F_V4F', - 'GL_T2F_C4UB_V3F', - 'GL_T2F_C3F_V3F', - 'GL_T2F_N3F_V3F', - 'GL_T2F_C4F_N3F_V3F', - 'GL_T4F_C4F_N3F_V4F', - ] - - def traceFunctionImplBody(self, function): - # Defer tracing of user array pointers... - if function.name in self.array_pointer_function_names: - print ' GLint __array_buffer = 0;' - print ' __glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &__array_buffer);' - print ' if (!__array_buffer) {' - print ' gltrace::Context *ctx = gltrace::getContext();' - print ' ctx->user_arrays = true;' - if function.name == "glVertexAttribPointerARB": - print ' ctx->user_arrays_arb = true;' - if function.name == "glVertexAttribPointerNV": - print ' ctx->user_arrays_nv = true;' - self.invokeFunction(function) - - # And also break down glInterleavedArrays into the individual calls - if function.name == 'glInterleavedArrays': - print - - # Initialize the enable flags - for camelcase_name, uppercase_name in self.arrays: - flag_name = '__' + uppercase_name.lower() - print ' GLboolean %s = GL_FALSE;' % flag_name - print - - # Switch for the interleaved formats - print ' switch (format) {' - for format in self.interleaved_formats: - print ' case %s:' % format - for camelcase_name, uppercase_name in self.arrays: - flag_name = '__' + uppercase_name.lower() - if format.find('_' + uppercase_name[0]) >= 0: - print ' %s = GL_TRUE;' % flag_name - print ' break;' - print ' default:' - print ' return;' - print ' }' - print - - # Emit fake glEnableClientState/glDisableClientState flags - for camelcase_name, uppercase_name in self.arrays: - flag_name = '__' + uppercase_name.lower() - enable_name = 'GL_%s_ARRAY' % uppercase_name - - # Emit a fake function - print ' {' - print ' static const trace::FunctionSig &__sig = %s ? __glEnableClientState_sig : __glDisableClientState_sig;' % flag_name - print ' unsigned __call = trace::localWriter.beginEnter(&__sig);' - print ' trace::localWriter.beginArg(0);' - self.serializeValue(glapi.GLenum, enable_name) - print ' trace::localWriter.endArg();' - print ' trace::localWriter.endEnter();' - print ' trace::localWriter.beginLeave(__call);' - print ' trace::localWriter.endLeave();' - print ' }' - - print ' return;' - print ' }' - - # ... to the draw calls - if function.name in self.draw_function_names: - print ' if (__need_user_arrays()) {' - arg_names = ', '.join([arg.name for arg in function.args[1:]]) - print ' GLuint maxindex = __%s_maxindex(%s);' % (function.name, arg_names) - print ' __trace_user_arrays(maxindex);' - print ' }' - - # Emit a fake memcpy on buffer uploads - if function.name == 'glBufferParameteriAPPLE': - print ' if (pname == GL_BUFFER_FLUSHING_UNMAP_APPLE && param == GL_FALSE) {' - print ' __checkBufferFlushingUnmapAPPLE = true;' - print ' }' - if function.name in ('glUnmapBuffer', 'glUnmapBufferARB'): - if function.name.endswith('ARB'): - suffix = 'ARB' - else: - suffix = '' - print ' GLint access = 0;' - print ' __glGetBufferParameteriv%s(target, GL_BUFFER_ACCESS, &access);' % suffix - print ' if (access != GL_READ_ONLY) {' - print ' GLvoid *map = NULL;' - print ' __glGetBufferPointerv%s(target, GL_BUFFER_MAP_POINTER, &map);' % suffix - print ' if (map) {' - print ' GLint length = -1;' - print ' bool flush = true;' - print ' if (__checkBufferMapRange) {' - print ' __glGetBufferParameteriv%s(target, GL_BUFFER_MAP_LENGTH, &length);' % suffix - print ' GLint access_flags = 0;' - print ' __glGetBufferParameteriv(target, GL_BUFFER_ACCESS_FLAGS, &access_flags);' - print ' flush = flush && !(access_flags & GL_MAP_FLUSH_EXPLICIT_BIT);' - print ' if (length == -1) {' - print ' // Mesa drivers refuse GL_BUFFER_MAP_LENGTH without GL 3.0' - print ' static bool warned = false;' - print ' if (!warned) {' - print ' os::log("apitrace: warning: glGetBufferParameteriv%s(GL_BUFFER_MAP_LENGTH) failed\\n");' % suffix - print ' warned = true;' - print ' }' - print ' struct buffer_mapping *mapping = get_buffer_mapping(target);' - print ' if (mapping) {' - print ' length = mapping->length;' - print ' flush = flush && !mapping->explicit_flush;' - print ' } else {' - print ' length = 0;' - print ' flush = false;' - print ' }' - print ' }' - print ' } else {' - print ' length = 0;' - print ' __glGetBufferParameteriv%s(target, GL_BUFFER_SIZE, &length);' % suffix - print ' }' - print ' if (__checkBufferFlushingUnmapAPPLE) {' - print ' GLint flushing_unmap = GL_TRUE;' - print ' __glGetBufferParameteriv%s(target, GL_BUFFER_FLUSHING_UNMAP_APPLE, &flushing_unmap);' % suffix - print ' flush = flush && flushing_unmap;' - print ' }' - print ' if (flush && length > 0) {' - self.emit_memcpy('map', 'map', 'length') - print ' }' - print ' }' - print ' }' - if function.name == 'glUnmapBufferOES': - print ' GLint access = 0;' - print ' __glGetBufferParameteriv(target, GL_BUFFER_ACCESS_OES, &access);' - print ' if (access == GL_WRITE_ONLY_OES) {' - print ' GLvoid *map = NULL;' - print ' __glGetBufferPointervOES(target, GL_BUFFER_MAP_POINTER_OES, &map);' - print ' GLint size = 0;' - print ' __glGetBufferParameteriv(target, GL_BUFFER_SIZE, &size);' - print ' if (map && size > 0) {' - self.emit_memcpy('map', 'map', 'size') - print ' }' - print ' }' - if function.name == 'glUnmapNamedBufferEXT': - print ' GLint access_flags = 0;' - print ' __glGetNamedBufferParameterivEXT(buffer, GL_BUFFER_ACCESS_FLAGS, &access_flags);' - print ' if ((access_flags & GL_MAP_WRITE_BIT) && !(access_flags & GL_MAP_FLUSH_EXPLICIT_BIT)) {' - print ' GLvoid *map = NULL;' - print ' __glGetNamedBufferPointervEXT(buffer, GL_BUFFER_MAP_POINTER, &map);' - print ' GLint length = 0;' - print ' __glGetNamedBufferParameterivEXT(buffer, GL_BUFFER_MAP_LENGTH, &length);' - print ' if (map && length > 0) {' - self.emit_memcpy('map', 'map', 'length') - print ' }' - print ' }' - if function.name == 'glFlushMappedBufferRange': - print ' GLvoid *map = NULL;' - print ' __glGetBufferPointerv(target, GL_BUFFER_MAP_POINTER, &map);' - print ' if (map && length > 0) {' - self.emit_memcpy('(char *)map + offset', '(const char *)map + offset', 'length') - print ' }' - if function.name == 'glFlushMappedBufferRangeAPPLE': - print ' GLvoid *map = NULL;' - print ' __glGetBufferPointerv(target, GL_BUFFER_MAP_POINTER, &map);' - print ' if (map && size > 0) {' - self.emit_memcpy('(char *)map + offset', '(const char *)map + offset', 'size') - print ' }' - if function.name == 'glFlushMappedNamedBufferRangeEXT': - print ' GLvoid *map = NULL;' - print ' __glGetNamedBufferPointervEXT(buffer, GL_BUFFER_MAP_POINTER, &map);' - print ' if (map && length > 0) {' - self.emit_memcpy('(char *)map + offset', '(const char *)map + offset', 'length') - print ' }' - - # Don't leave vertex attrib locations to chance. Instead emit fake - # glBindAttribLocation calls to ensure that the same locations will be - # used when retracing. Trying to remap locations after the fact would - # be an herculian task given that vertex attrib locations appear in - # many entry-points, including non-shader related ones. - if function.name == 'glLinkProgram': - Tracer.invokeFunction(self, function) - print ' GLint active_attributes = 0;' - print ' __glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &active_attributes);' - print ' for (GLint attrib = 0; attrib < active_attributes; ++attrib) {' - print ' GLint size = 0;' - print ' GLenum type = 0;' - print ' GLchar name[256];' - # TODO: Use ACTIVE_ATTRIBUTE_MAX_LENGTH instead of 256 - print ' __glGetActiveAttrib(program, attrib, sizeof name, NULL, &size, &type, name);' - print " if (name[0] != 'g' || name[1] != 'l' || name[2] != '_') {" - print ' GLint location = __glGetAttribLocation(program, name);' - print ' if (location >= 0) {' - bind_function = glapi.glapi.get_function_by_name('glBindAttribLocation') - self.fake_call(bind_function, ['program', 'location', 'name']) - print ' }' - print ' }' - print ' }' - if function.name == 'glLinkProgramARB': - Tracer.invokeFunction(self, function) - print ' GLint active_attributes = 0;' - print ' __glGetObjectParameterivARB(programObj, GL_OBJECT_ACTIVE_ATTRIBUTES_ARB, &active_attributes);' - print ' for (GLint attrib = 0; attrib < active_attributes; ++attrib) {' - print ' GLint size = 0;' - print ' GLenum type = 0;' - print ' GLcharARB name[256];' - # TODO: Use ACTIVE_ATTRIBUTE_MAX_LENGTH instead of 256 - print ' __glGetActiveAttribARB(programObj, attrib, sizeof name, NULL, &size, &type, name);' - print " if (name[0] != 'g' || name[1] != 'l' || name[2] != '_') {" - print ' GLint location = __glGetAttribLocationARB(programObj, name);' - print ' if (location >= 0) {' - bind_function = glapi.glapi.get_function_by_name('glBindAttribLocationARB') - self.fake_call(bind_function, ['programObj', 'location', 'name']) - print ' }' - print ' }' - print ' }' - - Tracer.traceFunctionImplBody(self, function) - - marker_functions = [ - # GL_GREMEDY_string_marker - 'glStringMarkerGREMEDY', - # GL_GREMEDY_frame_terminator - 'glFrameTerminatorGREMEDY', - # GL_EXT_debug_marker - 'glInsertEventMarkerEXT', - 'glPushGroupMarkerEXT', - 'glPopGroupMarkerEXT', - ] - - def invokeFunction(self, function): - if function.name in ('glLinkProgram', 'glLinkProgramARB'): - # These functions have been dispatched already - return - - # We implement GL_EXT_debug_marker, GL_GREMEDY_*, etc., and not the - # driver - if function.name in self.marker_functions: - return - - if function.name in ('glXGetProcAddress', 'glXGetProcAddressARB', 'wglGetProcAddress'): - else_ = '' - for marker_function in self.marker_functions: - if self.api.get_function_by_name(marker_function): - print ' %sif (strcmp("%s", (const char *)%s) == 0) {' % (else_, marker_function, function.args[0].name) - print ' __result = (%s)&%s;' % (function.type, marker_function) - print ' }' - else_ = 'else ' - print ' %s{' % else_ - Tracer.invokeFunction(self, function) - print ' }' - return - - # Override GL extensions - if function.name in ('glGetString', 'glGetIntegerv', 'glGetStringi'): - Tracer.invokeFunction(self, function, prefix = 'gltrace::__', suffix = '_override') - return - - Tracer.invokeFunction(self, function) - - buffer_targets = [ - 'ARRAY_BUFFER', - 'ELEMENT_ARRAY_BUFFER', - 'PIXEL_PACK_BUFFER', - 'PIXEL_UNPACK_BUFFER', - 'UNIFORM_BUFFER', - 'TEXTURE_BUFFER', - 'TRANSFORM_FEEDBACK_BUFFER', - 'COPY_READ_BUFFER', - 'COPY_WRITE_BUFFER', - 'DRAW_INDIRECT_BUFFER', - 'ATOMIC_COUNTER_BUFFER', - ] - - def wrapRet(self, function, instance): - Tracer.wrapRet(self, function, instance) - - # Keep track of buffer mappings - if function.name in ('glMapBuffer', 'glMapBufferARB'): - print ' struct buffer_mapping *mapping = get_buffer_mapping(target);' - print ' if (mapping) {' - print ' mapping->map = %s;' % (instance) - print ' mapping->length = 0;' - print ' __glGetBufferParameteriv(target, GL_BUFFER_SIZE, &mapping->length);' - print ' mapping->write = (access != GL_READ_ONLY);' - print ' mapping->explicit_flush = false;' - print ' }' - if function.name == 'glMapBufferRange': - print ' if (access & GL_MAP_WRITE_BIT) {' - print ' __checkBufferMapRange = true;' - print ' }' - print ' struct buffer_mapping *mapping = get_buffer_mapping(target);' - print ' if (mapping) {' - print ' mapping->map = %s;' % (instance) - print ' mapping->length = length;' - print ' mapping->write = access & GL_MAP_WRITE_BIT;' - print ' mapping->explicit_flush = access & GL_MAP_FLUSH_EXPLICIT_BIT;' - print ' }' - - boolean_names = [ - 'GL_FALSE', - 'GL_TRUE', - ] - - def gl_boolean(self, value): - return self.boolean_names[int(bool(value))] - - # Names of the functions that unpack from a pixel buffer object. See the - # ARB_pixel_buffer_object specification. - unpack_function_names = set([ - 'glBitmap', - 'glColorSubTable', - 'glColorTable', - 'glCompressedTexImage1D', - 'glCompressedTexImage2D', - 'glCompressedTexImage3D', - 'glCompressedTexSubImage1D', - 'glCompressedTexSubImage2D', - 'glCompressedTexSubImage3D', - 'glConvolutionFilter1D', - 'glConvolutionFilter2D', - 'glDrawPixels', - 'glMultiTexImage1DEXT', - 'glMultiTexImage2DEXT', - 'glMultiTexImage3DEXT', - 'glMultiTexSubImage1DEXT', - 'glMultiTexSubImage2DEXT', - 'glMultiTexSubImage3DEXT', - 'glPixelMapfv', - 'glPixelMapuiv', - 'glPixelMapusv', - 'glPolygonStipple', - 'glSeparableFilter2D', - 'glTexImage1D', - 'glTexImage1DEXT', - 'glTexImage2D', - 'glTexImage2DEXT', - 'glTexImage3D', - 'glTexImage3DEXT', - 'glTexSubImage1D', - 'glTexSubImage1DEXT', - 'glTexSubImage2D', - 'glTexSubImage2DEXT', - 'glTexSubImage3D', - 'glTexSubImage3DEXT', - 'glTextureImage1DEXT', - 'glTextureImage2DEXT', - 'glTextureImage3DEXT', - 'glTextureSubImage1DEXT', - 'glTextureSubImage2DEXT', - 'glTextureSubImage3DEXT', - ]) - - def serializeArgValue(self, function, arg): - if function.name in self.draw_function_names and arg.name == 'indices': - print ' GLint __element_array_buffer = 0;' - print ' __glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &__element_array_buffer);' - print ' if (!__element_array_buffer) {' - if isinstance(arg.type, stdapi.Array): - print ' trace::localWriter.beginArray(%s);' % arg.type.length - print ' for(GLsizei i = 0; i < %s; ++i) {' % arg.type.length - print ' trace::localWriter.beginElement();' - print ' trace::localWriter.writeBlob(%s[i], count[i]*__gl_type_size(type));' % (arg.name) - print ' trace::localWriter.endElement();' - print ' }' - print ' trace::localWriter.endArray();' - else: - print ' trace::localWriter.writeBlob(%s, count*__gl_type_size(type));' % (arg.name) - print ' } else {' - Tracer.serializeArgValue(self, function, arg) - print ' }' - return - - # Recognize offsets instead of blobs when a PBO is bound - if function.name in self.unpack_function_names \ - and (isinstance(arg.type, stdapi.Blob) \ - or (isinstance(arg.type, stdapi.Const) \ - and isinstance(arg.type.type, stdapi.Blob))): - print ' {' - print ' gltrace::Context *ctx = gltrace::getContext();' - print ' GLint __unpack_buffer = 0;' - print ' if (ctx->profile == gltrace::PROFILE_COMPAT)' - print ' __glGetIntegerv(GL_PIXEL_UNPACK_BUFFER_BINDING, &__unpack_buffer);' - print ' if (__unpack_buffer) {' - print ' trace::localWriter.writeOpaque(%s);' % arg.name - print ' } else {' - Tracer.serializeArgValue(self, function, arg) - print ' }' - print ' }' - return - - # Several GL state functions take GLenum symbolic names as - # integer/floats; so dump the symbolic name whenever possible - if function.name.startswith('gl') \ - and arg.type in (glapi.GLint, glapi.GLfloat, glapi.GLdouble) \ - 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 - print ' if (is_symbolic_pname(pname) && is_symbolic_param(%s)) {' % arg.name - self.serializeValue(glapi.GLenum, arg.name) - print ' } else {' - Tracer.serializeArgValue(self, function, arg) - print ' }' - return - - Tracer.serializeArgValue(self, function, arg) - - def footer(self, api): - Tracer.footer(self, api) - - # A simple state tracker to track the pointer values - # update the state - print 'static void __trace_user_arrays(GLuint maxindex)' - print '{' - print ' gltrace::Context *ctx = gltrace::getContext();' - - for camelcase_name, uppercase_name in self.arrays: - # in which profile is the array available? - profile_check = 'ctx->profile == gltrace::PROFILE_COMPAT' - if camelcase_name in self.arrays_es1: - profile_check = '(' + profile_check + ' || ctx->profile == gltrace::PROFILE_ES1)'; - - function_name = 'gl%sPointer' % camelcase_name - enable_name = 'GL_%s_ARRAY' % uppercase_name - binding_name = 'GL_%s_ARRAY_BUFFER_BINDING' % uppercase_name - function = api.get_function_by_name(function_name) - - print ' // %s' % function.prototype() - print ' if (%s) {' % profile_check - self.array_trace_prolog(api, uppercase_name) - self.array_prolog(api, uppercase_name) - print ' if (__glIsEnabled(%s)) {' % enable_name - print ' GLint __binding = 0;' - print ' __glGetIntegerv(%s, &__binding);' % binding_name - print ' if (!__binding) {' - - # Get the arguments via glGet* - for arg in function.args: - arg_get_enum = 'GL_%s_ARRAY_%s' % (uppercase_name, arg.name.upper()) - arg_get_function, arg_type = TypeGetter().visit(arg.type) - print ' %s %s = 0;' % (arg_type, arg.name) - print ' __%s(%s, &%s);' % (arg_get_function, arg_get_enum, arg.name) - - arg_names = ', '.join([arg.name for arg in function.args[:-1]]) - print ' size_t __size = __%s_size(%s, maxindex);' % (function.name, arg_names) - - # Emit a fake function - self.array_trace_intermezzo(api, uppercase_name) - print ' unsigned __call = trace::localWriter.beginEnter(&__%s_sig);' % (function.name,) - for arg in function.args: - assert not arg.output - print ' trace::localWriter.beginArg(%u);' % (arg.index,) - if arg.name != 'pointer': - self.serializeValue(arg.type, arg.name) - else: - print ' trace::localWriter.writeBlob((const void *)%s, __size);' % (arg.name) - print ' trace::localWriter.endArg();' - - print ' trace::localWriter.endEnter();' - print ' trace::localWriter.beginLeave(__call);' - print ' trace::localWriter.endLeave();' - print ' }' - print ' }' - self.array_epilog(api, uppercase_name) - self.array_trace_epilog(api, uppercase_name) - print ' }' - print - - # Samething, but for glVertexAttribPointer* - # - # Some variants of glVertexAttribPointer alias conventional and generic attributes: - # - glVertexAttribPointer: no - # - glVertexAttribPointerARB: implementation dependent - # - glVertexAttribPointerNV: yes - # - # This means that the implementations of these functions do not always - # alias, and they need to be considered independently. - # - print ' // ES1 does not support generic vertex attributes' - print ' if (ctx->profile == gltrace::PROFILE_ES1)' - print ' return;' - print - print ' vertex_attrib __vertex_attrib = __get_vertex_attrib();' - print - for suffix in ['', 'ARB', 'NV']: - if suffix: - SUFFIX = '_' + suffix - else: - SUFFIX = suffix - function_name = 'glVertexAttribPointer' + suffix - function = api.get_function_by_name(function_name) - - print ' // %s' % function.prototype() - print ' if (__vertex_attrib == VERTEX_ATTRIB%s) {' % SUFFIX - if suffix == 'NV': - print ' GLint __max_vertex_attribs = 16;' - else: - print ' GLint __max_vertex_attribs = 0;' - print ' __glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &__max_vertex_attribs);' - print ' for (GLint index = 0; index < __max_vertex_attribs; ++index) {' - print ' GLint __enabled = 0;' - if suffix == 'NV': - print ' __glGetIntegerv(GL_VERTEX_ATTRIB_ARRAY0_NV + index, &__enabled);' - else: - print ' __glGetVertexAttribiv%s(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED%s, &__enabled);' % (suffix, SUFFIX) - print ' if (__enabled) {' - print ' GLint __binding = 0;' - if suffix != 'NV': - # It doesn't seem possible to use VBOs with NV_vertex_program. - print ' __glGetVertexAttribiv%s(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING%s, &__binding);' % (suffix, SUFFIX) - print ' if (!__binding) {' - - # Get the arguments via glGet* - for arg in function.args[1:]: - if suffix == 'NV': - arg_get_enum = 'GL_ATTRIB_ARRAY_%s%s' % (arg.name.upper(), SUFFIX) - else: - arg_get_enum = 'GL_VERTEX_ATTRIB_ARRAY_%s%s' % (arg.name.upper(), SUFFIX) - arg_get_function, arg_type = TypeGetter('glGetVertexAttrib', False, suffix).visit(arg.type) - print ' %s %s = 0;' % (arg_type, arg.name) - print ' __%s(index, %s, &%s);' % (arg_get_function, arg_get_enum, arg.name) - - arg_names = ', '.join([arg.name for arg in function.args[1:-1]]) - print ' size_t __size = __%s_size(%s, maxindex);' % (function.name, arg_names) - - # Emit a fake function - print ' unsigned __call = trace::localWriter.beginEnter(&__%s_sig);' % (function.name,) - for arg in function.args: - assert not arg.output - print ' trace::localWriter.beginArg(%u);' % (arg.index,) - if arg.name != 'pointer': - self.serializeValue(arg.type, arg.name) - else: - print ' trace::localWriter.writeBlob((const void *)%s, __size);' % (arg.name) - print ' trace::localWriter.endArg();' - - print ' trace::localWriter.endEnter();' - print ' trace::localWriter.beginLeave(__call);' - print ' trace::localWriter.endLeave();' - print ' }' - print ' }' - print ' }' - print ' }' - print - - print '}' - print - - # - # Hooks for glTexCoordPointer, which is identical to the other array - # pointers except the fact that it is indexed by glClientActiveTexture. - # - - def array_prolog(self, api, uppercase_name): - if uppercase_name == 'TEXTURE_COORD': - print ' GLint client_active_texture = 0;' - print ' __glGetIntegerv(GL_CLIENT_ACTIVE_TEXTURE, &client_active_texture);' - print ' GLint max_texture_coords = 0;' - print ' if (ctx->profile == gltrace::PROFILE_COMPAT)' - print ' __glGetIntegerv(GL_MAX_TEXTURE_COORDS, &max_texture_coords);' - print ' else' - print ' __glGetIntegerv(GL_MAX_TEXTURE_UNITS, &max_texture_coords);' - print ' for (GLint unit = 0; unit < max_texture_coords; ++unit) {' - print ' GLint texture = GL_TEXTURE0 + unit;' - print ' __glClientActiveTexture(texture);' - - def array_trace_prolog(self, api, uppercase_name): - if uppercase_name == 'TEXTURE_COORD': - print ' bool client_active_texture_dirty = false;' - - def array_epilog(self, api, uppercase_name): - if uppercase_name == 'TEXTURE_COORD': - print ' }' - self.array_cleanup(api, uppercase_name) - - def array_cleanup(self, api, uppercase_name): - if uppercase_name == 'TEXTURE_COORD': - print ' __glClientActiveTexture(client_active_texture);' - - def array_trace_intermezzo(self, api, uppercase_name): - if uppercase_name == 'TEXTURE_COORD': - print ' if (texture != client_active_texture || client_active_texture_dirty) {' - print ' client_active_texture_dirty = true;' - self.fake_glClientActiveTexture_call(api, "texture"); - print ' }' - - def array_trace_epilog(self, api, uppercase_name): - if uppercase_name == 'TEXTURE_COORD': - print ' if (client_active_texture_dirty) {' - self.fake_glClientActiveTexture_call(api, "client_active_texture"); - print ' }' - - def fake_glClientActiveTexture_call(self, api, texture): - function = api.get_function_by_name('glClientActiveTexture') - self.fake_call(function, [texture]) - - def fake_call(self, function, args): - print ' unsigned __fake_call = trace::localWriter.beginEnter(&__%s_sig);' % (function.name,) - for arg, instance in zip(function.args, args): - assert not arg.output - print ' trace::localWriter.beginArg(%u);' % (arg.index,) - self.serializeValue(arg.type, instance) - print ' trace::localWriter.endArg();' - print ' trace::localWriter.endEnter();' - print ' trace::localWriter.beginLeave(__fake_call);' - print ' trace::localWriter.endLeave();' - - - - - - - - - - - diff --git a/glxtrace.py b/glxtrace.py deleted file mode 100644 index b8dac38..0000000 --- a/glxtrace.py +++ /dev/null @@ -1,161 +0,0 @@ -########################################################################## -# -# Copyright 2011 Jose Fonseca -# Copyright 2008-2010 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. -# -##########################################################################/ - - -"""GLX tracing generator.""" - - -from specs.stdapi import API -from specs.glapi import glapi -from specs.glxapi import glxapi -from gltrace import GlTracer -from dispatch import function_pointer_type, function_pointer_value - - -class GlxTracer(GlTracer): - - def isFunctionPublic(self, function): - # The symbols visible in libGL.so can vary, so expose them all - return True - - def wrapRet(self, function, instance): - GlTracer.wrapRet(self, function, instance) - - if function.name in ("glXGetProcAddress", "glXGetProcAddressARB"): - print ' %s = __unwrap_proc_addr(procName, %s);' % (instance, instance) - - -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_writer_local.hpp"' - print - print '// To validate our prototypes' - print '#define GL_GLEXT_PROTOTYPES' - print '#define GLX_GLXEXT_PROTOTYPES' - print - print '#include "glproc.hpp"' - print '#include "glsize.hpp"' - print - print 'static __GLXextFuncPtr __unwrap_proc_addr(const GLubyte * procName, __GLXextFuncPtr procPtr);' - print - - api = API() - api.addApi(glxapi) - api.addApi(glapi) - tracer = GlxTracer() - tracer.trace_api(api) - - print 'static __GLXextFuncPtr __unwrap_proc_addr(const GLubyte * procName, __GLXextFuncPtr procPtr) {' - print ' if (!procPtr) {' - print ' return procPtr;' - print ' }' - for f in api.functions: - ptype = function_pointer_type(f) - pvalue = function_pointer_value(f) - print ' if (strcmp("%s", (const char *)procName) == 0) {' % f.name - print ' %s = (%s)procPtr;' % (pvalue, ptype) - print ' return (__GLXextFuncPtr)&%s;' % (f.name,) - print ' }' - print ' os::log("apitrace: warning: unknown function \\"%s\\"\\n", (const char *)procName);' - print ' return procPtr;' - print '}' - print - print r''' - - -/* - * 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); -} - - -/* - * Several applications, such as Quake3, use dlopen("libGL.so.1"), but - * LD_PRELOAD does not intercept symbols obtained via dlopen/dlsym, therefore - * we need to intercept the dlopen() call here, and redirect to our wrapper - * shared object. - */ -extern "C" PUBLIC -void * dlopen(const char *filename, int flag) -{ - void *handle; - - handle = __dlopen(filename, flag); - - const char * libgl_filename = getenv("TRACE_LIBGL"); - - if (filename && handle && !libgl_filename) { - if (0) { - os::log("apitrace: warning: dlopen(\"%s\", 0x%x)\n", filename, flag); - } - - // FIXME: handle absolute paths and other versions - if (strcmp(filename, "libGL.so") == 0 || - strcmp(filename, "libGL.so.1") == 0) { - - // Use the true libGL.so handle instead of RTLD_NEXT from now on - __libGlHandle = handle; - - // Get the file path for our shared object, and use it instead - static int dummy = 0xdeedbeef; - Dl_info info; - if (dladdr(&dummy, &info)) { - os::log("apitrace: redirecting dlopen(\"%s\", 0x%x)\n", filename, flag); - handle = __dlopen(info.dli_fname, flag); - } else { - os::log("apitrace: warning: dladdr() failed\n"); - } - } - } - - return handle; -} - - - -''' diff --git a/specs/d3d10.def b/specs/d3d10.def deleted file mode 100644 index 5482ab5..0000000 --- a/specs/d3d10.def +++ /dev/null @@ -1,6 +0,0 @@ -LIBRARY "d3d10" - -EXPORTS - D3D10CreateDevice - D3D10CreateDeviceAndSwapChain - D3D10CreateBlob diff --git a/specs/d3d10_1.def b/specs/d3d10_1.def deleted file mode 100644 index 48bfe14..0000000 --- a/specs/d3d10_1.def +++ /dev/null @@ -1,6 +0,0 @@ -LIBRARY "d3d10_1" - -EXPORTS - D3D10CreateDevice1 - D3D10CreateDeviceAndSwapChain1 - D3D10CreateBlob diff --git a/specs/d3d11.def b/specs/d3d11.def deleted file mode 100644 index 2da8fc2..0000000 --- a/specs/d3d11.def +++ /dev/null @@ -1,5 +0,0 @@ -LIBRARY "d3d11" - -EXPORTS - D3D11CreateDevice - D3D11CreateDeviceAndSwapChain diff --git a/specs/d3d8.def b/specs/d3d8.def deleted file mode 100644 index 5134cb8..0000000 --- a/specs/d3d8.def +++ /dev/null @@ -1,4 +0,0 @@ -LIBRARY "d3d8" - -EXPORTS - Direct3DCreate8 @1 diff --git a/specs/d3d9.def b/specs/d3d9.def deleted file mode 100644 index dbbb029..0000000 --- a/specs/d3d9.def +++ /dev/null @@ -1,12 +0,0 @@ -LIBRARY "d3d9" - -EXPORTS - Direct3DCreate9 - Direct3DCreate9Ex - D3DPERF_BeginEvent - D3DPERF_EndEvent - D3DPERF_SetMarker - D3DPERF_SetRegion - D3DPERF_QueryRepeatFrame - D3DPERF_SetOptions - D3DPERF_GetStatus diff --git a/specs/ddraw.def b/specs/ddraw.def deleted file mode 100644 index 6186c60..0000000 --- a/specs/ddraw.def +++ /dev/null @@ -1,23 +0,0 @@ -EXPORTS - AcquireDDThreadLock - CompleteCreateSysmemSurface - D3DParseUnknownCommand - DDGetAttachedSurfaceLcl - DDInternalLock - DDInternalUnlock - DirectDrawCreate - DirectDrawCreateClipper - DirectDrawCreateEx - DirectDrawEnumerateA - DirectDrawEnumerateExA - DirectDrawEnumerateExW - DirectDrawEnumerateW - DllCanUnloadNow PRIVATE - DllGetClassObject PRIVATE - DSoundHelp - GetDDSurfaceLocal - GetOLEThunkData - GetSurfaceFromDC - RegisterSpecialCase - ReleaseDDThreadLock - ;SetAppCompatData diff --git a/specs/opengl32.def b/specs/opengl32.def deleted file mode 100644 index 9e717a7..0000000 --- a/specs/opengl32.def +++ /dev/null @@ -1,371 +0,0 @@ -LIBRARY opengl32 - -EXPORTS -; GlmfBeginGlsBlock -; GlmfCloseMetaFile -; GlmfEndGlsBlock -; GlmfEndPlayback -; GlmfInitPlayback -; GlmfPlayGlsRecord - glAccum - glAlphaFunc - glAreTexturesResident - glArrayElement - glBegin - glBindTexture - glBitmap - glBlendFunc - glCallList - glCallLists - glClear - glClearAccum - glClearColor - glClearDepth - glClearIndex - glClearStencil - glClipPlane - glColor3b - glColor3bv - glColor3d - glColor3dv - glColor3f - glColor3fv - glColor3i - glColor3iv - glColor3s - glColor3sv - glColor3ub - glColor3ubv - glColor3ui - glColor3uiv - glColor3us - glColor3usv - glColor4b - glColor4bv - glColor4d - glColor4dv - glColor4f - glColor4fv - glColor4i - glColor4iv - glColor4s - glColor4sv - glColor4ub - glColor4ubv - glColor4ui - glColor4uiv - glColor4us - glColor4usv - glColorMask - glColorMaterial - glColorPointer - glCopyPixels - glCopyTexImage1D - glCopyTexImage2D - glCopyTexSubImage1D - glCopyTexSubImage2D - glCullFace -; glDebugEntry - glDeleteLists - glDeleteTextures - glDepthFunc - glDepthMask - glDepthRange - glDisable - glDisableClientState - glDrawArrays - glDrawBuffer - glDrawElements - glDrawPixels - glEdgeFlag - glEdgeFlagPointer - glEdgeFlagv - glEnable - glEnableClientState - glEnd - glEndList - glEvalCoord1d - glEvalCoord1dv - glEvalCoord1f - glEvalCoord1fv - glEvalCoord2d - glEvalCoord2dv - glEvalCoord2f - glEvalCoord2fv - glEvalMesh1 - glEvalMesh2 - glEvalPoint1 - glEvalPoint2 - glFeedbackBuffer - glFinish - glFlush - glFogf - glFogfv - glFogi - glFogiv - glFrontFace - glFrustum - glGenLists - glGenTextures - glGetBooleanv - glGetClipPlane - glGetDoublev - glGetError - glGetFloatv - glGetIntegerv - glGetLightfv - glGetLightiv - glGetMapdv - glGetMapfv - glGetMapiv - glGetMaterialfv - glGetMaterialiv - glGetPixelMapfv - glGetPixelMapuiv - glGetPixelMapusv - glGetPointerv - glGetPolygonStipple - glGetString - glGetTexEnvfv - glGetTexEnviv - glGetTexGendv - glGetTexGenfv - glGetTexGeniv - glGetTexImage - glGetTexLevelParameterfv - glGetTexLevelParameteriv - glGetTexParameterfv - glGetTexParameteriv - glHint - glIndexMask - glIndexPointer - glIndexd - glIndexdv - glIndexf - glIndexfv - glIndexi - glIndexiv - glIndexs - glIndexsv - glIndexub - glIndexubv - glInitNames - glInterleavedArrays - glIsEnabled - glIsList - glIsTexture - glLightModelf - glLightModelfv - glLightModeli - glLightModeliv - glLightf - glLightfv - glLighti - glLightiv - glLineStipple - glLineWidth - glListBase - glLoadIdentity - glLoadMatrixd - glLoadMatrixf - glLoadName - glLogicOp - glMap1d - glMap1f - glMap2d - glMap2f - glMapGrid1d - glMapGrid1f - glMapGrid2d - glMapGrid2f - glMaterialf - glMaterialfv - glMateriali - glMaterialiv - glMatrixMode - glMultMatrixd - glMultMatrixf - glNewList - glNormal3b - glNormal3bv - glNormal3d - glNormal3dv - glNormal3f - glNormal3fv - glNormal3i - glNormal3iv - glNormal3s - glNormal3sv - glNormalPointer - glOrtho - glPassThrough - glPixelMapfv - glPixelMapuiv - glPixelMapusv - glPixelStoref - glPixelStorei - glPixelTransferf - glPixelTransferi - glPixelZoom - glPointSize - glPolygonMode - glPolygonOffset - glPolygonStipple - glPopAttrib - glPopClientAttrib - glPopMatrix - glPopName - glPrioritizeTextures - glPushAttrib - glPushClientAttrib - glPushMatrix - glPushName - glRasterPos2d - glRasterPos2dv - glRasterPos2f - glRasterPos2fv - glRasterPos2i - glRasterPos2iv - glRasterPos2s - glRasterPos2sv - glRasterPos3d - glRasterPos3dv - glRasterPos3f - glRasterPos3fv - glRasterPos3i - glRasterPos3iv - glRasterPos3s - glRasterPos3sv - glRasterPos4d - glRasterPos4dv - glRasterPos4f - glRasterPos4fv - glRasterPos4i - glRasterPos4iv - glRasterPos4s - glRasterPos4sv - glReadBuffer - glReadPixels - glRectd - glRectdv - glRectf - glRectfv - glRecti - glRectiv - glRects - glRectsv - glRenderMode - glRotated - glRotatef - glScaled - glScalef - glScissor - glSelectBuffer - glShadeModel - glStencilFunc - glStencilMask - glStencilOp - glTexCoord1d - glTexCoord1dv - glTexCoord1f - glTexCoord1fv - glTexCoord1i - glTexCoord1iv - glTexCoord1s - glTexCoord1sv - glTexCoord2d - glTexCoord2dv - glTexCoord2f - glTexCoord2fv - glTexCoord2i - glTexCoord2iv - glTexCoord2s - glTexCoord2sv - glTexCoord3d - glTexCoord3dv - glTexCoord3f - glTexCoord3fv - glTexCoord3i - glTexCoord3iv - glTexCoord3s - glTexCoord3sv - glTexCoord4d - glTexCoord4dv - glTexCoord4f - glTexCoord4fv - glTexCoord4i - glTexCoord4iv - glTexCoord4s - glTexCoord4sv - glTexCoordPointer - glTexEnvf - glTexEnvfv - glTexEnvi - glTexEnviv - glTexGend - glTexGendv - glTexGenf - glTexGenfv - glTexGeni - glTexGeniv - glTexImage1D - glTexImage2D - glTexParameterf - glTexParameterfv - glTexParameteri - glTexParameteriv - glTexSubImage1D - glTexSubImage2D - glTranslated - glTranslatef - glVertex2d - glVertex2dv - glVertex2f - glVertex2fv - glVertex2i - glVertex2iv - glVertex2s - glVertex2sv - glVertex3d - glVertex3dv - glVertex3f - glVertex3fv - glVertex3i - glVertex3iv - glVertex3s - glVertex3sv - glVertex4d - glVertex4dv - glVertex4f - glVertex4fv - glVertex4i - glVertex4iv - glVertex4s - glVertex4sv - glVertexPointer - glViewport - wglChoosePixelFormat - wglCopyContext - wglCreateContext - wglCreateLayerContext - wglDeleteContext - wglDescribeLayerPlane - wglDescribePixelFormat - wglGetCurrentContext - wglGetCurrentDC - wglGetDefaultProcAddress - wglGetLayerPaletteEntries - wglGetPixelFormat - wglGetProcAddress - wglMakeCurrent - wglRealizeLayerPalette - wglSetLayerPaletteEntries - wglSetPixelFormat - wglShareLists - wglSwapBuffers - wglSwapLayerBuffers - wglSwapMultipleBuffers - wglUseFontBitmapsA - wglUseFontBitmapsW - wglUseFontOutlinesA - wglUseFontOutlinesW diff --git a/trace.py b/trace.py deleted file mode 100644 index 4d6d974..0000000 --- a/trace.py +++ /dev/null @@ -1,607 +0,0 @@ -########################################################################## -# -# Copyright 2008-2010 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. -# -##########################################################################/ - -"""Common trace code generation.""" - - -import specs.stdapi as stdapi - - -def getWrapperInterfaceName(interface): - return "Wrap" + interface.expr - - -class ComplexValueSerializer(stdapi.OnceVisitor): - '''Type visitors which generates serialization functions for - complex types. - - Simple types are serialized inline. - ''' - - def __init__(self, serializer): - stdapi.OnceVisitor.__init__(self) - self.serializer = serializer - - def visitVoid(self, literal): - pass - - def visitLiteral(self, literal): - pass - - def visitString(self, string): - pass - - def visitConst(self, const): - self.visit(const.type) - - def visitStruct(self, struct): - for type, name in struct.members: - self.visit(type) - print 'static void _write__%s(const %s &value) {' % (struct.tag, struct.expr) - print ' static const char * members[%u] = {' % (len(struct.members),) - for type, name, in struct.members: - print ' "%s",' % (name,) - print ' };' - print ' static const trace::StructSig sig = {' - print ' %u, "%s", %u, members' % (struct.id, struct.name, len(struct.members)) - print ' };' - print ' trace::localWriter.beginStruct(&sig);' - for type, name in struct.members: - self.serializer.visit(type, 'value.%s' % (name,)) - print ' trace::localWriter.endStruct();' - print '}' - print - - def visitArray(self, array): - self.visit(array.type) - - def visitBlob(self, array): - pass - - def visitEnum(self, enum): - print 'static const trace::EnumValue __enum%s_values[] = {' % (enum.tag) - for value in enum.values: - print ' {"%s", %s},' % (value, value) - print '};' - print - print 'static const trace::EnumSig __enum%s_sig = {' % (enum.tag) - print ' %u, %u, __enum%s_values' % (enum.id, len(enum.values), enum.tag) - print '};' - print - - def visitBitmask(self, bitmask): - print 'static const trace::BitmaskFlag __bitmask%s_flags[] = {' % (bitmask.tag) - for value in bitmask.values: - print ' {"%s", %s},' % (value, value) - print '};' - print - print 'static const trace::BitmaskSig __bitmask%s_sig = {' % (bitmask.tag) - print ' %u, %u, __bitmask%s_flags' % (bitmask.id, len(bitmask.values), bitmask.tag) - print '};' - print - - def visitPointer(self, pointer): - self.visit(pointer.type) - - def visitIntPointer(self, pointer): - pass - - def visitObjPointer(self, pointer): - self.visit(pointer.type) - - def visitLinearPointer(self, pointer): - self.visit(pointer.type) - - def visitHandle(self, handle): - self.visit(handle.type) - - def visitReference(self, reference): - self.visit(reference.type) - - def visitAlias(self, alias): - self.visit(alias.type) - - def visitOpaque(self, opaque): - pass - - def visitInterface(self, interface): - pass - - def visitPolymorphic(self, polymorphic): - print 'static void _write__%s(int selector, const %s & value) {' % (polymorphic.tag, polymorphic.expr) - print ' switch (selector) {' - for cases, type in polymorphic.iterSwitch(): - for case in cases: - print ' %s:' % case - self.serializer.visit(type, 'static_cast<%s>(value)' % (type,)) - print ' break;' - print ' }' - print '}' - print - - -class ValueSerializer(stdapi.Visitor): - '''Visitor which generates code to serialize any type. - - Simple types are serialized inline here, whereas the serialization of - complex types is dispatched to the serialization functions generated by - ComplexValueSerializer visitor above. - ''' - - def visitLiteral(self, literal, instance): - print ' trace::localWriter.write%s(%s);' % (literal.kind, instance) - - def visitString(self, string, instance): - if string.kind == 'String': - cast = 'const char *' - elif string.kind == 'WString': - cast = 'const wchar_t *' - else: - assert False - if cast != string.expr: - # reinterpret_cast is necessary for GLubyte * <=> char * - instance = 'reinterpret_cast<%s>(%s)' % (cast, instance) - if string.length is not None: - length = ', %s' % string.length - else: - length = '' - print ' trace::localWriter.write%s(%s%s);' % (string.kind, instance, length) - - def visitConst(self, const, instance): - self.visit(const.type, instance) - - def visitStruct(self, struct, instance): - print ' _write__%s(%s);' % (struct.tag, instance) - - def visitArray(self, array, instance): - length = '__c' + array.type.tag - index = '__i' + array.type.tag - print ' if (%s) {' % instance - print ' size_t %s = %s;' % (length, array.length) - print ' trace::localWriter.beginArray(%s);' % length - print ' for (size_t %s = 0; %s < %s; ++%s) {' % (index, index, length, index) - print ' trace::localWriter.beginElement();' - self.visit(array.type, '(%s)[%s]' % (instance, index)) - print ' trace::localWriter.endElement();' - print ' }' - print ' trace::localWriter.endArray();' - print ' } else {' - print ' trace::localWriter.writeNull();' - print ' }' - - def visitBlob(self, blob, instance): - print ' trace::localWriter.writeBlob(%s, %s);' % (instance, blob.size) - - def visitEnum(self, enum, instance): - print ' trace::localWriter.writeEnum(&__enum%s_sig, %s);' % (enum.tag, instance) - - def visitBitmask(self, bitmask, instance): - print ' trace::localWriter.writeBitmask(&__bitmask%s_sig, %s);' % (bitmask.tag, instance) - - def visitPointer(self, pointer, instance): - print ' if (%s) {' % instance - print ' trace::localWriter.beginArray(1);' - print ' trace::localWriter.beginElement();' - self.visit(pointer.type, "*" + instance) - print ' trace::localWriter.endElement();' - print ' trace::localWriter.endArray();' - print ' } else {' - print ' trace::localWriter.writeNull();' - print ' }' - - def visitIntPointer(self, pointer, instance): - print ' trace::localWriter.writeOpaque((const void *)%s);' % instance - - def visitObjPointer(self, pointer, instance): - print ' trace::localWriter.writeOpaque((const void *)%s);' % instance - - def visitLinearPointer(self, pointer, instance): - print ' trace::localWriter.writeOpaque((const void *)%s);' % instance - - def visitReference(self, reference, instance): - self.visit(reference.type, instance) - - def visitHandle(self, handle, instance): - self.visit(handle.type, instance) - - def visitAlias(self, alias, instance): - self.visit(alias.type, instance) - - def visitOpaque(self, opaque, instance): - print ' trace::localWriter.writeOpaque((const void *)%s);' % instance - - def visitInterface(self, interface, instance): - print ' trace::localWriter.writeOpaque((const void *)&%s);' % instance - - def visitPolymorphic(self, polymorphic, instance): - print ' _write__%s(%s, %s);' % (polymorphic.tag, polymorphic.switchExpr, instance) - - -class ValueWrapper(stdapi.Visitor): - '''Type visitor which will generate the code to wrap an instance. - - Wrapping is necessary mostly for interfaces, however interface pointers can - appear anywhere inside complex types. - ''' - - def visitVoid(self, type, instance): - raise NotImplementedError - - def visitLiteral(self, type, instance): - pass - - def visitString(self, type, instance): - pass - - def visitConst(self, type, instance): - pass - - def visitStruct(self, struct, instance): - for type, name in struct.members: - self.visit(type, "(%s).%s" % (instance, name)) - - def visitArray(self, array, instance): - # XXX: actually it is possible to return an array of pointers - pass - - def visitBlob(self, blob, instance): - pass - - def visitEnum(self, enum, instance): - pass - - def visitBitmask(self, bitmask, instance): - pass - - def visitPointer(self, pointer, instance): - print " if (%s) {" % instance - self.visit(pointer.type, "*" + instance) - print " }" - - def visitIntPointer(self, pointer, instance): - pass - - def visitObjPointer(self, pointer, instance): - print " if (%s) {" % instance - self.visit(pointer.type, "*" + instance) - print " }" - - def visitLinearPointer(self, pointer, instance): - pass - - def visitReference(self, reference, instance): - self.visit(reference.type, instance) - - def visitHandle(self, handle, instance): - self.visit(handle.type, instance) - - def visitAlias(self, alias, instance): - self.visit(alias.type, instance) - - def visitOpaque(self, opaque, instance): - pass - - def visitInterface(self, interface, instance): - assert instance.startswith('*') - instance = instance[1:] - print " if (%s) {" % instance - print " %s = new %s(%s);" % (instance, getWrapperInterfaceName(interface), instance) - print " }" - - def visitPolymorphic(self, type, instance): - # XXX: There might be polymorphic values that need wrapping in the future - pass - - -class ValueUnwrapper(ValueWrapper): - '''Reverse of ValueWrapper.''' - - def visitInterface(self, interface, instance): - assert instance.startswith('*') - instance = instance[1:] - print r' if (%s) {' % instance - print r' %s *pWrapper = static_cast<%s*>(%s);' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), instance) - print r' if (pWrapper && pWrapper->m_dwMagic == 0xd8365d6c) {' - print r' %s = pWrapper->m_pInstance;' % (instance,) - print r' } else {' - print r' os::log("apitrace: warning: %%s: unexpected %%s pointer\n", __FUNCTION__, "%s");' % interface.name - print r' }' - print r' }' - - -class Tracer: - '''Base class to orchestrate the code generation of API tracing.''' - - def __init__(self): - self.api = None - - def serializerFactory(self): - '''Create a serializer. - - Can be overriden by derived classes to inject their own serialzer. - ''' - - return ValueSerializer() - - def trace_api(self, api): - self.api = api - - self.header(api) - - # Includes - for header in api.headers: - print header - print - - # Generate the serializer functions - types = api.getAllTypes() - visitor = ComplexValueSerializer(self.serializerFactory()) - map(visitor.visit, types) - print - - # Interfaces wrapers - interfaces = api.getAllInterfaces() - map(self.declareWrapperInterface, interfaces) - map(self.implementWrapperInterface, interfaces) - print - - # Function wrappers - map(self.traceFunctionDecl, api.functions) - map(self.traceFunctionImpl, api.functions) - print - - self.footer(api) - - def header(self, api): - pass - - def footer(self, api): - pass - - def traceFunctionDecl(self, function): - # Per-function declarations - - if function.args: - print 'static const char * __%s_args[%u] = {%s};' % (function.name, len(function.args), ', '.join(['"%s"' % arg.name for arg in function.args])) - else: - print 'static const char ** __%s_args = NULL;' % (function.name,) - print 'static const trace::FunctionSig __%s_sig = {%u, "%s", %u, __%s_args};' % (function.name, function.id, function.name, len(function.args), function.name) - print - - def isFunctionPublic(self, function): - return True - - def traceFunctionImpl(self, function): - if self.isFunctionPublic(function): - print 'extern "C" PUBLIC' - else: - print 'extern "C" PRIVATE' - print function.prototype() + ' {' - if function.type is not stdapi.Void: - print ' %s __result;' % function.type - self.traceFunctionImplBody(function) - if function.type is not stdapi.Void: - self.wrapRet(function, "__result") - print ' return __result;' - print '}' - print - - def traceFunctionImplBody(self, function): - print ' unsigned __call = trace::localWriter.beginEnter(&__%s_sig);' % (function.name,) - for arg in function.args: - if not arg.output: - self.unwrapArg(function, arg) - self.serializeArg(function, arg) - print ' trace::localWriter.endEnter();' - self.invokeFunction(function) - print ' trace::localWriter.beginLeave(__call);' - for arg in function.args: - if arg.output: - self.serializeArg(function, arg) - self.wrapArg(function, arg) - if function.type is not stdapi.Void: - self.serializeRet(function, "__result") - print ' trace::localWriter.endLeave();' - - def invokeFunction(self, function, prefix='__', suffix=''): - if function.type is stdapi.Void: - result = '' - else: - result = '__result = ' - dispatch = prefix + function.name + suffix - print ' %s%s(%s);' % (result, dispatch, ', '.join([str(arg.name) for arg in function.args])) - - def serializeArg(self, function, arg): - print ' trace::localWriter.beginArg(%u);' % (arg.index,) - self.serializeArgValue(function, arg) - print ' trace::localWriter.endArg();' - - def serializeArgValue(self, function, arg): - self.serializeValue(arg.type, arg.name) - - def wrapArg(self, function, arg): - self.wrapValue(arg.type, arg.name) - - def unwrapArg(self, function, arg): - self.unwrapValue(arg.type, arg.name) - - def serializeRet(self, function, instance): - print ' trace::localWriter.beginReturn();' - self.serializeValue(function.type, instance) - print ' trace::localWriter.endReturn();' - - def serializeValue(self, type, instance): - serializer = self.serializerFactory() - serializer.visit(type, instance) - - def wrapRet(self, function, instance): - self.wrapValue(function.type, instance) - - def unwrapRet(self, function, instance): - self.unwrapValue(function.type, instance) - - def wrapValue(self, type, instance): - visitor = ValueWrapper() - visitor.visit(type, instance) - - def unwrapValue(self, type, instance): - visitor = ValueUnwrapper() - visitor.visit(type, instance) - - def declareWrapperInterface(self, interface): - print "class %s : public %s " % (getWrapperInterfaceName(interface), interface.name) - print "{" - print "public:" - print " %s(%s * pInstance);" % (getWrapperInterfaceName(interface), interface.name) - print " virtual ~%s();" % getWrapperInterfaceName(interface) - print - for method in interface.iterMethods(): - print " " + method.prototype() + ";" - print - self.declareWrapperInterfaceVariables(interface) - print "};" - print - - def declareWrapperInterfaceVariables(self, interface): - #print "private:" - print " DWORD m_dwMagic;" - print " %s * m_pInstance;" % (interface.name,) - - def implementWrapperInterface(self, interface): - print '%s::%s(%s * pInstance) {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), interface.name) - print ' m_dwMagic = 0xd8365d6c;' - print ' m_pInstance = pInstance;' - print '}' - print - print '%s::~%s() {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface)) - print '}' - print - for base, method in interface.iterBaseMethods(): - self.implementWrapperInterfaceMethod(interface, base, method) - print - - def implementWrapperInterfaceMethod(self, interface, base, method): - print method.prototype(getWrapperInterfaceName(interface) + '::' + method.name) + ' {' - if method.type is not stdapi.Void: - print ' %s __result;' % method.type - - self.implementWrapperInterfaceMethodBody(interface, base, method) - - if method.type is not stdapi.Void: - print ' return __result;' - print '}' - print - - def implementWrapperInterfaceMethodBody(self, interface, base, method): - print ' static const char * __args[%u] = {%s};' % (len(method.args) + 1, ', '.join(['"this"'] + ['"%s"' % arg.name for arg in method.args])) - print ' static const trace::FunctionSig __sig = {%u, "%s", %u, __args};' % (method.id, interface.name + '::' + method.name, len(method.args) + 1) - print ' unsigned __call = trace::localWriter.beginEnter(&__sig);' - print ' trace::localWriter.beginArg(0);' - print ' trace::localWriter.writeOpaque((const void *)m_pInstance);' - print ' trace::localWriter.endArg();' - - from specs.winapi import REFIID - from specs.stdapi import Pointer, Opaque, Interface - - riid = None - for arg in method.args: - if not arg.output: - self.unwrapArg(method, arg) - self.serializeArg(method, arg) - if arg.type is REFIID: - riid = arg - print ' trace::localWriter.endEnter();' - - self.invokeMethod(interface, base, method) - - print ' trace::localWriter.beginLeave(__call);' - for arg in method.args: - if arg.output: - self.serializeArg(method, arg) - self.wrapArg(method, arg) - if riid is not None and isinstance(arg.type, Pointer): - if isinstance(arg.type.type, Opaque): - self.wrapIid(interface, method, riid, arg) - else: - assert isinstance(arg.type.type, Pointer) - assert isinstance(arg.type.type.type, Interface) - - if method.type is not stdapi.Void: - print ' trace::localWriter.beginReturn();' - self.serializeValue(method.type, "__result") - print ' trace::localWriter.endReturn();' - self.wrapValue(method.type, '__result') - print ' trace::localWriter.endLeave();' - if method.name == 'Release': - assert method.type is not stdapi.Void - print ' if (!__result)' - print ' delete this;' - - def wrapIid(self, interface, method, riid, out): - print ' if (%s && *%s) {' % (out.name, out.name) - print ' if (*%s == m_pInstance) {' % (out.name,) - print ' *%s = this;' % (out.name,) - print ' }' - for iface in self.api.getAllInterfaces(): - print r' else if (%s == IID_%s) {' % (riid.name, iface.name) - print r' *%s = new Wrap%s((%s *) *%s);' % (out.name, iface.name, iface.name, out.name) - print r' }' - print r' else {' - print r' os::log("apitrace: warning: %s::%s: unknown IID {0x%08lX,0x%04X,0x%04X,{0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,0x%02X}}\n",' - print r' "%s", "%s",' % (interface.name, method.name) - print r' %s.Data1, %s.Data2, %s.Data3,' % (riid.name, riid.name, riid.name) - print r' %s.Data4[0],' % (riid.name,) - print r' %s.Data4[1],' % (riid.name,) - print r' %s.Data4[2],' % (riid.name,) - print r' %s.Data4[3],' % (riid.name,) - print r' %s.Data4[4],' % (riid.name,) - print r' %s.Data4[5],' % (riid.name,) - print r' %s.Data4[6],' % (riid.name,) - print r' %s.Data4[7]);' % (riid.name,) - print r' }' - print ' }' - - def invokeMethod(self, interface, base, method): - if method.type is stdapi.Void: - result = '' - else: - result = '__result = ' - print ' %sstatic_cast<%s *>(m_pInstance)->%s(%s);' % (result, base, method.name, ', '.join([str(arg.name) for arg in method.args])) - - def emit_memcpy(self, dest, src, length): - print ' unsigned __call = trace::localWriter.beginEnter(&trace::memcpy_sig);' - print ' trace::localWriter.beginArg(0);' - print ' trace::localWriter.writeOpaque(%s);' % dest - print ' trace::localWriter.endArg();' - print ' trace::localWriter.beginArg(1);' - print ' trace::localWriter.writeBlob(%s, %s);' % (src, length) - print ' trace::localWriter.endArg();' - print ' trace::localWriter.beginArg(2);' - print ' trace::localWriter.writeUInt(%s);' % length - print ' trace::localWriter.endArg();' - print ' trace::localWriter.endEnter();' - print ' trace::localWriter.beginLeave(__call);' - print ' trace::localWriter.endLeave();' - diff --git a/wgltrace.py b/wgltrace.py deleted file mode 100644 index 4dfd0f4..0000000 --- a/wgltrace.py +++ /dev/null @@ -1,83 +0,0 @@ -########################################################################## -# -# 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. -# -##########################################################################/ - - -"""WGL tracing code generator.""" - - -from specs.stdapi import API -from specs.glapi import glapi -from specs.wglapi import wglapi -from dispatch import function_pointer_type, function_pointer_value -from gltrace import GlTracer -from codegen import * - - -class WglTracer(GlTracer): - - def wrapRet(self, function, instance): - GlTracer.wrapRet(self, function, instance) - - if function.name == "wglGetProcAddress": - print ' if (%s) {' % instance - - func_dict = dict([(f.name, f) for f in glapi.functions + wglapi.functions]) - - def handle_case(function_name): - f = func_dict[function_name] - ptype = function_pointer_type(f) - pvalue = function_pointer_value(f) - print ' %s = (%s)%s;' % (pvalue, ptype, instance) - print ' %s = (%s)&%s;' % (instance, function.type, f.name); - - def handle_default(): - print ' os::log("apitrace: warning: unknown function \\"%s\\"\\n", lpszProc);' - - string_switch('lpszProc', func_dict.keys(), handle_case, handle_default) - print ' }' - - -if __name__ == '__main__': - print - print '#define _GDI32_' - print - print '#include ' - print '#include ' - print - print '#include "trace_writer_local.hpp"' - print '#include "os.hpp"' - print - print '// To validate our prototypes' - print '#define GL_GLEXT_PROTOTYPES' - print '#define WGL_GLXEXT_PROTOTYPES' - print - print '#include "glproc.hpp"' - print '#include "glsize.hpp"' - print - api = API() - api.addApi(glapi) - api.addApi(wglapi) - tracer = WglTracer() - tracer.trace_api(api) diff --git a/wrappers/.gitignore b/wrappers/.gitignore new file mode 100644 index 0000000..8ba6fb8 --- /dev/null +++ b/wrappers/.gitignore @@ -0,0 +1,13 @@ +cgltrace.cpp +d3d10_1trace.cpp +d3d10trace.cpp +d3d11trace.cpp +d3d8trace.cpp +d3d9trace.cpp +ddrawtrace.cpp +dlltrace.cpp +egltrace.cpp +gltrace.cpp +glxtrace.cpp +trace.cpp +wgltrace.cpp diff --git a/wrappers/CMakeLists.txt b/wrappers/CMakeLists.txt new file mode 100644 index 0000000..d47dc6d --- /dev/null +++ b/wrappers/CMakeLists.txt @@ -0,0 +1,348 @@ +############################################################################## +# API tracers + + +include_directories (${CMAKE_CURRENT_SOURCE_DIR}) + + +if (WIN32) + if (MINGW) + # Silence warnings about @nn suffix mismatch + set (CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,--enable-stdcall-fixup") + endif () + + # ddraw.dll + if (DirectX_D3D_INCLUDE_DIR) + include_directories (SYSTEM ${DirectX_D3D_INCLUDE_DIR}) + add_custom_command ( + OUTPUT ddrawtrace.cpp + COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/ddrawtrace.py > ${CMAKE_CURRENT_BINARY_DIR}/ddrawtrace.cpp + DEPENDS + ddrawtrace.py + trace.py + ${CMAKE_SOURCE_DIR}/specs/d3d.py + ${CMAKE_SOURCE_DIR}/specs/d3dtypes.py + ${CMAKE_SOURCE_DIR}/specs/d3dcaps.py + ${CMAKE_SOURCE_DIR}/specs/ddraw.py + ${CMAKE_SOURCE_DIR}/specs/winapi.py + ${CMAKE_SOURCE_DIR}/specs/stdapi.py + ) + add_library (ddraw MODULE ddraw.def ddrawtrace.cpp) + target_link_libraries (ddraw + common + ${ZLIB_LIBRARIES} + ${SNAPPY_LIBRARIES} + ) + set_target_properties (ddraw + PROPERTIES PREFIX "" + ) + install (TARGETS ddraw LIBRARY DESTINATION ${WRAPPER_INSTALL_DIR}) + endif () + + # d3d8.dll + if (DirectX_D3D8_INCLUDE_DIR AND DirectX_D3DX9_INCLUDE_DIR) + include_directories (SYSTEM ${DirectX_D3D8_INCLUDE_DIR} ${DirectX_D3DX9_INCLUDE_DIR}) + add_custom_command ( + OUTPUT d3d8trace.cpp + COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/d3d8trace.py > ${CMAKE_CURRENT_BINARY_DIR}/d3d8trace.cpp + DEPENDS + d3d8trace.py + trace.py + ${CMAKE_SOURCE_DIR}/specs/d3d8.py + ${CMAKE_SOURCE_DIR}/specs/d3d8types.py + ${CMAKE_SOURCE_DIR}/specs/d3d8caps.py + ${CMAKE_SOURCE_DIR}/specs/winapi.py + ${CMAKE_SOURCE_DIR}/specs/stdapi.py + ) + add_library (d3d8 MODULE d3d8.def d3d8trace.cpp d3dshader.cpp) + target_link_libraries (d3d8 + common + ${ZLIB_LIBRARIES} + ${SNAPPY_LIBRARIES} + ) + set_target_properties (d3d8 + PROPERTIES PREFIX "" + ) + install (TARGETS d3d8 LIBRARY DESTINATION ${WRAPPER_INSTALL_DIR}) + endif () + + # d3d9.dll + if (DirectX_D3DX9_INCLUDE_DIR) + include_directories (SYSTEM ${DirectX_D3DX9_INCLUDE_DIR}) + add_custom_command ( + OUTPUT d3d9trace.cpp + COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/d3d9trace.py > ${CMAKE_CURRENT_BINARY_DIR}/d3d9trace.cpp + DEPENDS + d3d9trace.py + trace.py + ${CMAKE_SOURCE_DIR}/specs/d3d9.py + ${CMAKE_SOURCE_DIR}/specs/d3d9types.py + ${CMAKE_SOURCE_DIR}/specs/d3d9caps.py + ${CMAKE_SOURCE_DIR}/specs/winapi.py + ${CMAKE_SOURCE_DIR}/specs/stdapi.py + ) + add_library (d3d9 MODULE d3d9.def d3d9trace.cpp d3dshader.cpp) + target_link_libraries (d3d9 + common + ${ZLIB_LIBRARIES} + ${SNAPPY_LIBRARIES} + ) + set_target_properties (d3d9 + PROPERTIES PREFIX "" + ) + install (TARGETS d3d9 LIBRARY DESTINATION ${WRAPPER_INSTALL_DIR}) + endif () + + # d3d10.dll + if (DirectX_D3DX10_INCLUDE_DIR) + include_directories (SYSTEM ${DirectX_D3DX10_INCLUDE_DIR}) + add_custom_command ( + OUTPUT d3d10trace.cpp + COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/d3d10trace.py > ${CMAKE_CURRENT_BINARY_DIR}/d3d10trace.cpp + DEPENDS + d3d10trace.py + trace.py + ${CMAKE_SOURCE_DIR}/specs/d3d10misc.py + ${CMAKE_SOURCE_DIR}/specs/d3d10.py + ${CMAKE_SOURCE_DIR}/specs/d3d10sdklayers.py + ${CMAKE_SOURCE_DIR}/specs/d3dcommon.py + ${CMAKE_SOURCE_DIR}/specs/dxgi.py + ${CMAKE_SOURCE_DIR}/specs/dxgitype.py + ${CMAKE_SOURCE_DIR}/specs/dxgiformat.py + ${CMAKE_SOURCE_DIR}/specs/winapi.py + ${CMAKE_SOURCE_DIR}/specs/stdapi.py + ) + add_library (d3d10 MODULE d3d10.def d3d10trace.cpp) + target_link_libraries (d3d10 + common + ${ZLIB_LIBRARIES} + ${SNAPPY_LIBRARIES} + ) + set_target_properties (d3d10 + PROPERTIES PREFIX "" + ) + install (TARGETS d3d10 LIBRARY DESTINATION ${WRAPPER_INSTALL_DIR}) + endif () + + # d3d10_1.dll + if (DirectX_D3DX10_INCLUDE_DIR AND DirectX_D3D10_1_INCLUDE_DIR) + include_directories (SYSTEM ${DirectX_D3D10_1_INCLUDE_DIR}) + add_custom_command ( + OUTPUT d3d10_1trace.cpp + COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/d3d10_1trace.py > ${CMAKE_CURRENT_BINARY_DIR}/d3d10_1trace.cpp + DEPENDS + d3d10_1trace.py + trace.py + ${CMAKE_SOURCE_DIR}/specs/d3d10_1.py + ${CMAKE_SOURCE_DIR}/specs/d3d10.py + ${CMAKE_SOURCE_DIR}/specs/d3d10sdklayers.py + ${CMAKE_SOURCE_DIR}/specs/d3dcommon.py + ${CMAKE_SOURCE_DIR}/specs/dxgi.py + ${CMAKE_SOURCE_DIR}/specs/dxgitype.py + ${CMAKE_SOURCE_DIR}/specs/dxgiformat.py + ${CMAKE_SOURCE_DIR}/specs/winapi.py + ${CMAKE_SOURCE_DIR}/specs/stdapi.py + ) + add_library (d3d10_1 MODULE d3d10_1.def d3d10_1trace.cpp) + target_link_libraries (d3d10_1 + common + ${ZLIB_LIBRARIES} + ${SNAPPY_LIBRARIES} + ) + set_target_properties (d3d10_1 + PROPERTIES PREFIX "" + ) + install (TARGETS d3d10_1 LIBRARY DESTINATION ${WRAPPER_INSTALL_DIR}) + endif () + + # d3d11.dll + if (DirectX_D3DX11_INCLUDE_DIR) + include_directories (SYSTEM ${DirectX_D3DX11_INCLUDE_DIR}) + add_custom_command ( + OUTPUT d3d11trace.cpp + COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/d3d11trace.py > ${CMAKE_CURRENT_BINARY_DIR}/d3d11trace.cpp + DEPENDS + d3d11trace.py + trace.py + ${CMAKE_SOURCE_DIR}/specs/d3d11.py + ${CMAKE_SOURCE_DIR}/specs/d3d11sdklayers.py + ${CMAKE_SOURCE_DIR}/specs/d3dcommon.py + ${CMAKE_SOURCE_DIR}/specs/dxgi.py + ${CMAKE_SOURCE_DIR}/specs/dxgitype.py + ${CMAKE_SOURCE_DIR}/specs/dxgiformat.py + ${CMAKE_SOURCE_DIR}/specs/winapi.py + ${CMAKE_SOURCE_DIR}/specs/stdapi.py + ) + add_library (d3d11 MODULE d3d11.def d3d11trace.cpp) + target_link_libraries (d3d11 + common + ${ZLIB_LIBRARIES} + ${SNAPPY_LIBRARIES} + ) + set_target_properties (d3d11 + PROPERTIES PREFIX "" + ) + install (TARGETS d3d11 LIBRARY DESTINATION ${WRAPPER_INSTALL_DIR}) + endif () + + # opengl32.dll + add_custom_command ( + OUTPUT wgltrace.cpp + COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/wgltrace.py > ${CMAKE_CURRENT_BINARY_DIR}/wgltrace.cpp + DEPENDS + wgltrace.py + gltrace.py + trace.py + ${CMAKE_SOURCE_DIR}/specs/wglapi.py + ${CMAKE_SOURCE_DIR}/specs/wglenum.py + ${CMAKE_SOURCE_DIR}/specs/glapi.py + ${CMAKE_SOURCE_DIR}/specs/glparams.py + ${CMAKE_SOURCE_DIR}/specs/gltypes.py + ${CMAKE_SOURCE_DIR}/specs/winapi.py + ${CMAKE_SOURCE_DIR}/specs/stdapi.py + ) + add_library (wgltrace MODULE opengl32.def + wgltrace.cpp + glcaps.cpp + ${CMAKE_SOURCE_DIR}/glproc_gl.cpp + ) + add_dependencies (wgltrace glproc) + target_link_libraries (wgltrace + common + ${ZLIB_LIBRARIES} + ${SNAPPY_LIBRARIES} + ) + set_target_properties (wgltrace PROPERTIES + PREFIX "" + OUTPUT_NAME opengl32 + ) + install (TARGETS wgltrace LIBRARY DESTINATION ${WRAPPER_INSTALL_DIR}) + +elseif (APPLE) + # 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 + ${CMAKE_SOURCE_DIR}/specs/cglapi.py + ${CMAKE_SOURCE_DIR}/specs/glapi.py + ${CMAKE_SOURCE_DIR}/specs/glparams.py + ${CMAKE_SOURCE_DIR}/specs/gltypes.py + ${CMAKE_SOURCE_DIR}/specs/stdapi.py + ) + + add_library (cgltrace SHARED + cgltrace.cpp + glcaps.cpp + ${CMAKE_SOURCE_DIR}/glproc_gl.cpp + ) + + add_dependencies (cgltrace glproc) + + set_target_properties (cgltrace PROPERTIES + # OpenGL framework name + 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" + ) + + target_link_libraries (cgltrace + common + ${ZLIB_LIBRARIES} + ${SNAPPY_LIBRARIES} + ${CMAKE_THREAD_LIBS_INIT} + dl + ) + + install (TARGETS cgltrace LIBRARY DESTINATION ${WRAPPER_INSTALL_DIR}) +elseif (X11_FOUND) + # libGL.so + add_custom_command ( + OUTPUT glxtrace.cpp + COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/glxtrace.py > ${CMAKE_CURRENT_BINARY_DIR}/glxtrace.cpp + DEPENDS + glxtrace.py + gltrace.py + trace.py + ${CMAKE_SOURCE_DIR}/specs/glxapi.py + ${CMAKE_SOURCE_DIR}/specs/glapi.py + ${CMAKE_SOURCE_DIR}/specs/glparams.py + ${CMAKE_SOURCE_DIR}/specs/gltypes.py + ${CMAKE_SOURCE_DIR}/specs/stdapi.py + ) + + add_library (glxtrace SHARED + glxtrace.cpp + glcaps.cpp + ${CMAKE_SOURCE_DIR}/glproc_gl.cpp + ) + + add_dependencies (glxtrace glproc) + + set_target_properties (glxtrace PROPERTIES + # avoid the default "lib" prefix + PREFIX "" + # Prevent symbol relocations internal to our wrapper library to be + # overwritten by the application. + LINK_FLAGS "-Wl,-Bsymbolic -Wl,-Bsymbolic-functions" + ) + + target_link_libraries (glxtrace + common + ${ZLIB_LIBRARIES} + ${SNAPPY_LIBRARIES} + ${X11_X11_LIB} + ${CMAKE_THREAD_LIBS_INIT} + dl + ) + + install (TARGETS glxtrace LIBRARY DESTINATION ${WRAPPER_INSTALL_DIR}) +endif () + + +if (ENABLE_EGL AND NOT WIN32 AND NOT APPLE) + # libEGL.so/libGL.so + add_custom_command ( + OUTPUT egltrace.cpp + COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/egltrace.py > ${CMAKE_CURRENT_BINARY_DIR}/egltrace.cpp + DEPENDS + egltrace.py + gltrace.py + trace.py + ${CMAKE_SOURCE_DIR}/specs/eglapi.py + ${CMAKE_SOURCE_DIR}/specs/glesapi.py + ${CMAKE_SOURCE_DIR}/specs/glapi.py + ${CMAKE_SOURCE_DIR}/specs/glparams.py + ${CMAKE_SOURCE_DIR}/specs/gltypes.py + ${CMAKE_SOURCE_DIR}/specs/stdapi.py + ) + + add_library (egltrace SHARED + egltrace.cpp + glcaps.cpp + ${CMAKE_SOURCE_DIR}/glproc_egl.cpp + ) + + add_dependencies (egltrace glproc) + + set_target_properties (egltrace PROPERTIES + # avoid the default "lib" prefix + PREFIX "" + # Prevent symbol relocations internal to our wrapper library to be + # overwritten by the application. + LINK_FLAGS "-Wl,-Bsymbolic -Wl,-Bsymbolic-functions" + ) + + target_link_libraries (egltrace + common + ${ZLIB_LIBRARIES} + ${SNAPPY_LIBRARIES} + ${CMAKE_THREAD_LIBS_INIT} + dl + ) + + install (TARGETS egltrace LIBRARY DESTINATION ${WRAPPER_INSTALL_DIR}) +endif () diff --git a/wrappers/cgltrace.py b/wrappers/cgltrace.py new file mode 100644 index 0000000..ea2267c --- /dev/null +++ b/wrappers/cgltrace.py @@ -0,0 +1,68 @@ +########################################################################## +# +# 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 gltrace import GlTracer +from specs.stdapi import API +from specs.glapi import glapi +from specs.cglapi import cglapi + + +class CglTracer(GlTracer): + + def isFunctionPublic(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 '#include "trace_writer_local.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.addApi(cglapi) + api.addApi(glapi) + tracer = CglTracer() + tracer.trace_api(api) + + print r''' + +PUBLIC +void * gll_noop = 0; + +''' diff --git a/wrappers/d3d10.def b/wrappers/d3d10.def new file mode 100644 index 0000000..5482ab5 --- /dev/null +++ b/wrappers/d3d10.def @@ -0,0 +1,6 @@ +LIBRARY "d3d10" + +EXPORTS + D3D10CreateDevice + D3D10CreateDeviceAndSwapChain + D3D10CreateBlob diff --git a/wrappers/d3d10_1.def b/wrappers/d3d10_1.def new file mode 100644 index 0000000..48bfe14 --- /dev/null +++ b/wrappers/d3d10_1.def @@ -0,0 +1,6 @@ +LIBRARY "d3d10_1" + +EXPORTS + D3D10CreateDevice1 + D3D10CreateDeviceAndSwapChain1 + D3D10CreateBlob diff --git a/wrappers/d3d10_1trace.py b/wrappers/d3d10_1trace.py new file mode 100644 index 0000000..1a4443b --- /dev/null +++ b/wrappers/d3d10_1trace.py @@ -0,0 +1,46 @@ +########################################################################## +# +# 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. +# +##########################################################################/ + + +from dlltrace import DllTracer +from specs.d3d10_1 import d3d10_1 + + +if __name__ == '__main__': + print '#define INITGUID' + print + print '#include "trace_writer_local.hpp"' + print '#include "os.hpp"' + print + print '#include ' + print '#include ' + print + print '#include "compat.h"' + print + print '#include ' + print '#include ' + print + tracer = DllTracer('d3d10_1.dll') + tracer.trace_api(d3d10_1) diff --git a/wrappers/d3d10trace.py b/wrappers/d3d10trace.py new file mode 100644 index 0000000..1d65769 --- /dev/null +++ b/wrappers/d3d10trace.py @@ -0,0 +1,46 @@ +########################################################################## +# +# 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. +# +##########################################################################/ + + +from dlltrace import DllTracer +from specs.d3d10misc import d3d10 + + +if __name__ == '__main__': + print '#define INITGUID' + print + print '#include "trace_writer_local.hpp"' + print '#include "os.hpp"' + print + print '#include ' + print '#include ' + print + print '#include "compat.h"' + print + print '#include ' + print '#include ' + print + tracer = DllTracer('d3d10.dll') + tracer.trace_api(d3d10) diff --git a/wrappers/d3d11.def b/wrappers/d3d11.def new file mode 100644 index 0000000..2da8fc2 --- /dev/null +++ b/wrappers/d3d11.def @@ -0,0 +1,5 @@ +LIBRARY "d3d11" + +EXPORTS + D3D11CreateDevice + D3D11CreateDeviceAndSwapChain diff --git a/wrappers/d3d11trace.py b/wrappers/d3d11trace.py new file mode 100644 index 0000000..a4ccd6b --- /dev/null +++ b/wrappers/d3d11trace.py @@ -0,0 +1,46 @@ +########################################################################## +# +# Copyright 2008-2012 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. +# +##########################################################################/ + + +from dlltrace import DllTracer +from specs.d3d11 import d3d11 + + +if __name__ == '__main__': + print '#define INITGUID' + print + print '#include "trace_writer_local.hpp"' + print '#include "os.hpp"' + print + print '#include ' + print '#include ' + print + print '#include "compat.h"' + print + print '#include ' + print '#include ' + print + tracer = DllTracer('d3d11.dll') + tracer.trace_api(d3d11) diff --git a/wrappers/d3d8.def b/wrappers/d3d8.def new file mode 100644 index 0000000..5134cb8 --- /dev/null +++ b/wrappers/d3d8.def @@ -0,0 +1,4 @@ +LIBRARY "d3d8" + +EXPORTS + Direct3DCreate8 @1 diff --git a/wrappers/d3d8trace.py b/wrappers/d3d8trace.py new file mode 100644 index 0000000..09377cb --- /dev/null +++ b/wrappers/d3d8trace.py @@ -0,0 +1,54 @@ +########################################################################## +# +# 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. +# +##########################################################################/ + + +from dlltrace import DllTracer +from specs.d3d8 import d3d8 + + +class D3D8Tracer(DllTracer): + + def serializeArgValue(self, function, arg): + # Dump shaders as strings + if function.name in ('CreateVertexShader', 'CreatePixelShader') and arg.name == 'pFunction': + print ' DumpShader(trace::localWriter, %s);' % (arg.name) + return + + DllTracer.serializeArgValue(self, function, arg) + + +if __name__ == '__main__': + print '#define INITGUID' + print + print '#include ' + print '#include ' + print '#include "d3dshader.hpp"' + print + print '#include "trace_writer_local.hpp"' + print '#include "os.hpp"' + print + tracer = D3D8Tracer('d3d8.dll') + tracer.trace_api(d3d8) + diff --git a/wrappers/d3d9.def b/wrappers/d3d9.def new file mode 100644 index 0000000..dbbb029 --- /dev/null +++ b/wrappers/d3d9.def @@ -0,0 +1,12 @@ +LIBRARY "d3d9" + +EXPORTS + Direct3DCreate9 + Direct3DCreate9Ex + D3DPERF_BeginEvent + D3DPERF_EndEvent + D3DPERF_SetMarker + D3DPERF_SetRegion + D3DPERF_QueryRepeatFrame + D3DPERF_SetOptions + D3DPERF_GetStatus diff --git a/wrappers/d3d9trace.py b/wrappers/d3d9trace.py new file mode 100644 index 0000000..4f40194 --- /dev/null +++ b/wrappers/d3d9trace.py @@ -0,0 +1,94 @@ +########################################################################## +# +# 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. +# +##########################################################################/ + + +from dlltrace import DllTracer +from specs.d3d9 import d3d9 + + +class D3D9Tracer(DllTracer): + + def serializeArgValue(self, function, arg): + # Dump shaders as strings + if function.name in ('CreateVertexShader', 'CreatePixelShader') and arg.name == 'pFunction': + print ' DumpShader(trace::localWriter, %s);' % (arg.name) + return + + DllTracer.serializeArgValue(self, function, arg) + + def declareWrapperInterfaceVariables(self, interface): + DllTracer.declareWrapperInterfaceVariables(self, interface) + + if interface.name == 'IDirect3DVertexBuffer9': + print ' UINT m_SizeToLock;' + print ' VOID *m_pbData;' + + def implementWrapperInterfaceMethodBody(self, interface, base, method): + if interface.name == 'IDirect3DVertexBuffer9' and method.name == 'Unlock': + print ' if (m_pbData) {' + self.emit_memcpy('(LPBYTE)m_pbData', '(LPBYTE)m_pbData', 'm_SizeToLock') + print ' }' + + DllTracer.implementWrapperInterfaceMethodBody(self, interface, base, method) + + if interface.name == 'IDirect3DVertexBuffer9' and method.name == 'Lock': + # FIXME: handle recursive locks + print ' if (__result == D3D_OK && !(Flags & D3DLOCK_READONLY)) {' + print ' if (SizeToLock) {' + print ' m_SizeToLock = SizeToLock;' + print ' } else {' + print ' D3DVERTEXBUFFER_DESC Desc;' + print ' m_pInstance->GetDesc(&Desc);' + print ' m_SizeToLock = Desc.Size;' + print ' }' + print ' m_pbData = *ppbData;' + print ' } else {' + print ' m_pbData = NULL;' + print ' }' + + +if __name__ == '__main__': + print '#define INITGUID' + print + print '#include "trace_writer_local.hpp"' + print '#include "os.hpp"' + print + print '#include "d3d9imports.hpp"' + print '#include "d3dshader.hpp"' + print + print ''' +static inline size_t +_declCount(const D3DVERTEXELEMENT9 *pVertexElements) { + size_t count = 0; + if (pVertexElements) { + while (pVertexElements[count++].Stream != 0xff) + ; + } + return count; +} +''' + tracer = D3D9Tracer('d3d9.dll') + tracer.trace_api(d3d9) + diff --git a/wrappers/d3dshader.cpp b/wrappers/d3dshader.cpp new file mode 100644 index 0000000..a2d5c12 --- /dev/null +++ b/wrappers/d3dshader.cpp @@ -0,0 +1,96 @@ +/************************************************************************** + * + * Copyright 2011 Jose Fonseca + * 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. + * + **************************************************************************/ + + +#include + +#include "d3dshader.hpp" +#include "d3d9imports.hpp" + + +typedef HRESULT +(WINAPI *PD3DXDISASSEMBLESHADER)( + CONST DWORD *pShader, + BOOL EnableColorCode, + LPCSTR pComments, + LPD3DXBUFFER *ppDisassembly +); + + +void DumpShader(trace::Writer &writer, const DWORD *tokens) +{ + static BOOL firsttime = TRUE; + static HMODULE hD3DXModule = NULL; + static PD3DXDISASSEMBLESHADER pfnD3DXDisassembleShader = NULL; + + if (firsttime) { + if (!hD3DXModule) { + unsigned release; + int version; + for (release = 0; release <= 1; ++release) { + /* Version 41 corresponds to Mar 2009 version of DirectX Runtime / SDK */ + for (version = 41; version >= 0; --version) { + char filename[256]; + _snprintf(filename, sizeof(filename), + "d3dx9%s%s%u.dll", release ? "" : "d", version ? "_" : "", version); + hD3DXModule = LoadLibraryA(filename); + if (hD3DXModule) + goto found; + } + } +found: + ; + } + + if (hD3DXModule) { + if (!pfnD3DXDisassembleShader) { + pfnD3DXDisassembleShader = (PD3DXDISASSEMBLESHADER)GetProcAddress(hD3DXModule, "D3DXDisassembleShader"); + } + } + + firsttime = FALSE; + } + + if (pfnD3DXDisassembleShader) { + LPD3DXBUFFER pDisassembly = NULL; + HRESULT hr; + + hr = pfnD3DXDisassembleShader( (DWORD *)tokens, FALSE, NULL, &pDisassembly); + if (hr == D3D_OK) { + writer.writeString((const char *)pDisassembly->GetBufferPointer()); + } + + if (pDisassembly) { + pDisassembly->Release(); + } + + if (hr == D3D_OK) { + return; + } + } + + writer.writeOpaque(tokens); +} diff --git a/wrappers/d3dshader.hpp b/wrappers/d3dshader.hpp new file mode 100644 index 0000000..485df05 --- /dev/null +++ b/wrappers/d3dshader.hpp @@ -0,0 +1,38 @@ +/************************************************************************** + * + * Copyright 2011 Jose Fonseca + * 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. + * + **************************************************************************/ + +#ifndef _D3DSHADER_HPP_ +#define _D3DSHADER_HPP_ + + +#include + +#include "trace_writer.hpp" + +void DumpShader(trace::Writer &writer, const DWORD *tokens); + + +#endif /* _D3DSHADER_HPP_ */ diff --git a/wrappers/ddraw.def b/wrappers/ddraw.def new file mode 100644 index 0000000..6186c60 --- /dev/null +++ b/wrappers/ddraw.def @@ -0,0 +1,23 @@ +EXPORTS + AcquireDDThreadLock + CompleteCreateSysmemSurface + D3DParseUnknownCommand + DDGetAttachedSurfaceLcl + DDInternalLock + DDInternalUnlock + DirectDrawCreate + DirectDrawCreateClipper + DirectDrawCreateEx + DirectDrawEnumerateA + DirectDrawEnumerateExA + DirectDrawEnumerateExW + DirectDrawEnumerateW + DllCanUnloadNow PRIVATE + DllGetClassObject PRIVATE + DSoundHelp + GetDDSurfaceLocal + GetOLEThunkData + GetSurfaceFromDC + RegisterSpecialCase + ReleaseDDThreadLock + ;SetAppCompatData diff --git a/wrappers/ddrawtrace.py b/wrappers/ddrawtrace.py new file mode 100644 index 0000000..e640f40 --- /dev/null +++ b/wrappers/ddrawtrace.py @@ -0,0 +1,81 @@ +########################################################################## +# +# 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. +# +##########################################################################/ + + +from dlltrace import DllTracer +from specs.d3d import ddraw, interfaces + + +class DDrawTracer(DllTracer): + + def traceFunctionImplBody(self, function): + if function.name in ('AcquireDDThreadLock', 'ReleaseDDThreadLock'): + self.invokeFunction(function) + return + + DllTracer.traceFunctionImplBody(self, function) + + def serializeArg(self, function, arg): + if function.name == 'DirectDrawCreateEx' and arg.name == 'lplpDD': + print ' if (*lplpDD) {' + for iface in interfaces: + print ' if (iid == IID_%s) {' % iface.name + print ' *lplpDD = (LPVOID) new Wrap%s((%s *)*lplpDD);' % (iface.name, iface.name) + print ' }' + print ' }' + + DllTracer.serializeArg(self, function, arg) + + +if __name__ == '__main__': + print '#define INITGUID' + print '#include ' + print '#include ' + print '#include ' + print + print ''' + +#ifndef DDBLT_EXTENDED_FLAGS +#define DDBLT_EXTENDED_FLAGS 0x40000000l +#endif + +#ifndef DDBLT_EXTENDED_LINEAR_CONTENT +#define DDBLT_EXTENDED_LINEAR_CONTENT 0x00000004l +#endif + +#ifndef D3DLIGHT_PARALLELPOINT +#define D3DLIGHT_PARALLELPOINT (D3DLIGHTTYPE)4 +#endif + +#ifndef D3DLIGHT_GLSPOT +#define D3DLIGHT_GLSPOT (D3DLIGHTTYPE)5 +#endif + +''' + print '#include "trace_writer_local.hpp"' + print '#include "os.hpp"' + print + tracer = DDrawTracer('ddraw.dll') + tracer.trace_api(ddraw) diff --git a/wrappers/dlltrace.py b/wrappers/dlltrace.py new file mode 100644 index 0000000..3912dd0 --- /dev/null +++ b/wrappers/dlltrace.py @@ -0,0 +1,69 @@ +########################################################################## +# +# Copyright 2008-2010 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. +# +##########################################################################/ + +"""Trace code generation for Windows DLLs.""" + + +from trace import Tracer +from dispatch import Dispatcher + + +class DllTracer(Tracer): + + def __init__(self, dllname): + self.dllname = dllname + + def header(self, api): + print ''' +static HINSTANCE g_hDll = NULL; + +static PROC +__getPublicProcAddress(LPCSTR lpProcName) +{ + if (!g_hDll) { + char szDll[MAX_PATH] = {0}; + + if (!GetSystemDirectoryA(szDll, MAX_PATH)) { + return NULL; + } + + strcat(szDll, "\\\\%s"); + + g_hDll = LoadLibraryA(szDll); + if (!g_hDll) { + return NULL; + } + } + + return GetProcAddress(g_hDll, lpProcName); +} + +''' % self.dllname + + dispatcher = Dispatcher() + dispatcher.dispatch_api(api) + + Tracer.header(self, api) + diff --git a/wrappers/egltrace.py b/wrappers/egltrace.py new file mode 100644 index 0000000..65c14ef --- /dev/null +++ b/wrappers/egltrace.py @@ -0,0 +1,199 @@ +########################################################################## +# +# Copyright 2011 LunarG, Inc. +# All Rights Reserved. +# +# Based on glxtrace.py, which has +# +# Copyright 2011 Jose Fonseca +# Copyright 2008-2010 VMware, Inc. +# +# 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. +# +##########################################################################/ + + +"""EGL tracing generator.""" + + +from gltrace import GlTracer +from dispatch import function_pointer_type, function_pointer_value +from specs.stdapi import API +from specs.glapi import glapi +from specs.eglapi import eglapi +from specs.glesapi import glesapi + + +class EglTracer(GlTracer): + + def isFunctionPublic(self, function): + # The symbols visible in libEGL.so can vary, so expose them all + return True + + def traceFunctionImplBody(self, function): + GlTracer.traceFunctionImplBody(self, function) + + if function.name == 'eglMakeCurrent': + print ' // update the profile' + print ' if (ctx != EGL_NO_CONTEXT) {' + print ' EGLint api = EGL_OPENGL_ES_API, version = 1;' + print ' gltrace::Context *tr = gltrace::getContext();' + print ' __eglQueryContext(dpy, ctx, EGL_CONTEXT_CLIENT_TYPE, &api);' + print ' __eglQueryContext(dpy, ctx, EGL_CONTEXT_CLIENT_VERSION, &version);' + print ' if (api == EGL_OPENGL_API)' + print ' tr->profile = gltrace::PROFILE_COMPAT;' + print ' else if (version == 1)' + print ' tr->profile = gltrace::PROFILE_ES1;' + print ' else' + print ' tr->profile = gltrace::PROFILE_ES2;' + print ' }' + + def wrapRet(self, function, instance): + GlTracer.wrapRet(self, function, instance) + + if function.name == "eglGetProcAddress": + print ' %s = __unwrap_proc_addr(procname, %s);' % (instance, instance) + + +if __name__ == '__main__': + print '#include ' + print '#include ' + print '#include ' + print + print '#include "trace_writer_local.hpp"' + print + print '// To validate our prototypes' + print '#define GL_GLEXT_PROTOTYPES' + print '#define EGL_EGLEXT_PROTOTYPES' + print + print '#include "glproc.hpp"' + print '#include "glsize.hpp"' + print + print 'static __eglMustCastToProperFunctionPointerType __unwrap_proc_addr(const char * procname, __eglMustCastToProperFunctionPointerType procPtr);' + print + + api = API() + api.addApi(eglapi) + api.addApi(glapi) + api.addApi(glesapi) + tracer = EglTracer() + tracer.trace_api(api) + + print 'static __eglMustCastToProperFunctionPointerType __unwrap_proc_addr(const char * procname, __eglMustCastToProperFunctionPointerType procPtr) {' + print ' if (!procPtr) {' + print ' return procPtr;' + print ' }' + for f in api.functions: + ptype = function_pointer_type(f) + pvalue = function_pointer_value(f) + print ' if (!strcmp("%s", procname)) {' % f.name + print ' %s = (%s)procPtr;' % (pvalue, ptype) + print ' return (__eglMustCastToProperFunctionPointerType)&%s;' % (f.name,) + print ' }' + print ' os::log("apitrace: warning: unknown function \\"%s\\"\\n", procname);' + print ' return procPtr;' + print '}' + print + print r''' + + +/* + * Android does not support LD_PRELOAD. + */ +#if !defined(ANDROID) + + +/* + * 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); +} + + +/* + * Several applications, such as Quake3, use dlopen("libGL.so.1"), but + * LD_PRELOAD does not intercept symbols obtained via dlopen/dlsym, therefore + * we need to intercept the dlopen() call here, and redirect to our wrapper + * shared object. + */ +extern "C" PUBLIC +void * dlopen(const char *filename, int flag) +{ + bool intercept = false; + + if (filename) { + intercept = + strcmp(filename, "libEGL.so") == 0 || + strcmp(filename, "libEGL.so.1") == 0 || + strcmp(filename, "libGLESv1_CM.so") == 0 || + strcmp(filename, "libGLESv1_CM.so.1") == 0 || + strcmp(filename, "libGLESv2.so") == 0 || + strcmp(filename, "libGLESv2.so.2") == 0 || + strcmp(filename, "libGL.so") == 0 || + strcmp(filename, "libGL.so.1") == 0; + + if (intercept) { + os::log("apitrace: redirecting dlopen(\"%s\", 0x%x)\n", filename, flag); + + /* The current dispatch implementation relies on core entry-points to be globally available, so force this. + * + * TODO: A better approach would be note down the entry points here and + * use them latter. Another alternative would be to reopen the library + * with RTLD_NOLOAD | RTLD_GLOBAL. + */ + flag &= ~RTLD_LOCAL; + flag |= RTLD_GLOBAL; + } + } + + void *handle = __dlopen(filename, flag); + + if (intercept) { + // Get the file path for our shared object, and use it instead + static int dummy = 0xdeedbeef; + Dl_info info; + if (dladdr(&dummy, &info)) { + handle = __dlopen(info.dli_fname, flag); + } else { + os::log("apitrace: warning: dladdr() failed\n"); + } + } + + return handle; +} + + +#endif /* !ANDROID */ + + + +''' diff --git a/wrappers/glcaps.cpp b/wrappers/glcaps.cpp new file mode 100644 index 0000000..f6f70f3 --- /dev/null +++ b/wrappers/glcaps.cpp @@ -0,0 +1,226 @@ +/************************************************************************** + * + * 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. + * + **************************************************************************/ + + +/* + * Manipulation of GL extensions. + * + * So far we insert GREMEDY extensions, but in the future we could also clamp + * the GL extensions to core GL versions here. + */ + + +#include +#include +#include + +#include +#include + +#include "glproc.hpp" +#include "gltrace.hpp" + + +namespace gltrace { + + +typedef std::map ExtensionsMap; + +// Cache of the translated extensions strings +static ExtensionsMap extensionsMap; + + +// Additional extensions to be advertised +static const char * +extraExtension_stringsFull[] = { + "GL_GREMEDY_string_marker", + "GL_GREMEDY_frame_terminator", +}; + +static const char * +extraExtension_stringsES[] = { + "GL_EXT_debug_marker", +}; + +// Description of additional extensions we want to advertise +struct ExtensionsDesc +{ + unsigned numStrings; + const char **strings; +}; + +#define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0])) + +const struct ExtensionsDesc +extraExtensionsFull = { + ARRAY_SIZE(extraExtension_stringsFull), + extraExtension_stringsFull +}; + +const struct ExtensionsDesc +extraExtensionsES = { + ARRAY_SIZE(extraExtension_stringsES), + extraExtension_stringsES +}; + + +const struct ExtensionsDesc * +getExtraExtensions(void) +{ + Context *ctx = getContext(); + + switch (ctx->profile) { + case PROFILE_COMPAT: + return &extraExtensionsFull; + case PROFILE_ES1: + case PROFILE_ES2: + return &extraExtensionsES; + default: + assert(0); + return &extraExtensionsFull; + } +} + + +/** + * Translate the GL extensions string, adding new extensions. + */ +static const char * +overrideExtensionsString(const char *extensions) +{ + const ExtensionsDesc *desc = getExtraExtensions(); + size_t i; + + ExtensionsMap::const_iterator it = extensionsMap.find(extensions); + if (it != extensionsMap.end()) { + return it->second; + } + + size_t extensionsLen = strlen(extensions); + + size_t extraExtensionsLen = 0; + for (i = 0; i < desc->numStrings; ++i) { + const char * extraExtension = desc->strings[i]; + size_t extraExtensionLen = strlen(extraExtension); + extraExtensionsLen += extraExtensionLen + 1; + } + + // We use malloc memory instead of a std::string because we need to ensure + // that extensions strings will not move in memory as the extensionsMap is + // updated. + size_t newExtensionsLen = extensionsLen + 1 + extraExtensionsLen + 1; + char *newExtensions = (char *)malloc(newExtensionsLen); + if (!newExtensions) { + return extensions; + } + + if (extensionsLen) { + memcpy(newExtensions, extensions, extensionsLen); + + // Add space separator if necessary + if (newExtensions[extensionsLen - 1] != ' ') { + newExtensions[extensionsLen++] = ' '; + } + } + + for (i = 0; i < desc->numStrings; ++i) { + const char * extraExtension = desc->strings[i]; + size_t extraExtensionLen = strlen(extraExtension); + memcpy(newExtensions + extensionsLen, extraExtension, extraExtensionLen); + extensionsLen += extraExtensionLen; + newExtensions[extensionsLen++] = ' '; + } + newExtensions[extensionsLen++] = '\0'; + assert(extensionsLen <= newExtensionsLen); + + extensionsMap[extensions] = newExtensions; + + return newExtensions; +} + + +const GLubyte * +__glGetString_override(GLenum name) +{ + const GLubyte *result = __glGetString(name); + + if (result) { + switch (name) { + case GL_EXTENSIONS: + result = (const GLubyte *)overrideExtensionsString((const char *)result); + break; + default: + break; + } + } + + return result; +} + + +void +__glGetIntegerv_override(GLenum pname, GLint *params) +{ + __glGetIntegerv(pname, params); + + if (params) { + switch (pname) { + case GL_NUM_EXTENSIONS: + { + const ExtensionsDesc *desc = getExtraExtensions(); + *params += desc->numStrings; + } + break; + default: + break; + } + } +} + + +const GLubyte * +__glGetStringi_override(GLenum name, GLuint index) +{ + switch (name) { + case GL_EXTENSIONS: + { + const ExtensionsDesc *desc = getExtraExtensions(); + GLint numExtensions = 0; + __glGetIntegerv(GL_NUM_EXTENSIONS, &numExtensions); + if ((GLuint)numExtensions <= index && index < (GLuint)numExtensions + desc->numStrings) { + return (const GLubyte *)desc->strings[index - (GLuint)numExtensions]; + } + } + break; + default: + break; + } + + return __glGetStringi(name, index); +} + + +} /* namespace gltrace */ + diff --git a/wrappers/gltrace.hpp b/wrappers/gltrace.hpp new file mode 100644 index 0000000..e4fefc3 --- /dev/null +++ b/wrappers/gltrace.hpp @@ -0,0 +1,65 @@ +/************************************************************************** + * + * 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. + * + **************************************************************************/ + +#ifndef _GLTRACE_HPP_ +#define _GLTRACE_HPP_ + + +#include "glimports.hpp" + + +namespace gltrace { + + +enum Profile { + PROFILE_COMPAT, + PROFILE_ES1, + PROFILE_ES2, +}; + +struct Context { + enum Profile profile; + bool user_arrays; + bool user_arrays_arb; + bool user_arrays_nv; +}; + +Context * +getContext(void); + +const GLubyte * +__glGetString_override(GLenum name); + +void +__glGetIntegerv_override(GLenum pname, GLint *params); + +const GLubyte * +__glGetStringi_override(GLenum name, GLuint index); + + +} /* namespace gltrace */ + + +#endif /* _GLRETRACE_HPP_ */ diff --git a/wrappers/gltrace.py b/wrappers/gltrace.py new file mode 100644 index 0000000..128568f --- /dev/null +++ b/wrappers/gltrace.py @@ -0,0 +1,1010 @@ +########################################################################## +# +# Copyright 2008-2010 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. +# +##########################################################################/ + + +"""GL tracing generator.""" + + +from trace import Tracer +import specs.stdapi as stdapi +import specs.glapi as glapi +import specs.glparams as glparams +from specs.glxapi import glxapi + + +class TypeGetter(stdapi.Visitor): + '''Determine which glGet*v function that matches the specified type.''' + + def __init__(self, prefix = 'glGet', long_suffix = True, ext_suffix = ''): + self.prefix = prefix + self.long_suffix = long_suffix + self.ext_suffix = ext_suffix + + def visitConst(self, const): + return self.visit(const.type) + + def visitAlias(self, alias): + if alias.expr == 'GLboolean': + if self.long_suffix: + suffix = 'Booleanv' + arg_type = alias.expr + else: + suffix = 'iv' + arg_type = 'GLint' + elif alias.expr == 'GLdouble': + if self.long_suffix: + suffix = 'Doublev' + arg_type = alias.expr + else: + suffix = 'dv' + arg_type = alias.expr + elif alias.expr == 'GLfloat': + if self.long_suffix: + suffix = 'Floatv' + arg_type = alias.expr + else: + suffix = 'fv' + arg_type = alias.expr + elif alias.expr in ('GLint', 'GLuint', 'GLsizei'): + if self.long_suffix: + suffix = 'Integerv' + arg_type = 'GLint' + else: + suffix = 'iv' + arg_type = 'GLint' + else: + print alias.expr + assert False + function_name = self.prefix + suffix + self.ext_suffix + return function_name, arg_type + + def visitEnum(self, enum): + return self.visit(glapi.GLint) + + def visitBitmask(self, bitmask): + return self.visit(glapi.GLint) + + def visitOpaque(self, pointer): + return self.prefix + 'Pointerv' + self.ext_suffix, 'GLvoid *' + + +class GlTracer(Tracer): + + arrays = [ + ("Vertex", "VERTEX"), + ("Normal", "NORMAL"), + ("Color", "COLOR"), + ("Index", "INDEX"), + ("TexCoord", "TEXTURE_COORD"), + ("EdgeFlag", "EDGE_FLAG"), + ("FogCoord", "FOG_COORD"), + ("SecondaryColor", "SECONDARY_COLOR"), + ] + arrays.reverse() + + # arrays available in PROFILE_ES1 + arrays_es1 = ("Vertex", "Normal", "Color", "TexCoord") + + def header(self, api): + Tracer.header(self, api) + + print '#include "gltrace.hpp"' + print + + # Which glVertexAttrib* variant to use + print 'enum vertex_attrib {' + print ' VERTEX_ATTRIB,' + print ' VERTEX_ATTRIB_ARB,' + print ' VERTEX_ATTRIB_NV,' + print '};' + print + print 'gltrace::Context *' + print 'gltrace::getContext(void)' + print '{' + print ' // TODO return the context set by other APIs (GLX, EGL, and etc.)' + print ' static gltrace::Context __ctx = { gltrace::PROFILE_COMPAT, false, false, false };' + print ' return &__ctx;' + print '}' + print + print 'static vertex_attrib __get_vertex_attrib(void) {' + print ' gltrace::Context *ctx = gltrace::getContext();' + print ' if (ctx->user_arrays_arb || ctx->user_arrays_nv) {' + print ' GLboolean __vertex_program = GL_FALSE;' + print ' __glGetBooleanv(GL_VERTEX_PROGRAM_ARB, &__vertex_program);' + print ' if (__vertex_program) {' + print ' if (ctx->user_arrays_nv) {' + print ' GLint __vertex_program_binding_nv = 0;' + print ' __glGetIntegerv(GL_VERTEX_PROGRAM_BINDING_NV, &__vertex_program_binding_nv);' + print ' if (__vertex_program_binding_nv) {' + print ' return VERTEX_ATTRIB_NV;' + print ' }' + print ' }' + print ' return VERTEX_ATTRIB_ARB;' + print ' }' + print ' }' + print ' return VERTEX_ATTRIB;' + print '}' + print + + # Whether we need user arrays + print 'static inline bool __need_user_arrays(void)' + print '{' + print ' gltrace::Context *ctx = gltrace::getContext();' + print ' if (!ctx->user_arrays) {' + print ' return false;' + print ' }' + print + + for camelcase_name, uppercase_name in self.arrays: + # in which profile is the array available? + profile_check = 'ctx->profile == gltrace::PROFILE_COMPAT' + if camelcase_name in self.arrays_es1: + profile_check = '(' + profile_check + ' || ctx->profile == gltrace::PROFILE_ES1)'; + + function_name = 'gl%sPointer' % camelcase_name + enable_name = 'GL_%s_ARRAY' % uppercase_name + binding_name = 'GL_%s_ARRAY_BUFFER_BINDING' % uppercase_name + print ' // %s' % function_name + print ' if (%s) {' % profile_check + self.array_prolog(api, uppercase_name) + print ' if (__glIsEnabled(%s)) {' % enable_name + print ' GLint __binding = 0;' + print ' __glGetIntegerv(%s, &__binding);' % binding_name + print ' if (!__binding) {' + self.array_cleanup(api, uppercase_name) + print ' return true;' + print ' }' + print ' }' + self.array_epilog(api, uppercase_name) + print ' }' + print + + print ' // ES1 does not support generic vertex attributes' + print ' if (ctx->profile == gltrace::PROFILE_ES1)' + print ' return false;' + print + print ' vertex_attrib __vertex_attrib = __get_vertex_attrib();' + print + print ' // glVertexAttribPointer' + print ' if (__vertex_attrib == VERTEX_ATTRIB) {' + print ' GLint __max_vertex_attribs = 0;' + print ' __glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &__max_vertex_attribs);' + print ' for (GLint index = 0; index < __max_vertex_attribs; ++index) {' + print ' GLint __enabled = 0;' + print ' __glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &__enabled);' + print ' if (__enabled) {' + print ' GLint __binding = 0;' + print ' __glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &__binding);' + print ' if (!__binding) {' + print ' return true;' + print ' }' + print ' }' + print ' }' + print ' }' + print + print ' // glVertexAttribPointerARB' + print ' if (__vertex_attrib == VERTEX_ATTRIB_ARB) {' + print ' GLint __max_vertex_attribs = 0;' + print ' __glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &__max_vertex_attribs);' + print ' for (GLint index = 0; index < __max_vertex_attribs; ++index) {' + print ' GLint __enabled = 0;' + print ' __glGetVertexAttribivARB(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB, &__enabled);' + print ' if (__enabled) {' + print ' GLint __binding = 0;' + print ' __glGetVertexAttribivARB(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB, &__binding);' + print ' if (!__binding) {' + print ' return true;' + print ' }' + print ' }' + print ' }' + print ' }' + print + print ' // glVertexAttribPointerNV' + print ' if (__vertex_attrib == VERTEX_ATTRIB_NV) {' + print ' for (GLint index = 0; index < 16; ++index) {' + print ' GLint __enabled = 0;' + print ' __glGetIntegerv(GL_VERTEX_ATTRIB_ARRAY0_NV + index, &__enabled);' + print ' if (__enabled) {' + print ' return true;' + print ' }' + print ' }' + print ' }' + print + + print ' return false;' + print '}' + print + + print 'static void __trace_user_arrays(GLuint maxindex);' + print + + # Buffer mappings + print '// whether glMapBufferRange(GL_MAP_WRITE_BIT) has ever been called' + print 'static bool __checkBufferMapRange = false;' + print + print '// whether glBufferParameteriAPPLE(GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE) has ever been called' + print 'static bool __checkBufferFlushingUnmapAPPLE = false;' + print + # Buffer mapping information, necessary for old Mesa 2.1 drivers which + # do not support glGetBufferParameteriv(GL_BUFFER_ACCESS_FLAGS/GL_BUFFER_MAP_LENGTH) + print 'struct buffer_mapping {' + print ' void *map;' + print ' GLint length;' + print ' bool write;' + print ' bool explicit_flush;' + print '};' + print + for target in self.buffer_targets: + print 'struct buffer_mapping __%s_mapping;' % target.lower(); + print + print 'static inline struct buffer_mapping *' + print 'get_buffer_mapping(GLenum target) {' + print ' switch (target) {' + for target in self.buffer_targets: + print ' case GL_%s:' % target + print ' return & __%s_mapping;' % target.lower() + print ' default:' + print ' os::log("apitrace: warning: unknown buffer target 0x%04X\\n", target);' + print ' return NULL;' + print ' }' + print '}' + print + + # Generate a helper function to determine whether a parameter name + # refers to a symbolic value or not + print 'static bool' + print 'is_symbolic_pname(GLenum pname) {' + print ' switch (pname) {' + for function, type, count, name in glparams.parameters: + if type is glapi.GLenum: + print ' case %s:' % name + print ' return true;' + print ' default:' + print ' return false;' + print ' }' + print '}' + print + + # Generate a helper function to determine whether a parameter value is + # potentially symbolic or not; i.e., if the value can be represented in + # an enum or not + print 'template' + print 'static inline bool' + print 'is_symbolic_param(T param) {' + print ' return static_cast(static_cast(param)) == param;' + print '}' + print + + # Generate a helper function to know how many elements a parameter has + print 'static size_t' + print '__gl_param_size(GLenum pname) {' + print ' switch (pname) {' + for function, type, count, name in glparams.parameters: + if type is not None: + print ' case %s: return %u;' % (name, count) + print ' case GL_COMPRESSED_TEXTURE_FORMATS: {' + print ' GLint num_compressed_texture_formats = 0;' + print ' __glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &num_compressed_texture_formats);' + print ' return num_compressed_texture_formats;' + print ' }' + print ' default:' + print r' os::log("apitrace: warning: %s: unknown GLenum 0x%04X\n", __FUNCTION__, pname);' + print ' return 1;' + print ' }' + print '}' + print + + # states such as GL_UNPACK_ROW_LENGTH are not available in GLES + print 'static inline bool' + print 'can_unpack_subimage(void) {' + print ' gltrace::Context *ctx = gltrace::getContext();' + print ' return (ctx->profile == gltrace::PROFILE_COMPAT);' + print '}' + print + + array_pointer_function_names = set(( + "glVertexPointer", + "glNormalPointer", + "glColorPointer", + "glIndexPointer", + "glTexCoordPointer", + "glEdgeFlagPointer", + "glFogCoordPointer", + "glSecondaryColorPointer", + + "glInterleavedArrays", + + "glVertexPointerEXT", + "glNormalPointerEXT", + "glColorPointerEXT", + "glIndexPointerEXT", + "glTexCoordPointerEXT", + "glEdgeFlagPointerEXT", + "glFogCoordPointerEXT", + "glSecondaryColorPointerEXT", + + "glVertexAttribPointer", + "glVertexAttribPointerARB", + "glVertexAttribPointerNV", + "glVertexAttribIPointer", + "glVertexAttribIPointerEXT", + "glVertexAttribLPointer", + "glVertexAttribLPointerEXT", + + #"glMatrixIndexPointerARB", + )) + + draw_function_names = set(( + 'glDrawArrays', + 'glDrawElements', + 'glDrawRangeElements', + 'glMultiDrawArrays', + 'glMultiDrawElements', + 'glDrawArraysInstanced', + "glDrawArraysInstancedBaseInstance", + 'glDrawElementsInstanced', + 'glDrawArraysInstancedARB', + 'glDrawElementsInstancedARB', + 'glDrawElementsBaseVertex', + 'glDrawRangeElementsBaseVertex', + 'glDrawElementsInstancedBaseVertex', + "glDrawElementsInstancedBaseInstance", + "glDrawElementsInstancedBaseVertexBaseInstance", + 'glMultiDrawElementsBaseVertex', + 'glDrawArraysIndirect', + 'glDrawElementsIndirect', + 'glDrawArraysEXT', + 'glDrawRangeElementsEXT', + 'glDrawRangeElementsEXT_size', + 'glMultiDrawArraysEXT', + 'glMultiDrawElementsEXT', + 'glMultiModeDrawArraysIBM', + 'glMultiModeDrawElementsIBM', + 'glDrawArraysInstancedEXT', + 'glDrawElementsInstancedEXT', + )) + + interleaved_formats = [ + 'GL_V2F', + 'GL_V3F', + 'GL_C4UB_V2F', + 'GL_C4UB_V3F', + 'GL_C3F_V3F', + 'GL_N3F_V3F', + 'GL_C4F_N3F_V3F', + 'GL_T2F_V3F', + 'GL_T4F_V4F', + 'GL_T2F_C4UB_V3F', + 'GL_T2F_C3F_V3F', + 'GL_T2F_N3F_V3F', + 'GL_T2F_C4F_N3F_V3F', + 'GL_T4F_C4F_N3F_V4F', + ] + + def traceFunctionImplBody(self, function): + # Defer tracing of user array pointers... + if function.name in self.array_pointer_function_names: + print ' GLint __array_buffer = 0;' + print ' __glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &__array_buffer);' + print ' if (!__array_buffer) {' + print ' gltrace::Context *ctx = gltrace::getContext();' + print ' ctx->user_arrays = true;' + if function.name == "glVertexAttribPointerARB": + print ' ctx->user_arrays_arb = true;' + if function.name == "glVertexAttribPointerNV": + print ' ctx->user_arrays_nv = true;' + self.invokeFunction(function) + + # And also break down glInterleavedArrays into the individual calls + if function.name == 'glInterleavedArrays': + print + + # Initialize the enable flags + for camelcase_name, uppercase_name in self.arrays: + flag_name = '__' + uppercase_name.lower() + print ' GLboolean %s = GL_FALSE;' % flag_name + print + + # Switch for the interleaved formats + print ' switch (format) {' + for format in self.interleaved_formats: + print ' case %s:' % format + for camelcase_name, uppercase_name in self.arrays: + flag_name = '__' + uppercase_name.lower() + if format.find('_' + uppercase_name[0]) >= 0: + print ' %s = GL_TRUE;' % flag_name + print ' break;' + print ' default:' + print ' return;' + print ' }' + print + + # Emit fake glEnableClientState/glDisableClientState flags + for camelcase_name, uppercase_name in self.arrays: + flag_name = '__' + uppercase_name.lower() + enable_name = 'GL_%s_ARRAY' % uppercase_name + + # Emit a fake function + print ' {' + print ' static const trace::FunctionSig &__sig = %s ? __glEnableClientState_sig : __glDisableClientState_sig;' % flag_name + print ' unsigned __call = trace::localWriter.beginEnter(&__sig);' + print ' trace::localWriter.beginArg(0);' + self.serializeValue(glapi.GLenum, enable_name) + print ' trace::localWriter.endArg();' + print ' trace::localWriter.endEnter();' + print ' trace::localWriter.beginLeave(__call);' + print ' trace::localWriter.endLeave();' + print ' }' + + print ' return;' + print ' }' + + # ... to the draw calls + if function.name in self.draw_function_names: + print ' if (__need_user_arrays()) {' + arg_names = ', '.join([arg.name for arg in function.args[1:]]) + print ' GLuint maxindex = __%s_maxindex(%s);' % (function.name, arg_names) + print ' __trace_user_arrays(maxindex);' + print ' }' + + # Emit a fake memcpy on buffer uploads + if function.name == 'glBufferParameteriAPPLE': + print ' if (pname == GL_BUFFER_FLUSHING_UNMAP_APPLE && param == GL_FALSE) {' + print ' __checkBufferFlushingUnmapAPPLE = true;' + print ' }' + if function.name in ('glUnmapBuffer', 'glUnmapBufferARB'): + if function.name.endswith('ARB'): + suffix = 'ARB' + else: + suffix = '' + print ' GLint access = 0;' + print ' __glGetBufferParameteriv%s(target, GL_BUFFER_ACCESS, &access);' % suffix + print ' if (access != GL_READ_ONLY) {' + print ' GLvoid *map = NULL;' + print ' __glGetBufferPointerv%s(target, GL_BUFFER_MAP_POINTER, &map);' % suffix + print ' if (map) {' + print ' GLint length = -1;' + print ' bool flush = true;' + print ' if (__checkBufferMapRange) {' + print ' __glGetBufferParameteriv%s(target, GL_BUFFER_MAP_LENGTH, &length);' % suffix + print ' GLint access_flags = 0;' + print ' __glGetBufferParameteriv(target, GL_BUFFER_ACCESS_FLAGS, &access_flags);' + print ' flush = flush && !(access_flags & GL_MAP_FLUSH_EXPLICIT_BIT);' + print ' if (length == -1) {' + print ' // Mesa drivers refuse GL_BUFFER_MAP_LENGTH without GL 3.0' + print ' static bool warned = false;' + print ' if (!warned) {' + print ' os::log("apitrace: warning: glGetBufferParameteriv%s(GL_BUFFER_MAP_LENGTH) failed\\n");' % suffix + print ' warned = true;' + print ' }' + print ' struct buffer_mapping *mapping = get_buffer_mapping(target);' + print ' if (mapping) {' + print ' length = mapping->length;' + print ' flush = flush && !mapping->explicit_flush;' + print ' } else {' + print ' length = 0;' + print ' flush = false;' + print ' }' + print ' }' + print ' } else {' + print ' length = 0;' + print ' __glGetBufferParameteriv%s(target, GL_BUFFER_SIZE, &length);' % suffix + print ' }' + print ' if (__checkBufferFlushingUnmapAPPLE) {' + print ' GLint flushing_unmap = GL_TRUE;' + print ' __glGetBufferParameteriv%s(target, GL_BUFFER_FLUSHING_UNMAP_APPLE, &flushing_unmap);' % suffix + print ' flush = flush && flushing_unmap;' + print ' }' + print ' if (flush && length > 0) {' + self.emit_memcpy('map', 'map', 'length') + print ' }' + print ' }' + print ' }' + if function.name == 'glUnmapBufferOES': + print ' GLint access = 0;' + print ' __glGetBufferParameteriv(target, GL_BUFFER_ACCESS_OES, &access);' + print ' if (access == GL_WRITE_ONLY_OES) {' + print ' GLvoid *map = NULL;' + print ' __glGetBufferPointervOES(target, GL_BUFFER_MAP_POINTER_OES, &map);' + print ' GLint size = 0;' + print ' __glGetBufferParameteriv(target, GL_BUFFER_SIZE, &size);' + print ' if (map && size > 0) {' + self.emit_memcpy('map', 'map', 'size') + print ' }' + print ' }' + if function.name == 'glUnmapNamedBufferEXT': + print ' GLint access_flags = 0;' + print ' __glGetNamedBufferParameterivEXT(buffer, GL_BUFFER_ACCESS_FLAGS, &access_flags);' + print ' if ((access_flags & GL_MAP_WRITE_BIT) && !(access_flags & GL_MAP_FLUSH_EXPLICIT_BIT)) {' + print ' GLvoid *map = NULL;' + print ' __glGetNamedBufferPointervEXT(buffer, GL_BUFFER_MAP_POINTER, &map);' + print ' GLint length = 0;' + print ' __glGetNamedBufferParameterivEXT(buffer, GL_BUFFER_MAP_LENGTH, &length);' + print ' if (map && length > 0) {' + self.emit_memcpy('map', 'map', 'length') + print ' }' + print ' }' + if function.name == 'glFlushMappedBufferRange': + print ' GLvoid *map = NULL;' + print ' __glGetBufferPointerv(target, GL_BUFFER_MAP_POINTER, &map);' + print ' if (map && length > 0) {' + self.emit_memcpy('(char *)map + offset', '(const char *)map + offset', 'length') + print ' }' + if function.name == 'glFlushMappedBufferRangeAPPLE': + print ' GLvoid *map = NULL;' + print ' __glGetBufferPointerv(target, GL_BUFFER_MAP_POINTER, &map);' + print ' if (map && size > 0) {' + self.emit_memcpy('(char *)map + offset', '(const char *)map + offset', 'size') + print ' }' + if function.name == 'glFlushMappedNamedBufferRangeEXT': + print ' GLvoid *map = NULL;' + print ' __glGetNamedBufferPointervEXT(buffer, GL_BUFFER_MAP_POINTER, &map);' + print ' if (map && length > 0) {' + self.emit_memcpy('(char *)map + offset', '(const char *)map + offset', 'length') + print ' }' + + # Don't leave vertex attrib locations to chance. Instead emit fake + # glBindAttribLocation calls to ensure that the same locations will be + # used when retracing. Trying to remap locations after the fact would + # be an herculian task given that vertex attrib locations appear in + # many entry-points, including non-shader related ones. + if function.name == 'glLinkProgram': + Tracer.invokeFunction(self, function) + print ' GLint active_attributes = 0;' + print ' __glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &active_attributes);' + print ' for (GLint attrib = 0; attrib < active_attributes; ++attrib) {' + print ' GLint size = 0;' + print ' GLenum type = 0;' + print ' GLchar name[256];' + # TODO: Use ACTIVE_ATTRIBUTE_MAX_LENGTH instead of 256 + print ' __glGetActiveAttrib(program, attrib, sizeof name, NULL, &size, &type, name);' + print " if (name[0] != 'g' || name[1] != 'l' || name[2] != '_') {" + print ' GLint location = __glGetAttribLocation(program, name);' + print ' if (location >= 0) {' + bind_function = glapi.glapi.get_function_by_name('glBindAttribLocation') + self.fake_call(bind_function, ['program', 'location', 'name']) + print ' }' + print ' }' + print ' }' + if function.name == 'glLinkProgramARB': + Tracer.invokeFunction(self, function) + print ' GLint active_attributes = 0;' + print ' __glGetObjectParameterivARB(programObj, GL_OBJECT_ACTIVE_ATTRIBUTES_ARB, &active_attributes);' + print ' for (GLint attrib = 0; attrib < active_attributes; ++attrib) {' + print ' GLint size = 0;' + print ' GLenum type = 0;' + print ' GLcharARB name[256];' + # TODO: Use ACTIVE_ATTRIBUTE_MAX_LENGTH instead of 256 + print ' __glGetActiveAttribARB(programObj, attrib, sizeof name, NULL, &size, &type, name);' + print " if (name[0] != 'g' || name[1] != 'l' || name[2] != '_') {" + print ' GLint location = __glGetAttribLocationARB(programObj, name);' + print ' if (location >= 0) {' + bind_function = glapi.glapi.get_function_by_name('glBindAttribLocationARB') + self.fake_call(bind_function, ['programObj', 'location', 'name']) + print ' }' + print ' }' + print ' }' + + Tracer.traceFunctionImplBody(self, function) + + marker_functions = [ + # GL_GREMEDY_string_marker + 'glStringMarkerGREMEDY', + # GL_GREMEDY_frame_terminator + 'glFrameTerminatorGREMEDY', + # GL_EXT_debug_marker + 'glInsertEventMarkerEXT', + 'glPushGroupMarkerEXT', + 'glPopGroupMarkerEXT', + ] + + def invokeFunction(self, function): + if function.name in ('glLinkProgram', 'glLinkProgramARB'): + # These functions have been dispatched already + return + + # We implement GL_EXT_debug_marker, GL_GREMEDY_*, etc., and not the + # driver + if function.name in self.marker_functions: + return + + if function.name in ('glXGetProcAddress', 'glXGetProcAddressARB', 'wglGetProcAddress'): + else_ = '' + for marker_function in self.marker_functions: + if self.api.get_function_by_name(marker_function): + print ' %sif (strcmp("%s", (const char *)%s) == 0) {' % (else_, marker_function, function.args[0].name) + print ' __result = (%s)&%s;' % (function.type, marker_function) + print ' }' + else_ = 'else ' + print ' %s{' % else_ + Tracer.invokeFunction(self, function) + print ' }' + return + + # Override GL extensions + if function.name in ('glGetString', 'glGetIntegerv', 'glGetStringi'): + Tracer.invokeFunction(self, function, prefix = 'gltrace::__', suffix = '_override') + return + + Tracer.invokeFunction(self, function) + + buffer_targets = [ + 'ARRAY_BUFFER', + 'ELEMENT_ARRAY_BUFFER', + 'PIXEL_PACK_BUFFER', + 'PIXEL_UNPACK_BUFFER', + 'UNIFORM_BUFFER', + 'TEXTURE_BUFFER', + 'TRANSFORM_FEEDBACK_BUFFER', + 'COPY_READ_BUFFER', + 'COPY_WRITE_BUFFER', + 'DRAW_INDIRECT_BUFFER', + 'ATOMIC_COUNTER_BUFFER', + ] + + def wrapRet(self, function, instance): + Tracer.wrapRet(self, function, instance) + + # Keep track of buffer mappings + if function.name in ('glMapBuffer', 'glMapBufferARB'): + print ' struct buffer_mapping *mapping = get_buffer_mapping(target);' + print ' if (mapping) {' + print ' mapping->map = %s;' % (instance) + print ' mapping->length = 0;' + print ' __glGetBufferParameteriv(target, GL_BUFFER_SIZE, &mapping->length);' + print ' mapping->write = (access != GL_READ_ONLY);' + print ' mapping->explicit_flush = false;' + print ' }' + if function.name == 'glMapBufferRange': + print ' if (access & GL_MAP_WRITE_BIT) {' + print ' __checkBufferMapRange = true;' + print ' }' + print ' struct buffer_mapping *mapping = get_buffer_mapping(target);' + print ' if (mapping) {' + print ' mapping->map = %s;' % (instance) + print ' mapping->length = length;' + print ' mapping->write = access & GL_MAP_WRITE_BIT;' + print ' mapping->explicit_flush = access & GL_MAP_FLUSH_EXPLICIT_BIT;' + print ' }' + + boolean_names = [ + 'GL_FALSE', + 'GL_TRUE', + ] + + def gl_boolean(self, value): + return self.boolean_names[int(bool(value))] + + # Names of the functions that unpack from a pixel buffer object. See the + # ARB_pixel_buffer_object specification. + unpack_function_names = set([ + 'glBitmap', + 'glColorSubTable', + 'glColorTable', + 'glCompressedTexImage1D', + 'glCompressedTexImage2D', + 'glCompressedTexImage3D', + 'glCompressedTexSubImage1D', + 'glCompressedTexSubImage2D', + 'glCompressedTexSubImage3D', + 'glConvolutionFilter1D', + 'glConvolutionFilter2D', + 'glDrawPixels', + 'glMultiTexImage1DEXT', + 'glMultiTexImage2DEXT', + 'glMultiTexImage3DEXT', + 'glMultiTexSubImage1DEXT', + 'glMultiTexSubImage2DEXT', + 'glMultiTexSubImage3DEXT', + 'glPixelMapfv', + 'glPixelMapuiv', + 'glPixelMapusv', + 'glPolygonStipple', + 'glSeparableFilter2D', + 'glTexImage1D', + 'glTexImage1DEXT', + 'glTexImage2D', + 'glTexImage2DEXT', + 'glTexImage3D', + 'glTexImage3DEXT', + 'glTexSubImage1D', + 'glTexSubImage1DEXT', + 'glTexSubImage2D', + 'glTexSubImage2DEXT', + 'glTexSubImage3D', + 'glTexSubImage3DEXT', + 'glTextureImage1DEXT', + 'glTextureImage2DEXT', + 'glTextureImage3DEXT', + 'glTextureSubImage1DEXT', + 'glTextureSubImage2DEXT', + 'glTextureSubImage3DEXT', + ]) + + def serializeArgValue(self, function, arg): + if function.name in self.draw_function_names and arg.name == 'indices': + print ' GLint __element_array_buffer = 0;' + print ' __glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &__element_array_buffer);' + print ' if (!__element_array_buffer) {' + if isinstance(arg.type, stdapi.Array): + print ' trace::localWriter.beginArray(%s);' % arg.type.length + print ' for(GLsizei i = 0; i < %s; ++i) {' % arg.type.length + print ' trace::localWriter.beginElement();' + print ' trace::localWriter.writeBlob(%s[i], count[i]*__gl_type_size(type));' % (arg.name) + print ' trace::localWriter.endElement();' + print ' }' + print ' trace::localWriter.endArray();' + else: + print ' trace::localWriter.writeBlob(%s, count*__gl_type_size(type));' % (arg.name) + print ' } else {' + Tracer.serializeArgValue(self, function, arg) + print ' }' + return + + # Recognize offsets instead of blobs when a PBO is bound + if function.name in self.unpack_function_names \ + and (isinstance(arg.type, stdapi.Blob) \ + or (isinstance(arg.type, stdapi.Const) \ + and isinstance(arg.type.type, stdapi.Blob))): + print ' {' + print ' gltrace::Context *ctx = gltrace::getContext();' + print ' GLint __unpack_buffer = 0;' + print ' if (ctx->profile == gltrace::PROFILE_COMPAT)' + print ' __glGetIntegerv(GL_PIXEL_UNPACK_BUFFER_BINDING, &__unpack_buffer);' + print ' if (__unpack_buffer) {' + print ' trace::localWriter.writeOpaque(%s);' % arg.name + print ' } else {' + Tracer.serializeArgValue(self, function, arg) + print ' }' + print ' }' + return + + # Several GL state functions take GLenum symbolic names as + # integer/floats; so dump the symbolic name whenever possible + if function.name.startswith('gl') \ + and arg.type in (glapi.GLint, glapi.GLfloat, glapi.GLdouble) \ + 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 + print ' if (is_symbolic_pname(pname) && is_symbolic_param(%s)) {' % arg.name + self.serializeValue(glapi.GLenum, arg.name) + print ' } else {' + Tracer.serializeArgValue(self, function, arg) + print ' }' + return + + Tracer.serializeArgValue(self, function, arg) + + def footer(self, api): + Tracer.footer(self, api) + + # A simple state tracker to track the pointer values + # update the state + print 'static void __trace_user_arrays(GLuint maxindex)' + print '{' + print ' gltrace::Context *ctx = gltrace::getContext();' + + for camelcase_name, uppercase_name in self.arrays: + # in which profile is the array available? + profile_check = 'ctx->profile == gltrace::PROFILE_COMPAT' + if camelcase_name in self.arrays_es1: + profile_check = '(' + profile_check + ' || ctx->profile == gltrace::PROFILE_ES1)'; + + function_name = 'gl%sPointer' % camelcase_name + enable_name = 'GL_%s_ARRAY' % uppercase_name + binding_name = 'GL_%s_ARRAY_BUFFER_BINDING' % uppercase_name + function = api.get_function_by_name(function_name) + + print ' // %s' % function.prototype() + print ' if (%s) {' % profile_check + self.array_trace_prolog(api, uppercase_name) + self.array_prolog(api, uppercase_name) + print ' if (__glIsEnabled(%s)) {' % enable_name + print ' GLint __binding = 0;' + print ' __glGetIntegerv(%s, &__binding);' % binding_name + print ' if (!__binding) {' + + # Get the arguments via glGet* + for arg in function.args: + arg_get_enum = 'GL_%s_ARRAY_%s' % (uppercase_name, arg.name.upper()) + arg_get_function, arg_type = TypeGetter().visit(arg.type) + print ' %s %s = 0;' % (arg_type, arg.name) + print ' __%s(%s, &%s);' % (arg_get_function, arg_get_enum, arg.name) + + arg_names = ', '.join([arg.name for arg in function.args[:-1]]) + print ' size_t __size = __%s_size(%s, maxindex);' % (function.name, arg_names) + + # Emit a fake function + self.array_trace_intermezzo(api, uppercase_name) + print ' unsigned __call = trace::localWriter.beginEnter(&__%s_sig);' % (function.name,) + for arg in function.args: + assert not arg.output + print ' trace::localWriter.beginArg(%u);' % (arg.index,) + if arg.name != 'pointer': + self.serializeValue(arg.type, arg.name) + else: + print ' trace::localWriter.writeBlob((const void *)%s, __size);' % (arg.name) + print ' trace::localWriter.endArg();' + + print ' trace::localWriter.endEnter();' + print ' trace::localWriter.beginLeave(__call);' + print ' trace::localWriter.endLeave();' + print ' }' + print ' }' + self.array_epilog(api, uppercase_name) + self.array_trace_epilog(api, uppercase_name) + print ' }' + print + + # Samething, but for glVertexAttribPointer* + # + # Some variants of glVertexAttribPointer alias conventional and generic attributes: + # - glVertexAttribPointer: no + # - glVertexAttribPointerARB: implementation dependent + # - glVertexAttribPointerNV: yes + # + # This means that the implementations of these functions do not always + # alias, and they need to be considered independently. + # + print ' // ES1 does not support generic vertex attributes' + print ' if (ctx->profile == gltrace::PROFILE_ES1)' + print ' return;' + print + print ' vertex_attrib __vertex_attrib = __get_vertex_attrib();' + print + for suffix in ['', 'ARB', 'NV']: + if suffix: + SUFFIX = '_' + suffix + else: + SUFFIX = suffix + function_name = 'glVertexAttribPointer' + suffix + function = api.get_function_by_name(function_name) + + print ' // %s' % function.prototype() + print ' if (__vertex_attrib == VERTEX_ATTRIB%s) {' % SUFFIX + if suffix == 'NV': + print ' GLint __max_vertex_attribs = 16;' + else: + print ' GLint __max_vertex_attribs = 0;' + print ' __glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &__max_vertex_attribs);' + print ' for (GLint index = 0; index < __max_vertex_attribs; ++index) {' + print ' GLint __enabled = 0;' + if suffix == 'NV': + print ' __glGetIntegerv(GL_VERTEX_ATTRIB_ARRAY0_NV + index, &__enabled);' + else: + print ' __glGetVertexAttribiv%s(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED%s, &__enabled);' % (suffix, SUFFIX) + print ' if (__enabled) {' + print ' GLint __binding = 0;' + if suffix != 'NV': + # It doesn't seem possible to use VBOs with NV_vertex_program. + print ' __glGetVertexAttribiv%s(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING%s, &__binding);' % (suffix, SUFFIX) + print ' if (!__binding) {' + + # Get the arguments via glGet* + for arg in function.args[1:]: + if suffix == 'NV': + arg_get_enum = 'GL_ATTRIB_ARRAY_%s%s' % (arg.name.upper(), SUFFIX) + else: + arg_get_enum = 'GL_VERTEX_ATTRIB_ARRAY_%s%s' % (arg.name.upper(), SUFFIX) + arg_get_function, arg_type = TypeGetter('glGetVertexAttrib', False, suffix).visit(arg.type) + print ' %s %s = 0;' % (arg_type, arg.name) + print ' __%s(index, %s, &%s);' % (arg_get_function, arg_get_enum, arg.name) + + arg_names = ', '.join([arg.name for arg in function.args[1:-1]]) + print ' size_t __size = __%s_size(%s, maxindex);' % (function.name, arg_names) + + # Emit a fake function + print ' unsigned __call = trace::localWriter.beginEnter(&__%s_sig);' % (function.name,) + for arg in function.args: + assert not arg.output + print ' trace::localWriter.beginArg(%u);' % (arg.index,) + if arg.name != 'pointer': + self.serializeValue(arg.type, arg.name) + else: + print ' trace::localWriter.writeBlob((const void *)%s, __size);' % (arg.name) + print ' trace::localWriter.endArg();' + + print ' trace::localWriter.endEnter();' + print ' trace::localWriter.beginLeave(__call);' + print ' trace::localWriter.endLeave();' + print ' }' + print ' }' + print ' }' + print ' }' + print + + print '}' + print + + # + # Hooks for glTexCoordPointer, which is identical to the other array + # pointers except the fact that it is indexed by glClientActiveTexture. + # + + def array_prolog(self, api, uppercase_name): + if uppercase_name == 'TEXTURE_COORD': + print ' GLint client_active_texture = 0;' + print ' __glGetIntegerv(GL_CLIENT_ACTIVE_TEXTURE, &client_active_texture);' + print ' GLint max_texture_coords = 0;' + print ' if (ctx->profile == gltrace::PROFILE_COMPAT)' + print ' __glGetIntegerv(GL_MAX_TEXTURE_COORDS, &max_texture_coords);' + print ' else' + print ' __glGetIntegerv(GL_MAX_TEXTURE_UNITS, &max_texture_coords);' + print ' for (GLint unit = 0; unit < max_texture_coords; ++unit) {' + print ' GLint texture = GL_TEXTURE0 + unit;' + print ' __glClientActiveTexture(texture);' + + def array_trace_prolog(self, api, uppercase_name): + if uppercase_name == 'TEXTURE_COORD': + print ' bool client_active_texture_dirty = false;' + + def array_epilog(self, api, uppercase_name): + if uppercase_name == 'TEXTURE_COORD': + print ' }' + self.array_cleanup(api, uppercase_name) + + def array_cleanup(self, api, uppercase_name): + if uppercase_name == 'TEXTURE_COORD': + print ' __glClientActiveTexture(client_active_texture);' + + def array_trace_intermezzo(self, api, uppercase_name): + if uppercase_name == 'TEXTURE_COORD': + print ' if (texture != client_active_texture || client_active_texture_dirty) {' + print ' client_active_texture_dirty = true;' + self.fake_glClientActiveTexture_call(api, "texture"); + print ' }' + + def array_trace_epilog(self, api, uppercase_name): + if uppercase_name == 'TEXTURE_COORD': + print ' if (client_active_texture_dirty) {' + self.fake_glClientActiveTexture_call(api, "client_active_texture"); + print ' }' + + def fake_glClientActiveTexture_call(self, api, texture): + function = api.get_function_by_name('glClientActiveTexture') + self.fake_call(function, [texture]) + + def fake_call(self, function, args): + print ' unsigned __fake_call = trace::localWriter.beginEnter(&__%s_sig);' % (function.name,) + for arg, instance in zip(function.args, args): + assert not arg.output + print ' trace::localWriter.beginArg(%u);' % (arg.index,) + self.serializeValue(arg.type, instance) + print ' trace::localWriter.endArg();' + print ' trace::localWriter.endEnter();' + print ' trace::localWriter.beginLeave(__fake_call);' + print ' trace::localWriter.endLeave();' + + + + + + + + + + + diff --git a/wrappers/glxtrace.py b/wrappers/glxtrace.py new file mode 100644 index 0000000..8c18e0b --- /dev/null +++ b/wrappers/glxtrace.py @@ -0,0 +1,161 @@ +########################################################################## +# +# Copyright 2011 Jose Fonseca +# Copyright 2008-2010 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. +# +##########################################################################/ + + +"""GLX tracing generator.""" + + +from gltrace import GlTracer +from dispatch import function_pointer_type, function_pointer_value +from specs.stdapi import API +from specs.glapi import glapi +from specs.glxapi import glxapi + + +class GlxTracer(GlTracer): + + def isFunctionPublic(self, function): + # The symbols visible in libGL.so can vary, so expose them all + return True + + def wrapRet(self, function, instance): + GlTracer.wrapRet(self, function, instance) + + if function.name in ("glXGetProcAddress", "glXGetProcAddressARB"): + print ' %s = __unwrap_proc_addr(procName, %s);' % (instance, instance) + + +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_writer_local.hpp"' + print + print '// To validate our prototypes' + print '#define GL_GLEXT_PROTOTYPES' + print '#define GLX_GLXEXT_PROTOTYPES' + print + print '#include "glproc.hpp"' + print '#include "glsize.hpp"' + print + print 'static __GLXextFuncPtr __unwrap_proc_addr(const GLubyte * procName, __GLXextFuncPtr procPtr);' + print + + api = API() + api.addApi(glxapi) + api.addApi(glapi) + tracer = GlxTracer() + tracer.trace_api(api) + + print 'static __GLXextFuncPtr __unwrap_proc_addr(const GLubyte * procName, __GLXextFuncPtr procPtr) {' + print ' if (!procPtr) {' + print ' return procPtr;' + print ' }' + for f in api.functions: + ptype = function_pointer_type(f) + pvalue = function_pointer_value(f) + print ' if (strcmp("%s", (const char *)procName) == 0) {' % f.name + print ' %s = (%s)procPtr;' % (pvalue, ptype) + print ' return (__GLXextFuncPtr)&%s;' % (f.name,) + print ' }' + print ' os::log("apitrace: warning: unknown function \\"%s\\"\\n", (const char *)procName);' + print ' return procPtr;' + print '}' + print + print r''' + + +/* + * 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); +} + + +/* + * Several applications, such as Quake3, use dlopen("libGL.so.1"), but + * LD_PRELOAD does not intercept symbols obtained via dlopen/dlsym, therefore + * we need to intercept the dlopen() call here, and redirect to our wrapper + * shared object. + */ +extern "C" PUBLIC +void * dlopen(const char *filename, int flag) +{ + void *handle; + + handle = __dlopen(filename, flag); + + const char * libgl_filename = getenv("TRACE_LIBGL"); + + if (filename && handle && !libgl_filename) { + if (0) { + os::log("apitrace: warning: dlopen(\"%s\", 0x%x)\n", filename, flag); + } + + // FIXME: handle absolute paths and other versions + if (strcmp(filename, "libGL.so") == 0 || + strcmp(filename, "libGL.so.1") == 0) { + + // Use the true libGL.so handle instead of RTLD_NEXT from now on + __libGlHandle = handle; + + // Get the file path for our shared object, and use it instead + static int dummy = 0xdeedbeef; + Dl_info info; + if (dladdr(&dummy, &info)) { + os::log("apitrace: redirecting dlopen(\"%s\", 0x%x)\n", filename, flag); + handle = __dlopen(info.dli_fname, flag); + } else { + os::log("apitrace: warning: dladdr() failed\n"); + } + } + } + + return handle; +} + + + +''' diff --git a/wrappers/opengl32.def b/wrappers/opengl32.def new file mode 100644 index 0000000..9e717a7 --- /dev/null +++ b/wrappers/opengl32.def @@ -0,0 +1,371 @@ +LIBRARY opengl32 + +EXPORTS +; GlmfBeginGlsBlock +; GlmfCloseMetaFile +; GlmfEndGlsBlock +; GlmfEndPlayback +; GlmfInitPlayback +; GlmfPlayGlsRecord + glAccum + glAlphaFunc + glAreTexturesResident + glArrayElement + glBegin + glBindTexture + glBitmap + glBlendFunc + glCallList + glCallLists + glClear + glClearAccum + glClearColor + glClearDepth + glClearIndex + glClearStencil + glClipPlane + glColor3b + glColor3bv + glColor3d + glColor3dv + glColor3f + glColor3fv + glColor3i + glColor3iv + glColor3s + glColor3sv + glColor3ub + glColor3ubv + glColor3ui + glColor3uiv + glColor3us + glColor3usv + glColor4b + glColor4bv + glColor4d + glColor4dv + glColor4f + glColor4fv + glColor4i + glColor4iv + glColor4s + glColor4sv + glColor4ub + glColor4ubv + glColor4ui + glColor4uiv + glColor4us + glColor4usv + glColorMask + glColorMaterial + glColorPointer + glCopyPixels + glCopyTexImage1D + glCopyTexImage2D + glCopyTexSubImage1D + glCopyTexSubImage2D + glCullFace +; glDebugEntry + glDeleteLists + glDeleteTextures + glDepthFunc + glDepthMask + glDepthRange + glDisable + glDisableClientState + glDrawArrays + glDrawBuffer + glDrawElements + glDrawPixels + glEdgeFlag + glEdgeFlagPointer + glEdgeFlagv + glEnable + glEnableClientState + glEnd + glEndList + glEvalCoord1d + glEvalCoord1dv + glEvalCoord1f + glEvalCoord1fv + glEvalCoord2d + glEvalCoord2dv + glEvalCoord2f + glEvalCoord2fv + glEvalMesh1 + glEvalMesh2 + glEvalPoint1 + glEvalPoint2 + glFeedbackBuffer + glFinish + glFlush + glFogf + glFogfv + glFogi + glFogiv + glFrontFace + glFrustum + glGenLists + glGenTextures + glGetBooleanv + glGetClipPlane + glGetDoublev + glGetError + glGetFloatv + glGetIntegerv + glGetLightfv + glGetLightiv + glGetMapdv + glGetMapfv + glGetMapiv + glGetMaterialfv + glGetMaterialiv + glGetPixelMapfv + glGetPixelMapuiv + glGetPixelMapusv + glGetPointerv + glGetPolygonStipple + glGetString + glGetTexEnvfv + glGetTexEnviv + glGetTexGendv + glGetTexGenfv + glGetTexGeniv + glGetTexImage + glGetTexLevelParameterfv + glGetTexLevelParameteriv + glGetTexParameterfv + glGetTexParameteriv + glHint + glIndexMask + glIndexPointer + glIndexd + glIndexdv + glIndexf + glIndexfv + glIndexi + glIndexiv + glIndexs + glIndexsv + glIndexub + glIndexubv + glInitNames + glInterleavedArrays + glIsEnabled + glIsList + glIsTexture + glLightModelf + glLightModelfv + glLightModeli + glLightModeliv + glLightf + glLightfv + glLighti + glLightiv + glLineStipple + glLineWidth + glListBase + glLoadIdentity + glLoadMatrixd + glLoadMatrixf + glLoadName + glLogicOp + glMap1d + glMap1f + glMap2d + glMap2f + glMapGrid1d + glMapGrid1f + glMapGrid2d + glMapGrid2f + glMaterialf + glMaterialfv + glMateriali + glMaterialiv + glMatrixMode + glMultMatrixd + glMultMatrixf + glNewList + glNormal3b + glNormal3bv + glNormal3d + glNormal3dv + glNormal3f + glNormal3fv + glNormal3i + glNormal3iv + glNormal3s + glNormal3sv + glNormalPointer + glOrtho + glPassThrough + glPixelMapfv + glPixelMapuiv + glPixelMapusv + glPixelStoref + glPixelStorei + glPixelTransferf + glPixelTransferi + glPixelZoom + glPointSize + glPolygonMode + glPolygonOffset + glPolygonStipple + glPopAttrib + glPopClientAttrib + glPopMatrix + glPopName + glPrioritizeTextures + glPushAttrib + glPushClientAttrib + glPushMatrix + glPushName + glRasterPos2d + glRasterPos2dv + glRasterPos2f + glRasterPos2fv + glRasterPos2i + glRasterPos2iv + glRasterPos2s + glRasterPos2sv + glRasterPos3d + glRasterPos3dv + glRasterPos3f + glRasterPos3fv + glRasterPos3i + glRasterPos3iv + glRasterPos3s + glRasterPos3sv + glRasterPos4d + glRasterPos4dv + glRasterPos4f + glRasterPos4fv + glRasterPos4i + glRasterPos4iv + glRasterPos4s + glRasterPos4sv + glReadBuffer + glReadPixels + glRectd + glRectdv + glRectf + glRectfv + glRecti + glRectiv + glRects + glRectsv + glRenderMode + glRotated + glRotatef + glScaled + glScalef + glScissor + glSelectBuffer + glShadeModel + glStencilFunc + glStencilMask + glStencilOp + glTexCoord1d + glTexCoord1dv + glTexCoord1f + glTexCoord1fv + glTexCoord1i + glTexCoord1iv + glTexCoord1s + glTexCoord1sv + glTexCoord2d + glTexCoord2dv + glTexCoord2f + glTexCoord2fv + glTexCoord2i + glTexCoord2iv + glTexCoord2s + glTexCoord2sv + glTexCoord3d + glTexCoord3dv + glTexCoord3f + glTexCoord3fv + glTexCoord3i + glTexCoord3iv + glTexCoord3s + glTexCoord3sv + glTexCoord4d + glTexCoord4dv + glTexCoord4f + glTexCoord4fv + glTexCoord4i + glTexCoord4iv + glTexCoord4s + glTexCoord4sv + glTexCoordPointer + glTexEnvf + glTexEnvfv + glTexEnvi + glTexEnviv + glTexGend + glTexGendv + glTexGenf + glTexGenfv + glTexGeni + glTexGeniv + glTexImage1D + glTexImage2D + glTexParameterf + glTexParameterfv + glTexParameteri + glTexParameteriv + glTexSubImage1D + glTexSubImage2D + glTranslated + glTranslatef + glVertex2d + glVertex2dv + glVertex2f + glVertex2fv + glVertex2i + glVertex2iv + glVertex2s + glVertex2sv + glVertex3d + glVertex3dv + glVertex3f + glVertex3fv + glVertex3i + glVertex3iv + glVertex3s + glVertex3sv + glVertex4d + glVertex4dv + glVertex4f + glVertex4fv + glVertex4i + glVertex4iv + glVertex4s + glVertex4sv + glVertexPointer + glViewport + wglChoosePixelFormat + wglCopyContext + wglCreateContext + wglCreateLayerContext + wglDeleteContext + wglDescribeLayerPlane + wglDescribePixelFormat + wglGetCurrentContext + wglGetCurrentDC + wglGetDefaultProcAddress + wglGetLayerPaletteEntries + wglGetPixelFormat + wglGetProcAddress + wglMakeCurrent + wglRealizeLayerPalette + wglSetLayerPaletteEntries + wglSetPixelFormat + wglShareLists + wglSwapBuffers + wglSwapLayerBuffers + wglSwapMultipleBuffers + wglUseFontBitmapsA + wglUseFontBitmapsW + wglUseFontOutlinesA + wglUseFontOutlinesW diff --git a/wrappers/trace.py b/wrappers/trace.py new file mode 100644 index 0000000..e2e11ec --- /dev/null +++ b/wrappers/trace.py @@ -0,0 +1,613 @@ +########################################################################## +# +# Copyright 2008-2010 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. +# +##########################################################################/ + +"""Common trace code generation.""" + + +# Adjust path +import os.path +import sys +sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..')) + + +import specs.stdapi as stdapi + + +def getWrapperInterfaceName(interface): + return "Wrap" + interface.expr + + +class ComplexValueSerializer(stdapi.OnceVisitor): + '''Type visitors which generates serialization functions for + complex types. + + Simple types are serialized inline. + ''' + + def __init__(self, serializer): + stdapi.OnceVisitor.__init__(self) + self.serializer = serializer + + def visitVoid(self, literal): + pass + + def visitLiteral(self, literal): + pass + + def visitString(self, string): + pass + + def visitConst(self, const): + self.visit(const.type) + + def visitStruct(self, struct): + for type, name in struct.members: + self.visit(type) + print 'static void _write__%s(const %s &value) {' % (struct.tag, struct.expr) + print ' static const char * members[%u] = {' % (len(struct.members),) + for type, name, in struct.members: + print ' "%s",' % (name,) + print ' };' + print ' static const trace::StructSig sig = {' + print ' %u, "%s", %u, members' % (struct.id, struct.name, len(struct.members)) + print ' };' + print ' trace::localWriter.beginStruct(&sig);' + for type, name in struct.members: + self.serializer.visit(type, 'value.%s' % (name,)) + print ' trace::localWriter.endStruct();' + print '}' + print + + def visitArray(self, array): + self.visit(array.type) + + def visitBlob(self, array): + pass + + def visitEnum(self, enum): + print 'static const trace::EnumValue __enum%s_values[] = {' % (enum.tag) + for value in enum.values: + print ' {"%s", %s},' % (value, value) + print '};' + print + print 'static const trace::EnumSig __enum%s_sig = {' % (enum.tag) + print ' %u, %u, __enum%s_values' % (enum.id, len(enum.values), enum.tag) + print '};' + print + + def visitBitmask(self, bitmask): + print 'static const trace::BitmaskFlag __bitmask%s_flags[] = {' % (bitmask.tag) + for value in bitmask.values: + print ' {"%s", %s},' % (value, value) + print '};' + print + print 'static const trace::BitmaskSig __bitmask%s_sig = {' % (bitmask.tag) + print ' %u, %u, __bitmask%s_flags' % (bitmask.id, len(bitmask.values), bitmask.tag) + print '};' + print + + def visitPointer(self, pointer): + self.visit(pointer.type) + + def visitIntPointer(self, pointer): + pass + + def visitObjPointer(self, pointer): + self.visit(pointer.type) + + def visitLinearPointer(self, pointer): + self.visit(pointer.type) + + def visitHandle(self, handle): + self.visit(handle.type) + + def visitReference(self, reference): + self.visit(reference.type) + + def visitAlias(self, alias): + self.visit(alias.type) + + def visitOpaque(self, opaque): + pass + + def visitInterface(self, interface): + pass + + def visitPolymorphic(self, polymorphic): + print 'static void _write__%s(int selector, const %s & value) {' % (polymorphic.tag, polymorphic.expr) + print ' switch (selector) {' + for cases, type in polymorphic.iterSwitch(): + for case in cases: + print ' %s:' % case + self.serializer.visit(type, 'static_cast<%s>(value)' % (type,)) + print ' break;' + print ' }' + print '}' + print + + +class ValueSerializer(stdapi.Visitor): + '''Visitor which generates code to serialize any type. + + Simple types are serialized inline here, whereas the serialization of + complex types is dispatched to the serialization functions generated by + ComplexValueSerializer visitor above. + ''' + + def visitLiteral(self, literal, instance): + print ' trace::localWriter.write%s(%s);' % (literal.kind, instance) + + def visitString(self, string, instance): + if string.kind == 'String': + cast = 'const char *' + elif string.kind == 'WString': + cast = 'const wchar_t *' + else: + assert False + if cast != string.expr: + # reinterpret_cast is necessary for GLubyte * <=> char * + instance = 'reinterpret_cast<%s>(%s)' % (cast, instance) + if string.length is not None: + length = ', %s' % string.length + else: + length = '' + print ' trace::localWriter.write%s(%s%s);' % (string.kind, instance, length) + + def visitConst(self, const, instance): + self.visit(const.type, instance) + + def visitStruct(self, struct, instance): + print ' _write__%s(%s);' % (struct.tag, instance) + + def visitArray(self, array, instance): + length = '__c' + array.type.tag + index = '__i' + array.type.tag + print ' if (%s) {' % instance + print ' size_t %s = %s;' % (length, array.length) + print ' trace::localWriter.beginArray(%s);' % length + print ' for (size_t %s = 0; %s < %s; ++%s) {' % (index, index, length, index) + print ' trace::localWriter.beginElement();' + self.visit(array.type, '(%s)[%s]' % (instance, index)) + print ' trace::localWriter.endElement();' + print ' }' + print ' trace::localWriter.endArray();' + print ' } else {' + print ' trace::localWriter.writeNull();' + print ' }' + + def visitBlob(self, blob, instance): + print ' trace::localWriter.writeBlob(%s, %s);' % (instance, blob.size) + + def visitEnum(self, enum, instance): + print ' trace::localWriter.writeEnum(&__enum%s_sig, %s);' % (enum.tag, instance) + + def visitBitmask(self, bitmask, instance): + print ' trace::localWriter.writeBitmask(&__bitmask%s_sig, %s);' % (bitmask.tag, instance) + + def visitPointer(self, pointer, instance): + print ' if (%s) {' % instance + print ' trace::localWriter.beginArray(1);' + print ' trace::localWriter.beginElement();' + self.visit(pointer.type, "*" + instance) + print ' trace::localWriter.endElement();' + print ' trace::localWriter.endArray();' + print ' } else {' + print ' trace::localWriter.writeNull();' + print ' }' + + def visitIntPointer(self, pointer, instance): + print ' trace::localWriter.writeOpaque((const void *)%s);' % instance + + def visitObjPointer(self, pointer, instance): + print ' trace::localWriter.writeOpaque((const void *)%s);' % instance + + def visitLinearPointer(self, pointer, instance): + print ' trace::localWriter.writeOpaque((const void *)%s);' % instance + + def visitReference(self, reference, instance): + self.visit(reference.type, instance) + + def visitHandle(self, handle, instance): + self.visit(handle.type, instance) + + def visitAlias(self, alias, instance): + self.visit(alias.type, instance) + + def visitOpaque(self, opaque, instance): + print ' trace::localWriter.writeOpaque((const void *)%s);' % instance + + def visitInterface(self, interface, instance): + print ' trace::localWriter.writeOpaque((const void *)&%s);' % instance + + def visitPolymorphic(self, polymorphic, instance): + print ' _write__%s(%s, %s);' % (polymorphic.tag, polymorphic.switchExpr, instance) + + +class ValueWrapper(stdapi.Visitor): + '''Type visitor which will generate the code to wrap an instance. + + Wrapping is necessary mostly for interfaces, however interface pointers can + appear anywhere inside complex types. + ''' + + def visitVoid(self, type, instance): + raise NotImplementedError + + def visitLiteral(self, type, instance): + pass + + def visitString(self, type, instance): + pass + + def visitConst(self, type, instance): + pass + + def visitStruct(self, struct, instance): + for type, name in struct.members: + self.visit(type, "(%s).%s" % (instance, name)) + + def visitArray(self, array, instance): + # XXX: actually it is possible to return an array of pointers + pass + + def visitBlob(self, blob, instance): + pass + + def visitEnum(self, enum, instance): + pass + + def visitBitmask(self, bitmask, instance): + pass + + def visitPointer(self, pointer, instance): + print " if (%s) {" % instance + self.visit(pointer.type, "*" + instance) + print " }" + + def visitIntPointer(self, pointer, instance): + pass + + def visitObjPointer(self, pointer, instance): + print " if (%s) {" % instance + self.visit(pointer.type, "*" + instance) + print " }" + + def visitLinearPointer(self, pointer, instance): + pass + + def visitReference(self, reference, instance): + self.visit(reference.type, instance) + + def visitHandle(self, handle, instance): + self.visit(handle.type, instance) + + def visitAlias(self, alias, instance): + self.visit(alias.type, instance) + + def visitOpaque(self, opaque, instance): + pass + + def visitInterface(self, interface, instance): + assert instance.startswith('*') + instance = instance[1:] + print " if (%s) {" % instance + print " %s = new %s(%s);" % (instance, getWrapperInterfaceName(interface), instance) + print " }" + + def visitPolymorphic(self, type, instance): + # XXX: There might be polymorphic values that need wrapping in the future + pass + + +class ValueUnwrapper(ValueWrapper): + '''Reverse of ValueWrapper.''' + + def visitInterface(self, interface, instance): + assert instance.startswith('*') + instance = instance[1:] + print r' if (%s) {' % instance + print r' %s *pWrapper = static_cast<%s*>(%s);' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), instance) + print r' if (pWrapper && pWrapper->m_dwMagic == 0xd8365d6c) {' + print r' %s = pWrapper->m_pInstance;' % (instance,) + print r' } else {' + print r' os::log("apitrace: warning: %%s: unexpected %%s pointer\n", __FUNCTION__, "%s");' % interface.name + print r' }' + print r' }' + + +class Tracer: + '''Base class to orchestrate the code generation of API tracing.''' + + def __init__(self): + self.api = None + + def serializerFactory(self): + '''Create a serializer. + + Can be overriden by derived classes to inject their own serialzer. + ''' + + return ValueSerializer() + + def trace_api(self, api): + self.api = api + + self.header(api) + + # Includes + for header in api.headers: + print header + print + + # Generate the serializer functions + types = api.getAllTypes() + visitor = ComplexValueSerializer(self.serializerFactory()) + map(visitor.visit, types) + print + + # Interfaces wrapers + interfaces = api.getAllInterfaces() + map(self.declareWrapperInterface, interfaces) + map(self.implementWrapperInterface, interfaces) + print + + # Function wrappers + map(self.traceFunctionDecl, api.functions) + map(self.traceFunctionImpl, api.functions) + print + + self.footer(api) + + def header(self, api): + pass + + def footer(self, api): + pass + + def traceFunctionDecl(self, function): + # Per-function declarations + + if function.args: + print 'static const char * __%s_args[%u] = {%s};' % (function.name, len(function.args), ', '.join(['"%s"' % arg.name for arg in function.args])) + else: + print 'static const char ** __%s_args = NULL;' % (function.name,) + print 'static const trace::FunctionSig __%s_sig = {%u, "%s", %u, __%s_args};' % (function.name, function.id, function.name, len(function.args), function.name) + print + + def isFunctionPublic(self, function): + return True + + def traceFunctionImpl(self, function): + if self.isFunctionPublic(function): + print 'extern "C" PUBLIC' + else: + print 'extern "C" PRIVATE' + print function.prototype() + ' {' + if function.type is not stdapi.Void: + print ' %s __result;' % function.type + self.traceFunctionImplBody(function) + if function.type is not stdapi.Void: + self.wrapRet(function, "__result") + print ' return __result;' + print '}' + print + + def traceFunctionImplBody(self, function): + print ' unsigned __call = trace::localWriter.beginEnter(&__%s_sig);' % (function.name,) + for arg in function.args: + if not arg.output: + self.unwrapArg(function, arg) + self.serializeArg(function, arg) + print ' trace::localWriter.endEnter();' + self.invokeFunction(function) + print ' trace::localWriter.beginLeave(__call);' + for arg in function.args: + if arg.output: + self.serializeArg(function, arg) + self.wrapArg(function, arg) + if function.type is not stdapi.Void: + self.serializeRet(function, "__result") + print ' trace::localWriter.endLeave();' + + def invokeFunction(self, function, prefix='__', suffix=''): + if function.type is stdapi.Void: + result = '' + else: + result = '__result = ' + dispatch = prefix + function.name + suffix + print ' %s%s(%s);' % (result, dispatch, ', '.join([str(arg.name) for arg in function.args])) + + def serializeArg(self, function, arg): + print ' trace::localWriter.beginArg(%u);' % (arg.index,) + self.serializeArgValue(function, arg) + print ' trace::localWriter.endArg();' + + def serializeArgValue(self, function, arg): + self.serializeValue(arg.type, arg.name) + + def wrapArg(self, function, arg): + self.wrapValue(arg.type, arg.name) + + def unwrapArg(self, function, arg): + self.unwrapValue(arg.type, arg.name) + + def serializeRet(self, function, instance): + print ' trace::localWriter.beginReturn();' + self.serializeValue(function.type, instance) + print ' trace::localWriter.endReturn();' + + def serializeValue(self, type, instance): + serializer = self.serializerFactory() + serializer.visit(type, instance) + + def wrapRet(self, function, instance): + self.wrapValue(function.type, instance) + + def unwrapRet(self, function, instance): + self.unwrapValue(function.type, instance) + + def wrapValue(self, type, instance): + visitor = ValueWrapper() + visitor.visit(type, instance) + + def unwrapValue(self, type, instance): + visitor = ValueUnwrapper() + visitor.visit(type, instance) + + def declareWrapperInterface(self, interface): + print "class %s : public %s " % (getWrapperInterfaceName(interface), interface.name) + print "{" + print "public:" + print " %s(%s * pInstance);" % (getWrapperInterfaceName(interface), interface.name) + print " virtual ~%s();" % getWrapperInterfaceName(interface) + print + for method in interface.iterMethods(): + print " " + method.prototype() + ";" + print + self.declareWrapperInterfaceVariables(interface) + print "};" + print + + def declareWrapperInterfaceVariables(self, interface): + #print "private:" + print " DWORD m_dwMagic;" + print " %s * m_pInstance;" % (interface.name,) + + def implementWrapperInterface(self, interface): + print '%s::%s(%s * pInstance) {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), interface.name) + print ' m_dwMagic = 0xd8365d6c;' + print ' m_pInstance = pInstance;' + print '}' + print + print '%s::~%s() {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface)) + print '}' + print + for base, method in interface.iterBaseMethods(): + self.implementWrapperInterfaceMethod(interface, base, method) + print + + def implementWrapperInterfaceMethod(self, interface, base, method): + print method.prototype(getWrapperInterfaceName(interface) + '::' + method.name) + ' {' + if method.type is not stdapi.Void: + print ' %s __result;' % method.type + + self.implementWrapperInterfaceMethodBody(interface, base, method) + + if method.type is not stdapi.Void: + print ' return __result;' + print '}' + print + + def implementWrapperInterfaceMethodBody(self, interface, base, method): + print ' static const char * __args[%u] = {%s};' % (len(method.args) + 1, ', '.join(['"this"'] + ['"%s"' % arg.name for arg in method.args])) + print ' static const trace::FunctionSig __sig = {%u, "%s", %u, __args};' % (method.id, interface.name + '::' + method.name, len(method.args) + 1) + print ' unsigned __call = trace::localWriter.beginEnter(&__sig);' + print ' trace::localWriter.beginArg(0);' + print ' trace::localWriter.writeOpaque((const void *)m_pInstance);' + print ' trace::localWriter.endArg();' + + from specs.winapi import REFIID + from specs.stdapi import Pointer, Opaque, Interface + + riid = None + for arg in method.args: + if not arg.output: + self.unwrapArg(method, arg) + self.serializeArg(method, arg) + if arg.type is REFIID: + riid = arg + print ' trace::localWriter.endEnter();' + + self.invokeMethod(interface, base, method) + + print ' trace::localWriter.beginLeave(__call);' + for arg in method.args: + if arg.output: + self.serializeArg(method, arg) + self.wrapArg(method, arg) + if riid is not None and isinstance(arg.type, Pointer): + if isinstance(arg.type.type, Opaque): + self.wrapIid(interface, method, riid, arg) + else: + assert isinstance(arg.type.type, Pointer) + assert isinstance(arg.type.type.type, Interface) + + if method.type is not stdapi.Void: + print ' trace::localWriter.beginReturn();' + self.serializeValue(method.type, "__result") + print ' trace::localWriter.endReturn();' + self.wrapValue(method.type, '__result') + print ' trace::localWriter.endLeave();' + if method.name == 'Release': + assert method.type is not stdapi.Void + print ' if (!__result)' + print ' delete this;' + + def wrapIid(self, interface, method, riid, out): + print ' if (%s && *%s) {' % (out.name, out.name) + print ' if (*%s == m_pInstance) {' % (out.name,) + print ' *%s = this;' % (out.name,) + print ' }' + for iface in self.api.getAllInterfaces(): + print r' else if (%s == IID_%s) {' % (riid.name, iface.name) + print r' *%s = new Wrap%s((%s *) *%s);' % (out.name, iface.name, iface.name, out.name) + print r' }' + print r' else {' + print r' os::log("apitrace: warning: %s::%s: unknown IID {0x%08lX,0x%04X,0x%04X,{0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,0x%02X}}\n",' + print r' "%s", "%s",' % (interface.name, method.name) + print r' %s.Data1, %s.Data2, %s.Data3,' % (riid.name, riid.name, riid.name) + print r' %s.Data4[0],' % (riid.name,) + print r' %s.Data4[1],' % (riid.name,) + print r' %s.Data4[2],' % (riid.name,) + print r' %s.Data4[3],' % (riid.name,) + print r' %s.Data4[4],' % (riid.name,) + print r' %s.Data4[5],' % (riid.name,) + print r' %s.Data4[6],' % (riid.name,) + print r' %s.Data4[7]);' % (riid.name,) + print r' }' + print ' }' + + def invokeMethod(self, interface, base, method): + if method.type is stdapi.Void: + result = '' + else: + result = '__result = ' + print ' %sstatic_cast<%s *>(m_pInstance)->%s(%s);' % (result, base, method.name, ', '.join([str(arg.name) for arg in method.args])) + + def emit_memcpy(self, dest, src, length): + print ' unsigned __call = trace::localWriter.beginEnter(&trace::memcpy_sig);' + print ' trace::localWriter.beginArg(0);' + print ' trace::localWriter.writeOpaque(%s);' % dest + print ' trace::localWriter.endArg();' + print ' trace::localWriter.beginArg(1);' + print ' trace::localWriter.writeBlob(%s, %s);' % (src, length) + print ' trace::localWriter.endArg();' + print ' trace::localWriter.beginArg(2);' + print ' trace::localWriter.writeUInt(%s);' % length + print ' trace::localWriter.endArg();' + print ' trace::localWriter.endEnter();' + print ' trace::localWriter.beginLeave(__call);' + print ' trace::localWriter.endLeave();' + diff --git a/wrappers/wgltrace.py b/wrappers/wgltrace.py new file mode 100644 index 0000000..22db6f0 --- /dev/null +++ b/wrappers/wgltrace.py @@ -0,0 +1,83 @@ +########################################################################## +# +# 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. +# +##########################################################################/ + + +"""WGL tracing code generator.""" + + +from gltrace import GlTracer +from dispatch import function_pointer_type, function_pointer_value +from codegen import * +from specs.stdapi import API +from specs.glapi import glapi +from specs.wglapi import wglapi + + +class WglTracer(GlTracer): + + def wrapRet(self, function, instance): + GlTracer.wrapRet(self, function, instance) + + if function.name == "wglGetProcAddress": + print ' if (%s) {' % instance + + func_dict = dict([(f.name, f) for f in glapi.functions + wglapi.functions]) + + def handle_case(function_name): + f = func_dict[function_name] + ptype = function_pointer_type(f) + pvalue = function_pointer_value(f) + print ' %s = (%s)%s;' % (pvalue, ptype, instance) + print ' %s = (%s)&%s;' % (instance, function.type, f.name); + + def handle_default(): + print ' os::log("apitrace: warning: unknown function \\"%s\\"\\n", lpszProc);' + + string_switch('lpszProc', func_dict.keys(), handle_case, handle_default) + print ' }' + + +if __name__ == '__main__': + print + print '#define _GDI32_' + print + print '#include ' + print '#include ' + print + print '#include "trace_writer_local.hpp"' + print '#include "os.hpp"' + print + print '// To validate our prototypes' + print '#define GL_GLEXT_PROTOTYPES' + print '#define WGL_GLXEXT_PROTOTYPES' + print + print '#include "glproc.hpp"' + print '#include "glsize.hpp"' + print + api = API() + api.addApi(glapi) + api.addApi(wglapi) + tracer = WglTracer() + tracer.trace_api(api)