]> git.cworth.org Git - apitrace/commitdiff
Merge branch 'master' into d2d
authorJosé Fonseca <jose.r.fonseca@gmail.com>
Tue, 31 Jan 2012 19:07:03 +0000 (19:07 +0000)
committerJosé Fonseca <jose.r.fonseca@gmail.com>
Tue, 31 Jan 2012 19:07:03 +0000 (19:07 +0000)
Conflicts:
compat.h

45 files changed:
CMakeLists.txt
README.markdown
cli/CMakeLists.txt
cli/cli.hpp
cli/cli_diff.cpp
cli/cli_diff_images.cpp
cli/cli_diff_state.cpp
cli/cli_dump.cpp
cli/cli_main.cpp
cli/cli_pickle.cpp [new file with mode: 0644]
cli/cli_repack.cpp
cli/cli_trace.cpp
cli/cli_trim.cpp [new file with mode: 0644]
common/os_win32.cpp
common/pickle.hpp [new file with mode: 0644]
common/trace_callset.cpp [new file with mode: 0644]
common/trace_callset.hpp [new file with mode: 0644]
common/trace_dump.cpp
common/trace_dump.hpp
common/trace_model.cpp
common/trace_model.hpp
common/trace_parser.cpp
common/trace_writer_model.cpp
compat.h
d3d10trace.py
d3d9trace.py
glretrace.hpp
glretrace.py
glretrace_main.cpp
gui/apitracecall.cpp
gui/saverthread.cpp
retrace.cpp
retrace.hpp
retrace.py
scripts/retracediff.py
scripts/tracediff.sh
scripts/unpickle.py [new file with mode: 0755]
specs/d3d10misc.py
specs/dxgi.py
specs/stdapi.py
specs/temp.py [deleted file]
thirdparty/getopt/CMakeLists.txt [new file with mode: 0644]
thirdparty/getopt/getopt.h [new file with mode: 0644]
thirdparty/getopt/getopt_long.c [new file with mode: 0644]
trace.py

index e65c529f322a39b6047c3e406eb82fbd90fadb66..c87ef70f7e959a31c26801681d352885cc33c08e 100755 (executable)
@@ -178,6 +178,12 @@ include_directories (${PNG_INCLUDE_DIR})
 add_definitions (${PNG_DEFINITIONS})
 link_libraries (${PNG_LIBRARIES})
 
