blob: 5dbef389231f63cbb680cb0e4d3081e0d42b087a [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é Fonseca1a2fdd22011-04-01 00:55:09 +0100127 print ' // glVertexAttribPointer'
José Fonseca0a965252011-04-14 09:21:15 +0100128 print ' GLint __max_vertex_attribs = 0;'
José Fonseca1a2fdd22011-04-01 00:55:09 +0100129 print ' __glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &__max_vertex_attribs);'
130 print ' for (GLint index = 0; index < __max_vertex_attribs; ++index) {'
131 print ' GLint __enabled = 0;'
132 print ' __glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &__enabled);'
133 print ' if (__enabled) {'
134 print ' GLint __binding = 0;'
135 print ' __glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &__binding);'
136 print ' if (!__binding) {'
137 print ' return true;'
138 print ' }'
139 print ' }'
140 print ' }'
141 print
142
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000143 print ' return false;'
144 print '}'
145 print
José Fonseca669b1222011-02-20 09:05:10 +0000146
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000147 print 'static void __trace_user_arrays(GLuint maxindex);'
José Fonseca14c21bc2011-02-20 23:32:22 +0000148 print
José Fonseca867b1b72011-04-24 11:58:04 +0100149
150 print 'struct buffer_mapping {'
151 print ' void *map;'
152 print ' GLint length;'
153 print ' bool write;'
José Fonseca73373602011-05-20 17:45:26 +0100154 print ' bool explicit_flush;'
José Fonseca867b1b72011-04-24 11:58:04 +0100155 print '};'
156 print
157 for target in self.buffer_targets:
158 print 'struct buffer_mapping __%s_mapping;' % target.lower();
159 print
160 print 'static inline struct buffer_mapping *'
161 print 'get_buffer_mapping(GLenum target) {'
162 print ' switch(target) {'
163 for target in self.buffer_targets:
164 print ' case GL_%s:' % target
165 print ' return & __%s_mapping;' % target.lower()
166 print ' default:'
José Fonsecacbd225f2011-06-09 00:07:18 +0100167 print ' OS::DebugMessage("apitrace: warning: unknown buffer target 0x%04X\\n", target);'
José Fonseca867b1b72011-04-24 11:58:04 +0100168 print ' return NULL;'
169 print ' }'
170 print '}'
171 print
172
173 # Generate memcpy's signature
174 self.trace_function_decl(glapi.memcpy)
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100175
176 # Generate a helper function to determine whether a parameter name
177 # refers to a symbolic value or not
178 print 'static bool'
179 print 'is_symbolic_pname(GLenum pname) {'
180 print ' switch(pname) {'
José Fonseca5ea91872011-05-04 09:41:55 +0100181 for function, type, count, name in glparams.parameters:
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100182 if type is glapi.GLenum:
José Fonseca4c938c22011-04-30 22:44:38 +0100183 print ' case %s:' % name
184 print ' return true;'
185 print ' default:'
186 print ' return false;'
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100187 print ' }'
188 print '}'
189 print
190
191 # Generate a helper function to determine whether a parameter value is
192 # potentially symbolic or not; i.e., if the value can be represented in
193 # an enum or not
194 print 'template<class T>'
195 print 'static inline bool'
196 print 'is_symbolic_param(T param) {'
197 print ' return static_cast<T>(static_cast<GLenum>(param)) == param;'
198 print '}'
199 print
José Fonseca4c938c22011-04-30 22:44:38 +0100200
201 # Generate a helper function to know how many elements a parameter has
202 print 'static size_t'
José Fonsecaf4aca5d2011-05-08 08:29:30 +0100203 print '__gl_param_size(GLenum pname) {'
José Fonseca4c938c22011-04-30 22:44:38 +0100204 print ' switch(pname) {'
José Fonseca5ea91872011-05-04 09:41:55 +0100205 for function, type, count, name in glparams.parameters:
José Fonseca4c938c22011-04-30 22:44:38 +0100206 if type is not None:
207 print ' case %s: return %u;' % (name, count)
208 print ' case GL_COMPRESSED_TEXTURE_FORMATS: {'
209 print ' GLint num_compressed_texture_formats = 0;'
210 print ' __glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &num_compressed_texture_formats);'
211 print ' return num_compressed_texture_formats;'
212 print ' }'
213 print ' default:'
José Fonsecacbd225f2011-06-09 00:07:18 +0100214 print r' OS::DebugMessage("apitrace: warning: %s: unknown GLenum 0x%04X\n", __FUNCTION__, pname);'
José Fonseca4c938c22011-04-30 22:44:38 +0100215 print ' return 1;'
216 print ' }'
217 print '}'
218 print
219
José Fonseca99221832011-03-22 22:15:46 +0000220 array_pointer_function_names = set((
221 "glVertexPointer",
222 "glNormalPointer",
223 "glColorPointer",
224 "glIndexPointer",
225 "glTexCoordPointer",
226 "glEdgeFlagPointer",
227 "glFogCoordPointer",
228 "glSecondaryColorPointer",
José Fonseca7f5163e2011-03-31 23:37:26 +0100229
José Fonsecaac5285b2011-05-04 11:09:08 +0100230 "glInterleavedArrays",
231
José Fonseca7e0bfd92011-04-30 23:09:03 +0100232 "glVertexPointerEXT",
233 "glNormalPointerEXT",
234 "glColorPointerEXT",
235 "glIndexPointerEXT",
236 "glTexCoordPointerEXT",
237 "glEdgeFlagPointerEXT",
238 "glFogCoordPointerEXT",
239 "glSecondaryColorPointerEXT",
José Fonseca99221832011-03-22 22:15:46 +0000240
José Fonseca7f5163e2011-03-31 23:37:26 +0100241 "glVertexAttribPointer",
242 "glVertexAttribPointerARB",
243 "glVertexAttribPointerNV",
José Fonsecaac5285b2011-05-04 11:09:08 +0100244 "glVertexAttribIPointer",
245 "glVertexAttribIPointerEXT",
José Fonseca7f5163e2011-03-31 23:37:26 +0100246 "glVertexAttribLPointer",
247 "glVertexAttribLPointerEXT",
José Fonseca99221832011-03-22 22:15:46 +0000248
249 #"glMatrixIndexPointerARB",
250 ))
251
252 draw_function_names = set((
253 'glDrawArrays',
254 'glDrawElements',
255 'glDrawRangeElements',
José Fonseca5c749e32011-05-09 11:11:37 +0100256 'glMultiDrawArrays',
257 'glMultiDrawElements',
258 'glDrawArraysInstanced',
259 'glDrawElementsInstanced',
260 'glDrawArraysInstancedARB',
261 'glDrawElementsInstancedARB',
262 'glDrawElementsBaseVertex',
263 'glDrawRangeElementsBaseVertex',
264 'glDrawElementsInstancedBaseVertex',
265 'glMultiDrawElementsBaseVertex',
266 'glDrawArraysIndirect',
267 'glDrawElementsIndirect',
268 'glDrawArraysEXT',
José Fonseca7e0bfd92011-04-30 23:09:03 +0100269 'glDrawRangeElementsEXT',
José Fonseca5c749e32011-05-09 11:11:37 +0100270 'glDrawRangeElementsEXT_size',
271 'glMultiDrawArraysEXT',
272 'glMultiDrawElementsEXT',
273 'glMultiModeDrawArraysIBM',
274 'glMultiModeDrawElementsIBM',
275 'glDrawArraysInstancedEXT',
276 'glDrawElementsInstancedEXT',
José Fonseca99221832011-03-22 22:15:46 +0000277 ))
278
José Fonsecac9f12232011-03-25 20:07:42 +0000279 interleaved_formats = [
280 'GL_V2F',
281 'GL_V3F',
282 'GL_C4UB_V2F',
283 'GL_C4UB_V3F',
284 'GL_C3F_V3F',
285 'GL_N3F_V3F',
286 'GL_C4F_N3F_V3F',
287 'GL_T2F_V3F',
288 'GL_T4F_V4F',
289 'GL_T2F_C4UB_V3F',
290 'GL_T2F_C3F_V3F',
291 'GL_T2F_N3F_V3F',
292 'GL_T2F_C4F_N3F_V3F',
293 'GL_T4F_C4F_N3F_V4F',
294 ]
295
José Fonseca14c21bc2011-02-20 23:32:22 +0000296 def trace_function_impl_body(self, function):
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000297 # Defer tracing of user array pointers...
José Fonseca99221832011-03-22 22:15:46 +0000298 if function.name in self.array_pointer_function_names:
299 print ' GLint __array_buffer = 0;'
300 print ' __glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &__array_buffer);'
301 print ' if (!__array_buffer) {'
José Fonseca25ebe542011-04-24 10:08:22 +0100302 print ' __user_arrays = true;'
José Fonseca14c21bc2011-02-20 23:32:22 +0000303 self.dispatch_function(function)
José Fonsecaac5285b2011-05-04 11:09:08 +0100304
305 # And also break down glInterleavedArrays into the individual calls
306 if function.name == 'glInterleavedArrays':
307 print
308
309 # Initialize the enable flags
310 for camelcase_name, uppercase_name in self.arrays:
311 flag_name = '__' + uppercase_name.lower()
312 print ' GLboolean %s = GL_FALSE;' % flag_name
313 print
314
315 # Switch for the interleaved formats
316 print ' switch (format) {'
317 for format in self.interleaved_formats:
318 print ' case %s:' % format
319 for camelcase_name, uppercase_name in self.arrays:
320 flag_name = '__' + uppercase_name.lower()
321 if format.find('_' + uppercase_name[0]) >= 0:
322 print ' %s = GL_TRUE;' % flag_name
323 print ' break;'
324 print ' default:'
325 print ' return;'
326 print ' }'
327 print
328
329 # Emit fake glEnableClientState/glDisableClientState flags
330 for camelcase_name, uppercase_name in self.arrays:
331 flag_name = '__' + uppercase_name.lower()
332 enable_name = 'GL_%s_ARRAY' % uppercase_name
333
334 # Emit a fake function
335 print ' {'
336 print ' static const Trace::FunctionSig &__sig = %s ? __glEnableClientState_sig : __glDisableClientState_sig;' % flag_name
José Fonseca466753b2011-05-28 13:25:55 +0100337 print ' unsigned __call = __writer.beginEnter(&__sig);'
José Fonsecaeced7472011-05-28 10:37:12 +0100338 print ' __writer.beginArg(0);'
José Fonsecaac5285b2011-05-04 11:09:08 +0100339 dump_instance(glapi.GLenum, enable_name)
José Fonsecaeced7472011-05-28 10:37:12 +0100340 print ' __writer.endArg();'
341 print ' __writer.endEnter();'
342 print ' __writer.beginLeave(__call);'
343 print ' __writer.endLeave();'
José Fonsecaac5285b2011-05-04 11:09:08 +0100344 print ' }'
345
José Fonseca99221832011-03-22 22:15:46 +0000346 print ' return;'
347 print ' }'
José Fonseca14c21bc2011-02-20 23:32:22 +0000348
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000349 # ... to the draw calls
José Fonseca99221832011-03-22 22:15:46 +0000350 if function.name in self.draw_function_names:
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000351 print ' if (__need_user_arrays()) {'
José Fonseca99221832011-03-22 22:15:46 +0000352 arg_names = ', '.join([arg.name for arg in function.args[1:]])
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000353 print ' GLuint maxindex = __%s_maxindex(%s);' % (function.name, arg_names)
354 print ' __trace_user_arrays(maxindex);'
355 print ' }'
José Fonseca14c21bc2011-02-20 23:32:22 +0000356
José Fonseca73373602011-05-20 17:45:26 +0100357 # Emit a fake memcpy on buffer uploads
358 if function.name in ('glUnmapBuffer', 'glUnmapBufferARB', ):
José Fonseca867b1b72011-04-24 11:58:04 +0100359 print ' struct buffer_mapping *mapping = get_buffer_mapping(target);'
José Fonseca73373602011-05-20 17:45:26 +0100360 print ' if (mapping && mapping->write && !mapping->explicit_flush) {'
361 self.emit_memcpy('mapping->map', 'mapping->map', 'mapping->length')
José Fonseca867b1b72011-04-24 11:58:04 +0100362 print ' }'
José Fonseca73373602011-05-20 17:45:26 +0100363 if function.name in ('glFlushMappedBufferRange', 'glFlushMappedBufferRangeAPPLE'):
364 # TODO: avoid copying [0, offset] bytes
365 print ' struct buffer_mapping *mapping = get_buffer_mapping(target);'
366 print ' if (mapping) {'
367 if function.name.endswith('APPLE'):
368 print ' GLsizeiptr length = size;'
369 print ' mapping->explicit_flush = true;'
370 print ' //assert(offset + length <= mapping->length);'
371 self.emit_memcpy('mapping->map', 'mapping->map', 'offset + length')
372 print ' }'
373 # FIXME: glFlushMappedNamedBufferRangeEXT
José Fonseca867b1b72011-04-24 11:58:04 +0100374
José Fonseca91492d22011-05-23 21:20:31 +0100375 # Don't leave vertex attrib locations to chance. Instead emit fake
376 # glBindAttribLocation calls to ensure that the same locations will be
377 # used when retracing. Trying to remap locations after the fact would
378 # be an herculian task given that vertex attrib locations appear in
379 # many entry-points, including non-shader related ones.
380 if function.name == 'glLinkProgram':
381 Tracer.dispatch_function(self, function)
382 print ' GLint active_attributes = 0;'
383 print ' __glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &active_attributes);'
384 print ' for (GLuint attrib = 0; attrib < active_attributes; ++attrib) {'
385 print ' GLint size = 0;'
386 print ' GLenum type = 0;'
387 print ' GLchar name[256];'
388 # TODO: Use ACTIVE_ATTRIBUTE_MAX_LENGTH instead of 256
389 print ' __glGetActiveAttrib(program, attrib, sizeof name, NULL, &size, &type, name);'
José Fonseca2a794f52011-05-26 20:54:29 +0100390 print " if (name[0] != 'g' || name[1] != 'l' || name[2] != '_') {"
391 print ' GLint location = __glGetAttribLocation(program, name);'
392 print ' if (location >= 0) {'
José Fonseca91492d22011-05-23 21:20:31 +0100393 bind_function = glapi.glapi.get_function_by_name('glBindAttribLocation')
394 self.fake_call(bind_function, ['program', 'location', 'name'])
José Fonseca2a794f52011-05-26 20:54:29 +0100395 print ' }'
José Fonseca91492d22011-05-23 21:20:31 +0100396 print ' }'
397 print ' }'
398 if function.name == 'glLinkProgramARB':
399 Tracer.dispatch_function(self, function)
400 print ' GLint active_attributes = 0;'
401 print ' __glGetObjectParameterivARB(programObj, GL_OBJECT_ACTIVE_ATTRIBUTES_ARB, &active_attributes);'
402 print ' for (GLuint attrib = 0; attrib < active_attributes; ++attrib) {'
403 print ' GLint size = 0;'
404 print ' GLenum type = 0;'
405 print ' GLcharARB name[256];'
406 # TODO: Use ACTIVE_ATTRIBUTE_MAX_LENGTH instead of 256
407 print ' __glGetActiveAttribARB(programObj, attrib, sizeof name, NULL, &size, &type, name);'
José Fonseca2a794f52011-05-26 20:54:29 +0100408 print " if (name[0] != 'g' || name[1] != 'l' || name[2] != '_') {"
409 print ' GLint location = __glGetAttribLocationARB(programObj, name);'
410 print ' if (location >= 0) {'
José Fonseca91492d22011-05-23 21:20:31 +0100411 bind_function = glapi.glapi.get_function_by_name('glBindAttribLocationARB')
412 self.fake_call(bind_function, ['programObj', 'location', 'name'])
José Fonseca2a794f52011-05-26 20:54:29 +0100413 print ' }'
José Fonseca91492d22011-05-23 21:20:31 +0100414 print ' }'
415 print ' }'
416
José Fonseca14c21bc2011-02-20 23:32:22 +0000417 Tracer.trace_function_impl_body(self, function)
José Fonseca73373602011-05-20 17:45:26 +0100418
José Fonseca91492d22011-05-23 21:20:31 +0100419 def dispatch_function(self, function):
420 if function.name in ('glLinkProgram', 'glLinkProgramARB'):
421 # These functions have been dispatched already
422 return
423
424 Tracer.dispatch_function(self, function)
425
José Fonseca73373602011-05-20 17:45:26 +0100426 def emit_memcpy(self, dest, src, length):
José Fonseca466753b2011-05-28 13:25:55 +0100427 print ' unsigned __call = __writer.beginEnter(&__memcpy_sig);'
José Fonsecaeced7472011-05-28 10:37:12 +0100428 print ' __writer.beginArg(0);'
429 print ' __writer.writeOpaque(%s);' % dest
430 print ' __writer.endArg();'
431 print ' __writer.beginArg(1);'
432 print ' __writer.writeBlob(%s, %s);' % (src, length)
433 print ' __writer.endArg();'
434 print ' __writer.beginArg(2);'
435 print ' __writer.writeUInt(%s);' % length
436 print ' __writer.endArg();'
437 print ' __writer.endEnter();'
438 print ' __writer.beginLeave(__call);'
439 print ' __writer.endLeave();'
José Fonseca867b1b72011-04-24 11:58:04 +0100440
441 buffer_targets = [
442 'ARRAY_BUFFER',
443 'ELEMENT_ARRAY_BUFFER',
444 'PIXEL_PACK_BUFFER',
445 'PIXEL_UNPACK_BUFFER',
446 ]
447
448 def wrap_ret(self, function, instance):
449 Tracer.wrap_ret(self, function, instance)
450
451 if function.name in ('glMapBuffer', 'glMapBufferARB'):
452 print ' struct buffer_mapping *mapping = get_buffer_mapping(target);'
453 print ' if (mapping) {'
454 print ' mapping->map = %s;' % (instance)
455 print ' mapping->length = 0;'
456 print ' __glGetBufferParameteriv(target, GL_BUFFER_SIZE, &mapping->length);'
457 print ' mapping->write = (access != GL_READ_ONLY);'
José Fonseca73373602011-05-20 17:45:26 +0100458 print ' mapping->explicit_flush = false;'
José Fonseca867b1b72011-04-24 11:58:04 +0100459 print ' }'
460
461 if function.name == 'glMapBufferRange':
462 print ' struct buffer_mapping *mapping = get_buffer_mapping(target);'
463 print ' if (mapping) {'
464 print ' mapping->map = %s;' % (instance)
465 print ' mapping->length = length;'
466 print ' mapping->write = access & GL_MAP_WRITE_BIT;'
José Fonseca73373602011-05-20 17:45:26 +0100467 print ' mapping->explicit_flush = access & GL_MAP_FLUSH_EXPLICIT_BIT;'
José Fonseca867b1b72011-04-24 11:58:04 +0100468 print ' }'
José Fonseca669b1222011-02-20 09:05:10 +0000469
José Fonsecac9f12232011-03-25 20:07:42 +0000470 boolean_names = [
471 'GL_FALSE',
472 'GL_TRUE',
473 ]
474
475 def gl_boolean(self, value):
476 return self.boolean_names[int(bool(value))]
477
José Fonsecac29f4f12011-06-11 12:19:05 +0100478 # Names of the functions that unpack from a pixel buffer object. See the
479 # ARB_pixel_buffer_object specification.
José Fonsecae97bab92011-06-02 23:15:11 +0100480 unpack_function_names = set([
481 'glBitmap',
José Fonsecac29f4f12011-06-11 12:19:05 +0100482 'glColorSubTable',
483 'glColorTable',
484 'glCompressedTexImage1D',
485 'glCompressedTexImage2D',
486 'glCompressedTexImage3D',
487 'glCompressedTexSubImage1D',
488 'glCompressedTexSubImage2D',
489 'glCompressedTexSubImage3D',
490 'glConvolutionFilter1D',
491 'glConvolutionFilter2D',
José Fonsecae97bab92011-06-02 23:15:11 +0100492 'glDrawPixels',
493 'glMultiTexImage1DEXT',
494 'glMultiTexImage2DEXT',
495 'glMultiTexImage3DEXT',
496 'glMultiTexSubImage1DEXT',
497 'glMultiTexSubImage2DEXT',
498 'glMultiTexSubImage3DEXT',
José Fonsecac29f4f12011-06-11 12:19:05 +0100499 'glPixelMapfv',
500 'glPixelMapuiv',
501 'glPixelMapusv',
José Fonsecae97bab92011-06-02 23:15:11 +0100502 'glPolygonStipple',
José Fonsecac29f4f12011-06-11 12:19:05 +0100503 'glSeparableFilter2D',
José Fonsecae97bab92011-06-02 23:15:11 +0100504 'glTexImage1D',
505 'glTexImage1DEXT',
506 'glTexImage2D',
507 'glTexImage2DEXT',
508 'glTexImage3D',
509 'glTexImage3DEXT',
510 'glTexSubImage1D',
511 'glTexSubImage1DEXT',
512 'glTexSubImage2D',
513 'glTexSubImage2DEXT',
514 'glTexSubImage3D',
515 'glTexSubImage3DEXT',
516 'glTextureImage1DEXT',
517 'glTextureImage2DEXT',
518 'glTextureImage3DEXT',
519 'glTextureSubImage1DEXT',
520 'glTextureSubImage2DEXT',
521 'glTextureSubImage3DEXT',
522 ])
523
José Fonseca99221832011-03-22 22:15:46 +0000524 def dump_arg_instance(self, function, arg):
525 if function.name in self.draw_function_names and arg.name == 'indices':
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000526 print ' GLint __element_array_buffer = 0;'
527 print ' __glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &__element_array_buffer);'
528 print ' if (!__element_array_buffer) {'
José Fonseca5c749e32011-05-09 11:11:37 +0100529 if isinstance(arg.type, stdapi.Array):
José Fonsecaeced7472011-05-28 10:37:12 +0100530 print ' __writer.beginArray(%s);' % arg.type.length
José Fonseca5c749e32011-05-09 11:11:37 +0100531 print ' for(GLsizei i = 0; i < %s; ++i) {' % arg.type.length
José Fonsecaeced7472011-05-28 10:37:12 +0100532 print ' __writer.beginElement();'
José Fonsecafd34e4e2011-06-03 19:34:29 +0100533 print ' __writer.writeBlob(%s[i], count[i]*__gl_type_size(type));' % (arg.name)
José Fonsecaeced7472011-05-28 10:37:12 +0100534 print ' __writer.endElement();'
José Fonseca5c749e32011-05-09 11:11:37 +0100535 print ' }'
José Fonsecaeced7472011-05-28 10:37:12 +0100536 print ' __writer.endArray();'
José Fonseca5c749e32011-05-09 11:11:37 +0100537 else:
José Fonsecafd34e4e2011-06-03 19:34:29 +0100538 print ' __writer.writeBlob(%s, count*__gl_type_size(type));' % (arg.name)
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000539 print ' } else {'
José Fonseca5c749e32011-05-09 11:11:37 +0100540 Tracer.dump_arg_instance(self, function, arg)
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000541 print ' }'
542 return
543
José Fonsecae97bab92011-06-02 23:15:11 +0100544 # Recognize offsets instead of blobs when a PBO is bound
545 if function.name in self.unpack_function_names \
546 and (isinstance(arg.type, stdapi.Blob) \
547 or (isinstance(arg.type, stdapi.Const) \
548 and isinstance(arg.type.type, stdapi.Blob))):
José Fonsecac29f4f12011-06-11 12:19:05 +0100549 print ' {'
550 print ' GLint __unpack_buffer = 0;'
551 print ' __glGetIntegerv(GL_PIXEL_UNPACK_BUFFER_BINDING, &__unpack_buffer);'
552 print ' if (__unpack_buffer) {'
553 print ' __writer.writeOpaque(%s);' % arg.name
554 print ' } else {'
José Fonsecae97bab92011-06-02 23:15:11 +0100555 Tracer.dump_arg_instance(self, function, arg)
José Fonsecac29f4f12011-06-11 12:19:05 +0100556 print ' }'
José Fonsecae97bab92011-06-02 23:15:11 +0100557 print ' }'
558 return
559
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100560 # Several GL state functions take GLenum symbolic names as
561 # integer/floats; so dump the symbolic name whenever possible
José Fonseca3bcb33c2011-05-27 20:14:31 +0100562 if function.name.startswith('gl') \
563 and arg.type in (glapi.GLint, glapi.GLfloat) \
564 and arg.name == 'param':
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100565 assert arg.index > 0
566 assert function.args[arg.index - 1].name == 'pname'
567 assert function.args[arg.index - 1].type == glapi.GLenum
568 print ' if (is_symbolic_pname(pname) && is_symbolic_param(%s)) {' % arg.name
569 dump_instance(glapi.GLenum, arg.name)
570 print ' } else {'
571 Tracer.dump_arg_instance(self, function, arg)
572 print ' }'
573 return
574
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000575 Tracer.dump_arg_instance(self, function, arg)
José Fonseca99221832011-03-22 22:15:46 +0000576
José Fonseca4c938c22011-04-30 22:44:38 +0100577 def footer(self, api):
578 Tracer.footer(self, api)
José Fonseca669b1222011-02-20 09:05:10 +0000579
José Fonseca4c938c22011-04-30 22:44:38 +0100580 # A simple state tracker to track the pointer values
José Fonseca669b1222011-02-20 09:05:10 +0000581 # update the state
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000582 print 'static void __trace_user_arrays(GLuint maxindex)'
José Fonseca669b1222011-02-20 09:05:10 +0000583 print '{'
José Fonseca1a2fdd22011-04-01 00:55:09 +0100584
José Fonseca99221832011-03-22 22:15:46 +0000585 for camelcase_name, uppercase_name in self.arrays:
586 function_name = 'gl%sPointer' % camelcase_name
587 enable_name = 'GL_%s_ARRAY' % uppercase_name
588 binding_name = 'GL_%s_ARRAY_BUFFER_BINDING' % uppercase_name
José Fonseca14c21bc2011-02-20 23:32:22 +0000589 function = api.get_function_by_name(function_name)
José Fonseca99221832011-03-22 22:15:46 +0000590
591 print ' // %s' % function.name
José Fonsecafb6744f2011-04-15 11:18:37 +0100592 self.array_trace_prolog(api, uppercase_name)
593 self.array_prolog(api, uppercase_name)
594 print ' if (__glIsEnabled(%s)) {' % enable_name
José Fonseca7f5163e2011-03-31 23:37:26 +0100595 print ' GLint __binding = 0;'
596 print ' __glGetIntegerv(%s, &__binding);' % binding_name
597 print ' if (!__binding) {'
José Fonseca99221832011-03-22 22:15:46 +0000598
599 # Get the arguments via glGet*
600 for arg in function.args:
601 arg_get_enum = 'GL_%s_ARRAY_%s' % (uppercase_name, arg.name.upper())
602 arg_get_function, arg_type = TypeGetter().visit(arg.type)
José Fonseca7f5163e2011-03-31 23:37:26 +0100603 print ' %s %s = 0;' % (arg_type, arg.name)
604 print ' __%s(%s, &%s);' % (arg_get_function, arg_get_enum, arg.name)
José Fonseca99221832011-03-22 22:15:46 +0000605
606 arg_names = ', '.join([arg.name for arg in function.args[:-1]])
José Fonseca7f5163e2011-03-31 23:37:26 +0100607 print ' size_t __size = __%s_size(%s, maxindex);' % (function.name, arg_names)
José Fonseca99221832011-03-22 22:15:46 +0000608
609 # Emit a fake function
José Fonsecafb6744f2011-04-15 11:18:37 +0100610 self.array_trace_intermezzo(api, uppercase_name)
José Fonseca466753b2011-05-28 13:25:55 +0100611 print ' unsigned __call = __writer.beginEnter(&__%s_sig);' % (function.name,)
José Fonseca669b1222011-02-20 09:05:10 +0000612 for arg in function.args:
613 assert not arg.output
José Fonsecaeced7472011-05-28 10:37:12 +0100614 print ' __writer.beginArg(%u);' % (arg.index,)
José Fonseca14c21bc2011-02-20 23:32:22 +0000615 if arg.name != 'pointer':
José Fonseca99221832011-03-22 22:15:46 +0000616 dump_instance(arg.type, arg.name)
José Fonseca14c21bc2011-02-20 23:32:22 +0000617 else:
José Fonsecaeced7472011-05-28 10:37:12 +0100618 print ' __writer.writeBlob((const void *)%s, __size);' % (arg.name)
619 print ' __writer.endArg();'
José Fonseca99221832011-03-22 22:15:46 +0000620
José Fonsecaeced7472011-05-28 10:37:12 +0100621 print ' __writer.endEnter();'
622 print ' __writer.beginLeave(__call);'
623 print ' __writer.endLeave();'
José Fonseca99221832011-03-22 22:15:46 +0000624 print ' }'
José Fonseca669b1222011-02-20 09:05:10 +0000625 print ' }'
José Fonsecafb6744f2011-04-15 11:18:37 +0100626 self.array_epilog(api, uppercase_name)
627 self.array_trace_epilog(api, uppercase_name)
José Fonseca99221832011-03-22 22:15:46 +0000628 print
José Fonseca1a2fdd22011-04-01 00:55:09 +0100629
630 # Samething, but for glVertexAttribPointer
631 print ' // glVertexAttribPointer'
José Fonseca0a965252011-04-14 09:21:15 +0100632 print ' GLint __max_vertex_attribs = 0;'
José Fonseca1a2fdd22011-04-01 00:55:09 +0100633 print ' __glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &__max_vertex_attribs);'
634 print ' for (GLint index = 0; index < __max_vertex_attribs; ++index) {'
635 print ' GLint __enabled = 0;'
636 print ' __glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &__enabled);'
637 print ' if (__enabled) {'
638 print ' GLint __binding = 0;'
639 print ' __glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &__binding);'
640 print ' if (!__binding) {'
641
642 function = api.get_function_by_name('glVertexAttribPointer')
643
644 # Get the arguments via glGet*
645 for arg in function.args[1:]:
646 arg_get_enum = 'GL_VERTEX_ATTRIB_ARRAY_%s' % (arg.name.upper(),)
647 arg_get_function, arg_type = TypeGetter('glGetVertexAttrib', False).visit(arg.type)
648 print ' %s %s = 0;' % (arg_type, arg.name)
649 print ' __%s(index, %s, &%s);' % (arg_get_function, arg_get_enum, arg.name)
650
651 arg_names = ', '.join([arg.name for arg in function.args[1:-1]])
652 print ' size_t __size = __%s_size(%s, maxindex);' % (function.name, arg_names)
653
654 # Emit a fake function
José Fonseca466753b2011-05-28 13:25:55 +0100655 print ' unsigned __call = __writer.beginEnter(&__%s_sig);' % (function.name,)
José Fonseca1a2fdd22011-04-01 00:55:09 +0100656 for arg in function.args:
657 assert not arg.output
José Fonsecaeced7472011-05-28 10:37:12 +0100658 print ' __writer.beginArg(%u);' % (arg.index,)
José Fonseca1a2fdd22011-04-01 00:55:09 +0100659 if arg.name != 'pointer':
660 dump_instance(arg.type, arg.name)
661 else:
José Fonsecaeced7472011-05-28 10:37:12 +0100662 print ' __writer.writeBlob((const void *)%s, __size);' % (arg.name)
663 print ' __writer.endArg();'
José Fonseca1a2fdd22011-04-01 00:55:09 +0100664
José Fonsecaeced7472011-05-28 10:37:12 +0100665 print ' __writer.endEnter();'
666 print ' __writer.beginLeave(__call);'
667 print ' __writer.endLeave();'
José Fonseca1a2fdd22011-04-01 00:55:09 +0100668 print ' }'
669 print ' }'
670 print ' }'
671 print
672
José Fonseca669b1222011-02-20 09:05:10 +0000673 print '}'
674 print
675
José Fonsecafb6744f2011-04-15 11:18:37 +0100676 #
677 # Hooks for glTexCoordPointer, which is identical to the other array
678 # pointers except the fact that it is indexed by glClientActiveTexture.
679 #
680
681 def array_prolog(self, api, uppercase_name):
682 if uppercase_name == 'TEXTURE_COORD':
683 print ' GLint client_active_texture = 0;'
684 print ' __glGetIntegerv(GL_CLIENT_ACTIVE_TEXTURE, &client_active_texture);'
685 print ' GLint max_texture_coords = 0;'
686 print ' __glGetIntegerv(GL_MAX_TEXTURE_COORDS, &max_texture_coords);'
687 print ' for (GLint unit = 0; unit < max_texture_coords; ++unit) {'
688 print ' GLenum texture = GL_TEXTURE0 + unit;'
689 print ' __glClientActiveTexture(texture);'
690
691 def array_trace_prolog(self, api, uppercase_name):
692 if uppercase_name == 'TEXTURE_COORD':
693 print ' bool client_active_texture_dirty = false;'
694
695 def array_epilog(self, api, uppercase_name):
696 if uppercase_name == 'TEXTURE_COORD':
697 print ' }'
698 self.array_cleanup(api, uppercase_name)
699
700 def array_cleanup(self, api, uppercase_name):
701 if uppercase_name == 'TEXTURE_COORD':
702 print ' __glClientActiveTexture(client_active_texture);'
703
704 def array_trace_intermezzo(self, api, uppercase_name):
705 if uppercase_name == 'TEXTURE_COORD':
706 print ' if (texture != client_active_texture || client_active_texture_dirty) {'
707 print ' client_active_texture_dirty = true;'
708 self.fake_glClientActiveTexture_call(api, "texture");
709 print ' }'
710
711 def array_trace_epilog(self, api, uppercase_name):
712 if uppercase_name == 'TEXTURE_COORD':
713 print ' if (client_active_texture_dirty) {'
714 self.fake_glClientActiveTexture_call(api, "client_active_texture");
715 print ' }'
716
717 def fake_glClientActiveTexture_call(self, api, texture):
718 function = api.get_function_by_name('glClientActiveTexture')
719 self.fake_call(function, [texture])
720
721 def fake_call(self, function, args):
José Fonseca466753b2011-05-28 13:25:55 +0100722 print ' unsigned __fake_call = __writer.beginEnter(&__%s_sig);' % (function.name,)
José Fonsecafb6744f2011-04-15 11:18:37 +0100723 for arg, instance in zip(function.args, args):
724 assert not arg.output
José Fonsecaeced7472011-05-28 10:37:12 +0100725 print ' __writer.beginArg(%u);' % (arg.index,)
José Fonsecafb6744f2011-04-15 11:18:37 +0100726 dump_instance(arg.type, instance)
José Fonsecaeced7472011-05-28 10:37:12 +0100727 print ' __writer.endArg();'
728 print ' __writer.endEnter();'
729 print ' __writer.beginLeave(__fake_call);'
730 print ' __writer.endLeave();'
José Fonsecafb6744f2011-04-15 11:18:37 +0100731
732
733
734
735
José Fonseca669b1222011-02-20 09:05:10 +0000736
737
738
739
740
741