]> git.cworth.org Git - apitrace/blob - gltrace.py
Some cleanups for vertex arrays.
[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', 'GLuint', '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     arrays.reverse()
86
87     def state_tracker_decl(self, api):
88         # Whether we need user arrays
89         print 'static inline bool __need_user_arrays(void)'
90         print '{'
91         for camelcase_name, uppercase_name in self.arrays:
92             function_name = 'gl%sPointer' % camelcase_name
93             enable_name = 'GL_%s_ARRAY' % uppercase_name
94             binding_name = 'GL_%s_ARRAY_BUFFER_BINDING' % uppercase_name
95             print '    // %s' % function_name
96             print '    if (__glIsEnabled(%s)) {' % enable_name
97             print '        GLint __binding = 0;'
98             print '        __glGetIntegerv(%s, &__binding);' % binding_name
99             print '        if (!__binding) {'
100             print '            return true;'
101             print '        }'
102             print '    }'
103             print
104
105         print '    return false;'
106         print '}'
107         print
108
109         print 'static void __trace_user_arrays(GLuint maxindex);'
110         print
111     
112     array_pointer_function_names = set((
113         "glVertexPointer",
114         "glNormalPointer",
115         "glColorPointer",
116         "glIndexPointer",
117         "glTexCoordPointer",
118         "glEdgeFlagPointer",
119         "glFogCoordPointer",
120         "glSecondaryColorPointer",
121         
122         "glVertexPointerEXT",
123         "glNormalPointerEXT",
124         "glColorPointerEXT",
125         "glIndexPointerEXT",
126         "glTexCoordPointerEXT",
127         "glEdgeFlagPointerEXT",
128         "glFogCoordPointerEXT",
129         "glSecondaryColorPointerEXT",
130
131         "glVertexAttribPointer",
132         "glVertexAttribPointerARB",
133         "glVertexAttribPointerNV",
134         "glVertexAttribLPointer",
135         "glVertexAttribLPointerEXT",
136         
137         #"glMatrixIndexPointerARB",
138     ))
139
140     draw_function_names = set((
141         'glDrawArrays',
142         'glDrawElements',
143         'glDrawRangeElements',
144     ))
145
146     interleaved_formats = [
147          'GL_V2F',
148          'GL_V3F',
149          'GL_C4UB_V2F',
150          'GL_C4UB_V3F',
151          'GL_C3F_V3F',
152          'GL_N3F_V3F',
153          'GL_C4F_N3F_V3F',
154          'GL_T2F_V3F',
155          'GL_T4F_V4F',
156          'GL_T2F_C4UB_V3F',
157          'GL_T2F_C3F_V3F',
158          'GL_T2F_N3F_V3F',
159          'GL_T2F_C4F_N3F_V3F',
160          'GL_T4F_C4F_N3F_V4F',
161     ]
162
163     def trace_function_impl_body(self, function):
164         # Defer tracing of user array pointers...
165         if function.name in self.array_pointer_function_names:
166             print '    GLint __array_buffer = 0;'
167             print '    __glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &__array_buffer);'
168             print '    if (!__array_buffer) {'
169             self.dispatch_function(function)
170             print '        return;'
171             print '    }'
172
173         # ... to the draw calls
174         if function.name in self.draw_function_names:
175             print '    if (__need_user_arrays()) {'
176             arg_names = ', '.join([arg.name for arg in function.args[1:]])
177             print '        GLuint maxindex = __%s_maxindex(%s);' % (function.name, arg_names)
178             print '        __trace_user_arrays(maxindex);'
179             print '    }'
180         
181         # And also break down glInterleavedArrays into the individual calls
182         if function.name == 'glInterleavedArrays':
183             print '    GLint __array_buffer = 0;'
184             print '    __glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &__array_buffer);'
185             print '    if (!__array_buffer) {'
186             self.dispatch_function(function)
187             print
188
189             # Initialize the enable flags
190             for camelcase_name, uppercase_name in self.arrays:
191                 flag_name = '__' + uppercase_name.lower()
192                 print '        GLboolean %s = GL_FALSE;' % flag_name
193             print
194
195             # Swicth for the interleaved formats
196             print '        switch (format) {'
197             for format in self.interleaved_formats:
198                 print '            case %s:' % format
199                 for camelcase_name, uppercase_name in self.arrays:
200                     flag_name = '__' + uppercase_name.lower()
201                     if format.find('_' + uppercase_name[0]) >= 0:
202                         print '                %s = GL_TRUE;' % flag_name
203                 print '                break;'
204             print '            default:'
205             print '               return;'
206             print '        }'
207             print
208
209             # Emit fake glEnableClientState/glDisableClientState flags
210             for camelcase_name, uppercase_name in self.arrays:
211                 flag_name = '__' + uppercase_name.lower()
212                 enable_name = 'GL_%s_ARRAY' % uppercase_name
213
214                 # Emit a fake function
215                 print '        {'
216                 print '            static const Trace::FunctionSig &__sig = %s ? __glEnableClientState_sig : __glDisableClientState_sig;' % flag_name
217                 print '            unsigned __call = Trace::BeginEnter(__sig);'
218                 print '            Trace::BeginArg(0);'
219                 dump_instance(glapi.GLenum, enable_name)
220                 print '            Trace::EndArg();'
221                 print '            Trace::EndEnter();'
222                 print '            Trace::BeginLeave(__call);'
223                 print '            Trace::EndLeave();'
224                 print '        }'
225
226             print '        return;'
227             print '    }'
228
229         Tracer.trace_function_impl_body(self, function)
230
231     boolean_names = [
232         'GL_FALSE',
233         'GL_TRUE',
234     ]
235
236     def gl_boolean(self, value):
237         return self.boolean_names[int(bool(value))]
238
239     def dump_arg_instance(self, function, arg):
240         if function.name in self.draw_function_names and arg.name == 'indices':
241             print '    GLint __element_array_buffer = 0;'
242             print '    __glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &__element_array_buffer);'
243             print '    if (!__element_array_buffer) {'
244             print '        Trace::LiteralBlob((const void *)%s, count*__gl_type_size(type));' % (arg.name)
245             print '    } else {'
246             print '        Trace::LiteralOpaque((const void *)%s);' % (arg.name)
247             print '    }'
248             return
249
250         Tracer.dump_arg_instance(self, function, arg)
251
252     def state_tracker_impl(self, api):
253         # A simple state tracker to track the pointer values
254
255         # update the state
256         print 'static void __trace_user_arrays(GLuint maxindex)'
257         print '{'
258         for camelcase_name, uppercase_name in self.arrays:
259             function_name = 'gl%sPointer' % camelcase_name
260             enable_name = 'GL_%s_ARRAY' % uppercase_name
261             binding_name = 'GL_%s_ARRAY_BUFFER_BINDING' % uppercase_name
262             function = api.get_function_by_name(function_name)
263
264             print '    // %s' % function.name
265             print '    if (__glIsEnabled(%s)) {;' % enable_name
266             print '        GLint __binding = 0;'
267             print '        __glGetIntegerv(%s, &__binding);' % binding_name
268             print '        if (!__binding) {'
269
270             # Get the arguments via glGet*
271             for arg in function.args:
272                 arg_get_enum = 'GL_%s_ARRAY_%s' % (uppercase_name, arg.name.upper())
273                 arg_get_function, arg_type = TypeGetter().visit(arg.type)
274                 print '            %s %s = 0;' % (arg_type, arg.name)
275                 print '            __%s(%s, &%s);' % (arg_get_function, arg_get_enum, arg.name)
276             
277             arg_names = ', '.join([arg.name for arg in function.args[:-1]])
278             print '            size_t __size = __%s_size(%s, maxindex);' % (function.name, arg_names)
279
280             # Emit a fake function
281             print '            unsigned __call = Trace::BeginEnter(__%s_sig);' % (function.name,)
282             for arg in function.args:
283                 assert not arg.output
284                 print '            Trace::BeginArg(%u);' % (arg.index,)
285                 if arg.name != 'pointer':
286                     dump_instance(arg.type, arg.name)
287                 else:
288                     print '            Trace::LiteralBlob((const void *)%s, __size);' % (arg.name)
289                 print '            Trace::EndArg();'
290             
291             print '            Trace::EndEnter();'
292             print '            Trace::BeginLeave(__call);'
293             print '            Trace::EndLeave();'
294             print '        }'
295             print '    }'
296             print
297         print '}'
298         print
299
300
301
302
303
304
305