]> git.cworth.org Git - apitrace/commitdiff
Merge branch 'd3dretrace'
authorJosé Fonseca <jose.r.fonseca@gmail.com>
Fri, 13 Apr 2012 16:36:19 +0000 (17:36 +0100)
committerJosé Fonseca <jose.r.fonseca@gmail.com>
Fri, 13 Apr 2012 16:36:19 +0000 (17:36 +0100)
18 files changed:
CMakeLists.txt
cmake/FindDirectX.cmake
common/formatter.hpp
common/trace_model.hpp
d3dretrace.hpp [new file with mode: 0644]
d3dretrace.py [new file with mode: 0644]
d3dretrace_main.cpp [new file with mode: 0644]
glretrace.hpp
glretrace.py
glretrace_main.cpp
retrace.cpp
retrace.hpp
retrace.py
specs/d3d9.py
specs/stdapi.py
specs/tags.vim [new file with mode: 0644]
specs/winapi.py
trace.py

index 28c86d372dfaf108f64110251bc5fc6808777035..265b2141159e0e4ed66c35f98242f29adc5c0561 100755 (executable)
@@ -671,6 +671,28 @@ if (ENABLE_EGL AND X11_FOUND AND NOT WIN32 AND NOT APPLE)
     install (TARGETS eglretrace RUNTIME DESTINATION bin) 
 endif ()
 
+if (WIN32 AND DirectX_D3DX9_FOUND)
+    add_custom_command (
+        OUTPUT d3dretrace_d3d9.cpp
+        COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/d3dretrace.py > ${CMAKE_CURRENT_BINARY_DIR}/d3dretrace_d3d9.cpp
+        DEPENDS d3dretrace.py retrace.py specs/d3d9.py specs/d3d9types.py specs/d3d9caps.py specs/winapi.py specs/stdapi.py
+    )
+
+    include_directories (SYSTEM ${DirectX_D3DX9_INCLUDE_DIR})
+    add_executable (d3dretrace
+        retrace.cpp
+        retrace_stdc.cpp
+        d3dretrace_main.cpp
+        d3dretrace_d3d9.cpp
+    )
+    target_link_libraries (d3dretrace
+        common
+        ${ZLIB_LIBRARIES}
+        ${SNAPPY_LIBRARIES}
+        ${DirectX_D3D9_LIBRARY}
+    )
+endif ()
+
 ##############################################################################
 # CLI
 
