]> 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

1  2 
CMakeLists.txt
d3d9trace.py
specs/stdapi.py
trace.py

diff --combined CMakeLists.txt
index e65c529f322a39b6047c3e406eb82fbd90fadb66,7ac9676a8fff9bd208ef76a47edbec0b0496c669..c87ef70f7e959a31c26801681d352885cc33c08e
@@@ -178,6 -178,12 +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 +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
@@@ -379,37 -386,6 +386,37 @@@ if (WIN32
          install (TARGETS d3d10 LIBRARY DESTINATION ${WRAPPER_INSTALL_DIR})
      endif (DirectX_D3D10_INCLUDE_DIR)
  
 +    # d2d1.dll, dwrite.dll
 +    if (DirectX_D2D1_INCLUDE_DIR)
 +        include_directories (SYSTEM ${DirectX_D2D1_INCLUDE_DIR})
 +
 +        add_custom_command (
 +            OUTPUT d2d1trace.cpp
 +            COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/d2d1trace.py > ${CMAKE_CURRENT_BINARY_DIR}/d2d1trace.cpp
 +            DEPENDS d2d1trace.py trace.py specs/d2d1.py specs/d2d1.py specs/d2dbasetypes.py specs/d2derr.py specs/dwrite.py specs/dcommon.py specs/dxgi.py specs/dxgitype.py specs/dxgiformat.py specs/winapi.py specs/stdapi.py
 +        )
 +        add_library (d2d1 MODULE specs/d2d1.def d2d1trace.cpp)
 +        set_target_properties (d2d1
 +            PROPERTIES PREFIX ""
 +            RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/wrappers
 +            LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/wrappers
 +        )
 +        install (TARGETS d2d1 LIBRARY DESTINATION wrappers)
 +
 +        add_custom_command (
 +            OUTPUT dwritetrace.cpp
 +            COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/dwritetrace.py > ${CMAKE_CURRENT_BINARY_DIR}/dwritetrace.cpp
 +            DEPENDS dwritetrace.py trace.py specs/d2d1.py specs/d2d1.py specs/d2dbasetypes.py specs/d2derr.py specs/dwrite.py specs/dcommon.py specs/dxgi.py specs/dxgitype.py specs/dxgiformat.py specs/winapi.py specs/stdapi.py
 +        )
 +        add_library (dwrite MODULE specs/dwrite.def dwritetrace.cpp)
 +        set_target_properties (dwrite
 +            PROPERTIES PREFIX ""
 +            RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/wrappers
 +            LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/wrappers
 +        )
 +        install (TARGETS dwrite LIBRARY DESTINATION wrappers)
 +    endif (DirectX_D2D1_INCLUDE_DIR)
 +
      # opengl32.dll
      add_custom_command (
          OUTPUT wgltrace.cpp
diff --combined d3d9trace.py
index a40ae7f5f1eed1bcb189a3ea78ed848ec0e1d88f,c408b497b48f9aad156f6e23b5cb78c0f4013799..ae4acd039fe39f2b274afdfa46f9f624f003611f
@@@ -42,27 -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, method):
 +    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, method)
 +        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;'
diff --combined specs/stdapi.py
index b6bab8f542e2744ee642b3a7ffafa4663e05d9f1,5ba621fff35ceb7e26df9d94d0d303240d77e68c..0e3fe236154d554276f9bf986168b1029b08b9b3
@@@ -349,43 -349,26 +349,41 @@@ class Interface(Type)
          for method in self.methods:
              yield method
          raise StopIteration
 +    
 +    def iterBaseMethods(self):
 +        if self.base is not None:
 +            for iface, method in self.base.iterBaseMethods():
 +                yield iface, method
 +        for method in self.methods:
 +            yield self, method
 +        raise StopIteration
  
  
  class Method(Function):
  
 -    def __init__(self, type, name, args):
 +    def __init__(self, type, name, args, const=False):
          Function.__init__(self, type, name, args, call = '__stdcall')
          for index in range(len(self.args)):
              self.args[index].index = index + 1
 +        self.const = const
 +
 +    def prototype(self, name=None):
 +        s = Function.prototype(self, name)
 +        if self.const:
 +            s += ' const'
 +        return s
  
  
  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 -549,9 +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 -645,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:
                  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 -706,10 +721,10 @@@ ULongLong = Literal("unsigned long long
  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 --combined trace.py
index 38005008941efeb4e3744cbecf1ac3a9a5a01a66,a9395339c2981b054a612fbbacdcd43c2adcf4ec..fe35bea19699730a47abe98287f3f2382f8db90b
+++ b/trace.py
@@@ -148,10 -148,20 +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 +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
          print '%s::~%s() {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface))
          print '}'
          print
 -        for method in interface.iterMethods():
 -            self.implementWrapperInterfaceMethod(interface, method)
 +        for base, method in interface.iterBaseMethods():
 +            self.implementWrapperInterfaceMethod(interface, base, method)
          print
  
 -    def implementWrapperInterfaceMethod(self, interface, method):
 +    def implementWrapperInterfaceMethod(self, interface, base, method):
          print method.prototype(getWrapperInterfaceName(interface) + '::' + method.name) + ' {'
          if method.type is not stdapi.Void:
              print '    %s __result;' % method.type
      
 -        self.implementWrapperInterfaceMethodBody(interface, method)
 +        self.implementWrapperInterfaceMethodBody(interface, base, method)
      
          if method.type is not stdapi.Void:
              print '    return __result;'
          print '}'
          print
  
 -    def implementWrapperInterfaceMethodBody(self, interface, method):
 +    def implementWrapperInterfaceMethodBody(self, interface, base, method):
          print '    static const char * __args[%u] = {%s};' % (len(method.args) + 1, ', '.join(['"this"'] + ['"%s"' % arg.name for arg in method.args]))
          print '    static const trace::FunctionSig __sig = {%u, "%s", %u, __args};' % (method.id, interface.name + '::' + method.name, len(method.args) + 1)
          print '    unsigned __call = trace::localWriter.beginEnter(&__sig);'
          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, method)
 +        self.invokeMethod(interface, base, method)
  
          print '    trace::localWriter.beginLeave(__call);'
          for arg in method.args:
              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, method):
 +    def invokeMethod(self, interface, base, method):
          if method.type is stdapi.Void:
              result = ''
          else:
              result = '__result = '
 -        print '    %sm_pInstance->%s(%s);' % (result, method.name, ', '.join([str(arg.name) for arg in method.args]))
 +        print '    %sstatic_cast<%s *>(m_pInstance)->%s(%s);' % (result, base, method.name, ', '.join([str(arg.name) for arg in method.args]))
      
      def emit_memcpy(self, dest, src, length):
          print '        unsigned __call = trace::localWriter.beginEnter(&trace::memcpy_sig);'