1 ##########################################################################
3 # Copyright 2008-2010 VMware, Inc.
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:
13 # The above copyright notice and this permission notice shall be included in
14 # all copies or substantial portions of the Software.
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
24 ##########################################################################/
27 """GL tracing generator."""
30 from glxapi import glxapi
31 from trace import Tracer, dump_instance
34 class GlTracer(Tracer):
36 def header(self, api):
37 Tracer.header(self, api)
38 self.state_tracker_decl(api)
40 def footer(self, api):
41 Tracer.footer(self, api)
42 self.state_tracker_impl(api)
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",
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",
74 #"glVertexAttribPointer": "VertexAttribPointer",
75 #"glVertexAttribPointerARB": "VertexAttribPointer",
76 #"glVertexAttribPointerNV": "VertexAttribPointer",
77 #"glVertexAttribLPointer": "VertexAttribLPointer",
79 #"glMatrixIndexPointerARB": "MatrixIndexPointer",
84 'ELEMENT_ARRAY_BUFFER',
86 'PIXEL_UNPACK_BUFFER',
89 client_state_enums = [
95 'SECONDARY_COLOR_ARRAY',
96 'TEXTURE_COORD_ARRAY',
100 def state_tracker_decl(self, api):
101 # A simple state tracker to track the pointer values
103 # define the NEW_XXXX dirty flags
105 for array_name in self.array_names.iterkeys():
106 dirtyflag = "NEW_%s" % array_name.upper()
107 print '#define %s 0x%x' % (dirtyflag, value)
111 # declare the state structure
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)
120 for arg in function.args:
121 print ' %s %s;' % (arg.type, arg.name)
122 print ' } %s;' % array_name.lower()
123 print ' unsigned dirty;'
126 print 'static void __state_update(GLsizei maxIndex);'
129 def trace_function_impl_body(self, function):
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)
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(),)
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(),)
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
165 self.dispatch_function(function)
168 if function.name == 'glDrawArrays':
169 print ' __state_update(first + count - 1);'
171 Tracer.trace_function_impl_body(self, function)
173 def state_tracker_impl(self, api):
174 # A simple state tracker to track the pointer values
177 print 'static void __state_update(GLsizei maxIndex)'
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()
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)
197 print ' if (__state.array_buffer) {'
198 print ' Trace::LiteralOpaque((const void *)%s);' % value
199 print ' __state.dirty &= ~%s;' % dirtyflag
201 if array_name in ('INDEX', 'EDGE_FLAG', 'FOG_COORD'):
203 elif array_name == 'NORMAL':
206 size = '__state.%s.size' % array_name.lower()
207 if array_name == 'EDGE_FLAG':
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)
214 print ' Trace::EndArg();'
215 print ' Trace::EndEnter();'
216 print ' Trace::BeginLeave(__call);'
217 print ' Trace::EndLeave();'