index 2c54023ebc43b19af4458740a874d8530f130f38..a17487097b806c75d2161ff58fd13865b436b8fa 100644 (file)
@@ -26,6 +26,13 @@ if (${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
                DOC "DirectX SDK root directory")
 
 
+       if (CMAKE_CL_64)
+               set (DirectX_ARCHITECTURE x64)
+       else ()
+               set (DirectX_ARCHITECTURE x86)
+       endif ()
+
+
        find_path (DirectX_D3D_INCLUDE_DIR d3d.h
                PATHS
                        "${DirectX_ROOT_DIR}/Include"
@@ -38,12 +45,12 @@ if (${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
 
        find_library (DirectX_DDRAW_LIBRARY ddraw
                PATHS
-                       "${DirectX_ROOT_DIR}/Lib/x86"
+                       "${DirectX_ROOT_DIR}/Lib/${DirectX_ARCHITECTURE}"
                DOC "The directory where ddraw resides")
 
        find_library (DirectX_D3DX_LIBRARY d3dx
                PATHS
-                       "${DirectX_ROOT_DIR}/Lib/x86"
+                       "${DirectX_ROOT_DIR}/Lib/${DirectX_ARCHITECTURE}"
                DOC "The directory where d3dx resides")
 
        if (DirectX_D3D_INCLUDE_DIR AND DirectX_DDRAW_LIBRARY)
@@ -66,12 +73,12 @@ if (${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
 
        find_library (DirectX_D3D8_LIBRARY d3d8
                PATHS
-                       "${DirectX_ROOT_DIR}/Lib/x86"
+                       "${DirectX_ROOT_DIR}/Lib/${DirectX_ARCHITECTURE}"
                DOC "The directory where d3d8 resides")
 
        find_library (DirectX_D3DX8_LIBRARY d3dx8
                PATHS
-                       "${DirectX_ROOT_DIR}/Lib/x86"
+                       "${DirectX_ROOT_DIR}/Lib/${DirectX_ARCHITECTURE}"
                DOC "The directory where d3dx8 resides")
 
        if (DirectX_D3D8_INCLUDE_DIR AND DirectX_D3D8_LIBRARY)
@@ -94,12 +101,12 @@ if (${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
 
        find_library (DirectX_D3D9_LIBRARY d3d9
                PATHS
-                       "${DirectX_ROOT_DIR}/Lib/x86"
+                       "${DirectX_ROOT_DIR}/Lib/${DirectX_ARCHITECTURE}"
                DOC "The directory where d3d9 resides")
 
        find_library (DirectX_D3DX9_LIBRARY d3dx9
                PATHS
-                       "${DirectX_ROOT_DIR}/Lib/x86"
+                       "${DirectX_ROOT_DIR}/Lib/${DirectX_ARCHITECTURE}"
                DOC "The directory where d3dx9 resides")
 
        if (DirectX_D3D9_INCLUDE_DIR AND DirectX_D3D9_LIBRARY)
@@ -122,12 +129,12 @@ if (${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
 
        find_library (DirectX_D3D10_LIBRARY d3d10
                PATHS
-                       "${DirectX_ROOT_DIR}/Lib/x86"
+                       "${DirectX_ROOT_DIR}/Lib/${DirectX_ARCHITECTURE}"
                DOC "The directory where d3d10 resides")
 
        find_library (DirectX_D3DX10_LIBRARY d3dx10
                PATHS
-                       "${DirectX_ROOT_DIR}/Lib/x86"
+                       "${DirectX_ROOT_DIR}/Lib/${DirectX_ARCHITECTURE}"
                DOC "The directory where d3dx10 resides")
 
        if (DirectX_D3D10_INCLUDE_DIR AND DirectX_D3D10_LIBRARY)
index 10661e3b14ebb1b1df1b75f5b92f6e8e082fdbab..43b816eb1ef1fb453817bd850ac5f6aad6e56191 100644 (file)
@@ -195,6 +195,18 @@ public:
 inline Formatter *defaultFormatter(bool color = true) {
     if (color) {
 #ifdef _WIN32
+        // http://wiki.winehq.org/DeveloperFaq#detect-wine
+        static HMODULE hNtDll = NULL;
+        static bool bWine = false;
+        if (!hNtDll) {
+            hNtDll = LoadLibraryA("ntdll");
+            if (hNtDll) {
+                bWine = GetProcAddress(hNtDll, "wine_get_version") != NULL;
+            }
+        }
+        if (bWine) {
+            return new AnsiFormatter;
+        }
         return new WindowsFormatter;
 #else
         return new AnsiFormatter;
index a2fd97f4a68b2c9a425ec0196d51f292641ef581..3ddd9a0db13dc81bf5b7f959ecc64ededef67a69 100644 (file)
@@ -277,6 +277,11 @@ public:
     void visit(Visitor &visitor);
 
     std::vector<Value *> values;
+
+    inline size_t
+    size(void) const {
+        return values.size();
+    }
 };
 
 
diff --git a/d3dretrace.hpp b/d3dretrace.hpp
new file mode 100644 (file)
index 0000000..cac94cc
--- /dev/null
@@ -0,0 +1,41 @@
+/**************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+#ifndef _D3DRETRACE_HPP_
+#define _D3DRETRACE_HPP_
+
+#include "retrace.hpp"
+
+
+namespace d3dretrace {
+
+
+extern const retrace::Entry d3d9_callbacks[];
+
+
+} /* namespace d3dretrace */
+
+
+#endif /* _D3DRETRACE_HPP_ */
diff --git a/d3dretrace.py b/d3dretrace.py
new file mode 100644 (file)
index 0000000..a2ea75e
--- /dev/null
@@ -0,0 +1,145 @@
+##########################################################################
+#
+# Copyright 2011 Jose Fonseca
+# All Rights Reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+##########################################################################/
+
+
+"""GL retracer generator."""
+
+
+import specs.stdapi as stdapi
+from specs.d3d9 import d3d9
+from retrace import Retracer
+
+
+class D3DRetracer(Retracer):
+
+    table_name = 'd3dretrace::d3d9_callbacks'
+
+    def invokeInterfaceMethod(self, interface, method):
+        if interface.name == 'IDirect3D9' and method.name == 'CreateDevice':
+            print 'HWND hWnd = createWindow(pPresentationParameters->BackBufferWidth, pPresentationParameters->BackBufferHeight);'
+            print 'pPresentationParameters->hDeviceWindow = hWnd;'
+            print 'hFocusWindow = hWnd;'
+
+        Retracer.invokeInterfaceMethod(self, interface, method)
+
+        if str(method.type) == 'HRESULT':
+            print r'    if (__result != S_OK) {'
+            print r'        retrace::warning(call) << "failed\n";'
+            print r'    }'
+
+        if interface.name == 'IDirect3DVertexBuffer9' and method.name == 'Lock':
+            print '        if (!SizeToLock) {'
+            print '            D3DVERTEXBUFFER_DESC Desc;'
+            print '            _this->GetDesc(&Desc);'
+            print '            SizeToLock = Desc.Size;'
+            print '        }'
+
+
+if __name__ == '__main__':
+    print r'''
+#include <string.h>
+
+#include <iostream>
+
+#include "d3d9imports.hpp"
+#include "d3dretrace.hpp"
+
+
+// XXX: Don't duplicate this code.
+
+static LRESULT CALLBACK
+WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+    MINMAXINFO *pMMI;
+    switch (uMsg) {
+    case WM_GETMINMAXINFO:
+        // Allow to create a window bigger than the desktop
+        pMMI = (MINMAXINFO *)lParam;
+        pMMI->ptMaxSize.x = 60000;
+        pMMI->ptMaxSize.y = 60000;
+        pMMI->ptMaxTrackSize.x = 60000;
+        pMMI->ptMaxTrackSize.y = 60000;
+        break;
+    default:
+        break;
+    }
+
+    return DefWindowProc(hWnd, uMsg, wParam, lParam);
+}
+
+
+static HWND
+createWindow(int width, int height) {
+    static bool first = TRUE;
+    RECT rect;
+
+    if (first) {
+        WNDCLASS wc;
+        memset(&wc, 0, sizeof wc);
+        wc.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1);
+        wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+        wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
+        wc.lpfnWndProc = WndProc;
+        wc.lpszClassName = "d3dretrace";
+        wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
+        RegisterClass(&wc);
+        first = FALSE;
+    }
+
+    DWORD dwExStyle;
+    DWORD dwStyle;
+    HWND hWnd;
+
+    dwExStyle = 0;
+    dwStyle = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW;
+
+    int x = 0, y = 0;
+
+    rect.left = x;
+    rect.top = y;
+    rect.right = rect.left + width;
+    rect.bottom = rect.top + height;
+
+    AdjustWindowRectEx(&rect, dwStyle, FALSE, dwExStyle);
+
+    hWnd = CreateWindowEx(dwExStyle,
+                          "d3dretrace", /* wc.lpszClassName */
+                          NULL,
+                          dwStyle,
+                          0, /* x */
+                          0, /* y */
+                          rect.right - rect.left, /* width */
+                          rect.bottom - rect.top, /* height */
+                          NULL,
+                          NULL,
+                          NULL,
+                          NULL);
+    ShowWindow(hWnd, SW_SHOW);
+    return hWnd;
+}
+
+'''
+    retracer = D3DRetracer()
+    retracer.retraceApi(d3d9)
diff --git a/d3dretrace_main.cpp b/d3dretrace_main.cpp
new file mode 100644 (file)
index 0000000..133f3a7
--- /dev/null
@@ -0,0 +1,103 @@
+/**************************************************************************
+ *
+ * Copyright 2011 Jose Fonseca
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include <string.h>
+
+#include "os_string.hpp"
+#include "retrace.hpp"
+#include "d3dretrace.hpp"
+
+
+namespace d3dretrace {
+
+static void display(void) {
+    retrace::Retracer retracer;
+
+    retracer.addCallbacks(d3d9_callbacks);
+
+    trace::Call *call;
+
+    while ((call = retrace::parser.parse_call())) {
+        retracer.retrace(*call);
+
+        delete call;
+    }
+
+    exit(0);
+}
+
+
+static void usage(void) {
+    std::cout << 
+        "Usage: d3dretrace [OPTION] TRACE\n"
+        "Replay TRACE.\n"
+        "\n"
+        "  -v           increase output verbosity\n"
+    ;
+}
+
+
+extern "C"
+int main(int argc, char **argv)
+{
+
+    int i;
+    for (i = 1; i < argc; ++i) {
+        const char *arg = argv[i];
+
+        if (arg[0] != '-') {
+            break;
+        }
+
+        if (!strcmp(arg, "--")) {
+            break;
+        } else if (!strcmp(arg, "--help")) {
+            usage();
+            return 0;
+        } else if (!strcmp(arg, "-v")) {
+            ++retrace::verbosity;
+        } else {
+            std::cerr << "error: unknown option " << arg << "\n";
+            usage();
+            return 1;
+        }
+    }
+
+    for ( ; i < argc; ++i) {
+        if (!retrace::parser.open(argv[i])) {
+            std::cerr << "error: failed to open " << argv[i] << "\n";
+            return 1;
+        }
+
+        display();
+
+        retrace::parser.close();
+    }
+
+    return 0;
+}
+
+} /* namespace glretrace */
index 83535223fcf3c7f1009d9731df459ff8a9090203..8ba2a80edd477b8e2b418f0c21bfb76b57aace32 100644 (file)
@@ -26,7 +26,6 @@
 #ifndef _GLRETRACE_HPP_
 #define _GLRETRACE_HPP_
 
-#include "trace_parser.hpp"
 #include "glws.hpp"
 #include "retrace.hpp"
 
@@ -36,7 +35,6 @@ namespace glretrace {
 
 extern bool double_buffer;
 extern bool insideGlBeginEnd;
-extern trace::Parser parser;
 extern glws::Profile defaultProfile;
 extern glws::Visual *visual[glws::PROFILE_MAX];
 extern glws::Drawable *drawable;
index cd7fe803267766954d6fd4e8450d9761c834ceb4..d91c8a25fe2ec2e68d39c89c15a2ada41e1b5f90 100644 (file)
@@ -178,7 +178,7 @@ class GlRetracer(Retracer):
         is_misc_draw = function.name in self.misc_draw_function_names
 
         if is_array_pointer or is_draw_array or is_draw_elements:
-            print '    if (glretrace::parser.version < 1) {'
+            print '    if (retrace::parser.version < 1) {'
 
             if is_array_pointer or is_draw_array:
                 print '        GLint __array_buffer = 0;'
@@ -391,7 +391,8 @@ class GlRetracer(Retracer):
         # Handle pointer with offsets into the current pack pixel buffer
         # object.
         if function.name in self.pack_function_names and arg.output:
-            self.extractOpaqueArg(function, arg, arg_type, lvalue, rvalue)
+            assert isinstance(arg_type, (stdapi.Pointer, stdapi.Array, stdapi.Blob, stdapi.Opaque))
+            print '    %s = static_cast<%s>((%s).toPointer());' % (lvalue, arg_type, rvalue)
             return
 
         if arg.type is glapi.GLlocation \
index 11f34ce8200ca16215780c0fbfce976f918ca414..313a563459216f4508edfa2ae836af2a0c6c3a84 100644 (file)
@@ -41,7 +41,6 @@ namespace glretrace {
 
 bool double_buffer = true;
 bool insideGlBeginEnd = false;
-trace::Parser parser;
 glws::Profile defaultProfile = glws::PROFILE_COMPAT;
 glws::Visual *visual[glws::PROFILE_MAX];
 glws::Drawable *drawable = NULL;
@@ -214,7 +213,7 @@ static void display(void) {
     startTime = os::getTime();
     trace::Call *call;
 
-    while ((call = parser.parse_call())) {
+    while ((call = retrace::parser.parse_call())) {
         bool swapRenderTarget = call->flags & trace::CALL_FLAG_SWAP_RENDERTARGET;
         bool doSnapshot =
             snapshot_frequency.contains(*call) ||
@@ -369,14 +368,14 @@ int main(int argc, char **argv)
     visual[glws::PROFILE_ES2] = glws::createVisual(double_buffer, glws::PROFILE_ES2);
 
     for ( ; i < argc; ++i) {
-        if (!parser.open(argv[i])) {
+        if (!retrace::parser.open(argv[i])) {
             std::cerr << "error: failed to open " << argv[i] << "\n";
             return 1;
         }
 
         display();
 
-        parser.close();
+        retrace::parser.close();
     }
 
     for (int n = 0; n < glws::PROFILE_MAX; n++) {
index d2e6d379b06d283ca729e1712e80a22044103189..1630995cdb440551232c6bdfcd214ea1f61f2abe 100644 (file)
@@ -35,6 +35,9 @@
 namespace retrace {
 
 
+trace::Parser parser;
+
+
 int verbosity = 0;
 bool profiling = false;
 
index 8ce15ad6720c7e0696440fd5688da523d90452bc..c1e556a97fbb03d726be09de3cb92540de88e5fc 100644 (file)
 #include <ostream>
 
 #include "trace_model.hpp"
+#include "trace_parser.hpp"
 
 
 namespace retrace {
 
 
+extern trace::Parser parser;
+
+
 /**
  * Handle map.
  *
@@ -119,6 +123,24 @@ public:
         return static_cast<T *>(alloc(sizeof(T) * n));
     }
 
+    /**
+     * Allocate an array with the same dimensions as the specified value.
+     */
+    template< class T >
+    inline T *
+    alloc(const trace::Value *value) {
+        const trace::Array *array = dynamic_cast<const trace::Array *>(value);
+        if (array) {
+            return alloc<T>(array->size());
+        }
+        const trace::Null *null = dynamic_cast<const trace::Null *>(value);
+        if (null) {
+            return NULL;
+        }
+        assert(0);
+        return NULL;
+    }
+
     /**
      * Prevent this pointer from being automatically freed.
      */
index e4d462ae99ed5bdabc8ecc8a473a21dfe53db05e..a450f8221ea47499622b118896fa6ed0f6783720 100644 (file)
@@ -33,13 +33,26 @@ import specs.stdapi as stdapi
 import specs.glapi as glapi
 
 
-class ConstRemover(stdapi.Rebuilder):
-    '''Type visitor which strips out const qualifiers from types.'''
+class MutableRebuilder(stdapi.Rebuilder):
+    '''Type visitor which derives a mutable type.'''
 
     def visitConst(self, const):
+        # Strip out const qualifier
         return const.type
 
+    def visitAlias(self, alias):
+        # Tear the alias on type changes
+        type = self.visit(alias.type)
+        if type is alias.type:
+            return alias
+        return type
+
+    def visitReference(self, reference):
+        # Strip out references
+        return reference.type
+
     def visitOpaque(self, opaque):
+        # Don't recursule
         return opaque
 
 
@@ -51,6 +64,57 @@ def lookupHandle(handle, value):
         return "__%s_map[%s][%s]" % (handle.name, key_name, value)
 
 
+class ValueAllocator(stdapi.Visitor):
+
+    def visitLiteral(self, literal, lvalue, rvalue):
+        pass
+
+    def visitConst(self, const, lvalue, rvalue):
+        self.visit(const.type, lvalue, rvalue)
+
+    def visitAlias(self, alias, lvalue, rvalue):
+        self.visit(alias.type, lvalue, rvalue)
+
+    def visitEnum(self, enum, lvalue, rvalue):
+        pass
+
+    def visitBitmask(self, bitmask, lvalue, rvalue):
+        pass
+
+    def visitArray(self, array, lvalue, rvalue):
+        print '    %s = _allocator.alloc<%s>(&%s);' % (lvalue, array.type, rvalue)
+
+    def visitPointer(self, pointer, lvalue, rvalue):
+        print '    %s = _allocator.alloc<%s>(&%s);' % (lvalue, pointer.type, rvalue)
+
+    def visitIntPointer(self, pointer, lvalue, rvalue):
+        pass
+
+    def visitObjPointer(self, pointer, lvalue, rvalue):
+        pass
+
+    def visitLinearPointer(self, pointer, lvalue, rvalue):
+        pass
+
+    def visitReference(self, reference, lvalue, rvalue):
+        self.visit(reference.type, lvalue, rvalue);
+
+    def visitHandle(self, handle, lvalue, rvalue):
+        pass
+
+    def visitBlob(self, blob, lvalue, rvalue):
+        pass
+
+    def visitString(self, string, lvalue, rvalue):
+        pass
+
+    def visitStruct(self, struct, lvalue, rvalue):
+        pass
+
+    def visitPolymorphic(self, polymorphic, lvalue, rvalue):
+        self.visit(polymorphic.defaultType, lvalue, rvalue)
+
+
 class ValueDeserializer(stdapi.Visitor):
 
     def visitLiteral(self, literal, lvalue, rvalue):
@@ -69,37 +133,49 @@ class ValueDeserializer(stdapi.Visitor):
         self.visit(bitmask.type, lvalue, rvalue)
 
     def visitArray(self, array, lvalue, rvalue):
-        print '    const trace::Array *__a%s = dynamic_cast<const trace::Array *>(&%s);' % (array.tag, rvalue)
-        print '    if (__a%s) {' % (array.tag)
-        length = '__a%s->values.size()' % array.tag
-        print '        %s = _allocator.alloc<%s>(%s);' % (lvalue, array.type, length)
+
+        tmp = '__a_' + array.tag + '_' + str(self.seq)
+        self.seq += 1
+
+        print '    if (%s) {' % (lvalue,)
+        print '        const trace::Array *%s = dynamic_cast<const trace::Array *>(&%s);' % (tmp, rvalue)
+        length = '%s->values.size()' % (tmp,)
         index = '__j' + array.tag
         print '        for (size_t {i} = 0; {i} < {length}; ++{i}) {{'.format(i = index, length = length)
         try:
-            self.visit(array.type, '%s[%s]' % (lvalue, index), '*__a%s->values[%s]' % (array.tag, index))
+            self.visit(array.type, '%s[%s]' % (lvalue, index), '*%s->values[%s]' % (tmp, index))
         finally:
             print '        }'
-            print '    } else {'
-            print '        %s = NULL;' % lvalue
             print '    }'
     
     def visitPointer(self, pointer, lvalue, rvalue):
-        print '    const trace::Array *__a%s = dynamic_cast<const trace::Array *>(&%s);' % (pointer.tag, rvalue)
-        print '    if (__a%s) {' % (pointer.tag)
-        print '        %s = _allocator.alloc<%s>();' % (lvalue, pointer.type)
+        tmp = '__a_' + pointer.tag + '_' + str(self.seq)
+        self.seq += 1
+
+        print '    if (%s) {' % (lvalue,)
+        print '        const trace::Array *%s = dynamic_cast<const trace::Array *>(&%s);' % (tmp, rvalue)
         try:
-            self.visit(pointer.type, '%s[0]' % (lvalue,), '*__a%s->values[0]' % (pointer.tag,))
+            self.visit(pointer.type, '%s[0]' % (lvalue,), '*%s->values[0]' % (tmp,))
         finally:
-            print '    } else {'
-            print '        %s = NULL;' % lvalue
             print '    }'
 
     def visitIntPointer(self, pointer, lvalue, rvalue):
         print '    %s = static_cast<%s>((%s).toPointer());' % (lvalue, pointer, rvalue)
 
+    def visitObjPointer(self, pointer, lvalue, rvalue):
+        old_lvalue = '(%s).toUIntPtr()' % (rvalue,)
+        new_lvalue = '_obj_map[%s]' % (old_lvalue,)
+        print '    if (retrace::verbosity >= 2) {'
+        print '        std::cout << std::hex << "obj 0x" << size_t(%s) << " <- 0x" << size_t(%s) << std::dec <<"\\n";' % (old_lvalue, new_lvalue)
+        print '    }'
+        print '    %s = static_cast<%s>(%s);' % (lvalue, pointer, new_lvalue)
+
     def visitLinearPointer(self, pointer, lvalue, rvalue):
         print '    %s = static_cast<%s>(retrace::toPointer(%s));' % (lvalue, pointer, rvalue)
 
+    def visitReference(self, reference, lvalue, rvalue):
+        self.visit(reference.type, lvalue, rvalue);
+
     def visitHandle(self, handle, lvalue, rvalue):
         #OpaqueValueDeserializer().visit(handle.type, lvalue, rvalue);
         self.visit(handle.type, lvalue, rvalue);
@@ -115,6 +191,21 @@ class ValueDeserializer(stdapi.Visitor):
     def visitString(self, string, lvalue, rvalue):
         print '    %s = (%s)((%s).toString());' % (lvalue, string.expr, rvalue)
 
+    seq = 0
+
+    def visitStruct(self, struct, lvalue, rvalue):
+        tmp = '__s_' + struct.tag + '_' + str(self.seq)
+        self.seq += 1
+
+        print '    const trace::Struct *%s = dynamic_cast<const trace::Struct *>(&%s);' % (tmp, rvalue)
+        print '    assert(%s);' % (tmp)
+        for i in range(len(struct.members)):
+            member_type, member_name = struct.members[i]
+            self.visit(member_type, '%s.%s' % (lvalue, member_name), '*%s->members[%s]' % (tmp, i))
+
+    def visitPolymorphic(self, polymorphic, lvalue, rvalue):
+        self.visit(polymorphic.defaultType, lvalue, rvalue)
+
 
 class OpaqueValueDeserializer(ValueDeserializer):
     '''Value extractor that also understands opaque values.
@@ -165,11 +256,17 @@ class SwizzledValueRegistrator(stdapi.Visitor):
     def visitIntPointer(self, pointer, lvalue, rvalue):
         pass
     
+    def visitObjPointer(self, pointer, lvalue, rvalue):
+        print r'    _obj_map[(%s).toUIntPtr()] = %s;' % (rvalue, lvalue)
+    
     def visitLinearPointer(self, pointer, lvalue, rvalue):
         assert pointer.size is not None
         if pointer.size is not None:
             print r'    retrace::addRegion((%s).toUIntPtr(), %s, %s);' % (rvalue, lvalue, pointer.size)
 
+    def visitReference(self, reference, lvalue, rvalue):
+        pass
+    
     def visitHandle(self, handle, lvalue, rvalue):
         print '    %s __orig_result;' % handle.type
         OpaqueValueDeserializer().visit(handle.type, '__orig_result', rvalue);
@@ -198,6 +295,22 @@ class SwizzledValueRegistrator(stdapi.Visitor):
     def visitString(self, string, lvalue, rvalue):
         pass
 
+    seq = 0
+
+    def visitStruct(self, struct, lvalue, rvalue):
+        tmp = '__s_' + struct.tag + '_' + str(self.seq)
+        self.seq += 1
+
+        print '    const trace::Struct *%s = dynamic_cast<const trace::Struct *>(&%s);' % (tmp, rvalue)
+        print '    assert(%s);' % (tmp,)
+        print '    (void)%s;' % (tmp,)
+        for i in range(len(struct.members)):
+            member_type, member_name = struct.members[i]
+            self.visit(member_type, '%s.%s' % (lvalue, member_name), '*%s->members[%s]' % (tmp, i))
+    
+    def visitPolymorphic(self, polymorphic, lvalue, rvalue):
+        self.visit(polymorphic.defaultType, lvalue, rvalue)
+
 
 class Retracer:
 
@@ -207,31 +320,67 @@ class Retracer:
         print '}'
         print
 
+    def retraceInterfaceMethod(self, interface, method):
+        print 'static void retrace_%s__%s(trace::Call &call) {' % (interface.name, method.name)
+        self.retraceInterfaceMethodBody(interface, method)
+        print '}'
+        print
+
     def retraceFunctionBody(self, function):
         assert function.sideeffects
 
+        self.deserializeArgs(function)
+        
+        self.invokeFunction(function)
+
+        self.swizzleValues(function)
+
+    def retraceInterfaceMethodBody(self, interface, method):
+        assert method.sideeffects
+
+        self.deserializeThisPointer(interface)
+
+        self.deserializeArgs(method)
+        
+        self.invokeInterfaceMethod(interface, method)
+
+        self.swizzleValues(method)
+
+    def deserializeThisPointer(self, interface):
+        print r'    %s *_this;' % (interface.name,)
+        print r'    _this = static_cast<%s *>(_obj_map[call.arg(0).toUIntPtr()]);' % (interface.name,)
+        print r'    if (!_this) {'
+        print r'        retrace::warning(call) << "NULL this pointer\n";'
+        print r'        return;'
+        print r'    }'
+
+    def deserializeArgs(self, function):
         print '    retrace::ScopedAllocator _allocator;'
         print '    (void)_allocator;'
         success = True
         for arg in function.args:
-            arg_type = ConstRemover().visit(arg.type)
-            #print '    // %s ->  %s' % (arg.type, arg_type)
+            arg_type = MutableRebuilder().visit(arg.type)
             print '    %s %s;' % (arg_type, arg.name)
             rvalue = 'call.arg(%u)' % (arg.index,)
             lvalue = arg.name
             try:
                 self.extractArg(function, arg, arg_type, lvalue, rvalue)
             except NotImplementedError:
-                success = False
-                print '    %s = 0; // FIXME' % arg.name
+                success =  False
+                print '    memset(&%s, 0, sizeof %s); // FIXME' % (arg.name, arg.name)
+            print
+
         if not success:
             print '    if (1) {'
             self.failFunction(function)
+            if function.name[-1].islower():
+                sys.stderr.write('warning: unsupported %s call\n' % function.name)
             print '    }'
-        self.invokeFunction(function)
+
+    def swizzleValues(self, function):
         for arg in function.args:
             if arg.output:
-                arg_type = ConstRemover().visit(arg.type)
+                arg_type = MutableRebuilder().visit(arg.type)
                 rvalue = 'call.arg(%u)' % (arg.index,)
                 lvalue = arg.name
                 try:
@@ -244,10 +393,8 @@ class Retracer:
             try:
                 self.regiterSwizzledValue(function.type, lvalue, rvalue)
             except NotImplementedError:
+                raise
                 print '    // XXX: result'
-        if not success:
-            if function.name[-1].islower():
-                sys.stderr.write('warning: unsupported %s call\n' % function.name)
 
     def failFunction(self, function):
         print '    if (retrace::verbosity >= 0) {'
@@ -256,9 +403,15 @@ class Retracer:
         print '    return;'
 
     def extractArg(self, function, arg, arg_type, lvalue, rvalue):
-        ValueDeserializer().visit(arg_type, lvalue, rvalue)
+        ValueAllocator().visit(arg_type, lvalue, rvalue)
+        if arg.input:
+            ValueDeserializer().visit(arg_type, lvalue, rvalue)
     
     def extractOpaqueArg(self, function, arg, arg_type, lvalue, rvalue):
+        try:
+            ValueAllocator().visit(arg_type, lvalue, rvalue)
+        except NotImplementedError:
+            pass
         OpaqueValueDeserializer().visit(arg_type, lvalue, rvalue)
 
     def regiterSwizzledValue(self, type, lvalue, rvalue):
@@ -274,29 +427,20 @@ class Retracer:
         else:
             print '    %s(%s);' % (function.name, arg_names)
 
+    def invokeInterfaceMethod(self, interface, method):
+        arg_names = ", ".join(method.argNames())
+        if method.type is not stdapi.Void:
+            print '    %s __result;' % (method.type)
+            print '    __result = _this->%s(%s);' % (method.name, arg_names)
+            print '    (void)__result;'
+        else:
+            print '    _this->%s(%s);' % (method.name, arg_names)
+
     def filterFunction(self, function):
         return True
 
     table_name = 'retrace::callbacks'
 
-    def retraceFunctions(self, functions):
-        functions = filter(self.filterFunction, functions)
-
-        for function in functions:
-            if function.sideeffects:
-                self.retraceFunction(function)
-
-        print 'const retrace::Entry %s[] = {' % self.table_name
-        for function in functions:
-            if function.sideeffects:
-                print '    {"%s", &retrace_%s},' % (function.name, function.name)
-            else:
-                print '    {"%s", &retrace::ignore},' % (function.name,)
-        print '    {NULL, NULL}'
-        print '};'
-        print
-
-
     def retraceApi(self, api):
 
         print '#include "os_time.hpp"'
@@ -317,5 +461,32 @@ class Retracer:
                 handle_names.add(handle.name)
         print
 
-        self.retraceFunctions(api.functions)
+        print 'static std::map<unsigned long long, void *> _obj_map;'
+        print
+
+        functions = filter(self.filterFunction, api.functions)
+        for function in functions:
+            if function.sideeffects:
+                self.retraceFunction(function)
+        interfaces = api.getAllInterfaces()
+        for interface in interfaces:
+            for method in interface.iterMethods():
+                if method.sideeffects:
+                    self.retraceInterfaceMethod(interface, method)
+
+        print 'const retrace::Entry %s[] = {' % self.table_name
+        for function in functions:
+            if function.sideeffects:
+                print '    {"%s", &retrace_%s},' % (function.name, function.name)
+            else:
+                print '    {"%s", &retrace::ignore},' % (function.name,)
+        for interface in interfaces:
+            for method in interface.iterMethods():                
+                if method.sideeffects:
+                    print '    {"%s::%s", &retrace_%s__%s},' % (interface.name, method.name, interface.name, method.name)
+                else:
+                    print '    {"%s::%s", &retrace::ignore},' % (interface.name, method.name)
+        print '    {NULL, NULL}'
+        print '};'
+        print
 
index 742c652e2ab6a3244f0fe447bf4e88b4b3d78549..9b2b179f57c2f63d5e576d69095fbca1fe13022f 100644 (file)
@@ -132,123 +132,123 @@ IDirect3D9Ex = Interface("IDirect3D9Ex", IDirect3D9)
 IDirect3DDevice9Ex = Interface("IDirect3DDevice9Ex", IDirect3DDevice9)
 IDirect3DSwapChain9Ex = Interface("IDirect3DSwapChain9Ex", IDirect3DSwapChain9)
 
-PDIRECT3D9 = Pointer(IDirect3D9)
-PDIRECT3DDEVICE9 = Pointer(IDirect3DDevice9)
-PDIRECT3DSTATEBLOCK9 = Pointer(IDirect3DStateBlock9)
-PDIRECT3DSWAPCHAIN9 = Pointer(IDirect3DSwapChain9)
-PDIRECT3DRESOURCE9 = Pointer(IDirect3DResource9)
-PDIRECT3DVERTEXDECLARATION9 = Pointer(IDirect3DVertexDeclaration9)
-PDIRECT3DVERTEXSHADER9 = Pointer(IDirect3DVertexShader9)
-PDIRECT3DPIXELSHADER9 = Pointer(IDirect3DPixelShader9)
-PDIRECT3DBASETEXTURE9 = Pointer(IDirect3DBaseTexture9)
-PDIRECT3DTEXTURE9 = Pointer(IDirect3DTexture9)
-PDIRECT3DVOLUMETEXTURE9 = Pointer(IDirect3DVolumeTexture9)
-PDIRECT3DCUBETEXTURE9 = Pointer(IDirect3DCubeTexture9)
-PDIRECT3DVERTEXBUFFER9 = Pointer(IDirect3DVertexBuffer9)
-PDIRECT3DINDEXBUFFER9 = Pointer(IDirect3DIndexBuffer9)
-PDIRECT3DSURFACE9 = Pointer(IDirect3DSurface9)
-PDIRECT3DVOLUME9 = Pointer(IDirect3DVolume9)
-PDIRECT3DQUERY9 = Pointer(IDirect3DQuery9)
-PDIRECT3D9EX = Pointer(IDirect3D9Ex)
-PDIRECT3DDEVICE9EX = Pointer(IDirect3DDevice9Ex)
-PDIRECT3DSWAPCHAIN9EX = Pointer(IDirect3DSwapChain9Ex)
+PDIRECT3D9 = ObjPointer(IDirect3D9)
+PDIRECT3DDEVICE9 = ObjPointer(IDirect3DDevice9)
+PDIRECT3DSTATEBLOCK9 = ObjPointer(IDirect3DStateBlock9)
+PDIRECT3DSWAPCHAIN9 = ObjPointer(IDirect3DSwapChain9)
+PDIRECT3DRESOURCE9 = ObjPointer(IDirect3DResource9)
+PDIRECT3DVERTEXDECLARATION9 = ObjPointer(IDirect3DVertexDeclaration9)
+PDIRECT3DVERTEXSHADER9 = ObjPointer(IDirect3DVertexShader9)
+PDIRECT3DPIXELSHADER9 = ObjPointer(IDirect3DPixelShader9)
+PDIRECT3DBASETEXTURE9 = ObjPointer(IDirect3DBaseTexture9)
+PDIRECT3DTEXTURE9 = ObjPointer(IDirect3DTexture9)
+PDIRECT3DVOLUMETEXTURE9 = ObjPointer(IDirect3DVolumeTexture9)
+PDIRECT3DCUBETEXTURE9 = ObjPointer(IDirect3DCubeTexture9)
+PDIRECT3DVERTEXBUFFER9 = ObjPointer(IDirect3DVertexBuffer9)
+PDIRECT3DINDEXBUFFER9 = ObjPointer(IDirect3DIndexBuffer9)
+PDIRECT3DSURFACE9 = ObjPointer(IDirect3DSurface9)
+PDIRECT3DVOLUME9 = ObjPointer(IDirect3DVolume9)
+PDIRECT3DQUERY9 = ObjPointer(IDirect3DQuery9)
+PDIRECT3D9EX = ObjPointer(IDirect3D9Ex)
+PDIRECT3DDEVICE9EX = ObjPointer(IDirect3DDevice9Ex)
+PDIRECT3DSWAPCHAIN9EX = ObjPointer(IDirect3DSwapChain9Ex)
 
 IDirect3D9.methods += [
-    Method(HRESULT, "RegisterSoftwareDevice", [(OpaquePointer(Void), "pInitializeFunction")]),
-    Method(UINT, "GetAdapterCount", []),
-    Method(HRESULT, "GetAdapterIdentifier", [(UINT, "Adapter"), (D3DENUM, "Flags"), Out(Pointer(D3DADAPTER_IDENTIFIER9), "pIdentifier")]),
-    Method(UINT, "GetAdapterModeCount", [(UINT, "Adapter"), (D3DFORMAT, "Format")]),
-    Method(HRESULT, "EnumAdapterModes", [(UINT, "Adapter"), (D3DFORMAT, "Format"), (UINT, "Mode"), Out(Pointer(D3DDISPLAYMODE), "pMode")]),
-    Method(HRESULT, "GetAdapterDisplayMode", [(UINT, "Adapter"), Out(Pointer(D3DDISPLAYMODE), "pMode")]),
-    Method(HRESULT, "CheckDeviceType", [(UINT, "Adapter"), (D3DDEVTYPE, "DevType"), (D3DFORMAT, "AdapterFormat"), (D3DFORMAT, "BackBufferFormat"), (BOOL, "bWindowed")]),
-    Method(HRESULT, "CheckDeviceFormat", [(UINT, "Adapter"), (D3DDEVTYPE, "DeviceType"), (D3DFORMAT, "AdapterFormat"), (D3DUSAGE, "Usage"), (D3DRESOURCETYPE, "RType"), (D3DFORMAT, "CheckFormat")]),
-    Method(HRESULT, "CheckDeviceMultiSampleType", [(UINT, "Adapter"), (D3DDEVTYPE, "DeviceType"), (D3DFORMAT, "SurfaceFormat"), (BOOL, "Windowed"), (D3DMULTISAMPLE_TYPE, "MultiSampleType"), Out(Pointer(DWORD), "pQualityLevels")]),
-    Method(HRESULT, "CheckDepthStencilMatch", [(UINT, "Adapter"), (D3DDEVTYPE, "DeviceType"), (D3DFORMAT, "AdapterFormat"), (D3DFORMAT, "RenderTargetFormat"), (D3DFORMAT, "DepthStencilFormat")]),
-    Method(HRESULT, "CheckDeviceFormatConversion", [(UINT, "Adapter"), (D3DDEVTYPE, "DeviceType"), (D3DFORMAT, "SourceFormat"), (D3DFORMAT, "TargetFormat")]),
-    Method(HRESULT, "GetDeviceCaps", [(UINT, "Adapter"), (D3DDEVTYPE, "DeviceType"), Out(Pointer(D3DCAPS9), "pCaps")]),
-    Method(HMONITOR, "GetAdapterMonitor", [(UINT, "Adapter")]),
-    Method(HRESULT, "CreateDevice", [(UINT, "Adapter"), (D3DDEVTYPE, "DeviceType"), (HWND, "hFocusWindow"), (D3DCREATE, "BehaviorFlags"), Out(Pointer(D3DPRESENT_PARAMETERS), "pPresentationParameters"), Out(Pointer(PDIRECT3DDEVICE9), "ppReturnedDeviceInterface")]),
+    Method(HRESULT, "RegisterSoftwareDevice", [(OpaquePointer(Void), "pInitializeFunction")], sideeffects=False),
+    Method(UINT, "GetAdapterCount", [], sideeffects=False),
+    Method(HRESULT, "GetAdapterIdentifier", [(UINT, "Adapter"), (D3DENUM, "Flags"), Out(Pointer(D3DADAPTER_IDENTIFIER9), "pIdentifier")], sideeffects=False),
+    Method(UINT, "GetAdapterModeCount", [(UINT, "Adapter"), (D3DFORMAT, "Format")], sideeffects=False),
+    Method(HRESULT, "EnumAdapterModes", [(UINT, "Adapter"), (D3DFORMAT, "Format"), (UINT, "Mode"), Out(Pointer(D3DDISPLAYMODE), "pMode")], sideeffects=False),
+    Method(HRESULT, "GetAdapterDisplayMode", [(UINT, "Adapter"), Out(Pointer(D3DDISPLAYMODE), "pMode")], sideeffects=False),
+    Method(HRESULT, "CheckDeviceType", [(UINT, "Adapter"), (D3DDEVTYPE, "DevType"), (D3DFORMAT, "AdapterFormat"), (D3DFORMAT, "BackBufferFormat"), (BOOL, "bWindowed")], sideeffects=False),
+    Method(HRESULT, "CheckDeviceFormat", [(UINT, "Adapter"), (D3DDEVTYPE, "DeviceType"), (D3DFORMAT, "AdapterFormat"), (D3DUSAGE, "Usage"), (D3DRESOURCETYPE, "RType"), (D3DFORMAT, "CheckFormat")], sideeffects=False),
+    Method(HRESULT, "CheckDeviceMultiSampleType", [(UINT, "Adapter"), (D3DDEVTYPE, "DeviceType"), (D3DFORMAT, "SurfaceFormat"), (BOOL, "Windowed"), (D3DMULTISAMPLE_TYPE, "MultiSampleType"), Out(Pointer(DWORD), "pQualityLevels")], sideeffects=False),
+    Method(HRESULT, "CheckDepthStencilMatch", [(UINT, "Adapter"), (D3DDEVTYPE, "DeviceType"), (D3DFORMAT, "AdapterFormat"), (D3DFORMAT, "RenderTargetFormat"), (D3DFORMAT, "DepthStencilFormat")], sideeffects=False),
+    Method(HRESULT, "CheckDeviceFormatConversion", [(UINT, "Adapter"), (D3DDEVTYPE, "DeviceType"), (D3DFORMAT, "SourceFormat"), (D3DFORMAT, "TargetFormat")], sideeffects=False),
+    Method(HRESULT, "GetDeviceCaps", [(UINT, "Adapter"), (D3DDEVTYPE, "DeviceType"), Out(Pointer(D3DCAPS9), "pCaps")], sideeffects=False),
+    Method(HMONITOR, "GetAdapterMonitor", [(UINT, "Adapter")], sideeffects=False),
+    Method(HRESULT, "CreateDevice", [(UINT, "Adapter"), (D3DDEVTYPE, "DeviceType"), (HWND, "hFocusWindow"), (D3DCREATE, "BehaviorFlags"), InOut(Pointer(D3DPRESENT_PARAMETERS), "pPresentationParameters"), Out(Pointer(PDIRECT3DDEVICE9), "ppReturnedDeviceInterface")]),
 ]
 
 IDirect3DDevice9.methods += [
     Method(HRESULT, "TestCooperativeLevel", []),
-    Method(UINT, "GetAvailableTextureMem", []),
+    Method(UINT, "GetAvailableTextureMem", [], sideeffects=False),
     Method(HRESULT, "EvictManagedResources", []),
-    Method(HRESULT, "GetDirect3D", [Out(Pointer(PDIRECT3D9), "ppD3D9")]),
-    Method(HRESULT, "GetDeviceCaps", [Out(Pointer(D3DCAPS9), "pCaps")]),
-    Method(HRESULT, "GetDisplayMode", [(UINT, "iSwapChain"), Out(Pointer(D3DDISPLAYMODE), "pMode")]),
-    Method(HRESULT, "GetCreationParameters", [Out(Pointer(D3DDEVICE_CREATION_PARAMETERS), "pParameters")]),
+    Method(HRESULT, "GetDirect3D", [Out(Pointer(PDIRECT3D9), "ppD3D9")], sideeffects=False),
+    Method(HRESULT, "GetDeviceCaps", [Out(Pointer(D3DCAPS9), "pCaps")], sideeffects=False),
+    Method(HRESULT, "GetDisplayMode", [(UINT, "iSwapChain"), Out(Pointer(D3DDISPLAYMODE), "pMode")], sideeffects=False),
+    Method(HRESULT, "GetCreationParameters", [Out(Pointer(D3DDEVICE_CREATION_PARAMETERS), "pParameters")], sideeffects=False),
     Method(HRESULT, "SetCursorProperties", [(UINT, "XHotSpot"), (UINT, "YHotSpot"), (PDIRECT3DSURFACE9, "pCursorBitmap")]),
     Method(Void, "SetCursorPosition", [(Int, "X"), (Int, "Y"), (D3DCURSOR, "Flags")]),
     Method(BOOL, "ShowCursor", [(BOOL, "bShow")]),
     Method(HRESULT, "CreateAdditionalSwapChain", [Out(Pointer(D3DPRESENT_PARAMETERS), "pPresentationParameters"), Out(Pointer(PDIRECT3DSWAPCHAIN9), "pSwapChain")]),
-    Method(HRESULT, "GetSwapChain", [(UINT, "iSwapChain"), Out(Pointer(PDIRECT3DSWAPCHAIN9), "pSwapChain")]),
-    Method(UINT, "GetNumberOfSwapChains", []),
+    Method(HRESULT, "GetSwapChain", [(UINT, "iSwapChain"), Out(Pointer(PDIRECT3DSWAPCHAIN9), "pSwapChain")], sideeffects=False),
+    Method(UINT, "GetNumberOfSwapChains", [], sideeffects=False),
     Method(HRESULT, "Reset", [Out(Pointer(D3DPRESENT_PARAMETERS), "pPresentationParameters")]),
     Method(HRESULT, "Present", [(ConstPointer(RECT), "pSourceRect"), (ConstPointer(RECT), "pDestRect"), (HWND, "hDestWindowOverride"), (ConstPointer(RGNDATA), "pDirtyRegion")]),
     Method(HRESULT, "GetBackBuffer", [(UINT, "iSwapChain"), (UINT, "iBackBuffer"), (D3DBACKBUFFER_TYPE, "Type"), Out(Pointer(PDIRECT3DSURFACE9), "ppBackBuffer")]),
-    Method(HRESULT, "GetRasterStatus", [(UINT, "iSwapChain"), Out(Pointer(D3DRASTER_STATUS), "pRasterStatus")]),
+    Method(HRESULT, "GetRasterStatus", [(UINT, "iSwapChain"), Out(Pointer(D3DRASTER_STATUS), "pRasterStatus")], sideeffects=False),
     Method(HRESULT, "SetDialogBoxMode", [(BOOL, "bEnableDialogs")]),
     Method(Void, "SetGammaRamp", [(UINT, "iSwapChain"), (D3DSGR, "Flags"), (ConstPointer(D3DGAMMARAMP), "pRamp")]),
-    Method(Void, "GetGammaRamp", [(UINT, "iSwapChain"), Out(Pointer(D3DGAMMARAMP), "pRamp")]),
-    Method(HRESULT, "CreateTexture", [(UINT, "Width"), (UINT, "Height"), (UINT, "Levels"), (D3DUSAGE, "Usage"), (D3DFORMAT, "Format"), (D3DPOOL, "Pool"), Out(Pointer(PDIRECT3DTEXTURE9), "ppTexture"), Out(Pointer(HANDLE), "pSharedHandle")]),
-    Method(HRESULT, "CreateVolumeTexture", [(UINT, "Width"), (UINT, "Height"), (UINT, "Depth"), (UINT, "Levels"), (D3DUSAGE, "Usage"), (D3DFORMAT, "Format"), (D3DPOOL, "Pool"), Out(Pointer(PDIRECT3DVOLUMETEXTURE9), "ppVolumeTexture"), Out(Pointer(HANDLE), "pSharedHandle")]),
-    Method(HRESULT, "CreateCubeTexture", [(UINT, "EdgeLength"), (UINT, "Levels"), (D3DUSAGE, "Usage"), (D3DFORMAT, "Format"), (D3DPOOL, "Pool"), Out(Pointer(PDIRECT3DCUBETEXTURE9), "ppCubeTexture"), Out(Pointer(HANDLE), "pSharedHandle")]),
-    Method(HRESULT, "CreateVertexBuffer", [(UINT, "Length"), (D3DUSAGE, "Usage"), (D3DFVF, "FVF"), (D3DPOOL, "Pool"), Out(Pointer(PDIRECT3DVERTEXBUFFER9), "ppVertexBuffer"), Out(Pointer(HANDLE), "pSharedHandle")]),
-    Method(HRESULT, "CreateIndexBuffer", [(UINT, "Length"), (D3DUSAGE, "Usage"), (D3DFORMAT, "Format"), (D3DPOOL, "Pool"), Out(Pointer(PDIRECT3DINDEXBUFFER9), "ppIndexBuffer"), Out(Pointer(HANDLE), "pSharedHandle")]),
-    Method(HRESULT, "CreateRenderTarget", [(UINT, "Width"), (UINT, "Height"), (D3DFORMAT, "Format"), (D3DMULTISAMPLE_TYPE, "MultiSample"), (DWORD, "MultisampleQuality"), (BOOL, "Lockable"), Out(Pointer(PDIRECT3DSURFACE9), "ppSurface"), Out(Pointer(HANDLE), "pSharedHandle")]),
-    Method(HRESULT, "CreateDepthStencilSurface", [(UINT, "Width"), (UINT, "Height"), (D3DFORMAT, "Format"), (D3DMULTISAMPLE_TYPE, "MultiSample"), (DWORD, "MultisampleQuality"), (BOOL, "Discard"), Out(Pointer(PDIRECT3DSURFACE9), "ppSurface"), Out(Pointer(HANDLE), "pSharedHandle")]),
+    Method(Void, "GetGammaRamp", [(UINT, "iSwapChain"), Out(Pointer(D3DGAMMARAMP), "pRamp")], sideeffects=False),
+    Method(HRESULT, "CreateTexture", [(UINT, "Width"), (UINT, "Height"), (UINT, "Levels"), (D3DUSAGE, "Usage"), (D3DFORMAT, "Format"), (D3DPOOL, "Pool"), Out(Pointer(PDIRECT3DTEXTURE9), "ppTexture"), (Pointer(HANDLE), "pSharedHandle")]),
+    Method(HRESULT, "CreateVolumeTexture", [(UINT, "Width"), (UINT, "Height"), (UINT, "Depth"), (UINT, "Levels"), (D3DUSAGE, "Usage"), (D3DFORMAT, "Format"), (D3DPOOL, "Pool"), Out(Pointer(PDIRECT3DVOLUMETEXTURE9), "ppVolumeTexture"), (Pointer(HANDLE), "pSharedHandle")]),
+    Method(HRESULT, "CreateCubeTexture", [(UINT, "EdgeLength"), (UINT, "Levels"), (D3DUSAGE, "Usage"), (D3DFORMAT, "Format"), (D3DPOOL, "Pool"), Out(Pointer(PDIRECT3DCUBETEXTURE9), "ppCubeTexture"), (Pointer(HANDLE), "pSharedHandle")]),
+    Method(HRESULT, "CreateVertexBuffer", [(UINT, "Length"), (D3DUSAGE, "Usage"), (D3DFVF, "FVF"), (D3DPOOL, "Pool"), Out(Pointer(PDIRECT3DVERTEXBUFFER9), "ppVertexBuffer"), (Pointer(HANDLE), "pSharedHandle")]),
+    Method(HRESULT, "CreateIndexBuffer", [(UINT, "Length"), (D3DUSAGE, "Usage"), (D3DFORMAT, "Format"), (D3DPOOL, "Pool"), Out(Pointer(PDIRECT3DINDEXBUFFER9), "ppIndexBuffer"), (Pointer(HANDLE), "pSharedHandle")]),
+    Method(HRESULT, "CreateRenderTarget", [(UINT, "Width"), (UINT, "Height"), (D3DFORMAT, "Format"), (D3DMULTISAMPLE_TYPE, "MultiSample"), (DWORD, "MultisampleQuality"), (BOOL, "Lockable"), Out(Pointer(PDIRECT3DSURFACE9), "ppSurface"), (Pointer(HANDLE), "pSharedHandle")]),
+    Method(HRESULT, "CreateDepthStencilSurface", [(UINT, "Width"), (UINT, "Height"), (D3DFORMAT, "Format"), (D3DMULTISAMPLE_TYPE, "MultiSample"), (DWORD, "MultisampleQuality"), (BOOL, "Discard"), Out(Pointer(PDIRECT3DSURFACE9), "ppSurface"), (Pointer(HANDLE), "pSharedHandle")]),
     Method(HRESULT, "UpdateSurface", [(PDIRECT3DSURFACE9, "pSourceSurface"), (ConstPointer(RECT), "pSourceRect"), (PDIRECT3DSURFACE9, "pDestinationSurface"), (ConstPointer(POINT), "pDestPoint")]),
     Method(HRESULT, "UpdateTexture", [(PDIRECT3DBASETEXTURE9, "pSourceTexture"), (PDIRECT3DBASETEXTURE9, "pDestinationTexture")]),
-    Method(HRESULT, "GetRenderTargetData", [(PDIRECT3DSURFACE9, "pRenderTarget"), (PDIRECT3DSURFACE9, "pDestSurface")]),
-    Method(HRESULT, "GetFrontBufferData", [(UINT, "iSwapChain"), (PDIRECT3DSURFACE9, "pDestSurface")]),
+    Method(HRESULT, "GetRenderTargetData", [(PDIRECT3DSURFACE9, "pRenderTarget"), (PDIRECT3DSURFACE9, "pDestSurface")], sideeffects=False),
+    Method(HRESULT, "GetFrontBufferData", [(UINT, "iSwapChain"), (PDIRECT3DSURFACE9, "pDestSurface")], sideeffects=False),
     Method(HRESULT, "StretchRect", [(PDIRECT3DSURFACE9, "pSourceSurface"), (ConstPointer(RECT), "pSourceRect"), (PDIRECT3DSURFACE9, "pDestSurface"), (ConstPointer(RECT), "pDestRect"), (D3DTEXTUREFILTERTYPE, "Filter")]),
     Method(HRESULT, "ColorFill", [(PDIRECT3DSURFACE9, "pSurface"), (ConstPointer(RECT), "pRect"), (D3DCOLOR, "color")]),
-    Method(HRESULT, "CreateOffscreenPlainSurface", [(UINT, "Width"), (UINT, "Height"), (D3DFORMAT, "Format"), (D3DPOOL, "Pool"), Out(Pointer(PDIRECT3DSURFACE9), "ppSurface"), Out(Pointer(HANDLE), "pSharedHandle")]),
+    Method(HRESULT, "CreateOffscreenPlainSurface", [(UINT, "Width"), (UINT, "Height"), (D3DFORMAT, "Format"), (D3DPOOL, "Pool"), Out(Pointer(PDIRECT3DSURFACE9), "ppSurface"), (Pointer(HANDLE), "pSharedHandle")]),
     Method(HRESULT, "SetRenderTarget", [(DWORD, "RenderTargetIndex"), (PDIRECT3DSURFACE9, "pRenderTarget")]),
-    Method(HRESULT, "GetRenderTarget", [(DWORD, "RenderTargetIndex"), Out(Pointer(PDIRECT3DSURFACE9), "ppRenderTarget")]),
+    Method(HRESULT, "GetRenderTarget", [(DWORD, "RenderTargetIndex"), Out(Pointer(PDIRECT3DSURFACE9), "ppRenderTarget")], sideeffects=False),
     Method(HRESULT, "SetDepthStencilSurface", [(PDIRECT3DSURFACE9, "pNewZStencil")]),
-    Method(HRESULT, "GetDepthStencilSurface", [Out(Pointer(PDIRECT3DSURFACE9), "ppZStencilSurface")]),
+    Method(HRESULT, "GetDepthStencilSurface", [Out(Pointer(PDIRECT3DSURFACE9), "ppZStencilSurface")], sideeffects=False),
     Method(HRESULT, "BeginScene", []),
     Method(HRESULT, "EndScene", []),
     Method(HRESULT, "Clear", [(DWORD, "Count"), (ConstPointer(D3DRECT), "pRects"), (D3DCLEAR, "Flags"), (D3DCOLOR, "Color"), (Float, "Z"), (DWORD, "Stencil")]),
     Method(HRESULT, "SetTransform", [(D3DTRANSFORMSTATETYPE, "State"), (ConstPointer(D3DMATRIX), "pMatrix")]),
-    Method(HRESULT, "GetTransform", [(D3DTRANSFORMSTATETYPE, "State"), Out(Pointer(D3DMATRIX), "pMatrix")]),
+    Method(HRESULT, "GetTransform", [(D3DTRANSFORMSTATETYPE, "State"), Out(Pointer(D3DMATRIX), "pMatrix")], sideeffects=False),
     Method(HRESULT, "MultiplyTransform", [(D3DTRANSFORMSTATETYPE, "State"), (ConstPointer(D3DMATRIX), "pMatrix")]),
     Method(HRESULT, "SetViewport", [(ConstPointer(D3DVIEWPORT9), "pViewport")]),
-    Method(HRESULT, "GetViewport", [Out(Pointer(D3DVIEWPORT9), "pViewport")]),
+    Method(HRESULT, "GetViewport", [Out(Pointer(D3DVIEWPORT9), "pViewport")], sideeffects=False),
     Method(HRESULT, "SetMaterial", [(ConstPointer(D3DMATERIAL9), "pMaterial")]),
-    Method(HRESULT, "GetMaterial", [Out(Pointer(D3DMATERIAL9), "pMaterial")]),
+    Method(HRESULT, "GetMaterial", [Out(Pointer(D3DMATERIAL9), "pMaterial")], sideeffects=False),
     Method(HRESULT, "SetLight", [(DWORD, "Index"), (ConstPointer(D3DLIGHT9), "pLight")]),
-    Method(HRESULT, "GetLight", [(DWORD, "Index"), Out(Pointer(D3DLIGHT9), "pLight")]),
+    Method(HRESULT, "GetLight", [(DWORD, "Index"), Out(Pointer(D3DLIGHT9), "pLight")], sideeffects=False),
     Method(HRESULT, "LightEnable", [(DWORD, "Index"), (BOOL, "Enable")]),
-    Method(HRESULT, "GetLightEnable", [(DWORD, "Index"), Out(Pointer(BOOL), "pEnable")]),
+    Method(HRESULT, "GetLightEnable", [(DWORD, "Index"), Out(Pointer(BOOL), "pEnable")], sideeffects=False),
     Method(HRESULT, "SetClipPlane", [(DWORD, "Index"), (ConstPointer(Float), "pPlane")]),
-    Method(HRESULT, "GetClipPlane", [(DWORD, "Index"), Out(Pointer(Float), "pPlane")]),
+    Method(HRESULT, "GetClipPlane", [(DWORD, "Index"), Out(Pointer(Float), "pPlane")], sideeffects=False),
     Method(HRESULT, "SetRenderState", [(D3DRENDERSTATETYPE, "State"), (D3DRENDERSTATEVALUE, "Value")]),
-    Method(HRESULT, "GetRenderState", [(D3DRENDERSTATETYPE, "State"), Out(Pointer(D3DRENDERSTATEVALUE), "pValue")]),
+    Method(HRESULT, "GetRenderState", [(D3DRENDERSTATETYPE, "State"), Out(Pointer(D3DRENDERSTATEVALUE), "pValue")], sideeffects=False),
     Method(HRESULT, "CreateStateBlock", [(D3DSTATEBLOCKTYPE, "Type"), Out(Pointer(PDIRECT3DSTATEBLOCK9), "ppSB")]),
     Method(HRESULT, "BeginStateBlock", []),
     Method(HRESULT, "EndStateBlock", [Out(Pointer(PDIRECT3DSTATEBLOCK9), "ppSB")]),
     Method(HRESULT, "SetClipStatus", [(ConstPointer(D3DCLIPSTATUS9), "pClipStatus")]),
-    Method(HRESULT, "GetClipStatus", [Out(Pointer(D3DCLIPSTATUS9), "pClipStatus")]),
-    Method(HRESULT, "GetTexture", [(DWORD, "Stage"), Out(Pointer(PDIRECT3DBASETEXTURE9), "ppTexture")]),
+    Method(HRESULT, "GetClipStatus", [Out(Pointer(D3DCLIPSTATUS9), "pClipStatus")], sideeffects=False),
+    Method(HRESULT, "GetTexture", [(DWORD, "Stage"), Out(Pointer(PDIRECT3DBASETEXTURE9), "ppTexture")], sideeffects=False),
     Method(HRESULT, "SetTexture", [(DWORD, "Stage"), (PDIRECT3DBASETEXTURE9, "pTexture")]),
-    Method(HRESULT, "GetTextureStageState", [(DWORD, "Stage"), (D3DTEXTURESTAGESTATETYPE, "Type"), Out(Pointer(D3DTEXTURESTAGESTATEVALUE), "pValue")]),
+    Method(HRESULT, "GetTextureStageState", [(DWORD, "Stage"), (D3DTEXTURESTAGESTATETYPE, "Type"), Out(Pointer(D3DTEXTURESTAGESTATEVALUE), "pValue")], sideeffects=False),
     Method(HRESULT, "SetTextureStageState", [(DWORD, "Stage"), (D3DTEXTURESTAGESTATETYPE, "Type"), (D3DTEXTURESTAGESTATEVALUE, "Value")]),
-    Method(HRESULT, "GetSamplerState", [(DWORD, "Sampler"), (D3DSAMPLERSTATETYPE, "Type"), Out(Pointer(D3DSAMPLERSTATEVALUE), "pValue")]),
+    Method(HRESULT, "GetSamplerState", [(DWORD, "Sampler"), (D3DSAMPLERSTATETYPE, "Type"), Out(Pointer(D3DSAMPLERSTATEVALUE), "pValue")], sideeffects=False),
     Method(HRESULT, "SetSamplerState", [(DWORD, "Sampler"), (D3DSAMPLERSTATETYPE, "Type"), (D3DSAMPLERSTATEVALUE, "Value")]),
     Method(HRESULT, "ValidateDevice", [Out(Pointer(DWORD), "pNumPasses")]),
     Method(HRESULT, "SetPaletteEntries", [(UINT, "PaletteNumber"), (ConstPointer(PALETTEENTRY), "pEntries")]),
-    Method(HRESULT, "GetPaletteEntries", [(UINT, "PaletteNumber"), Out(Pointer(PALETTEENTRY), "pEntries")]),
+    Method(HRESULT, "GetPaletteEntries", [(UINT, "PaletteNumber"), Out(Pointer(PALETTEENTRY), "pEntries")], sideeffects=False),
     Method(HRESULT, "SetCurrentTexturePalette", [(UINT, "PaletteNumber")]),
-    Method(HRESULT, "GetCurrentTexturePalette", [Out(Pointer(UINT), "PaletteNumber")]),
+    Method(HRESULT, "GetCurrentTexturePalette", [Out(Pointer(UINT), "PaletteNumber")], sideeffects=False),
     Method(HRESULT, "SetScissorRect", [(ConstPointer(RECT), "pRect")]),
     Method(HRESULT, "GetScissorRect", [Out(Pointer(RECT), "pRect")]),
     Method(HRESULT, "SetSoftwareVertexProcessing", [(BOOL, "bSoftware")]),
-    Method(BOOL, "GetSoftwareVertexProcessing", []),
+    Method(BOOL, "GetSoftwareVertexProcessing", [], sideeffects=False),
     Method(HRESULT, "SetNPatchMode", [(Float, "nSegments")]),
-    Method(Float, "GetNPatchMode", []),
+    Method(Float, "GetNPatchMode", [], sideeffects=False),
     Method(HRESULT, "DrawPrimitive", [(D3DPRIMITIVETYPE, "PrimitiveType"), (UINT, "StartVertex"), (UINT, "PrimitiveCount")]),
     Method(HRESULT, "DrawIndexedPrimitive", [(D3DPRIMITIVETYPE, "PrimitiveType"), (INT, "BaseVertexIndex"), (UINT, "MinVertexIndex"), (UINT, "NumVertices"), (UINT, "startIndex"), (UINT, "primCount")]),
     Method(HRESULT, "DrawPrimitiveUP", [(D3DPRIMITIVETYPE, "PrimitiveType"), (UINT, "PrimitiveCount"), (OpaquePointer(Const(Void)), "pVertexStreamZeroData"), (UINT, "VertexStreamZeroStride")]),
@@ -256,33 +256,33 @@ IDirect3DDevice9.methods += [
     Method(HRESULT, "ProcessVertices", [(UINT, "SrcStartIndex"), (UINT, "DestIndex"), (UINT, "VertexCount"), (PDIRECT3DVERTEXBUFFER9, "pDestBuffer"), (PDIRECT3DVERTEXDECLARATION9, "pVertexDecl"), (D3DPV, "Flags")]),
     Method(HRESULT, "CreateVertexDeclaration", [(Array(Const(D3DVERTEXELEMENT9), "_declCount(pVertexElements)"), "pVertexElements"), Out(Pointer(PDIRECT3DVERTEXDECLARATION9), "ppDecl")]),
     Method(HRESULT, "SetVertexDeclaration", [(PDIRECT3DVERTEXDECLARATION9, "pDecl")]),
-    Method(HRESULT, "GetVertexDeclaration", [Out(Pointer(PDIRECT3DVERTEXDECLARATION9), "ppDecl")]),
+    Method(HRESULT, "GetVertexDeclaration", [Out(Pointer(PDIRECT3DVERTEXDECLARATION9), "ppDecl")], sideeffects=False),
     Method(HRESULT, "SetFVF", [(D3DFVF, "FVF")]),
-    Method(HRESULT, "GetFVF", [Out(Pointer(D3DFVF), "pFVF")]),
+    Method(HRESULT, "GetFVF", [Out(Pointer(D3DFVF), "pFVF")], sideeffects=False),
     Method(HRESULT, "CreateVertexShader", [(D3DSHADER9, "pFunction"), Out(Pointer(PDIRECT3DVERTEXSHADER9), "ppShader")]),
     Method(HRESULT, "SetVertexShader", [(PDIRECT3DVERTEXSHADER9, "pShader")]),
-    Method(HRESULT, "GetVertexShader", [Out(Pointer(PDIRECT3DVERTEXSHADER9), "ppShader")]),
+    Method(HRESULT, "GetVertexShader", [Out(Pointer(PDIRECT3DVERTEXSHADER9), "ppShader")], sideeffects=False),
     Method(HRESULT, "SetVertexShaderConstantF", [(UINT, "StartRegister"), (Array(Const(Float), "4*Vector4fCount"), "pConstantData"), (UINT, "Vector4fCount")]),
-    Method(HRESULT, "GetVertexShaderConstantF", [(UINT, "StartRegister"), Out(Array(Float, "4*Vector4fCount"), "pConstantData"), (UINT, "Vector4fCount")]),
+    Method(HRESULT, "GetVertexShaderConstantF", [(UINT, "StartRegister"), Out(Array(Float, "4*Vector4fCount"), "pConstantData"), (UINT, "Vector4fCount")], sideeffects=False),
     Method(HRESULT, "SetVertexShaderConstantI", [(UINT, "StartRegister"), (Array(Const(Int), "4*Vector4iCount"), "pConstantData"), (UINT, "Vector4iCount")]),
-    Method(HRESULT, "GetVertexShaderConstantI", [(UINT, "StartRegister"), Out(Array(Int, "4*Vector4iCount"), "pConstantData"), (UINT, "Vector4iCount")]),
+    Method(HRESULT, "GetVertexShaderConstantI", [(UINT, "StartRegister"), Out(Array(Int, "4*Vector4iCount"), "pConstantData"), (UINT, "Vector4iCount")], sideeffects=False),
     Method(HRESULT, "SetVertexShaderConstantB", [(UINT, "StartRegister"), (Array(Const(BOOL), "BoolCount"), "pConstantData"), (UINT, "BoolCount")]),
-    Method(HRESULT, "GetVertexShaderConstantB", [(UINT, "StartRegister"), Out(Array(BOOL, "BoolCount"), "pConstantData"), (UINT, "BoolCount")]),
+    Method(HRESULT, "GetVertexShaderConstantB", [(UINT, "StartRegister"), Out(Array(BOOL, "BoolCount"), "pConstantData"), (UINT, "BoolCount")], sideeffects=False),
     Method(HRESULT, "SetStreamSource", [(UINT, "StreamNumber"), (PDIRECT3DVERTEXBUFFER9, "pStreamData"), (UINT, "OffsetInBytes"), (UINT, "Stride")]),
-    Method(HRESULT, "GetStreamSource", [(UINT, "StreamNumber"), Out(Pointer(PDIRECT3DVERTEXBUFFER9), "ppStreamData"), Out(Pointer(UINT), "pOffsetInBytes"), Out(Pointer(UINT), "pStride")]),
+    Method(HRESULT, "GetStreamSource", [(UINT, "StreamNumber"), Out(Pointer(PDIRECT3DVERTEXBUFFER9), "ppStreamData"), Out(Pointer(UINT), "pOffsetInBytes"), Out(Pointer(UINT), "pStride")], sideeffects=False),
     Method(HRESULT, "SetStreamSourceFreq", [(UINT, "StreamNumber"), (UINT, "Setting")]),
-    Method(HRESULT, "GetStreamSourceFreq", [(UINT, "StreamNumber"), Out(Pointer(UINT), "pSetting")]),
+    Method(HRESULT, "GetStreamSourceFreq", [(UINT, "StreamNumber"), Out(Pointer(UINT), "pSetting")], sideeffects=False),
     Method(HRESULT, "SetIndices", [(PDIRECT3DINDEXBUFFER9, "pIndexData")]),
-    Method(HRESULT, "GetIndices", [Out(Pointer(PDIRECT3DINDEXBUFFER9), "ppIndexData")]),
+    Method(HRESULT, "GetIndices", [Out(Pointer(PDIRECT3DINDEXBUFFER9), "ppIndexData")], sideeffects=False),
     Method(HRESULT, "CreatePixelShader", [(D3DSHADER9, "pFunction"), Out(Pointer(PDIRECT3DPIXELSHADER9), "ppShader")]),
     Method(HRESULT, "SetPixelShader", [(PDIRECT3DPIXELSHADER9, "pShader")]),
-    Method(HRESULT, "GetPixelShader", [Out(Pointer(PDIRECT3DPIXELSHADER9), "ppShader")]),
+    Method(HRESULT, "GetPixelShader", [Out(Pointer(PDIRECT3DPIXELSHADER9), "ppShader")], sideeffects=False),
     Method(HRESULT, "SetPixelShaderConstantF", [(UINT, "StartRegister"), (Array(Const(Float), "4*Vector4fCount"), "pConstantData"), (UINT, "Vector4fCount")]),
-    Method(HRESULT, "GetPixelShaderConstantF", [(UINT, "StartRegister"), Out(Array(Float, "4*Vector4fCount"), "pConstantData"), (UINT, "Vector4fCount")]),
+    Method(HRESULT, "GetPixelShaderConstantF", [(UINT, "StartRegister"), Out(Array(Float, "4*Vector4fCount"), "pConstantData"), (UINT, "Vector4fCount")], sideeffects=False),
     Method(HRESULT, "SetPixelShaderConstantI", [(UINT, "StartRegister"), (Array(Const(Int), "4*Vector4iCount"), "pConstantData"), (UINT, "Vector4iCount")]),
-    Method(HRESULT, "GetPixelShaderConstantI", [(UINT, "StartRegister"), Out(Array(Int, "4*Vector4iCount"), "pConstantData"), (UINT, "Vector4iCount")]),
+    Method(HRESULT, "GetPixelShaderConstantI", [(UINT, "StartRegister"), Out(Array(Int, "4*Vector4iCount"), "pConstantData"), (UINT, "Vector4iCount")], sideeffects=False),
     Method(HRESULT, "SetPixelShaderConstantB", [(UINT, "StartRegister"), (Array(Const(BOOL), "BoolCount"), "pConstantData"), (UINT, "BoolCount")]),
-    Method(HRESULT, "GetPixelShaderConstantB", [(UINT, "StartRegister"), Out(Array(BOOL, "BoolCount"), "pConstantData"), (UINT, "BoolCount")]),
+    Method(HRESULT, "GetPixelShaderConstantB", [(UINT, "StartRegister"), Out(Array(BOOL, "BoolCount"), "pConstantData"), (UINT, "BoolCount")], sideeffects=False),
     Method(HRESULT, "DrawRectPatch", [(UINT, "Handle"), (ConstPointer(Float), "pNumSegs"), (ConstPointer(D3DRECTPATCH_INFO), "pRectPatchInfo")]),
     Method(HRESULT, "DrawTriPatch", [(UINT, "Handle"), (ConstPointer(Float), "pNumSegs"), (ConstPointer(D3DTRIPATCH_INFO), "pTriPatchInfo")]),
     Method(HRESULT, "DeletePatch", [(UINT, "Handle")]),
@@ -290,95 +290,95 @@ IDirect3DDevice9.methods += [
 ]
 
 IDirect3DStateBlock9.methods += [
-    Method(HRESULT, "GetDevice", [Out(Pointer(PDIRECT3DDEVICE9), "ppDevice")]),
+    Method(HRESULT, "GetDevice", [Out(Pointer(PDIRECT3DDEVICE9), "ppDevice")], sideeffects=False),
     Method(HRESULT, "Capture", []),
     Method(HRESULT, "Apply", []),
 ]
 
 IDirect3DSwapChain9.methods += [
     Method(HRESULT, "Present", [(ConstPointer(RECT), "pSourceRect"), (ConstPointer(RECT), "pDestRect"), (HWND, "hDestWindowOverride"), (ConstPointer(RGNDATA), "pDirtyRegion"), (D3DPRESENT, "dwFlags")]),
-    Method(HRESULT, "GetFrontBufferData", [(PDIRECT3DSURFACE9, "pDestSurface")]),
-    Method(HRESULT, "GetBackBuffer", [(UINT, "iBackBuffer"), (D3DBACKBUFFER_TYPE, "Type"), Out(Pointer(PDIRECT3DSURFACE9), "ppBackBuffer")]),
-    Method(HRESULT, "GetRasterStatus", [Out(Pointer(D3DRASTER_STATUS), "pRasterStatus")]),
-    Method(HRESULT, "GetDisplayMode", [Out(Pointer(D3DDISPLAYMODE), "pMode")]),
-    Method(HRESULT, "GetDevice", [Out(Pointer(PDIRECT3DDEVICE9), "ppDevice")]),
-    Method(HRESULT, "GetPresentParameters", [Out(Pointer(D3DPRESENT_PARAMETERS), "pPresentationParameters")]),
+    Method(HRESULT, "GetFrontBufferData", [(PDIRECT3DSURFACE9, "pDestSurface")], sideeffects=False),
+    Method(HRESULT, "GetBackBuffer", [(UINT, "iBackBuffer"), (D3DBACKBUFFER_TYPE, "Type"), Out(Pointer(PDIRECT3DSURFACE9), "ppBackBuffer")], sideeffects=False),
+    Method(HRESULT, "GetRasterStatus", [Out(Pointer(D3DRASTER_STATUS), "pRasterStatus")], sideeffects=False),
+    Method(HRESULT, "GetDisplayMode", [Out(Pointer(D3DDISPLAYMODE), "pMode")], sideeffects=False),
+    Method(HRESULT, "GetDevice", [Out(Pointer(PDIRECT3DDEVICE9), "ppDevice")], sideeffects=False),
+    Method(HRESULT, "GetPresentParameters", [Out(Pointer(D3DPRESENT_PARAMETERS), "pPresentationParameters")], sideeffects=False),
 ]
 
 IDirect3DResource9.methods += [
-    Method(HRESULT, "GetDevice", [Out(Pointer(PDIRECT3DDEVICE9), "ppDevice")]),
-    Method(HRESULT, "SetPrivateData", [(REFGUID, "refguid"), (OpaquePointer(Const(Void)), "pData"), (DWORD, "SizeOfData"), (D3DSPD, "Flags")]),
-    Method(HRESULT, "GetPrivateData", [(REFGUID, "refguid"), Out(OpaquePointer(Void), "pData"), Out(Pointer(DWORD), "pSizeOfData")]),
-    Method(HRESULT, "FreePrivateData", [(REFGUID, "refguid")]),
+    Method(HRESULT, "GetDevice", [Out(Pointer(PDIRECT3DDEVICE9), "ppDevice")], sideeffects=False),
+    Method(HRESULT, "SetPrivateData", [(REFGUID, "refguid"), (OpaquePointer(Const(Void)), "pData"), (DWORD, "SizeOfData"), (D3DSPD, "Flags")], sideeffects=False),
+    Method(HRESULT, "GetPrivateData", [(REFGUID, "refguid"), Out(OpaquePointer(Void), "pData"), Out(Pointer(DWORD), "pSizeOfData")], sideeffects=False),
+    Method(HRESULT, "FreePrivateData", [(REFGUID, "refguid")], sideeffects=False),
     Method(D3D9_RESOURCE_PRIORITY, "SetPriority", [(D3D9_RESOURCE_PRIORITY, "PriorityNew")]),
-    Method(D3D9_RESOURCE_PRIORITY, "GetPriority", []),
+    Method(D3D9_RESOURCE_PRIORITY, "GetPriority", [], sideeffects=False),
     Method(Void, "PreLoad", []),
-    Method(D3DRESOURCETYPE, "GetType", []),
+    Method(D3DRESOURCETYPE, "GetType", [], sideeffects=False),
 ]
 
 IDirect3DVertexDeclaration9.methods += [
-    Method(HRESULT, "GetDevice", [Out(Pointer(PDIRECT3DDEVICE9), "ppDevice")]),
-    Method(HRESULT, "GetDeclaration", [Out(Pointer(D3DVERTEXELEMENT9), "pElement"), Out(Pointer(UINT), "pNumElements")]),
+    Method(HRESULT, "GetDevice", [Out(Pointer(PDIRECT3DDEVICE9), "ppDevice")], sideeffects=False),
+    Method(HRESULT, "GetDeclaration", [Out(Pointer(D3DVERTEXELEMENT9), "pElement"), Out(Pointer(UINT), "pNumElements")], sideeffects=False),
 ]
 
 IDirect3DVertexShader9.methods += [
-    Method(HRESULT, "GetDevice", [Out(Pointer(PDIRECT3DDEVICE9), "ppDevice")]),
-    Method(HRESULT, "GetFunction", [Out(OpaquePointer(Void), "pData"), Out(Pointer(UINT), "pSizeOfData")]),
+    Method(HRESULT, "GetDevice", [Out(Pointer(PDIRECT3DDEVICE9), "ppDevice")], sideeffects=False),
+    Method(HRESULT, "GetFunction", [Out(OpaquePointer(Void), "pData"), Out(Pointer(UINT), "pSizeOfData")], sideeffects=False),
 ]
 
 IDirect3DPixelShader9.methods += [
-    Method(HRESULT, "GetDevice", [Out(Pointer(PDIRECT3DDEVICE9), "ppDevice")]),
-    Method(HRESULT, "GetFunction", [Out(OpaquePointer(Void), "pData"), Out(Pointer(UINT), "pSizeOfData")]),
+    Method(HRESULT, "GetDevice", [Out(Pointer(PDIRECT3DDEVICE9), "ppDevice")], sideeffects=False),
+    Method(HRESULT, "GetFunction", [Out(OpaquePointer(Void), "pData"), Out(Pointer(UINT), "pSizeOfData")], sideeffects=False),
 ]
 
 IDirect3DBaseTexture9.methods += [
     Method(DWORD, "SetLOD", [(DWORD, "LODNew")]),
-    Method(DWORD, "GetLOD", []),
-    Method(DWORD, "GetLevelCount", []),
+    Method(DWORD, "GetLOD", [], sideeffects=False),
+    Method(DWORD, "GetLevelCount", [], sideeffects=False),
     Method(HRESULT, "SetAutoGenFilterType", [(D3DTEXTUREFILTERTYPE, "FilterType")]),
-    Method(D3DTEXTUREFILTERTYPE, "GetAutoGenFilterType", []),
+    Method(D3DTEXTUREFILTERTYPE, "GetAutoGenFilterType", [], sideeffects=False),
     Method(Void, "GenerateMipSubLevels", []),
 ]
 
 IDirect3DTexture9.methods += [
-    Method(HRESULT, "GetLevelDesc", [(UINT, "Level"), Out(Pointer(D3DSURFACE_DESC), "pDesc")]),
-    Method(HRESULT, "GetSurfaceLevel", [(UINT, "Level"), Out(Pointer(PDIRECT3DSURFACE9), "ppSurfaceLevel")]),
+    Method(HRESULT, "GetLevelDesc", [(UINT, "Level"), Out(Pointer(D3DSURFACE_DESC), "pDesc")], sideeffects=False),
+    Method(HRESULT, "GetSurfaceLevel", [(UINT, "Level"), Out(Pointer(PDIRECT3DSURFACE9), "ppSurfaceLevel")], sideeffects=False),
     Method(HRESULT, "LockRect", [(UINT, "Level"), Out(Pointer(D3DLOCKED_RECT), "pLockedRect"), (ConstPointer(RECT), "pRect"), (D3DLOCK, "Flags")]),
     Method(HRESULT, "UnlockRect", [(UINT, "Level")]),
     Method(HRESULT, "AddDirtyRect", [(ConstPointer(RECT), "pDirtyRect")]),
 ]
 
 IDirect3DVolumeTexture9.methods += [
-    Method(HRESULT, "GetLevelDesc", [(UINT, "Level"), Out(Pointer(D3DVOLUME_DESC), "pDesc")]),
-    Method(HRESULT, "GetVolumeLevel", [(UINT, "Level"), Out(Pointer(PDIRECT3DVOLUME9), "ppVolumeLevel")]),
+    Method(HRESULT, "GetLevelDesc", [(UINT, "Level"), Out(Pointer(D3DVOLUME_DESC), "pDesc")], sideeffects=False),
+    Method(HRESULT, "GetVolumeLevel", [(UINT, "Level"), Out(Pointer(PDIRECT3DVOLUME9), "ppVolumeLevel")], sideeffects=False),
     Method(HRESULT, "LockBox", [(UINT, "Level"), Out(Pointer(D3DLOCKED_BOX), "pLockedVolume"), (ConstPointer(D3DBOX), "pBox"), (D3DLOCK, "Flags")]),
     Method(HRESULT, "UnlockBox", [(UINT, "Level")]),
     Method(HRESULT, "AddDirtyBox", [(ConstPointer(D3DBOX), "pDirtyBox")]),
 ]
 
 IDirect3DCubeTexture9.methods += [
-    Method(HRESULT, "GetLevelDesc", [(UINT, "Level"), Out(Pointer(D3DSURFACE_DESC), "pDesc")]),
-    Method(HRESULT, "GetCubeMapSurface", [(D3DCUBEMAP_FACES, "FaceType"), (UINT, "Level"), Out(Pointer(PDIRECT3DSURFACE9), "ppCubeMapSurface")]),
+    Method(HRESULT, "GetLevelDesc", [(UINT, "Level"), Out(Pointer(D3DSURFACE_DESC), "pDesc")], sideeffects=False),
+    Method(HRESULT, "GetCubeMapSurface", [(D3DCUBEMAP_FACES, "FaceType"), (UINT, "Level"), Out(Pointer(PDIRECT3DSURFACE9), "ppCubeMapSurface")], sideeffects=False),
     Method(HRESULT, "LockRect", [(D3DCUBEMAP_FACES, "FaceType"), (UINT, "Level"), Out(Pointer(D3DLOCKED_RECT), "pLockedRect"), (ConstPointer(RECT), "pRect"), (D3DLOCK, "Flags")]),
     Method(HRESULT, "UnlockRect", [(D3DCUBEMAP_FACES, "FaceType"), (UINT, "Level")]),
     Method(HRESULT, "AddDirtyRect", [(D3DCUBEMAP_FACES, "FaceType"), (ConstPointer(RECT), "pDirtyRect")]),
 ]
 
 IDirect3DVertexBuffer9.methods += [
-    Method(HRESULT, "Lock", [(UINT, "OffsetToLock"), (UINT, "SizeToLock"), Out(Pointer(OpaquePointer(Void)), "ppbData"), (D3DLOCK, "Flags")]),
+    Method(HRESULT, "Lock", [(UINT, "OffsetToLock"), (UINT, "SizeToLock"), Out(Pointer(LinearPointer(Void, "SizeToLock")), "ppbData"), (D3DLOCK, "Flags")]),
     Method(HRESULT, "Unlock", []),
-    Method(HRESULT, "GetDesc", [Out(Pointer(D3DVERTEXBUFFER_DESC), "pDesc")]),
+    Method(HRESULT, "GetDesc", [Out(Pointer(D3DVERTEXBUFFER_DESC), "pDesc")], sideeffects=False),
 ]
 
 IDirect3DIndexBuffer9.methods += [
-    Method(HRESULT, "Lock", [(UINT, "OffsetToLock"), (UINT, "SizeToLock"), Out(Pointer(OpaquePointer(Void)), "ppbData"), (D3DLOCK, "Flags")]),
+    Method(HRESULT, "Lock", [(UINT, "OffsetToLock"), (UINT, "SizeToLock"), Out(Pointer(LinearPointer(Void, "SizeToLock")), "ppbData"), (D3DLOCK, "Flags")]),
     Method(HRESULT, "Unlock", []),
-    Method(HRESULT, "GetDesc", [Out(Pointer(D3DINDEXBUFFER_DESC), "pDesc")]),
+    Method(HRESULT, "GetDesc", [Out(Pointer(D3DINDEXBUFFER_DESC), "pDesc")], sideeffects=False),
 ]
 
 IDirect3DSurface9.methods += [
-    Method(HRESULT, "GetContainer", [(REFIID, "riid"), Out(Pointer(OpaquePointer(Void)), "ppContainer")]),
-    Method(HRESULT, "GetDesc", [Out(Pointer(D3DSURFACE_DESC), "pDesc")]),
+    Method(HRESULT, "GetContainer", [(REFIID, "riid"), Out(Pointer(OpaquePointer(Void)), "ppContainer")], sideeffects=False),
+    Method(HRESULT, "GetDesc", [Out(Pointer(D3DSURFACE_DESC), "pDesc")], sideeffects=False),
     Method(HRESULT, "LockRect", [Out(Pointer(D3DLOCKED_RECT), "pLockedRect"), (ConstPointer(RECT), "pRect"), (D3DLOCK, "Flags")]),
     Method(HRESULT, "UnlockRect", []),
     Method(HRESULT, "GetDC", [Out(Pointer(HDC), "phdc")]),
@@ -386,65 +386,65 @@ IDirect3DSurface9.methods += [
 ]
 
 IDirect3DVolume9.methods += [
-    Method(HRESULT, "GetDevice", [Out(Pointer(PDIRECT3DDEVICE9), "ppDevice")]),
-    Method(HRESULT, "SetPrivateData", [(REFGUID, "refguid"), (OpaquePointer(Const(Void)), "pData"), (DWORD, "SizeOfData"), (D3DSPD, "Flags")]),
-    Method(HRESULT, "GetPrivateData", [(REFGUID, "refguid"), Out(OpaquePointer(Void), "pData"), Out(Pointer(DWORD), "pSizeOfData")]),
-    Method(HRESULT, "FreePrivateData", [(REFGUID, "refguid")]),
-    Method(HRESULT, "GetContainer", [(REFIID, "riid"), Out(Pointer(OpaquePointer(Void)), "ppContainer")]),
-    Method(HRESULT, "GetDesc", [Out(Pointer(D3DVOLUME_DESC), "pDesc")]),
+    Method(HRESULT, "GetDevice", [Out(Pointer(PDIRECT3DDEVICE9), "ppDevice")], sideeffects=False),
+    Method(HRESULT, "SetPrivateData", [(REFGUID, "refguid"), (OpaquePointer(Const(Void)), "pData"), (DWORD, "SizeOfData"), (D3DSPD, "Flags")], sideeffects=False),
+    Method(HRESULT, "GetPrivateData", [(REFGUID, "refguid"), Out(OpaquePointer(Void), "pData"), Out(Pointer(DWORD), "pSizeOfData")], sideeffects=False),
+    Method(HRESULT, "FreePrivateData", [(REFGUID, "refguid")], sideeffects=False),
+    Method(HRESULT, "GetContainer", [(REFIID, "riid"), Out(Pointer(OpaquePointer(Void)), "ppContainer")], sideeffects=False),
+    Method(HRESULT, "GetDesc", [Out(Pointer(D3DVOLUME_DESC), "pDesc")], sideeffects=False),
     Method(HRESULT, "LockBox", [Out(Pointer(D3DLOCKED_BOX), "pLockedVolume"), (ConstPointer(D3DBOX), "pBox"), (D3DLOCK, "Flags")]),
     Method(HRESULT, "UnlockBox", []),
 ]
 
 IDirect3DQuery9.methods += [
-    Method(HRESULT, "GetDevice", [Out(Pointer(PDIRECT3DDEVICE9), "ppDevice")]),
-    Method(D3DQUERYTYPE, "GetType", []),
-    Method(DWORD, "GetDataSize", []),
+    Method(HRESULT, "GetDevice", [Out(Pointer(PDIRECT3DDEVICE9), "ppDevice")], sideeffects=False),
+    Method(D3DQUERYTYPE, "GetType", [], sideeffects=False),
+    Method(DWORD, "GetDataSize", [], sideeffects=False),
     Method(HRESULT, "Issue", [(D3DISSUE, "dwIssueFlags")]),
     Method(HRESULT, "GetData", [Out(Blob(Void, "dwSize"), "pData"), (DWORD, "dwSize"), (D3DGETDATA, "dwGetDataFlags")]),
 ]
 
 IDirect3D9Ex.methods += [
-    Method(UINT, "GetAdapterModeCountEx", [(UINT, "Adapter"), (ConstPointer(D3DDISPLAYMODEFILTER), "pFilter") ]),
-    Method(HRESULT, "EnumAdapterModesEx", [(UINT, "Adapter"), (ConstPointer(D3DDISPLAYMODEFILTER), "pFilter"), (UINT, "Mode"), Out(Pointer(D3DDISPLAYMODEEX), "pMode")]),
-    Method(HRESULT, "GetAdapterDisplayModeEx", [(UINT, "Adapter"), Out(Pointer(D3DDISPLAYMODEEX), "pMode"), Out(Pointer(D3DDISPLAYROTATION), "pRotation")]),
+    Method(UINT, "GetAdapterModeCountEx", [(UINT, "Adapter"), (ConstPointer(D3DDISPLAYMODEFILTER), "pFilter") ], sideeffects=False),
+    Method(HRESULT, "EnumAdapterModesEx", [(UINT, "Adapter"), (ConstPointer(D3DDISPLAYMODEFILTER), "pFilter"), (UINT, "Mode"), Out(Pointer(D3DDISPLAYMODEEX), "pMode")], sideeffects=False),
+    Method(HRESULT, "GetAdapterDisplayModeEx", [(UINT, "Adapter"), Out(Pointer(D3DDISPLAYMODEEX), "pMode"), Out(Pointer(D3DDISPLAYROTATION), "pRotation")], sideeffects=False),
     Method(HRESULT, "CreateDeviceEx", [(UINT, "Adapter"), (D3DDEVTYPE, "DeviceType"), (HWND, "hFocusWindow"), (D3DCREATE, "BehaviorFlags"), Out(Pointer(D3DPRESENT_PARAMETERS), "pPresentationParameters"), Out(Pointer(D3DDISPLAYMODEEX), "pFullscreenDisplayMode"), Out(Pointer(PDIRECT3DDEVICE9EX), "ppReturnedDeviceInterface")]),
-    Method(HRESULT, "GetAdapterLUID", [(UINT, "Adapter"), Out(Pointer(LUID), "pLUID")]),
+    Method(HRESULT, "GetAdapterLUID", [(UINT, "Adapter"), Out(Pointer(LUID), "pLUID")], sideeffects=False),
 ]
 
 IDirect3DDevice9Ex.methods += [
     Method(HRESULT, "SetConvolutionMonoKernel", [(UINT, "width"), (UINT, "height"), (Array(Float, "width"), "rows"), (Array(Float, "height"), "columns")]),
     Method(HRESULT, "ComposeRects", [(PDIRECT3DSURFACE9, "pSrc"), (PDIRECT3DSURFACE9, "pDst"), (PDIRECT3DVERTEXBUFFER9, "pSrcRectDescs"), (UINT, "NumRects"), (PDIRECT3DVERTEXBUFFER9, "pDstRectDescs"), (D3DCOMPOSERECTSOP, "Operation"), (Int, "Xoffset"), (Int, "Yoffset")]),
     Method(HRESULT, "PresentEx", [(ConstPointer(RECT), "pSourceRect"), (ConstPointer(RECT), "pDestRect"), (HWND, "hDestWindowOverride"), (ConstPointer(RGNDATA), "pDirtyRegion"), (D3DPRESENT, "dwFlags")]),
-    Method(HRESULT, "GetGPUThreadPriority", [Out(Pointer(INT), "pPriority")]),
+    Method(HRESULT, "GetGPUThreadPriority", [Out(Pointer(INT), "pPriority")], sideeffects=False),
     Method(HRESULT, "SetGPUThreadPriority", [(INT, "Priority")]),
     Method(HRESULT, "WaitForVBlank", [(UINT, "iSwapChain")]),
     Method(HRESULT, "CheckResourceResidency", [(Array(PDIRECT3DRESOURCE9, "NumResources"), "pResourceArray"), (UINT32, "NumResources")]),
     Method(HRESULT, "SetMaximumFrameLatency", [(UINT, "MaxLatency")]),
-    Method(HRESULT, "GetMaximumFrameLatency", [Out(Pointer(UINT), "pMaxLatency")]),
-    Method(HRESULT, "CheckDeviceState", [(HWND, "hDestinationWindow")]),
-    Method(HRESULT, "CreateRenderTargetEx", [(UINT, "Width"), (UINT, "Height"), (D3DFORMAT, "Format"), (D3DMULTISAMPLE_TYPE, "MultiSample"), (DWORD, "MultisampleQuality"), (BOOL, "Lockable"), Out(Pointer(PDIRECT3DSURFACE9), "ppSurface"), Out(Pointer(HANDLE), "pSharedHandle"), (D3DUSAGE, "Usage")]),
+    Method(HRESULT, "GetMaximumFrameLatency", [Out(Pointer(UINT), "pMaxLatency")], sideeffects=False),
+    Method(HRESULT, "CheckDeviceState", [(HWND, "hDestinationWindow")], sideeffects=False),
+    Method(HRESULT, "CreateRenderTargetEx", [(UINT, "Width"), (UINT, "Height"), (D3DFORMAT, "Format"), (D3DMULTISAMPLE_TYPE, "MultiSample"), (DWORD, "MultisampleQuality"), (BOOL, "Lockable"), Out(Pointer(PDIRECT3DSURFACE9), "ppSurface"), (Pointer(HANDLE), "pSharedHandle"), (D3DUSAGE, "Usage")]),
     Method(HRESULT, "CreateOffscreenPlainSurfaceEx", [(UINT, "Width"), (UINT, "Height"), (D3DFORMAT, "Format"), (D3DPOOL, "Pool"), Out(Pointer(PDIRECT3DSURFACE9), "ppSurface"), Out(Pointer(HANDLE), "pSharedHandle"), (D3DUSAGE, "Usage")]),
-    Method(HRESULT, "CreateDepthStencilSurfaceEx", [(UINT, "Width"), (UINT, "Height"), (D3DFORMAT, "Format"), (D3DMULTISAMPLE_TYPE, "MultiSample"), (DWORD, "MultisampleQuality"), (BOOL, "Discard"), Out(Pointer(PDIRECT3DSURFACE9), "ppSurface"), Out(Pointer(HANDLE), "pSharedHandle"), (D3DUSAGE, "Usage")]),
+    Method(HRESULT, "CreateDepthStencilSurfaceEx", [(UINT, "Width"), (UINT, "Height"), (D3DFORMAT, "Format"), (D3DMULTISAMPLE_TYPE, "MultiSample"), (DWORD, "MultisampleQuality"), (BOOL, "Discard"), Out(Pointer(PDIRECT3DSURFACE9), "ppSurface"), (Pointer(HANDLE), "pSharedHandle"), (D3DUSAGE, "Usage")]),
     Method(HRESULT, "ResetEx", [Out(Pointer(D3DPRESENT_PARAMETERS), "pPresentationParameters"), Out(Pointer(D3DDISPLAYMODEEX), "pFullscreenDisplayMode")]),
-    Method(HRESULT, "GetDisplayModeEx", [(UINT, "iSwapChain"), Out(Pointer(D3DDISPLAYMODEEX), "pMode"), Out(Pointer(D3DDISPLAYROTATION), "pRotation")]),
+    Method(HRESULT, "GetDisplayModeEx", [(UINT, "iSwapChain"), Out(Pointer(D3DDISPLAYMODEEX), "pMode"), Out(Pointer(D3DDISPLAYROTATION), "pRotation")], sideeffects=False),
 ]
 
 IDirect3DSwapChain9Ex.methods += [
-    Method(HRESULT, "GetLastPresentCount", [Out(Pointer(UINT), "pLastPresentCount")]),
-    Method(HRESULT, "GetPresentStats", [Out(Pointer(D3DPRESENTSTATS), "pPresentationStatistics")]),
-    Method(HRESULT, "GetDisplayModeEx", [Out(Pointer(D3DDISPLAYMODEEX), "pMode"), Out(Pointer(D3DDISPLAYROTATION), "pRotation")]),
+    Method(HRESULT, "GetLastPresentCount", [Out(Pointer(UINT), "pLastPresentCount")], sideeffects=False),
+    Method(HRESULT, "GetPresentStats", [Out(Pointer(D3DPRESENTSTATS), "pPresentationStatistics")], sideeffects=False),
+    Method(HRESULT, "GetDisplayModeEx", [Out(Pointer(D3DDISPLAYMODEEX), "pMode"), Out(Pointer(D3DDISPLAYROTATION), "pRotation")], sideeffects=False),
 ]
 
 d3d9 = API("d3d9")
 d3d9.addFunctions([
     StdFunction(PDIRECT3D9, "Direct3DCreate9", [(UINT, "SDKVersion")], fail='NULL'),
     StdFunction(HRESULT, "Direct3DCreate9Ex", [(UINT, "SDKVersion"), Out(Pointer(PDIRECT3D9EX), "ppD3D")], fail='D3DERR_NOTAVAILABLE'),
-    StdFunction(Int, "D3DPERF_BeginEvent", [(D3DCOLOR, "col"), (LPCWSTR, "wszName")], fail='-1'),
-    StdFunction(Int, "D3DPERF_EndEvent", [], fail='-1'),
-    StdFunction(Void, "D3DPERF_SetMarker", [(D3DCOLOR, "col"), (LPCWSTR, "wszName")]),
-    StdFunction(Void, "D3DPERF_SetRegion", [(D3DCOLOR, "col"), (LPCWSTR, "wszName")]),
-    StdFunction(BOOL, "D3DPERF_QueryRepeatFrame", [], fail='FALSE'),
-    StdFunction(Void, "D3DPERF_SetOptions", [(DWORD, "dwOptions")]),
-    StdFunction(DWORD, "D3DPERF_GetStatus", [], fail='0'),
+    StdFunction(Int, "D3DPERF_BeginEvent", [(D3DCOLOR, "col"), (LPCWSTR, "wszName")], fail='-1', sideeffects=False),
+    StdFunction(Int, "D3DPERF_EndEvent", [], fail='-1', sideeffects=False),
+    StdFunction(Void, "D3DPERF_SetMarker", [(D3DCOLOR, "col"), (LPCWSTR, "wszName")], sideeffects=False),
+    StdFunction(Void, "D3DPERF_SetRegion", [(D3DCOLOR, "col"), (LPCWSTR, "wszName")], sideeffects=False),
+    StdFunction(BOOL, "D3DPERF_QueryRepeatFrame", [], fail='FALSE', sideeffects=False),
+    StdFunction(Void, "D3DPERF_SetOptions", [(DWORD, "dwOptions")], sideeffects=False),
+    StdFunction(DWORD, "D3DPERF_GetStatus", [], fail='0', sideeffects=False),
 ])
index 6aa4089f6d0984880f475bf57a87d75fc0d2cd5e..c74d3111bca9aae9659d99be97c6fa2db7285bb6 100644 (file)
@@ -134,8 +134,19 @@ class IntPointer(Type):
         return visitor.visitIntPointer(self, *args, **kwargs)
 
 
+class ObjPointer(Type):
+    '''Pointer to an object.'''
+
+    def __init__(self, type):
+        Type.__init__(self, type.expr + " *", 'P' + type.tag)
+        self.type = type
+
+    def visit(self, visitor, *args, **kwargs):
+        return visitor.visitObjPointer(self, *args, **kwargs)
+
+
 class LinearPointer(Type):
-    '''Integer encoded as a pointer.'''
+    '''Pointer to a linear range of memory.'''
 
     def __init__(self, type, size = None):
         Type.__init__(self, type.expr + " *", 'P' + type.tag)
@@ -146,6 +157,17 @@ class LinearPointer(Type):
         return visitor.visitLinearPointer(self, *args, **kwargs)
 
 
+class Reference(Type):
+    '''C++ references.'''
+
+    def __init__(self, type):
+        Type.__init__(self, type.expr + " &", 'R' + type.tag)
+        self.type = type
+
+    def visit(self, visitor, *args, **kwargs):
+        return visitor.visitReference(self, *args, **kwargs)
+
+
 class Handle(Type):
 
     def __init__(self, name, type, range=None, key=None):
@@ -250,17 +272,12 @@ class Alias(Type):
     def visit(self, visitor, *args, **kwargs):
         return visitor.visitAlias(self, *args, **kwargs)
 
-
-def Out(type, name):
-    arg = Arg(type, name, output=True)
-    return arg
-
-
 class Arg:
 
-    def __init__(self, type, name, output=False):
+    def __init__(self, type, name, input=True, output=False):
         self.type = type
         self.name = name
+        self.input = input
         self.output = output
         self.index = None
 
@@ -268,6 +285,16 @@ class Arg:
         return '%s %s' % (self.type, self.name)
 
 
+def In(type, name):
+    return Arg(type, name, input=True, output=False)
+
+def Out(type, name):
+    return Arg(type, name, input=False, output=True)
+
+def InOut(type, name):
+    return Arg(type, name, input=True, output=True)
+
+
 class Function:
 
     # 0-3 are reserved to memcpy, malloc, free, and realloc
@@ -361,8 +388,8 @@ class Interface(Type):
 
 class Method(Function):
 
-    def __init__(self, type, name, args, const=False):
-        Function.__init__(self, type, name, args, call = '__stdcall')
+    def __init__(self, type, name, args, const=False, sideeffects=True):
+        Function.__init__(self, type, name, args, call = '__stdcall', sideeffects=sideeffects)
         for index in range(len(self.args)):
             self.args[index].index = index + 1
         self.const = const
@@ -472,9 +499,15 @@ class Visitor:
     def visitIntPointer(self, pointer, *args, **kwargs):
         raise NotImplementedError
 
+    def visitObjPointer(self, pointer, *args, **kwargs):
+        raise NotImplementedError
+
     def visitLinearPointer(self, pointer, *args, **kwargs):
         raise NotImplementedError
 
+    def visitReference(self, reference, *args, **kwargs):
+        raise NotImplementedError
+
     def visitHandle(self, handle, *args, **kwargs):
         raise NotImplementedError
 
@@ -521,7 +554,11 @@ class Rebuilder(Visitor):
         return string
 
     def visitConst(self, const):
-        return Const(const.type)
+        const_type = self.visit(const.type)
+        if const_type is const.type:
+            return const
+        else:
+            return Const(const_type)
 
     def visitStruct(self, struct):
         members = [(self.visit(type), name) for type, name in struct.members]
@@ -543,23 +580,49 @@ class Rebuilder(Visitor):
         return Bitmask(type, bitmask.values)
 
     def visitPointer(self, pointer):
-        type = self.visit(pointer.type)
-        return Pointer(type)
+        pointer_type = self.visit(pointer.type)
+        if pointer_type is pointer.type:
+            return pointer
+        else:
+            return Pointer(pointer_type)
 
     def visitIntPointer(self, pointer):
         return pointer
 
+    def visitObjPointer(self, pointer):
+        pointer_type = self.visit(pointer.type)
+        if pointer_type is pointer.type:
+            return pointer
+        else:
+            return ObjPointer(pointer_type)
+
     def visitLinearPointer(self, pointer):
-        type = self.visit(pointer.type)
-        return LinearPointer(type, pointer.size)
+        pointer_type = self.visit(pointer.type)
+        if pointer_type is pointer.type:
+            return pointer
+        else:
+            return LinearPointer(pointer_type)
+
+    def visitReference(self, reference):
+        reference_type = self.visit(reference.type)
+        if reference_type is reference.type:
+            return reference
+        else:
+            return Reference(reference_type)
 
     def visitHandle(self, handle):
-        type = self.visit(handle.type)
-        return Handle(handle.name, type, range=handle.range, key=handle.key)
+        handle_type = self.visit(handle.type)
+        if handle_type is handle.type:
+            return handle
+        else:
+            return Handle(handle.name, handle_type, range=handle.range, key=handle.key)
 
     def visitAlias(self, alias):
-        type = self.visit(alias.type)
-        return Alias(alias.expr, type)
+        alias_type = self.visit(alias.type)
+        if alias_type is alias.type:
+            return alias
+        else:
+            return Alias(alias.expr, alias_type)
 
     def visitOpaque(self, opaque):
         return opaque
@@ -622,9 +685,15 @@ class Collector(Visitor):
     def visitIntPointer(self, pointer):
         pass
 
+    def visitObjPointer(self, pointer):
+        self.visit(pointer.type)
+
     def visitLinearPointer(self, pointer):
         self.visit(pointer.type)
 
+    def visitReference(self, reference):
+        self.visit(reference.type)
+
     def visitHandle(self, handle):
         self.visit(handle.type)
 
diff --git a/specs/tags.vim b/specs/tags.vim
new file mode 100644 (file)
index 0000000..627aad3
--- /dev/null
@@ -0,0 +1,38 @@
+s/\<__deref_out_bcount\>([^)]*)/[out]/g
+s/\<__deref_out_bcount\>([^)]*)/[out]/g
+s/\<__deref_out_bcount\>([^)]*)/[out]/g
+s/\<__field_ecount\>([^)]*)//g
+s/\<__field_ecount\>([^)]*)//g
+s/\<__field_ecount\>([^)]*)//g
+s/\<__in\>//g
+s/\<__in_bcount\>([^)]*)//g
+s/\<__in_bcount\>([^)]*)//g
+s/\<__in_ecount\>([^)]*)//g
+s/\<__in_ecount\>([^)]*)//g
+s/\<__in_ecount\>([^)]*)//g
+s/\<__in_ecount_opt\>([^)]*)//g
+s/\<__in_ecount_opt\>([^)]*)//g
+s/\<__in_ecount\>([^)]*)//g
+s/\<__in_ecount\>([^)]*)//g
+s/\<__in_opt\>//g
+s/\<__inout\>//g
+s/\<__in_z\>//g
+s/\<__in_z_opt\>//g
+s/\<__maybenull\>//g
+s/\<__notnull\>//g
+s/\<__nullterminated\>//g
+s/\<__out\>/[out]/g
+s/\<__out_bcount\>([^)]*)/[out]/g
+s/\<__out_ecount\>([^)]*)/[out]/g
+s/\<__out_ecount\>([^)]*)/[out]/g
+s/\<__out_ecount\>([^)]*)/[out]/g
+s/\<__out_ecount_opt\>([^)]*)/[out]/g
+s/\<__out_ecount_opt\>([^)]*)/[out]/g
+s/\<__out_ecount_opt\>([^)]*)/[out]/g
+s/\<__out_ecount_opt\>([^)]*)/[out]/g
+s/\<__out_ecount\>([^)]*)/[out]/g
+s/\<__out_ecount_z\>([^)]*)/[out]/g
+s/\<__out_ecount_z\>([^)]*)/[out]/g
+s/\<__out_ecount_z\>([^)]*)/[out]/g
+s/\<__out_opt\>/[out]/g
+s/\<__out_z\>/[out]/g
index 017cf5f0e527dab0094998a44326c6404e638f1e..e5df0f9d3f81e7800b1a9a5ff2729a0ecb1ea743 100644 (file)
@@ -74,10 +74,14 @@ HRESULT = Alias("HRESULT", Int)
 VOID = Void
 PVOID = Opaque("PVOID")
 LPVOID = PVOID
-HANDLE = Opaque("HANDLE")
-HWND = Opaque("HWND")
-HDC = Opaque("HDC")
-HMONITOR = Opaque("HMONITOR")
+
+def DECLARE_HANDLE(expr):
+    return Handle(expr, IntPointer(expr))
+
+HANDLE = DECLARE_HANDLE("HANDLE")
+HWND = DECLARE_HANDLE("HWND")
+HDC = DECLARE_HANDLE("HDC")
+HMONITOR = DECLARE_HANDLE("HMONITOR")
 
 GUID = Struct("GUID", [
     (DWORD, "Data1"),
@@ -87,16 +91,13 @@ GUID = Struct("GUID", [
 ])
 LPGUID = Pointer(GUID)
 
-#REFGUID = Alias("REFGUID", Pointer(GUID))
-REFGUID = Alias("REFGUID", GUID)
+REFGUID = Alias("REFGUID", Reference(GUID))
 
 IID = Alias("IID", GUID)
-#REFIID = Alias("REFIID", Pointer(IID))
-REFIID = Alias("REFIID", IID)
+REFIID = Alias("REFIID", Reference(IID))
 
 CLSID = Alias("CLSID", GUID)
-#REFCLSID = Alias("REFCLSID", Pointer(CLSID))
-REFCLSID = Alias("REFCLSID", CLSID)
+REFCLSID = Alias("REFCLSID", Reference(CLSID))
 
 LUID = Struct("LUID", [
     (DWORD, "LowPart"),
@@ -146,7 +147,7 @@ RGNDATA = Struct("RGNDATA", [
 ])
 LPRGNDATA = Pointer(RGNDATA)
 
-HMODULE = Opaque("HMODULE")
+HMODULE = DECLARE_HANDLE("HMODULE")
 
 IUnknown = Interface("IUnknown")
 
index 397fa9d80c953e29eba05f772f129a47a3f65d1e..4d6d97450501b12280740aecbd06b45a9d22979e 100644 (file)
--- a/trace.py
+++ b/trace.py
@@ -108,12 +108,18 @@ class ComplexValueSerializer(stdapi.OnceVisitor):
     def visitIntPointer(self, pointer):
         pass
 
+    def visitObjPointer(self, pointer):
+        self.visit(pointer.type)
+
     def visitLinearPointer(self, pointer):
         self.visit(pointer.type)
 
     def visitHandle(self, handle):
         self.visit(handle.type)
 
+    def visitReference(self, reference):
+        self.visit(reference.type)
+
     def visitAlias(self, alias):
         self.visit(alias.type)
 
@@ -208,9 +214,15 @@ class ValueSerializer(stdapi.Visitor):
     def visitIntPointer(self, pointer, instance):
         print '    trace::localWriter.writeOpaque((const void *)%s);' % instance
 
+    def visitObjPointer(self, pointer, instance):
+        print '    trace::localWriter.writeOpaque((const void *)%s);' % instance
+
     def visitLinearPointer(self, pointer, instance):
         print '    trace::localWriter.writeOpaque((const void *)%s);' % instance
 
+    def visitReference(self, reference, instance):
+        self.visit(reference.type, instance)
+
     def visitHandle(self, handle, instance):
         self.visit(handle.type, instance)
 
@@ -271,9 +283,17 @@ class ValueWrapper(stdapi.Visitor):
     def visitIntPointer(self, pointer, instance):
         pass
 
+    def visitObjPointer(self, pointer, instance):
+        print "    if (%s) {" % instance
+        self.visit(pointer.type, "*" + instance)
+        print "    }"
+    
     def visitLinearPointer(self, pointer, instance):
         pass
 
+    def visitReference(self, reference, instance):
+        self.visit(reference.type, instance)
+    
     def visitHandle(self, handle, instance):
         self.visit(handle.type, instance)