]> git.cworth.org Git - apitrace/blob - gltrace.py
Basic DrawArrays support.
[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 from glxapi import glxapi
31 from trace import Tracer, dump_instance
32
33
34 class GlTracer(Tracer):
35
36     def header(self, api):
37         Tracer.header(self, api)
38         self.state_tracker_decl(api)
39
40     def footer(self, api):
41         Tracer.footer(self, api)
42         self.state_tracker_impl(api)
43
44     array_names = {
45         "VERTEX": "glVertexPointer",
46         "NORMAL": "glNormalPointer",
47         "COLOR": "glColorPointer",
48         "INDEX": "glIndexPointer",
49         "TEX_COORD": "glTexCoordPointer",
50         "EDGE_FLAG": "glEdgeFlagPointer",
51         "FOG_COORD": "glFogCoordPointer",
52         "SECONDARY_COLOR": "glSecondaryColorPointer",
53     }
54
55     pointer_function_names = {
56         "glVertexPointer": "VERTEX",
57         "glNormalPointer": "NORMAL",
58         "glColorPointer": "COLOR",
59         "glIndexPointer": "INDEX",
60         "glTexCoordPointer": "TEX_COORD",
61         "glEdgeFlagPointer": "EDGE_FLAG",
62         "glFogCoordPointer": "FOG_COORD",
63         "glSecondaryColorPointer": "SECONDARY_COLOR",
64         #"glInterleavedArrays": ("InterleavedArrays", None)
65         #"glVertexPointerEXT": "VERTEX",
66         #"glNormalPointerEXT": "NORMAL",
67         #"glColorPointerEXT": "COLOR",
68         #"glIndexPointerEXT": "INDEX",
69         #"glTexCoordPointerEXT": "TEX_COORD",
70         #"glEdgeFlagPointerEXT": "EDGE_FLAG",
71         #"glFogCoordPointerEXT": "FOG_COORD",
72         #"glSecondaryColorPointerEXT": "SECONDARY_COLOR",
73
74         #"glVertexAttribPointer": "VertexAttribPointer",
75         #"glVertexAttribPointerARB": "VertexAttribPointer",
76         #"glVertexAttribPointerNV": "VertexAttribPointer",
77         #"glVertexAttribLPointer": "VertexAttribLPointer",
78         
79         #"glMatrixIndexPointerARB": "MatrixIndexPointer",
80     }
81
82     bind_buffer_enums = [
83         'ARRAY_BUFFER',
84         'ELEMENT_ARRAY_BUFFER',
85         'PIXEL_PACK_BUFFER',
86         'PIXEL_UNPACK_BUFFER',
87     ]
88
89     client_state_enums = [
90          'COLOR_ARRAY',
91          'EDGE_FLAG_ARRAY', 
92          'FOG_COORD_ARRAY', 
93          'INDEX_ARRAY', 
94          'NORMAL_ARRAY', 
95          'SECONDARY_COLOR_ARRAY', 
96          'TEXTURE_COORD_ARRAY', 
97          'VERTEX_ARRAY',
98     ]
99
100     def state_tracker_decl(self, api):
101         # A simple state tracker to track the pointer values
102
103         # define the NEW_XXXX dirty flags
104         value = 1
105         for array_name in self.array_names.iterkeys():
106             dirtyflag = "NEW_%s" % array_name.upper()
107             print '#define %s 0x%x' % (dirtyflag, value)
108             value <<= 1
109         print
110
111         # declare the state structure
112         print 'struct {'
113         for enum in self.bind_buffer_enums:
114             print '    GLuint %s;' % (enum.lower(),)
115         for enum in self.client_state_enums:
116             print '    GLboolean %s;' % (enum.lower(),)
117         for array_name, function_name in self.array_names.iteritems():
118             function = api.get_function_by_name(function_name)
119             print '    struct {'
120             for arg in function.args:
121                 print '        %s %s;' % (arg.type, arg.name)
122             print '    } %s;' % array_name.lower()
123         print '    unsigned dirty;'
124         print '} __state;'
125         print
126         print 'static void __state_update(GLsizei maxIndex);'
127         print
128     
129     def trace_function_impl_body(self, function):
130         # Track bound VBOs
131         if function.name in ('glBindBuffer', 'glBindBufferARB'):
132             print '    switch(%s) {' % function.args[0].name
133             for enum in self.bind_buffer_enums:
134                 print '    case GL_%s:' % enum
135                 print '        __state.%s = %s;' % (enum.lower(), function.args[1].name)
136                 print '        break;'
137             print '    }'
138
139         # Track enabled arrays
140         if function.name == 'glEnableClientState':
141             print '    switch(%s) {' % function.args[0].name
142             for enum in self.client_state_enums:
143                 print '    case GL_%s:' % enum
144                 print '        __state.%s = GL_TRUE;' % (enum.lower(),)
145                 print '        break;'
146             print '    }'
147         if function.name == 'glDisableClientState':
148             print '    switch(%s) {' % function.args[0].name
149             for enum in self.client_state_enums:
150                 print '    case GL_%s:' % enum
151                 print '        __state.%s = GL_FALSE;' % (enum.lower(),)
152                 print '        break;'
153             print '    }'
154
155         # Track array pointers
156         if function.name in self.pointer_function_names:
157             array_name = self.pointer_function_names[function.name]
158             dirtyflag = "NEW_%s" % array_name.upper()
159             for arg in function.args:
160                 assert not arg.output
161                 print '    __state.%s.%s = %s;' % (array_name.lower(), arg.name, arg.name)
162             print '    __state.dirty |= %s; ' % dirtyflag
163
164             # Defer tracing
165             self.dispatch_function(function)
166             return
167
168         if function.name == 'glDrawArrays':
169             print '   __state_update(first + count - 1);'
170         
171         Tracer.trace_function_impl_body(self, function)
172
173     def state_tracker_impl(self, api):
174         # A simple state tracker to track the pointer values
175
176         # update the state
177         print 'static void __state_update(GLsizei maxIndex)'
178         print '{'
179         print '    GLint __array_buffer = 0;'
180         print '    __glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &__array_buffer);'
181         for array_name, function_name in self.array_names.iteritems():
182             function = api.get_function_by_name(function_name)
183             dirtyflag = "NEW_%s" % array_name.upper()
184             if array_name == 'TEX_COORD':
185                 enableflag = 'TEXTURE_COORD_ARRAY'.lower()
186             else:
187                 enableflag = '%s_array' % array_name.lower()
188             print '    if (__state.%s && (__state.dirty & %s)) {' % (enableflag, dirtyflag)
189             print '        unsigned __call = Trace::BeginEnter(__%s_sig);' % (function.name,)
190             for arg in function.args:
191                 assert not arg.output
192                 value = '__state.%s.%s' % (array_name.lower(), arg.name)
193                 print '        Trace::BeginArg(%u);' % (arg.index,)
194                 if arg.name != 'pointer':
195                     dump_instance(arg.type, value)
196                 else:
197                     print '        if (__state.array_buffer) {'
198                     print '            Trace::LiteralOpaque((const void *)%s);' % value
199                     print '            __state.dirty &= ~%s;' % dirtyflag
200                     print '        } else {'
201                     if array_name in ('INDEX', 'EDGE_FLAG', 'FOG_COORD'):
202                         size = '1'
203                     elif array_name == 'NORMAL':
204                         size = '3'
205                     else:
206                         size = '__state.%s.size' % array_name.lower()
207                     if array_name == 'EDGE_FLAG':
208                         type = 'GL_BOOL'
209                     else:
210                         type = '__state.%s.type' % array_name.lower()
211                     stride = '__state.%s.stride' % array_name.lower()
212                     print '            Trace::LiteralBlob((const void *)%s, __glArrayPointer_size(%s, %s, %s, maxIndex));' % (value, size, type, stride)
213                     print '        }'
214                     print '        Trace::EndArg();'
215             print '        Trace::EndEnter();'
216             print '        Trace::BeginLeave(__call);'
217             print '        Trace::EndLeave();'
218             print '    }'
219         print '}'
220         print
221
222
223
224
225
226
227