blob: 1e71376583db0f39a316168ee58eed6506aa08bb [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é Fonseca1a2fdd22011-04-01 00:55:09 +010040 def __init__(self, prefix = 'glGet', long_suffix = True):
41 self.prefix = prefix
42 self.long_suffix = long_suffix
43
José Fonseca99221832011-03-22 22:15:46 +000044 def visit_const(self, const):
45 return self.visit(const.type)
46
47 def visit_alias(self, alias):
48 if alias.expr == 'GLboolean':
José Fonseca1a2fdd22011-04-01 00:55:09 +010049 if self.long_suffix:
50 return self.prefix + 'Booleanv', alias.expr
51 else:
52 return self.prefix + 'iv', 'GLint'
José Fonseca99221832011-03-22 22:15:46 +000053 elif alias.expr == 'GLdouble':
José Fonseca1a2fdd22011-04-01 00:55:09 +010054 if self.long_suffix:
55 return self.prefix + 'Doublev', alias.expr
56 else:
57 return self.prefix + 'dv', alias.expr
José Fonseca99221832011-03-22 22:15:46 +000058 elif alias.expr == 'GLfloat':
José Fonseca1a2fdd22011-04-01 00:55:09 +010059 if self.long_suffix:
60 return self.prefix + 'Floatv', alias.expr
61 else:
62 return self.prefix + 'fv', alias.expr
José Fonseca7f5163e2011-03-31 23:37:26 +010063 elif alias.expr in ('GLint', 'GLuint', 'GLsizei'):
José Fonseca1a2fdd22011-04-01 00:55:09 +010064 if self.long_suffix:
65 return self.prefix + 'Integerv', 'GLint'
66 else:
67 return self.prefix + 'iv', 'GLint'
José Fonseca99221832011-03-22 22:15:46 +000068 else:
69 print alias.expr
70 assert False
71
72 def visit_enum(self, enum):
José Fonseca1a2fdd22011-04-01 00:55:09 +010073 return self.visit(glapi.GLint)
José Fonseca99221832011-03-22 22:15:46 +000074
75 def visit_bitmask(self, bitmask):
José Fonseca1a2fdd22011-04-01 00:55:09 +010076 return self.visit(glapi.GLint)
José Fonseca99221832011-03-22 22:15:46 +000077
78 def visit_opaque(self, pointer):
José Fonseca1a2fdd22011-04-01 00:55:09 +010079 return self.prefix + 'Pointerv', 'GLvoid *'
José Fonseca99221832011-03-22 22:15:46 +000080
81
José Fonseca669b1222011-02-20 09:05:10 +000082class GlTracer(Tracer):
83
José Fonseca99221832011-03-22 22:15:46 +000084 arrays = [
85 ("Vertex", "VERTEX"),
86 ("Normal", "NORMAL"),
87 ("Color", "COLOR"),
88 ("Index", "INDEX"),
89 ("TexCoord", "TEXTURE_COORD"),
90 ("EdgeFlag", "EDGE_FLAG"),
91 ("FogCoord", "FOG_COORD"),
92 ("SecondaryColor", "SECONDARY_COLOR"),
José Fonseca14c21bc2011-02-20 23:32:22 +000093 ]
José Fonsecac9f12232011-03-25 20:07:42 +000094 arrays.reverse()
José Fonseca669b1222011-02-20 09:05:10 +000095
José Fonseca4c938c22011-04-30 22:44:38 +010096 def header(self, api):
97 Tracer.header(self, api)
98
José Fonseca25ebe542011-04-24 10:08:22 +010099 print '// Whether user arrays were used'
100 print 'static bool __user_arrays = false;'
101 print
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000102 # Whether we need user arrays
103 print 'static inline bool __need_user_arrays(void)'
104 print '{'
José Fonseca25ebe542011-04-24 10:08:22 +0100105 print ' if (!__user_arrays) {'
106 print ' return false;'
107 print ' }'
108 print
José Fonseca1a2fdd22011-04-01 00:55:09 +0100109
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000110 for camelcase_name, uppercase_name in self.arrays:
111 function_name = 'gl%sPointer' % camelcase_name
112 enable_name = 'GL_%s_ARRAY' % uppercase_name
113 binding_name = 'GL_%s_ARRAY_BUFFER_BINDING' % uppercase_name
114 print ' // %s' % function_name
José Fonsecafb6744f2011-04-15 11:18:37 +0100115 self.array_prolog(api, uppercase_name)
José Fonseca7f5163e2011-03-31 23:37:26 +0100116 print ' if (__glIsEnabled(%s)) {' % enable_name
117 print ' GLint __binding = 0;'
118 print ' __glGetIntegerv(%s, &__binding);' % binding_name
119 print ' if (!__binding) {'
José Fonsecafb6744f2011-04-15 11:18:37 +0100120 self.array_cleanup(api, uppercase_name)
José Fonseca7f5163e2011-03-31 23:37:26 +0100121 print ' return true;'
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000122 print ' }'
123 print ' }'
José Fonsecafb6744f2011-04-15 11:18:37 +0100124 self.array_epilog(api, uppercase_name)
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000125 print
José Fonseca7f5163e2011-03-31 23:37:26 +0100126
José Fonsecad94aaac2011-06-28 20:50:49 +0100127 print ' GLboolean __vertex_program = GL_FALSE;'
128 print ' __glGetBooleanv(GL_VERTEX_PROGRAM_ARB, &__vertex_program);'
129 print ' if (__vertex_program) {'
130 print ' // glVertexAttribPointerARB'
131 print ' GLint __max_vertex_attribs = 0;'
132 print ' __glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &__max_vertex_attribs);'
133 print ' for (GLint index = 0; index < __max_vertex_attribs; ++index) {'
134 print ' GLint __enabled = 0;'
135 print ' __glGetVertexAttribivARB(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB, &__enabled);'
136 print ' if (__enabled) {'
137 print ' GLint __binding = 0;'
138 print ' __glGetVertexAttribivARB(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB, &__binding);'
139 print ' if (!__binding) {'
140 print ' return true;'
141 print ' }'
142 print ' }'
143 print ' }'
144 print ' } else {'
145 print ' // glVertexAttribPointer'
146 print ' GLint __max_vertex_attribs = 0;'
147 print ' __glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &__max_vertex_attribs);'
148 print ' for (GLint index = 0; index < __max_vertex_attribs; ++index) {'
149 print ' GLint __enabled = 0;'
150 print ' __glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &__enabled);'
151 print ' if (__enabled) {'
152 print ' GLint __binding = 0;'
153 print ' __glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &__binding);'
154 print ' if (!__binding) {'
155 print ' return true;'
156 print ' }'
José Fonseca1a2fdd22011-04-01 00:55:09 +0100157 print ' }'
158 print ' }'
159 print ' }'
160 print
161
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000162 print ' return false;'
163 print '}'
164 print
José Fonseca669b1222011-02-20 09:05:10 +0000165
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000166 print 'static void __trace_user_arrays(GLuint maxindex);'
José Fonseca14c21bc2011-02-20 23:32:22 +0000167 print
José Fonseca867b1b72011-04-24 11:58:04 +0100168
169 print 'struct buffer_mapping {'
170 print ' void *map;'
171 print ' GLint length;'
172 print ' bool write;'
José Fonseca73373602011-05-20 17:45:26 +0100173 print ' bool explicit_flush;'
José Fonseca867b1b72011-04-24 11:58:04 +0100174 print '};'
175 print
176 for target in self.buffer_targets:
177 print 'struct buffer_mapping __%s_mapping;' % target.lower();
178 print
179 print 'static inline struct buffer_mapping *'
180 print 'get_buffer_mapping(GLenum target) {'
181 print ' switch(target) {'
182 for target in self.buffer_targets:
183 print ' case GL_%s:' % target
184 print ' return & __%s_mapping;' % target.lower()
185 print ' default:'
José Fonsecacbd225f2011-06-09 00:07:18 +0100186 print ' OS::DebugMessage("apitrace: warning: unknown buffer target 0x%04X\\n", target);'
José Fonseca867b1b72011-04-24 11:58:04 +0100187 print ' return NULL;'
188 print ' }'
189 print '}'
190 print
191
192 # Generate memcpy's signature
193 self.trace_function_decl(glapi.memcpy)
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100194
195 # Generate a helper function to determine whether a parameter name
196 # refers to a symbolic value or not
197 print 'static bool'
198 print 'is_symbolic_pname(GLenum pname) {'
199 print ' switch(pname) {'
José Fonseca5ea91872011-05-04 09:41:55 +0100200 for function, type, count, name in glparams.parameters:
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100201 if type is glapi.GLenum:
José Fonseca4c938c22011-04-30 22:44:38 +0100202 print ' case %s:' % name
203 print ' return true;'
204 print ' default:'
205 print ' return false;'
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100206 print ' }'
207 print '}'
208 print
209
210 # Generate a helper function to determine whether a parameter value is
211 # potentially symbolic or not; i.e., if the value can be represented in
212 # an enum or not
213 print 'template<class T>'
214 print 'static inline bool'
215 print 'is_symbolic_param(T param) {'
216 print ' return static_cast<T>(static_cast<GLenum>(param)) == param;'
217 print '}'
218 print
José Fonseca4c938c22011-04-30 22:44:38 +0100219
220 # Generate a helper function to know how many elements a parameter has
221 print 'static size_t'
José Fonsecaf4aca5d2011-05-08 08:29:30 +0100222 print '__gl_param_size(GLenum pname) {'
José Fonseca4c938c22011-04-30 22:44:38 +0100223 print ' switch(pname) {'
José Fonseca5ea91872011-05-04 09:41:55 +0100224 for function, type, count, name in glparams.parameters:
José Fonseca4c938c22011-04-30 22:44:38 +0100225 if type is not None:
226 print ' case %s: return %u;' % (name, count)
227 print ' case GL_COMPRESSED_TEXTURE_FORMATS: {'
228 print ' GLint num_compressed_texture_formats = 0;'
229 print ' __glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &num_compressed_texture_formats);'
230 print ' return num_compressed_texture_formats;'
231 print ' }'
232 print ' default:'
José Fonsecacbd225f2011-06-09 00:07:18 +0100233 print r' OS::DebugMessage("apitrace: warning: %s: unknown GLenum 0x%04X\n", __FUNCTION__, pname);'
José Fonseca4c938c22011-04-30 22:44:38 +0100234 print ' return 1;'
235 print ' }'
236 print '}'
237 print
238
José Fonseca99221832011-03-22 22:15:46 +0000239 array_pointer_function_names = set((
240 "glVertexPointer",
241 "glNormalPointer",
242 "glColorPointer",
243 "glIndexPointer",
244 "glTexCoordPointer",
245 "glEdgeFlagPointer",
246 "glFogCoordPointer",
247 "glSecondaryColorPointer",
José Fonseca7f5163e2011-03-31 23:37:26 +0100248
José Fonsecaac5285b2011-05-04 11:09:08 +0100249 "glInterleavedArrays",
250
José Fonseca7e0bfd92011-04-30 23:09:03 +0100251 "glVertexPointerEXT",
252 "glNormalPointerEXT",
253 "glColorPointerEXT",
254 "glIndexPointerEXT",
255 "glTexCoordPointerEXT",
256 "glEdgeFlagPointerEXT",
257 "glFogCoordPointerEXT",
258 "glSecondaryColorPointerEXT",
José Fonseca99221832011-03-22 22:15:46 +0000259
José Fonseca7f5163e2011-03-31 23:37:26 +0100260 "glVertexAttribPointer",
261 "glVertexAttribPointerARB",
262 "glVertexAttribPointerNV",
José Fonsecaac5285b2011-05-04 11:09:08 +0100263 "glVertexAttribIPointer",
264 "glVertexAttribIPointerEXT",
José Fonseca7f5163e2011-03-31 23:37:26 +0100265 "glVertexAttribLPointer",
266 "glVertexAttribLPointerEXT",
José Fonseca99221832011-03-22 22:15:46 +0000267
268 #"glMatrixIndexPointerARB",
269 ))
270
271 draw_function_names = set((
272 'glDrawArrays',
273 'glDrawElements',
274 'glDrawRangeElements',
José Fonseca5c749e32011-05-09 11:11:37 +0100275 'glMultiDrawArrays',
276 'glMultiDrawElements',
277 'glDrawArraysInstanced',
278 'glDrawElementsInstanced',
279 'glDrawArraysInstancedARB',
280 'glDrawElementsInstancedARB',
281 'glDrawElementsBaseVertex',
282 'glDrawRangeElementsBaseVertex',
283 'glDrawElementsInstancedBaseVertex',
284 'glMultiDrawElementsBaseVertex',
285 'glDrawArraysIndirect',
286 'glDrawElementsIndirect',
287 'glDrawArraysEXT',
José Fonseca7e0bfd92011-04-30 23:09:03 +0100288 'glDrawRangeElementsEXT',
José Fonseca5c749e32011-05-09 11:11:37 +0100289 'glDrawRangeElementsEXT_size',
290 'glMultiDrawArraysEXT',
291 'glMultiDrawElementsEXT',
292 'glMultiModeDrawArraysIBM',
293 'glMultiModeDrawElementsIBM',
294 'glDrawArraysInstancedEXT',
295 'glDrawElementsInstancedEXT',
José Fonseca99221832011-03-22 22:15:46 +0000296 ))
297
José Fonsecac9f12232011-03-25 20:07:42 +0000298 interleaved_formats = [
299 'GL_V2F',
300 'GL_V3F',
301 'GL_C4UB_V2F',
302 'GL_C4UB_V3F',
303 'GL_C3F_V3F',
304 'GL_N3F_V3F',
305 'GL_C4F_N3F_V3F',
306 'GL_T2F_V3F',
307 'GL_T4F_V4F',
308 'GL_T2F_C4UB_V3F',
309 'GL_T2F_C3F_V3F',
310 'GL_T2F_N3F_V3F',
311 'GL_T2F_C4F_N3F_V3F',
312 'GL_T4F_C4F_N3F_V4F',
313 ]
314
José Fonseca14c21bc2011-02-20 23:32:22 +0000315 def trace_function_impl_body(self, function):
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000316 # Defer tracing of user array pointers...
José Fonseca99221832011-03-22 22:15:46 +0000317 if function.name in self.array_pointer_function_names:
318 print ' GLint __array_buffer = 0;'
319 print ' __glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &__array_buffer);'
320 print ' if (!__array_buffer) {'
José Fonseca25ebe542011-04-24 10:08:22 +0100321 print ' __user_arrays = true;'
José Fonseca14c21bc2011-02-20 23:32:22 +0000322 self.dispatch_function(function)
José Fonsecaac5285b2011-05-04 11:09:08 +0100323
324 # And also break down glInterleavedArrays into the individual calls
325 if function.name == 'glInterleavedArrays':
326 print
327
328 # Initialize the enable flags
329 for camelcase_name, uppercase_name in self.arrays:
330 flag_name = '__' + uppercase_name.lower()
331 print ' GLboolean %s = GL_FALSE;' % flag_name
332 print
333
334 # Switch for the interleaved formats
335 print ' switch (format) {'
336 for format in self.interleaved_formats:
337 print ' case %s:' % format
338 for camelcase_name, uppercase_name in self.arrays:
339 flag_name = '__' + uppercase_name.lower()
340 if format.find('_' + uppercase_name[0]) >= 0:
341 print ' %s = GL_TRUE;' % flag_name
342 print ' break;'
343 print ' default:'
344 print ' return;'
345 print ' }'
346 print
347
348 # Emit fake glEnableClientState/glDisableClientState flags
349 for camelcase_name, uppercase_name in self.arrays:
350 flag_name = '__' + uppercase_name.lower()
351 enable_name = 'GL_%s_ARRAY' % uppercase_name
352
353 # Emit a fake function
354 print ' {'
355 print ' static const Trace::FunctionSig &__sig = %s ? __glEnableClientState_sig : __glDisableClientState_sig;' % flag_name
José Fonseca466753b2011-05-28 13:25:55 +0100356 print ' unsigned __call = __writer.beginEnter(&__sig);'
José Fonsecaeced7472011-05-28 10:37:12 +0100357 print ' __writer.beginArg(0);'
José Fonsecaac5285b2011-05-04 11:09:08 +0100358 dump_instance(glapi.GLenum, enable_name)
José Fonsecaeced7472011-05-28 10:37:12 +0100359 print ' __writer.endArg();'
360 print ' __writer.endEnter();'
361 print ' __writer.beginLeave(__call);'
362 print ' __writer.endLeave();'
José Fonsecaac5285b2011-05-04 11:09:08 +0100363 print ' }'
364
José Fonseca99221832011-03-22 22:15:46 +0000365 print ' return;'
366 print ' }'
José Fonseca14c21bc2011-02-20 23:32:22 +0000367
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000368 # ... to the draw calls
José Fonseca99221832011-03-22 22:15:46 +0000369 if function.name in self.draw_function_names:
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000370 print ' if (__need_user_arrays()) {'
José Fonseca99221832011-03-22 22:15:46 +0000371 arg_names = ', '.join([arg.name for arg in function.args[1:]])
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000372 print ' GLuint maxindex = __%s_maxindex(%s);' % (function.name, arg_names)
373 print ' __trace_user_arrays(maxindex);'
374 print ' }'
José Fonseca14c21bc2011-02-20 23:32:22 +0000375
José Fonseca73373602011-05-20 17:45:26 +0100376 # Emit a fake memcpy on buffer uploads
377 if function.name in ('glUnmapBuffer', 'glUnmapBufferARB', ):
José Fonseca867b1b72011-04-24 11:58:04 +0100378 print ' struct buffer_mapping *mapping = get_buffer_mapping(target);'
José Fonseca73373602011-05-20 17:45:26 +0100379 print ' if (mapping && mapping->write && !mapping->explicit_flush) {'
380 self.emit_memcpy('mapping->map', 'mapping->map', 'mapping->length')
José Fonseca867b1b72011-04-24 11:58:04 +0100381 print ' }'
José Fonseca73373602011-05-20 17:45:26 +0100382 if function.name in ('glFlushMappedBufferRange', 'glFlushMappedBufferRangeAPPLE'):
383 # TODO: avoid copying [0, offset] bytes
384 print ' struct buffer_mapping *mapping = get_buffer_mapping(target);'
385 print ' if (mapping) {'
386 if function.name.endswith('APPLE'):
387 print ' GLsizeiptr length = size;'
388 print ' mapping->explicit_flush = true;'
389 print ' //assert(offset + length <= mapping->length);'
390 self.emit_memcpy('mapping->map', 'mapping->map', 'offset + length')
391 print ' }'
392 # FIXME: glFlushMappedNamedBufferRangeEXT
José Fonseca867b1b72011-04-24 11:58:04 +0100393
José Fonseca91492d22011-05-23 21:20:31 +0100394 # Don't leave vertex attrib locations to chance. Instead emit fake
395 # glBindAttribLocation calls to ensure that the same locations will be
396 # used when retracing. Trying to remap locations after the fact would
397 # be an herculian task given that vertex attrib locations appear in
398 # many entry-points, including non-shader related ones.
399 if function.name == 'glLinkProgram':
400 Tracer.dispatch_function(self, function)
401 print ' GLint active_attributes = 0;'
402 print ' __glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &active_attributes);'
403 print ' for (GLuint attrib = 0; attrib < active_attributes; ++attrib) {'
404 print ' GLint size = 0;'
405 print ' GLenum type = 0;'
406 print ' GLchar name[256];'
407 # TODO: Use ACTIVE_ATTRIBUTE_MAX_LENGTH instead of 256
408 print ' __glGetActiveAttrib(program, attrib, sizeof name, NULL, &size, &type, name);'
José Fonseca2a794f52011-05-26 20:54:29 +0100409 print " if (name[0] != 'g' || name[1] != 'l' || name[2] != '_') {"
410 print ' GLint location = __glGetAttribLocation(program, name);'
411 print ' if (location >= 0) {'
José Fonseca91492d22011-05-23 21:20:31 +0100412 bind_function = glapi.glapi.get_function_by_name('glBindAttribLocation')
413 self.fake_call(bind_function, ['program', 'location', 'name'])
José Fonseca2a794f52011-05-26 20:54:29 +0100414 print ' }'
José Fonseca91492d22011-05-23 21:20:31 +0100415 print ' }'
416 print ' }'
417 if function.name == 'glLinkProgramARB':
418 Tracer.dispatch_function(self, function)
419 print ' GLint active_attributes = 0;'
420 print ' __glGetObjectParameterivARB(programObj, GL_OBJECT_ACTIVE_ATTRIBUTES_ARB, &active_attributes);'
421 print ' for (GLuint attrib = 0; attrib < active_attributes; ++attrib) {'
422 print ' GLint size = 0;'
423 print ' GLenum type = 0;'
424 print ' GLcharARB name[256];'
425 # TODO: Use ACTIVE_ATTRIBUTE_MAX_LENGTH instead of 256
426 print ' __glGetActiveAttribARB(programObj, attrib, sizeof name, NULL, &size, &type, name);'
José Fonseca2a794f52011-05-26 20:54:29 +0100427 print " if (name[0] != 'g' || name[1] != 'l' || name[2] != '_') {"
428 print ' GLint location = __glGetAttribLocationARB(programObj, name);'
429 print ' if (location >= 0) {'
José Fonseca91492d22011-05-23 21:20:31 +0100430 bind_function = glapi.glapi.get_function_by_name('glBindAttribLocationARB')
431 self.fake_call(bind_function, ['programObj', 'location', 'name'])
José Fonseca2a794f52011-05-26 20:54:29 +0100432 print ' }'
José Fonseca91492d22011-05-23 21:20:31 +0100433 print ' }'
434 print ' }'
435
José Fonseca14c21bc2011-02-20 23:32:22 +0000436 Tracer.trace_function_impl_body(self, function)
José Fonseca73373602011-05-20 17:45:26 +0100437
José Fonseca91492d22011-05-23 21:20:31 +0100438 def dispatch_function(self, function):
439 if function.name in ('glLinkProgram', 'glLinkProgramARB'):
440 # These functions have been dispatched already
441 return
442
443 Tracer.dispatch_function(self, function)
444
José Fonseca73373602011-05-20 17:45:26 +0100445 def emit_memcpy(self, dest, src, length):
José Fonseca466753b2011-05-28 13:25:55 +0100446 print ' unsigned __call = __writer.beginEnter(&__memcpy_sig);'
José Fonsecaeced7472011-05-28 10:37:12 +0100447 print ' __writer.beginArg(0);'
448 print ' __writer.writeOpaque(%s);' % dest
449 print ' __writer.endArg();'
450 print ' __writer.beginArg(1);'
451 print ' __writer.writeBlob(%s, %s);' % (src, length)
452 print ' __writer.endArg();'
453 print ' __writer.beginArg(2);'
454 print ' __writer.writeUInt(%s);' % length
455 print ' __writer.endArg();'
456 print ' __writer.endEnter();'
457 print ' __writer.beginLeave(__call);'
458 print ' __writer.endLeave();'
José Fonseca867b1b72011-04-24 11:58:04 +0100459
460 buffer_targets = [
461 'ARRAY_BUFFER',
462 'ELEMENT_ARRAY_BUFFER',
463 'PIXEL_PACK_BUFFER',
464 'PIXEL_UNPACK_BUFFER',
465 ]
466
467 def wrap_ret(self, function, instance):
468 Tracer.wrap_ret(self, function, instance)
469
470 if function.name in ('glMapBuffer', 'glMapBufferARB'):
471 print ' struct buffer_mapping *mapping = get_buffer_mapping(target);'
472 print ' if (mapping) {'
473 print ' mapping->map = %s;' % (instance)
474 print ' mapping->length = 0;'
475 print ' __glGetBufferParameteriv(target, GL_BUFFER_SIZE, &mapping->length);'
476 print ' mapping->write = (access != GL_READ_ONLY);'
José Fonseca73373602011-05-20 17:45:26 +0100477 print ' mapping->explicit_flush = false;'
José Fonseca867b1b72011-04-24 11:58:04 +0100478 print ' }'
479
480 if function.name == 'glMapBufferRange':
481 print ' struct buffer_mapping *mapping = get_buffer_mapping(target);'
482 print ' if (mapping) {'
483 print ' mapping->map = %s;' % (instance)
484 print ' mapping->length = length;'
485 print ' mapping->write = access & GL_MAP_WRITE_BIT;'
José Fonseca73373602011-05-20 17:45:26 +0100486 print ' mapping->explicit_flush = access & GL_MAP_FLUSH_EXPLICIT_BIT;'
José Fonseca867b1b72011-04-24 11:58:04 +0100487 print ' }'
José Fonseca669b1222011-02-20 09:05:10 +0000488
José Fonsecac9f12232011-03-25 20:07:42 +0000489 boolean_names = [
490 'GL_FALSE',
491 'GL_TRUE',
492 ]
493
494 def gl_boolean(self, value):
495 return self.boolean_names[int(bool(value))]
496
José Fonsecac29f4f12011-06-11 12:19:05 +0100497 # Names of the functions that unpack from a pixel buffer object. See the
498 # ARB_pixel_buffer_object specification.
José Fonsecae97bab92011-06-02 23:15:11 +0100499 unpack_function_names = set([
500 'glBitmap',
José Fonsecac29f4f12011-06-11 12:19:05 +0100501 'glColorSubTable',
502 'glColorTable',
503 'glCompressedTexImage1D',
504 'glCompressedTexImage2D',
505 'glCompressedTexImage3D',
506 'glCompressedTexSubImage1D',
507 'glCompressedTexSubImage2D',
508 'glCompressedTexSubImage3D',
509 'glConvolutionFilter1D',
510 'glConvolutionFilter2D',
José Fonsecae97bab92011-06-02 23:15:11 +0100511 'glDrawPixels',
512 'glMultiTexImage1DEXT',
513 'glMultiTexImage2DEXT',
514 'glMultiTexImage3DEXT',
515 'glMultiTexSubImage1DEXT',
516 'glMultiTexSubImage2DEXT',
517 'glMultiTexSubImage3DEXT',
José Fonsecac29f4f12011-06-11 12:19:05 +0100518 'glPixelMapfv',
519 'glPixelMapuiv',
520 'glPixelMapusv',
José Fonsecae97bab92011-06-02 23:15:11 +0100521 'glPolygonStipple',
José Fonsecac29f4f12011-06-11 12:19:05 +0100522 'glSeparableFilter2D',
José Fonsecae97bab92011-06-02 23:15:11 +0100523 'glTexImage1D',
524 'glTexImage1DEXT',
525 'glTexImage2D',
526 'glTexImage2DEXT',
527 'glTexImage3D',
528 'glTexImage3DEXT',
529 'glTexSubImage1D',
530 'glTexSubImage1DEXT',
531 'glTexSubImage2D',
532 'glTexSubImage2DEXT',
533 'glTexSubImage3D',
534 'glTexSubImage3DEXT',
535 'glTextureImage1DEXT',
536 'glTextureImage2DEXT',
537 'glTextureImage3DEXT',
538 'glTextureSubImage1DEXT',
539 'glTextureSubImage2DEXT',
540 'glTextureSubImage3DEXT',
541 ])
542
José Fonseca99221832011-03-22 22:15:46 +0000543 def dump_arg_instance(self, function, arg):
544 if function.name in self.draw_function_names and arg.name == 'indices':
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000545 print ' GLint __element_array_buffer = 0;'
546 print ' __glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &__element_array_buffer);'
547 print ' if (!__element_array_buffer) {'
José Fonseca5c749e32011-05-09 11:11:37 +0100548 if isinstance(arg.type, stdapi.Array):
José Fonsecaeced7472011-05-28 10:37:12 +0100549 print ' __writer.beginArray(%s);' % arg.type.length
José Fonseca5c749e32011-05-09 11:11:37 +0100550 print ' for(GLsizei i = 0; i < %s; ++i) {' % arg.type.length
José Fonsecaeced7472011-05-28 10:37:12 +0100551 print ' __writer.beginElement();'
José Fonsecafd34e4e2011-06-03 19:34:29 +0100552 print ' __writer.writeBlob(%s[i], count[i]*__gl_type_size(type));' % (arg.name)
José Fonsecaeced7472011-05-28 10:37:12 +0100553 print ' __writer.endElement();'
José Fonseca5c749e32011-05-09 11:11:37 +0100554 print ' }'
José Fonsecaeced7472011-05-28 10:37:12 +0100555 print ' __writer.endArray();'
José Fonseca5c749e32011-05-09 11:11:37 +0100556 else:
José Fonsecafd34e4e2011-06-03 19:34:29 +0100557 print ' __writer.writeBlob(%s, count*__gl_type_size(type));' % (arg.name)
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000558 print ' } else {'
José Fonseca5c749e32011-05-09 11:11:37 +0100559 Tracer.dump_arg_instance(self, function, arg)
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000560 print ' }'
561 return
562
José Fonsecae97bab92011-06-02 23:15:11 +0100563 # Recognize offsets instead of blobs when a PBO is bound
564 if function.name in self.unpack_function_names \
565 and (isinstance(arg.type, stdapi.Blob) \
566 or (isinstance(arg.type, stdapi.Const) \
567 and isinstance(arg.type.type, stdapi.Blob))):
José Fonsecac29f4f12011-06-11 12:19:05 +0100568 print ' {'
569 print ' GLint __unpack_buffer = 0;'
570 print ' __glGetIntegerv(GL_PIXEL_UNPACK_BUFFER_BINDING, &__unpack_buffer);'
571 print ' if (__unpack_buffer) {'
572 print ' __writer.writeOpaque(%s);' % arg.name
573 print ' } else {'
José Fonsecae97bab92011-06-02 23:15:11 +0100574 Tracer.dump_arg_instance(self, function, arg)
José Fonsecac29f4f12011-06-11 12:19:05 +0100575 print ' }'
José Fonsecae97bab92011-06-02 23:15:11 +0100576 print ' }'
577 return
578
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100579 # Several GL state functions take GLenum symbolic names as
580 # integer/floats; so dump the symbolic name whenever possible
José Fonseca3bcb33c2011-05-27 20:14:31 +0100581 if function.name.startswith('gl') \
582 and arg.type in (glapi.GLint, glapi.GLfloat) \
583 and arg.name == 'param':
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100584 assert arg.index > 0
585 assert function.args[arg.index - 1].name == 'pname'
586 assert function.args[arg.index - 1].type == glapi.GLenum
587 print ' if (is_symbolic_pname(pname) && is_symbolic_param(%s)) {' % arg.name
588 dump_instance(glapi.GLenum, arg.name)
589 print ' } else {'
590 Tracer.dump_arg_instance(self, function, arg)
591 print ' }'
592 return
593
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000594 Tracer.dump_arg_instance(self, function, arg)
José Fonseca99221832011-03-22 22:15:46 +0000595
José Fonseca4c938c22011-04-30 22:44:38 +0100596 def footer(self, api):
597 Tracer.footer(self, api)
José Fonseca669b1222011-02-20 09:05:10 +0000598
José Fonseca4c938c22011-04-30 22:44:38 +0100599 # A simple state tracker to track the pointer values
José Fonseca669b1222011-02-20 09:05:10 +0000600 # update the state
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000601 print 'static void __trace_user_arrays(GLuint maxindex)'
José Fonseca669b1222011-02-20 09:05:10 +0000602 print '{'
José Fonseca1a2fdd22011-04-01 00:55:09 +0100603
José Fonseca99221832011-03-22 22:15:46 +0000604 for camelcase_name, uppercase_name in self.arrays:
605 function_name = 'gl%sPointer' % camelcase_name
606 enable_name = 'GL_%s_ARRAY' % uppercase_name
607 binding_name = 'GL_%s_ARRAY_BUFFER_BINDING' % uppercase_name
José Fonseca14c21bc2011-02-20 23:32:22 +0000608 function = api.get_function_by_name(function_name)
José Fonseca99221832011-03-22 22:15:46 +0000609
610 print ' // %s' % function.name
José Fonsecafb6744f2011-04-15 11:18:37 +0100611 self.array_trace_prolog(api, uppercase_name)
612 self.array_prolog(api, uppercase_name)
613 print ' if (__glIsEnabled(%s)) {' % enable_name
José Fonseca7f5163e2011-03-31 23:37:26 +0100614 print ' GLint __binding = 0;'
615 print ' __glGetIntegerv(%s, &__binding);' % binding_name
616 print ' if (!__binding) {'
José Fonseca99221832011-03-22 22:15:46 +0000617
618 # Get the arguments via glGet*
619 for arg in function.args:
620 arg_get_enum = 'GL_%s_ARRAY_%s' % (uppercase_name, arg.name.upper())
621 arg_get_function, arg_type = TypeGetter().visit(arg.type)
José Fonseca7f5163e2011-03-31 23:37:26 +0100622 print ' %s %s = 0;' % (arg_type, arg.name)
623 print ' __%s(%s, &%s);' % (arg_get_function, arg_get_enum, arg.name)
José Fonseca99221832011-03-22 22:15:46 +0000624
625 arg_names = ', '.join([arg.name for arg in function.args[:-1]])
José Fonseca7f5163e2011-03-31 23:37:26 +0100626 print ' size_t __size = __%s_size(%s, maxindex);' % (function.name, arg_names)
José Fonseca99221832011-03-22 22:15:46 +0000627
628 # Emit a fake function
José Fonsecafb6744f2011-04-15 11:18:37 +0100629 self.array_trace_intermezzo(api, uppercase_name)
José Fonseca466753b2011-05-28 13:25:55 +0100630 print ' unsigned __call = __writer.beginEnter(&__%s_sig);' % (function.name,)
José Fonseca669b1222011-02-20 09:05:10 +0000631 for arg in function.args:
632 assert not arg.output
José Fonsecaeced7472011-05-28 10:37:12 +0100633 print ' __writer.beginArg(%u);' % (arg.index,)
José Fonseca14c21bc2011-02-20 23:32:22 +0000634 if arg.name != 'pointer':
José Fonseca99221832011-03-22 22:15:46 +0000635 dump_instance(arg.type, arg.name)
José Fonseca14c21bc2011-02-20 23:32:22 +0000636 else:
José Fonsecaeced7472011-05-28 10:37:12 +0100637 print ' __writer.writeBlob((const void *)%s, __size);' % (arg.name)
638 print ' __writer.endArg();'
José Fonseca99221832011-03-22 22:15:46 +0000639
José Fonsecaeced7472011-05-28 10:37:12 +0100640 print ' __writer.endEnter();'
641 print ' __writer.beginLeave(__call);'
642 print ' __writer.endLeave();'
José Fonseca99221832011-03-22 22:15:46 +0000643 print ' }'
José Fonseca669b1222011-02-20 09:05:10 +0000644 print ' }'
José Fonsecafb6744f2011-04-15 11:18:37 +0100645 self.array_epilog(api, uppercase_name)
646 self.array_trace_epilog(api, uppercase_name)
José Fonseca99221832011-03-22 22:15:46 +0000647 print
José Fonseca1a2fdd22011-04-01 00:55:09 +0100648
José Fonseca1601c412011-05-10 10:38:19 +0100649 # Samething, but for glVertexAttribPointer*
650 #
651 # Some variants of glVertexAttribPointer alias conventional and generic attributes:
652 # - glVertexAttribPointer: no
653 # - glVertexAttribPointerARB: implementation dependent
654 # - glVertexAttribPointerNV: yes
655 #
656 # This means that the implementations of these functions do not always
657 # alias, and they need to be considered independently.
658 #
José Fonsecad94aaac2011-06-28 20:50:49 +0100659 print ' GLboolean __vertex_program = GL_FALSE;'
660 print ' __glGetBooleanv(GL_VERTEX_PROGRAM_ARB, &__vertex_program);'
José Fonseca1601c412011-05-10 10:38:19 +0100661 for suffix in ['', 'ARB']:
José Fonsecad94aaac2011-06-28 20:50:49 +0100662 if suffix == 'ARB':
663 SUFFIX = '_' + suffix
664 logic_op = ''
665 else:
666 SUFFIX = ''
667 logic_op = '!'
668 print ' if (%s__vertex_program) {' % logic_op
José Fonseca1601c412011-05-10 10:38:19 +0100669 function_name = 'glVertexAttribPointer' + suffix
José Fonsecad94aaac2011-06-28 20:50:49 +0100670 print ' // %s' % function_name
671 print ' if (__glVertexAttribPointer%s_ptr &&' % suffix
672 print ' (__glVertexAttribPointer%s_ptr != __glVertexAttribPointer_ptr)) {' % suffix
673 print ' GLint __max_vertex_attribs = 0;'
674 print ' __glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &__max_vertex_attribs);'
675 print ' for (GLint index = 0; index < __max_vertex_attribs; ++index) {'
676 print ' GLint __enabled = 0;'
677 print ' __glGetVertexAttribiv%s(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED%s, &__enabled);' % (suffix, SUFFIX)
678 print ' if (__enabled) {'
679 print ' GLint __binding = 0;'
680 print ' __glGetVertexAttribiv%s(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING%s, &__binding);' % (suffix, SUFFIX)
681 print ' if (!__binding) {'
José Fonseca1a2fdd22011-04-01 00:55:09 +0100682
José Fonseca1601c412011-05-10 10:38:19 +0100683 function = api.get_function_by_name(function_name)
José Fonseca1a2fdd22011-04-01 00:55:09 +0100684
José Fonseca1601c412011-05-10 10:38:19 +0100685 # Get the arguments via glGet*
686 for arg in function.args[1:]:
José Fonsecad94aaac2011-06-28 20:50:49 +0100687 arg_get_enum = 'GL_VERTEX_ATTRIB_ARRAY_%s%s' % (arg.name.upper(), SUFFIX)
José Fonseca1601c412011-05-10 10:38:19 +0100688 arg_get_function, arg_type = TypeGetter('glGetVertexAttrib', False).visit(arg.type)
José Fonsecad94aaac2011-06-28 20:50:49 +0100689 print ' %s %s = 0;' % (arg_type, arg.name)
690 print ' __%s(index, %s, &%s);' % (arg_get_function, arg_get_enum, arg.name)
José Fonseca1601c412011-05-10 10:38:19 +0100691
692 arg_names = ', '.join([arg.name for arg in function.args[1:-1]])
José Fonsecad94aaac2011-06-28 20:50:49 +0100693 print ' size_t __size = __%s_size(%s, maxindex);' % (function.name, arg_names)
José Fonseca1a2fdd22011-04-01 00:55:09 +0100694
José Fonseca1601c412011-05-10 10:38:19 +0100695 # Emit a fake function
José Fonsecad94aaac2011-06-28 20:50:49 +0100696 print ' unsigned __call = __writer.beginEnter(&__%s_sig);' % (function.name,)
José Fonseca1601c412011-05-10 10:38:19 +0100697 for arg in function.args:
698 assert not arg.output
José Fonsecad94aaac2011-06-28 20:50:49 +0100699 print ' __writer.beginArg(%u);' % (arg.index,)
José Fonseca1601c412011-05-10 10:38:19 +0100700 if arg.name != 'pointer':
701 dump_instance(arg.type, arg.name)
702 else:
José Fonsecad94aaac2011-06-28 20:50:49 +0100703 print ' __writer.writeBlob((const void *)%s, __size);' % (arg.name)
704 print ' __writer.endArg();'
José Fonseca1601c412011-05-10 10:38:19 +0100705
José Fonsecad94aaac2011-06-28 20:50:49 +0100706 print ' __writer.endEnter();'
707 print ' __writer.beginLeave(__call);'
708 print ' __writer.endLeave();'
709 print ' }'
José Fonseca1601c412011-05-10 10:38:19 +0100710 print ' }'
711 print ' }'
712 print ' }'
713 print ' }'
714 print
José Fonseca1a2fdd22011-04-01 00:55:09 +0100715
José Fonseca669b1222011-02-20 09:05:10 +0000716 print '}'
717 print
718
José Fonsecafb6744f2011-04-15 11:18:37 +0100719 #
720 # Hooks for glTexCoordPointer, which is identical to the other array
721 # pointers except the fact that it is indexed by glClientActiveTexture.
722 #
723
724 def array_prolog(self, api, uppercase_name):
725 if uppercase_name == 'TEXTURE_COORD':
726 print ' GLint client_active_texture = 0;'
727 print ' __glGetIntegerv(GL_CLIENT_ACTIVE_TEXTURE, &client_active_texture);'
728 print ' GLint max_texture_coords = 0;'
729 print ' __glGetIntegerv(GL_MAX_TEXTURE_COORDS, &max_texture_coords);'
730 print ' for (GLint unit = 0; unit < max_texture_coords; ++unit) {'
731 print ' GLenum texture = GL_TEXTURE0 + unit;'
732 print ' __glClientActiveTexture(texture);'
733
734 def array_trace_prolog(self, api, uppercase_name):
735 if uppercase_name == 'TEXTURE_COORD':
736 print ' bool client_active_texture_dirty = false;'
737
738 def array_epilog(self, api, uppercase_name):
739 if uppercase_name == 'TEXTURE_COORD':
740 print ' }'
741 self.array_cleanup(api, uppercase_name)
742
743 def array_cleanup(self, api, uppercase_name):
744 if uppercase_name == 'TEXTURE_COORD':
745 print ' __glClientActiveTexture(client_active_texture);'
746
747 def array_trace_intermezzo(self, api, uppercase_name):
748 if uppercase_name == 'TEXTURE_COORD':
749 print ' if (texture != client_active_texture || client_active_texture_dirty) {'
750 print ' client_active_texture_dirty = true;'
751 self.fake_glClientActiveTexture_call(api, "texture");
752 print ' }'
753
754 def array_trace_epilog(self, api, uppercase_name):
755 if uppercase_name == 'TEXTURE_COORD':
756 print ' if (client_active_texture_dirty) {'
757 self.fake_glClientActiveTexture_call(api, "client_active_texture");
758 print ' }'
759
760 def fake_glClientActiveTexture_call(self, api, texture):
761 function = api.get_function_by_name('glClientActiveTexture')
762 self.fake_call(function, [texture])
763
764 def fake_call(self, function, args):
José Fonseca466753b2011-05-28 13:25:55 +0100765 print ' unsigned __fake_call = __writer.beginEnter(&__%s_sig);' % (function.name,)
José Fonsecafb6744f2011-04-15 11:18:37 +0100766 for arg, instance in zip(function.args, args):
767 assert not arg.output
José Fonsecaeced7472011-05-28 10:37:12 +0100768 print ' __writer.beginArg(%u);' % (arg.index,)
José Fonsecafb6744f2011-04-15 11:18:37 +0100769 dump_instance(arg.type, instance)
José Fonsecaeced7472011-05-28 10:37:12 +0100770 print ' __writer.endArg();'
771 print ' __writer.endEnter();'
772 print ' __writer.beginLeave(__fake_call);'
773 print ' __writer.endLeave();'
José Fonsecafb6744f2011-04-15 11:18:37 +0100774
775
776
777
778
José Fonseca669b1222011-02-20 09:05:10 +0000779
780
781
782
783
784