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
endif ()
add_library (common STATIC
+ common/trace_callset.cpp
common/trace_dump.cpp
common/trace_file.cpp
common/trace_file_read.cpp
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
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;'
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.'''
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
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)
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")
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)
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);'