+if (MSVC)
+    add_subdirectory (thirdparty/getopt EXCLUDE_FROM_ALL)
+    include_directories (${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/getopt)
+    set (GETOPT_LIBRARIES getopt_bundled)
+endif ()
+
 # The Qt website provides binaries for Windows and MacOSX, and they are
 # automatically found by cmake without any manual intervention.  The situation
 # for QJSON is substantially different: there are no binaries for QJSON
@@ -271,6 +277,7 @@ else ()
 endif ()
 
 add_library (common STATIC
+    common/trace_callset.cpp
     common/trace_dump.cpp
     common/trace_file.cpp
     common/trace_file_read.cpp
index 0a1bcebab065ecf85aa12ac15aa085ab45506417..38dfa5e21c357ae47a9187ded3d786b895a9dee4 100644 (file)
@@ -64,6 +64,34 @@ Advanced command line usage
 ===========================
 
 
+Call sets
+---------
+
+Several tools take `CALLSET` arguments, e.g:
+
+    apitrace dump --calls CALLSET foo.trace
+    glretrace -S CALLSET foo.trace
+
+The call syntax is very flexible. Here are a few examples:
+
+ * `4`             one call
+
+ * `1,2,4,5`       set of calls
+
+ * `"1 2 4 5"`     set of calls (commas are optional and can be replaced with whitespace)
+
+ * `1-100/2`       calls 1, 3, 5, ...,  99
+
+ * `1-1000/draw`   all draw calls between 1 and 1000
+
+ * `1-1000/fbo`    all fbo changes between calls 1 and 1000
+
+ * `frame`         all calls at end of frames
+
+ * `@foo.txt`      read call numbers from `foo.txt`, using the same syntax as above
+
+
+
 Tracing manually
 ----------------
 
index 3cdf52cabe081d9d1c0567deeedf16ae514b9102..af99f57aaa06c3ad17caca0822a7be31dd31304d 100644 (file)
@@ -5,8 +5,14 @@ add_executable (apitrace
     cli_diff_images.cpp
     cli_dump.cpp
     cli_pager.cpp
+    cli_pickle.cpp
     cli_repack.cpp
     cli_trace.cpp
+    cli_trim.cpp
+)
+
+target_link_libraries (apitrace
+    ${GETOPT_LIBRARIES}
 )
 
 install (TARGETS apitrace RUNTIME DESTINATION bin)
index ba2148bfa00d3adb4f5cdf73398dadceca013028..6c080e86de65683883d520661ecc728ac8a1ae2a 100644 (file)
@@ -44,7 +44,9 @@ extern const Command diff_command;
 extern const Command diff_state_command;
 extern const Command diff_images_command;
 extern const Command dump_command;
+extern const Command pickle_command;
 extern const Command repack_command;
 extern const Command trace_command;
+extern const Command trim_command;
 
 #endif /* _APITRACE_CLI_HPP_ */
index 0bd1b31f4f2c1c968b86a04d9a9470255023e57d..9f6efefa00eac2ac29e2b086161dd16b0c2a354c 100644 (file)
@@ -50,7 +50,7 @@ command(int argc, char *argv[])
 {
     int i;
 
-    for (i = 0; i < argc; ++i) {
+    for (i = 1; i < argc; ++i) {
         const char *arg = argv[i];
 
         if (arg[0] != '-') {
index 42aaaff071d6927d73c3c0c36bb3e55e3f5fc222..626a34fc7790f4a56fb5070d81f2246c9deb72db 100644 (file)
@@ -68,12 +68,12 @@ command(int argc, char *argv[])
         return 1;
     }
 
-    char **args = new char* [argc + 2];
+    char **args = new char* [argc + 1];
     args[0] = (char *) command.str();
-    for (i = 0; i < argc; i++) {
-        args[i + 1] = argv[i];
+    for (i = 1; i < argc; i++) {
+        args[i] = argv[i];
     }
-    args[i + 1] = NULL;
+    args[argc] = NULL;
 
     ret = os::execute(args);
 
index 8918d582f8195023a4e452ad94486bb009a4c82b..8536e3235c16b170388ce899ce9c651d29ae5f7c 100644 (file)
@@ -50,7 +50,7 @@ command(int argc, char *argv[])
 {
     int i;
 
-    for (i = 0; i < argc; ++i) {
+    for (i = 1; i < argc; ++i) {
         const char *arg = argv[i];
 
         if (arg[0] != '-') {
index adecb22e4abd1d0178f0f25d64a13f8d669756fe..d6f50141a3ebda2495dc0eacfddd0415bcdfac55 100644 (file)
 
 
 #include <string.h>
+#include <limits.h> // for CHAR_MAX
+#include <getopt.h>
 
 #include "cli.hpp"
 #include "cli_pager.hpp"
 
 #include "trace_parser.hpp"
 #include "trace_dump.hpp"
+#include "trace_callset.hpp"
 
 
 enum ColorOption {
@@ -44,66 +47,113 @@ static ColorOption color = COLOR_OPTION_AUTO;
 
 static bool verbose = false;
 
+static trace::CallSet calls(trace::FREQUENCY_ALL);
+
 static const char *synopsis = "Dump given trace(s) to standard output.";
 
 static void
 usage(void)
 {
     std::cout
-        << "usage: apitrace dump [OPTIONS] <trace-file>...\n"
+        << "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"
-        "    --no-arg-names      Don't dump argument names\n"
-        "    --thread-ids        Dump thread ids\n"
+        "    -h, --help           show this help message and exit\n"
+        "    -v, --verbose        verbose output\n"
+        "    --calls=CALLSET      only dump specified calls\n"
+        "    --color[=WHEN]\n"
+        "    --colour[=WHEN]      colored syntax highlighting\n"
+        "                         WHEN is 'auto', 'always', or 'never'\n"
+        "    --arg-names[=BOOL]   dump argument names [default: yes]\n"
+        "    --thread-ids=[=BOOL] dump thread ids [default: no]\n"
+        "\n"
     ;
 }
 
+enum {
+       CALLS_OPT = CHAR_MAX + 1,
+       COLOR_OPT,
+    ARG_NAMES_OPT,
+    THREAD_IDS_OPT,
+};
+
+const static char *
+shortOptions = "hv";
+
+const static struct option
+longOptions[] = {
+    {"help", no_argument, 0, 'h'},
+    {"verbose", no_argument, 0, 'v'},
+    {"calls", required_argument, 0, CALLS_OPT},
+    {"colour", optional_argument, 0, COLOR_OPT},
+    {"color", optional_argument, 0, COLOR_OPT},
+    {"arg-names", optional_argument, 0, ARG_NAMES_OPT},
+    {"thread-ids", optional_argument, 0, THREAD_IDS_OPT},
+    {0, 0, 0, 0}
+};
+
+static bool
+boolOption(const char *option, bool default_ = true) {
+    if (!option) {
+        return default_;
+    }
+    if (strcmp(option, "0") == 0 ||
+        strcmp(option, "no") == 0 ||
+        strcmp(option, "false") == 0) {
+        return false;
+    }
+    if (strcmp(option, "0") == 0 ||
+        strcmp(option, "yes") == 0 ||
+        strcmp(option, "true") == 0) {
+        return true;
+    }
+    std::cerr << "error: unexpected bool " << option << "\n";
+    return default_;
+}
+
 static int
 command(int argc, char *argv[])
 {
     trace::DumpFlags dumpFlags = 0;
     bool dumpThreadIds = false;
-
-    int i;
-
-    for (i = 0; i < argc; ++i) {
-        const char *arg = argv[i];
-
-        if (arg[0] != '-') {
-            break;
-        }
-
-        if (!strcmp(arg, "--")) {
-            break;
-        } else if (!strcmp(arg, "--help")) {
+    
+    int opt;
+    while ((opt = getopt_long(argc, argv, shortOptions, longOptions, NULL)) != -1) {
+        switch (opt) {
+        case 'h':
             usage();
             return 0;
-        } else if (strcmp(arg, "-v") == 0 ||
-                   strcmp(arg, "--verbose") == 0) {
+        case 'v':
             verbose = true;
-        } else if (!strcmp(arg, "--color=auto") ||
-                   !strcmp(arg, "--colour=auto")) {
-            color = COLOR_OPTION_AUTO;
-        } else if (!strcmp(arg, "--color") ||
-                   !strcmp(arg, "--colour") ||
-                   !strcmp(arg, "--color=always") ||
-                   !strcmp(arg, "--colour=always")) {
-            color = COLOR_OPTION_ALWAYS;
-        } else if (!strcmp(arg, "--color=never") ||
-                   !strcmp(arg, "--colour=never") ||
-                   !strcmp(arg, "--no-color") ||
-                   !strcmp(arg, "--no-colour")) {
-            color = COLOR_OPTION_NEVER;
-        } else if (!strcmp(arg, "--no-arg-names")) {
-            dumpFlags |= trace::DUMP_FLAG_NO_ARG_NAMES;
-        } else if (!strcmp(arg, "--thread-ids")) {
-            dumpThreadIds = true;
-        } else {
-            std::cerr << "error: unknown option " << arg << "\n";
+            break;
+        case CALLS_OPT:
+            calls = trace::CallSet(optarg);
+            break;
+        case COLOR_OPT:
+            if (!optarg ||
+                !strcmp(optarg, "always")) {
+                color = COLOR_OPTION_ALWAYS;
+            } else if (!strcmp(optarg, "auto")) {
+                color = COLOR_OPTION_AUTO;
+            } else if (!strcmp(optarg, "never")) {
+                color = COLOR_OPTION_NEVER;
+            } else {
+                std::cerr << "error: unknown color argument " << optarg << "\n";
+                return 1;
+            }
+            break;
+        case ARG_NAMES_OPT:
+            if (boolOption(optarg)) {
+                dumpFlags &= ~trace::DUMP_FLAG_NO_ARG_NAMES;
+            } else {
+                dumpFlags |= trace::DUMP_FLAG_NO_ARG_NAMES;
+            }
+            break;
+        case THREAD_IDS_OPT:
+            dumpThreadIds = boolOption(optarg);
+            break;
+        default:
+            std::cerr << "error: unexpected option `" << opt << "`\n";
             usage();
             return 1;
         }
@@ -122,7 +172,7 @@ command(int argc, char *argv[])
         dumpFlags |= trace::DUMP_FLAG_NO_COLOR;
     }
 
-    for (; i < argc; ++i) {
+    for (int i = optind; i < argc; ++i) {
         trace::Parser p;
 
         if (!p.open(argv[i])) {
@@ -132,12 +182,14 @@ command(int argc, char *argv[])
 
         trace::Call *call;
         while ((call = p.parse_call())) {
-            if (verbose ||
-                !(call->flags & trace::CALL_FLAG_VERBOSE)) {
-                if (dumpThreadIds) {
-                    std::cout << std::hex << call->thread_id << std::dec << " ";
+            if (calls.contains(*call)) {
+                if (verbose ||
+                    !(call->flags & trace::CALL_FLAG_VERBOSE)) {
+                    if (dumpThreadIds) {
+                        std::cout << std::hex << call->thread_id << std::dec << " ";
+                    }
+                    trace::dump(*call, std::cout, dumpFlags);
                 }
-                trace::dump(*call, std::cout, dumpFlags);
             }
             delete call;
         }
index 8f9392e49909c86478d3f6bbbaa0c34bed832e22..cff6a05de111955323219d8575ba7400d955f174 100644 (file)
@@ -70,8 +70,10 @@ static const Command * commands[] = {
     &diff_state_command,
     &diff_images_command,
     &dump_command,
+    &pickle_command,
     &repack_command,
     &trace_command,
+    &trim_command,
     &help_command
 };
 
@@ -120,12 +122,12 @@ do_help_command(int argc, char *argv[])
     const Command *command;
     int i;
 
-    if (argc != 1) {
+    if (argc != 2) {
         help_usage();
         return 0;
     }
 
-    char *command_name = argv[0];
+    char *command_name = argv[1];
 
     for (i = 0; i < ARRAY_SIZE(commands); i++) {
         command = commands[i];
@@ -170,7 +172,7 @@ main(int argc, char **argv)
         return 1;
     }
 
-    command_name = argv[i++];
+    command_name = argv[i];
 
     argc -= i;
     argv = &argv[i];
diff --git a/cli/cli_pickle.cpp b/cli/cli_pickle.cpp
new file mode 100644 (file)
index 0000000..6af879f
--- /dev/null
@@ -0,0 +1,237 @@
+/**************************************************************************
+ *
+ * Copyright 2012 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>
+
+#ifdef _WIN32
+#include <fcntl.h>
+#include <io.h>
+#endif
+
+#include "pickle.hpp"
+
+#include "cli.hpp"
+#include "cli_pager.hpp"
+
+#include "trace_parser.hpp"
+#include "trace_model.hpp"
+#include "trace_callset.hpp"
+
+
+using namespace trace;
+
+
+class PickleVisitor : public trace::Visitor
+{
+protected:
+    PickleWriter &writer;
+
+public:
+    PickleVisitor(PickleWriter &_writer) :
+        writer(_writer) {
+    }
+
+    void visit(Null *node) {
+        writer.writeInt(0);
+    }
+
+    void visit(Bool *node) {
+        writer.writeBool(node->value);
+    }
+
+    void visit(SInt *node) {
+        writer.writeInt(node->value);
+    }
+
+    void visit(UInt *node) {
+        writer.writeInt(node->value);
+    }
+
+    void visit(Float *node) {
+        writer.writeFloat(node->value);
+    }
+
+    void visit(Double *node) {
+        writer.writeFloat(node->value);
+    }
+
+    void visit(String *node) {
+        writer.writeString(node->value);
+    }
+
+    void visit(Enum *node) {
+        // TODO: keep symbolic name
+        writer.writeInt(node->value);
+    }
+
+    void visit(Bitmask *node) {
+        // TODO: keep symbolic name
+        writer.writeInt(node->value);
+    }
+
+    void visit(Struct *node) {
+        writer.beginDict();
+        for (unsigned i = 0; i < node->sig->num_members; ++i) {
+            writer.beginItem(node->sig->member_names[i]);
+            _visit(node->members[i]);
+            writer.endItem();
+        }
+        writer.endDict();
+    }
+
+    void visit(Array *node) {
+        writer.beginList();
+        for (std::vector<Value *>::iterator it = node->values.begin(); it != node->values.end(); ++it) {
+            _visit(*it);
+        }
+        writer.endList();
+    }
+
+    void visit(Blob *node) {
+        writer.writeString((const char *)node->buf, node->size);
+    }
+
+    void visit(Pointer *node) {
+        writer.writeInt(node->value);
+    }
+
+    void visit(Call *call) {
+        writer.beginTuple();
+
+        writer.writeInt(call->no);
+
+        writer.writeString(call->name());
+
+        writer.beginList();
+        for (unsigned i = 0; i < call->args.size(); ++i) {
+            if (call->args[i].value) {
+                _visit(call->args[i].value);
+            } else {
+                writer.writeNone();
+            }
+        }
+        writer.endList();
+
+        if (call->ret) {
+            _visit(call->ret);
+        } else {
+            writer.writeNone();
+        }
+
+        writer.endTuple();
+    }
+};
+
+
+static trace::CallSet calls(trace::FREQUENCY_ALL);
+
+static const char *synopsis = "Pickle given trace(s) to standard output.";
+
+static void
+usage(void)
+{
+    std::cout
+        << "usage: apitrace pickle [OPTIONS] <trace-file>...\n"
+        << synopsis << "\n"
+        "\n"
+        "    --calls <CALLSET>   Only pickle specified calls\n"
+    ;
+}
+
+static int
+command(int argc, char *argv[])
+{
+    int i;
+
+    for (i = 1; i < argc;) {
+        const char *arg = argv[i];
+
+        if (arg[0] != '-') {
+            break;
+        }
+
+        ++i;
+
+        if (!strcmp(arg, "--")) {
+            break;
+        } else if (!strcmp(arg, "--help")) {
+            usage();
+            return 0;
+        } else if (!strcmp(arg, "--calls")) {
+            calls = trace::CallSet(argv[i++]);
+        } else {
+            std::cerr << "error: unknown option " << arg << "\n";
+            usage();
+            return 1;
+        }
+    }
+
+#ifdef _WIN32
+    // Set stdout in binary mode
+    fflush(stdout);
+    int mode = _setmode(_fileno(stdout), _O_BINARY);
+    if (mode == -1) {
+        std::cerr << "warning: failed to set stdout in binary mode\n";
+    }
+#endif
+
+    for (; i < argc; ++i) {
+        trace::Parser parser;
+
+        if (!parser.open(argv[i])) {
+            std::cerr << "error: failed to open " << argv[i] << "\n";
+            return 1;
+        }
+
+        trace::Call *call;
+        while ((call = parser.parse_call())) {
+            if (calls.contains(*call)) {
+                PickleWriter writer(std::cout);
+                PickleVisitor visitor(writer);
+                
+                visitor.visit(call);
+            }
+            delete call;
+        }
+    }
+
+#ifdef _WIN32
+    std::cout.flush();
+    fflush(stdout);
+    if (mode != -1) {
+        _setmode(_fileno(stdout), mode);
+    }
+#endif
+
+    return 0;
+}
+
+const Command pickle_command = {
+    "pickle",
+    synopsis,
+    usage,
+    command
+};
index 918f54a830b0a347c8e35d650360fc05dc712ba3..a92723d60ddaa59af5c43c0adf2bd0db77ac2f85 100644 (file)
@@ -80,7 +80,7 @@ command(int argc, char *argv[])
 {
     int i;
 
-    for (i = 0; i < argc; ++i) {
+    for (i = 1; i < argc; ++i) {
         const char *arg = argv[i];
 
         if (arg[0] != '-') {
index 92251b4bef0ad6cd10b4d9b924a0414f27b9e67b..68526cb4b01c69a5ce559f93a2227434d20cfe90 100644 (file)
@@ -64,7 +64,7 @@ command(int argc, char *argv[])
     const char *output = NULL;
     int i;
 
-    for (i = 0; i < argc; ) {
+    for (i = 1; i < argc; ) {
         const char *arg = argv[i];
 
         if (arg[0] != '-') {
diff --git a/cli/cli_trim.cpp b/cli/cli_trim.cpp
new file mode 100644 (file)
index 0000000..515b4b6
--- /dev/null
@@ -0,0 +1,130 @@
+/**************************************************************************
+ *
+ * Copyright 2010 VMware, Inc.
+ * Copyright 2011 Intel corporation
+ * 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 "cli.hpp"
+
+#include "os_string.hpp"
+
+#include "trace_callset.hpp"
+#include "trace_parser.hpp"
+#include "trace_writer.hpp"
+
+static const char *synopsis = "Create a new trace by trimming an existing trace.";
+
+static void
+usage(void)
+{
+    std::cout
+        << "usage: apitrace trim [OPTIONS] <trace-file>...\n"
+        << synopsis << "\n"
+        "\n"
+        "       --calls <CALLSET>     Only trim specified calls\n"
+        "    -o --output <TRACEFILE>  Output trace file\n"
+        "\n"
+    ;
+}
+
+static int
+command(int argc, char *argv[])
+{
+    std::string output;
+    trace::CallSet calls(trace::FREQUENCY_ALL);
+    int i;
+
+    for (i = 1; i < argc;) {
+        const char *arg = argv[i];
+
+        if (arg[0] != '-') {
+            break;
+        }
+
+        ++i;
+
+        if (!strcmp(arg, "--")) {
+            break;
+        } else if (!strcmp(arg, "--help")) {
+            usage();
+            return 0;
+        } else if (!strcmp(arg, "--calls")) {
+            calls = trace::CallSet(argv[i++]);
+        } else if (!strcmp(arg, "-o") ||
+                   !strcmp(arg, "--output")) {
+            output = argv[i++];
+        } else {
+            std::cerr << "error: unknown option " << arg << "\n";
+            usage();
+            return 1;
+        }
+    }
+
+    if (i >= argc) {
+        std::cerr << "Error: apitrace trim requires a trace file as an argument.\n";
+        usage();
+        return 1;
+    }
+
+    for ( ; i < argc; ++i) {
+        trace::Parser p;
+        if (!p.open(argv[i])) {
+            std::cerr << "error: failed to open " << argv[i] << "\n";
+            return 1;
+        }
+
+        if (output.empty()) {
+            os::String base(argv[i]);
+            base.trimExtension();
+
+            output = std::string(base.str()) + std::string("-trim.trace");
+        }
+
+        trace::Writer writer;
+        if (!writer.open(output.c_str())) {
+            std::cerr << "error: failed to create " << argv[i] << "\n";
+            return 1;
+        }
+
+        trace::Call *call;
+        while ((call = p.parse_call())) {
+            if (calls.contains(*call)) {
+                writer.writeCall(call);
+            }
+            delete call;
+        }
+
+        std::cout << "Trimmed trace is available as " << output << "\n";
+    }
+
+    return 0;
+}
+
+const Command trim_command = {
+    "trim",
+    synopsis,
+    usage,
+    command
+};
index 199ae5a7e4a656be9b41c24d8c53090acabe0360..33fe427bad7370784d32c42c416e172ed97bcd89 100644 (file)
@@ -255,6 +255,15 @@ unhandledExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo)
         return EXCEPTION_CONTINUE_SEARCH;
     }
 
+    /*
+     * Ignore thread naming exception.
+     *
+     * http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
+     */
+    if (pExceptionRecord->ExceptionCode == 0x406d1388) {
+        return EXCEPTION_CONTINUE_SEARCH;
+    }
+
     // Clear direction flag
 #ifdef _MSC_VER
 #ifndef _WIN64
diff --git a/common/pickle.hpp b/common/pickle.hpp
new file mode 100644 (file)
index 0000000..f333960
--- /dev/null
@@ -0,0 +1,310 @@
+/**************************************************************************
+ *
+ * Copyright 2012 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.
+ *
+ **************************************************************************/
+
+/*
+ * Python pickle writer
+ */
+
+#ifndef _PICKLE_HPP_
+#define _PICKLE_HPP_
+
+#include <assert.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include <ostream>
+#include <string>
+
+
+class PickleWriter
+{
+private:
+    std::ostream &os;
+
+    /*
+     * Python pickle opcodes.  See pickle.py and pickletools.py from Python
+     * standard library for details.
+     */
+    enum Opcode {
+        MARK            = '(',
+        STOP            = '.',
+        POP             = '0',
+        POP_MARK        = '1',
+        DUP             = '2',
+        FLOAT           = 'F',
+        INT             = 'I',
+        BININT          = 'J',
+        BININT1         = 'K',
+        LONG            = 'L',
+        BININT2         = 'M',
+        NONE            = 'N',
+        PERSID          = 'P',
+        BINPERSID       = 'Q',
+        REDUCE          = 'R',
+        STRING          = 'S',
+        BINSTRING       = 'T',
+        SHORT_BINSTRING = 'U',
+        UNICODE         = 'V',
+        BINUNICODE      = 'X',
+        APPEND          = 'a',
+        BUILD           = 'b',
+        GLOBAL          = 'c',
+        DICT            = 'd',
+        EMPTY_DICT      = '}',
+        APPENDS         = 'e',
+        GET             = 'g',
+        BINGET          = 'h',
+        INST            = 'i',
+        LONG_BINGET     = 'j',
+        LIST            = 'l',
+        EMPTY_LIST      = ']',
+        OBJ             = 'o',
+        PUT             = 'p',
+        BINPUT          = 'q',
+        LONG_BINPUT     = 'r',
+        SETITEM         = 's',
+        TUPLE           = 't',
+        EMPTY_TUPLE     = ')',
+        SETITEMS        = 'u',
+        BINFLOAT        = 'G',
+
+        PROTO           = '\x80',
+        NEWOBJ          = '\x81',
+        EXT1            = '\x82',
+        EXT2            = '\x83',
+        EXT4            = '\x84',
+        TUPLE1          = '\x85',
+        TUPLE2          = '\x86',
+        TUPLE3          = '\x87',
+        NEWTRUE         = '\x88',
+        NEWFALSE        = '\x89',
+        LONG1           = '\x8a',
+        LONG4           = '\x8b',
+    };
+
+public:
+    PickleWriter(std::ostream &_os) :
+        os(_os)
+    {
+        os.put(PROTO);
+        os.put(2);
+    }
+
+    ~PickleWriter() {
+        os.put(STOP);
+    }
+
+    inline void beginDict() {
+        os.put(EMPTY_DICT);
+        os.put(BINPUT);
+        os.put(1);
+    }
+
+    inline void endDict() {
+    }
+
+    inline void beginItem() {
+    }
+
+    inline void beginItem(const char * name) {
+        writeString(name);
+    }
+
+    inline void beginItem(const std::string &name) {
+        beginItem(name.c_str());
+    }
+
+    inline void endItem(void) {
+        os.put(SETITEM);
+    }
+
+    inline void beginList() {
+        os.put(EMPTY_LIST);
+        os.put(BINPUT);
+        os.put(1);
+        os.put(MARK);
+    }
+
+    inline void endList(void) {
+        os.put(APPENDS);
+    }
+
+    inline void beginTuple() {
+        os.put(MARK);
+    }
+
+    inline void endTuple(void) {
+        os.put(TUPLE);
+    }
+
+    inline void writeString(const char *s, size_t length) {
+        if (!s) {
+            writeNone();
+            return;
+        }
+
+        if (length < 256) {
+            os.put(SHORT_BINSTRING);
+            os.put(length);
+        } else {
+            os.put(BINSTRING);
+            putInt32(length);
+        }
+        os.write(s, length);
+
+        os.put(BINPUT);
+        os.put(1);
+    }
+
+    inline void writeString(const char *s) {
+        if (!s) {
+            writeNone();
+            return;
+        }
+
+        writeString(s, strlen(s));
+    }
+
+    inline void writeString(const std::string &s) {
+        writeString(s.c_str(), s.size());
+    }
+
+    inline void writeNone(void) {
+        os.put(NONE);
+    }
+
+    inline void writeBool(bool b) {
+        os.put(b ? NEWTRUE : NEWFALSE);
+    }
+
+    inline void writeInt(uint8_t i) {
+        os.put(BININT1);
+        os.put(i);
+    }
+
+    inline void writeInt(uint16_t i) {
+        if (i < 0x100) {
+            writeInt((uint8_t)i);
+        } else {
+            os.put(BININT2);
+            putInt16(i);
+        }
+    }
+
+    inline void writeInt(int32_t i) {
+        if (0 <= i && i < 0x10000) {
+            writeInt((uint16_t)i);
+        } else {
+            os.put(BININT);
+            putInt32(i);
+        }
+    }
+
+    inline void writeInt(uint32_t i) {
+        if (i < 0x8000000) {
+            writeInt((int32_t)i);
+        } else {
+            writeLong(i);
+        }
+    }
+
+    inline void writeInt(long long i) {
+        if (-0x8000000 <= i && i < 0x8000000) {
+            writeInt((int32_t)i);
+        } else {
+            writeLong(i);
+        }
+    }
+
+    inline void writeInt(unsigned long long i) {
+        if (i < 0x8000000) {
+            writeInt((int32_t)i);
+        } else {
+            writeLong(i);
+        }
+    }
+
+    inline void writeFloat(double f) {
+        union {
+            double f;
+            char c[8];
+        } u;
+
+        assert(sizeof u.f == sizeof u.c);
+        u.f = f;
+
+        os.put(BINFLOAT);
+        os.put(u.c[7]);
+        os.put(u.c[6]);
+        os.put(u.c[5]);
+        os.put(u.c[4]);
+        os.put(u.c[3]);
+        os.put(u.c[2]);
+        os.put(u.c[1]);
+        os.put(u.c[0]);
+    }
+
+protected:
+    inline void putInt16(uint16_t i) {
+        os.put( i        & 0xff);
+        os.put( i >>  8        );
+    }
+
+    inline void putInt32(uint32_t i) {
+        os.put( i        & 0xff);
+        os.put((i >>  8) & 0xff);
+        os.put((i >> 16) & 0xff);
+        os.put( i >> 24        );
+    }
+
+    template< class T >
+    inline void writeLong(T l) {
+        os.put(LONG1);
+
+        if (l == 0) {
+            os.put(0);
+            return;
+        }
+
+        unsigned c = 1;
+        // Same as l >> (8 * sizeof l), but without the warnings
+        T sign = l < 0 ? ~0 : 0;
+        while ((l >> (8 * c)) != sign) {
+            ++c;
+        }
+        // Add an extra byte if sign bit doesn't match
+        if (((l >> (8 * c - 1)) & 1) != ((l >> (8 * sizeof l - 1)) & 1)) {
+            ++c;
+        }
+        os.put(c);
+
+        for (unsigned i = 0; i < c; ++ i) {
+            os.put(l & 0xff);
+            l >>= 8;
+        }
+    }
+};
+
+#endif /* _Pickle_HPP_ */
diff --git a/common/trace_callset.cpp b/common/trace_callset.cpp
new file mode 100644 (file)
index 0000000..3c33087
--- /dev/null
@@ -0,0 +1,247 @@
+/**************************************************************************
+ *
+ * Copyright 2012 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include <assert.h>
+#include <stdlib.h>
+
+#include <limits>
+#include <fstream>
+#include <iostream>
+#include <string>
+
+#include <trace_callset.hpp>
+
+
+using namespace trace;
+
+
+// Parser class for call sets
+class CallSetParser
+{
+    CallSet &set;
+
+protected:
+    char lookahead;
+
+    CallSetParser(CallSet &_set) :
+        set(_set),
+        lookahead(0)
+    {}
+
+public:
+    void parse() {
+        skipWhiteSpace();
+        while (lookahead) {
+            assert(!isSpace());
+            parseRange();
+            // skip any comma
+            isOperator(',');
+        }
+    }
+
+private:
+    void parseRange() {
+        CallNo start = std::numeric_limits<CallNo>::min();
+        CallNo stop = std::numeric_limits<CallNo>::max();
+        CallNo step = 1;
+        CallFlags freq = FREQUENCY_ALL;
+        if (isAlpha()) {
+            freq = parseFrequency();
+        } else {
+            if (isOperator('*')) {
+                // no-change
+            } else {
+                start = parseCallNo();
+                if (isOperator('-')) {
+                    if (isDigit()) {
+                        stop = parseCallNo();
+                    } else {
+                        // no-change
+                    }
+                } else {
+                    stop = start;
+                }
+            }
+            if (isOperator('/')) {
+                if (isDigit()) {
+                    step = parseCallNo();
+                } else {
+                    freq = parseFrequency();
+                }
+            }
+        }
+        set.addRange(CallRange(start, stop, step, freq));
+    }
+
+    // match and consume an operator
+    bool isOperator(char c) {
+        if (lookahead == c) {
+            consume();
+            skipWhiteSpace();
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    CallNo parseCallNo() {
+        CallNo number = 0;
+        if (isDigit()) {
+            do {
+                CallNo digit = consume() - '0';
+                number = number * 10 + digit;
+            } while (isDigit());
+        } else {
+            std::cerr << "error: expected digit, found '" << lookahead << "'\n";
+            exit(0);
+        }
+        skipWhiteSpace();
+        return number;
+    }
+
+    CallFlags parseFrequency() {
+        std::string freq;
+        if (isAlpha()) {
+            do {
+                freq.push_back(consume());
+            } while (isAlpha());
+        } else {
+            std::cerr << "error: expected frequency, found '" << lookahead << "'\n";
+            exit(0);
+        }
+        skipWhiteSpace();
+        if (freq == "frame") {
+            return FREQUENCY_FRAME;
+        } else if (freq == "rendertarget" || freq == "fbo") {
+            return FREQUENCY_RENDERTARGET;
+        } else if (freq == "render" || freq == "draw") {
+            return FREQUENCY_RENDER;
+        } else {
+            std::cerr << "error: expected frequency, found '" << freq << "'\n";
+            exit(0);
+            return FREQUENCY_NONE;
+        }
+    }
+
+    // match lookahead with a digit (does not consume)
+    bool isDigit() const {
+        return lookahead >= '0' && lookahead <= '9';
+    }
+
+    bool isAlpha() const {
+        return lookahead >= 'a' && lookahead <= 'z';
+    }
+
+    void skipWhiteSpace() {
+        while (isSpace()) {
+            consume();
+        }
+    }
+
+    bool isSpace() const {
+        return lookahead == ' ' ||
+               lookahead == '\t' ||
+               lookahead == '\r' ||
+               lookahead == '\n';
+    }
+
+    virtual char consume() = 0;
+};
+
+
+class StringCallSetParser : public CallSetParser
+{
+    const char *buf;
+
+public:
+    StringCallSetParser(CallSet &_set, const char *_buf) :
+        CallSetParser(_set),
+        buf(_buf)
+    {
+        lookahead = *buf;
+    }
+
+    char consume() {
+        char c = lookahead;
+        if (lookahead) {
+            ++buf;
+            lookahead = *buf;
+        }
+        return c;
+    }
+};
+
+
+class FileCallSetParser : public CallSetParser
+{
+    std::ifstream stream;
+
+public:
+    FileCallSetParser(CallSet &_set, const char *filename) :
+        CallSetParser(_set)
+    {
+        stream.open(filename);
+        if (!stream.is_open()) {
+            std::cerr << "error: failed to open \"" << filename << "\"\n";
+            exit(1);
+        }
+
+        stream.get(lookahead);
+    }
+
+    char consume() {
+        char c = lookahead;
+        if (stream.eof()) {
+            lookahead = 0;
+        } else {
+            stream.get(lookahead);
+        }
+        return c;
+    }
+};
+
+
+CallSet::CallSet(const char *string)
+{
+    if (*string == '@') {
+        FileCallSetParser parser(*this, &string[1]);
+        parser.parse();
+    } else {
+        StringCallSetParser parser(*this, string);
+        parser.parse();
+    }
+}
+
+
+CallSet::CallSet(CallFlags freq) {
+    if (freq != FREQUENCY_NONE) {
+        CallNo start = std::numeric_limits<CallNo>::min();
+        CallNo stop = std::numeric_limits<CallNo>::max();
+        CallNo step = 1;
+        addRange(CallRange(start, stop, step, freq));
+        assert(!empty());
+    }
+}
diff --git a/common/trace_callset.hpp b/common/trace_callset.hpp
new file mode 100644 (file)
index 0000000..b679d94
--- /dev/null
@@ -0,0 +1,167 @@
+/**************************************************************************
+ *
+ * Copyright 2012 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/*
+ * Representation of call sets.
+ *
+ * Grammar:
+ *
+ *     set = '@' filename
+ *         | range ( ',' ? range ) *
+ *
+ *     range = interval ( '/' frequency )
+ *
+ *     interval = '*'
+ *              | number
+ *              | start_number '-' end_number
+ *
+ *     frequency = divisor
+ *               | "frame"
+ *               | "rendertarget" | "fbo"
+ *               | "render | "draw"
+ *
+ */
+
+#ifndef _TRACE_CALLSET_HPP_
+#define _TRACE_CALLSET_HPP_
+
+
+#include <list>
+
+#include "trace_model.hpp"
+
+
+namespace trace {
+
+
+    // Should match Call::no
+    typedef unsigned CallNo;
+
+
+    // Aliases for call flags
+    enum {
+        FREQUENCY_NONE         = 0,
+        FREQUENCY_FRAME        = CALL_FLAG_END_FRAME,
+        FREQUENCY_RENDERTARGET = CALL_FLAG_END_FRAME | CALL_FLAG_SWAP_RENDERTARGET,
+        FREQUENCY_RENDER       = CALL_FLAG_RENDER,
+        FREQUENCY_ALL          = 0xffffffff
+    };
+
+    // A linear range of calls
+    class CallRange
+    {
+    public:
+        CallNo start;
+        CallNo stop;
+        CallNo step;
+        CallFlags freq;
+
+        CallRange(CallNo callNo) :
+            start(callNo),
+            stop(callNo),
+            step(1),
+            freq(FREQUENCY_ALL)
+        {}
+
+        CallRange(CallNo _start, CallNo _stop, CallNo _step = 1, CallFlags _freq = FREQUENCY_ALL) :
+            start(_start),
+            stop(_stop),
+            step(_step),
+            freq(_freq)
+        {}
+
+        bool
+        contains(CallNo callNo, CallFlags callFlags) const {
+            return callNo >= start &&
+                   callNo <= stop &&
+                   ((callNo - start) % step) == 0 &&
+                   ((callFlags & freq) ||
+                    freq == FREQUENCY_ALL);
+        }
+    };
+
+
+    // A collection of call ranges
+    class CallSet
+    {
+    public:
+        // TODO: use binary tree to speed up lookups
+        typedef std::list< CallRange > RangeList;
+        RangeList ranges;
+
+        CallSet() {}
+
+        CallSet(CallFlags freq);
+
+        CallSet(const char *str);
+
+        // Not empty set
+        inline bool
+        empty() const {
+            return ranges.empty();
+        }
+
+        void
+        addRange(const CallRange & range) {
+            if (range.start <= range.stop &&
+                range.freq != FREQUENCY_NONE) {
+
+                RangeList::iterator it = ranges.begin();
+                while (it != ranges.end() && it->start < range.start) {
+                    ++it;
+                }
+
+                ranges.insert(it, range);
+            }
+        }
+
+        inline bool
+        contains(CallNo callNo, CallFlags callFlags = FREQUENCY_ALL) const {
+            if (empty()) {
+                return false;
+            }
+            RangeList::const_iterator it;
+            for (it = ranges.begin(); it != ranges.end() && it->start <= callNo; ++it) {
+                if (it->contains(callNo, callFlags)) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        inline bool
+        contains(const trace::Call &call) {
+            return contains(call.no, call.flags);
+        }
+    };
+
+
+    CallSet parse(const char *string);
+
+
+} /* namespace trace */
+
+
+#endif /* _TRACE_CALLSET_HPP_ */
index 6b2fdc30aa96e53affe20aabbe67e7f62583362c..c55bbb1ca324e776ad67b5cef5f72cb64376ed1e 100644 (file)
@@ -200,6 +200,10 @@ public:
 
     void visit(Call *call) {
         CallFlags callFlags = call->flags;
+        
+        if (!(dumpFlags & DUMP_FLAG_NO_CALL_NO)) {
+            os << call->no << " ";
+        }
 
         if (callFlags & CALL_FLAG_NON_REPRODUCIBLE) {
             os << strike;
@@ -217,8 +221,8 @@ public:
             if (!(dumpFlags & DUMP_FLAG_NO_ARG_NAMES)) {
                 os << italic << call->sig->arg_names[i] << normal << " = ";
             }
-            if (call->args[i]) {
-                _visit(call->args[i]);
+            if (call->args[i].value) {
+                _visit(call->args[i].value);
             } else {
                os << "?";
             }
@@ -252,7 +256,6 @@ void dump(Value *value, std::ostream &os, DumpFlags flags) {
 
 void dump(Call &call, std::ostream &os, DumpFlags flags) {
     Dumper d(os, flags);
-    os << call.no << " ";
     d.visit(&call);
 }
 
index 4ffe65ac09b460f3fcdbb5da8e67b277f2913de9..d4612e5599d784848202dc84ef3118826ae12369 100644 (file)
@@ -44,6 +44,7 @@ typedef unsigned DumpFlags;
 enum {
     DUMP_FLAG_NO_COLOR                 = (1 << 0),
     DUMP_FLAG_NO_ARG_NAMES             = (1 << 1),
+    DUMP_FLAG_NO_CALL_NO               = (1 << 2),
 };
 
 
index e05ca276cf59dedc2f1496a329f8b2ce01501117..7e926ba46db70e65c5e8ee1a732f7ce9dcde784e 100644 (file)
@@ -32,7 +32,7 @@ namespace trace {
 
 Call::~Call() {
     for (unsigned i = 0; i < args.size(); ++i) {
-        delete args[i];
+        delete args[i].value;
     }
 
     if (ret) {
index 076ff098d61f9fa25edf72a80aef7c4796663d9f..7973026cd9b07884af719feefd3b7ed72ed1a2cc 100644 (file)
@@ -406,6 +406,11 @@ enum {
 };
 
 
+struct Arg
+{
+    Value *value;
+};
+
 
 class Call
 {
@@ -413,7 +418,7 @@ public:
     unsigned thread_id;
     unsigned no;
     const FunctionSig *sig;
-    std::vector<Value *> args;
+    std::vector<Arg> args;
     Value *ret;
 
     CallFlags flags;
@@ -434,7 +439,7 @@ public:
 
     inline Value & arg(unsigned index) {
         assert(index < args.size());
-        return *(args[index]);
+        return *(args[index].value);
     }
 };
 
index 88afa98521fc46342081e5b7d4a4f4d375001bf7..dc9634f0d36f823b635d26c7efd7bc1a1082625f 100644 (file)
@@ -480,7 +480,7 @@ void Parser::parse_arg(Call *call, Mode mode) {
         if (index >= call->args.size()) {
             call->args.resize(index + 1);
         }
-        call->args[index] = value;
+        call->args[index].value = value;
     }
 }
 
index cc3af284d3f9db7c18c042a51d1cce2a3bfc45cf..96544d1502f6eb24c74343866764722f05ec70b2 100644 (file)
@@ -103,9 +103,9 @@ public:
     void visit(Call *call) {
         unsigned call_no = writer.beginEnter(call->sig, call->thread_id);
         for (unsigned i = 0; i < call->args.size(); ++i) {
-            if (call->args[i]) {
+            if (call->args[i].value) {
                 writer.beginArg(i);
-                _visit(call->args[i]);
+                _visit(call->args[i].value);
                 writer.endArg();
             }
         }
index 5fe7912955d7f79bf8ae0e351074fcbb0c62db2f..f7d95a16a6c83ba4fee9cc60cfcf9da40f343ba6 100644 (file)
--- a/compat.h
+++ b/compat.h
 #define __inline static __inline__
 #define __deref_out /**/
 #define __deref_out_opt /**/
-#define __deref_out_bcount(x)
-#define __maybenull
-#define __in_z
-#define __in_z_opt
-#define __out_z
-#define __out_ecount_z(x)
-#define __nullterminated
-#define __notnull
-#define __field_ecount_opt(x)
-#define __range(x,y)
-#define __out_ecount_part_opt(x,y)
+#define __deref_out_bcount(x) /**/
+#define __maybenull /**/
+#define __in_z /**/
+#define __in_z_opt /**/
+#define __out_z /**/
+#define __out_ecount_z(x) /**/
+#define __nullterminated /**/
+#define __notnull /**/
+#define __field_ecount_opt(x) /**/
+#define __range(x,y) /**/
+#define __out_ecount_part_opt(x,y) /**/
 
 #ifndef DECLSPEC_DEPRECATED
 #define DECLSPEC_DEPRECATED /**/
 #endif
 
 #ifndef DECLSPEC_NOVTABLE
-#define DECLSPEC_NOVTABLE
+#define DECLSPEC_NOVTABLE /**/
 #endif
 
 #ifndef __MINGW64_VERSION_MAJOR
index a2120032946e974fe31c36312bb8294ce27db8ac..7d0fc75573d8121497a7d27b5a1c9d0bf4eaae2c 100644 (file)
@@ -29,6 +29,8 @@ from dlltrace import DllTracer
 
 
 if __name__ == '__main__':
+    print '#define INITGUID'
+    print
     print '#include "trace_writer_local.hpp"'
     print '#include "os.hpp"'
     print
index a40ae7f5f1eed1bcb189a3ea78ed848ec0e1d88f..ae4acd039fe39f2b274afdfa46f9f624f003611f 100644 (file)
@@ -42,27 +42,27 @@ class D3D9Tracer(DllTracer):
         DllTracer.declareWrapperInterfaceVariables(self, interface)
         
         if interface.name == 'IDirect3DVertexBuffer9':
-            print '    UINT m_OffsetToLock;'
             print '    UINT m_SizeToLock;'
             print '    VOID *m_pbData;'
 
     def implementWrapperInterfaceMethodBody(self, interface, base, method):
         if interface.name == 'IDirect3DVertexBuffer9' and method.name == 'Unlock':
             print '    if (m_pbData) {'
-            print '        if (!m_SizeToLock) {'
-            print '            D3DVERTEXBUFFER_DESC Desc;'
-            print '            m_pInstance->GetDesc(&Desc);'
-            print '            m_SizeToLock = Desc.Size;'
-            print '        }'
-            self.emit_memcpy('(LPBYTE)m_pbData + m_OffsetToLock', '(LPBYTE)m_pbData + m_OffsetToLock', 'm_SizeToLock')
+            self.emit_memcpy('(LPBYTE)m_pbData', '(LPBYTE)m_pbData', 'm_SizeToLock')
             print '    }'
 
         DllTracer.implementWrapperInterfaceMethodBody(self, interface, base, method)
 
         if interface.name == 'IDirect3DVertexBuffer9' and method.name == 'Lock':
+            # FIXME: handle recursive locks
             print '    if (__result == D3D_OK && !(Flags & D3DLOCK_READONLY)) {'
-            print '        m_OffsetToLock = OffsetToLock;'
-            print '        m_SizeToLock = SizeToLock;'
+            print '        if (SizeToLock) {'
+            print '            m_SizeToLock = SizeToLock;'
+            print '        } else {'
+            print '            D3DVERTEXBUFFER_DESC Desc;'
+            print '            m_pInstance->GetDesc(&Desc);'
+            print '            m_SizeToLock = Desc.Size;'
+            print '        }'
             print '        m_pbData = *ppbData;'
             print '    } else {'
             print '        m_pbData = NULL;'
index 41e2997c1482c126ae9b9c9f40180bb4f09a5fba..83535223fcf3c7f1009d9731df459ff8a9090203 100644 (file)
@@ -46,17 +46,7 @@ extern unsigned frame;
 extern long long startTime;
 extern bool wait;
 
-enum frequency {
-    FREQUENCY_NEVER = 0,
-    FREQUENCY_FRAME,
-    FREQUENCY_FRAMEBUFFER,
-    FREQUENCY_DRAW,
-};
-
 extern bool benchmark;
-extern const char *compare_prefix;
-extern const char *snapshot_prefix;
-extern enum frequency snapshot_frequency;
 
 extern unsigned dump_state;
 
@@ -69,7 +59,6 @@ extern const retrace::Entry glx_callbacks[];
 extern const retrace::Entry wgl_callbacks[];
 extern const retrace::Entry egl_callbacks[];
 
-void snapshot(unsigned call_no);
 void frame_complete(trace::Call &call);
 
 void updateDrawable(int width, int height);
index f3ae91bda830965e951e6b20c00ab7ae534c6998..e862e25a3757b9c99ad94d7f556abcfd3dbee8e9 100644 (file)
@@ -197,21 +197,12 @@ class GlRetracer(Retracer):
             print '    GLint __pack_buffer = 0;'
             print '    glGetIntegerv(GL_PIXEL_PACK_BUFFER_BINDING, &__pack_buffer);'
             print '    if (!__pack_buffer) {'
-            if function.name == 'glReadPixels':
-                print '    glFinish();'
-                print '    if (glretrace::snapshot_frequency == glretrace::FREQUENCY_FRAME ||'
-                print '        glretrace::snapshot_frequency == glretrace::FREQUENCY_FRAMEBUFFER) {'
-                print '        glretrace::snapshot(call.no);'
-                print '    }'
             print '        return;'
             print '    }'
 
         # Pre-snapshots
         if function.name in self.bind_framebuffer_function_names:
             print '    assert(call.flags & trace::CALL_FLAG_SWAP_RENDERTARGET);'
-            print '    if (glretrace::snapshot_frequency == glretrace::FREQUENCY_FRAMEBUFFER) {'
-            print '        glretrace::snapshot(call.no - 1);'
-            print '    }'
         if function.name == 'glFrameTerminatorGREMEDY':
             print '    glretrace::frame_complete(call);'
             return
@@ -225,9 +216,6 @@ class GlRetracer(Retracer):
             print '    }'
         if is_draw_array or is_draw_elements or is_misc_draw:
             print '    assert(call.flags & trace::CALL_FLAG_RENDER);'
-            print '    if (glretrace::snapshot_frequency == glretrace::FREQUENCY_DRAW) {'
-            print '        glretrace::snapshot(call.no);'
-            print '    }'
 
 
     def invokeFunction(self, function):
@@ -252,7 +240,7 @@ class GlRetracer(Retracer):
             print '    glretrace::insideGlBeginEnd = true;'
         elif function.name.startswith('gl'):
             # glGetError is not allowed inside glBegin/glEnd
-            print '    if (!glretrace::benchmark && !glretrace::insideGlBeginEnd) {'
+            print '    if (!glretrace::benchmark && !retrace::profiling && !glretrace::insideGlBeginEnd) {'
             print '        glretrace::checkGlError(call);'
             if function.name in ('glProgramStringARB', 'glProgramStringNV'):
                 print r'        GLint error_position = -1;'
index 12086321bd3a2bc94ef11a1b024e62ebecbe96c2..785d6feaadf6bdbf90b4c359958b7478f2254315 100644 (file)
@@ -30,6 +30,7 @@
 #include "os_time.hpp"
 #include "image.hpp"
 #include "retrace.hpp"
+#include "trace_callset.hpp"
 #include "glproc.hpp"
 #include "glstate.hpp"
 #include "glretrace.hpp"
@@ -50,9 +51,10 @@ long long startTime = 0;
 bool wait = false;
 
 bool benchmark = false;
-const char *compare_prefix = NULL;
-const char *snapshot_prefix = NULL;
-enum frequency snapshot_frequency = FREQUENCY_NEVER;
+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;
 
@@ -138,9 +140,11 @@ updateDrawable(int width, int height) {
 }
 
 
-void snapshot(unsigned call_no) {
-    if (!drawable ||
-        (!snapshot_prefix && !compare_prefix)) {
+static void
+snapshot(unsigned call_no) {
+    assert(snapshot_prefix || compare_prefix);
+
+    if (!drawable) {
         return;
     }
 
@@ -194,11 +198,6 @@ void frame_complete(trace::Call &call) {
     if (!drawable->visible) {
         retrace::warning(call) << "could not infer drawable size (glViewport never called)\n";
     }
-
-    if (snapshot_frequency == FREQUENCY_FRAME ||
-        snapshot_frequency == FREQUENCY_FRAMEBUFFER) {
-        snapshot(call.no);
-    }
 }
 
 
@@ -215,8 +214,32 @@ static void display(void) {
     trace::Call *call;
 
     while ((call = 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) {
@@ -233,7 +256,7 @@ static void display(void) {
     long long endTime = os::getTime();
     float timeInterval = (endTime - startTime) * (1.0 / os::timeFrequency);
 
-    if (retrace::verbosity >= -1) { 
+    if ((retrace::verbosity >= -1) || (retrace::profiling)) {
         std::cout << 
             "Rendered " << frame << " frames"
             " in " <<  timeInterval << " secs,"
@@ -254,12 +277,14 @@ static void usage(void) {
         "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 FREQUENCY snapshot frequency: frame (default), framebuffer, or draw\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";
@@ -268,6 +293,8 @@ static void usage(void) {
 extern "C"
 int main(int argc, char **argv)
 {
+    assert(compare_frequency.empty());
+    assert(snapshot_frequency.empty());
 
     int i;
     for (i = 1; i < argc; ++i) {
@@ -283,10 +310,19 @@ int main(int argc, char **argv)
             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 (snapshot_frequency == FREQUENCY_NEVER) {
-                snapshot_frequency = FREQUENCY_FRAME;
+            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]);
@@ -302,25 +338,14 @@ int main(int argc, char **argv)
             return 0;
         } else if (!strcmp(arg, "-s")) {
             snapshot_prefix = argv[++i];
-            if (snapshot_frequency == FREQUENCY_NEVER) {
-                snapshot_frequency = FREQUENCY_FRAME;
+            if (snapshot_frequency.empty()) {
+                snapshot_frequency = trace::CallSet(trace::FREQUENCY_FRAME);
             }
             if (snapshot_prefix[0] == '-' && snapshot_prefix[1] == 0) {
                 retrace::verbosity = -2;
             }
         } else if (!strcmp(arg, "-S")) {
-            arg = argv[++i];
-            if (!strcmp(arg, "frame")) {
-                snapshot_frequency = FREQUENCY_FRAME;
-            } else if (!strcmp(arg, "framebuffer")) {
-                snapshot_frequency = FREQUENCY_FRAMEBUFFER;
-            } else if (!strcmp(arg, "draw")) {
-                snapshot_frequency = FREQUENCY_DRAW;
-            } else {
-                std::cerr << "error: unknown frequency " << arg << "\n";
-                usage();
-                return 1;
-            }
+            snapshot_frequency = trace::CallSet(argv[++i]);
             if (snapshot_prefix == NULL) {
                 snapshot_prefix = "";
             }
index 57d2d86eb23c48bc37f75bdbbc69c9ab7a5dc197..267dc0980edeaaa7ea02c26de9e981d25e96b6fa 100644 (file)
@@ -678,9 +678,9 @@ ApiTraceCall::ApiTraceCall(ApiTraceFrame *parentFrame,
     }
     m_argValues.reserve(call->args.size());
     for (int i = 0; i < call->args.size(); ++i) {
-        if (call->args[i]) {
+        if (call->args[i].value) {
             VariantVisitor argVisitor(loader);
-            call->args[i]->visit(argVisitor);
+            call->args[i].value->visit(argVisitor);
             m_argValues.append(argVisitor.variant());
             if (m_argValues[i].type() == QVariant::ByteArray) {
                 m_hasBinaryData = true;
index 7e7c471d3067cdb07512af7fb7201ee8386f8d83..54ef5d24a82840b85d2d4bbf42e5e0f5df8304b1 100644 (file)
@@ -314,12 +314,12 @@ static void
 overwriteValue(trace::Call *call, const QVariant &val, int index)
 {
     EditVisitor visitor(val);
-    trace::Value *origValue = call->args[index];
+    trace::Value *origValue = call->args[index].value;
     origValue->visit(visitor);
 
     if (visitor.value() && origValue != visitor.value()) {
         delete origValue;
-        call->args[index] = visitor.value();
+        call->args[index].value = visitor.value();
     }
 }
 
index 849c597f10cafaf64ef12b6d19a9266eab7b393b..d2e6d379b06d283ca729e1712e80a22044103189 100644 (file)
@@ -27,6 +27,7 @@
 #include <string.h>
 #include <iostream>
 
+#include "os_time.hpp"
 #include "trace_dump.hpp"
 #include "retrace.hpp"
 
@@ -35,6 +36,7 @@ namespace retrace {
 
 
 int verbosity = 0;
+bool profiling = false;
 
 
 static bool call_dumped = false;
@@ -114,7 +116,20 @@ void Retracer::retrace(trace::Call &call) {
     assert(callback);
     assert(callbacks[id] == callback);
 
-    callback(call);
+    if (retrace::profiling) {
+        long long startTime = os::getTime();
+        callback(call);
+        long long stopTime = os::getTime();
+        float timeInterval = (stopTime - startTime) * (1.0E6 / os::timeFrequency);
+
+        std::cout
+            << call.no << " "
+            << "[" << timeInterval << " usec] "
+        ;
+        trace::dump(call, std::cout, trace::DUMP_FLAG_NO_CALL_NO | trace::DUMP_FLAG_NO_COLOR);
+    } else {
+        callback(call);
+    }
 }
 
 
index a59a6eb8901e97195d2f268082101a331396881b..57b8b052639085e6b8742bd5e395761f999577fe 100644 (file)
@@ -95,6 +95,11 @@ toPointer(trace::Value &value, bool bind = false);
  */
 extern int verbosity;
 
+/**
+ * Add profiling data to the dump when retracing.
+ */
+extern bool profiling;
+
 
 std::ostream &warning(trace::Call &call);
 
index 0e28d18b4a64618db8fb10b0e5b4faa407137df5..25e26093597df8fad5ff9ab5d0217d1ffb1c6069 100644 (file)
@@ -299,7 +299,7 @@ class Retracer:
         print '#include "retrace.hpp"'
         print
 
-        types = api.all_types()
+        types = api.getAllTypes()
         handles = [type for type in types if isinstance(type, stdapi.Handle)]
         handle_names = set()
         for handle in handles:
index bed216c314921e386ec03bc849c7a1a3d2c59359..34959753fc0acf9b137e07394a6e60e621028e9d 100755 (executable)
@@ -156,9 +156,9 @@ def main():
         type="float", dest="threshold", default=12.0,
         help="threshold precision  [default: %default]")
     optparser.add_option(
-        '-S', '--snapshot-frequency', metavar='FREQUENCY',
+        '-S', '--snapshot-frequency', metavar='CALLSET',
         type="string", dest="snapshot_frequency", default='draw',
-        help="snapshot frequency: frame, framebuffer, or draw  [default: %default]")
+        help="calls to compare [default: %default]")
 
     (options, args) = optparser.parse_args(sys.argv[1:])
     ref_env = parse_env(optparser, options.ref_env)
index 9f9633d2d4666f94e41411d427402279a59ca62d..819a25120ebdfceb2a8234ce1addd3923f1b0916 100755 (executable)
@@ -31,7 +31,7 @@ APITRACE=${APITRACE:-apitrace}
 $APITRACE dump
 
 stripdump () {
-    $APITRACE dump --color=never --no-arg-names "$1" \
+    $APITRACE dump --color=never --arg-names=no "$1" \
     | sed \
         -e 's/\r$//g' \
         -e 's/^[0-9]\+ //' \
diff --git a/scripts/unpickle.py b/scripts/unpickle.py
new file mode 100755 (executable)
index 0000000..a3c274c
--- /dev/null
@@ -0,0 +1,88 @@
+#!/usr/bin/env python
+##########################################################################
+#
+# Copyright 2012 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.
+#
+##########################################################################/
+
+'''Sample program for apitrace pickle command.
+
+Run as:
+
+   apitrace pickle foo.trace | python unpickle.py
+
+'''
+
+
+import optparse
+import cPickle as pickle
+import sys
+import time
+
+
+def main():
+    optparser = optparse.OptionParser(
+        usage="\n\tapitrace pickle trace. %prog [options]")
+    optparser.add_option(
+        '--quiet',
+        action="store_true", dest="quiet", default=False,
+        help="don't dump calls to stdout")
+
+    (options, args) = optparser.parse_args(sys.argv[1:])
+
+    if args:
+        optparser.error('unexpected arguments')
+
+    # Change stdin to binary mode
+    try:
+        import msvcrt
+    except ImportError:
+        pass
+    else:
+        import os
+        msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)
+
+    calls = 0
+    startTime = time.time()
+    while True:
+        try:
+            call = pickle.load(sys.stdin)
+        except EOFError:
+            break
+        else:
+            callNo, functionName, args, ret = call
+            if not options.quiet:
+                sys.stdout.write('%u ' % callNo)
+                sys.stdout.write(functionName)
+                sys.stdout.write('(' + ', '.join(map(repr, args)) + ')')
+                if ret is not None:
+                    sys.stdout.write(' = ')
+                    sys.stdout.write(repr(ret))
+                sys.stdout.write('\n')
+            calls += 1
+    stopTime = time.time()
+    duration = stopTime - startTime
+    sys.stderr.write('%u calls, %.03f secs, %u calls/sec\n' % (calls, duration, calls/duration))
+
+
+if __name__ == '__main__':
+    main()
index 8ee9cf7249bfa141d29dc36be9ed256a8f429a17..a129382d6f11e70a26b3a268ae186d63abe9f105 100644 (file)
@@ -47,8 +47,36 @@ D3D10_DRIVER_TYPE = Enum("D3D10_DRIVER_TYPE", [
 
 
 d3d10 = API("d3d10")
+
 d3d10.addFunctions([
     StdFunction(HRESULT, "D3D10CreateDevice", [(Pointer(IDXGIAdapter), "pAdapter"), (D3D10_DRIVER_TYPE, "DriverType"), (HMODULE, "Software"), (UINT, "Flags"), (UINT, "SDKVersion"), Out(Pointer(Pointer(ID3D10Device)), "ppDevice")]),
     StdFunction(HRESULT, "D3D10CreateDeviceAndSwapChain", [(Pointer(IDXGIAdapter), "pAdapter"), (D3D10_DRIVER_TYPE, "DriverType"), (HMODULE, "Software"), (UINT, "Flags"), (UINT, "SDKVersion"), (Pointer(DXGI_SWAP_CHAIN_DESC), "pSwapChainDesc"), Out(Pointer(Pointer(IDXGISwapChain)), "ppSwapChain"), Out(Pointer(Pointer(ID3D10Device)), "ppDevice")]),
     StdFunction(HRESULT, "D3D10CreateBlob", [(SIZE_T, "NumBytes"), Out(Pointer(LPD3D10BLOB), "ppBuffer")]),
 ])
+
+d3d10.addInterfaces([
+    ID3D10DeviceChild,
+    ID3D10Resource,
+    ID3D10Buffer,
+    ID3D10Texture1D,
+    ID3D10Texture2D,
+    ID3D10Texture3D,
+    ID3D10View,
+    ID3D10DepthStencilView,
+    ID3D10RenderTargetView,
+    ID3D10ShaderResourceView,
+    ID3D10BlendState,
+    ID3D10DepthStencilState,
+    ID3D10GeometryShader,
+    ID3D10InputLayout,
+    ID3D10PixelShader,
+    ID3D10RasterizerState,
+    ID3D10SamplerState,
+    ID3D10VertexShader,
+    ID3D10Asynchronous,
+    ID3D10Counter,
+    ID3D10Query,
+    ID3D10Predicate,
+    ID3D10Device,
+    ID3D10Multithread,
+])
index 50327ebef0802deb855f23bf04e5cff15742cbb7..8fef9bd532f9827ec543935e771ac5146a5f390a 100644 (file)
@@ -56,7 +56,7 @@ DXGI_MAPPED_RECT = Struct("DXGI_MAPPED_RECT", [
 ])
 
 DXGI_OUTPUT_DESC = Struct("DXGI_OUTPUT_DESC", [
-    (Array(WCHAR, 32), "DeviceName"),
+    (WString, "DeviceName"),
     (RECT, "DesktopCoordinates"),
     (BOOL, "AttachedToDesktop"),
     (DXGI_MODE_ROTATION, "Rotation"),
@@ -72,7 +72,7 @@ DXGI_FRAME_STATISTICS = Struct("DXGI_FRAME_STATISTICS", [
 ])
 
 DXGI_ADAPTER_DESC = Struct("DXGI_ADAPTER_DESC", [
-    (Array(WCHAR, 128), "Description"),
+    (WString, "Description"),
     (UINT, "VendorId"),
     (UINT, "DeviceId"),
     (UINT, "SubSysId"),
index b6bab8f542e2744ee642b3a7ffafa4663e05d9f1..0e3fe236154d554276f9bf986168b1029b08b9b3 100644 (file)
@@ -376,16 +376,14 @@ class Method(Function):
 
 class String(Type):
 
-    def __init__(self, expr = "char *", length = None):
+    def __init__(self, expr = "char *", length = None, kind = 'String'):
         Type.__init__(self, expr)
         self.length = length
+        self.kind = kind
 
     def visit(self, visitor, *args, **kwargs):
         return visitor.visitString(self, *args, **kwargs)
 
-# C string (i.e., zero terminated)
-CString = String()
-
 
 class Opaque(Type):
     '''Opaque pointer.'''
@@ -566,6 +564,9 @@ class Rebuilder(Visitor):
     def visitOpaque(self, opaque):
         return opaque
 
+    def visitInterface(self, interface, *args, **kwargs):
+        return interface
+
     def visitPolymorphic(self, polymorphic):
         defaultType = self.visit(polymorphic.defaultType)
         switchExpr = polymorphic.switchExpr
@@ -659,7 +660,7 @@ class API:
         self.functions = []
         self.interfaces = []
 
-    def all_types(self):
+    def getAllTypes(self):
         collector = Collector()
         for function in self.functions:
             for arg in function.args:
@@ -673,6 +674,14 @@ class API:
                 collector.visit(method.type)
         return collector.types
 
+    def getAllInterfaces(self):
+        types = self.getAllTypes()
+        interfaces = [type for type in types if isinstance(type, Interface)]
+        for interface in self.interfaces:
+            if interface not in interfaces:
+                interfaces.append(interface)
+        return interfaces
+
     def addFunction(self, function):
         self.functions.append(function)
 
@@ -712,7 +721,10 @@ ULongLong = Literal("unsigned long long", "UInt")
 Float = Literal("float", "Float")
 Double = Literal("double", "Double")
 SizeT = Literal("size_t", "UInt")
-WString = Literal("wchar_t *", "WString")
+
+# C string (i.e., zero terminated)
+CString = String()
+WString = String("wchar_t *", kind="WString")
 
 Int8 = Literal("int8_t", "SInt")
 UInt8 = Literal("uint8_t", "UInt")
diff --git a/specs/temp.py b/specs/temp.py
deleted file mode 100644 (file)
index 7b51a97..0000000
+++ /dev/null
@@ -1,624 +0,0 @@
-D2D1_ALPHA_MODE = Enum("D2D1_ALPHA_MODE", [
-    "D2D1_ALPHA_MODE_UNKNOWN",
-    "D2D1_ALPHA_MODE_PREMULTIPLIED",
-    "D2D1_ALPHA_MODE_STRAIGHT",
-    "D2D1_ALPHA_MODE_IGNORE",
-    "D2D1_ALPHA_MODE_FORCE_DWORD",
-])
-
-D2D1_GAMMA = Enum("D2D1_GAMMA", [
-    "D2D1_GAMMA_2_2",
-    "D2D1_GAMMA_1_0",
-    "D2D1_GAMMA_FORCE_DWORD",
-])
-
-D2D1_OPACITY_MASK_CONTENT = Enum("D2D1_OPACITY_MASK_CONTENT", [
-    "D2D1_OPACITY_MASK_CONTENT_GRAPHICS",
-    "D2D1_OPACITY_MASK_CONTENT_TEXT_NATURAL",
-    "D2D1_OPACITY_MASK_CONTENT_TEXT_GDI_COMPATIBLE",
-    "D2D1_OPACITY_MASK_CONTENT_FORCE_DWORD",
-])
-
-D2D1_EXTEND_MODE = Enum("D2D1_EXTEND_MODE", [
-    "D2D1_EXTEND_MODE_CLAMP",
-    "D2D1_EXTEND_MODE_WRAP",
-    "D2D1_EXTEND_MODE_MIRROR",
-    "D2D1_EXTEND_MODE_FORCE_DWORD",
-])
-
-D2D1_ANTIALIAS_MODE = Enum("D2D1_ANTIALIAS_MODE", [
-    "D2D1_ANTIALIAS_MODE_PER_PRIMITIVE",
-    "D2D1_ANTIALIAS_MODE_ALIASED",
-    "D2D1_ANTIALIAS_MODE_FORCE_DWORD",
-])
-
-D2D1_TEXT_ANTIALIAS_MODE = Enum("D2D1_TEXT_ANTIALIAS_MODE", [
-    "D2D1_TEXT_ANTIALIAS_MODE_DEFAULT",
-    "D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE",
-    "D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE",
-    "D2D1_TEXT_ANTIALIAS_MODE_ALIASED",
-    "D2D1_TEXT_ANTIALIAS_MODE_FORCE_DWORD",
-])
-
-D2D1_BITMAP_INTERPOLATION_MODE = Enum("D2D1_BITMAP_INTERPOLATION_MODE", [
-    "D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR",
-    "D2D1_BITMAP_INTERPOLATION_MODE_LINEAR",
-    "D2D1_BITMAP_INTERPOLATION_MODE_FORCE_DWORD",
-])
-
-D2D1_DRAW_TEXT_OPTIONS = Enum("D2D1_DRAW_TEXT_OPTIONS", [
-    "D2D1_DRAW_TEXT_OPTIONS_NO_SNAP",
-    "D2D1_DRAW_TEXT_OPTIONS_NO_CLIP",
-    "D2D1_DRAW_TEXT_OPTIONS_NONE",
-    "D2D1_DRAW_TEXT_OPTIONS_FORCE_DWORD",
-])
-
-D2D1_PIXEL_FORMAT = Struct("D2D1_PIXEL_FORMAT", [
-    (DXGI_FORMAT, "format"),
-    (D2D1_ALPHA_MODE, "alphaMode"),
-])
-
-D2D1_POINT_2U = Alias("D2D1_POINT_2U", D2D_POINT_2U)
-D2D1_POINT_2F = Alias("D2D1_POINT_2F", D2D_POINT_2F)
-D2D1_RECT_F = Alias("D2D1_RECT_F", D2D_RECT_F)
-D2D1_RECT_U = Alias("D2D1_RECT_U", D2D_RECT_U)
-D2D1_SIZE_F = Alias("D2D1_SIZE_F", D2D_SIZE_F)
-D2D1_SIZE_U = Alias("D2D1_SIZE_U", D2D_SIZE_U)
-D2D1_COLOR_F = Alias("D2D1_COLOR_F", D2D_COLOR_F)
-D2D1_MATRIX_3X2_F = Alias("D2D1_MATRIX_3X2_F", D2D_MATRIX_3X2_F)
-D2D1_TAG = Alias("D2D1_TAG", UINT64)
-D2D1_BITMAP_PROPERTIES = Struct("D2D1_BITMAP_PROPERTIES", [
-    (D2D1_PIXEL_FORMAT, "pixelFormat"),
-    (FLOAT, "dpiX"),
-    (FLOAT, "dpiY"),
-])
-
-D2D1_GRADIENT_STOP = Struct("D2D1_GRADIENT_STOP", [
-    (FLOAT, "position"),
-    (D2D1_COLOR_F, "color"),
-])
-
-D2D1_BRUSH_PROPERTIES = Struct("D2D1_BRUSH_PROPERTIES", [
-    (FLOAT, "opacity"),
-    (D2D1_MATRIX_3X2_F, "transform"),
-])
-
-D2D1_BITMAP_BRUSH_PROPERTIES = Struct("D2D1_BITMAP_BRUSH_PROPERTIES", [
-    (D2D1_EXTEND_MODE, "extendModeX"),
-    (D2D1_EXTEND_MODE, "extendModeY"),
-    (D2D1_BITMAP_INTERPOLATION_MODE, "interpolationMode"),
-])
-
-D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES = Struct("D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES", [
-    (D2D1_POINT_2F, "startPoint"),
-    (D2D1_POINT_2F, "endPoint"),
-])
-
-D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES = Struct("D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES", [
-    (D2D1_POINT_2F, "center"),
-    (D2D1_POINT_2F, "gradientOriginOffset"),
-    (FLOAT, "radiusX"),
-    (FLOAT, "radiusY"),
-])
-
-D2D1_ARC_SIZE = Enum("D2D1_ARC_SIZE", [
-    "D2D1_ARC_SIZE_SMALL",
-    "D2D1_ARC_SIZE_LARGE",
-    "D2D1_ARC_SIZE_FORCE_DWORD",
-])
-
-D2D1_CAP_STYLE = Enum("D2D1_CAP_STYLE", [
-    "D2D1_CAP_STYLE_FLAT",
-    "D2D1_CAP_STYLE_SQUARE",
-    "D2D1_CAP_STYLE_ROUND",
-    "D2D1_CAP_STYLE_TRIANGLE",
-    "D2D1_CAP_STYLE_FORCE_DWORD",
-])
-
-D2D1_DASH_STYLE = Enum("D2D1_DASH_STYLE", [
-    "D2D1_DASH_STYLE_SOLID",
-    "D2D1_DASH_STYLE_DASH",
-    "D2D1_DASH_STYLE_DOT",
-    "D2D1_DASH_STYLE_DASH_DOT",
-    "D2D1_DASH_STYLE_DASH_DOT_DOT",
-    "D2D1_DASH_STYLE_CUSTOM",
-    "D2D1_DASH_STYLE_FORCE_DWORD",
-])
-
-D2D1_LINE_JOIN = Enum("D2D1_LINE_JOIN", [
-    "D2D1_LINE_JOIN_MITER",
-    "D2D1_LINE_JOIN_BEVEL",
-    "D2D1_LINE_JOIN_ROUND",
-    "D2D1_LINE_JOIN_MITER_OR_BEVEL",
-    "D2D1_LINE_JOIN_FORCE_DWORD",
-])
-
-D2D1_COMBINE_MODE = Enum("D2D1_COMBINE_MODE", [
-    "D2D1_COMBINE_MODE_UNION",
-    "D2D1_COMBINE_MODE_INTERSECT",
-    "D2D1_COMBINE_MODE_XOR",
-    "D2D1_COMBINE_MODE_EXCLUDE",
-    "D2D1_COMBINE_MODE_FORCE_DWORD",
-])
-
-D2D1_GEOMETRY_RELATION = Enum("D2D1_GEOMETRY_RELATION", [
-    "D2D1_GEOMETRY_RELATION_UNKNOWN",
-    "D2D1_GEOMETRY_RELATION_DISJOINT",
-    "D2D1_GEOMETRY_RELATION_IS_CONTAINED",
-    "D2D1_GEOMETRY_RELATION_CONTAINS",
-    "D2D1_GEOMETRY_RELATION_OVERLAP",
-    "D2D1_GEOMETRY_RELATION_FORCE_DWORD",
-])
-
-D2D1_GEOMETRY_SIMPLIFICATION_OPTION = Enum("D2D1_GEOMETRY_SIMPLIFICATION_OPTION", [
-    "D2D1_GEOMETRY_SIMPLIFICATION_OPTION_CUBICS_AND_LINES",
-    "D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES",
-    "D2D1_GEOMETRY_SIMPLIFICATION_OPTION_FORCE_DWORD",
-])
-
-D2D1_FIGURE_BEGIN = Enum("D2D1_FIGURE_BEGIN", [
-    "D2D1_FIGURE_BEGIN_FILLED",
-    "D2D1_FIGURE_BEGIN_HOLLOW",
-    "D2D1_FIGURE_BEGIN_FORCE_DWORD",
-])
-
-D2D1_FIGURE_END = Enum("D2D1_FIGURE_END", [
-    "D2D1_FIGURE_END_OPEN",
-    "D2D1_FIGURE_END_CLOSED",
-    "D2D1_FIGURE_END_FORCE_DWORD",
-])
-
-D2D1_BEZIER_SEGMENT = Struct("D2D1_BEZIER_SEGMENT", [
-    (D2D1_POINT_2F, "point1"),
-    (D2D1_POINT_2F, "point2"),
-    (D2D1_POINT_2F, "point3"),
-])
-
-D2D1_TRIANGLE = Struct("D2D1_TRIANGLE", [
-    (D2D1_POINT_2F, "point1"),
-    (D2D1_POINT_2F, "point2"),
-    (D2D1_POINT_2F, "point3"),
-])
-
-D2D1_PATH_SEGMENT = Enum("D2D1_PATH_SEGMENT", [
-    "D2D1_PATH_SEGMENT_NONE",
-    "D2D1_PATH_SEGMENT_FORCE_UNSTROKED",
-    "D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN",
-    "D2D1_PATH_SEGMENT_FORCE_DWORD",
-])
-
-D2D1_SWEEP_DIRECTION = Enum("D2D1_SWEEP_DIRECTION", [
-    "D2D1_SWEEP_DIRECTION_COUNTER_CLOCKWISE",
-    "D2D1_SWEEP_DIRECTION_CLOCKWISE",
-    "D2D1_SWEEP_DIRECTION_FORCE_DWORD",
-])
-
-D2D1_FILL_MODE = Enum("D2D1_FILL_MODE", [
-    "D2D1_FILL_MODE_ALTERNATE",
-    "D2D1_FILL_MODE_WINDING",
-    "D2D1_FILL_MODE_FORCE_DWORD",
-])
-
-D2D1_ARC_SEGMENT = Struct("D2D1_ARC_SEGMENT", [
-    (D2D1_POINT_2F, "point"),
-    (D2D1_SIZE_F, "size"),
-    (FLOAT, "rotationAngle"),
-    (D2D1_SWEEP_DIRECTION, "sweepDirection"),
-    (D2D1_ARC_SIZE, "arcSize"),
-])
-
-D2D1_QUADRATIC_BEZIER_SEGMENT = Struct("D2D1_QUADRATIC_BEZIER_SEGMENT", [
-    (D2D1_POINT_2F, "point1"),
-    (D2D1_POINT_2F, "point2"),
-])
-
-D2D1_ELLIPSE = Struct("D2D1_ELLIPSE", [
-    (D2D1_POINT_2F, "point"),
-    (FLOAT, "radiusX"),
-    (FLOAT, "radiusY"),
-])
-
-D2D1_ROUNDED_RECT = Struct("D2D1_ROUNDED_RECT", [
-    (D2D1_RECT_F, "rect"),
-    (FLOAT, "radiusX"),
-    (FLOAT, "radiusY"),
-])
-
-D2D1_STROKE_STYLE_PROPERTIES = Struct("D2D1_STROKE_STYLE_PROPERTIES", [
-    (D2D1_CAP_STYLE, "startCap"),
-    (D2D1_CAP_STYLE, "endCap"),
-    (D2D1_CAP_STYLE, "dashCap"),
-    (D2D1_LINE_JOIN, "lineJoin"),
-    (FLOAT, "miterLimit"),
-    (D2D1_DASH_STYLE, "dashStyle"),
-    (FLOAT, "dashOffset"),
-])
-
-D2D1_LAYER_OPTIONS = Enum("D2D1_LAYER_OPTIONS", [
-    "D2D1_LAYER_OPTIONS_NONE",
-    "D2D1_LAYER_OPTIONS_INITIALIZE_FOR_CLEARTYPE",
-    "D2D1_LAYER_OPTIONS_FORCE_DWORD",
-])
-
-D2D1_LAYER_PARAMETERS = Struct("D2D1_LAYER_PARAMETERS", [
-    (D2D1_RECT_F, "contentBounds"),
-    (OpaquePointer(ID2D1Geometry), "geometricMask"),
-    (D2D1_ANTIALIAS_MODE, "maskAntialiasMode"),
-    (D2D1_MATRIX_3X2_F, "maskTransform"),
-    (FLOAT, "opacity"),
-    (OpaquePointer(ID2D1Brush), "opacityBrush"),
-    (D2D1_LAYER_OPTIONS, "layerOptions"),
-])
-
-D2D1_WINDOW_STATE = Enum("D2D1_WINDOW_STATE", [
-    "D2D1_WINDOW_STATE_NONE",
-    "D2D1_WINDOW_STATE_OCCLUDED",
-    "D2D1_WINDOW_STATE_FORCE_DWORD",
-])
-
-D2D1_RENDER_TARGET_TYPE = Enum("D2D1_RENDER_TARGET_TYPE", [
-    "D2D1_RENDER_TARGET_TYPE_DEFAULT",
-    "D2D1_RENDER_TARGET_TYPE_SOFTWARE",
-    "D2D1_RENDER_TARGET_TYPE_HARDWARE",
-    "D2D1_RENDER_TARGET_TYPE_FORCE_DWORD",
-])
-
-D2D1_FEATURE_LEVEL = Enum("D2D1_FEATURE_LEVEL", [
-    "D2D1_FEATURE_LEVEL_DEFAULT",
-    "D2D1_FEATURE_LEVEL_9",
-    "D2D1_FEATURE_LEVEL_10",
-    "D2D1_FEATURE_LEVEL_FORCE_DWORD",
-])
-
-D2D1_RENDER_TARGET_USAGE = Enum("D2D1_RENDER_TARGET_USAGE", [
-    "D2D1_RENDER_TARGET_USAGE_NONE",
-    "D2D1_RENDER_TARGET_USAGE_FORCE_BITMAP_REMOTING",
-    "D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE",
-    "D2D1_RENDER_TARGET_USAGE_FORCE_DWORD",
-])
-
-D2D1_PRESENT_OPTIONS = Enum("D2D1_PRESENT_OPTIONS", [
-    "D2D1_PRESENT_OPTIONS_NONE",
-    "D2D1_PRESENT_OPTIONS_RETAIN_CONTENTS",
-    "D2D1_PRESENT_OPTIONS_IMMEDIATELY",
-    "D2D1_PRESENT_OPTIONS_FORCE_DWORD",
-])
-
-D2D1_RENDER_TARGET_PROPERTIES = Struct("D2D1_RENDER_TARGET_PROPERTIES", [
-    (D2D1_RENDER_TARGET_TYPE, "type"),
-    (D2D1_PIXEL_FORMAT, "pixelFormat"),
-    (FLOAT, "dpiX"),
-    (FLOAT, "dpiY"),
-    (D2D1_RENDER_TARGET_USAGE, "usage"),
-    (D2D1_FEATURE_LEVEL, "minLevel"),
-])
-
-D2D1_HWND_RENDER_TARGET_PROPERTIES = Struct("D2D1_HWND_RENDER_TARGET_PROPERTIES", [
-    (HWND, "hwnd"),
-    (D2D1_SIZE_U, "pixelSize"),
-    (D2D1_PRESENT_OPTIONS, "presentOptions"),
-])
-
-D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS = Enum("D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS", [
-    "D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_NONE",
-    "D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_GDI_COMPATIBLE",
-    "D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_FORCE_DWORD",
-])
-
-D2D1_DRAWING_STATE_DESCRIPTION = Struct("D2D1_DRAWING_STATE_DESCRIPTION", [
-    (D2D1_ANTIALIAS_MODE, "antialiasMode"),
-    (D2D1_TEXT_ANTIALIAS_MODE, "textAntialiasMode"),
-    (D2D1_TAG, "tag1"),
-    (D2D1_TAG, "tag2"),
-    (D2D1_MATRIX_3X2_F, "transform"),
-])
-
-D2D1_DC_INITIALIZE_MODE = Enum("D2D1_DC_INITIALIZE_MODE", [
-    "D2D1_DC_INITIALIZE_MODE_COPY",
-    "D2D1_DC_INITIALIZE_MODE_CLEAR",
-    "D2D1_DC_INITIALIZE_MODE_FORCE_DWORD",
-])
-
-D2D1_DEBUG_LEVEL = Enum("D2D1_DEBUG_LEVEL", [
-    "D2D1_DEBUG_LEVEL_NONE",
-    "D2D1_DEBUG_LEVEL_ERROR",
-    "D2D1_DEBUG_LEVEL_WARNING",
-    "D2D1_DEBUG_LEVEL_INFORMATION",
-    "D2D1_DEBUG_LEVEL_FORCE_DWORD",
-])
-
-D2D1_FACTORY_TYPE = Enum("D2D1_FACTORY_TYPE", [
-    "D2D1_FACTORY_TYPE_SINGLE_THREADED",
-    "D2D1_FACTORY_TYPE_MULTI_THREADED",
-    "D2D1_FACTORY_TYPE_FORCE_DWORD",
-])
-
-D2D1_FACTORY_OPTIONS = Struct("D2D1_FACTORY_OPTIONS", [
-    (D2D1_DEBUG_LEVEL, "debugLevel"),
-])
-
-ID2D1Resource = Interface("ID2D1Resource", IUnknown)
-ID2D1Resource.methods += [
-    Method(Void, "GetFactory", [Out(OpaquePointer(OpaquePointer(ID2D1Factory)), "factory")], const=True),
-]
-
-ID2D1Bitmap = Interface("ID2D1Bitmap", ID2D1Resource)
-ID2D1Bitmap.methods += [
-    Method(D2D1_SIZE_F, "GetSize", [], const=True),
-    Method(D2D1_SIZE_U, "GetPixelSize", [], const=True),
-    Method(D2D1_PIXEL_FORMAT, "GetPixelFormat", [], const=True),
-    Method(Void, "GetDpi", [Out(OpaquePointer(FLOAT), "dpiX"), Out(OpaquePointer(FLOAT), "dpiY")], const=True),
-    Method(HRESULT, "CopyFromBitmap", [(OpaquePointer(Const(D2D1_POINT_2U)), "destPoint"), (OpaquePointer(ID2D1Bitmap), "bitmap"), (OpaquePointer(Const(D2D1_RECT_U)), "srcRect")]),
-    Method(HRESULT, "CopyFromRenderTarget", [(OpaquePointer(Const(D2D1_POINT_2U)), "destPoint"), (OpaquePointer(ID2D1RenderTarget), "renderTarget"), (OpaquePointer(Const(D2D1_RECT_U)), "srcRect")]),
-    Method(HRESULT, "CopyFromMemory", [(OpaquePointer(Const(D2D1_RECT_U)), "dstRect"), (OpaquePointer(Const(Void)), "srcData"), (UINT32, "pitch")]),
-]
-
-ID2D1GradientStopCollection = Interface("ID2D1GradientStopCollection", ID2D1Resource)
-ID2D1GradientStopCollection.methods += [
-    Method(UINT32, "GetGradientStopCount", [], const=True),
-    Method(Void, "GetGradientStops", [Out(OpaquePointer(D2D1_GRADIENT_STOP), "gradientStops"), (UINT, "gradientStopsCount")], const=True),
-    Method(D2D1_GAMMA, "GetColorInterpolationGamma", [], const=True),
-    Method(D2D1_EXTEND_MODE, "GetExtendMode", [], const=True),
-]
-
-ID2D1Brush = Interface("ID2D1Brush", ID2D1Resource)
-ID2D1Brush.methods += [
-    Method(Void, "SetOpacity", [(FLOAT, "opacity")]),
-    Method(Void, "SetTransform", [(OpaquePointer(Const(D2D1_MATRIX_3X2_F)), "transform")]),
-    Method(FLOAT, "GetOpacity", [], const=True),
-    Method(Void, "GetTransform", [Out(OpaquePointer(D2D1_MATRIX_3X2_F), "transform")], const=True),
-]
-
-ID2D1BitmapBrush = Interface("ID2D1BitmapBrush", ID2D1Brush)
-ID2D1BitmapBrush.methods += [
-    Method(Void, "SetExtendModeX", [(D2D1_EXTEND_MODE, "extendModeX")]),
-    Method(Void, "SetExtendModeY", [(D2D1_EXTEND_MODE, "extendModeY")]),
-    Method(Void, "SetInterpolationMode", [(D2D1_BITMAP_INTERPOLATION_MODE, "interpolationMode")]),
-    Method(Void, "SetBitmap", [(OpaquePointer(ID2D1Bitmap), "bitmap")]),
-    Method(D2D1_EXTEND_MODE, "GetExtendModeX", [], const=True),
-    Method(D2D1_EXTEND_MODE, "GetExtendModeY", [], const=True),
-    Method(D2D1_BITMAP_INTERPOLATION_MODE, "GetInterpolationMode", [], const=True),
-    Method(Void, "GetBitmap", [Out(OpaquePointer(OpaquePointer(ID2D1Bitmap)), "bitmap")], const=True),
-]
-
-ID2D1SolidColorBrush = Interface("ID2D1SolidColorBrush", ID2D1Brush)
-ID2D1SolidColorBrush.methods += [
-    Method(Void, "SetColor", [(OpaquePointer(Const(D2D1_COLOR_F)), "color")]),
-    Method(D2D1_COLOR_F, "GetColor", [], const=True),
-]
-
-ID2D1LinearGradientBrush = Interface("ID2D1LinearGradientBrush", ID2D1Brush)
-ID2D1LinearGradientBrush.methods += [
-    Method(Void, "SetStartPoint", [(D2D1_POINT_2F, "startPoint")]),
-    Method(Void, "SetEndPoint", [(D2D1_POINT_2F, "endPoint")]),
-    Method(D2D1_POINT_2F, "GetStartPoint", [], const=True),
-    Method(D2D1_POINT_2F, "GetEndPoint", [], const=True),
-    Method(Void, "GetGradientStopCollection", [Out(OpaquePointer(OpaquePointer(ID2D1GradientStopCollection)), "gradientStopCollection")], const=True),
-]
-
-ID2D1RadialGradientBrush = Interface("ID2D1RadialGradientBrush", ID2D1Brush)
-ID2D1RadialGradientBrush.methods += [
-    Method(Void, "SetCenter", [(D2D1_POINT_2F, "center")]),
-    Method(Void, "SetGradientOriginOffset", [(D2D1_POINT_2F, "gradientOriginOffset")]),
-    Method(Void, "SetRadiusX", [(FLOAT, "radiusX")]),
-    Method(Void, "SetRadiusY", [(FLOAT, "radiusY")]),
-    Method(D2D1_POINT_2F, "GetCenter", [], const=True),
-    Method(D2D1_POINT_2F, "GetGradientOriginOffset", [], const=True),
-    Method(FLOAT, "GetRadiusX", [], const=True),
-    Method(FLOAT, "GetRadiusY", [], const=True),
-    Method(Void, "GetGradientStopCollection", [Out(OpaquePointer(OpaquePointer(ID2D1GradientStopCollection)), "gradientStopCollection")], const=True),
-]
-
-ID2D1StrokeStyle = Interface("ID2D1StrokeStyle", ID2D1Resource)
-ID2D1StrokeStyle.methods += [
-    Method(D2D1_CAP_STYLE, "GetStartCap", [], const=True),
-    Method(D2D1_CAP_STYLE, "GetEndCap", [], const=True),
-    Method(D2D1_CAP_STYLE, "GetDashCap", [], const=True),
-    Method(FLOAT, "GetMiterLimit", [], const=True),
-    Method(D2D1_LINE_JOIN, "GetLineJoin", [], const=True),
-    Method(FLOAT, "GetDashOffset", [], const=True),
-    Method(D2D1_DASH_STYLE, "GetDashStyle", [], const=True),
-    Method(UINT32, "GetDashesCount", [], const=True),
-    Method(Void, "GetDashes", [Out(OpaquePointer(FLOAT), "dashes"), (UINT, "dashesCount")], const=True),
-]
-
-ID2D1Geometry = Interface("ID2D1Geometry", ID2D1Resource)
-ID2D1Geometry.methods += [
-    Method(HRESULT, "GetBounds", [(OpaquePointer(Const(D2D1_MATRIX_3X2_F)), "worldTransform"), Out(OpaquePointer(D2D1_RECT_F), "bounds")], const=True),
-    Method(HRESULT, "GetWidenedBounds", [(FLOAT, "strokeWidth"), (OpaquePointer(ID2D1StrokeStyle), "strokeStyle"), (OpaquePointer(Const(D2D1_MATRIX_3X2_F)), "worldTransform"), (FLOAT, "flatteningTolerance"), Out(OpaquePointer(D2D1_RECT_F), "bounds")], const=True),
-    Method(HRESULT, "StrokeContainsPoint", [(D2D1_POINT_2F, "point"), (FLOAT, "strokeWidth"), (OpaquePointer(ID2D1StrokeStyle), "strokeStyle"), (OpaquePointer(Const(D2D1_MATRIX_3X2_F)), "worldTransform"), (FLOAT, "flatteningTolerance"), Out(OpaquePointer(BOOL), "contains")], const=True),
-    Method(HRESULT, "FillContainsPoint", [(D2D1_POINT_2F, "point"), (OpaquePointer(Const(D2D1_MATRIX_3X2_F)), "worldTransform"), (FLOAT, "flatteningTolerance"), Out(OpaquePointer(BOOL), "contains")], const=True),
-    Method(HRESULT, "CompareWithGeometry", [(OpaquePointer(ID2D1Geometry), "inputGeometry"), (OpaquePointer(Const(D2D1_MATRIX_3X2_F)), "inputGeometryTransform"), (FLOAT, "flatteningTolerance"), Out(OpaquePointer(D2D1_GEOMETRY_RELATION), "relation")], const=True),
-    Method(HRESULT, "Simplify", [(D2D1_GEOMETRY_SIMPLIFICATION_OPTION, "simplificationOption"), (OpaquePointer(Const(D2D1_MATRIX_3X2_F)), "worldTransform"), (FLOAT, "flatteningTolerance"), (OpaquePointer(ID2D1SimplifiedGeometrySink), "geometrySink")], const=True),
-    Method(HRESULT, "Tessellate", [(OpaquePointer(Const(D2D1_MATRIX_3X2_F)), "worldTransform"), (FLOAT, "flatteningTolerance"), (OpaquePointer(ID2D1TessellationSink), "tessellationSink")], const=True),
-    Method(HRESULT, "CombineWithGeometry", [(OpaquePointer(ID2D1Geometry), "inputGeometry"), (D2D1_COMBINE_MODE, "combineMode"), (OpaquePointer(Const(D2D1_MATRIX_3X2_F)), "inputGeometryTransform"), (FLOAT, "flatteningTolerance"), (OpaquePointer(ID2D1SimplifiedGeometrySink), "geometrySink")], const=True),
-    Method(HRESULT, "Outline", [(OpaquePointer(Const(D2D1_MATRIX_3X2_F)), "worldTransform"), (FLOAT, "flatteningTolerance"), (OpaquePointer(ID2D1SimplifiedGeometrySink), "geometrySink")], const=True),
-    Method(HRESULT, "ComputeArea", [(OpaquePointer(Const(D2D1_MATRIX_3X2_F)), "worldTransform"), (FLOAT, "flatteningTolerance"), Out(OpaquePointer(FLOAT), "area")], const=True),
-    Method(HRESULT, "ComputeLength", [(OpaquePointer(Const(D2D1_MATRIX_3X2_F)), "worldTransform"), (FLOAT, "flatteningTolerance"), Out(OpaquePointer(FLOAT), "length")], const=True),
-    Method(HRESULT, "ComputePointAtLength", [(FLOAT, "length"), (OpaquePointer(Const(D2D1_MATRIX_3X2_F)), "worldTransform"), (FLOAT, "flatteningTolerance"), Out(OpaquePointer(D2D1_POINT_2F), "point"), Out(OpaquePointer(D2D1_POINT_2F), "unitTangentVector")], const=True),
-    Method(HRESULT, "Widen", [(FLOAT, "strokeWidth"), (OpaquePointer(ID2D1StrokeStyle), "strokeStyle"), (OpaquePointer(Const(D2D1_MATRIX_3X2_F)), "worldTransform"), (FLOAT, "flatteningTolerance"), (OpaquePointer(ID2D1SimplifiedGeometrySink), "geometrySink")], const=True),
-]
-
-ID2D1RectangleGeometry = Interface("ID2D1RectangleGeometry", ID2D1Geometry)
-ID2D1RectangleGeometry.methods += [
-    Method(Void, "GetRect", [Out(OpaquePointer(D2D1_RECT_F), "rect")], const=True),
-]
-
-ID2D1RoundedRectangleGeometry = Interface("ID2D1RoundedRectangleGeometry", ID2D1Geometry)
-ID2D1RoundedRectangleGeometry.methods += [
-    Method(Void, "GetRoundedRect", [Out(OpaquePointer(D2D1_ROUNDED_RECT), "roundedRect")], const=True),
-]
-
-ID2D1EllipseGeometry = Interface("ID2D1EllipseGeometry", ID2D1Geometry)
-ID2D1EllipseGeometry.methods += [
-    Method(Void, "GetEllipse", [Out(OpaquePointer(D2D1_ELLIPSE), "ellipse")], const=True),
-]
-
-ID2D1GeometryGroup = Interface("ID2D1GeometryGroup", ID2D1Geometry)
-ID2D1GeometryGroup.methods += [
-    Method(D2D1_FILL_MODE, "GetFillMode", [], const=True),
-    Method(UINT32, "GetSourceGeometryCount", [], const=True),
-    Method(Void, "GetSourceGeometries", [Out(OpaquePointer(OpaquePointer(ID2D1Geometry)), "geometries"), (UINT, "geometriesCount")], const=True),
-]
-
-ID2D1TransformedGeometry = Interface("ID2D1TransformedGeometry", ID2D1Geometry)
-ID2D1TransformedGeometry.methods += [
-    Method(Void, "GetSourceGeometry", [Out(OpaquePointer(OpaquePointer(ID2D1Geometry)), "sourceGeometry")], const=True),
-    Method(Void, "GetTransform", [Out(OpaquePointer(D2D1_MATRIX_3X2_F), "transform")], const=True),
-]
-
-ID2D1SimplifiedGeometrySink = Interface("ID2D1SimplifiedGeometrySink", IUnknown)
-ID2D1SimplifiedGeometrySink.methods += [
-    Method(Void, "SetFillMode", [(D2D1_FILL_MODE, "fillMode")]),
-    Method(Void, "SetSegmentFlags", [(D2D1_PATH_SEGMENT, "vertexFlags")]),
-    Method(Void, "BeginFigure", [(D2D1_POINT_2F, "startPoint"), (D2D1_FIGURE_BEGIN, "figureBegin")]),
-    Method(Void, "AddLines", [(OpaquePointer(Const(D2D1_POINT_2F)), "points"), (UINT, "pointsCount")]),
-    Method(Void, "AddBeziers", [(OpaquePointer(Const(D2D1_BEZIER_SEGMENT)), "beziers"), (UINT, "beziersCount")]),
-    Method(Void, "EndFigure", [(D2D1_FIGURE_END, "figureEnd")]),
-    Method(HRESULT, "Close", []),
-]
-
-ID2D1GeometrySink = Interface("ID2D1GeometrySink", ID2D1SimplifiedGeometrySink)
-ID2D1GeometrySink.methods += [
-    Method(Void, "AddLine", [(D2D1_POINT_2F, "point")]),
-    Method(Void, "AddBezier", [(OpaquePointer(Const(D2D1_BEZIER_SEGMENT)), "bezier")]),
-    Method(Void, "AddQuadraticBezier", [(OpaquePointer(Const(D2D1_QUADRATIC_BEZIER_SEGMENT)), "bezier")]),
-    Method(Void, "AddQuadraticBeziers", [(OpaquePointer(Const(D2D1_QUADRATIC_BEZIER_SEGMENT)), "beziers"), (UINT, "beziersCount")]),
-    Method(Void, "AddArc", [(OpaquePointer(Const(D2D1_ARC_SEGMENT)), "arc")]),
-]
-
-ID2D1TessellationSink = Interface("ID2D1TessellationSink", IUnknown)
-ID2D1TessellationSink.methods += [
-    Method(Void, "AddTriangles", [(OpaquePointer(Const(D2D1_TRIANGLE)), "triangles"), (UINT, "trianglesCount")]),
-    Method(HRESULT, "Close", []),
-]
-
-ID2D1PathGeometry = Interface("ID2D1PathGeometry", ID2D1Geometry)
-ID2D1PathGeometry.methods += [
-    Method(HRESULT, "Open", [Out(OpaquePointer(OpaquePointer(ID2D1GeometrySink)), "geometrySink")]),
-    Method(HRESULT, "Stream", [(OpaquePointer(ID2D1GeometrySink), "geometrySink")], const=True),
-    Method(HRESULT, "GetSegmentCount", [Out(OpaquePointer(UINT32), "count")], const=True),
-    Method(HRESULT, "GetFigureCount", [Out(OpaquePointer(UINT32), "count")], const=True),
-]
-
-ID2D1Mesh = Interface("ID2D1Mesh", ID2D1Resource)
-ID2D1Mesh.methods += [
-    Method(HRESULT, "Open", [Out(OpaquePointer(OpaquePointer(ID2D1TessellationSink)), "tessellationSink")]),
-]
-
-ID2D1Layer = Interface("ID2D1Layer", ID2D1Resource)
-ID2D1Layer.methods += [
-    Method(D2D1_SIZE_F, "GetSize", [], const=True),
-]
-
-ID2D1DrawingStateBlock = Interface("ID2D1DrawingStateBlock", ID2D1Resource)
-ID2D1DrawingStateBlock.methods += [
-    Method(Void, "GetDescription", [Out(OpaquePointer(D2D1_DRAWING_STATE_DESCRIPTION), "stateDescription")], const=True),
-    Method(Void, "SetDescription", [(OpaquePointer(Const(D2D1_DRAWING_STATE_DESCRIPTION)), "stateDescription")]),
-    Method(Void, "SetTextRenderingParams", [(OpaquePointer(IDWriteRenderingParams), "textRenderingParams")]),
-    Method(Void, "GetTextRenderingParams", [Out(OpaquePointer(OpaquePointer(IDWriteRenderingParams)), "textRenderingParams")], const=True),
-]
-
-ID2D1RenderTarget = Interface("ID2D1RenderTarget", ID2D1Resource)
-ID2D1RenderTarget.methods += [
-    Method(HRESULT, "CreateBitmap", [(D2D1_SIZE_U, "size"), (OpaquePointer(Const(Void)), "srcData"), (UINT32, "pitch"), (OpaquePointer(Const(D2D1_BITMAP_PROPERTIES)), "bitmapProperties"), Out(OpaquePointer(OpaquePointer(ID2D1Bitmap)), "bitmap")]),
-    Method(HRESULT, "CreateBitmapFromWicBitmap", [(OpaquePointer(IWICBitmapSource), "wicBitmapSource"), (OpaquePointer(Const(D2D1_BITMAP_PROPERTIES)), "bitmapProperties"), Out(OpaquePointer(OpaquePointer(ID2D1Bitmap)), "bitmap")]),
-    Method(HRESULT, "CreateSharedBitmap", [(REFIID, "riid"), Out(OpaquePointer(Void), "data"), (OpaquePointer(Const(D2D1_BITMAP_PROPERTIES)), "bitmapProperties"), Out(OpaquePointer(OpaquePointer(ID2D1Bitmap)), "bitmap")]),
-    Method(HRESULT, "CreateBitmapBrush", [(OpaquePointer(ID2D1Bitmap), "bitmap"), (OpaquePointer(Const(D2D1_BITMAP_BRUSH_PROPERTIES)), "bitmapBrushProperties"), (OpaquePointer(Const(D2D1_BRUSH_PROPERTIES)), "brushProperties"), Out(OpaquePointer(OpaquePointer(ID2D1BitmapBrush)), "bitmapBrush")]),
-    Method(HRESULT, "CreateSolidColorBrush", [(OpaquePointer(Const(D2D1_COLOR_F)), "color"), (OpaquePointer(Const(D2D1_BRUSH_PROPERTIES)), "brushProperties"), Out(OpaquePointer(OpaquePointer(ID2D1SolidColorBrush)), "solidColorBrush")]),
-    Method(HRESULT, "CreateGradientStopCollection", [(OpaquePointer(Const(D2D1_GRADIENT_STOP)), "gradientStops"), (UINT, "gradientStopsCount"), (D2D1_GAMMA, "colorInterpolationGamma"), (D2D1_EXTEND_MODE, "extendMode"), Out(OpaquePointer(OpaquePointer(ID2D1GradientStopCollection)), "gradientStopCollection")]),
-    Method(HRESULT, "CreateLinearGradientBrush", [(OpaquePointer(Const(D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES)), "linearGradientBrushProperties"), (OpaquePointer(Const(D2D1_BRUSH_PROPERTIES)), "brushProperties"), (OpaquePointer(ID2D1GradientStopCollection), "gradientStopCollection"), Out(OpaquePointer(OpaquePointer(ID2D1LinearGradientBrush)), "linearGradientBrush")]),
-    Method(HRESULT, "CreateRadialGradientBrush", [(OpaquePointer(Const(D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES)), "radialGradientBrushProperties"), (OpaquePointer(Const(D2D1_BRUSH_PROPERTIES)), "brushProperties"), (OpaquePointer(ID2D1GradientStopCollection), "gradientStopCollection"), Out(OpaquePointer(OpaquePointer(ID2D1RadialGradientBrush)), "radialGradientBrush")]),
-    Method(HRESULT, "CreateCompatibleRenderTarget", [(OpaquePointer(Const(D2D1_SIZE_F)), "desiredSize"), (OpaquePointer(Const(D2D1_SIZE_U)), "desiredPixelSize"), (OpaquePointer(Const(D2D1_PIXEL_FORMAT)), "desiredFormat"), (D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS, "options"), Out(OpaquePointer(OpaquePointer(ID2D1BitmapRenderTarget)), "bitmapRenderTarget")]),
-    Method(HRESULT, "CreateLayer", [(OpaquePointer(Const(D2D1_SIZE_F)), "size"), Out(OpaquePointer(OpaquePointer(ID2D1Layer)), "layer")]),
-    Method(HRESULT, "CreateMesh", [Out(OpaquePointer(OpaquePointer(ID2D1Mesh)), "mesh")]),
-    Method(Void, "DrawLine", [(D2D1_POINT_2F, "point0"), (D2D1_POINT_2F, "point1"), (OpaquePointer(ID2D1Brush), "brush"), (FLOAT, "strokeWidth"), (OpaquePointer(ID2D1StrokeStyle), "strokeStyle")]),
-    Method(Void, "DrawRectangle", [(OpaquePointer(Const(D2D1_RECT_F)), "rect"), (OpaquePointer(ID2D1Brush), "brush"), (FLOAT, "strokeWidth"), (OpaquePointer(ID2D1StrokeStyle), "strokeStyle")]),
-    Method(Void, "FillRectangle", [(OpaquePointer(Const(D2D1_RECT_F)), "rect"), (OpaquePointer(ID2D1Brush), "brush")]),
-    Method(Void, "DrawRoundedRectangle", [(OpaquePointer(Const(D2D1_ROUNDED_RECT)), "roundedRect"), (OpaquePointer(ID2D1Brush), "brush"), (FLOAT, "strokeWidth"), (OpaquePointer(ID2D1StrokeStyle), "strokeStyle")]),
-    Method(Void, "FillRoundedRectangle", [(OpaquePointer(Const(D2D1_ROUNDED_RECT)), "roundedRect"), (OpaquePointer(ID2D1Brush), "brush")]),
-    Method(Void, "DrawEllipse", [(OpaquePointer(Const(D2D1_ELLIPSE)), "ellipse"), (OpaquePointer(ID2D1Brush), "brush"), (FLOAT, "strokeWidth"), (OpaquePointer(ID2D1StrokeStyle), "strokeStyle")]),
-    Method(Void, "FillEllipse", [(OpaquePointer(Const(D2D1_ELLIPSE)), "ellipse"), (OpaquePointer(ID2D1Brush), "brush")]),
-    Method(Void, "DrawGeometry", [(OpaquePointer(ID2D1Geometry), "geometry"), (OpaquePointer(ID2D1Brush), "brush"), (FLOAT, "strokeWidth"), (OpaquePointer(ID2D1StrokeStyle), "strokeStyle")]),
-    Method(Void, "FillGeometry", [(OpaquePointer(ID2D1Geometry), "geometry"), (OpaquePointer(ID2D1Brush), "brush"), (OpaquePointer(ID2D1Brush), "opacityBrush")]),
-    Method(Void, "FillMesh", [(OpaquePointer(ID2D1Mesh), "mesh"), (OpaquePointer(ID2D1Brush), "brush")]),
-    Method(Void, "FillOpacityMask", [(OpaquePointer(ID2D1Bitmap), "opacityMask"), (OpaquePointer(ID2D1Brush), "brush"), (D2D1_OPACITY_MASK_CONTENT, "content"), (OpaquePointer(Const(D2D1_RECT_F)), "destinationRectangle"), (OpaquePointer(Const(D2D1_RECT_F)), "sourceRectangle")]),
-    Method(Void, "DrawBitmap", [(OpaquePointer(ID2D1Bitmap), "bitmap"), (OpaquePointer(Const(D2D1_RECT_F)), "destinationRectangle"), (FLOAT, "opacity"), (D2D1_BITMAP_INTERPOLATION_MODE, "interpolationMode"), (OpaquePointer(Const(D2D1_RECT_F)), "sourceRectangle")]),
-    Method(Void, "DrawText", [(OpaquePointer(Const(WCHAR)), "string"), (UINT, "stringLength"), (OpaquePointer(IDWriteTextFormat), "textFormat"), (OpaquePointer(Const(D2D1_RECT_F)), "layoutRect"), (OpaquePointer(ID2D1Brush), "defaultForegroundBrush"), (D2D1_DRAW_TEXT_OPTIONS, "options"), (DWRITE_MEASURING_MODE, "measuringMode")]),
-    Method(Void, "DrawTextLayout", [(D2D1_POINT_2F, "origin"), (OpaquePointer(IDWriteTextLayout), "textLayout"), (OpaquePointer(ID2D1Brush), "defaultForegroundBrush"), (D2D1_DRAW_TEXT_OPTIONS, "options")]),
-    Method(Void, "DrawGlyphRun", [(D2D1_POINT_2F, "baselineOrigin"), (OpaquePointer(Const(DWRITE_GLYPH_RUN)), "glyphRun"), (OpaquePointer(ID2D1Brush), "foregroundBrush"), (DWRITE_MEASURING_MODE, "measuringMode")]),
-    Method(Void, "SetTransform", [(OpaquePointer(Const(D2D1_MATRIX_3X2_F)), "transform")]),
-    Method(Void, "GetTransform", [Out(OpaquePointer(D2D1_MATRIX_3X2_F), "transform")], const=True),
-    Method(Void, "SetAntialiasMode", [(D2D1_ANTIALIAS_MODE, "antialiasMode")]),
-    Method(D2D1_ANTIALIAS_MODE, "GetAntialiasMode", [], const=True),
-    Method(Void, "SetTextAntialiasMode", [(D2D1_TEXT_ANTIALIAS_MODE, "textAntialiasMode")]),
-    Method(D2D1_TEXT_ANTIALIAS_MODE, "GetTextAntialiasMode", [], const=True),
-    Method(Void, "SetTextRenderingParams", [(OpaquePointer(IDWriteRenderingParams), "textRenderingParams")]),
-    Method(Void, "GetTextRenderingParams", [Out(OpaquePointer(OpaquePointer(IDWriteRenderingParams)), "textRenderingParams")], const=True),
-    Method(Void, "SetTags", [(D2D1_TAG, "tag1"), (D2D1_TAG, "tag2")]),
-    Method(Void, "GetTags", [Out(OpaquePointer(D2D1_TAG), "tag1"), Out(OpaquePointer(D2D1_TAG), "tag2")], const=True),
-    Method(Void, "PushLayer", [(OpaquePointer(Const(D2D1_LAYER_PARAMETERS)), "layerParameters"), (OpaquePointer(ID2D1Layer), "layer")]),
-    Method(Void, "PopLayer", []),
-    Method(HRESULT, "Flush", [Out(OpaquePointer(D2D1_TAG), "tag1"), Out(OpaquePointer(D2D1_TAG), "tag2")]),
-    Method(Void, "SaveDrawingState", [Out(OpaquePointer(ID2D1DrawingStateBlock), "drawingStateBlock")], const=True),
-    Method(Void, "RestoreDrawingState", [(OpaquePointer(ID2D1DrawingStateBlock), "drawingStateBlock")]),
-    Method(Void, "PushAxisAlignedClip", [(OpaquePointer(Const(D2D1_RECT_F)), "clipRect"), (D2D1_ANTIALIAS_MODE, "antialiasMode")]),
-    Method(Void, "PopAxisAlignedClip", []),
-    Method(Void, "Clear", [(OpaquePointer(Const(D2D1_COLOR_F)), "clearColor")]),
-    Method(Void, "BeginDraw", []),
-    Method(HRESULT, "EndDraw", [Out(OpaquePointer(D2D1_TAG), "tag1"), Out(OpaquePointer(D2D1_TAG), "tag2")]),
-    Method(D2D1_PIXEL_FORMAT, "GetPixelFormat", [], const=True),
-    Method(Void, "SetDpi", [(FLOAT, "dpiX"), (FLOAT, "dpiY")]),
-    Method(Void, "GetDpi", [Out(OpaquePointer(FLOAT), "dpiX"), Out(OpaquePointer(FLOAT), "dpiY")], const=True),
-    Method(D2D1_SIZE_F, "GetSize", [], const=True),
-    Method(D2D1_SIZE_U, "GetPixelSize", [], const=True),
-    Method(UINT32, "GetMaximumBitmapSize", [], const=True),
-    Method(BOOL, "IsSupported", [(OpaquePointer(Const(D2D1_RENDER_TARGET_PROPERTIES)), "renderTargetProperties")], const=True),
-]
-
-ID2D1BitmapRenderTarget = Interface("ID2D1BitmapRenderTarget", ID2D1RenderTarget)
-ID2D1BitmapRenderTarget.methods += [
-    Method(HRESULT, "GetBitmap", [Out(OpaquePointer(OpaquePointer(ID2D1Bitmap)), "bitmap")]),
-]
-
-ID2D1HwndRenderTarget = Interface("ID2D1HwndRenderTarget", ID2D1RenderTarget)
-ID2D1HwndRenderTarget.methods += [
-    Method(D2D1_WINDOW_STATE, "CheckWindowState", []),
-    Method(HRESULT, "Resize", [(OpaquePointer(Const(D2D1_SIZE_U)), "pixelSize")]),
-    Method(HWND, "GetHwnd", [], const=True),
-]
-
-ID2D1GdiInteropRenderTarget = Interface("ID2D1GdiInteropRenderTarget", IUnknown)
-ID2D1GdiInteropRenderTarget.methods += [
-    Method(HRESULT, "GetDC", [(D2D1_DC_INITIALIZE_MODE, "mode"), Out(OpaquePointer(HDC), "hdc")]),
-    Method(HRESULT, "ReleaseDC", [(OpaquePointer(Const(RECT)), "update")]),
-]
-
-ID2D1DCRenderTarget = Interface("ID2D1DCRenderTarget", ID2D1RenderTarget)
-ID2D1DCRenderTarget.methods += [
-    Method(HRESULT, "BindDC", [(Const(HDC), "hDC"), (OpaquePointer(Const(RECT)), "pSubRect")]),
-]
-
-ID2D1Factory = Interface("ID2D1Factory", IUnknown)
-ID2D1Factory.methods += [
-    Method(HRESULT, "ReloadSystemMetrics", []),
-    Method(Void, "GetDesktopDpi", [Out(OpaquePointer(FLOAT), "dpiX"), Out(OpaquePointer(FLOAT), "dpiY")]),
-    Method(HRESULT, "CreateRectangleGeometry", [(OpaquePointer(Const(D2D1_RECT_F)), "rectangle"), Out(OpaquePointer(OpaquePointer(ID2D1RectangleGeometry)), "rectangleGeometry")]),
-    Method(HRESULT, "CreateRoundedRectangleGeometry", [(OpaquePointer(Const(D2D1_ROUNDED_RECT)), "roundedRectangle"), Out(OpaquePointer(OpaquePointer(ID2D1RoundedRectangleGeometry)), "roundedRectangleGeometry")]),
-    Method(HRESULT, "CreateEllipseGeometry", [(OpaquePointer(Const(D2D1_ELLIPSE)), "ellipse"), Out(OpaquePointer(OpaquePointer(ID2D1EllipseGeometry)), "ellipseGeometry")]),
-    Method(HRESULT, "CreateGeometryGroup", [(D2D1_FILL_MODE, "fillMode"), (OpaquePointer(OpaquePointer(ID2D1Geometry)), "geometries"), (UINT, "geometriesCount"), Out(OpaquePointer(OpaquePointer(ID2D1GeometryGroup)), "geometryGroup")]),
-    Method(HRESULT, "CreateTransformedGeometry", [(OpaquePointer(ID2D1Geometry), "sourceGeometry"), (OpaquePointer(Const(D2D1_MATRIX_3X2_F)), "transform"), Out(OpaquePointer(OpaquePointer(ID2D1TransformedGeometry)), "transformedGeometry")]),
-    Method(HRESULT, "CreatePathGeometry", [Out(OpaquePointer(OpaquePointer(ID2D1PathGeometry)), "pathGeometry")]),
-    Method(HRESULT, "CreateStrokeStyle", [(OpaquePointer(Const(D2D1_STROKE_STYLE_PROPERTIES)), "strokeStyleProperties"), (OpaquePointer(Const(FLOAT)), "dashes"), (UINT, "dashesCount"), Out(OpaquePointer(OpaquePointer(ID2D1StrokeStyle)), "strokeStyle")]),
-    Method(HRESULT, "CreateDrawingStateBlock", [(OpaquePointer(Const(D2D1_DRAWING_STATE_DESCRIPTION)), "drawingStateDescription"), (OpaquePointer(IDWriteRenderingParams), "textRenderingParams"), Out(OpaquePointer(OpaquePointer(ID2D1DrawingStateBlock)), "drawingStateBlock")]),
-    Method(HRESULT, "CreateWicBitmapRenderTarget", [(OpaquePointer(IWICBitmap), "target"), (OpaquePointer(Const(D2D1_RENDER_TARGET_PROPERTIES)), "renderTargetProperties"), Out(OpaquePointer(OpaquePointer(ID2D1RenderTarget)), "renderTarget")]),
-    Method(HRESULT, "CreateHwndRenderTarget", [(OpaquePointer(Const(D2D1_RENDER_TARGET_PROPERTIES)), "renderTargetProperties"), (OpaquePointer(Const(D2D1_HWND_RENDER_TARGET_PROPERTIES)), "hwndRenderTargetProperties"), Out(OpaquePointer(OpaquePointer(ID2D1HwndRenderTarget)), "hwndRenderTarget")]),
-    Method(HRESULT, "CreateDxgiSurfaceRenderTarget", [(OpaquePointer(IDXGISurface), "dxgiSurface"), (OpaquePointer(Const(D2D1_RENDER_TARGET_PROPERTIES)), "renderTargetProperties"), Out(OpaquePointer(OpaquePointer(ID2D1RenderTarget)), "renderTarget")]),
-    Method(HRESULT, "CreateDCRenderTarget", [(OpaquePointer(Const(D2D1_RENDER_TARGET_PROPERTIES)), "renderTargetProperties"), Out(OpaquePointer(OpaquePointer(ID2D1DCRenderTarget)), "dcRenderTarget")]),
-]
-
-    StdFunction(HRESULT, "D2D1CreateFactory", [(D2D1_FACTORY_TYPE, "factoryType"), (REFIID, "riid"), (OpaquePointer(Const(D2D1_FACTORY_OPTIONS)), "pFactoryOptions"), Out(OpaquePointer(OpaquePointer(Void)), "ppIFactory")]),
-    StdFunction(Void, "D2D1MakeRotateMatrix", [(FLOAT, "angle"), (D2D1_POINT_2F, "center"), Out(OpaquePointer(D2D1_MATRIX_3X2_F), "matrix")]),
-    StdFunction(Void, "D2D1MakeSkewMatrix", [(FLOAT, "angleX"), (FLOAT, "angleY"), (D2D1_POINT_2F, "center"), Out(OpaquePointer(D2D1_MATRIX_3X2_F), "matrix")]),
-    StdFunction(BOOL, "D2D1IsMatrixInvertible", [(OpaquePointer(Const(D2D1_MATRIX_3X2_F)), "matrix")]),
-    StdFunction(BOOL, "D2D1InvertMatrix", [Out(OpaquePointer(D2D1_MATRIX_3X2_F), "matrix")]),
diff --git a/thirdparty/getopt/CMakeLists.txt b/thirdparty/getopt/CMakeLists.txt
new file mode 100644 (file)
index 0000000..fc46f7d
--- /dev/null
@@ -0,0 +1,5 @@
+include_directories (${CMAKE_CURRENT_SOURCE_DIR})
+
+add_library (getopt_bundled STATIC
+    getopt_long.c
+)
diff --git a/thirdparty/getopt/getopt.h b/thirdparty/getopt/getopt.h
new file mode 100644 (file)
index 0000000..117608f
--- /dev/null
@@ -0,0 +1,82 @@
+/*     $OpenBSD: getopt.h,v 1.2 2008/06/26 05:42:04 ray Exp $  */
+/*     $NetBSD: getopt.h,v 1.4 2000/07/07 10:43:54 ad Exp $    */
+
+/*-
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Dieter Baron and Thomas Klausner.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _GETOPT_H_
+#define _GETOPT_H_
+
+/*
+ * GNU-like getopt_long() and 4.4BSD getsubopt()/optreset extensions
+ */
+#define no_argument        0
+#define required_argument  1
+#define optional_argument  2
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct option {
+       /* name of long option */
+       const char *name;
+       /*
+        * one of no_argument, required_argument, and optional_argument:
+        * whether option takes an argument
+        */
+       int has_arg;
+       /* if not NULL, set *flag to val when option found */
+       int *flag;
+       /* if flag not NULL, value to set *flag to; else return value */
+       int val;
+};
+
+int     getopt_long(int, char * const *, const char *,
+           const struct option *, int *);
+int     getopt_long_only(int, char * const *, const char *,
+           const struct option *, int *);
+#ifndef _GETOPT_DEFINED_
+#define _GETOPT_DEFINED_
+int     getopt(int, char * const *, const char *);
+int     getsubopt(char **, char * const *, char **);
+
+extern   char *optarg;                  /* getopt(3) external variables */
+extern   int opterr;
+extern   int optind;
+extern   int optopt;
+extern   int optreset;
+extern   char *suboptarg;               /* getsubopt(3) external variable */
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !_GETOPT_H_ */
diff --git a/thirdparty/getopt/getopt_long.c b/thirdparty/getopt/getopt_long.c
new file mode 100644 (file)
index 0000000..81268b8
--- /dev/null
@@ -0,0 +1,511 @@
+/*     $OpenBSD: getopt_long.c,v 1.24 2010/07/22 19:31:53 blambert Exp $       */
+/*     $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $      */
+
+/*
+ * Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+/*-
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Dieter Baron and Thomas Klausner.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <errno.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+int    opterr = 1;             /* if error message should be printed */
+int    optind = 1;             /* index into parent argv vector */
+int    optopt = '?';           /* character checked for validity */
+int    optreset;               /* reset getopt */
+char    *optarg;               /* argument associated with option */
+
+#define PRINT_ERROR    ((opterr) && (*options != ':'))
+
+#define FLAG_PERMUTE   0x01    /* permute non-options to the end of argv */
+#define FLAG_ALLARGS   0x02    /* treat non-options as args to option "-1" */
+#define FLAG_LONGONLY  0x04    /* operate as getopt_long_only */
+
+/* return values */
+#define        BADCH           (int)'?'
+#define        BADARG          ((*options == ':') ? (int)':' : (int)'?')
+#define        INORDER         (int)1
+
+#define        EMSG            ""
+
+static int getopt_internal(int, char * const *, const char *,
+                          const struct option *, int *, int);
+static int parse_long_options(char * const *, const char *,
+                             const struct option *, int *, int);
+static int gcd(int, int);
+static void permute_args(int, int, int, char * const *);
+
+static char *place = EMSG; /* option letter processing */
+
+/* XXX: set optreset to 1 rather than these two */
+static int nonopt_start = -1; /* first non option argument (for permute) */
+static int nonopt_end = -1;   /* first option after non options (for permute) */
+
+/* Error messages */
+static const char recargchar[] = "option requires an argument -- %c";
+static const char recargstring[] = "option requires an argument -- %s";
+static const char ambig[] = "ambiguous option -- %.*s";
+static const char noarg[] = "option doesn't take an argument -- %.*s";
+static const char illoptchar[] = "unknown option -- %c";
+static const char illoptstring[] = "unknown option -- %s";
+
+/*
+ * Compute the greatest common divisor of a and b.
+ */
+static int
+gcd(int a, int b)
+{
+       int c;
+
+       c = a % b;
+       while (c != 0) {
+               a = b;
+               b = c;
+               c = a % b;
+       }
+
+       return (b);
+}
+
+/*
+ * Exchange the block from nonopt_start to nonopt_end with the block
+ * from nonopt_end to opt_end (keeping the same order of arguments
+ * in each block).
+ */
+static void
+permute_args(int panonopt_start, int panonopt_end, int opt_end,
+       char * const *nargv)
+{
+       int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
+       char *swap;
+
+       /*
+        * compute lengths of blocks and number and size of cycles
+        */
+       nnonopts = panonopt_end - panonopt_start;
+       nopts = opt_end - panonopt_end;
+       ncycle = gcd(nnonopts, nopts);
+       cyclelen = (opt_end - panonopt_start) / ncycle;
+
+       for (i = 0; i < ncycle; i++) {
+               cstart = panonopt_end+i;
+               pos = cstart;
+               for (j = 0; j < cyclelen; j++) {
+                       if (pos >= panonopt_end)
+                               pos -= nnonopts;
+                       else
+                               pos += nopts;
+                       swap = nargv[pos];
+                       /* LINTED const cast */
+                       ((char **) nargv)[pos] = nargv[cstart];
+                       /* LINTED const cast */
+                       ((char **)nargv)[cstart] = swap;
+               }
+       }
+}
+
+/*
+ * parse_long_options --
+ *     Parse long options in argc/argv argument vector.
+ * Returns -1 if short_too is set and the option does not match long_options.
+ */
+static int
+parse_long_options(char * const *nargv, const char *options,
+       const struct option *long_options, int *idx, int short_too)
+{
+       char *current_argv, *has_equal;
+       size_t current_argv_len;
+       int i, match;
+
+       current_argv = place;
+       match = -1;
+
+       optind++;
+
+       if ((has_equal = strchr(current_argv, '=')) != NULL) {
+               /* argument found (--option=arg) */
+               current_argv_len = has_equal - current_argv;
+               has_equal++;
+       } else
+               current_argv_len = strlen(current_argv);
+
+       for (i = 0; long_options[i].name; i++) {
+               /* find matching long option */
+               if (strncmp(current_argv, long_options[i].name,
+                   current_argv_len))
+                       continue;
+
+               if (strlen(long_options[i].name) == current_argv_len) {
+                       /* exact match */
+                       match = i;
+                       break;
+               }
+               /*
+                * If this is a known short option, don't allow
+                * a partial match of a single character.
+                */
+               if (short_too && current_argv_len == 1)
+                       continue;
+
+               if (match == -1)        /* partial match */
+                       match = i;
+               else {
+                       /* ambiguous abbreviation */
+                       if (PRINT_ERROR)
+                               fprintf(stderr, ambig, (int)current_argv_len,
+                                    current_argv);
+                       optopt = 0;
+                       return (BADCH);
+               }
+       }
+       if (match != -1) {              /* option found */
+               if (long_options[match].has_arg == no_argument
+                   && has_equal) {
+                       if (PRINT_ERROR)
+                               fprintf(stderr, noarg, (int)current_argv_len,
+                                    current_argv);
+                       /*
+                        * XXX: GNU sets optopt to val regardless of flag
+                        */
+                       if (long_options[match].flag == NULL)
+                               optopt = long_options[match].val;
+                       else
+                               optopt = 0;
+                       return (BADARG);
+               }
+               if (long_options[match].has_arg == required_argument ||
+                   long_options[match].has_arg == optional_argument) {
+                       if (has_equal)
+                               optarg = has_equal;
+                       else if (long_options[match].has_arg ==
+                           required_argument) {
+                               /*
+                                * optional argument doesn't use next nargv
+                                */
+                               optarg = nargv[optind++];
+                       }
+               }
+               if ((long_options[match].has_arg == required_argument)
+                   && (optarg == NULL)) {
+                       /*
+                        * Missing argument; leading ':' indicates no error
+                        * should be generated.
+                        */
+                       if (PRINT_ERROR)
+                               fprintf(stderr, recargstring,
+                                   current_argv);
+                       /*
+                        * XXX: GNU sets optopt to val regardless of flag
+                        */
+                       if (long_options[match].flag == NULL)
+                               optopt = long_options[match].val;
+                       else
+                               optopt = 0;
+                       --optind;
+                       return (BADARG);
+               }
+       } else {                        /* unknown option */
+               if (short_too) {
+                       --optind;
+                       return (-1);
+               }
+               if (PRINT_ERROR)
+                       fprintf(stderr, illoptstring, current_argv);
+               optopt = 0;
+               return (BADCH);
+       }
+       if (idx)
+               *idx = match;
+       if (long_options[match].flag) {
+               *long_options[match].flag = long_options[match].val;
+               return (0);
+       } else
+               return (long_options[match].val);
+}
+
+/*
+ * getopt_internal --
+ *     Parse argc/argv argument vector.  Called by user level routines.
+ */
+static int
+getopt_internal(int nargc, char * const *nargv, const char *options,
+       const struct option *long_options, int *idx, int flags)
+{
+       char *oli;                              /* option letter list index */
+       int optchar, short_too;
+       static int posixly_correct = -1;
+
+       if (options == NULL)
+               return (-1);
+
+       /*
+        * Disable GNU extensions if POSIXLY_CORRECT is set or options
+        * string begins with a '+'.
+        */
+       if (posixly_correct == -1)
+               posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);
+       if (posixly_correct || *options == '+')
+               flags &= ~FLAG_PERMUTE;
+       else if (*options == '-')
+               flags |= FLAG_ALLARGS;
+       if (*options == '+' || *options == '-')
+               options++;
+
+       /*
+        * XXX Some GNU programs (like cvs) set optind to 0 instead of
+        * XXX using optreset.  Work around this braindamage.
+        */
+       if (optind == 0)
+               optind = optreset = 1;
+
+       optarg = NULL;
+       if (optreset)
+               nonopt_start = nonopt_end = -1;
+start:
+       if (optreset || !*place) {              /* update scanning pointer */
+               optreset = 0;
+               if (optind >= nargc) {          /* end of argument vector */
+                       place = EMSG;
+                       if (nonopt_end != -1) {
+                               /* do permutation, if we have to */
+                               permute_args(nonopt_start, nonopt_end,
+                                   optind, nargv);
+                               optind -= nonopt_end - nonopt_start;
+                       }
+                       else if (nonopt_start != -1) {
+                               /*
+                                * If we skipped non-options, set optind
+                                * to the first of them.
+                                */
+                               optind = nonopt_start;
+                       }
+                       nonopt_start = nonopt_end = -1;
+                       return (-1);
+               }
+               if (*(place = nargv[optind]) != '-' ||
+                   (place[1] == '\0' && strchr(options, '-') == NULL)) {
+                       place = EMSG;           /* found non-option */
+                       if (flags & FLAG_ALLARGS) {
+                               /*
+                                * GNU extension:
+                                * return non-option as argument to option 1
+                                */
+                               optarg = nargv[optind++];
+                               return (INORDER);
+                       }
+                       if (!(flags & FLAG_PERMUTE)) {
+                               /*
+                                * If no permutation wanted, stop parsing
+                                * at first non-option.
+                                */
+                               return (-1);
+                       }
+                       /* do permutation */
+                       if (nonopt_start == -1)
+                               nonopt_start = optind;
+                       else if (nonopt_end != -1) {
+                               permute_args(nonopt_start, nonopt_end,
+                                   optind, nargv);
+                               nonopt_start = optind -
+                                   (nonopt_end - nonopt_start);
+                               nonopt_end = -1;
+                       }
+                       optind++;
+                       /* process next argument */
+                       goto start;
+               }
+               if (nonopt_start != -1 && nonopt_end == -1)
+                       nonopt_end = optind;
+
+               /*
+                * If we have "-" do nothing, if "--" we are done.
+                */
+               if (place[1] != '\0' && *++place == '-' && place[1] == '\0') {
+                       optind++;
+                       place = EMSG;
+                       /*
+                        * We found an option (--), so if we skipped
+                        * non-options, we have to permute.
+                        */
+                       if (nonopt_end != -1) {
+                               permute_args(nonopt_start, nonopt_end,
+                                   optind, nargv);
+                               optind -= nonopt_end - nonopt_start;
+                       }
+                       nonopt_start = nonopt_end = -1;
+                       return (-1);
+               }
+       }
+
+       /*
+        * Check long options if:
+        *  1) we were passed some
+        *  2) the arg is not just "-"
+        *  3) either the arg starts with -- we are getopt_long_only()
+        */
+       if (long_options != NULL && place != nargv[optind] &&
+           (*place == '-' || (flags & FLAG_LONGONLY))) {
+               short_too = 0;
+               if (*place == '-')
+                       place++;                /* --foo long option */
+               else if (*place != ':' && strchr(options, *place) != NULL)
+                       short_too = 1;          /* could be short option too */
+
+               optchar = parse_long_options(nargv, options, long_options,
+                   idx, short_too);
+               if (optchar != -1) {
+                       place = EMSG;
+                       return (optchar);
+               }
+       }
+
+       if ((optchar = (int)*place++) == (int)':' ||
+           (optchar == (int)'-' && *place != '\0') ||
+           (oli = strchr(options, optchar)) == NULL) {
+               /*
+                * If the user specified "-" and  '-' isn't listed in
+                * options, return -1 (non-option) as per POSIX.
+                * Otherwise, it is an unknown option character (or ':').
+                */
+               if (optchar == (int)'-' && *place == '\0')
+                       return (-1);
+               if (!*place)
+                       ++optind;
+               if (PRINT_ERROR)
+                       fprintf(stderr, illoptchar, optchar);
+               optopt = optchar;
+               return (BADCH);
+       }
+       if (long_options != NULL && optchar == 'W' && oli[1] == ';') {
+               /* -W long-option */
+               if (*place)                     /* no space */
+                       /* NOTHING */;
+               else if (++optind >= nargc) {   /* no arg */
+                       place = EMSG;
+                       if (PRINT_ERROR)
+                               fprintf(stderr, recargchar, optchar);
+                       optopt = optchar;
+                       return (BADARG);
+               } else                          /* white space */
+                       place = nargv[optind];
+               optchar = parse_long_options(nargv, options, long_options,
+                   idx, 0);
+               place = EMSG;
+               return (optchar);
+       }
+       if (*++oli != ':') {                    /* doesn't take argument */
+               if (!*place)
+                       ++optind;
+       } else {                                /* takes (optional) argument */
+               optarg = NULL;
+               if (*place)                     /* no white space */
+                       optarg = place;
+               else if (oli[1] != ':') {       /* arg not optional */
+                       if (++optind >= nargc) {        /* no arg */
+                               place = EMSG;
+                               if (PRINT_ERROR)
+                                       fprintf(stderr, recargchar, optchar);
+                               optopt = optchar;
+                               return (BADARG);
+                       } else
+                               optarg = nargv[optind];
+               }
+               place = EMSG;
+               ++optind;
+       }
+       /* dump back option letter */
+       return (optchar);
+}
+
+/*
+ * getopt --
+ *     Parse argc/argv argument vector.
+ *
+ * [eventually this will replace the BSD getopt]
+ */
+int
+getopt(int nargc, char * const *nargv, const char *options)
+{
+
+       /*
+        * We don't pass FLAG_PERMUTE to getopt_internal() since
+        * the BSD getopt(3) (unlike GNU) has never done this.
+        *
+        * Furthermore, since many privileged programs call getopt()
+        * before dropping privileges it makes sense to keep things
+        * as simple (and bug-free) as possible.
+        */
+       return (getopt_internal(nargc, nargv, options, NULL, NULL, 0));
+}
+
+/*
+ * getopt_long --
+ *     Parse argc/argv argument vector.
+ */
+int
+getopt_long(int nargc, char * const *nargv, const char *options,
+    const struct option *long_options, int *idx)
+{
+
+       return (getopt_internal(nargc, nargv, options, long_options, idx,
+           FLAG_PERMUTE));
+}
+
+/*
+ * getopt_long_only --
+ *     Parse argc/argv argument vector.
+ */
+int
+getopt_long_only(int nargc, char * const *nargv, const char *options,
+    const struct option *long_options, int *idx)
+{
+
+       return (getopt_internal(nargc, nargv, options, long_options, idx,
+           FLAG_PERMUTE|FLAG_LONGONLY));
+}
index 38005008941efeb4e3744cbecf1ac3a9a5a01a66..fe35bea19699730a47abe98287f3f2382f8db90b 100644 (file)
--- a/trace.py
+++ b/trace.py
@@ -148,10 +148,20 @@ class ValueSerializer(stdapi.Visitor):
         print '    trace::localWriter.write%s(%s);' % (literal.kind, instance)
 
     def visitString(self, string, instance):
+        if string.kind == 'String':
+            cast = 'const char *'
+        elif string.kind == 'WString':
+            cast = 'const wchar_t *'
+        else:
+            assert False
+        if cast != string.expr:
+            # reinterpret_cast is necessary for GLubyte * <=> char *
+            instance = 'reinterpret_cast<%s>(%s)' % (cast, instance)
         if string.length is not None:
-            print '    trace::localWriter.writeString((const char *)%s, %s);' % (instance, string.length)
+            length = ', %s' % string.length
         else:
-            print '    trace::localWriter.writeString((const char *)%s);' % instance
+            length = ''
+        print '    trace::localWriter.write%s(%s%s);' % (string.kind, instance, length)
 
     def visitConst(self, const, instance):
         self.visit(const.type, instance)
@@ -321,13 +331,13 @@ class Tracer:
         print
 
         # Generate the serializer functions
-        types = api.all_types()
+        types = api.getAllTypes()
         visitor = ComplexValueSerializer(self.serializerFactory())
         map(visitor.visit, types)
         print
 
         # Interfaces wrapers
-        interfaces = [type for type in types if isinstance(type, stdapi.Interface)]
+        interfaces = api.getAllInterfaces()
         map(self.declareWrapperInterface, interfaces)
         map(self.implementWrapperInterface, interfaces)
         print
@@ -484,10 +494,17 @@ class Tracer:
         print '    trace::localWriter.beginArg(0);'
         print '    trace::localWriter.writeOpaque((const void *)m_pInstance);'
         print '    trace::localWriter.endArg();'
+
+        from specs.winapi import REFIID
+        from specs.stdapi import Pointer, Opaque
+
+        riid = None
         for arg in method.args:
             if not arg.output:
                 self.unwrapArg(method, arg)
                 self.serializeArg(method, arg)
+                if arg.type is REFIID:
+                    riid = arg
         print '    trace::localWriter.endEnter();'
         
         self.invokeMethod(interface, base, method)
@@ -497,38 +514,43 @@ class Tracer:
             if arg.output:
                 self.serializeArg(method, arg)
                 self.wrapArg(method, arg)
+                if riid is not None and isinstance(arg.type, Pointer):
+                    assert isinstance(arg.type.type, Opaque)
+                    self.wrapIid(interface, method, riid, arg)
+
         if method.type is not stdapi.Void:
             print '    trace::localWriter.beginReturn();'
             self.serializeValue(method.type, "__result")
             print '    trace::localWriter.endReturn();'
             self.wrapValue(method.type, '__result')
         print '    trace::localWriter.endLeave();'
-        if method.name == 'QueryInterface':
-            print '    if (ppvObj && *ppvObj) {'
-            print '        if (*ppvObj == m_pInstance) {'
-            print '            *ppvObj = this;'
+        if method.name == 'Release':
+            assert method.type is not stdapi.Void
+            print '    if (!__result)'
+            print '        delete this;'
+
+    def wrapIid(self, interface, method, riid, out):
+            print '    if (%s && *%s) {' % (out.name, out.name)
+            print '        if (*%s == m_pInstance) {' % (out.name,)
+            print '            *%s = this;' % (out.name,)
             print '        }'
             for iface in self.api.interfaces:
-                print r'        else if (riid == IID_%s) {' % iface.name
-                print r'            *ppvObj = new Wrap%s((%s *) *ppvObj);' % (iface.name, iface.name)
+                print r'        else if (%s == IID_%s) {' % (riid.name, iface.name)
+                print r'            *%s = new Wrap%s((%s *) *%s);' % (out.name, iface.name, iface.name, out.name)
                 print r'        }'
             print r'        else {'
             print r'            os::log("apitrace: warning: unknown REFIID {0x%08lX,0x%04X,0x%04X,{0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,0x%02X}}\n",'
-            print r'                    riid.Data1, riid.Data2, riid.Data3,'
-            print r'                    riid.Data4[0],'
-            print r'                    riid.Data4[1],'
-            print r'                    riid.Data4[2],'
-            print r'                    riid.Data4[3],'
-            print r'                    riid.Data4[4],'
-            print r'                    riid.Data4[5],'
-            print r'                    riid.Data4[6],'
-            print r'                    riid.Data4[7]);'
+            print r'                    %s.Data1, %s.Data2, %s.Data3,' % (riid.name, riid.name, riid.name)
+            print r'                    %s.Data4[0],' % (riid.name,)
+            print r'                    %s.Data4[1],' % (riid.name,)
+            print r'                    %s.Data4[2],' % (riid.name,)
+            print r'                    %s.Data4[3],' % (riid.name,)
+            print r'                    %s.Data4[4],' % (riid.name,)
+            print r'                    %s.Data4[5],' % (riid.name,)
+            print r'                    %s.Data4[6],' % (riid.name,)
+            print r'                    %s.Data4[7]);' % (riid.name,)
             print r'        }'
             print '    }'
-        if method.name == 'Release':
-            assert method.type is not stdapi.Void
-            print '    if (!__result)'
-            print '        delete this;'
 
     def invokeMethod(self, interface, base, method):
         if method.type is stdapi.Void: