blob: bfccd581ad690ba597cc9b6a4082459a89890730 [file] [log] [blame]
José Fonseca669b1222011-02-20 09:05:10 +00001##########################################################################
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
José Fonseca99221832011-03-22 22:15:46 +000030import stdapi
31import glapi
José Fonseca5ea91872011-05-04 09:41:55 +010032import glparams
José Fonseca669b1222011-02-20 09:05:10 +000033from glxapi import glxapi
34from trace import Tracer, dump_instance
35
36
José Fonseca99221832011-03-22 22:15:46 +000037class TypeGetter(stdapi.Visitor):
38 '''Determine which glGet*v function that matches the specified type.'''
39
José Fonsecac493e3e2011-06-29 12:57:06 +010040 def __init__(self, prefix = 'glGet', long_suffix = True, ext_suffix = ''):
José Fonseca1a2fdd22011-04-01 00:55:09 +010041 self.prefix = prefix
42 self.long_suffix = long_suffix
José Fonsecac493e3e2011-06-29 12:57:06 +010043 self.ext_suffix = ext_suffix
José Fonseca1a2fdd22011-04-01 00:55:09 +010044
José Fonseca99221832011-03-22 22:15:46 +000045 def visit_const(self, const):
46 return self.visit(const.type)
47
48 def visit_alias(self, alias):
49 if alias.expr == 'GLboolean':
José Fonseca1a2fdd22011-04-01 00:55:09 +010050 if self.long_suffix:
José Fonsecac493e3e2011-06-29 12:57:06 +010051 suffix = 'Booleanv'
52 arg_type = alias.expr
José Fonseca1a2fdd22011-04-01 00:55:09 +010053 else:
José Fonsecac493e3e2011-06-29 12:57:06 +010054 suffix = 'iv'
55 arg_type = 'GLint'
José Fonseca99221832011-03-22 22:15:46 +000056 elif alias.expr == 'GLdouble':
José Fonseca1a2fdd22011-04-01 00:55:09 +010057 if self.long_suffix:
José Fonsecac493e3e2011-06-29 12:57:06 +010058 suffix = 'Doublev'
59 arg_type = alias.expr
José Fonseca1a2fdd22011-04-01 00:55:09 +010060 else:
José Fonsecac493e3e2011-06-29 12:57:06 +010061 suffix = 'dv'
62 arg_type = alias.expr
José Fonseca99221832011-03-22 22:15:46 +000063 elif alias.expr == 'GLfloat':
José Fonseca1a2fdd22011-04-01 00:55:09 +010064 if self.long_suffix:
José Fonsecac493e3e2011-06-29 12:57:06 +010065 suffix = 'Floatv'
66 arg_type = alias.expr
José Fonseca1a2fdd22011-04-01 00:55:09 +010067 else:
José Fonsecac493e3e2011-06-29 12:57:06 +010068 suffix = 'fv'
69 arg_type = alias.expr
José Fonseca7f5163e2011-03-31 23:37:26 +010070 elif alias.expr in ('GLint', 'GLuint', 'GLsizei'):
José Fonseca1a2fdd22011-04-01 00:55:09 +010071 if self.long_suffix:
José Fonsecac493e3e2011-06-29 12:57:06 +010072 suffix = 'Integerv'
73 arg_type = 'GLint'
José Fonseca1a2fdd22011-04-01 00:55:09 +010074 else:
José Fonsecac493e3e2011-06-29 12:57:06 +010075 suffix = 'iv'
76 arg_type = 'GLint'
José Fonseca99221832011-03-22 22:15:46 +000077 else:
78 print alias.expr
79 assert False
José Fonsecac493e3e2011-06-29 12:57:06 +010080 function_name = self.prefix + suffix + self.ext_suffix
81 return function_name, arg_type
José Fonseca99221832011-03-22 22:15:46 +000082
83 def visit_enum(self, enum):
José Fonseca1a2fdd22011-04-01 00:55:09 +010084 return self.visit(glapi.GLint)
José Fonseca99221832011-03-22 22:15:46 +000085
86 def visit_bitmask(self, bitmask):
José Fonseca1a2fdd22011-04-01 00:55:09 +010087 return self.visit(glapi.GLint)
José Fonseca99221832011-03-22 22:15:46 +000088
89 def visit_opaque(self, pointer):
José Fonsecac493e3e2011-06-29 12:57:06 +010090 return self.prefix + 'Pointerv' + self.ext_suffix, 'GLvoid *'
José Fonseca99221832011-03-22 22:15:46 +000091
92
José Fonseca669b1222011-02-20 09:05:10 +000093class GlTracer(Tracer):
94
José Fonseca99221832011-03-22 22:15:46 +000095 arrays = [
96 ("Vertex", "VERTEX"),
97 ("Normal", "NORMAL"),
98 ("Color", "COLOR"),
99 ("Index", "INDEX"),
100 ("TexCoord", "TEXTURE_COORD"),
101 ("EdgeFlag", "EDGE_FLAG"),
102 ("FogCoord", "FOG_COORD"),
103 ("SecondaryColor", "SECONDARY_COLOR"),
José Fonseca14c21bc2011-02-20 23:32:22 +0000104 ]
José Fonsecac9f12232011-03-25 20:07:42 +0000105 arrays.reverse()
José Fonseca669b1222011-02-20 09:05:10 +0000106
José Fonseca4c938c22011-04-30 22:44:38 +0100107 def header(self, api):
108 Tracer.header(self, api)
109
José Fonseca25ebe542011-04-24 10:08:22 +0100110 print '// Whether user arrays were used'
111 print 'static bool __user_arrays = false;'
112 print
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000113 # Whether we need user arrays
114 print 'static inline bool __need_user_arrays(void)'
115 print '{'
José Fonseca25ebe542011-04-24 10:08:22 +0100116 print ' if (!__user_arrays) {'
117 print ' return false;'
118 print ' }'
119 print
José Fonseca1a2fdd22011-04-01 00:55:09 +0100120
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000121 for camelcase_name, uppercase_name in self.arrays:
122 function_name = 'gl%sPointer' % camelcase_name
123 enable_name = 'GL_%s_ARRAY' % uppercase_name
124 binding_name = 'GL_%s_ARRAY_BUFFER_BINDING' % uppercase_name
125 print ' // %s' % function_name
José Fonsecafb6744f2011-04-15 11:18:37 +0100126 self.array_prolog(api, uppercase_name)
José Fonseca7f5163e2011-03-31 23:37:26 +0100127 print ' if (__glIsEnabled(%s)) {' % enable_name
128 print ' GLint __binding = 0;'
129 print ' __glGetIntegerv(%s, &__binding);' % binding_name
130 print ' if (!__binding) {'
José Fonsecafb6744f2011-04-15 11:18:37 +0100131 self.array_cleanup(api, uppercase_name)
José Fonseca7f5163e2011-03-31 23:37:26 +0100132 print ' return true;'
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000133 print ' }'
134 print ' }'
José Fonsecafb6744f2011-04-15 11:18:37 +0100135 self.array_epilog(api, uppercase_name)
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000136 print
José Fonseca7f5163e2011-03-31 23:37:26 +0100137
José Fonsecad94aaac2011-06-28 20:50:49 +0100138 print ' GLboolean __vertex_program = GL_FALSE;'
139 print ' __glGetBooleanv(GL_VERTEX_PROGRAM_ARB, &__vertex_program);'
140 print ' if (__vertex_program) {'
141 print ' // glVertexAttribPointerARB'
142 print ' GLint __max_vertex_attribs = 0;'
143 print ' __glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &__max_vertex_attribs);'
144 print ' for (GLint index = 0; index < __max_vertex_attribs; ++index) {'
145 print ' GLint __enabled = 0;'
146 print ' __glGetVertexAttribivARB(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB, &__enabled);'
147 print ' if (__enabled) {'
148 print ' GLint __binding = 0;'
149 print ' __glGetVertexAttribivARB(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB, &__binding);'
150 print ' if (!__binding) {'
151 print ' return true;'
152 print ' }'
153 print ' }'
154 print ' }'
155 print ' } else {'
156 print ' // glVertexAttribPointer'
157 print ' GLint __max_vertex_attribs = 0;'
158 print ' __glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &__max_vertex_attribs);'
159 print ' for (GLint index = 0; index < __max_vertex_attribs; ++index) {'
160 print ' GLint __enabled = 0;'
161 print ' __glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &__enabled);'
162 print ' if (__enabled) {'
163 print ' GLint __binding = 0;'
164 print ' __glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &__binding);'
165 print ' if (!__binding) {'
166 print ' return true;'
167 print ' }'
José Fonseca1a2fdd22011-04-01 00:55:09 +0100168 print ' }'
169 print ' }'
170 print ' }'
171 print
172
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000173 print ' return false;'
174 print '}'
175 print
José Fonseca669b1222011-02-20 09:05:10 +0000176
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000177 print 'static void __trace_user_arrays(GLuint maxindex);'
José Fonseca14c21bc2011-02-20 23:32:22 +0000178 print
José Fonseca867b1b72011-04-24 11:58:04 +0100179
180 print 'struct buffer_mapping {'
181 print ' void *map;'
182 print ' GLint length;'
183 print ' bool write;'
José Fonseca73373602011-05-20 17:45:26 +0100184 print ' bool explicit_flush;'
José Fonseca867b1b72011-04-24 11:58:04 +0100185 print '};'
186 print
187 for target in self.buffer_targets:
188 print 'struct buffer_mapping __%s_mapping;' % target.lower();
189 print
190 print 'static inline struct buffer_mapping *'
191 print 'get_buffer_mapping(GLenum target) {'
192 print ' switch(target) {'
193 for target in self.buffer_targets:
194 print ' case GL_%s:' % target
195 print ' return & __%s_mapping;' % target.lower()
196 print ' default:'
José Fonsecacbd225f2011-06-09 00:07:18 +0100197 print ' OS::DebugMessage("apitrace: warning: unknown buffer target 0x%04X\\n", target);'
José Fonseca867b1b72011-04-24 11:58:04 +0100198 print ' return NULL;'
199 print ' }'
200 print '}'
201 print
202
203 # Generate memcpy's signature
204 self.trace_function_decl(glapi.memcpy)
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100205
206 # Generate a helper function to determine whether a parameter name
207 # refers to a symbolic value or not
208 print 'static bool'
209 print 'is_symbolic_pname(GLenum pname) {'
210 print ' switch(pname) {'
José Fonseca5ea91872011-05-04 09:41:55 +0100211 for function, type, count, name in glparams.parameters:
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100212 if type is glapi.GLenum:
José Fonseca4c938c22011-04-30 22:44:38 +0100213 print ' case %s:' % name
214 print ' return true;'
215 print ' default:'
216 print ' return false;'
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100217 print ' }'
218 print '}'
219 print
220
221 # Generate a helper function to determine whether a parameter value is
222 # potentially symbolic or not; i.e., if the value can be represented in
223 # an enum or not
224 print 'template<class T>'
225 print 'static inline bool'
226 print 'is_symbolic_param(T param) {'
227 print ' return static_cast<T>(static_cast<GLenum>(param)) == param;'
228 print '}'
229 print
José Fonseca4c938c22011-04-30 22:44:38 +0100230
231 # Generate a helper function to know how many elements a parameter has
232 print 'static size_t'
José Fonsecaf4aca5d2011-05-08 08:29:30 +0100233 print '__gl_param_size(GLenum pname) {'
José Fonseca4c938c22011-04-30 22:44:38 +0100234 print ' switch(pname) {'
José Fonseca5ea91872011-05-04 09:41:55 +0100235 for function, type, count, name in glparams.parameters:
José Fonseca4c938c22011-04-30 22:44:38 +0100236 if type is not None:
237 print ' case %s: return %u;' % (name, count)
238 print ' case GL_COMPRESSED_TEXTURE_FORMATS: {'
239 print ' GLint num_compressed_texture_formats = 0;'
240 print ' __glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &num_compressed_texture_formats);'
241 print ' return num_compressed_texture_formats;'
242 print ' }'
243 print ' default:'
José Fonsecacbd225f2011-06-09 00:07:18 +0100244 print r' OS::DebugMessage("apitrace: warning: %s: unknown GLenum 0x%04X\n", __FUNCTION__, pname);'
José Fonseca4c938c22011-04-30 22:44:38 +0100245 print ' return 1;'
246 print ' }'
247 print '}'
248 print
249
José Fonseca99221832011-03-22 22:15:46 +0000250 array_pointer_function_names = set((
251 "glVertexPointer",
252 "glNormalPointer",
253 "glColorPointer",
254 "glIndexPointer",
255 "glTexCoordPointer",
256 "glEdgeFlagPointer",
257 "glFogCoordPointer",
258 "glSecondaryColorPointer",
José Fonseca7f5163e2011-03-31 23:37:26 +0100259
José Fonsecaac5285b2011-05-04 11:09:08 +0100260 "glInterleavedArrays",
261
José Fonseca7e0bfd92011-04-30 23:09:03 +0100262 "glVertexPointerEXT",
263 "glNormalPointerEXT",
264 "glColorPointerEXT",
265 "glIndexPointerEXT",
266 "glTexCoordPointerEXT",
267 "glEdgeFlagPointerEXT",
268 "glFogCoordPointerEXT",
269 "glSecondaryColorPointerEXT",
José Fonseca99221832011-03-22 22:15:46 +0000270
José Fonseca7f5163e2011-03-31 23:37:26 +0100271 "glVertexAttribPointer",
272 "glVertexAttribPointerARB",
273 "glVertexAttribPointerNV",
José Fonsecaac5285b2011-05-04 11:09:08 +0100274 "glVertexAttribIPointer",
275 "glVertexAttribIPointerEXT",
José Fonseca7f5163e2011-03-31 23:37:26 +0100276 "glVertexAttribLPointer",
277 "glVertexAttribLPointerEXT",
José Fonseca99221832011-03-22 22:15:46 +0000278
279 #"glMatrixIndexPointerARB",
280 ))
281
282 draw_function_names = set((
283 'glDrawArrays',
284 'glDrawElements',
285 'glDrawRangeElements',
José Fonseca5c749e32011-05-09 11:11:37 +0100286 'glMultiDrawArrays',
287 'glMultiDrawElements',
288 'glDrawArraysInstanced',
289 'glDrawElementsInstanced',
290 'glDrawArraysInstancedARB',
291 'glDrawElementsInstancedARB',
292 'glDrawElementsBaseVertex',
293 'glDrawRangeElementsBaseVertex',
294 'glDrawElementsInstancedBaseVertex',
295 'glMultiDrawElementsBaseVertex',
296 'glDrawArraysIndirect',
297 'glDrawElementsIndirect',
298 'glDrawArraysEXT',
José Fonseca7e0bfd92011-04-30 23:09:03 +0100299 'glDrawRangeElementsEXT',
José Fonseca5c749e32011-05-09 11:11:37 +0100300 'glDrawRangeElementsEXT_size',
301 'glMultiDrawArraysEXT',
302 'glMultiDrawElementsEXT',
303 'glMultiModeDrawArraysIBM',
304 'glMultiModeDrawElementsIBM',
305 'glDrawArraysInstancedEXT',
306 'glDrawElementsInstancedEXT',
José Fonseca99221832011-03-22 22:15:46 +0000307 ))
308
José Fonsecac9f12232011-03-25 20:07:42 +0000309 interleaved_formats = [
310 'GL_V2F',
311 'GL_V3F',
312 'GL_C4UB_V2F',
313 'GL_C4UB_V3F',
314 'GL_C3F_V3F',
315 'GL_N3F_V3F',
316 'GL_C4F_N3F_V3F',
317 'GL_T2F_V3F',
318 'GL_T4F_V4F',
319 'GL_T2F_C4UB_V3F',
320 'GL_T2F_C3F_V3F',
321 'GL_T2F_N3F_V3F',
322 'GL_T2F_C4F_N3F_V3F',
323 'GL_T4F_C4F_N3F_V4F',
324 ]
325
José Fonseca14c21bc2011-02-20 23:32:22 +0000326 def trace_function_impl_body(self, function):
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000327 # Defer tracing of user array pointers...
José Fonseca99221832011-03-22 22:15:46 +0000328 if function.name in self.array_pointer_function_names:
329 print ' GLint __array_buffer = 0;'
330 print ' __glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &__array_buffer);'
331 print ' if (!__array_buffer) {'
José Fonseca25ebe542011-04-24 10:08:22 +0100332 print ' __user_arrays = true;'
José Fonseca14c21bc2011-02-20 23:32:22 +0000333 self.dispatch_function(function)
José Fonsecaac5285b2011-05-04 11:09:08 +0100334
335 # And also break down glInterleavedArrays into the individual calls
336 if function.name == 'glInterleavedArrays':
337 print
338
339 # Initialize the enable flags
340 for camelcase_name, uppercase_name in self.arrays:
341 flag_name = '__' + uppercase_name.lower()
342 print ' GLboolean %s = GL_FALSE;' % flag_name
343 print
344
345 # Switch for the interleaved formats
346 print ' switch (format) {'
347 for format in self.interleaved_formats:
348 print ' case %s:' % format
349 for camelcase_name, uppercase_name in self.arrays:
350 flag_name = '__' + uppercase_name.lower()
351 if format.find('_' + uppercase_name[0]) >= 0:
352 print ' %s = GL_TRUE;' % flag_name
353 print ' break;'
354 print ' default:'
355 print ' return;'
356 print ' }'
357 print
358
359 # Emit fake glEnableClientState/glDisableClientState flags
360 for camelcase_name, uppercase_name in self.arrays:
361 flag_name = '__' + uppercase_name.lower()
362 enable_name = 'GL_%s_ARRAY' % uppercase_name
363
364 # Emit a fake function
365 print ' {'
366 print ' static const Trace::FunctionSig &__sig = %s ? __glEnableClientState_sig : __glDisableClientState_sig;' % flag_name
José Fonseca466753b2011-05-28 13:25:55 +0100367 print ' unsigned __call = __writer.beginEnter(&__sig);'
José Fonsecaeced7472011-05-28 10:37:12 +0100368 print ' __writer.beginArg(0);'
José Fonsecaac5285b2011-05-04 11:09:08 +0100369 dump_instance(glapi.GLenum, enable_name)
José Fonsecaeced7472011-05-28 10:37:12 +0100370 print ' __writer.endArg();'
371 print ' __writer.endEnter();'
372 print ' __writer.beginLeave(__call);'
373 print ' __writer.endLeave();'
José Fonsecaac5285b2011-05-04 11:09:08 +0100374 print ' }'
375
José Fonseca99221832011-03-22 22:15:46 +0000376 print ' return;'
377 print ' }'
José Fonseca14c21bc2011-02-20 23:32:22 +0000378
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000379 # ... to the draw calls
José Fonseca99221832011-03-22 22:15:46 +0000380 if function.name in self.draw_function_names:
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000381 print ' if (__need_user_arrays()) {'
José Fonseca99221832011-03-22 22:15:46 +0000382 arg_names = ', '.join([arg.name for arg in function.args[1:]])
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000383 print ' GLuint maxindex = __%s_maxindex(%s);' % (function.name, arg_names)
384 print ' __trace_user_arrays(maxindex);'
385 print ' }'
José Fonseca14c21bc2011-02-20 23:32:22 +0000386
José Fonseca73373602011-05-20 17:45:26 +0100387 # Emit a fake memcpy on buffer uploads
388 if function.name in ('glUnmapBuffer', 'glUnmapBufferARB', ):
José Fonseca867b1b72011-04-24 11:58:04 +0100389 print ' struct buffer_mapping *mapping = get_buffer_mapping(target);'
José Fonseca73373602011-05-20 17:45:26 +0100390 print ' if (mapping && mapping->write && !mapping->explicit_flush) {'
391 self.emit_memcpy('mapping->map', 'mapping->map', 'mapping->length')
José Fonseca867b1b72011-04-24 11:58:04 +0100392 print ' }'
José Fonseca73373602011-05-20 17:45:26 +0100393 if function.name in ('glFlushMappedBufferRange', 'glFlushMappedBufferRangeAPPLE'):
394 # TODO: avoid copying [0, offset] bytes
395 print ' struct buffer_mapping *mapping = get_buffer_mapping(target);'
396 print ' if (mapping) {'
397 if function.name.endswith('APPLE'):
398 print ' GLsizeiptr length = size;'
399 print ' mapping->explicit_flush = true;'
400 print ' //assert(offset + length <= mapping->length);'
401 self.emit_memcpy('mapping->map', 'mapping->map', 'offset + length')
402 print ' }'
403 # FIXME: glFlushMappedNamedBufferRangeEXT
José Fonseca867b1b72011-04-24 11:58:04 +0100404
José Fonseca91492d22011-05-23 21:20:31 +0100405 # Don't leave vertex attrib locations to chance. Instead emit fake
406 # glBindAttribLocation calls to ensure that the same locations will be
407 # used when retracing. Trying to remap locations after the fact would
408 # be an herculian task given that vertex attrib locations appear in
409 # many entry-points, including non-shader related ones.
410 if function.name == 'glLinkProgram':
411 Tracer.dispatch_function(self, function)
412 print ' GLint active_attributes = 0;'
413 print ' __glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &active_attributes);'
414 print ' for (GLuint attrib = 0; attrib < active_attributes; ++attrib) {'
415 print ' GLint size = 0;'
416 print ' GLenum type = 0;'
417 print ' GLchar name[256];'
418 # TODO: Use ACTIVE_ATTRIBUTE_MAX_LENGTH instead of 256
419 print ' __glGetActiveAttrib(program, attrib, sizeof name, NULL, &size, &type, name);'
José Fonseca2a794f52011-05-26 20:54:29 +0100420 print " if (name[0] != 'g' || name[1] != 'l' || name[2] != '_') {"
421 print ' GLint location = __glGetAttribLocation(program, name);'
422 print ' if (location >= 0) {'
José Fonseca91492d22011-05-23 21:20:31 +0100423 bind_function = glapi.glapi.get_function_by_name('glBindAttribLocation')
424 self.fake_call(bind_function, ['program', 'location', 'name'])
José Fonseca2a794f52011-05-26 20:54:29 +0100425 print ' }'
José Fonseca91492d22011-05-23 21:20:31 +0100426 print ' }'
427 print ' }'
428 if function.name == 'glLinkProgramARB':
429 Tracer.dispatch_function(self, function)
430 print ' GLint active_attributes = 0;'
431 print ' __glGetObjectParameterivARB(programObj, GL_OBJECT_ACTIVE_ATTRIBUTES_ARB, &active_attributes);'
432 print ' for (GLuint attrib = 0; attrib < active_attributes; ++attrib) {'
433 print ' GLint size = 0;'
434 print ' GLenum type = 0;'
435 print ' GLcharARB name[256];'
436 # TODO: Use ACTIVE_ATTRIBUTE_MAX_LENGTH instead of 256
437 print ' __glGetActiveAttribARB(programObj, attrib, sizeof name, NULL, &size, &type, name);'
José Fonseca2a794f52011-05-26 20:54:29 +0100438 print " if (name[0] != 'g' || name[1] != 'l' || name[2] != '_') {"
439 print ' GLint location = __glGetAttribLocationARB(programObj, name);'
440 print ' if (location >= 0) {'
José Fonseca91492d22011-05-23 21:20:31 +0100441 bind_function = glapi.glapi.get_function_by_name('glBindAttribLocationARB')
442 self.fake_call(bind_function, ['programObj', 'location', 'name'])
José Fonseca2a794f52011-05-26 20:54:29 +0100443 print ' }'
José Fonseca91492d22011-05-23 21:20:31 +0100444 print ' }'
445 print ' }'
446
José Fonseca14c21bc2011-02-20 23:32:22 +0000447 Tracer.trace_function_impl_body(self, function)
José Fonseca73373602011-05-20 17:45:26 +0100448
José Fonseca91492d22011-05-23 21:20:31 +0100449 def dispatch_function(self, function):
450 if function.name in ('glLinkProgram', 'glLinkProgramARB'):
451 # These functions have been dispatched already
452 return
453
454 Tracer.dispatch_function(self, function)
455
José Fonseca73373602011-05-20 17:45:26 +0100456 def emit_memcpy(self, dest, src, length):
José Fonseca466753b2011-05-28 13:25:55 +0100457 print ' unsigned __call = __writer.beginEnter(&__memcpy_sig);'
José Fonsecaeced7472011-05-28 10:37:12 +0100458 print ' __writer.beginArg(0);'
459 print ' __writer.writeOpaque(%s);' % dest
460 print ' __writer.endArg();'
461 print ' __writer.beginArg(1);'
462 print ' __writer.writeBlob(%s, %s);' % (src, length)
463 print ' __writer.endArg();'
464 print ' __writer.beginArg(2);'
465 print ' __writer.writeUInt(%s);' % length
466 print ' __writer.endArg();'
467 print ' __writer.endEnter();'
468 print ' __writer.beginLeave(__call);'
469 print ' __writer.endLeave();'
José Fonseca867b1b72011-04-24 11:58:04 +0100470
471 buffer_targets = [
472 'ARRAY_BUFFER',
473 'ELEMENT_ARRAY_BUFFER',
474 'PIXEL_PACK_BUFFER',
475 'PIXEL_UNPACK_BUFFER',
476 ]
477
478 def wrap_ret(self, function, instance):
479 Tracer.wrap_ret(self, function, instance)
480
481 if function.name in ('glMapBuffer', 'glMapBufferARB'):
482 print ' struct buffer_mapping *mapping = get_buffer_mapping(target);'
483 print ' if (mapping) {'
484 print ' mapping->map = %s;' % (instance)
485 print ' mapping->length = 0;'
486 print ' __glGetBufferParameteriv(target, GL_BUFFER_SIZE, &mapping->length);'
487 print ' mapping->write = (access != GL_READ_ONLY);'
José Fonseca73373602011-05-20 17:45:26 +0100488 print ' mapping->explicit_flush = false;'
José Fonseca867b1b72011-04-24 11:58:04 +0100489 print ' }'
490
491 if function.name == 'glMapBufferRange':
492 print ' struct buffer_mapping *mapping = get_buffer_mapping(target);'
493 print ' if (mapping) {'
494 print ' mapping->map = %s;' % (instance)
495 print ' mapping->length = length;'
496 print ' mapping->write = access & GL_MAP_WRITE_BIT;'
José Fonseca73373602011-05-20 17:45:26 +0100497 print ' mapping->explicit_flush = access & GL_MAP_FLUSH_EXPLICIT_BIT;'
José Fonseca867b1b72011-04-24 11:58:04 +0100498 print ' }'
José Fonseca669b1222011-02-20 09:05:10 +0000499
José Fonsecac9f12232011-03-25 20:07:42 +0000500 boolean_names = [
501 'GL_FALSE',
502 'GL_TRUE',
503 ]
504
505 def gl_boolean(self, value):
506 return self.boolean_names[int(bool(value))]
507
José Fonsecac29f4f12011-06-11 12:19:05 +0100508 # Names of the functions that unpack from a pixel buffer object. See the
509 # ARB_pixel_buffer_object specification.
José Fonsecae97bab92011-06-02 23:15:11 +0100510 unpack_function_names = set([
511 'glBitmap',
José Fonsecac29f4f12011-06-11 12:19:05 +0100512 'glColorSubTable',
513 'glColorTable',
514 'glCompressedTexImage1D',
515 'glCompressedTexImage2D',
516 'glCompressedTexImage3D',
517 'glCompressedTexSubImage1D',
518 'glCompressedTexSubImage2D',
519 'glCompressedTexSubImage3D',
520 'glConvolutionFilter1D',
521 'glConvolutionFilter2D',
José Fonsecae97bab92011-06-02 23:15:11 +0100522 'glDrawPixels',
523 'glMultiTexImage1DEXT',
524 'glMultiTexImage2DEXT',
525 'glMultiTexImage3DEXT',
526 'glMultiTexSubImage1DEXT',
527 'glMultiTexSubImage2DEXT',
528 'glMultiTexSubImage3DEXT',
José Fonsecac29f4f12011-06-11 12:19:05 +0100529 'glPixelMapfv',
530 'glPixelMapuiv',
531 'glPixelMapusv',
José Fonsecae97bab92011-06-02 23:15:11 +0100532 'glPolygonStipple',
José Fonsecac29f4f12011-06-11 12:19:05 +0100533 'glSeparableFilter2D',
José Fonsecae97bab92011-06-02 23:15:11 +0100534 'glTexImage1D',
535 'glTexImage1DEXT',
536 'glTexImage2D',
537 'glTexImage2DEXT',
538 'glTexImage3D',
539 'glTexImage3DEXT',
540 'glTexSubImage1D',
541 'glTexSubImage1DEXT',
542 'glTexSubImage2D',
543 'glTexSubImage2DEXT',
544 'glTexSubImage3D',
545 'glTexSubImage3DEXT',
546 'glTextureImage1DEXT',
547 'glTextureImage2DEXT',
548 'glTextureImage3DEXT',
549 'glTextureSubImage1DEXT',
550 'glTextureSubImage2DEXT',
551 'glTextureSubImage3DEXT',
552 ])
553
José Fonseca99221832011-03-22 22:15:46 +0000554 def dump_arg_instance(self, function, arg):
555 if function.name in self.draw_function_names and arg.name == 'indices':
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000556 print ' GLint __element_array_buffer = 0;'
557 print ' __glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &__element_array_buffer);'
558 print ' if (!__element_array_buffer) {'
José Fonseca5c749e32011-05-09 11:11:37 +0100559 if isinstance(arg.type, stdapi.Array):
José Fonsecaeced7472011-05-28 10:37:12 +0100560 print ' __writer.beginArray(%s);' % arg.type.length
José Fonseca5c749e32011-05-09 11:11:37 +0100561 print ' for(GLsizei i = 0; i < %s; ++i) {' % arg.type.length
José Fonsecaeced7472011-05-28 10:37:12 +0100562 print ' __writer.beginElement();'
José Fonsecafd34e4e2011-06-03 19:34:29 +0100563 print ' __writer.writeBlob(%s[i], count[i]*__gl_type_size(type));' % (arg.name)
José Fonsecaeced7472011-05-28 10:37:12 +0100564 print ' __writer.endElement();'
José Fonseca5c749e32011-05-09 11:11:37 +0100565 print ' }'
José Fonsecaeced7472011-05-28 10:37:12 +0100566 print ' __writer.endArray();'
José Fonseca5c749e32011-05-09 11:11:37 +0100567 else:
José Fonsecafd34e4e2011-06-03 19:34:29 +0100568 print ' __writer.writeBlob(%s, count*__gl_type_size(type));' % (arg.name)
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000569 print ' } else {'
José Fonseca5c749e32011-05-09 11:11:37 +0100570 Tracer.dump_arg_instance(self, function, arg)
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000571 print ' }'
572 return
573
José Fonsecae97bab92011-06-02 23:15:11 +0100574 # Recognize offsets instead of blobs when a PBO is bound
575 if function.name in self.unpack_function_names \
576 and (isinstance(arg.type, stdapi.Blob) \
577 or (isinstance(arg.type, stdapi.Const) \
578 and isinstance(arg.type.type, stdapi.Blob))):
José Fonsecac29f4f12011-06-11 12:19:05 +0100579 print ' {'
580 print ' GLint __unpack_buffer = 0;'
581 print ' __glGetIntegerv(GL_PIXEL_UNPACK_BUFFER_BINDING, &__unpack_buffer);'
582 print ' if (__unpack_buffer) {'
583 print ' __writer.writeOpaque(%s);' % arg.name
584 print ' } else {'
José Fonsecae97bab92011-06-02 23:15:11 +0100585 Tracer.dump_arg_instance(self, function, arg)
José Fonsecac29f4f12011-06-11 12:19:05 +0100586 print ' }'
José Fonsecae97bab92011-06-02 23:15:11 +0100587 print ' }'
588 return
589
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100590 # Several GL state functions take GLenum symbolic names as
591 # integer/floats; so dump the symbolic name whenever possible
José Fonseca3bcb33c2011-05-27 20:14:31 +0100592 if function.name.startswith('gl') \
593 and arg.type in (glapi.GLint, glapi.GLfloat) \
594 and arg.name == 'param':
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100595 assert arg.index > 0
596 assert function.args[arg.index - 1].name == 'pname'
597 assert function.args[arg.index - 1].type == glapi.GLenum
598 print ' if (is_symbolic_pname(pname) && is_symbolic_param(%s)) {' % arg.name
599 dump_instance(glapi.GLenum, arg.name)
600 print ' } else {'
601 Tracer.dump_arg_instance(self, function, arg)
602 print ' }'
603 return
604
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000605 Tracer.dump_arg_instance(self, function, arg)
José Fonseca99221832011-03-22 22:15:46 +0000606
José Fonseca4c938c22011-04-30 22:44:38 +0100607 def footer(self, api):
608 Tracer.footer(self, api)
José Fonseca669b1222011-02-20 09:05:10 +0000609
José Fonseca4c938c22011-04-30 22:44:38 +0100610 # A simple state tracker to track the pointer values
José Fonseca669b1222011-02-20 09:05:10 +0000611 # update the state
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000612 print 'static void __trace_user_arrays(GLuint maxindex)'
José Fonseca669b1222011-02-20 09:05:10 +0000613 print '{'
José Fonseca1a2fdd22011-04-01 00:55:09 +0100614
José Fonseca99221832011-03-22 22:15:46 +0000615 for camelcase_name, uppercase_name in self.arrays:
616 function_name = 'gl%sPointer' % camelcase_name
617 enable_name = 'GL_%s_ARRAY' % uppercase_name
618 binding_name = 'GL_%s_ARRAY_BUFFER_BINDING' % uppercase_name
José Fonseca14c21bc2011-02-20 23:32:22 +0000619 function = api.get_function_by_name(function_name)
José Fonseca99221832011-03-22 22:15:46 +0000620
621 print ' // %s' % function.name
José Fonsecafb6744f2011-04-15 11:18:37 +0100622 self.array_trace_prolog(api, uppercase_name)
623 self.array_prolog(api, uppercase_name)
624 print ' if (__glIsEnabled(%s)) {' % enable_name
José Fonseca7f5163e2011-03-31 23:37:26 +0100625 print ' GLint __binding = 0;'
626 print ' __glGetIntegerv(%s, &__binding);' % binding_name
627 print ' if (!__binding) {'
José Fonseca99221832011-03-22 22:15:46 +0000628
629 # Get the arguments via glGet*
630 for arg in function.args:
631 arg_get_enum = 'GL_%s_ARRAY_%s' % (uppercase_name, arg.name.upper())
632 arg_get_function, arg_type = TypeGetter().visit(arg.type)
José Fonseca7f5163e2011-03-31 23:37:26 +0100633 print ' %s %s = 0;' % (arg_type, arg.name)
634 print ' __%s(%s, &%s);' % (arg_get_function, arg_get_enum, arg.name)
José Fonseca99221832011-03-22 22:15:46 +0000635
636 arg_names = ', '.join([arg.name for arg in function.args[:-1]])
José Fonseca7f5163e2011-03-31 23:37:26 +0100637 print ' size_t __size = __%s_size(%s, maxindex);' % (function.name, arg_names)
José Fonseca99221832011-03-22 22:15:46 +0000638
639 # Emit a fake function
José Fonsecafb6744f2011-04-15 11:18:37 +0100640 self.array_trace_intermezzo(api, uppercase_name)
José Fonseca466753b2011-05-28 13:25:55 +0100641 print ' unsigned __call = __writer.beginEnter(&__%s_sig);' % (function.name,)
José Fonseca669b1222011-02-20 09:05:10 +0000642 for arg in function.args:
643 assert not arg.output
José Fonsecaeced7472011-05-28 10:37:12 +0100644 print ' __writer.beginArg(%u);' % (arg.index,)
José Fonseca14c21bc2011-02-20 23:32:22 +0000645 if arg.name != 'pointer':
José Fonseca99221832011-03-22 22:15:46 +0000646 dump_instance(arg.type, arg.name)
José Fonseca14c21bc2011-02-20 23:32:22 +0000647 else:
José Fonsecaeced7472011-05-28 10:37:12 +0100648 print ' __writer.writeBlob((const void *)%s, __size);' % (arg.name)
649 print ' __writer.endArg();'
José Fonseca99221832011-03-22 22:15:46 +0000650
José Fonsecaeced7472011-05-28 10:37:12 +0100651 print ' __writer.endEnter();'
652 print ' __writer.beginLeave(__call);'
653 print ' __writer.endLeave();'
José Fonseca99221832011-03-22 22:15:46 +0000654 print ' }'
José Fonseca669b1222011-02-20 09:05:10 +0000655 print ' }'
José Fonsecafb6744f2011-04-15 11:18:37 +0100656 self.array_epilog(api, uppercase_name)
657 self.array_trace_epilog(api, uppercase_name)
José Fonseca99221832011-03-22 22:15:46 +0000658 print
José Fonseca1a2fdd22011-04-01 00:55:09 +0100659
José Fonseca1601c412011-05-10 10:38:19 +0100660 # Samething, but for glVertexAttribPointer*
661 #
662 # Some variants of glVertexAttribPointer alias conventional and generic attributes:
663 # - glVertexAttribPointer: no
664 # - glVertexAttribPointerARB: implementation dependent
665 # - glVertexAttribPointerNV: yes
666 #
667 # This means that the implementations of these functions do not always
668 # alias, and they need to be considered independently.
669 #
José Fonsecad94aaac2011-06-28 20:50:49 +0100670 print ' GLboolean __vertex_program = GL_FALSE;'
671 print ' __glGetBooleanv(GL_VERTEX_PROGRAM_ARB, &__vertex_program);'
José Fonseca1601c412011-05-10 10:38:19 +0100672 for suffix in ['', 'ARB']:
José Fonsecad94aaac2011-06-28 20:50:49 +0100673 if suffix == 'ARB':
674 SUFFIX = '_' + suffix
675 logic_op = ''
676 else:
677 SUFFIX = ''
678 logic_op = '!'
679 print ' if (%s__vertex_program) {' % logic_op
José Fonseca1601c412011-05-10 10:38:19 +0100680 function_name = 'glVertexAttribPointer' + suffix
José Fonsecad94aaac2011-06-28 20:50:49 +0100681 print ' // %s' % function_name
682 print ' if (__glVertexAttribPointer%s_ptr &&' % suffix
683 print ' (__glVertexAttribPointer%s_ptr != __glVertexAttribPointer_ptr)) {' % suffix
684 print ' GLint __max_vertex_attribs = 0;'
685 print ' __glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &__max_vertex_attribs);'
686 print ' for (GLint index = 0; index < __max_vertex_attribs; ++index) {'
687 print ' GLint __enabled = 0;'
688 print ' __glGetVertexAttribiv%s(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED%s, &__enabled);' % (suffix, SUFFIX)
689 print ' if (__enabled) {'
690 print ' GLint __binding = 0;'
691 print ' __glGetVertexAttribiv%s(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING%s, &__binding);' % (suffix, SUFFIX)
692 print ' if (!__binding) {'
José Fonseca1a2fdd22011-04-01 00:55:09 +0100693
José Fonseca1601c412011-05-10 10:38:19 +0100694 function = api.get_function_by_name(function_name)
José Fonseca1a2fdd22011-04-01 00:55:09 +0100695
José Fonseca1601c412011-05-10 10:38:19 +0100696 # Get the arguments via glGet*
697 for arg in function.args[1:]:
José Fonsecad94aaac2011-06-28 20:50:49 +0100698 arg_get_enum = 'GL_VERTEX_ATTRIB_ARRAY_%s%s' % (arg.name.upper(), SUFFIX)
José Fonsecac493e3e2011-06-29 12:57:06 +0100699 arg_get_function, arg_type = TypeGetter('glGetVertexAttrib', False, suffix).visit(arg.type)
José Fonsecad94aaac2011-06-28 20:50:49 +0100700 print ' %s %s = 0;' % (arg_type, arg.name)
701 print ' __%s(index, %s, &%s);' % (arg_get_function, arg_get_enum, arg.name)
José Fonseca1601c412011-05-10 10:38:19 +0100702
703 arg_names = ', '.join([arg.name for arg in function.args[1:-1]])
José Fonsecad94aaac2011-06-28 20:50:49 +0100704 print ' size_t __size = __%s_size(%s, maxindex);' % (function.name, arg_names)
José Fonseca1a2fdd22011-04-01 00:55:09 +0100705
José Fonseca1601c412011-05-10 10:38:19 +0100706 # Emit a fake function
José Fonsecad94aaac2011-06-28 20:50:49 +0100707 print ' unsigned __call = __writer.beginEnter(&__%s_sig);' % (function.name,)
José Fonseca1601c412011-05-10 10:38:19 +0100708 for arg in function.args:
709 assert not arg.output
José Fonsecad94aaac2011-06-28 20:50:49 +0100710 print ' __writer.beginArg(%u);' % (arg.index,)
José Fonseca1601c412011-05-10 10:38:19 +0100711 if arg.name != 'pointer':
712 dump_instance(arg.type, arg.name)
713 else:
José Fonsecad94aaac2011-06-28 20:50:49 +0100714 print ' __writer.writeBlob((const void *)%s, __size);' % (arg.name)
715 print ' __writer.endArg();'
José Fonseca1601c412011-05-10 10:38:19 +0100716
José Fonsecad94aaac2011-06-28 20:50:49 +0100717 print ' __writer.endEnter();'
718 print ' __writer.beginLeave(__call);'
719 print ' __writer.endLeave();'
720 print ' }'
José Fonseca1601c412011-05-10 10:38:19 +0100721 print ' }'
722 print ' }'
723 print ' }'
724 print ' }'
725 print
José Fonseca1a2fdd22011-04-01 00:55:09 +0100726
José Fonseca669b1222011-02-20 09:05:10 +0000727 print '}'
728 print
729
José Fonsecafb6744f2011-04-15 11:18:37 +0100730 #
731 # Hooks for glTexCoordPointer, which is identical to the other array
732 # pointers except the fact that it is indexed by glClientActiveTexture.
733 #
734
735 def array_prolog(self, api, uppercase_name):
736 if uppercase_name == 'TEXTURE_COORD':
737 print ' GLint client_active_texture = 0;'
738 print ' __glGetIntegerv(GL_CLIENT_ACTIVE_TEXTURE, &client_active_texture);'
739 print ' GLint max_texture_coords = 0;'
740 print ' __glGetIntegerv(GL_MAX_TEXTURE_COORDS, &max_texture_coords);'
741 print ' for (GLint unit = 0; unit < max_texture_coords; ++unit) {'
742 print ' GLenum texture = GL_TEXTURE0 + unit;'
743 print ' __glClientActiveTexture(texture);'
744
745 def array_trace_prolog(self, api, uppercase_name):
746 if uppercase_name == 'TEXTURE_COORD':
747 print ' bool client_active_texture_dirty = false;'
748
749 def array_epilog(self, api, uppercase_name):
750 if uppercase_name == 'TEXTURE_COORD':
751 print ' }'
752 self.array_cleanup(api, uppercase_name)
753
754 def array_cleanup(self, api, uppercase_name):
755 if uppercase_name == 'TEXTURE_COORD':
756 print ' __glClientActiveTexture(client_active_texture);'
757
758 def array_trace_intermezzo(self, api, uppercase_name):
759 if uppercase_name == 'TEXTURE_COORD':
760 print ' if (texture != client_active_texture || client_active_texture_dirty) {'
761 print ' client_active_texture_dirty = true;'
762 self.fake_glClientActiveTexture_call(api, "texture");
763 print ' }'
764
765 def array_trace_epilog(self, api, uppercase_name):
766 if uppercase_name == 'TEXTURE_COORD':
767 print ' if (client_active_texture_dirty) {'
768 self.fake_glClientActiveTexture_call(api, "client_active_texture");
769 print ' }'
770
771 def fake_glClientActiveTexture_call(self, api, texture):
772 function = api.get_function_by_name('glClientActiveTexture')
773 self.fake_call(function, [texture])
774
775 def fake_call(self, function, args):
José Fonseca466753b2011-05-28 13:25:55 +0100776 print ' unsigned __fake_call = __writer.beginEnter(&__%s_sig);' % (function.name,)
José Fonsecafb6744f2011-04-15 11:18:37 +0100777 for arg, instance in zip(function.args, args):
778 assert not arg.output
José Fonsecaeced7472011-05-28 10:37:12 +0100779 print ' __writer.beginArg(%u);' % (arg.index,)
José Fonsecafb6744f2011-04-15 11:18:37 +0100780 dump_instance(arg.type, instance)
José Fonsecaeced7472011-05-28 10:37:12 +0100781 print ' __writer.endArg();'
782 print ' __writer.endEnter();'
783 print ' __writer.beginLeave(__fake_call);'
784 print ' __writer.endLeave();'
José Fonsecafb6744f2011-04-15 11:18:37 +0100785
786
787
788
789
José Fonseca669b1222011-02-20 09:05:10 +0000790
791
792
793
794
795