]> git.cworth.org Git - apitrace/commitdiff
Merge pull request #61 from prahal/gui-edit
authorzackr <zack@kde.org>
Sat, 3 Dec 2011 17:12:42 +0000 (09:12 -0800)
committerzackr <zack@kde.org>
Sat, 3 Dec 2011 17:12:42 +0000 (09:12 -0800)
gui: let the edit mode work.

26 files changed:
CMakeLists.txt
cgltrace.py
cli/cli_dump.cpp
common/formatter.hpp
common/trace_loader.cpp
common/trace_lookup.hpp [new file with mode: 0644]
common/trace_model.cpp
common/trace_model.hpp
common/trace_parser.cpp
common/trace_parser.hpp
common/trace_parser_flags.cpp [new file with mode: 0644]
dispatch.py
egltrace.py
glimports.hpp
glproc.py
glproc_egl.cpp [new file with mode: 0644]
glproc_gl.cpp [new file with mode: 0644]
glstate.cpp
glws_egl_xlib.cpp
glws_glx.cpp
glws_wgl.cpp
glxtrace.py
gui/apitrace.cpp
gui/apitracecall.cpp
gui/apitracecall.h
wgltrace.py

index 93ab8d13afe01d541a8d1e2e863398444cb19a5a..710c626ec7dbc465c626e137c2aac754038fc478 100755 (executable)
@@ -40,15 +40,14 @@ if (ENABLE_GUI)
     find_package (QJSON ${REQUIRE_GUI})
 endif ()
 
+include_directories (${OPENGL_INCLUDE_DIR})
+
 if (WIN32)
     find_package (DirectX)
 elseif (APPLE)
 else ()
     find_package (X11 REQUIRED)
 
-    set (X11_INCLUDE_DIR ${X11_INCLUDE_DIR} ${OPENGL_INCLUDE_DIR})
-    set (X11_GL_LIB ${OPENGL_gl_LIBRARY})
-
     include_directories (${X11_INCLUDE_DIR})
 
     if (ENABLE_EGL)
