]> git.cworth.org Git - apitrace/blob - retrace.py
List GL_TEXTURE_xxx and GL_TEXTURE_BINDING_xxx params per texture unit.
[apitrace] / retrace.py
1 ##########################################################################
2 #
3 # Copyright 2010 VMware, Inc.
4 # All Rights Reserved.
5 #
6 # Permission is hereby granted, free of charge, to any person obtaining a copy
7 # of this software and associated documentation files (the "Software"), to deal
8 # in the Software without restriction, including without limitation the rights
9 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 # copies of the Software, and to permit persons to whom the Software is
11 # furnished to do so, subject to the following conditions:
12 #
13 # The above copyright notice and this permission notice shall be included in
14 # all copies or substantial portions of the Software.
15 #
16 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 # THE SOFTWARE.
23 #
24 ##########################################################################/
25
26
27 """Generic retracing code generator."""
28
29 import stdapi
30 import glapi
31 from codegen import *
32
33
34 class ConstRemover(stdapi.Rebuilder):
35
36     def visit_const(self, const):
37         return const.type
38
39     def visit_opaque(self, opaque):
40         return opaque
41
42
43 def handle_entry(handle, value):
44     if handle.key is None:
45         return "__%s_map[%s]" % (handle.name, value)
46     else:
47         key_name, key_type = handle.key
48         return "__%s_map[%s][%s]" % (handle.name, key_name, value)
49
50
51 class ValueExtractor(stdapi.Visitor):
52
53     def visit_literal(self, literal, lvalue, rvalue):
54         #if literal.format in ('Bool', 'UInt'):
55         print '    %s = (%s).to%s();' % (lvalue, rvalue, literal.format)
56
57     def visit_const(self, const, lvalue, rvalue):
58         self.visit(const.type, lvalue, rvalue)
59
60     def visit_alias(self, alias, lvalue, rvalue):
61         self.visit(alias.type, lvalue, rvalue)
62     
63     def visit_enum(self, enum, lvalue, rvalue):
64         print '    %s = (%s).toSInt();' % (lvalue, rvalue)
65
66     def visit_bitmask(self, bitmask, lvalue, rvalue):
67         self.visit(bitmask.type, lvalue, rvalue)
68
69     def visit_array(self, array, lvalue, rvalue):
70         print '    const Trace::Array *__a%s = dynamic_cast<const Trace::Array *>(&%s);' % (array.id, rvalue)
71         print '    if (__a%s) {' % (array.id)
72         length = '__a%s->values.size()' % array.id
73         print '        %s = new %s[%s];' % (lvalue, array.type, length)
74         index = '__j' + array.id
75         print '        for (size_t {i} = 0; {i} < {length}; ++{i}) {{'.format(i = index, length = length)
76         try:
77             self.visit(array.type, '%s[%s]' % (lvalue, index), '*__a%s->values[%s]' % (array.id, index))
78         finally:
79             print '        }'
80             print '    } else {'
81             print '        %s = NULL;' % lvalue
82             print '    }'
83     
84     def visit_pointer(self, pointer, lvalue, rvalue):
85         print '    const Trace::Array *__a%s = dynamic_cast<const Trace::Array *>(&%s);' % (pointer.id, rvalue)
86         print '    if (__a%s) {' % (pointer.id)
87         print '        %s = new %s;' % (lvalue, pointer.type)
88         try:
89             self.visit(pointer.type, '%s[0]' % (lvalue,), '*__a%s->values[0]' % (pointer.id,))
90         finally:
91             print '    } else {'
92             print '        %s = NULL;' % lvalue
93             print '    }'
94
95     def visit_handle(self, handle, lvalue, rvalue):
96         OpaqueValueExtractor().visit(handle.type, lvalue, rvalue);
97         new_lvalue = handle_entry(handle, lvalue)
98         print '    if (retrace::verbosity >= 2) {'
99         print '        std::cout << "%s " << size_t(%s) << " <- " << size_t(%s) << "\\n";' % (handle.name, lvalue, new_lvalue)
100         print '    }'
101         print '    %s = %s;' % (lvalue, new_lvalue)
102     
103     def visit_blob(self, blob, lvalue, rvalue):
104         print '    %s = static_cast<%s>((%s).toPointer());' % (lvalue, blob, rvalue)
105     
106     def visit_string(self, string, lvalue, rvalue):
107         print '    %s = (%s)((%s).toString());' % (lvalue, string.expr, rvalue)
108
109
110 class OpaqueValueExtractor(ValueExtractor):
111     '''Value extractor that also understands opaque values.
112
113     Normally opaque values can't be retraced, unless they are being extracted
114     in the context of handles.'''
115
116     def visit_opaque(self, opaque, lvalue, rvalue):
117         print '    %s = static_cast<%s>((%s).toPointer());' % (lvalue, opaque, rvalue)
118
119
120 class ValueWrapper(stdapi.Visitor):
121
122     def visit_literal(self, literal, lvalue, rvalue):
123         pass
124
125     def visit_alias(self, alias, lvalue, rvalue):
126         self.visit(alias.type, lvalue, rvalue)
127     
128     def visit_enum(self, enum, lvalue, rvalue):
129         pass
130
131     def visit_bitmask(self, bitmask, lvalue, rvalue):
132         pass
133
134     def visit_array(self, array, lvalue, rvalue):
135         print '    const Trace::Array *__a%s = dynamic_cast<const Trace::Array *>(&%s);' % (array.id, rvalue)
136         print '    if (__a%s) {' % (array.id)
137         length = '__a%s->values.size()' % array.id
138         index = '__j' + array.id
139         print '        for (size_t {i} = 0; {i} < {length}; ++{i}) {{'.format(i = index, length = length)
140         try:
141             self.visit(array.type, '%s[%s]' % (lvalue, index), '*__a%s->values[%s]' % (array.id, index))
142         finally:
143             print '        }'
144             print '    }'
145     
146     def visit_pointer(self, pointer, lvalue, rvalue):
147         print '    const Trace::Array *__a%s = dynamic_cast<const Trace::Array *>(&%s);' % (pointer.id, rvalue)
148         print '    if (__a%s) {' % (pointer.id)
149         try:
150             self.visit(pointer.type, '%s[0]' % (lvalue,), '*__a%s->values[0]' % (pointer.id,))
151         finally:
152             print '    }'
153     
154     def visit_handle(self, handle, lvalue, rvalue):
155         print '    %s __orig_result;' % handle.type
156         OpaqueValueExtractor().visit(handle.type, '__orig_result', rvalue);
157         if handle.range is None:
158             rvalue = "__orig_result"
159             entry = handle_entry(handle, rvalue) 
160             print "    %s = %s;" % (entry, lvalue)
161             print '    if (retrace::verbosity >= 2) {'
162             print '        std::cout << "{handle.name} " << {rvalue} << " -> " << {lvalue} << "\\n";'.format(**locals())
163             print '    }'
164         else:
165             i = '__h' + handle.id
166             lvalue = "%s + %s" % (lvalue, i)
167             rvalue = "__orig_result + %s" % (i,)
168             entry = handle_entry(handle, rvalue) 
169             print '    for ({handle.type} {i} = 0; {i} < {handle.range}; ++{i}) {{'.format(**locals())
170             print '        {entry} = {lvalue};'.format(**locals())
171             print '        if (retrace::verbosity >= 2) {'
172             print '            std::cout << "{handle.name} " << ({rvalue}) << " -> " << ({lvalue}) << "\\n";'.format(**locals())
173             print '        }'
174             print '    }'
175     
176     def visit_blob(self, blob, lvalue, rvalue):
177         pass
178     
179     def visit_string(self, string, lvalue, rvalue):
180         pass
181
182
183 class Retracer:
184
185     def retrace_function(self, function):
186         print 'static void retrace_%s(Trace::Call &call) {' % function.name
187         self.retrace_function_body(function)
188         print '}'
189         print
190
191     def retrace_function_body(self, function):
192         if not function.sideeffects:
193             print '    (void)call;'
194             return
195
196         success = True
197         for arg in function.args:
198             arg_type = ConstRemover().visit(arg.type)
199             #print '    // %s ->  %s' % (arg.type, arg_type)
200             print '    %s %s;' % (arg_type, arg.name)
201             rvalue = 'call.arg(%u)' % (arg.index,)
202             lvalue = arg.name
203             try:
204                 self.extract_arg(function, arg, arg_type, lvalue, rvalue)
205             except NotImplementedError:
206                 success = False
207                 print '    %s = 0; // FIXME' % arg.name
208         if not success:
209             print '    if (1) {'
210             self.fail_function(function)
211             print '    }'
212         self.call_function(function)
213         for arg in function.args:
214             if arg.output:
215                 arg_type = ConstRemover().visit(arg.type)
216                 rvalue = 'call.arg(%u)' % (arg.index,)
217                 lvalue = arg.name
218                 try:
219                     ValueWrapper().visit(arg_type, lvalue, rvalue)
220                 except NotImplementedError:
221                     print '   // FIXME: %s' % arg.name
222         if function.type is not stdapi.Void:
223             rvalue = '*call.ret'
224             lvalue = '__result'
225             try:
226                 ValueWrapper().visit(function.type, lvalue, rvalue)
227             except NotImplementedError:
228                 print '   // FIXME: result'
229
230     def fail_function(self, function):
231         print '    if (retrace::verbosity >= 0)'
232         print '        std::cerr << "warning: unsupported call %s\\n";' % function.name
233         print '    return;'
234
235     def extract_arg(self, function, arg, arg_type, lvalue, rvalue):
236         ValueExtractor().visit(arg_type, lvalue, rvalue)
237     
238     def extract_opaque_arg(self, function, arg, arg_type, lvalue, rvalue):
239         OpaqueValueExtractor().visit(arg_type, lvalue, rvalue)
240
241     def call_function(self, function):
242         arg_names = ", ".join([arg.name for arg in function.args])
243         if function.type is not stdapi.Void:
244             print '    %s __result;' % (function.type)
245             print '    __result = %s(%s);' % (function.name, arg_names)
246             print '    (void)__result;'
247         else:
248             print '    %s(%s);' % (function.name, arg_names)
249
250     def filter_function(self, function):
251         return True
252
253     def retrace_functions(self, functions):
254         functions = filter(self.filter_function, functions)
255
256         for function in functions:
257             self.retrace_function(function)
258
259         print 'void retrace::retrace_call(Trace::Call &call) {'
260         print '    const char *name = call.name();'
261         print
262
263         func_dict = dict([(function.name, function) for function in functions])
264
265         def handle_case(function_name):
266             function = func_dict[function_name]
267             print '        retrace_%s(call);' % function.name
268             print '        return;'
269     
270         string_switch('name', func_dict.keys(), handle_case)
271
272         print '    retrace_unknown(call);'
273         print '}'
274         print
275
276
277     def retrace_api(self, api):
278
279         print '#include "trace_parser.hpp"'
280         print '#include "retrace.hpp"'
281         print
282
283         types = api.all_types()
284         handles = [type for type in types if isinstance(type, stdapi.Handle)]
285         handle_names = set()
286         for handle in handles:
287             if handle.name not in handle_names:
288                 if handle.key is None:
289                     print 'static retrace::map<%s> __%s_map;' % (handle.type, handle.name)
290                 else:
291                     key_name, key_type = handle.key
292                     print 'static std::map<%s, retrace::map<%s> > __%s_map;' % (key_type, handle.type, handle.name)
293                 handle_names.add(handle.name)
294         print
295
296         self.retrace_functions(api.functions)
297