]> git.cworth.org Git - apitrace/commitdiff
Introduce call flags.
authorJosé Fonseca <jose.r.fonseca@gmail.com>
Wed, 30 Nov 2011 07:04:44 +0000 (07:04 +0000)
committerJosé Fonseca <jose.r.fonseca@gmail.com>
Fri, 2 Dec 2011 14:23:03 +0000 (14:23 +0000)
A central place for metainfo such as whether a call terminates a frame
or not, etc.

No trace format changes yet.  Will introduce them later after more
careful thought.

13 files changed:
CMakeLists.txt
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]
gui/apitrace.cpp
gui/apitracecall.cpp
gui/apitracecall.h

index 93ab8d13afe01d541a8d1e2e863398444cb19a5a..29df0cbfb932d7c1b97073706aad3459f9a96af6 100755 (executable)
@@ -269,6 +269,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
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..1449eda7da1e102ad70e58c36511fd8fa557c800 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 */
@@ -142,6 +144,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 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;