add_executable (dump dump.cpp trace_model.cpp)
 
+if (WIN32)
+    set (os os_win32.cpp)
+else (WIN32)
+    set (os os_posix.cpp)
+endif (WIN32)
 
 if (GLUT_INCLUDE_DIR)
        add_custom_command (
                ${GLUT_INCLUDE_DIR}
        )
 
-       add_executable (glretrace glretrace.cpp trace_model.cpp ${CMAKE_CURRENT_BINARY_DIR}/glproc.hpp)
+       add_executable (glretrace glretrace.cpp trace_model.cpp ${os} ${CMAKE_CURRENT_BINARY_DIR}/glproc.hpp)
 
        target_link_libraries (glretrace
                ${OPENGL_gl_LIBRARY}
 
 
 
 if __name__ == '__main__':
-    print
-    print '#include <string.h>'
-    print '#include <iostream>'
-    print
-    print '#include "glproc.hpp"'
-    print '#include <GL/glut.h>'
-    print
-    print 'static bool double_buffer = false;'
-    print 'static bool insideGlBeginEnd = false;'
-    print 'static int __window_width = 256, __window_height = 256;'
-    print 'bool __reshape_window = false;'
-    print
     print '''
+#include <string.h>
+#include <iostream>
+
+#include "glproc.hpp"
+#include <GL/glut.h>
+
+static bool double_buffer = false;
+static bool insideGlBeginEnd = false;
+
+static int __window_width = 256, __window_height = 256;
+bool __reshape_window = false;
+
+unsigned __frame = 0;
+long long __startTime = 0;
+
 static void
 checkGlError(void) {
     if (insideGlBeginEnd) {
 
 static Trace::Parser parser;
 
+static void display_noop(void) {
+}
+
 static void display(void) {
     Trace::Call *call;
 
     while ((call = parser.parse_call())) {
         if (call->name() == "glFlush") {
             glFlush();
-            return;
+            if (!double_buffer) {
+                ++__frame;
+                return;
+            }
         }
         
         if (!retrace_call(*call)) {
                     glutSwapBuffers();
                 else
                     glFlush();
+                ++__frame;
                 return;
             }
         }
     }
 
+    // Reached the end of trace
     glFlush();
+
+    long long endTime = OS::GetTime();
+    float timeInterval = (endTime - __startTime) * 1.0E-6;
+
+    std::cout << 
+        "Rendered " << __frame << " frames"
+        " in " <<  timeInterval << " secs,"
+        " average of " << (__frame/timeInterval) << " fps\\n";
+
+    glutDisplayFunc(&display_noop);
     glutIdleFunc(NULL);
 }
 
 
     for ( ; i < argc; ++i) {
         if (parser.open(argv[i])) {
+            __startTime = OS::GetTime();
             glutMainLoop();
             parser.close();
         }
 
 
 void DebugMessage(const char *format, ...);
 
+/**
+ * Get the current time in microseconds from an unknown base.
+ */
+long long GetTime(void);
+
 void Abort(void);
 
 } /* namespace OS */
 
 
 #include <string.h>
 #include <stdio.h>
-#include <unistd.h>
 #include <stdlib.h>
+
+#include <unistd.h>
+#include <sys/time.h>
 #include <pthread.h>
 
 #include "os.hpp"
-#include "trace_write.hpp"
 
 namespace OS {
 
    va_end(ap);
 }
 
+long long GetTime(void)
+{
+   struct timeval tv;
+   gettimeofday(&tv, NULL);
+   return tv.tv_usec + tv.tv_sec*1000000LL;
+}
+
 void
 Abort(void)
 {
 
 } /* namespace OS */
 
-static void _uninit(void) __attribute__((destructor));
-static void _uninit(void) {
-    Trace::Close();
-}
-
 
 #include <stdio.h>
 
 #include "os.hpp"
-#include "trace_write.hpp"
 
 
 namespace OS {
    }
 }
 
+long long GetTime(void)
+{
+   static LARGE_INTEGER frequency;
+   LARGE_INTEGER counter;
+   if(!frequency.QuadPart)
+      QueryPerformanceFrequency(&frequency);
+   QueryPerformanceCounter(&counter);
+   return counter.QuadPart*1000000LL/frequency.QuadPart;
+}
+
 void
 Abort(void)
 {
 #endif
 }
 
-
-
 } /* namespace OS */
-
-
-#if 0
-BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
-    switch(fdwReason) {
-    case DLL_PROCESS_ATTACH:
-    case DLL_THREAD_ATTACH:
-        return TRUE;
-    case DLL_THREAD_DETACH:
-        return TRUE;
-    case DLL_PROCESS_DETACH:
-        Trace::Close();
-        return TRUE;
-    }
-    (void)hinstDLL;
-    (void)lpvReserved;
-    return TRUE;
-}
-#endif
 
 }
 
 } /* namespace Trace */
+
+
+#ifdef WIN32
+
+#if 0
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
+    switch(fdwReason) {
+    case DLL_PROCESS_ATTACH:
+    case DLL_THREAD_ATTACH:
+        return TRUE;
+    case DLL_THREAD_DETACH:
+        return TRUE;
+    case DLL_PROCESS_DETACH:
+        Trace::Close();
+        return TRUE;
+    }
+    (void)hinstDLL;
+    (void)lpvReserved;
+    return TRUE;
+}
+#endif
+
+#else
+
+static void _uninit(void) __attribute__((destructor));
+static void _uninit(void) {
+    Trace::Close();
+}
+
+#endif