@@ -269,6 +268,7 @@ add_library (common STATIC
     common/trace_file_snappy.cpp
     common/trace_model.cpp
     common/trace_parser.cpp
+    common/trace_parser_flags.cpp
     common/trace_writer.cpp
     common/trace_writer_local.cpp
     common/trace_writer_model.cpp
@@ -377,6 +377,7 @@ if (WIN32)
     add_library (wgltrace MODULE specs/opengl32.def
         wgltrace.cpp
         glcaps.cpp
+        glproc_gl.cpp
         ${CMAKE_CURRENT_BINARY_DIR}/glproc.hpp
     )
     set_target_properties (wgltrace PROPERTIES
@@ -398,6 +399,7 @@ elseif (APPLE)
     add_library (cgltrace SHARED
         cgltrace.cpp
         glcaps.cpp
+        glproc_gl.cpp
         ${CMAKE_CURRENT_BINARY_DIR}/glproc.hpp
     )
 
@@ -425,6 +427,7 @@ else ()
         ${CMAKE_CURRENT_BINARY_DIR}/glproc.hpp
         glxtrace.cpp
         glcaps.cpp
+        glproc_gl.cpp
     )
 
     set_target_properties (glxtrace PROPERTIES
@@ -455,6 +458,7 @@ if (EGL_FOUND)
         ${CMAKE_CURRENT_BINARY_DIR}/glproc.hpp
         egltrace.cpp
         glcaps.cpp
+        glproc_egl.cpp
     )
 
     set_property (
@@ -516,6 +520,7 @@ set (retrace_sources
 add_executable (glretrace
     ${retrace_sources}
     ${glws_os}
+    glproc_gl.cpp
 )
 
 set_property (
@@ -529,7 +534,6 @@ target_link_libraries (glretrace
 )
 
 if (WIN32)
-    target_link_libraries (glretrace ${OPENGL_gl_LIBRARY})
 elseif (APPLE)
     target_link_libraries (glretrace
         "-framework Cocoa"
@@ -537,7 +541,7 @@ elseif (APPLE)
         ${OPENGL_gl_LIBRARY} # CGL*
     )
 else ()
-    target_link_libraries (glretrace ${OPENGL_gl_LIBRARY} ${X11_X11_LIB})
+    target_link_libraries (glretrace ${X11_X11_LIB})
 endif ()
 
 install (TARGETS glretrace RUNTIME DESTINATION bin) 
@@ -546,6 +550,7 @@ if (EGL_FOUND AND NOT WIN32 AND NOT APPLE)
     add_executable (eglretrace
         ${retrace_sources}
         glws_egl_xlib.cpp
+        glproc_egl.cpp
     )
 
     set_property (
@@ -560,8 +565,6 @@ if (EGL_FOUND AND NOT WIN32 AND NOT APPLE)
     )
 
     target_link_libraries (eglretrace
-        ${EGL_LIBRARIES}
-        ${OPENGL_gl_LIBRARY}
         ${X11_X11_LIB}
     )
 
index b6a6fd0847215e9775f195b1a40c7cb2f740c774..21007237d9e8e725152550e5ffd4a9d8da99c7b7 100644 (file)
@@ -44,12 +44,6 @@ if __name__ == '__main__':
     print
     print '#include <stdlib.h>'
     print '#include <string.h>'
-    print '#include <unistd.h>'
-    print
-    print '#ifndef _GNU_SOURCE'
-    print '#define _GNU_SOURCE // for dladdr'
-    print '#endif'
-    print '#include <dlfcn.h>'
     print
     print '#include "trace_writer.hpp"'
     print
@@ -68,62 +62,6 @@ if __name__ == '__main__':
 
     print r'''
 
-
-/*
- * Path to the true OpenGL framework
- */
-static const char *libgl_filename = "/System/Library/Frameworks/OpenGL.framework/OpenGL";
-
-
-/*
- * Handle to the true OpenGL framework.
- */
-static void *libgl_handle = NULL;
-
-
-/*
- * Lookup a libGL symbol
- */
-void * __libgl_sym(const char *symbol)
-{
-    void *result;
-
-    if (!libgl_handle) {
-        /* 
-        * Unfortunately we can't just dlopen the true dynamic library because
-        * DYLD_LIBRARY_PATH/DYLD_FRAMEWORK_PATH take precedence, even for
-        * absolute paths.  So we create a temporary symlink, and dlopen that
-        * instead.
-         */
-
-        char temp_filename[] = "/tmp/tmp.XXXXXX";
-
-        if (mktemp(temp_filename) != NULL) {
-           if (symlink(libgl_filename, temp_filename) == 0) {
-                libgl_handle = dlopen(temp_filename, RTLD_LOCAL | RTLD_NOW | RTLD_FIRST);
-                remove(temp_filename);
-            }
-        }
-
-        if (!libgl_handle) {
-            os::log("apitrace: error: couldn't load %s\n", libgl_filename);
-            os::abort();
-            return NULL;
-        }
-    }
-
-    result = dlsym(libgl_handle, symbol);
-
-    if (result == dlsym(RTLD_SELF, symbol)) {
-        os::log("apitrace: error: symbol lookup recursion\n");
-        os::abort();
-        return NULL;
-    }
-
-    return result;
-}
-
-
 PUBLIC
 void * gll_noop = 0;
 
index 5baa5ae88b44b11378f9360dc6201e8f00135488..4a7338285b26aafd0e1a0d86f2dbc7c9c986f431 100644 (file)
@@ -37,6 +37,8 @@ enum ColorOption {
 
 static ColorOption color = COLOR_OPTION_AUTO;
 
+static bool verbose = false;
+
 static const char *synopsis = "Dump given trace(s) to standard output.";
 
 static void
@@ -46,6 +48,7 @@ usage(void)
         << "usage: apitrace dump [OPTIONS] <trace-file>...\n"
         << synopsis << "\n"
         "\n"
+        "    -v, --verbose       verbose output\n"
         "    --color=<WHEN>\n"
         "    --colour=<WHEN>     Colored syntax highlighting\n"
         "                        WHEN is 'auto', 'always', or 'never'\n";
@@ -68,6 +71,9 @@ command(int argc, char *argv[])
         } else if (!strcmp(arg, "--help")) {
             usage();
             return 0;
+        } else if (strcmp(arg, "-v") == 0 ||
+                   strcmp(arg, "--verbose") == 0) {
+            verbose = true;
         } else if (!strcmp(arg, "--color=auto") ||
                    !strcmp(arg, "--colour=auto")) {
             color = COLOR_OPTION_AUTO;
@@ -106,7 +112,10 @@ command(int argc, char *argv[])
 
         trace::Call *call;
         while ((call = p.parse_call())) {
-            call->dump(std::cout, color);
+            if (verbose ||
+                !(call->flags & trace::CALL_FLAG_VERBOSE)) {
+                call->dump(std::cout, color);
+            }
             delete call;
         }
     }
index 61bafdecc2095085ec974ecb3066e7052e98dfac..59f0feac22220f53dc00474edc9f5355694fe330 100644 (file)
@@ -62,6 +62,7 @@ public:
     virtual Attribute *normal(void) const { return new Attribute; }
     virtual Attribute *bold(void) const { return new Attribute; }
     virtual Attribute *italic(void) const { return new Attribute; }
+    virtual Attribute *strike(void) const { return new Attribute; }
     virtual Attribute *color(Color) const { return new Attribute; }
 };
 
@@ -88,6 +89,7 @@ public:
     virtual Attribute *normal(void) const { return new AnsiAttribute("0m"); }
     virtual Attribute *bold(void) const { return new AnsiAttribute("1m"); }
     virtual Attribute *italic(void) const { return new AnsiAttribute("3m"); }
+    virtual Attribute *strike(void) const { return new AnsiAttribute("9m"); }
     virtual Attribute *color(Color c) const { 
         static const char *color_escapes[] = {
             "31m", /* red */
@@ -107,8 +109,39 @@ inline std::ostream& operator<<(std::ostream& os, const Attribute *attr) {
 
 #ifdef _WIN32
 
+
 #include <windows.h>
 
+
+#ifndef COMMON_LVB_LEADING_BYTE
+#define COMMON_LVB_LEADING_BYTE    0x0100
+#endif
+
+#ifndef COMMON_LVB_TRAILING_BYTE
+#define COMMON_LVB_TRAILING_BYTE   0x0200
+#endif
+
+#ifndef COMMON_LVB_GRID_HORIZONTAL
+#define COMMON_LVB_GRID_HORIZONTAL 0x0400
+#endif
+
+#ifndef COMMON_LVB_GRID_LVERTICAL
+#define COMMON_LVB_GRID_LVERTICAL  0x0800
+#endif
+
+#ifndef COMMON_LVB_GRID_RVERTICAL
+#define COMMON_LVB_GRID_RVERTICAL  0x1000
+#endif
+
+#ifndef COMMON_LVB_REVERSE_VIDEO
+#define COMMON_LVB_REVERSE_VIDEO   0x4000
+#endif
+
+#ifndef COMMON_LVB_UNDERSCORE
+#define COMMON_LVB_UNDERSCORE      0x8000
+#endif
+
+
 class WindowsAttribute : public Attribute {
 protected:
     WORD wAttributes;
@@ -142,6 +175,7 @@ public:
     virtual Attribute *normal(void) const { return new WindowsAttribute(FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED); }
     virtual Attribute *bold(void) const { return new WindowsAttribute(FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY); }
     virtual Attribute *italic(void) const { return new WindowsAttribute(FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED); }
+    virtual Attribute *strike(void) const { return new WindowsAttribute(COMMON_LVB_REVERSE_VIDEO | FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED); }
     virtual Attribute *color(Color c) const { 
         static const WORD color_escapes[] = {
             FOREGROUND_RED | FOREGROUND_INTENSITY,
index a4d23d2bdc75e4ca4ba3e4fde39799eea62fba2e..e091dce38688f1395fba51d0a67c86a96426c49c 100644 (file)
@@ -95,9 +95,7 @@ bool Loader::isCallAFrameMarker(const trace::Call *call) const
 
     switch (m_frameMarker) {
     case FrameMarker_SwapBuffers:
-        return  name.find("SwapBuffers") != std::string::npos ||
-                name == "CGLFlushDrawable" ||
-                name == "glFrameTerminatorGREMEDY";
+        return call->flags & trace::CALL_FLAG_END_FRAME;
         break;
     case FrameMarker_Flush:
         return name == "glFlush";
diff --git a/common/trace_lookup.hpp b/common/trace_lookup.hpp
new file mode 100644 (file)
index 0000000..7134778
--- /dev/null
@@ -0,0 +1,111 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+/*
+ * Helper code for function name indexed lookup tables.
+ */
+
+#ifndef _TRACE_LOOKUP_HPP_
+#define _TRACE_LOOKUP_HPP_
+
+
+#include <assert.h>
+#include <string.h>
+
+#include <algorithm>
+#include <iostream>
+
+
+namespace trace {
+
+
+/**
+ * Generic type for (name, value) pairs.
+ */
+template< class T >
+struct Entry
+{
+    const char *name;
+    T value;
+};
+
+
+/**
+ * Function object which compare entries by name.
+ */
+template< class T >
+struct EntryCompare {
+    inline bool
+    operator() (const Entry<T> & a, const Entry<T> & b) const {
+        return strcmp(a.name, b.name) < 0;
+    }
+};
+
+
+/**
+ * Lookup the entry with the given name, .
+ *
+ * The entry table must be sorted alphabetically (the same rules used by
+ * strcmp).
+ */
+template< class T, std::size_t n >
+inline const T &
+entryLookup(const char *name, const Entry<T> (& entries)[n], const T & default_)
+{
+    typedef const Entry<T> * ConstIterator;
+
+    ConstIterator first = &entries[0];
+    ConstIterator last = &entries[n];
+
+    assert(first != last);
+
+    Entry<T> reference;
+    reference.name = name;
+
+    EntryCompare<T> compare;
+
+#ifndef NDEBUG
+    for (ConstIterator it = first; it != last; ++it) {
+        ConstIterator next = it + 1;
+        if (next != last && !compare(*it, *next)) {
+            std::cerr << "error: " << it->name << " and " << next->name << " not properly sorted\n";
+            assert(0);
+        }
+    }
+#endif
+    
+    first = std::lower_bound(first, last, reference, compare);
+  
+    if (first == last || compare(reference, *first)) {
+        return default_;
+    }
+
+    return first->value;
+}
+
+
+} /* namespace trace */
+
+#endif /* _TRACE_LOOKUP_HPP_ */
index 2a381edb64e665256ad6a79d186c6d5415736555..5c6b14572d4a265c9de17b17b9b99d04133ee6d9 100644 (file)
@@ -196,6 +196,7 @@ protected:
     formatter::Attribute *normal;
     formatter::Attribute *bold;
     formatter::Attribute *italic;
+    formatter::Attribute *strike;
     formatter::Attribute *red;
     formatter::Attribute *pointer;
     formatter::Attribute *literal;
@@ -206,6 +207,7 @@ public:
         normal = formatter->normal();
         bold = formatter->bold();
         italic = formatter->italic();
+        strike = formatter->strike();
         red = formatter->color(formatter::RED);
         pointer = formatter->color(formatter::GREEN);
         literal = formatter->color(formatter::BLUE);
@@ -341,8 +343,19 @@ public:
     }
 
     void visit(Call *call) {
+        CallFlags flags = call->flags;
+
+        if (flags & CALL_FLAG_NON_REPRODUCIBLE) {
+            os << strike;
+        } else if (flags & (CALL_FLAG_FAKE | CALL_FLAG_NO_SIDE_EFFECTS)) {
+            os << normal;
+        } else {
+            os << bold;
+        }
+        os << call->sig->name << normal;
+
+        os << "(";
         const char *sep = "";
-        os << bold << call->sig->name << normal << "(";
         for (unsigned i = 0; i < call->args.size(); ++i) {
             os << sep << italic << call->sig->arg_names[i] << normal << " = ";
             if (call->args[i]) {
@@ -353,11 +366,21 @@ public:
             sep = ", ";
         }
         os << ")";
+
         if (call->ret) {
             os << " = ";
             _visit(call->ret);
         }
+        
+        if (flags & CALL_FLAG_INCOMPLETE) {
+            os << " // " << red << "incomplete" << normal;
+        }
+        
         os << "\n";
+
+        if (flags & CALL_FLAG_END_FRAME) {
+            os << "\n";
+        }
     }
 };
 
index 61ff4a6be49acabf99be57ca0a7550d3dfa5b140..f208032d371eeb1e38d4704c07dc342203b88931 100644 (file)
@@ -339,6 +339,83 @@ inline std::ostream & operator <<(std::ostream &os, Value *value) {
 }
 
 
+typedef unsigned CallFlags;
+
+/**
+ * Call flags.
+ *
+ * TODO: It might be better to to record some of these (but not all) into the
+ * trace file.
+ */
+enum {
+
+    /**
+     * Whether a call was really done by the application or not.
+     *
+     * This flag is set for fake calls -- calls not truly done by the application
+     * but emitted and recorded for completeness, to provide contextual information
+     * necessary for retracing, that would not be available through other ways.
+     *
+     * XXX: This one definetely needs to go into the trace file.
+     */
+    CALL_FLAG_FAKE                      = (1 << 0),
+
+    /**
+     * Whether this call should be retraced or ignored.
+     *
+     * This flag is set for calls which can't be safely replayed (due to incomplete
+     * information) or that have no sideffects.
+     *
+     * Some incomplete calls are unreproduceable, but not all.
+     */
+    CALL_FLAG_NON_REPRODUCIBLE         = (1 << 1),
+    
+    /**
+     * Whether this call has no side-effects, therefore don't need to be
+     * retraced.
+     *
+     * This flag is set for calls that merely query information which is not
+     * needed for posterior calls.
+     */
+    CALL_FLAG_NO_SIDE_EFFECTS            = (1 << 2),
+
+    /**
+     * Whether this call renders into the bound rendertargets.
+     */
+    CALL_FLAG_RENDER                    = (1 << 3),
+
+    /**
+     * Whether this call causes render target to be swapped.
+     *
+     * This does not mark frame termination by itself -- that's solely the
+     * responsibility of `endOfFrame` bit. 
+     *
+     * This mean that snapshots should be take prior to the call, and not
+     * after.
+     */
+    CALL_FLAG_SWAP_RENDERTARGET         = (1 << 4),
+        
+    /**
+     * Whether this call terminates a frame.
+     *
+     * XXX: This can't always be determined by the function name, so it should also
+     * go into the trace file eventually.
+     */
+    CALL_FLAG_END_FRAME                 = (1 << 5),
+
+    /**
+     * Whether this call is incomplete, i.e., it never returned.
+     */
+    CALL_FLAG_INCOMPLETE                = (1 << 6),
+
+    /**
+     * Whether this call is verbose (i.e., not usually interesting).
+     */
+    CALL_FLAG_VERBOSE                  = (1 << 7),
+};
+
+
+
 class Call
 {
 public:
@@ -347,7 +424,15 @@ public:
     std::vector<Value *> args;
     Value *ret;
 
-    Call(FunctionSig *_sig) : sig(_sig), args(_sig->num_args), ret(0) { }
+    CallFlags flags;
+
+    Call(FunctionSig *_sig, const CallFlags &_flags) :
+        sig(_sig), 
+        args(_sig->num_args), 
+        ret(0),
+        flags(_flags) {
+    }
+
     ~Call();
 
     inline const char * name(void) const {
index aabf388121cb73232f85f67d242fe8e439ed56df..1a1139d0f05a68a9253cfe900dd2a603caa4f652 100644 (file)
@@ -27,6 +27,7 @@
 
 #include <assert.h>
 #include <stdlib.h>
+#include <string.h>
 
 #include "trace_file.hpp"
 #include "trace_parser.hpp"
@@ -42,6 +43,8 @@ Parser::Parser() {
     file = NULL;
     next_call_no = 0;
     version = 0;
+
+    glGetErrorSig = NULL;
 }
 
 
@@ -164,21 +167,25 @@ void Parser::setBookmark(const ParseBookmark &bookmark) {
 
 Call *Parser::parse_call(Mode mode) {
     do {
+        Call *call;
         int c = read_byte();
         switch (c) {
         case trace::EVENT_ENTER:
             parse_enter(mode);
             break;
         case trace::EVENT_LEAVE:
-            return parse_leave(mode);
+            call = parse_leave(mode);
+            adjust_call_flags(call);
+            return call;
         default:
             std::cerr << "error: unknown event " << c << "\n";
             exit(1);
         case -1:
             if (!calls.empty()) {
-                Call *call = calls.front();
-                std::cerr << call->no << ": warning: incomplete call " << call->name() << "\n";
+                call = calls.front();
+                call->flags |= CALL_FLAG_INCOMPLETE;
                 calls.pop_front();
+                adjust_call_flags(call);
                 return call;
             }
             return NULL;
@@ -201,7 +208,8 @@ T *lookup(std::vector<T *> &map, size_t index) {
 }
 
 
-FunctionSig *Parser::parse_function_sig(void) {
+Parser::FunctionSigFlags *
+Parser::parse_function_sig(void) {
     size_t id = read_uint();
 
     FunctionSigState *sig = lookup(functions, id);
@@ -217,8 +225,21 @@ FunctionSig *Parser::parse_function_sig(void) {
             arg_names[i] = read_string();
         }
         sig->arg_names = arg_names;
+        sig->flags = lookupCallFlags(sig->name);
         sig->offset = file->currentOffset();
         functions[id] = sig;
+
+        /**
+         * Note down the signature of special functions for future reference.
+         *
+         * NOTE: If the number of comparisons increases we should move this to a
+         * separate function and use bisection.
+         */
+        if (sig->num_args == 0 &&
+            strcmp(sig->name, "glGetError") == 0) {
+            glGetErrorSig = sig;
+        }
+
     } else if (file->currentOffset() < sig->offset) {
         /* skip over the signature */
         skip_string(); /* name */
@@ -327,9 +348,9 @@ BitmaskSig *Parser::parse_bitmask_sig() {
 
 
 void Parser::parse_enter(Mode mode) {
-    FunctionSig *sig = parse_function_sig();
+    FunctionSigFlags *sig = parse_function_sig();
 
-    Call *call = new Call(sig);
+    Call *call = new Call(sig, sig->flags);
 
     call->no = next_call_no++;
 
@@ -387,6 +408,21 @@ bool Parser::parse_call_details(Call *call, Mode mode) {
 }
 
 
+/**
+ * Make adjustments to this particular call flags.
+ *
+ * NOTE: This is called per-call so no string comparisons should be done here.
+ * All name comparisons should be done when the signature is parsed instead.
+ */
+void Parser::adjust_call_flags(Call *call) {
+    // Mark glGetError() = GL_NO_ERROR as verbose
+    if (call->sig == glGetErrorSig &&
+        call->ret &&
+        call->ret->toSInt() == 0) {
+        call->flags |= CALL_FLAG_VERBOSE;
+    }
+}
+
 void Parser::parse_arg(Call *call, Mode mode) {
     unsigned index = read_uint();
     Value *value = parse_value(mode);
index 8b071f5153fce4040105023daa29d08ed5e3de25..73bb7764d6cd05195622bccd7312f4110b97133d 100644 (file)
@@ -59,6 +59,10 @@ protected:
     typedef std::list<Call *> CallList;
     CallList calls;
 
+    struct FunctionSigFlags : public FunctionSig {
+        CallFlags flags;
+    };
+
     // Helper template that extends a base signature structure, with additional
     // parsing information.
     template< class T >
@@ -69,7 +73,7 @@ protected:
         File::Offset offset;
     };
 
-    typedef SigState<FunctionSig> FunctionSigState;
+    typedef SigState<FunctionSigFlags> FunctionSigState;
     typedef SigState<StructSig> StructSigState;
     typedef SigState<EnumSig> EnumSigState;
     typedef SigState<BitmaskSig> BitmaskSigState;
@@ -84,6 +88,8 @@ protected:
     EnumMap enums;
     BitmaskMap bitmasks;
 
+    FunctionSig *glGetErrorSig;
+
     unsigned next_call_no;
 
 public:
@@ -122,11 +128,14 @@ public:
 protected:
     Call *parse_call(Mode mode);
 
-    FunctionSig *parse_function_sig(void);
+    FunctionSigFlags *parse_function_sig(void);
     StructSig *parse_struct_sig();
     EnumSig *parse_enum_sig();
     BitmaskSig *parse_bitmask_sig();
     
+    static CallFlags
+    lookupCallFlags(const char *name);
+
     Call *parse_Call(Mode mode);
 
     void parse_enter(Mode mode);
@@ -135,6 +144,8 @@ protected:
 
     bool parse_call_details(Call *call, Mode mode);
 
+    void adjust_call_flags(Call *call);
+
     void parse_arg(Call *call, Mode mode);
 
     Value *parse_value(void);
diff --git a/common/trace_parser_flags.cpp b/common/trace_parser_flags.cpp
new file mode 100644 (file)
index 0000000..3e0286f
--- /dev/null
@@ -0,0 +1,128 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+
+/**
+ * Label functions based on their name.
+ */
+
+
+#include "trace_lookup.hpp"
+#include "trace_parser.hpp"
+
+
+using namespace trace;
+
+
+/**
+ * Shortcut for SwapBuffers, which terminate and swap bound render buffer.
+ */
+#define CALL_FLAG_SWAPBUFFERS (CALL_FLAG_END_FRAME | CALL_FLAG_SWAP_RENDERTARGET)
+
+
+
+/** 
+ * Default call flags.
+ */
+const CallFlags
+defaultCallFlags = 0;
+
+
+/**
+ * Call flags lookup table.
+ */
+const Entry<CallFlags>
+callFlagTable[] = {
+    { "CGLFlushDrawable",               CALL_FLAG_END_FRAME },
+    { "eglGetProcAddress",              CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+    { "eglQueryString",                 CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+    { "eglSwapBuffers",                 CALL_FLAG_SWAPBUFFERS },
+    { "glFrameTerminatorGREMEDY",       CALL_FLAG_END_FRAME },
+    { "glGetError",                     CALL_FLAG_NO_SIDE_EFFECTS }, // verbose will be set later for GL_NO_ERROR 
+    { "glGetString",                    CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+    { "glGetStringi",                   CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+    { "glIsAsyncMarkerSGIX",            CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+    { "glIsBuffer",                     CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+    { "glIsBufferARB",                  CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+    { "glIsBufferResidentNV",           CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+    { "glIsEnabled",                    CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+    { "glIsEnabledIndexedEXT",          CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+    { "glIsEnabledi",                   CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+    { "glIsFenceAPPLE",                 CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+    { "glIsFenceNV",                    CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+    { "glIsFramebuffer",                CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+    { "glIsFramebufferEXT",             CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+    { "glIsList",                       CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+    { "glIsNameAMD",                    CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+    { "glIsNamedBufferResidentNV",      CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+    { "glIsNamedStringARB",             CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+    { "glIsObjectBufferATI",            CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+    { "glIsOcclusionQueryNV",           CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+    { "glIsProgram",                    CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+    { "glIsProgramARB",                 CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+    { "glIsProgramNV",                  CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+    { "glIsProgramPipeline",            CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+    { "glIsQuery",                      CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+    { "glIsQueryARB",                   CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+    { "glIsRenderbuffer",               CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+    { "glIsRenderbufferEXT",            CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+    { "glIsSampler",                    CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+    { "glIsShader",                     CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+    { "glIsSync",                       CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+    { "glIsTexture",                    CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+    { "glIsTextureEXT",                 CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+    { "glIsTransformFeedback",          CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+    { "glIsTransformFeedbackNV",        CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+    { "glIsVariantEnabledEXT",          CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+    { "glIsVertexArray",                CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+    { "glIsVertexArrayAPPLE",           CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+    { "glIsVertexAttribEnabledAPPLE",   CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+    { "glXGetClientString",             CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+    { "glXGetCurrentContext",           CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+    { "glXGetCurrentDisplay",           CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+    { "glXGetCurrentDrawable",          CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+    { "glXGetProcAddress",              CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+    { "glXGetProcAddressARB",           CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+    { "glXIsDirect",                    CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+    { "glXQueryExtension",              CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+    { "glXQueryExtensionsString",       CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+    { "glXQueryVersion",                CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+    { "glXSwapBuffers",                 CALL_FLAG_SWAPBUFFERS },
+    { "wglGetDefaultProcAddress",       CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+    { "wglGetProcAddress",              CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE },
+    { "wglSwapBuffers",                 CALL_FLAG_SWAPBUFFERS },
+    { "wglSwapLayerBuffers",            CALL_FLAG_SWAPBUFFERS },
+    { "wglSwapMultipleBuffers",         CALL_FLAG_SWAPBUFFERS },
+    // NOTE: New entries must be sorted alphabetically
+};
+
+
+/**
+ * Lookup call flags by name.
+ */
+CallFlags
+Parser::lookupCallFlags(const char *name) {
+    return entryLookup(name, callFlagTable, defaultCallFlags);
+}
index a2f23e92d5f126bc47162f18ce8f9d4d7f9d7645..adb16b71ab7f23682e90f53e42b7bb5d44134082 100644 (file)
@@ -61,17 +61,11 @@ class Dispatcher:
         # functions
         print '#ifdef RETRACE'
         for function in api.functions:
-            if self.is_public_function(function):
-                print '#define __%s %s' % (function.name, function.name)
-            else:
-                print '#define %s __%s' % (function.name, function.name)
+            print '#define %s __%s' % (function.name, function.name)
         print '#endif /* RETRACE */'
         print
 
     def dispatch_function(self, function):
-        if self.is_public_function(function):
-            print '#ifndef RETRACE'
-            print
         ptype = function_pointer_type(function)
         pvalue = function_pointer_value(function)
         print 'typedef ' + function.prototype('* %s' % ptype) + ';'
@@ -87,9 +81,6 @@ class Dispatcher:
         print '    %s%s(%s);' % (ret, pvalue, ', '.join([str(arg.name) for arg in function.args]))
         print '}'
         print
-        if self.is_public_function(function):
-            print '#endif /* !RETRACE */'
-            print
 
     def is_public_function(self, function):
         return True
index 1148924d7e58447adcb80a2526ca1d26abc1ab7d..de90799bf1ccc35056d94f50886e04efec3cc986 100644 (file)
@@ -110,23 +110,3 @@ if __name__ == '__main__':
     print '    return procPtr;'
     print '}'
     print
-    print r'''
-
-/*
- * Lookup a EGL or GLES symbol
- */
-void * __libegl_sym(const char *symbol)
-{
-    void *proc;
-
-    /* Always try dlsym before eglGetProcAddress as spec 3.10 says
-     * implementation may choose to also export extension functions
-     * publicly.
-     */
-    proc = dlsym(RTLD_NEXT, symbol);
-    if (!proc && symbol[0] == 'g' && symbol[1] == 'l')
-        proc = (void *) __eglGetProcAddress(symbol);
-
-    return proc;
-}
-'''
index d0dc0daa3e90b1230a19617707caabd17df4fe47..65b0aca1f2977e9ca534830d8eac982918080dec 100644 (file)
 // Prevent including system's glext.h
 #define __glext_h_
 
+
 // Some functions take GLenum disguised as GLint.  Apple noticed and fixed it
 // in the Mac OS X 10.6.x gl.h headers.  Regardless, C++ typechecking rules
 // force the wrappers to match the prototype precisely.
-#if defined(__APPLE__) && !defined(MAC_OS_X_VERSION_10_7)
-#define GLenum_int GLenum
+#if defined(__APPLE__)
+#  include <AvailabilityMacros.h> // for MAC_OS_X_VERSION_10_7
+#  if defined(MAC_OS_X_VERSION_10_7)
+#    define GLenum_int GLint
+#  else
+#    define GLenum_int GLenum
+#  endif
 #else
-#define GLenum_int GLint
+#  define GLenum_int GLint
 #endif
 
 
index 67079e45623de2e2b0bb41dac30a20b605d66874..26df9df5a38058dbee62c1b473ec27dfdcd374dd 100644 (file)
--- a/glproc.py
+++ b/glproc.py
@@ -492,38 +492,16 @@ public_symbols.update([
 class GlDispatcher(Dispatcher):
 
     def header(self):
-        print '#ifdef RETRACE'
-        print '#  if defined(TRACE_EGL)'
-        print '#    define __getPrivateProcAddress(name) eglGetProcAddress(name)'
-        print '#  elif defined(_WIN32)'
-        print '#    define __getPrivateProcAddress(name) wglGetProcAddress(name)'
-        print '#  elif defined(__APPLE__)'
-        print '#    include <dlfcn.h>'
-        print '#    define __getPrivateProcAddress(name) dlsym(RTLD_DEFAULT, name)'
-        print '#  else'
-        print '#    define __getPrivateProcAddress(name) glXGetProcAddressARB((const GLubyte *)(name))'
-        print '#  endif'
-        print '#else /* !RETRACE */'
-        print '#  if defined(TRACE_EGL)'
-        print '#    define __getPublicProcAddress(name) __libegl_sym(name)'
-        print '#    define __getPrivateProcAddress(name) __libegl_sym(name)'
-        print '     void * __libegl_sym(const char *symbol);'
-        print '#  elif defined(_WIN32)'
-        print '     PROC __getPublicProcAddress(LPCSTR lpProcName);'
-        print '#    define __getPrivateProcAddress(name) __wglGetProcAddress(name)'
-        print '     static inline PROC __stdcall __wglGetProcAddress(const char * lpszProc);'
-        print '#  else'
-        print '#    define __getPublicProcAddress(name) __libgl_sym(name)'
-        print '     void * __libgl_sym(const char *symbol);'
-        print '#    ifdef __APPLE__'
-        print '#      define __getPrivateProcAddress(name) __getPublicProcAddress(name)'
-        print '#    else'
-        print '#      define __getPrivateProcAddress(name) __glXGetProcAddressARB((const GLubyte *)(name))'
-        print '       static inline __GLXextFuncPtr __glXGetProcAddressARB(const GLubyte * procName);'
-        print '#    endif'
-        print '#  endif'
-        print '#endif /* !RETRACE */'
-        print
+        print '''
+#if defined(_WIN32)
+extern HINSTANCE __libGlHandle;
+#else
+extern void * __libGlHandle;
+#endif
+
+void * __getPublicProcAddress(const char *procName);
+void * __getPrivateProcAddress(const char *procName);
+'''
         
     def is_public_function(self, function):
         return function.name in public_symbols or function.name.startswith('CGL')
diff --git a/glproc_egl.cpp b/glproc_egl.cpp
new file mode 100644 (file)
index 0000000..4ceb2ff
--- /dev/null
@@ -0,0 +1,100 @@
+/**************************************************************************
+ *
+ * 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 "glproc.hpp"
+
+
+#if !defined(_WIN32)
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE // for dladdr
+#endif
+#include <dlfcn.h>
+#endif
+
+
+/*
+ * Handle to the true OpenGL library.
+ */
+#if defined(_WIN32)
+HINSTANCE __libGlHandle = NULL;
+#else
+void *__libGlHandle = NULL;
+#endif
+
+
+
+#if defined(_WIN32)
+
+#error Unsupported
+
+#elif defined(__APPLE__)
+
+#error Unsupported
+
+#else
+
+/*
+ * Lookup a public EGL/GL/GLES symbol
+ *
+ * The spec states that eglGetProcAddress should only be used for non-core
+ * (extensions) entry-points.  Core entry-points should be taken directly from
+ * the API specific libraries.
+ *
+ * We cannot tell here which API a symbol is meant for here (as some are
+ * exported by many).  So this code assumes that the appropriate shared
+ * libraries have been loaded previously (either dlopened with RTLD_GLOBAL, or
+ * as part of the executable dependencies), and that their symbols available
+ * for quering via dlsym(RTLD_NEXT, ...).
+ */
+void *
+__getPublicProcAddress(const char *procName)
+{
+    return dlsym(RTLD_NEXT, procName);
+}
+
+/*
+ * Lookup a private EGL/GL/GLES symbol
+ *
+ * Private symbols should always be available through eglGetProcAddress, and
+ * they are guaranteed to work with any context bound (regardless of the API).
+ *
+ * However, per issue#57, eglGetProcAddress returns garbage on some
+ * implementations, and the spec states that implementations may choose to also
+ * export extension functions publicly, so we always attempt dlsym before
+ * eglGetProcAddress to mitigate that.
+ */
+void *
+__getPrivateProcAddress(const char *procName)
+{
+    void *proc;
+    proc = dlsym(RTLD_NEXT, procName);
+    if (!proc && procName[0] == 'g' && procName[1] == 'l')
+        proc = (void *) __eglGetProcAddress(procName);
+
+    return proc;
+}
+
+#endif
diff --git a/glproc_gl.cpp b/glproc_gl.cpp
new file mode 100644 (file)
index 0000000..d032e8b
--- /dev/null
@@ -0,0 +1,230 @@
+/**************************************************************************
+ *
+ * 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 "glproc.hpp"
+
+
+#if !defined(_WIN32)
+#include <unistd.h> // for symlink
+#include <dlfcn.h>
+#endif
+
+
+/*
+ * Handle to the true OpenGL library.
+ */
+#if defined(_WIN32)
+HINSTANCE __libGlHandle = NULL;
+#else
+void *__libGlHandle = NULL;
+#endif
+
+
+
+#if defined(_WIN32)
+
+void *
+__getPublicProcAddress(const char *procName)
+{
+    if (!__libGlHandle) {
+        char szDll[MAX_PATH] = {0};
+        
+        if (!GetSystemDirectoryA(szDll, MAX_PATH)) {
+            return NULL;
+        }
+        
+        strcat(szDll, "\\\\opengl32.dll");
+        
+        __libGlHandle = LoadLibraryA(szDll);
+        if (!__libGlHandle) {
+            os::log("apitrace: error: couldn't load %s\n", szDll);
+            return NULL;
+        }
+    }
+        
+    return (void *)GetProcAddress(__libGlHandle, procName);
+}
+
+
+void *
+__getPrivateProcAddress(const char *procName) {
+    return (void *)__wglGetProcAddress(procName);
+}
+
+
+#elif defined(__APPLE__)
+
+
+/*
+ * Path to the true OpenGL framework
+ */
+static const char *libgl_filename = "/System/Library/Frameworks/OpenGL.framework/OpenGL";
+
+
+/*
+ * Lookup a libGL symbol
+ */
+void * __libgl_sym(const char *symbol)
+{
+    void *result;
+
+    if (!__libGlHandle) {
+        /* 
+         * Unfortunately we can't just dlopen the true dynamic library because
+         * DYLD_LIBRARY_PATH/DYLD_FRAMEWORK_PATH take precedence, even for
+         * absolute paths.  So we create a temporary symlink, and dlopen that
+         * instead.
+         */
+
+        char temp_filename[] = "/tmp/tmp.XXXXXX";
+
+        if (mktemp(temp_filename) != NULL) {
+            if (symlink(libgl_filename, temp_filename) == 0) {
+                __libGlHandle = dlopen(temp_filename, RTLD_LOCAL | RTLD_NOW | RTLD_FIRST);
+                remove(temp_filename);
+            }
+        }
+
+        if (!__libGlHandle) {
+            os::log("apitrace: error: couldn't load %s\n", libgl_filename);
+            os::abort();
+            return NULL;
+        }
+    }
+
+    result = dlsym(__libGlHandle, symbol);
+
+#ifndef RETRACE
+    if (result == dlsym(RTLD_SELF, symbol)) {
+        os::log("apitrace: error: symbol lookup recursion\n");
+        os::abort();
+        return NULL;
+    }
+#endif
+
+    return result;
+}
+
+
+void *
+__getPublicProcAddress(const char *procName)
+{
+    return __libgl_sym(procName);
+}
+
+void *
+__getPrivateProcAddress(const char *procName)
+{
+    return __libgl_sym(procName);
+}
+
+
+#else
+
+
+/*
+ * 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);
+}
+
+
+/*
+ * Lookup a libGL symbol
+ */
+void * __libgl_sym(const char *symbol)
+{
+    void *result;
+
+    if (!__libGlHandle) {
+        /*
+         * The app doesn't directly link against libGL.so, nor does it directly
+         * dlopen it.  So we have to load it ourselves.
+         */
+
+        const char * libgl_filename = getenv("TRACE_LIBGL");
+
+        if (!libgl_filename) {
+            /*
+             * Try to use whatever libGL.so the library is linked against.
+             */
+
+            result = dlsym(RTLD_NEXT, symbol);
+            if (result) {
+                __libGlHandle = RTLD_NEXT;
+                return result;
+            }
+
+            libgl_filename = "libGL.so.1";
+        }
+
+        /*
+         * It would have been preferable to use RTLD_LOCAL to ensure that the
+         * application can never access libGL.so symbols directly, but this
+         * won't work, given libGL.so often loads a driver specific SO and
+         * exposes symbols to it.
+         */
+
+        __libGlHandle = __dlopen(libgl_filename, RTLD_GLOBAL | RTLD_LAZY);
+        if (!__libGlHandle) {
+            os::log("apitrace: error: couldn't find libGL.so\n");
+            return NULL;
+        }
+    }
+
+    return dlsym(__libGlHandle, symbol);
+}
+
+
+void *
+__getPublicProcAddress(const char *procName)
+{
+    return __libgl_sym(procName);
+}
+
+void *
+__getPrivateProcAddress(const char *procName)
+{
+    return (void *)__glXGetProcAddressARB((const GLubyte *)procName);
+}
+
+
+#endif 
+
index 6b9c0723d0dcc8b2a18044bf6c071b9a805dd67a..329276ffdf0b38e9ba8e91fcb9a36241b80c91c8 100644 (file)
@@ -738,6 +738,7 @@ getDrawableBounds(GLint *width, GLint *height) {
 
 #else
 
+#if !TRACE_EGL
     Display *display;
     Drawable drawable;
     Window root;
@@ -760,6 +761,9 @@ getDrawableBounds(GLint *width, GLint *height) {
 
     *width = w;
     *height = h;
+#else
+    return false;
+#endif
 
 #endif
 
index 958e951b4ef6526cd1bdf6943e4eb3a8f5b7fe45..d1277058c4c9fddc5b607ed99aa4f6c9fdccb42e 100644 (file)
 
 #include <iostream>
 
-#include "glws.hpp"
+#include <dlfcn.h>
 
 #include "glproc.hpp"
+#include "glws.hpp"
 
 
 namespace glws {
@@ -136,7 +137,7 @@ public:
         eglWaitNative(EGL_CORE_NATIVE_ENGINE);
 
         EGLConfig config = static_cast<const EglVisual *>(visual)->config;
-        surface = eglCreateWindowSurface(eglDisplay, config, window, NULL);
+        surface = eglCreateWindowSurface(eglDisplay, config, (EGLNativeWindowType)window, NULL);
     }
 
     void waitForEvent(int type) {
@@ -219,8 +220,23 @@ public:
     }
 };
 
+/**
+ * Load the symbols from the specified shared object into global namespace, so
+ * that they can be later found by dlsym(RTLD_NEXT, ...);
+ */
+static void
+load(const char *filename)
+{
+    if (!dlopen(filename, RTLD_GLOBAL | RTLD_LAZY)) {
+        std::cerr << "error: unable to open " << filename << "\n";
+        exit(1);
+    }
+}
+
 void
 init(void) {
+    load("libEGL.so.1");
+
     display = XOpenDisplay(NULL);
     if (!display) {
         std::cerr << "error: unable to open display " << XDisplayName(NULL) << "\n";
@@ -229,7 +245,7 @@ init(void) {
 
     screen = DefaultScreen(display);
 
-    eglDisplay = eglGetDisplay(display);
+    eglDisplay = eglGetDisplay((EGLNativeDisplayType)display);
     if (eglDisplay == EGL_NO_DISPLAY) {
         std::cerr << "error: unable to get EGL display\n";
         XCloseDisplay(display);
@@ -320,12 +336,15 @@ createContext(const Visual *_visual, Context *shareContext, Profile profile)
 
     switch (profile) {
     case PROFILE_COMPAT:
+        load("libGL.so.1");
         eglBindAPI(EGL_OPENGL_API);
         break;
     case PROFILE_ES1:
+        load("libGLESv1_CM.so.1");
         eglBindAPI(EGL_OPENGL_ES_API);
         break;
     case PROFILE_ES2:
+        load("libGLESv2.so.2");
         eglBindAPI(EGL_OPENGL_ES_API);
         attribs.add(EGL_CONTEXT_CLIENT_VERSION, 2);
         break;
index 8a0b40306cd632939a7287f16b11aebdbe8ed41f..db24b7f535f3b4bcef50bf0ba7c0508f78172650 100644 (file)
@@ -28,9 +28,8 @@
 
 #include <iostream>
 
-#include "glws.hpp"
-
 #include "glproc.hpp"
+#include "glws.hpp"
 
 
 namespace glws {
index 2487eb077fb46016f0dafbf6c3bb08b79892f427..63ce5fea1444748ef2f6c3956d1a732cb3fdef6d 100644 (file)
@@ -23,7 +23,7 @@
  *
  **************************************************************************/
 
-#include "glimports.hpp"
+#include "glproc.hpp"
 #include "glws.hpp"
 
 
@@ -188,6 +188,10 @@ public:
 
 void
 init(void) {
+    /*
+     * OpenGL library must be loaded by the time we call GDI.
+     */
+    __libGlHandle = LoadLibraryA("OPENGL32");
 }
 
 void
index be577cb0d67f8bbf6585787cc0b9b4376584490b..c9e9518f00df5d00ee387ad686d4f994d1392c87 100644 (file)
@@ -94,12 +94,6 @@ if __name__ == '__main__':
     print r'''
 
 
-/*
- * Handle to the true libGL.so
- */
-static void *libgl_handle = NULL;
-
-
 /*
  * Invoke the true dlopen() function.
  */
@@ -145,7 +139,7 @@ void * dlopen(const char *filename, int flag)
             strcmp(filename, "libGL.so.1") == 0) {
 
             // Use the true libGL.so handle instead of RTLD_NEXT from now on
-            libgl_handle = handle;
+            __libGlHandle = handle;
 
             // Get the file path for our shared object, and use it instead
             static int dummy = 0xdeedbeef;
@@ -163,51 +157,5 @@ void * dlopen(const char *filename, int flag)
 }
 
 
-/*
- * Lookup a libGL symbol
- */
-void * __libgl_sym(const char *symbol)
-{
-    void *result;
-
-    if (!libgl_handle) {
-        /*
-         * The app doesn't directly link against libGL.so, nor does it directly
-         * dlopen it.  So we have to load it ourselves.
-         */
-
-        const char * libgl_filename = getenv("TRACE_LIBGL");
-
-        if (!libgl_filename) {
-            /*
-             * Try to use whatever libGL.so the library is linked against.
-             */
-
-            result = dlsym(RTLD_NEXT, symbol);
-            if (result) {
-                libgl_handle = RTLD_NEXT;
-                return result;
-            }
-
-            libgl_filename = "libGL.so.1";
-        }
-
-        /*
-         * It would have been preferable to use RTLD_LOCAL to ensure that the
-         * application can never access libGL.so symbols directly, but this
-         * won't work, given libGL.so often loads a driver specific SO and
-         * exposes symbols to it.
-         */
-
-        libgl_handle = __dlopen(libgl_filename, RTLD_GLOBAL | RTLD_LAZY);
-        if (!libgl_handle) {
-            os::log("apitrace: error: couldn't find libGL.so\n");
-            return NULL;
-        }
-    }
-
-    return dlsym(libgl_handle, symbol);
-}
-
 
 '''
index c94688eaa09327bb98684515dc9fc462f8473aac..5758b0750a3acb0ca743af3908bafe6a21d59796 100644 (file)
@@ -82,9 +82,7 @@ bool ApiTrace::isCallAFrameMarker(const ApiTraceCall *call,
 
     switch (marker) {
     case FrameMarker_SwapBuffers:
-        return call->name().contains(QLatin1String("SwapBuffers")) ||
-               call->name() == QLatin1String("CGLFlushDrawable") ||
-               call->name() == QLatin1String("glFrameTerminatorGREMEDY");
+        return call->flags() & trace::CALL_FLAG_END_FRAME;
     case FrameMarker_Flush:
         return call->name() == QLatin1String("glFlush");
     case FrameMarker_Finish:
index d0eb542c3583371e2d8610d0b46eb95787c5a5fd..bc88c3b4f29bc2c40fb4e78a8467d986fae64aff 100644 (file)
@@ -670,6 +670,7 @@ ApiTraceCall::ApiTraceCall(ApiTraceFrame *parentFrame,
         }
     }
     m_argValues.squeeze();
+    m_flags = call->flags;
 }
 
 ApiTraceCall::~ApiTraceCall()
@@ -785,6 +786,11 @@ QVariant ApiTraceCall::returnValue() const
     return m_returnValue;
 }
 
+trace::CallFlags ApiTraceCall::flags() const
+{
+    return m_flags;
+}
+
 QUrl ApiTraceCall::helpUrl() const
 {
     return m_signature->helpUrl();
index f017f5dffefa4f303621144980b4295d7902304e..784834b17a52764279acad5b64b9fed44241090f 100644 (file)
@@ -253,6 +253,7 @@ public:
     QStringList argNames() const;
     QVector<QVariant> arguments() const;
     QVariant returnValue() const;
+    trace::CallFlags flags() const;
     QUrl helpUrl() const;
     void setHelpUrl(const QUrl &url);
     ApiTraceFrame *parentFrame()const;
@@ -285,6 +286,7 @@ private:
     ApiTraceCallSignature *m_signature;
     QVector<QVariant> m_argValues;
     QVariant m_returnValue;
+    trace::CallFlags m_flags;
     ApiTraceFrame *m_parentFrame;
 
     QVector<QVariant> m_editedValues;
index cf2cc97e401206cd45d630cc601efeda6882ff24..d5a5248f9e1a018738a5da22ea898ae03147c6f9 100644 (file)
@@ -69,31 +69,6 @@ if __name__ == '__main__':
     print '#include "trace_writer.hpp"'
     print '#include "os.hpp"'
     print
-    print '''
-static HINSTANCE g_hDll = NULL;
-
-PROC
-__getPublicProcAddress(LPCSTR lpProcName)
-{
-    if (!g_hDll) {
-        char szDll[MAX_PATH] = {0};
-        
-        if (!GetSystemDirectoryA(szDll, MAX_PATH)) {
-            return NULL;
-        }
-        
-        strcat(szDll, "\\\\opengl32.dll");
-        
-        g_hDll = LoadLibraryA(szDll);
-        if (!g_hDll) {
-            return NULL;
-        }
-    }
-        
-    return GetProcAddress(g_hDll, lpProcName);
-}
-
-    '''
     print '// To validate our prototypes'
     print '#define GL_GLEXT_PROTOTYPES'
     print '#define WGL_GLXEXT_PROTOTYPES'