]> git.cworth.org Git - apitrace/commitdiff
Share more code between glretrace and d3dretrace.
authorJosé Fonseca <jose.r.fonseca@gmail.com>
Sun, 22 Apr 2012 08:36:59 +0000 (09:36 +0100)
committerJosé Fonseca <jose.r.fonseca@gmail.com>
Sun, 22 Apr 2012 08:36:59 +0000 (09:36 +0100)
18 files changed:
retrace/CMakeLists.txt
retrace/d3dretrace_main.cpp
retrace/glretrace.hpp
retrace/glretrace.py
retrace/glretrace_cgl.cpp
retrace/glretrace_egl.cpp
retrace/glretrace_glx.cpp
retrace/glretrace_main.cpp
retrace/glretrace_wgl.cpp
retrace/glws.cpp
retrace/glws.hpp
retrace/glws_cocoa.mm
retrace/glws_egl_xlib.cpp
retrace/glws_glx.cpp
retrace/glws_wgl.cpp
retrace/retrace.cpp
retrace/retrace.hpp
retrace/retrace_main.cpp [new file with mode: 0644]

index 8cc9cd8f2d17dbbcfe17b34f297165b703de8a5d..b5e89dc94b378954ba6e8e9fd1cfbdb231029bf7 100644 (file)
@@ -32,6 +32,19 @@ add_custom_command (
 )
 
 add_library (retrace_common
+    retrace.cpp
+    retrace_main.cpp
+    retrace_stdc.cpp
+)
+
+target_link_libraries (retrace_common
+    common
+    ${PNG_LIBRARIES}
+    ${ZLIB_LIBRARIES}
+    ${SNAPPY_LIBRARIES}
+)
+
+add_library (glretrace_common
     glretrace_gl.cpp
     glretrace_cgl.cpp
     glretrace_glx.cpp
@@ -42,12 +55,11 @@ add_library (retrace_common
     glstate_images.cpp
     glstate_params.cpp
     glstate_shaders.cpp
-    retrace.cpp
-    retrace_stdc.cpp
     glws.cpp
 )
 
-add_dependencies (retrace_common glproc)
+add_dependencies (glretrace_common glproc)
+
 
 if (WIN32 OR APPLE OR X11_FOUND)
     add_executable (glretrace
@@ -58,11 +70,8 @@ if (WIN32 OR APPLE OR X11_FOUND)
 
     target_link_libraries (glretrace
         retrace_common
+        glretrace_common
         glproc_gl
-        common
-        ${PNG_LIBRARIES}
-        ${ZLIB_LIBRARIES}
-        ${SNAPPY_LIBRARIES}
     )
 
     if (WIN32)
@@ -103,11 +112,8 @@ if (ENABLE_EGL AND X11_FOUND AND NOT WIN32 AND NOT APPLE)
 
     target_link_libraries (eglretrace
         retrace_common
+        glretrace_common
         glproc_egl
-        common
-        ${PNG_LIBRARIES}
-        ${ZLIB_LIBRARIES}
-        ${SNAPPY_LIBRARIES}
         ${X11_X11_LIB}
         ${CMAKE_THREAD_LIBS_INIT}
         dl
@@ -144,9 +150,7 @@ if (WIN32 AND DirectX_D3DX9_INCLUDE_DIR)
         d3dretrace_d3d9.cpp
     )
     target_link_libraries (d3dretrace
-        common
-        ${ZLIB_LIBRARIES}
-        ${SNAPPY_LIBRARIES}
+        retrace_common
     )
     
     install (TARGETS d3dretrace RUNTIME DESTINATION bin) 
index 133f3a7ae483678a88b13728241bc4c63e20a508..e4a8986d925f60bdd898f8bdc0bf621eafc0ad89 100644 (file)
 #include "d3dretrace.hpp"
 
 
-namespace d3dretrace {
-
-static void display(void) {
-    retrace::Retracer retracer;
-
-    retracer.addCallbacks(d3d9_callbacks);
-
-    trace::Call *call;
-
-    while ((call = retrace::parser.parse_call())) {
-        retracer.retrace(*call);
+void
+retrace::setUp(void) {
+}
 
-        delete call;
-    }
 
-    exit(0);
+void
+retrace::addCallbacks(retrace::Retracer &retracer)
+{
+    retracer.addCallbacks(d3dretrace::d3d9_callbacks);
 }
 
 
-static void usage(void) {
-    std::cout << 
-        "Usage: d3dretrace [OPTION] TRACE\n"
-        "Replay TRACE.\n"
-        "\n"
-        "  -v           increase output verbosity\n"
-    ;
+image::Image *
+retrace::getSnapshot(void) {
+    return NULL;
 }
 
 
-extern "C"
-int main(int argc, char **argv)
+bool
+retrace::dumpState(std::ostream &os)
 {
+    return false;
+}
 
-    int i;
-    for (i = 1; i < argc; ++i) {
-        const char *arg = argv[i];
-
-        if (arg[0] != '-') {
-            break;
-        }
-
-        if (!strcmp(arg, "--")) {
-            break;
-        } else if (!strcmp(arg, "--help")) {
-            usage();
-            return 0;
-        } else if (!strcmp(arg, "-v")) {
-            ++retrace::verbosity;
-        } else {
-            std::cerr << "error: unknown option " << arg << "\n";
-            usage();
-            return 1;
-        }
-    }
-
-    for ( ; i < argc; ++i) {
-        if (!retrace::parser.open(argv[i])) {
-            std::cerr << "error: failed to open " << argv[i] << "\n";
-            return 1;
-        }
-
-        display();
 
-        retrace::parser.close();
-    }
+void
+retrace::flushRendering(void) {
+}
 
-    return 0;
+void
+retrace::waitForInput(void) {
 }
 
-} /* namespace glretrace */
+void
+retrace::cleanUp(void) {
+}
index 8ba2a80edd477b8e2b418f0c21bfb76b57aace32..100d5a8991870cd1ce9ead988a103467c3f7ebab 100644 (file)
 namespace glretrace {
 
 
-extern bool double_buffer;
 extern bool insideGlBeginEnd;
 extern glws::Profile defaultProfile;
 extern glws::Visual *visual[glws::PROFILE_MAX];
 extern glws::Drawable *drawable;
 extern glws::Context *context;
 
-extern unsigned frame;
-extern long long startTime;
-extern bool wait;
-
-extern bool benchmark;
-
-extern unsigned dump_state;
-
 void
 checkGlError(trace::Call &call);
 
index e6a0b588f6289cd5fc7658f07169fb08ac4bca16..c0edb202a885fc6c6f3cf83e973a8813c5f99bfc 100644 (file)
@@ -215,7 +215,7 @@ class GlRetracer(Retracer):
 
         # Post-snapshots
         if function.name in ('glFlush', 'glFinish'):
-            print '    if (!glretrace::double_buffer) {'
+            print '    if (!retrace::doubleBuffer) {'
             print '        glretrace::frame_complete(call);'
             print '    }'
         if is_draw_array or is_draw_elements or is_misc_draw:
@@ -250,7 +250,7 @@ class GlRetracer(Retracer):
             print '    glretrace::insideGlBeginEnd = false;'
 
         if function.name.startswith('gl') and not function.name.startswith('glX'):
-            print r'    if (!glretrace::context && !retrace::benchmark && !retrace::profiling) {'
+            print r'    if (retrace::debug && !glretrace::context) {'
             print r'        retrace::warning(call) << "no current context\n";'
             print r'    }'
 
@@ -286,7 +286,7 @@ class GlRetracer(Retracer):
             print '    glretrace::insideGlBeginEnd = true;'
         elif function.name.startswith('gl'):
             # glGetError is not allowed inside glBegin/glEnd
-            print '    if (!retrace::benchmark && !retrace::profiling && !glretrace::insideGlBeginEnd) {'
+            print '    if (retrace::debug && !glretrace::insideGlBeginEnd) {'
             print '        glretrace::checkGlError(call);'
             if function.name in ('glProgramStringARB', 'glProgramStringNV'):
                 print r'        GLint error_position = -1;'
index 63b94b466d6f2804a8663f3effb67f405eeabeb4..fccd532d12ced030586bb9d7f462362f0a15e96b 100644 (file)
@@ -70,7 +70,7 @@ getContext(unsigned long long ctx) {
     it = context_map.find(ctx);
     if (it == context_map.end()) {
         glws::Context *context;
-        context_map[ctx] = context = glws::createContext(visual[glretrace::defaultProfile], sharedContext, glretrace::defaultProfile);
+        context_map[ctx] = context = glws::createContext(visual[glretrace::defaultProfile], sharedContext, glretrace::defaultProfile, retrace::debug);
         if (!sharedContext) {
             sharedContext = context;
         }
@@ -101,7 +101,7 @@ static void retrace_CGLSetCurrentContext(trace::Call &call) {
 
 static void retrace_CGLFlushDrawable(trace::Call &call) {
     if (drawable && context) {
-        if (double_buffer) {
+        if (retrace::doubleBuffer) {
             drawable->swapBuffers();
         } else {
             glFlush();
index d7b14ecad6c5e7db5861b42083e1b6b5fd3be2d5..1f8020a45ffe5c6694d012d31aba90aa6a69297e 100644 (file)
@@ -169,7 +169,7 @@ static void retrace_eglCreateContext(trace::Call &call) {
     }
 
 
-    glws::Context *context = glws::createContext(glretrace::visual[profile], share_context, profile);
+    glws::Context *context = glws::createContext(glretrace::visual[profile], share_context, profile, retrace::debug);
     if (!context) {
         const char *name;
         switch (profile) {
@@ -218,7 +218,7 @@ static void retrace_eglMakeCurrent(trace::Call &call) {
 
     if (drawable && context) {
         glFlush();
-        if (!double_buffer) {
+        if (!retrace::doubleBuffer) {
             frame_complete(call);
         }
     }
@@ -238,7 +238,7 @@ static void retrace_eglMakeCurrent(trace::Call &call) {
 static void retrace_eglSwapBuffers(trace::Call &call) {
     frame_complete(call);
 
-    if (double_buffer && drawable) {
+    if (retrace::doubleBuffer && drawable) {
         drawable->swapBuffers();
     } else {
         glFlush();
index 7342908a7cd93f73a63668c783e1097544c55cd6..20afe5107e4720d94ce5f55b8d051df4e447549a 100644 (file)
@@ -62,7 +62,7 @@ getContext(unsigned long long context_ptr) {
     ContextMap::const_iterator it;
     it = context_map.find(context_ptr);
     if (it == context_map.end()) {
-        return (context_map[context_ptr] = glws::createContext(visual[glretrace::defaultProfile], NULL, glretrace::defaultProfile));
+        return (context_map[context_ptr] = glws::createContext(visual[glretrace::defaultProfile], NULL, glretrace::defaultProfile, retrace::debug));
     }
 
     return it->second;
@@ -72,7 +72,7 @@ static void retrace_glXCreateContext(trace::Call &call) {
     unsigned long long orig_context = call.ret->toUIntPtr();
     glws::Context *share_context = getContext(call.arg(2).toUIntPtr());
 
-    glws::Context *context = glws::createContext(glretrace::visual[glretrace::defaultProfile], share_context, glretrace::defaultProfile);
+    glws::Context *context = glws::createContext(glretrace::visual[glretrace::defaultProfile], share_context, glretrace::defaultProfile, retrace::debug);
     context_map[orig_context] = context;
 }
 
@@ -80,7 +80,7 @@ static void retrace_glXCreateContextAttribsARB(trace::Call &call) {
     unsigned long long orig_context = call.ret->toUIntPtr();
     glws::Context *share_context = getContext(call.arg(2).toUIntPtr());
 
-    glws::Context *context = glws::createContext(glretrace::visual[glretrace::defaultProfile], share_context, glretrace::defaultProfile);
+    glws::Context *context = glws::createContext(glretrace::visual[glretrace::defaultProfile], share_context, glretrace::defaultProfile, retrace::debug);
     context_map[orig_context] = context;
 }
 
@@ -94,7 +94,7 @@ static void retrace_glXMakeCurrent(trace::Call &call) {
 
     if (drawable && context) {
         glFlush();
-        if (!double_buffer) {
+        if (!retrace::doubleBuffer) {
             frame_complete(call);
         }
     }
@@ -123,7 +123,7 @@ static void retrace_glXDestroyContext(trace::Call &call) {
 
 static void retrace_glXSwapBuffers(trace::Call &call) {
     frame_complete(call);
-    if (double_buffer) {
+    if (retrace::doubleBuffer) {
         drawable->swapBuffers();
     } else {
         glFlush();
@@ -134,7 +134,7 @@ static void retrace_glXCreateNewContext(trace::Call &call) {
     unsigned long long orig_context = call.ret->toUIntPtr();
     glws::Context *share_context = getContext(call.arg(3).toUIntPtr());
 
-    glws::Context *context = glws::createContext(glretrace::visual[glretrace::defaultProfile], share_context, glretrace::defaultProfile);
+    glws::Context *context = glws::createContext(glretrace::visual[glretrace::defaultProfile], share_context, glretrace::defaultProfile, retrace::debug);
     context_map[orig_context] = context;
 }
 
@@ -148,7 +148,7 @@ static void retrace_glXMakeContextCurrent(trace::Call &call) {
 
     if (drawable && context) {
         glFlush();
-        if (!double_buffer) {
+        if (!retrace::doubleBuffer) {
             frame_complete(call);
         }
     }
index 011a3549f9d0b01b81018a052599b80c14bfc2cf..429208b009ec3204da174577720605aa6a8f21dc 100644 (file)
 
 #include <string.h>
 
-#include "os_binary.hpp"
-#include "os_string.hpp"
-#include "os_time.hpp"
-#include "image.hpp"
 #include "retrace.hpp"
-#include "trace_callset.hpp"
 #include "glproc.hpp"
 #include "glstate.hpp"
 #include "glretrace.hpp"
 
 namespace glretrace {
 
-bool double_buffer = true;
 bool insideGlBeginEnd = false;
 glws::Profile defaultProfile = glws::PROFILE_COMPAT;
 glws::Visual *visual[glws::PROFILE_MAX];
 glws::Drawable *drawable = NULL;
 glws::Context *context = NULL;
 
-unsigned frame = 0;
-long long startTime = 0;
-bool wait = false;
-
-static const char *compare_prefix = NULL;
-static const char *snapshot_prefix = NULL;
-static trace::CallSet snapshot_frequency;
-static trace::CallSet compare_frequency;
-
-unsigned dump_state = ~0;
-
 void
 checkGlError(trace::Call &call) {
     GLenum error = glGetError();
@@ -139,56 +122,8 @@ updateDrawable(int width, int height) {
 }
 
 
-static void
-snapshot(unsigned call_no) {
-    assert(snapshot_prefix || compare_prefix);
-
-    if (!drawable) {
-        return;
-    }
-
-    image::Image *ref = NULL;
-
-    if (compare_prefix) {
-        os::String filename = os::String::format("%s%010u.png", compare_prefix, call_no);
-        ref = image::readPNG(filename);
-        if (!ref) {
-            return;
-        }
-        if (retrace::verbosity >= 0) {
-            std::cout << "Read " << filename << "\n";
-        }
-    }
-
-    image::Image *src = glstate::getDrawBufferImage();
-    if (!src) {
-        return;
-    }
-
-    if (snapshot_prefix) {
-        if (snapshot_prefix[0] == '-' && snapshot_prefix[1] == 0) {
-            char comment[21];
-            snprintf(comment, sizeof comment, "%u", call_no);
-            src->writePNM(std::cout, comment);
-        } else {
-            os::String filename = os::String::format("%s%010u.png", snapshot_prefix, call_no);
-            if (src->writePNG(filename) && retrace::verbosity >= 0) {
-                std::cout << "Wrote " << filename << "\n";
-            }
-        }
-    }
-
-    if (ref) {
-        std::cout << "Snapshot " << call_no << " average precision of " << src->compare(*ref) << " bits\n";
-        delete ref;
-    }
-
-    delete src;
-}
-
-
 void frame_complete(trace::Call &call) {
-    ++frame;
+    retrace::frameComplete(call);
 
     if (!drawable) {
         return;
@@ -200,190 +135,75 @@ void frame_complete(trace::Call &call) {
 }
 
 
-static void display(void) {
-    retrace::Retracer retracer;
-
-    retracer.addCallbacks(gl_callbacks);
-    retracer.addCallbacks(glx_callbacks);
-    retracer.addCallbacks(wgl_callbacks);
-    retracer.addCallbacks(cgl_callbacks);
-    retracer.addCallbacks(egl_callbacks);
-
-    startTime = os::getTime();
-    trace::Call *call;
-
-    while ((call = retrace::parser.parse_call())) {
-        bool swapRenderTarget = call->flags & trace::CALL_FLAG_SWAP_RENDERTARGET;
-        bool doSnapshot =
-            snapshot_frequency.contains(*call) ||
-            compare_frequency.contains(*call)
-        ;
-
-        // For calls which cause rendertargets to be swaped, we take the
-        // snapshot _before_ swapping the rendertargets.
-        if (doSnapshot && swapRenderTarget) {
-            if (call->flags & trace::CALL_FLAG_END_FRAME) {
-                // For swapbuffers/presents we still use this call number,
-                // spite not have been executed yet.
-                snapshot(call->no);
-            } else {
-                // Whereas for ordinate fbo/rendertarget changes we use the
-                // previous call's number.
-                snapshot(call->no - 1);
-            }
-        }
-
-        retracer.retrace(*call);
-
-        if (doSnapshot && !swapRenderTarget) {
-            snapshot(call->no);
-        }
-
-        if (!insideGlBeginEnd &&
-            drawable && context &&
-            call->no >= dump_state) {
-            glstate::dumpCurrentContext(std::cout);
-            exit(0);
-        }
-
-        delete call;
+} /* namespace glretrace */
+
+
+void
+retrace::setUp(void) {
+    if (retrace::coreProfile) {
+        glretrace::defaultProfile = glws::PROFILE_CORE;
     }
 
-    // Reached the end of trace
-    glFlush();
+    glws::init();
 
-    long long endTime = os::getTime();
-    float timeInterval = (endTime - startTime) * (1.0 / os::timeFrequency);
+    glretrace::visual[glws::PROFILE_COMPAT] = glws::createVisual(retrace::doubleBuffer, glws::PROFILE_COMPAT);
+    glretrace::visual[glws::PROFILE_CORE] = glws::createVisual(retrace::doubleBuffer, glws::PROFILE_CORE);
+    glretrace::visual[glws::PROFILE_ES1] = glws::createVisual(retrace::doubleBuffer, glws::PROFILE_ES1);
+    glretrace::visual[glws::PROFILE_ES2] = glws::createVisual(retrace::doubleBuffer, glws::PROFILE_ES2);
+}
 
-    if ((retrace::verbosity >= -1) || (retrace::profiling)) {
-        std::cout << 
-            "Rendered " << frame << " frames"
-            " in " <<  timeInterval << " secs,"
-            " average of " << (frame/timeInterval) << " fps\n";
-    }
 
-    if (wait) {
-        while (glws::processEvents()) {}
-    } else {
-        exit(0);
-    }
+void
+retrace::addCallbacks(retrace::Retracer &retracer)
+{
+    retracer.addCallbacks(glretrace::gl_callbacks);
+    retracer.addCallbacks(glretrace::glx_callbacks);
+    retracer.addCallbacks(glretrace::wgl_callbacks);
+    retracer.addCallbacks(glretrace::cgl_callbacks);
+    retracer.addCallbacks(glretrace::egl_callbacks);
 }
 
 
-static void usage(void) {
-    std::cout << 
-        "Usage: glretrace [OPTION] TRACE\n"
-        "Replay TRACE.\n"
-        "\n"
-        "  -b           benchmark mode (no error checking or warning messages)\n"
-        "  -p           profiling mode (run whole trace, dump profiling info)\n"
-        "  -c PREFIX    compare against snapshots\n"
-        "  -C CALLSET   calls to compare (default is every frame)\n"
-        "  -core        use core profile\n"
-        "  -db          use a double buffer visual (default)\n"
-        "  -sb          use a single buffer visual\n"
-        "  -s PREFIX    take snapshots; `-` for PNM stdout output\n"
-        "  -S CALLSET   calls to snapshot (default is every frame)\n"
-        "  -v           increase output verbosity\n"
-        "  -D CALLNO    dump state at specific call no\n"
-        "  -w           wait on final frame\n";
+image::Image *
+retrace::getSnapshot(void) {
+    if (!glretrace::drawable) {
+        return NULL;
+    }
+
+    return glstate::getDrawBufferImage();
 }
 
-extern "C"
-int main(int argc, char **argv)
+
+bool
+retrace::dumpState(std::ostream &os)
 {
-    assert(compare_frequency.empty());
-    assert(snapshot_frequency.empty());
-
-    int i;
-    for (i = 1; i < argc; ++i) {
-        const char *arg = argv[i];
-
-        if (arg[0] != '-') {
-            break;
-        }
-
-        if (!strcmp(arg, "--")) {
-            break;
-        } else if (!strcmp(arg, "-b")) {
-            retrace::benchmark = true;
-            retrace::verbosity = -1;
-            glws::debug = false;
-        } else if (!strcmp(arg, "-p")) {
-            retrace::profiling = true;
-            retrace::verbosity = -1;
-            glws::debug = false;
-        } else if (!strcmp(arg, "-c")) {
-            compare_prefix = argv[++i];
-            if (compare_frequency.empty()) {
-                compare_frequency = trace::CallSet(trace::FREQUENCY_FRAME);
-            }
-        } else if (!strcmp(arg, "-C")) {
-            compare_frequency = trace::CallSet(argv[++i]);
-            if (compare_prefix == NULL) {
-                compare_prefix = "";
-            }
-        } else if (!strcmp(arg, "-D")) {
-            dump_state = atoi(argv[++i]);
-            retrace::verbosity = -2;
-        } else if (!strcmp(arg, "-core")) {
-            defaultProfile = glws::PROFILE_CORE;
-        } else if (!strcmp(arg, "-db")) {
-            double_buffer = true;
-        } else if (!strcmp(arg, "-sb")) {
-            double_buffer = false;
-        } else if (!strcmp(arg, "--help")) {
-            usage();
-            return 0;
-        } else if (!strcmp(arg, "-s")) {
-            snapshot_prefix = argv[++i];
-            if (snapshot_frequency.empty()) {
-                snapshot_frequency = trace::CallSet(trace::FREQUENCY_FRAME);
-            }
-            if (snapshot_prefix[0] == '-' && snapshot_prefix[1] == 0) {
-                os::setBinaryMode(stdout);
-                retrace::verbosity = -2;
-            }
-        } else if (!strcmp(arg, "-S")) {
-            snapshot_frequency = trace::CallSet(argv[++i]);
-            if (snapshot_prefix == NULL) {
-                snapshot_prefix = "";
-            }
-        } else if (!strcmp(arg, "-v")) {
-            ++retrace::verbosity;
-        } else if (!strcmp(arg, "-w")) {
-            wait = true;
-        } else {
-            std::cerr << "error: unknown option " << arg << "\n";
-            usage();
-            return 1;
-        }
+    if (glretrace::insideGlBeginEnd ||
+        !glretrace::drawable ||
+        !glretrace::context) {
+        return false;
     }
 
-    glws::init();
-    visual[glws::PROFILE_COMPAT] = glws::createVisual(double_buffer, glws::PROFILE_COMPAT);
-    visual[glws::PROFILE_CORE] = glws::createVisual(double_buffer, glws::PROFILE_CORE);
-    visual[glws::PROFILE_ES1] = glws::createVisual(double_buffer, glws::PROFILE_ES1);
-    visual[glws::PROFILE_ES2] = glws::createVisual(double_buffer, glws::PROFILE_ES2);
+    glstate::dumpCurrentContext(os);
 
-    for ( ; i < argc; ++i) {
-        if (!retrace::parser.open(argv[i])) {
-            std::cerr << "error: failed to open " << argv[i] << "\n";
-            return 1;
-        }
+    return true;
+}
 
-        display();
+void
+retrace::flushRendering(void) {
+    glFlush();
+}
 
-        retrace::parser.close();
+void
+retrace::waitForInput(void) {
+    while (glws::processEvents()) {
     }
+}
 
+void
+retrace::cleanUp(void) {
     for (int n = 0; n < glws::PROFILE_MAX; n++) {
-        delete visual[n];
+        delete glretrace::visual[n];
     }
 
     glws::cleanup();
-
-    return 0;
 }
-
-} /* namespace glretrace */
index 447d1771f872803e1fb03982760fb3363d2e094a..5ede7e130022c1541d013c34fa3c594dd7b2fcf4 100644 (file)
@@ -56,7 +56,7 @@ getDrawable(unsigned long long hdc) {
 
 static void retrace_wglCreateContext(trace::Call &call) {
     unsigned long long orig_context = call.ret->toUIntPtr();
-    glws::Context *context = glws::createContext(glretrace::visual[glretrace::defaultProfile], NULL, glretrace::defaultProfile);
+    glws::Context *context = glws::createContext(glretrace::visual[glretrace::defaultProfile], NULL, glretrace::defaultProfile, retrace::debug);
     context_map[orig_context] = context;
 }
 
@@ -66,7 +66,7 @@ static void retrace_wglDeleteContext(trace::Call &call) {
 static void retrace_wglMakeCurrent(trace::Call &call) {
     if (drawable && context) {
         glFlush();
-        if (!double_buffer) {
+        if (!retrace::doubleBuffer) {
             frame_complete(call);
         }
     }
@@ -99,7 +99,7 @@ static void retrace_wglSetPixelFormat(trace::Call &call) {
 
 static void retrace_wglSwapBuffers(trace::Call &call) {
     frame_complete(call);
-    if (double_buffer) {
+    if (retrace::doubleBuffer) {
         drawable->swapBuffers();
     } else {
         glFlush();
@@ -114,7 +114,7 @@ static void retrace_wglShareLists(trace::Call &call) {
     glws::Context *old_context = context_map[hglrc2];
 
     glws::Context *new_context =
-        glws::createContext(old_context->visual, share_context, glretrace::defaultProfile);
+        glws::createContext(old_context->visual, share_context, glretrace::defaultProfile, retrace::debug);
     if (new_context) {
         if (context == old_context) {
             glws::makeCurrent(drawable, new_context);
@@ -223,7 +223,7 @@ static void retrace_wglCreateContextAttribsARB(trace::Call &call) {
         share_context = context_map[call.arg(1).toUIntPtr()];
     }
 
-    glws::Context *context = glws::createContext(glretrace::visual[glretrace::defaultProfile], share_context, glretrace::defaultProfile);
+    glws::Context *context = glws::createContext(glretrace::visual[glretrace::defaultProfile], share_context, glretrace::defaultProfile, retrace::debug);
     context_map[orig_context] = context;
 }
 
index c5c41ebdecb53cbb786361c158828f57ceb729f8..4e07ede9d227a856e0bffe091300906638771604 100644 (file)
@@ -30,9 +30,6 @@
 namespace glws {
 
 
-bool debug = true;
-
-
 bool
 checkExtension(const char *extName, const char *extString)
 {
index 9afebf4b878a4b639863bb08d8bf12927fbd0495..05903a7b55281b96b6d00058c844fe551a2b9f7e 100644 (file)
@@ -46,9 +46,6 @@ enum Profile {
 };
 
 
-extern bool debug;
-
-
 bool
 checkExtension(const char *extName, const char *extString);
 
@@ -155,7 +152,7 @@ Drawable *
 createDrawable(const Visual *visual, int width = 32, int height = 32);
 
 Context *
-createContext(const Visual *visual, Context *shareContext = 0, Profile profile = PROFILE_COMPAT);
+createContext(const Visual *visual, Context *shareContext = 0, Profile profile = PROFILE_COMPAT, bool debug = false);
 
 bool
 makeCurrent(Drawable *drawable, Context *context);
index 7f696fa0f36b9b0f8c48a4f822bc6df930f9f1f0..2ac30913d515e3f5405c4f8f019a62eea1fce7c9 100644 (file)
@@ -208,7 +208,7 @@ createDrawable(const Visual *visual, int width, int height)
 }
 
 Context *
-createContext(const Visual *visual, Context *shareContext, Profile profile)
+createContext(const Visual *visual, Context *shareContext, Profile profile, bool debug)
 {
     NSOpenGLPixelFormat *pixelFormat = static_cast<const CocoaVisual *>(visual)->pixelFormat;
     NSOpenGLContext *share_context = nil;
index 66557815017fda939a5edc4e622b84c7e0ee7459..0b8f34c17bc595d192d297cf5517901632abbb05 100644 (file)
@@ -356,7 +356,7 @@ createDrawable(const Visual *visual, int width, int height)
 }
 
 Context *
-createContext(const Visual *_visual, Context *shareContext, Profile profile)
+createContext(const Visual *_visual, Context *shareContext, Profile profile, bool debug)
 {
     const EglVisual *visual = static_cast<const EglVisual *>(_visual);
     EGLContext share_context = EGL_NO_CONTEXT;
index c151db1c07fb91914c070699cc79fec4bc49f076..1573bb9d69ec80c41fdb3db4d59db8d5bda2e2c4 100644 (file)
@@ -296,7 +296,7 @@ createDrawable(const Visual *visual, int width, int height)
 }
 
 Context *
-createContext(const Visual *_visual, Context *shareContext, Profile profile)
+createContext(const Visual *_visual, Context *shareContext, Profile profile, bool debug)
 {
     const GlxVisual *visual = static_cast<const GlxVisual *>(_visual);
     GLXContext share_context = NULL;
index 887a528db38dc21cbb833efb6236036b24c8bbee..c7e84c3509af42827dbccd8658ecc6c7d71e6688 100644 (file)
@@ -283,7 +283,7 @@ createDrawable(const Visual *visual, int width, int height)
 }
 
 Context *
-createContext(const Visual *visual, Context *shareContext, Profile profile)
+createContext(const Visual *visual, Context *shareContext, Profile profile, bool debug)
 {
     if (profile != PROFILE_COMPAT) {
         return NULL;
index bd3dd996a86655f1b93dc6c5219d889e6190d766..25c3f646de2dc2e5ae46f83a1ab3262c7edd4367 100644 (file)
 namespace retrace {
 
 
-trace::Parser parser;
-
-
-int verbosity = 0;
-bool benchmark = false;
-bool profiling = false;
-
-
 static bool call_dumped = false;
 
 
index f0bc4534b69d068f89518050b6361e0dfc9a0764..2f75dbe6f5285cea539f22123e0d8523fa9d8d35 100644 (file)
 #include "trace_parser.hpp"
 
 
+namespace image {
+    class Image;
+}
+
+
 namespace retrace {
 
 
@@ -185,9 +190,9 @@ toPointer(trace::Value &value, bool bind = false);
 extern int verbosity;
 
 /**
- * Avoid expensive checks when benchmarking.
+ * Debugging checks.
  */
-extern bool benchmark;
+extern bool debug;
 
 /**
  * Add profiling data to the dump when retracing.
@@ -195,6 +200,10 @@ extern bool benchmark;
 extern bool profiling;
 
 
+extern bool doubleBuffer;
+extern bool coreProfile;
+
+
 std::ostream &warning(trace::Call &call);
 
 
@@ -241,6 +250,31 @@ public:
 };
 
 
+void
+setUp(void);
+
+void
+addCallbacks(retrace::Retracer &retracer);
+
+void
+frameComplete(trace::Call &call);
+
+image::Image *
+getSnapshot(void);
+
+bool
+dumpState(std::ostream &os);
+
+void
+flushRendering(void);
+
+void
+waitForInput(void);
+
+void
+cleanUp(void);
+
+
 } /* namespace retrace */
 
 #endif /* _RETRACE_HPP_ */
diff --git a/retrace/retrace_main.cpp b/retrace/retrace_main.cpp
new file mode 100644 (file)
index 0000000..f91928b
--- /dev/null
@@ -0,0 +1,296 @@
+/**************************************************************************
+ *
+ * Copyright 2011 Jose Fonseca
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include <string.h>
+#include <iostream>
+
+#include "os_binary.hpp"
+#include "os_time.hpp"
+#include "image.hpp"
+#include "trace_callset.hpp"
+#include "trace_dump.hpp"
+#include "retrace.hpp"
+
+
+static bool wait = false;
+
+static const char *comparePrefix = NULL;
+static const char *snapshotPrefix = NULL;
+static trace::CallSet snapshotFrequency;
+static trace::CallSet compareFrequency;
+
+static unsigned dumpStateCallNo = ~0;
+
+
+namespace retrace {
+
+
+trace::Parser parser;
+
+
+int verbosity = 0;
+bool debug = true;
+bool profiling = false;
+
+
+bool doubleBuffer = true;
+bool coreProfile = false;
+
+
+static unsigned frameNo = 0;
+
+
+void
+frameComplete(trace::Call &call) {
+    ++frameNo;
+}
+
+
+static void
+takeSnapshot(unsigned call_no) {
+    assert(snapshotPrefix || comparePrefix);
+
+    image::Image *ref = NULL;
+
+    if (comparePrefix) {
+        os::String filename = os::String::format("%s%010u.png", comparePrefix, call_no);
+        ref = image::readPNG(filename);
+        if (!ref) {
+            return;
+        }
+        if (retrace::verbosity >= 0) {
+            std::cout << "Read " << filename << "\n";
+        }
+    }
+
+    image::Image *src = getSnapshot();
+    if (!src) {
+        return;
+    }
+
+    if (snapshotPrefix) {
+        if (snapshotPrefix[0] == '-' && snapshotPrefix[1] == 0) {
+            char comment[21];
+            snprintf(comment, sizeof comment, "%u", call_no);
+            src->writePNM(std::cout, comment);
+        } else {
+            os::String filename = os::String::format("%s%010u.png", snapshotPrefix, call_no);
+            if (src->writePNG(filename) && retrace::verbosity >= 0) {
+                std::cout << "Wrote " << filename << "\n";
+            }
+        }
+    }
+
+    if (ref) {
+        std::cout << "Snapshot " << call_no << " average precision of " << src->compare(*ref) << " bits\n";
+        delete ref;
+    }
+
+    delete src;
+
+    return;
+}
+
+
+static void
+mainLoop() {
+    retrace::Retracer retracer;
+
+    addCallbacks(retracer);
+
+    long long startTime = 0; 
+
+    startTime = os::getTime();
+    trace::Call *call;
+
+    while ((call = retrace::parser.parse_call())) {
+        bool swapRenderTarget = call->flags & trace::CALL_FLAG_SWAP_RENDERTARGET;
+        bool doSnapshot =
+            snapshotFrequency.contains(*call) ||
+            compareFrequency.contains(*call)
+        ;
+
+        // For calls which cause rendertargets to be swaped, we take the
+        // snapshot _before_ swapping the rendertargets.
+        if (doSnapshot && swapRenderTarget) {
+            if (call->flags & trace::CALL_FLAG_END_FRAME) {
+                // For swapbuffers/presents we still use this call number,
+                // spite not have been executed yet.
+                takeSnapshot(call->no);
+            } else {
+                // Whereas for ordinate fbo/rendertarget changes we use the
+                // previous call's number.
+                takeSnapshot(call->no - 1);
+            }
+        }
+
+        retracer.retrace(*call);
+
+        if (doSnapshot && !swapRenderTarget) {
+            takeSnapshot(call->no);
+        }
+
+        if (call->no >= dumpStateCallNo &&
+            dumpState(std::cout)) {
+            exit(0);
+        }
+
+        delete call;
+    }
+
+    // Reached the end of trace
+    flushRendering();
+
+    long long endTime = os::getTime();
+    float timeInterval = (endTime - startTime) * (1.0 / os::timeFrequency);
+
+    if ((retrace::verbosity >= -1) || (retrace::profiling)) {
+        std::cout << 
+            "Rendered " << frameNo << " frames"
+            " in " <<  timeInterval << " secs,"
+            " average of " << (frameNo/timeInterval) << " fps\n";
+    }
+
+    if (wait) {
+        waitForInput();
+    } else {
+        exit(0);
+    }
+}
+
+
+} /* namespace retrace */
+
+
+static void
+usage(const char *argv0) {
+    std::cout << 
+        "Usage: " << argv0 << " [OPTION] TRACE\n"
+        "Replay TRACE.\n"
+        "\n"
+        "  -b           benchmark mode (no error checking or warning messages)\n"
+        "  -p           profiling mode (run whole trace, dump profiling info)\n"
+        "  -c PREFIX    compare against snapshots\n"
+        "  -C CALLSET   calls to compare (default is every frame)\n"
+        "  -core        use core profile\n"
+        "  -db          use a double buffer visual (default)\n"
+        "  -sb          use a single buffer visual\n"
+        "  -s PREFIX    take snapshots; `-` for PNM stdout output\n"
+        "  -S CALLSET   calls to snapshot (default is every frame)\n"
+        "  -v           increase output verbosity\n"
+        "  -D CALLNO    dump state at specific call no\n"
+        "  -w           wait on final frame\n";
+}
+
+
+extern "C"
+int main(int argc, char **argv)
+{
+    assert(compareFrequency.empty());
+    assert(snapshotFrequency.empty());
+
+    int i;
+    for (i = 1; i < argc; ++i) {
+        const char *arg = argv[i];
+
+        if (arg[0] != '-') {
+            break;
+        }
+
+        if (!strcmp(arg, "--")) {
+            break;
+        } else if (!strcmp(arg, "-b")) {
+            retrace::debug = false;
+            retrace::verbosity = -1;
+        } else if (!strcmp(arg, "-p")) {
+            retrace::debug = false;
+            retrace::profiling = true;
+            retrace::verbosity = -1;
+        } else if (!strcmp(arg, "-c")) {
+            comparePrefix = argv[++i];
+            if (compareFrequency.empty()) {
+                compareFrequency = trace::CallSet(trace::FREQUENCY_FRAME);
+            }
+        } else if (!strcmp(arg, "-C")) {
+            compareFrequency = trace::CallSet(argv[++i]);
+            if (comparePrefix == NULL) {
+                comparePrefix = "";
+            }
+        } else if (!strcmp(arg, "-D")) {
+            dumpStateCallNo = atoi(argv[++i]);
+            retrace::verbosity = -2;
+        } else if (!strcmp(arg, "-core")) {
+            retrace::coreProfile = true;
+        } else if (!strcmp(arg, "-db")) {
+            retrace::doubleBuffer = true;
+        } else if (!strcmp(arg, "-sb")) {
+            retrace::doubleBuffer = false;
+        } else if (!strcmp(arg, "--help")) {
+            usage(argv[0]);
+            return 0;
+        } else if (!strcmp(arg, "-s")) {
+            snapshotPrefix = argv[++i];
+            if (snapshotFrequency.empty()) {
+                snapshotFrequency = trace::CallSet(trace::FREQUENCY_FRAME);
+            }
+            if (snapshotPrefix[0] == '-' && snapshotPrefix[1] == 0) {
+                os::setBinaryMode(stdout);
+                retrace::verbosity = -2;
+            }
+        } else if (!strcmp(arg, "-S")) {
+            snapshotFrequency = trace::CallSet(argv[++i]);
+            if (snapshotPrefix == NULL) {
+                snapshotPrefix = "";
+            }
+        } else if (!strcmp(arg, "-v")) {
+            ++retrace::verbosity;
+        } else if (!strcmp(arg, "-w")) {
+            wait = true;
+        } else {
+            std::cerr << "error: unknown option " << arg << "\n";
+            usage(argv[0]);
+            return 1;
+        }
+    }
+
+    retrace::setUp();
+
+    for ( ; i < argc; ++i) {
+        if (!retrace::parser.open(argv[i])) {
+            std::cerr << "error: failed to open " << argv[i] << "\n";
+            return 1;
+        }
+
+        retrace::mainLoop();
+
+        retrace::parser.close();
+    }
+
+    retrace::cleanUp();
+
+    return 0;
+}
+