From: José Fonseca Date: Mon, 23 Jan 2012 00:30:35 +0000 (+0000) Subject: D3D retrace checkpoint. X-Git-Url: https://git.cworth.org/git?p=apitrace;a=commitdiff_plain;h=8e3c2c0d01c7ec5479845fedc053da00fa88e76a D3D retrace checkpoint. --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 24e2afc..a141e10 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -613,6 +613,21 @@ if (EGL_FOUND AND X11_FOUND AND NOT WIN32 AND NOT APPLE) install (TARGETS eglretrace RUNTIME DESTINATION bin) endif () +if (WIN32 AND DirectX_D3DX9_INCLUDE_DIR) + 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 + d3dretrace_main.cpp + d3dretrace_d3d9.cpp + ) +endif () + ############################################################################## # CLI diff --git a/d3dretrace.hpp b/d3dretrace.hpp new file mode 100644 index 0000000..cac94cc --- /dev/null +++ b/d3dretrace.hpp @@ -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 index 0000000..21c87b9 --- /dev/null +++ b/d3dretrace.py @@ -0,0 +1,52 @@ +########################################################################## +# +# 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' + + +if __name__ == '__main__': + print r''' +#include + +#include + +#include "d3d9imports.hpp" +#include "d3dretrace.hpp" + + +''' + retracer = D3DRetracer() + retracer.retraceApi(d3d9) diff --git a/d3dretrace_main.cpp b/d3dretrace_main.cpp new file mode 100644 index 0000000..133f3a7 --- /dev/null +++ b/d3dretrace_main.cpp @@ -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 + +#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 */ diff --git a/glretrace.hpp b/glretrace.hpp index 41e2997..f7d244f 100644 --- a/glretrace.hpp +++ b/glretrace.hpp @@ -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; diff --git a/glretrace_main.cpp b/glretrace_main.cpp index 1208632..d80775f 100644 --- a/glretrace_main.cpp +++ b/glretrace_main.cpp @@ -39,7 +39,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; diff --git a/retrace.cpp b/retrace.cpp index 849c597..fe0694d 100644 --- a/retrace.cpp +++ b/retrace.cpp @@ -34,6 +34,9 @@ namespace retrace { +trace::Parser parser; + + int verbosity = 0; diff --git a/retrace.hpp b/retrace.hpp index a59a6eb..3367141 100644 --- a/retrace.hpp +++ b/retrace.hpp @@ -33,11 +33,15 @@ #include #include "trace_model.hpp" +#include "trace_parser.hpp" namespace retrace { +extern trace::Parser parser; + + /** * Handle map. * diff --git a/retrace.py b/retrace.py index 0e28d18..15cdaf5 100644 --- a/retrace.py +++ b/retrace.py @@ -207,11 +207,41 @@ 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): if not function.sideeffects: print ' (void)call;' return + self.deserializeArgs(function) + + self.invokeFunction(function) + + self.swizzleValues(function) + + def retraceInterfaceMethodBody(self, interface, method): + if not method.sideeffects: + print ' (void)call;' + return + + self.deserializeThisPointer(interface) + + self.deserializeArgs(method) + + self.invokeInterfaceMethod(interface, method) + + self.swizzleValues(method) + + def deserializeThisPointer(self, interface): + print ' %s *_this;' % (interface.name,) + # FIXME + + def deserializeArgs(self, function): success = True for arg in function.args: arg_type = ConstRemover().visit(arg.type) @@ -222,13 +252,17 @@ class Retracer: try: self.extractArg(function, arg, arg_type, lvalue, rvalue) except NotImplementedError: - success = False + success = False print ' %s = 0; // FIXME' % arg.name + 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) @@ -245,9 +279,6 @@ class Retracer: self.regiterSwizzledValue(function.type, lvalue, rvalue) except NotImplementedError: 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) {' @@ -274,32 +305,27 @@ 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: - self.retraceFunction(function) - - print 'const retrace::Entry %s[] = {' % self.table_name - for function in functions: - print ' {"%s", &retrace_%s},' % (function.name, function.name) - print ' {NULL, NULL}' - print '};' - print - - def retraceApi(self, api): print '#include "trace_parser.hpp"' print '#include "retrace.hpp"' print - types = api.all_types() + types = api.getAllTypes() handles = [type for type in types if isinstance(type, stdapi.Handle)] handle_names = set() for handle in handles: @@ -312,5 +338,21 @@ class Retracer: handle_names.add(handle.name) print - self.retraceFunctions(api.functions) + functions = filter(self.filterFunction, api.functions) + for function in functions: + self.retraceFunction(function) + interfaces = api.getAllInterfaces() + for interface in interfaces: + for method in interface.iterMethods(): + self.retraceInterfaceMethod(interface, method) + + print 'const retrace::Entry %s[] = {' % self.table_name + for function in functions: + print ' {"%s", &retrace_%s},' % (function.name, function.name) + for interface in interfaces: + for method in interface.iterMethods(): + print ' {"%s::%s", &retrace_%s__%s},' % (interface.name, method.name, interface.name, method.name) + print ' {NULL, NULL}' + print '};' + print diff --git a/specs/stdapi.py b/specs/stdapi.py index 44d4680..61e2b21 100644 --- a/specs/stdapi.py +++ b/specs/stdapi.py @@ -551,6 +551,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 @@ -644,7 +647,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: @@ -658,6 +661,14 @@ class API: collector.visit(method.type) return collector.types + def getAllInterfaces(self): + types = self.getAllTypes() + interfaces = [type for type in types if isinstance(type, Interface)] + for interface in self.interfaces: + if interface not in interfaces: + interfaces.append(interface) + return interfaces + def addFunction(self, function): self.functions.append(function) diff --git a/trace.py b/trace.py index 4d2f055..0d973a2 100644 --- a/trace.py +++ b/trace.py @@ -321,13 +321,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