]> git.cworth.org Git - apitrace/blob - gltrace.py
0aa60cd6e81fb84643053d4d7436e3be265dddf8
[apitrace] / gltrace.py
1 ##########################################################################
2 #
3 # Copyright 2008-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 """GL tracing generator."""
28
29
30 import stdapi
31 import glapi
32 from glxapi import glxapi
33 from trace import Tracer, dump_instance
34
35
36 class TypeGetter(stdapi.Visitor):
37     '''Determine which glGet*v function that matches the specified type.'''
38
39     def visit_const(self, const):
40         return self.visit(const.type)
41
42     def visit_alias(self, alias):
43         if alias.expr == 'GLboolean':
44             return 'glGetBooleanv', alias.expr
45         elif alias.expr == 'GLdouble':
46             return 'glGetDoublev', alias.expr
47         elif alias.expr == 'GLfloat':
48             return 'glGetFloatv', alias.expr
49         elif alias.expr in ('GLint', 'GLsizei'):
50             return 'glGetIntegerv', 'GLint'
51         else:
52             print alias.expr
53             assert False
54     
55     def visit_enum(self, enum):
56         return 'glGetIntegerv', 'GLint'
57
58     def visit_bitmask(self, bitmask):
59         return 'glGetIntegerv', 'GLint'
60
61     def visit_opaque(self, pointer):
62         return 'glGetPointerv', 'GLvoid *'
63
64
65 class GlTracer(Tracer):
66
67     def header(self, api):
68         Tracer.header(self, api)
69         self.state_tracker_decl(api)
70
71     def footer(self, api):
72         Tracer.footer(self, api)
73         self.state_tracker_impl(api)
74
75     arrays = [
76         ("Vertex", "VERTEX"),
77         ("Normal", "NORMAL"),
78         ("Color", "COLOR"),
79         ("Index", "INDEX"),
80         ("TexCoord", "TEXTURE_COORD"),
81         ("EdgeFlag", "EDGE_FLAG"),
82         ("FogCoord", "FOG_COORD"),
83         ("SecondaryColor", "SECONDARY_COLOR"),
84     ]
85
86     def state_tracker_decl(self, api):
87         # A simple state tracker to track the pointer values
88
89         print 'static void __trace_arrays(GLsizei maxindex);'
90         print
91     
92     array_pointer_function_names = set((
93         "glVertexPointer",
94         "glNormalPointer",
95         "glColorPointer",
96         "glIndexPointer",
97         "glTexCoordPointer",
98         "glEdgeFlagPointer",
99         "glFogCoordPointer",
100         "glSecondaryColorPointer",
101
102         "glInterleavedArrays",
103
104         #"glVertexPointerEXT",
105         #"glNormalPointerEXT",
106         #"glColorPointerEXT",
107         #"glIndexPointerEXT",
108         #"glTexCoordPointerEXT",
109         #"glEdgeFlagPointerEXT",
110         #"glFogCoordPointerEXT",
111         #"glSecondaryColorPointerEXT",
112
113         #"glVertexAttribPointer",
114         #"glVertexAttribPointerARB",
115         #"glVertexAttribPointerNV",
116         #"glVertexAttribLPointer",
117         
118         #"glMatrixIndexPointerARB",
119     ))
120
121     draw_function_names = set((
122         'glDrawArrays',
123         'glDrawElements',
124         'glDrawRangeElements',
125     ))
126
127     def trace_function_impl_body(self, function):
128         # Defer tracing of array pointers
129         if function.name in self.array_pointer_function_names:
130             print '    GLint __array_buffer = 0;'
131             print '    __glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &__array_buffer);'
132             print '    if (!__array_buffer) {'
133             self.dispatch_function(function)
134             print '        return;'
135             print '    }'
136
137         if function.name in self.draw_function_names:
138             arg_names = ', '.join([arg.name for arg in function.args[1:]])
139             print '    __trace_arrays(__%s_maxindex(%s));' % (function.name, arg_names)
140         
141         Tracer.trace_function_impl_body(self, function)
142
143     def dump_arg_instance(self, function, arg):
144         if function.name in self.draw_function_names and arg.name == 'indices':
145             print '    Trace::LiteralBlob((const void *)%s, count*__gl_type_size(type));' % (arg.name)
146         else:
147             dump_instance(arg.type, arg.name)
148
149     def state_tracker_impl(self, api):
150         # A simple state tracker to track the pointer values
151
152         # update the state
153         print 'static void __trace_arrays(GLsizei maxindex)'
154         print '{'
155         for camelcase_name, uppercase_name in self.arrays:
156             function_name = 'gl%sPointer' % camelcase_name
157             enable_name = 'GL_%s_ARRAY' % uppercase_name
158             binding_name = 'GL_%s_ARRAY_BUFFER_BINDING' % uppercase_name
159             function = api.get_function_by_name(function_name)
160
161             print '    // %s' % function.name
162             print '    {'
163             print '        GLboolean __enabled = GL_FALSE;'
164             print '        __glGetBooleanv(%s, &__enabled);' % enable_name
165             print '        if (__enabled) {'
166             print '            GLint __binding = 0;'
167             print '            __glGetIntegerv(%s, &__binding);' % binding_name
168             print '            if (!__binding) {'
169
170             # Get the arguments via glGet*
171             for arg in function.args:
172                 arg_get_enum = 'GL_%s_ARRAY_%s' % (uppercase_name, arg.name.upper())
173                 arg_get_function, arg_type = TypeGetter().visit(arg.type)
174                 print '                %s %s = 0;' % (arg_type, arg.name)
175                 print '                __%s(%s, &%s);' % (arg_get_function, arg_get_enum, arg.name)
176             
177             arg_names = ', '.join([arg.name for arg in function.args[:-1]])
178             print '                size_t __size = __%s_size(%s, maxindex);' % (function.name, arg_names)
179
180             # Emit a fake function
181             print '                unsigned __call = Trace::BeginEnter(__%s_sig);' % (function.name,)
182             for arg in function.args:
183                 assert not arg.output
184                 print '                Trace::BeginArg(%u);' % (arg.index,)
185                 if arg.name != 'pointer':
186                     dump_instance(arg.type, arg.name)
187                 else:
188                     print '                Trace::LiteralBlob((const void *)%s, __size);' % (arg.name)
189                 print '                Trace::EndArg();'
190             
191             print '                Trace::EndEnter();'
192             print '                Trace::BeginLeave(__call);'
193             print '                Trace::EndLeave();'
194             print '            }'
195             print '        }'
196             print '    }'
197             print
198         print '}'
199         print
200
201
202
203
204
205
206