]> git.cworth.org Git - apitrace/blob - gltrace.py
Merge branch 'drawarrays'
[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         # Whether we need user arrays
88         print 'static inline bool __need_user_arrays(void)'
89         print '{'
90         for camelcase_name, uppercase_name in self.arrays:
91             function_name = 'gl%sPointer' % camelcase_name
92             enable_name = 'GL_%s_ARRAY' % uppercase_name
93             binding_name = 'GL_%s_ARRAY_BUFFER_BINDING' % uppercase_name
94             print '    // %s' % function_name
95             print '    {'
96             print '        GLboolean __enabled = GL_FALSE;'
97             print '        __glGetBooleanv(%s, &__enabled);' % enable_name
98             print '        if (__enabled) {'
99             print '            GLint __binding = 0;'
100             print '            __glGetIntegerv(%s, &__binding);' % binding_name
101             print '            if (!__binding) {'
102             print '                return true;'
103             print '            }'
104             print '        }'
105             print '    }'
106             print
107         print '    return false;'
108         print '}'
109         print
110
111         print 'static void __trace_user_arrays(GLuint maxindex);'
112         print
113     
114     array_pointer_function_names = set((
115         "glVertexPointer",
116         "glNormalPointer",
117         "glColorPointer",
118         "glIndexPointer",
119         "glTexCoordPointer",
120         "glEdgeFlagPointer",
121         "glFogCoordPointer",
122         "glSecondaryColorPointer",
123
124         "glInterleavedArrays",
125
126         #"glVertexPointerEXT",
127         #"glNormalPointerEXT",
128         #"glColorPointerEXT",
129         #"glIndexPointerEXT",
130         #"glTexCoordPointerEXT",
131         #"glEdgeFlagPointerEXT",
132         #"glFogCoordPointerEXT",
133         #"glSecondaryColorPointerEXT",
134
135         #"glVertexAttribPointer",
136         #"glVertexAttribPointerARB",
137         #"glVertexAttribPointerNV",
138         #"glVertexAttribLPointer",
139         
140         #"glMatrixIndexPointerARB",
141     ))
142
143     draw_function_names = set((
144         'glDrawArrays',
145         'glDrawElements',
146         'glDrawRangeElements',
147     ))
148
149     def trace_function_impl_body(self, function):
150         # Defer tracing of user array pointers...
151         if function.name in self.array_pointer_function_names:
152             print '    GLint __array_buffer = 0;'
153             print '    __glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &__array_buffer);'
154             print '    if (!__array_buffer) {'
155             self.dispatch_function(function)
156             print '        return;'
157             print '    }'
158
159         # ... to the draw calls
160         if function.name in self.draw_function_names:
161             print '    if (__need_user_arrays()) {'
162             arg_names = ', '.join([arg.name for arg in function.args[1:]])
163             print '        GLuint maxindex = __%s_maxindex(%s);' % (function.name, arg_names)
164             print '        __trace_user_arrays(maxindex);'
165             print '    }'
166         
167         Tracer.trace_function_impl_body(self, function)
168
169     def dump_arg_instance(self, function, arg):
170         if function.name in self.draw_function_names and arg.name == 'indices':
171             print '    GLint __element_array_buffer = 0;'
172             print '    __glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &__element_array_buffer);'
173             print '    if (!__element_array_buffer) {'
174             print '        Trace::LiteralBlob((const void *)%s, count*__gl_type_size(type));' % (arg.name)
175             print '    } else {'
176             print '        Trace::LiteralOpaque((const void *)%s);' % (arg.name)
177             print '    }'
178             return
179
180         Tracer.dump_arg_instance(self, function, arg)
181
182     def state_tracker_impl(self, api):
183         # A simple state tracker to track the pointer values
184
185         # update the state
186         print 'static void __trace_user_arrays(GLuint maxindex)'
187         print '{'
188         for camelcase_name, uppercase_name in self.arrays:
189             function_name = 'gl%sPointer' % camelcase_name
190             enable_name = 'GL_%s_ARRAY' % uppercase_name
191             binding_name = 'GL_%s_ARRAY_BUFFER_BINDING' % uppercase_name
192             function = api.get_function_by_name(function_name)
193
194             print '    // %s' % function.name
195             print '    {'
196             print '        GLboolean __enabled = GL_FALSE;'
197             print '        __glGetBooleanv(%s, &__enabled);' % enable_name
198             print '        if (__enabled) {'
199             print '            GLint __binding = 0;'
200             print '            __glGetIntegerv(%s, &__binding);' % binding_name
201             print '            if (!__binding) {'
202
203             # Get the arguments via glGet*
204             for arg in function.args:
205                 arg_get_enum = 'GL_%s_ARRAY_%s' % (uppercase_name, arg.name.upper())
206                 arg_get_function, arg_type = TypeGetter().visit(arg.type)
207                 print '                %s %s = 0;' % (arg_type, arg.name)
208                 print '                __%s(%s, &%s);' % (arg_get_function, arg_get_enum, arg.name)
209             
210             arg_names = ', '.join([arg.name for arg in function.args[:-1]])
211             print '                size_t __size = __%s_size(%s, maxindex);' % (function.name, arg_names)
212
213             # Emit a fake function
214             print '                unsigned __call = Trace::BeginEnter(__%s_sig);' % (function.name,)
215             for arg in function.args:
216                 assert not arg.output
217                 print '                Trace::BeginArg(%u);' % (arg.index,)
218                 if arg.name != 'pointer':
219                     dump_instance(arg.type, arg.name)
220                 else:
221                     print '                Trace::LiteralBlob((const void *)%s, __size);' % (arg.name)
222                 print '                Trace::EndArg();'
223             
224             print '                Trace::EndEnter();'
225             print '                Trace::BeginLeave(__call);'
226             print '                Trace::EndLeave();'
227             print '            }'
228             print '        }'
229             print '    }'
230             print
231         print '}'
232         print
233
234
235
236
237
238
239