]> git.cworth.org Git - apitrace/commitdiff
Merge branch 'trace-editing'
authorZack Rusin <zack@kde.org>
Mon, 18 Apr 2011 21:04:01 +0000 (17:04 -0400)
committerZack Rusin <zack@kde.org>
Mon, 18 Apr 2011 21:04:01 +0000 (17:04 -0400)
fixes #1

20 files changed:
.gitignore
CMakeLists.txt [changed mode: 0644->0755]
README
TODO
dump.cpp [deleted file]
formatter.hpp
glimports.hpp
glproc.py
glretrace.py
glsize.hpp
glstate.py
gltrace.py
glxtrace.py
json.hpp
os.hpp
scripts/tracediff.sh
trace_parser.cpp
trace_parser.hpp
trace_write.cpp
tracedump.cpp [new file with mode: 0644]

index 0a45575493087a80731e9f1b84b35ccd042d36e5..cdd2823e2e126800af46bac36d29251704dffdd3 100644 (file)
@@ -28,12 +28,12 @@ d3d10_1.cpp
 d3d8.cpp
 d3d9.cpp
 ddraw.cpp
-dump
 dxsdk
 glproc.hpp
 glretrace
 glretrace_gl.cpp
 glretrace_state.cpp
 glxtrace.cpp
+tracedump
 traces
 wgltrace.cpp
old mode 100644 (file)
new mode 100755 (executable)
index 0270d97..a157889
@@ -41,6 +41,9 @@ if (MSVC)
     # Enable math constants defines
     add_definitions (-D_USE_MATH_DEFINES)
 
+    # No min/max macros
+    add_definitions (-DNOMINMAX)
+
     # Adjust warnings
     add_definitions (-D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_WARNINGS)
     add_definitions (-D_SCL_SECURE_NO_DEPRECATE -D_SCL_SECURE_NO_WARNINGS)
@@ -209,8 +212,8 @@ endif (WIN32)
 
 add_library (trace trace_model.cpp trace_parser.cpp trace_write.cpp ${os})
 
-add_executable (dump dump.cpp)
-target_link_libraries (dump trace)
+add_executable (tracedump tracedump.cpp)
+target_link_libraries (tracedump trace)
 
 add_custom_command (
     OUTPUT glretrace_gl.cpp
diff --git a/README b/README
index 8091a414d68f72bafde79f6a7e48d3928be14f10..8fc78a1d6c9b167ccb5b84532b325eddc62bb867 100644 (file)
--- a/README
+++ b/README
@@ -89,7 +89,7 @@ http://www.cmake.org/Wiki/CmakeMingw for detailed instructions.
 
 * View the trace with
 
- /path/to/dump application.trace
+ /path/to/tracedump application.trace
 
 * Replay the trace with
 
@@ -105,7 +105,7 @@ http://www.cmake.org/Wiki/CmakeMingw for detailed instructions.
 
 * View the trace with
 
- /path/to/dump application.trace
+ /path/to/tracedump application.trace
 
 * Replay the trace with
 
diff --git a/TODO b/TODO
index 97ca506b78733968447481c47a6f2fc0febb45ca..ffa5a608f7b277073ebb3508260f15edef1ef2b0 100644 (file)
--- a/TODO
+++ b/TODO
@@ -26,6 +26,9 @@ Tracing:
 
 * Add option to include call stack frames in the trace
 
+* Call gzflush() only when there is a signal/exception, except of doing it on
+  every call.
+
 
 Retracing:
 
diff --git a/dump.cpp b/dump.cpp
deleted file mode 100644 (file)
index 22f62e3..0000000
--- a/dump.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-/**************************************************************************
- *
- * Copyright 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.
- *
- **************************************************************************/
-
-
-/*
- * Simple utility to dump a trace to standard output.
- */
-
-
-#include "trace_parser.hpp"
-
-
-int main(int argc, char **argv)
-{
-    for (int i = 1; i < argc; ++i) {
-        Trace::Parser p;
-        if (p.open(argv[i])) {
-            Trace::Call *call;
-            call = p.parse_call();
-            while (call) {
-                std::cout << *call;
-                delete call;
-                call = p.parse_call();
-            }
-        }
-    }
-    return 0;
-}
index 9f17c006afc05b7ecd309c4adc17013070873c34..040d06d49084feafa191c8232ad708dea3d1e3bb 100644 (file)
@@ -105,7 +105,7 @@ inline std::ostream& operator<<(std::ostream& os, const Attribute *attr) {
 }
 
 
-#ifdef WIN32
+#ifdef _WIN32
 
 #include <windows.h>
 
@@ -156,7 +156,7 @@ public:
 
 
 inline Formatter *defaultFormatter(void) {
-#ifdef WIN32
+#ifdef _WIN32
     return new WindowsFormatter;
 #else
     return new AnsiFormatter;
index 4b21083449114031498b91068c2b9af6db6d7777..d3dc89b7dfbb2776609ce9e0fc357096d5c0d326 100644 (file)
@@ -30,7 +30,7 @@
 #ifndef _GLIMPORTS_HPP_
 #define _GLIMPORTS_HPP_
 
-#ifdef WIN32
+#ifdef _WIN32
 
 #ifndef WIN32_LEAN_AND_MEAN
 #define WIN32_LEAN_AND_MEAN 1
 
 #include <windows.h>
 
-#else /* !WIN32 */
+#else /* !_WIN32 */
 
 #include <X11/Xlib.h>
 
-#endif /* !WIN32 */
+#endif /* !_WIN32 */
 
 #include <GL/gl.h>
 
@@ -52,7 +52,7 @@
 #define GL_TEXTURE_INDEX_SIZE_EXT         0x80ED
 #endif
 
-#ifdef WIN32
+#ifdef _WIN32
 
 #include <GL/wglext.h>
 
@@ -78,7 +78,7 @@ typedef struct _WGLSWAP
 
 #endif /* __MINGW32__ */
 
-#else /* !WIN32 */
+#else /* !_WIN32 */
 
 #include <GL/glx.h>
 #include <GL/glext.h>
@@ -86,6 +86,6 @@ typedef struct _WGLSWAP
 /* Prevent collision with Trace::Bool */
 #undef Bool
 
-#endif /* !WIN32 */
+#endif /* !_WIN32 */
 
 #endif /* _GLIMPORTS_HPP_ */
index fa1db1ec423f61f1908161f61097b96e1aab941d..e1e7d16f3ed164ec3369859f413f16f2c40e8feb 100644 (file)
--- a/glproc.py
+++ b/glproc.py
@@ -410,18 +410,19 @@ class GlDispatcher(Dispatcher):
 
     def header(self):
         print '#ifdef RETRACE'
-        print '#  ifdef WIN32'
+        print '#  ifdef _WIN32'
         print '#    define __getPrivateProcAddress(name) wglGetProcAddress(name)'
         print '#  else'
         print '#    define __getPrivateProcAddress(name) glXGetProcAddressARB((const GLubyte *)(name))'
         print '#  endif'
         print '#  define __abort() OS::Abort()'
         print '#else /* !RETRACE */'
-        print '#  ifdef WIN32'
+        print '#  ifdef _WIN32'
         print '#    define __getPrivateProcAddress(name) __wglGetProcAddress(name)'
         print '     static inline PROC __stdcall __wglGetProcAddress(const char * lpszProc);'
         print '#  else'
-        print '#    define __getPublicProcAddress(name) dlsym(RTLD_NEXT, name)'
+        print '     static void *libgl_handle = RTLD_NEXT;'
+        print '#    define __getPublicProcAddress(name) dlsym(libgl_handle, name)'
         print '#    define __getPrivateProcAddress(name) __glXGetProcAddressARB((const GLubyte *)(name))'
         print '     static inline __GLXextFuncPtr __glXGetProcAddressARB(const GLubyte * procName);'
         print '#  endif'
@@ -444,13 +445,13 @@ if __name__ == '__main__':
     print
     dispatcher = GlDispatcher()
     dispatcher.header()
-    print '#ifdef WIN32'
+    print '#ifdef _WIN32'
     print
     dispatcher.dispatch_api(wglapi)
-    print '#else /* !WIN32 */'
+    print '#else /* !_WIN32 */'
     print
     dispatcher.dispatch_api(glxapi)
-    print '#endif /* !WIN32 */'
+    print '#endif /* !_WIN32 */'
     print
     dispatcher.dispatch_api(glapi)
     print
index 2736a9fb52e4d6b375e321d4a6b1ff548dac1b33..0040d580c5cb169c42144e1305d165ee06d2a1ea 100644 (file)
@@ -103,7 +103,7 @@ class GlRetracer(Retracer):
         is_draw_elements = function.name in self.draw_elements_function_names
 
         if is_array_pointer or is_draw_array or is_draw_elements:
-            print '    if (Trace::Parser::version < 1) {'
+            print '    if (glretrace::parser.version < 1) {'
 
             if is_array_pointer or is_draw_array:
                 print '        GLint __array_buffer = 0;'
index 64b96af25ee61c24728fe6bbec129b0ac513896f..d85cdea343c9c1f68e4ce1b8d6a8d89148923ec7 100644 (file)
@@ -1413,22 +1413,18 @@ __gl_format_channels(GLenum format) {
     case GL_DEPTH_COMPONENT:
     case GL_STENCIL_INDEX:
         return 1;
-        break;
     case GL_LUMINANCE_ALPHA:
+    case GL_RG:
         return 2;
-        break;
     case GL_RGB:
     case GL_BGR:
         return 3;
-        break;
     case GL_RGBA:
     case GL_BGRA:
         return 4;
-        break;
     default:
         OS::DebugMessage("warning: %s: unexpected format GLenum 0x%04X\n", __FUNCTION__, format);
         return 0;
-        break;
     }
 }
 
index b54634e64efcd84985fae582cf0b4f2d27a638cb..796ec2988e5574b8c895fc65f3c68be958b8d7ef 100644 (file)
@@ -604,7 +604,7 @@ parameters = [
     ("glGet",  X,      1,      "GL_PROXY_TEXTURE_1D"), # 0x8063
     ("glGet",  X,      1,      "GL_PROXY_TEXTURE_2D"), # 0x8064
     ("glGet",  X,      1,      "GL_TEXTURE_TOO_LARGE_EXT"),    # 0x8065
-    ("glGetTexParameter",      I,      1,      "GL_TEXTURE_PRIORITY"), # 0x8066
+    ("glGetTexParameter",      F,      1,      "GL_TEXTURE_PRIORITY"), # 0x8066
     ("glGetTexParameter",      B,      1,      "GL_TEXTURE_RESIDENT"), # 0x8067
     ("glGet",  I,      1,      "GL_TEXTURE_BINDING_1D"),       # 0x8068
     ("glGet",  I,      1,      "GL_TEXTURE_BINDING_2D"),       # 0x8069
@@ -2958,6 +2958,7 @@ glGet = StateGetter('glGet', {
 
 glGetVertexAttrib = StateGetter('glGetVertexAttrib', {I: 'iv', F: 'fv', D: 'dv', P: 'Pointerv'})
 glGetTexParameter = StateGetter('glGetTexParameter', {I: 'iv', F: 'fv'})
+glGetTexLevelParameter = StateGetter('glGetTexLevelParameter', {I: 'iv', F: 'fv'})
 
 
 class JsonWriter(Visitor):
@@ -3016,6 +3017,7 @@ class StateDumper:
     def dump(self):
         print '#include <string.h>'
         print '#include <iostream>'
+        print '#include <algorithm>'
         print
         print '#include "json.hpp"'
         print '#include "glimports.hpp"'
@@ -3261,17 +3263,6 @@ writeDrawBufferImage(JSONWriter &json, GLenum format)
         print '    }'
         print
         print '    json.beginObject();'
-        print
-        print '    GLfloat param;'
-        for function, type, count, name in parameters:
-            if function != 'glGetTexParameter' or count != 1:
-                continue
-            print '        glGetTexParameterfv(target, %s, &param);' % name
-            print '        json.beginMember("%s");'  % name
-            JsonWriter().visit(type, 'param')
-            print '        json.endMember();'
-            print
-        print
         print '    json.beginMember("levels");'
         print '    json.beginArray();'
         print '    GLint level = 0;'
@@ -3290,15 +3281,6 @@ writeDrawBufferImage(JSONWriter &json, GLenum format)
         print '        json.writeNumber(texture);'
         print '        json.endMember();'
         print
-        # TODO: Generalize this
-        for function, type, count, name in parameters:
-            if function != 'glGetTexLevelParameter' or count != 1:
-                continue
-            print '        glGetTexLevelParameterfv(target, level, %s, &param);' % name
-            print '        json.beginMember("%s");'  % name
-            JsonWriter().visit(type, 'param')
-            print '        json.endMember();'
-            print
         print '        json.beginMember("image");'
         print '        writeTextureImage(json, target, level);'
         print '        json.endMember();'
@@ -3330,24 +3312,62 @@ writeDrawBufferImage(JSONWriter &json, GLenum format)
         self.dump_atoms(glGet)
         
         self.dump_vertex_attribs()
+        self.dump_texture_parameters()
 
         print '    json.endObject();'
         print '    json.endMember(); // parameters'
         print
 
     def dump_vertex_attribs(self):
-        print '    json.beginMember("GL_VERTEX_ATTRIB");'
-        print '    json.beginArray();'
         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 '        char name[32];'
+        print '        snprintf(name, sizeof name, "GL_VERTEX_ATTRIB_ARRAY%i", index);'
+        print '        json.beginMember(name);'
         print '        json.beginObject();'
         self.dump_atoms(glGetVertexAttrib, 'index')
         print '        json.endObject();'
+        print '        json.endMember(); // GL_VERTEX_ATTRIB_ARRAYi'
         print '    }'
         print
-        print '    json.endArray();'
-        print '    json.endMember(); // GL_VERTEX_ATTRIB'
+
+    def dump_texture_parameters(self):
+        print '    {'
+        print '        GLint active_texture = GL_TEXTURE0;'
+        print '        glGetIntegerv(GL_ACTIVE_TEXTURE, &active_texture);'
+        print '        GLint max_texture_coords = 0;'
+        print '        glGetIntegerv(GL_MAX_TEXTURE_COORDS, &max_texture_coords);'
+        print '        GLint max_combined_texture_image_units = 0;'
+        print '        glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_combined_texture_image_units);'
+        print '        GLint max_units = std::max(max_combined_texture_image_units, max_texture_coords);'
+        print '        for (GLint unit = 0; unit < max_units; ++unit) {'
+        print '            char name[32];'
+        print '            snprintf(name, sizeof name, "GL_TEXTURE%i", unit);'
+        print '            json.beginMember(name);'
+        print '            glActiveTexture(GL_TEXTURE0 + unit);'
+        print '            json.beginObject();'
+        print '            GLint texture;'
+        print
+        for target, binding in texture_targets:
+            print '            // %s' % target
+            print '            texture = 0;'
+            print '            glGetIntegerv(%s, &texture);' % binding
+            print '            if (glIsEnabled(%s) || texture) {' % target
+            print '                json.beginMember("%s");' % target
+            print '                json.beginObject();'
+            self.dump_atoms(glGetTexParameter, target)
+            # We only dump the first level parameters
+            self.dump_atoms(glGetTexLevelParameter, target, "0")
+            print '                json.endObject();'
+            print '                json.endMember(); // %s' % target
+            print '            }'
+            print
+        print '            json.endObject();'
+        print '            json.endMember(); // GL_TEXTUREi'
+        print '        }'
+        print '        glActiveTexture(active_texture);'
+        print '    }'
         print
 
     def dump_current_program(self):
@@ -3361,24 +3381,29 @@ writeDrawBufferImage(JSONWriter &json, GLenum format)
         print
 
     def dump_textures(self):
-        print '    json.beginMember("textures");'
-        print '    json.beginArray();'
-        print '    GLint active_texture = GL_TEXTURE0;'
-        print '    glGetIntegerv(GL_ACTIVE_TEXTURE, &active_texture);'
-        print '    GLint max_texture_coords = 0;'
-        print '    glGetIntegerv(GL_MAX_TEXTURE_COORDS, &max_texture_coords);'
-        print '    for (GLint unit = 0; unit < max_texture_coords; ++unit) {'
-        print '        glActiveTexture(GL_TEXTURE0 + unit);'
-        print '        json.beginObject();'
+        print '    {'
+        print '        json.beginMember("textures");'
+        print '        json.beginArray();'
+        print '        GLint active_texture = GL_TEXTURE0;'
+        print '        glGetIntegerv(GL_ACTIVE_TEXTURE, &active_texture);'
+        print '        GLint max_texture_coords = 0;'
+        print '        glGetIntegerv(GL_MAX_TEXTURE_COORDS, &max_texture_coords);'
+        print '        GLint max_combined_texture_image_units = 0;'
+        print '        glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_combined_texture_image_units);'
+        print '        GLint max_units = std::max(max_combined_texture_image_units, max_texture_coords);'
+        print '        for (GLint unit = 0; unit < max_units; ++unit) {'
+        print '            glActiveTexture(GL_TEXTURE0 + unit);'
+        print '            json.beginObject();'
         for target, binding in texture_targets:
-            print '        json.beginMember("%s");' % target
-            print '        writeTexture(json, %s, %s);' % (target, binding)
-            print '        json.endMember();'
-        print '        json.endObject();'
+            print '            json.beginMember("%s");' % target
+            print '            writeTexture(json, %s, %s);' % (target, binding)
+            print '            json.endMember();'
+        print '            json.endObject();'
+        print '        }'
+        print '        glActiveTexture(active_texture);'
+        print '        json.endArray();'
+        print '        json.endMember(); // texture'
         print '    }'
-        print '    glActiveTexture(active_texture);'
-        print '    json.endArray();'
-        print '    json.endMember(); // texture'
         print
 
     def dump_framebuffer(self):
index 3113f258efdcfeaf40e98f8f7b95fe3ffbf8ff5b..3f6311671a730a3f646b5029a76eeb846f9deb63 100644 (file)
@@ -110,13 +110,16 @@ class GlTracer(Tracer):
             enable_name = 'GL_%s_ARRAY' % uppercase_name
             binding_name = 'GL_%s_ARRAY_BUFFER_BINDING' % uppercase_name
             print '    // %s' % function_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) {'
+            self.array_cleanup(api, uppercase_name)
             print '            return true;'
             print '        }'
             print '    }'
+            self.array_epilog(api, uppercase_name)
             print
 
         print '    // glVertexAttribPointer'
@@ -296,7 +299,9 @@ class GlTracer(Tracer):
             function = api.get_function_by_name(function_name)
 
             print '    // %s' % function.name
-            print '    if (__glIsEnabled(%s)) {;' % enable_name
+            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) {'
@@ -312,6 +317,7 @@ class GlTracer(Tracer):
             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::BeginEnter(__%s_sig);' % (function.name,)
             for arg in function.args:
                 assert not arg.output
@@ -327,6 +333,8 @@ class GlTracer(Tracer):
             print '            Trace::EndLeave();'
             print '        }'
             print '    }'
+            self.array_epilog(api, uppercase_name)
+            self.array_trace_epilog(api, uppercase_name)
             print
 
         # Samething, but for glVertexAttribPointer
@@ -375,6 +383,66 @@ class GlTracer(Tracer):
         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 '    __glGetIntegerv(GL_MAX_TEXTURE_COORDS, &max_texture_coords);'
+            print '    for (GLint unit = 0; unit < max_texture_coords; ++unit) {'
+            print '        GLenum 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::BeginEnter(__%s_sig);' % (function.name,)
+        for arg, instance in zip(function.args, args):
+            assert not arg.output
+            print '            Trace::BeginArg(%u);' % (arg.index,)
+            dump_instance(arg.type, instance)
+            print '            Trace::EndArg();'
+        print '            Trace::EndEnter();'
+        print '            Trace::BeginLeave(__fake_call);'
+        print '            Trace::EndLeave();'
+
+
+
+
+
 
 
 
index e1a5aa59e989b726351d385fa2c36ebf7597d4e1..a5317a4b74888f56c89142b29501a3c5832e3347 100644 (file)
@@ -48,6 +48,10 @@ if __name__ == '__main__':
     print
     print '#include <stdlib.h>'
     print '#include <string.h>'
+    print
+    print '#ifndef _GNU_SOURCE'
+    print '#define _GNU_SOURCE // for dladdr'
+    print '#endif'
     print '#include <dlfcn.h>'
     print
     print '#include "trace_write.hpp"'
@@ -80,4 +84,55 @@ if __name__ == '__main__':
     print '    return procPtr;'
     print '}'
     print
+    print r'''
+
+/*
+ * 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.
+ */
+void *dlopen(const char *filename, int flag)
+{
+    typedef void * (*PFNDLOPEN)(const char *, int);
+    static PFNDLOPEN dlopen_ptr = NULL;
+    void *handle;
+
+    if (!dlopen_ptr) {
+        dlopen_ptr = (PFNDLOPEN)dlsym(RTLD_NEXT, "dlopen");
+        if (!dlopen_ptr) {
+            OS::DebugMessage("error: dlsym(RTLD_NEXT, \"dlopen\") failed\n");
+            return NULL;
+        }
+    }
+
+    handle = dlopen_ptr(filename, flag);
+
+    if (filename && handle) {
+        if (0) {
+            OS::DebugMessage("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
+            libgl_handle = 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::DebugMessage("apitrace: redirecting dlopen(\"%s\", 0x%x)\n", filename, flag);
+                handle = dlopen_ptr(info.dli_fname, flag);
+            } else {
+                OS::DebugMessage("warning: dladdr() failed\n");
+            }
+        }
+    }
+
+    return handle;
+}
+
+'''
     print '} /* extern "C" */'
index ee2a9e03b76286646e5dbdabcb0e388890951ac2..24d9c873930d358980c7750572882c3365d7f631 100644 (file)
--- a/json.hpp
+++ b/json.hpp
@@ -295,7 +295,7 @@ public:
     template<class T>
     inline void writeNumber(T n) {
         separator();
-        os << std::dec << n;
+        os << std::dec << std::setprecision(9) << n;
         value = true;
         space = ' ';
     }
diff --git a/os.hpp b/os.hpp
index 42a3daac7ce7cf09f80359c424530daded40f190..eaf571db0926f0097c5ccbae6f22c450b8be5bb5 100644 (file)
--- a/os.hpp
+++ b/os.hpp
@@ -34,7 +34,7 @@
 #include <stdarg.h>
 #include <stdio.h>
 
-#ifdef WIN32
+#ifdef _WIN32
 #ifndef snprintf
 #define snprintf _snprintf
 #endif
@@ -42,9 +42,9 @@
 #define vsnprintf _vsnprintf
 #endif
 #define PATH_SEP '\\'
-#else /* !WIN32 */
+#else /* !_WIN32 */
 #define PATH_SEP '/'
-#endif /* !WIN32 */
+#endif /* !_WIN32 */
 
 #ifndef PATH_MAX
 #define PATH_MAX 1024
index 95ec5d23795bacfd20e8b0dbfda930454b2c957e..01f383403c7af1999e820d1bb15037522d8cc6a2 100755 (executable)
 
 set -e
 
-DUMP=${DUMP:-`dirname "$0"`/dump}
+TRACEDUMP=${TRACEDUMP:-`dirname "$0"`/tracedump}
 
-$DUMP
+$TRACEDUMP
 
 stripdump () {
     # http://www.theeggeadventure.com/wikimedia/index.php/Linux_Tips#Use_sed_to_remove_ANSI_colors
-    $DUMP "$1" \
+    $TRACEDUMP "$1" \
     | sed \
         -e 's/\x1b\[[0-9]\{1,2\}\(;[0-9]\{1,2\}\)\{0,2\}m//g' \
         -e 's/\r$//g' \
index 80519737a1268334cb565ee810097f994b933398..eb770d3ff1ac47dc21ceacae2c18de37fedbe11e 100644 (file)
 namespace Trace {
 
 
-unsigned long long Parser::version = 0;
-
-
 Parser::Parser() {
     file = NULL;
     next_call_no = 0;
+    version = 0;
 }
 
 
index 78ea4273778bcc6489a3863682622a0b43b7527c..49e89087601b3148cc06ec940f6310290d4349f1 100644 (file)
@@ -28,7 +28,6 @@
 
 
 #include <iostream>
-#include <map>
 #include <list>
 #include <string>
 
@@ -62,7 +61,7 @@ protected:
     unsigned next_call_no;
 
 public:
-    static unsigned long long version;
+    unsigned long long version;
 
     Parser();
 
index 7167d35dfb8033b6c60155acd927b7937de1d04b..3187b9972ab1ab125fad58f87199de81a8bc9547 100644 (file)
@@ -352,7 +352,7 @@ void Abort(void) {
 } /* namespace Trace */
 
 
-#ifdef WIN32
+#ifdef _WIN32
 
 #if 0
 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
diff --git a/tracedump.cpp b/tracedump.cpp
new file mode 100644 (file)
index 0000000..22f62e3
--- /dev/null
@@ -0,0 +1,50 @@
+/**************************************************************************
+ *
+ * Copyright 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.
+ *
+ **************************************************************************/
+
+
+/*
+ * Simple utility to dump a trace to standard output.
+ */
+
+
+#include "trace_parser.hpp"
+
+
+int main(int argc, char **argv)
+{
+    for (int i = 1; i < argc; ++i) {
+        Trace::Parser p;
+        if (p.open(argv[i])) {
+            Trace::Call *call;
+            call = p.parse_call();
+            while (call) {
+                std::cout << *call;
+                delete call;
+                call = p.parse_call();
+            }
+        }
+    }
+    return 0;
+}