blob: 29df475d8cc37f5f137796ed88b3d6917760b45a [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é Fonsecabd86a222011-09-27 09:21:38 +010030import specs.stdapi as stdapi
31import specs.glapi as glapi
32import specs.glparams as glparams
33from specs.glxapi import glxapi
José Fonseca54f304a2012-01-14 19:33:08 +000034from trace import Tracer
José Fonseca669b1222011-02-20 09:05:10 +000035
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é Fonseca54f304a2012-01-14 19:33:08 +000045 def visitConst(self, const):
José Fonseca99221832011-03-22 22:15:46 +000046 return self.visit(const.type)
47
José Fonseca54f304a2012-01-14 19:33:08 +000048 def visitAlias(self, alias):
José Fonseca99221832011-03-22 22:15:46 +000049 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
José Fonseca54f304a2012-01-14 19:33:08 +000083 def visitEnum(self, enum):
José Fonseca1a2fdd22011-04-01 00:55:09 +010084 return self.visit(glapi.GLint)
José Fonseca99221832011-03-22 22:15:46 +000085
José Fonseca54f304a2012-01-14 19:33:08 +000086 def visitBitmask(self, bitmask):
José Fonseca1a2fdd22011-04-01 00:55:09 +010087 return self.visit(glapi.GLint)
José Fonseca99221832011-03-22 22:15:46 +000088
José Fonseca54f304a2012-01-14 19:33:08 +000089 def visitOpaque(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
Chia-I Wub3d218d2011-11-03 01:37:36 +0800107 # arrays available in PROFILE_ES1
108 arrays_es1 = ("Vertex", "Normal", "Color", "TexCoord")
109
José Fonseca4c938c22011-04-30 22:44:38 +0100110 def header(self, api):
111 Tracer.header(self, api)
112
José Fonseca1b3d3752011-07-15 10:15:19 +0100113 print '#include "gltrace.hpp"'
114 print
Chia-I Wub3d218d2011-11-03 01:37:36 +0800115 print 'enum tracer_context_profile {'
Chia-I Wu9da53de2011-11-03 01:32:35 +0800116 print ' PROFILE_COMPAT,'
Chia-I Wub3d218d2011-11-03 01:37:36 +0800117 print ' PROFILE_ES1,'
118 print ' PROFILE_ES2,'
Chia-I Wu9da53de2011-11-03 01:32:35 +0800119 print '};'
120 print
Chia-I Wu8ef66972011-11-03 01:19:46 +0800121 print 'struct tracer_context {'
Chia-I Wub3d218d2011-11-03 01:37:36 +0800122 print ' enum tracer_context_profile profile;'
Chia-I Wu8ef66972011-11-03 01:19:46 +0800123 print ' bool user_arrays;'
124 print ' bool user_arrays_arb;'
125 print ' bool user_arrays_nv;'
126 print '};'
José Fonseca25ebe542011-04-24 10:08:22 +0100127 print
José Fonseca5a568a92011-06-29 16:43:36 +0100128
129 # Which glVertexAttrib* variant to use
130 print 'enum vertex_attrib {'
131 print ' VERTEX_ATTRIB,'
132 print ' VERTEX_ATTRIB_ARB,'
133 print ' VERTEX_ATTRIB_NV,'
134 print '};'
135 print
Chia-I Wu8ef66972011-11-03 01:19:46 +0800136 print 'static tracer_context *__get_context(void)'
137 print '{'
138 print ' // TODO return the context set by other APIs (GLX, EGL, and etc.)'
Chia-I Wu9da53de2011-11-03 01:32:35 +0800139 print ' static tracer_context __ctx = { PROFILE_COMPAT, false, false, false };'
Chia-I Wu8ef66972011-11-03 01:19:46 +0800140 print ' return &__ctx;'
141 print '}'
142 print
José Fonseca5a568a92011-06-29 16:43:36 +0100143 print 'static vertex_attrib __get_vertex_attrib(void) {'
Chia-I Wu8ef66972011-11-03 01:19:46 +0800144 print ' tracer_context *ctx = __get_context();'
145 print ' if (ctx->user_arrays_arb || ctx->user_arrays_nv) {'
José Fonseca5a568a92011-06-29 16:43:36 +0100146 print ' GLboolean __vertex_program = GL_FALSE;'
147 print ' __glGetBooleanv(GL_VERTEX_PROGRAM_ARB, &__vertex_program);'
148 print ' if (__vertex_program) {'
Chia-I Wu8ef66972011-11-03 01:19:46 +0800149 print ' if (ctx->user_arrays_nv) {'
José Fonseca5a568a92011-06-29 16:43:36 +0100150 print ' GLint __vertex_program_binding_nv = 0;'
151 print ' __glGetIntegerv(GL_VERTEX_PROGRAM_BINDING_NV, &__vertex_program_binding_nv);'
152 print ' if (__vertex_program_binding_nv) {'
153 print ' return VERTEX_ATTRIB_NV;'
154 print ' }'
155 print ' }'
156 print ' return VERTEX_ATTRIB_ARB;'
157 print ' }'
158 print ' }'
159 print ' return VERTEX_ATTRIB;'
160 print '}'
161 print
162
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000163 # Whether we need user arrays
164 print 'static inline bool __need_user_arrays(void)'
165 print '{'
Chia-I Wu8ef66972011-11-03 01:19:46 +0800166 print ' tracer_context *ctx = __get_context();'
167 print ' if (!ctx->user_arrays) {'
José Fonseca25ebe542011-04-24 10:08:22 +0100168 print ' return false;'
169 print ' }'
170 print
José Fonseca1a2fdd22011-04-01 00:55:09 +0100171
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000172 for camelcase_name, uppercase_name in self.arrays:
Chia-I Wub3d218d2011-11-03 01:37:36 +0800173 # in which profile is the array available?
174 profile_check = 'ctx->profile == PROFILE_COMPAT'
175 if camelcase_name in self.arrays_es1:
176 profile_check = '(' + profile_check + ' || ctx->profile == PROFILE_ES1)';
177
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000178 function_name = 'gl%sPointer' % camelcase_name
179 enable_name = 'GL_%s_ARRAY' % uppercase_name
180 binding_name = 'GL_%s_ARRAY_BUFFER_BINDING' % uppercase_name
181 print ' // %s' % function_name
Chia-I Wub3d218d2011-11-03 01:37:36 +0800182 print ' if (%s) {' % profile_check
José Fonsecafb6744f2011-04-15 11:18:37 +0100183 self.array_prolog(api, uppercase_name)
José Fonseca7f5163e2011-03-31 23:37:26 +0100184 print ' if (__glIsEnabled(%s)) {' % enable_name
185 print ' GLint __binding = 0;'
186 print ' __glGetIntegerv(%s, &__binding);' % binding_name
187 print ' if (!__binding) {'
José Fonsecafb6744f2011-04-15 11:18:37 +0100188 self.array_cleanup(api, uppercase_name)
José Fonseca7f5163e2011-03-31 23:37:26 +0100189 print ' return true;'
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000190 print ' }'
191 print ' }'
José Fonsecafb6744f2011-04-15 11:18:37 +0100192 self.array_epilog(api, uppercase_name)
Chia-I Wub3d218d2011-11-03 01:37:36 +0800193 print ' }'
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000194 print
José Fonseca7f5163e2011-03-31 23:37:26 +0100195
Chia-I Wub3d218d2011-11-03 01:37:36 +0800196 print ' // ES1 does not support generic vertex attributes'
197 print ' if (ctx->profile == PROFILE_ES1)'
198 print ' return false;'
199 print
José Fonseca5a568a92011-06-29 16:43:36 +0100200 print ' vertex_attrib __vertex_attrib = __get_vertex_attrib();'
201 print
202 print ' // glVertexAttribPointer'
203 print ' if (__vertex_attrib == VERTEX_ATTRIB) {'
204 print ' GLint __max_vertex_attribs = 0;'
205 print ' __glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &__max_vertex_attribs);'
206 print ' for (GLint index = 0; index < __max_vertex_attribs; ++index) {'
207 print ' GLint __enabled = 0;'
208 print ' __glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &__enabled);'
209 print ' if (__enabled) {'
210 print ' GLint __binding = 0;'
211 print ' __glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &__binding);'
212 print ' if (!__binding) {'
213 print ' return true;'
214 print ' }'
215 print ' }'
216 print ' }'
217 print ' }'
218 print
219 print ' // glVertexAttribPointerARB'
220 print ' if (__vertex_attrib == VERTEX_ATTRIB_ARB) {'
José Fonsecad94aaac2011-06-28 20:50:49 +0100221 print ' GLint __max_vertex_attribs = 0;'
222 print ' __glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &__max_vertex_attribs);'
223 print ' for (GLint index = 0; index < __max_vertex_attribs; ++index) {'
224 print ' GLint __enabled = 0;'
225 print ' __glGetVertexAttribivARB(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB, &__enabled);'
226 print ' if (__enabled) {'
227 print ' GLint __binding = 0;'
228 print ' __glGetVertexAttribivARB(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB, &__binding);'
229 print ' if (!__binding) {'
230 print ' return true;'
231 print ' }'
232 print ' }'
233 print ' }'
José Fonseca5a568a92011-06-29 16:43:36 +0100234 print ' }'
235 print
236 print ' // glVertexAttribPointerNV'
237 print ' if (__vertex_attrib == VERTEX_ATTRIB_NV) {'
238 print ' for (GLint index = 0; index < 16; ++index) {'
José Fonsecad94aaac2011-06-28 20:50:49 +0100239 print ' GLint __enabled = 0;'
José Fonseca5a568a92011-06-29 16:43:36 +0100240 print ' __glGetIntegerv(GL_VERTEX_ATTRIB_ARRAY0_NV + index, &__enabled);'
José Fonsecad94aaac2011-06-28 20:50:49 +0100241 print ' if (__enabled) {'
José Fonseca5a568a92011-06-29 16:43:36 +0100242 print ' return true;'
José Fonseca1a2fdd22011-04-01 00:55:09 +0100243 print ' }'
244 print ' }'
245 print ' }'
246 print
247
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000248 print ' return false;'
249 print '}'
250 print
José Fonseca669b1222011-02-20 09:05:10 +0000251
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000252 print 'static void __trace_user_arrays(GLuint maxindex);'
José Fonseca14c21bc2011-02-20 23:32:22 +0000253 print
José Fonseca867b1b72011-04-24 11:58:04 +0100254
255 print 'struct buffer_mapping {'
256 print ' void *map;'
257 print ' GLint length;'
258 print ' bool write;'
José Fonseca73373602011-05-20 17:45:26 +0100259 print ' bool explicit_flush;'
José Fonseca867b1b72011-04-24 11:58:04 +0100260 print '};'
261 print
262 for target in self.buffer_targets:
263 print 'struct buffer_mapping __%s_mapping;' % target.lower();
264 print
265 print 'static inline struct buffer_mapping *'
266 print 'get_buffer_mapping(GLenum target) {'
José Fonseca06e85192011-10-16 14:15:36 +0100267 print ' switch (target) {'
José Fonseca867b1b72011-04-24 11:58:04 +0100268 for target in self.buffer_targets:
269 print ' case GL_%s:' % target
270 print ' return & __%s_mapping;' % target.lower()
271 print ' default:'
José Fonseca559d5342011-10-27 08:10:56 +0100272 print ' os::log("apitrace: warning: unknown buffer target 0x%04X\\n", target);'
José Fonseca867b1b72011-04-24 11:58:04 +0100273 print ' return NULL;'
274 print ' }'
275 print '}'
276 print
277
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100278 # Generate a helper function to determine whether a parameter name
279 # refers to a symbolic value or not
280 print 'static bool'
281 print 'is_symbolic_pname(GLenum pname) {'
José Fonseca06e85192011-10-16 14:15:36 +0100282 print ' switch (pname) {'
José Fonseca5ea91872011-05-04 09:41:55 +0100283 for function, type, count, name in glparams.parameters:
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100284 if type is glapi.GLenum:
José Fonseca4c938c22011-04-30 22:44:38 +0100285 print ' case %s:' % name
286 print ' return true;'
287 print ' default:'
288 print ' return false;'
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100289 print ' }'
290 print '}'
291 print
292
293 # Generate a helper function to determine whether a parameter value is
294 # potentially symbolic or not; i.e., if the value can be represented in
295 # an enum or not
296 print 'template<class T>'
297 print 'static inline bool'
298 print 'is_symbolic_param(T param) {'
299 print ' return static_cast<T>(static_cast<GLenum>(param)) == param;'
300 print '}'
301 print
José Fonseca4c938c22011-04-30 22:44:38 +0100302
303 # Generate a helper function to know how many elements a parameter has
304 print 'static size_t'
José Fonsecaf4aca5d2011-05-08 08:29:30 +0100305 print '__gl_param_size(GLenum pname) {'
José Fonseca06e85192011-10-16 14:15:36 +0100306 print ' switch (pname) {'
José Fonseca5ea91872011-05-04 09:41:55 +0100307 for function, type, count, name in glparams.parameters:
José Fonseca4c938c22011-04-30 22:44:38 +0100308 if type is not None:
309 print ' case %s: return %u;' % (name, count)
310 print ' case GL_COMPRESSED_TEXTURE_FORMATS: {'
311 print ' GLint num_compressed_texture_formats = 0;'
312 print ' __glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &num_compressed_texture_formats);'
313 print ' return num_compressed_texture_formats;'
314 print ' }'
315 print ' default:'
José Fonseca559d5342011-10-27 08:10:56 +0100316 print r' os::log("apitrace: warning: %s: unknown GLenum 0x%04X\n", __FUNCTION__, pname);'
José Fonseca4c938c22011-04-30 22:44:38 +0100317 print ' return 1;'
318 print ' }'
319 print '}'
320 print
321
Chia-I Wu335efb42011-11-03 01:59:22 +0800322 # states such as GL_UNPACK_ROW_LENGTH are not available in GLES
323 print 'static inline bool'
324 print 'can_unpack_subimage(void) {'
325 print ' tracer_context *ctx = __get_context();'
326 print ' return (ctx->profile == PROFILE_COMPAT);'
327 print '}'
328 print
329
José Fonseca99221832011-03-22 22:15:46 +0000330 array_pointer_function_names = set((
331 "glVertexPointer",
332 "glNormalPointer",
333 "glColorPointer",
334 "glIndexPointer",
335 "glTexCoordPointer",
336 "glEdgeFlagPointer",
337 "glFogCoordPointer",
338 "glSecondaryColorPointer",
José Fonseca7f5163e2011-03-31 23:37:26 +0100339
José Fonsecaac5285b2011-05-04 11:09:08 +0100340 "glInterleavedArrays",
341
José Fonseca7e0bfd92011-04-30 23:09:03 +0100342 "glVertexPointerEXT",
343 "glNormalPointerEXT",
344 "glColorPointerEXT",
345 "glIndexPointerEXT",
346 "glTexCoordPointerEXT",
347 "glEdgeFlagPointerEXT",
348 "glFogCoordPointerEXT",
349 "glSecondaryColorPointerEXT",
José Fonseca99221832011-03-22 22:15:46 +0000350
José Fonseca7f5163e2011-03-31 23:37:26 +0100351 "glVertexAttribPointer",
352 "glVertexAttribPointerARB",
353 "glVertexAttribPointerNV",
José Fonsecaac5285b2011-05-04 11:09:08 +0100354 "glVertexAttribIPointer",
355 "glVertexAttribIPointerEXT",
José Fonseca7f5163e2011-03-31 23:37:26 +0100356 "glVertexAttribLPointer",
357 "glVertexAttribLPointerEXT",
José Fonseca99221832011-03-22 22:15:46 +0000358
359 #"glMatrixIndexPointerARB",
360 ))
361
362 draw_function_names = set((
363 'glDrawArrays',
364 'glDrawElements',
365 'glDrawRangeElements',
José Fonseca5c749e32011-05-09 11:11:37 +0100366 'glMultiDrawArrays',
367 'glMultiDrawElements',
368 'glDrawArraysInstanced',
José Fonsecaff8848b2011-10-09 01:04:17 +0100369 "glDrawArraysInstancedBaseInstance",
José Fonseca5c749e32011-05-09 11:11:37 +0100370 'glDrawElementsInstanced',
371 'glDrawArraysInstancedARB',
372 'glDrawElementsInstancedARB',
373 'glDrawElementsBaseVertex',
374 'glDrawRangeElementsBaseVertex',
375 'glDrawElementsInstancedBaseVertex',
José Fonsecaff8848b2011-10-09 01:04:17 +0100376 "glDrawElementsInstancedBaseInstance",
377 "glDrawElementsInstancedBaseVertexBaseInstance",
José Fonseca5c749e32011-05-09 11:11:37 +0100378 'glMultiDrawElementsBaseVertex',
379 'glDrawArraysIndirect',
380 'glDrawElementsIndirect',
381 'glDrawArraysEXT',
José Fonseca7e0bfd92011-04-30 23:09:03 +0100382 'glDrawRangeElementsEXT',
José Fonseca5c749e32011-05-09 11:11:37 +0100383 'glDrawRangeElementsEXT_size',
384 'glMultiDrawArraysEXT',
385 'glMultiDrawElementsEXT',
386 'glMultiModeDrawArraysIBM',
387 'glMultiModeDrawElementsIBM',
388 'glDrawArraysInstancedEXT',
389 'glDrawElementsInstancedEXT',
José Fonseca99221832011-03-22 22:15:46 +0000390 ))
391
José Fonsecac9f12232011-03-25 20:07:42 +0000392 interleaved_formats = [
393 'GL_V2F',
394 'GL_V3F',
395 'GL_C4UB_V2F',
396 'GL_C4UB_V3F',
397 'GL_C3F_V3F',
398 'GL_N3F_V3F',
399 'GL_C4F_N3F_V3F',
400 'GL_T2F_V3F',
401 'GL_T4F_V4F',
402 'GL_T2F_C4UB_V3F',
403 'GL_T2F_C3F_V3F',
404 'GL_T2F_N3F_V3F',
405 'GL_T2F_C4F_N3F_V3F',
406 'GL_T4F_C4F_N3F_V4F',
407 ]
408
José Fonseca54f304a2012-01-14 19:33:08 +0000409 def traceFunctionImplBody(self, function):
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000410 # Defer tracing of user array pointers...
José Fonseca99221832011-03-22 22:15:46 +0000411 if function.name in self.array_pointer_function_names:
412 print ' GLint __array_buffer = 0;'
413 print ' __glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &__array_buffer);'
414 print ' if (!__array_buffer) {'
Chia-I Wu8ef66972011-11-03 01:19:46 +0800415 print ' tracer_context *ctx = __get_context();'
416 print ' ctx->user_arrays = true;'
José Fonseca5a568a92011-06-29 16:43:36 +0100417 if function.name == "glVertexAttribPointerARB":
Chia-I Wu8ef66972011-11-03 01:19:46 +0800418 print ' ctx->user_arrays_arb = true;'
José Fonseca5a568a92011-06-29 16:43:36 +0100419 if function.name == "glVertexAttribPointerNV":
Chia-I Wu8ef66972011-11-03 01:19:46 +0800420 print ' ctx->user_arrays_nv = true;'
José Fonseca54f304a2012-01-14 19:33:08 +0000421 self.invokeFunction(function)
José Fonsecaac5285b2011-05-04 11:09:08 +0100422
423 # And also break down glInterleavedArrays into the individual calls
424 if function.name == 'glInterleavedArrays':
425 print
426
427 # Initialize the enable flags
428 for camelcase_name, uppercase_name in self.arrays:
429 flag_name = '__' + uppercase_name.lower()
430 print ' GLboolean %s = GL_FALSE;' % flag_name
431 print
432
433 # Switch for the interleaved formats
434 print ' switch (format) {'
435 for format in self.interleaved_formats:
436 print ' case %s:' % format
437 for camelcase_name, uppercase_name in self.arrays:
438 flag_name = '__' + uppercase_name.lower()
439 if format.find('_' + uppercase_name[0]) >= 0:
440 print ' %s = GL_TRUE;' % flag_name
441 print ' break;'
442 print ' default:'
443 print ' return;'
444 print ' }'
445 print
446
447 # Emit fake glEnableClientState/glDisableClientState flags
448 for camelcase_name, uppercase_name in self.arrays:
449 flag_name = '__' + uppercase_name.lower()
450 enable_name = 'GL_%s_ARRAY' % uppercase_name
451
452 # Emit a fake function
453 print ' {'
José Fonsecab4a3d142011-10-27 07:43:19 +0100454 print ' static const trace::FunctionSig &__sig = %s ? __glEnableClientState_sig : __glDisableClientState_sig;' % flag_name
455 print ' unsigned __call = trace::localWriter.beginEnter(&__sig);'
456 print ' trace::localWriter.beginArg(0);'
José Fonseca54f304a2012-01-14 19:33:08 +0000457 self.serializeValue(glapi.GLenum, enable_name)
José Fonsecab4a3d142011-10-27 07:43:19 +0100458 print ' trace::localWriter.endArg();'
459 print ' trace::localWriter.endEnter();'
460 print ' trace::localWriter.beginLeave(__call);'
461 print ' trace::localWriter.endLeave();'
José Fonsecaac5285b2011-05-04 11:09:08 +0100462 print ' }'
463
José Fonseca99221832011-03-22 22:15:46 +0000464 print ' return;'
465 print ' }'
José Fonseca14c21bc2011-02-20 23:32:22 +0000466
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000467 # ... to the draw calls
José Fonseca99221832011-03-22 22:15:46 +0000468 if function.name in self.draw_function_names:
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000469 print ' if (__need_user_arrays()) {'
José Fonseca99221832011-03-22 22:15:46 +0000470 arg_names = ', '.join([arg.name for arg in function.args[1:]])
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000471 print ' GLuint maxindex = __%s_maxindex(%s);' % (function.name, arg_names)
472 print ' __trace_user_arrays(maxindex);'
473 print ' }'
José Fonseca14c21bc2011-02-20 23:32:22 +0000474
José Fonseca73373602011-05-20 17:45:26 +0100475 # Emit a fake memcpy on buffer uploads
476 if function.name in ('glUnmapBuffer', 'glUnmapBufferARB', ):
José Fonseca867b1b72011-04-24 11:58:04 +0100477 print ' struct buffer_mapping *mapping = get_buffer_mapping(target);'
José Fonseca73373602011-05-20 17:45:26 +0100478 print ' if (mapping && mapping->write && !mapping->explicit_flush) {'
479 self.emit_memcpy('mapping->map', 'mapping->map', 'mapping->length')
José Fonseca867b1b72011-04-24 11:58:04 +0100480 print ' }'
José Fonseca73373602011-05-20 17:45:26 +0100481 if function.name in ('glFlushMappedBufferRange', 'glFlushMappedBufferRangeAPPLE'):
José Fonseca73373602011-05-20 17:45:26 +0100482 print ' struct buffer_mapping *mapping = get_buffer_mapping(target);'
483 print ' if (mapping) {'
484 if function.name.endswith('APPLE'):
485 print ' GLsizeiptr length = size;'
486 print ' mapping->explicit_flush = true;'
487 print ' //assert(offset + length <= mapping->length);'
José Fonseca46a48392011-10-14 11:34:27 +0100488 self.emit_memcpy('(char *)mapping->map + offset', '(const char *)mapping->map + offset', 'length')
José Fonseca73373602011-05-20 17:45:26 +0100489 print ' }'
490 # FIXME: glFlushMappedNamedBufferRangeEXT
José Fonseca867b1b72011-04-24 11:58:04 +0100491
José Fonseca91492d22011-05-23 21:20:31 +0100492 # Don't leave vertex attrib locations to chance. Instead emit fake
493 # glBindAttribLocation calls to ensure that the same locations will be
494 # used when retracing. Trying to remap locations after the fact would
495 # be an herculian task given that vertex attrib locations appear in
496 # many entry-points, including non-shader related ones.
497 if function.name == 'glLinkProgram':
José Fonseca54f304a2012-01-14 19:33:08 +0000498 Tracer.invokeFunction(self, function)
José Fonseca91492d22011-05-23 21:20:31 +0100499 print ' GLint active_attributes = 0;'
500 print ' __glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &active_attributes);'
José Fonseca7525e6f2011-09-28 09:04:56 +0100501 print ' for (GLint attrib = 0; attrib < active_attributes; ++attrib) {'
José Fonseca91492d22011-05-23 21:20:31 +0100502 print ' GLint size = 0;'
503 print ' GLenum type = 0;'
504 print ' GLchar name[256];'
505 # TODO: Use ACTIVE_ATTRIBUTE_MAX_LENGTH instead of 256
506 print ' __glGetActiveAttrib(program, attrib, sizeof name, NULL, &size, &type, name);'
José Fonseca2a794f52011-05-26 20:54:29 +0100507 print " if (name[0] != 'g' || name[1] != 'l' || name[2] != '_') {"
508 print ' GLint location = __glGetAttribLocation(program, name);'
509 print ' if (location >= 0) {'
José Fonseca91492d22011-05-23 21:20:31 +0100510 bind_function = glapi.glapi.get_function_by_name('glBindAttribLocation')
511 self.fake_call(bind_function, ['program', 'location', 'name'])
José Fonseca2a794f52011-05-26 20:54:29 +0100512 print ' }'
José Fonseca91492d22011-05-23 21:20:31 +0100513 print ' }'
514 print ' }'
515 if function.name == 'glLinkProgramARB':
José Fonseca54f304a2012-01-14 19:33:08 +0000516 Tracer.invokeFunction(self, function)
José Fonseca91492d22011-05-23 21:20:31 +0100517 print ' GLint active_attributes = 0;'
518 print ' __glGetObjectParameterivARB(programObj, GL_OBJECT_ACTIVE_ATTRIBUTES_ARB, &active_attributes);'
José Fonseca7525e6f2011-09-28 09:04:56 +0100519 print ' for (GLint attrib = 0; attrib < active_attributes; ++attrib) {'
José Fonseca91492d22011-05-23 21:20:31 +0100520 print ' GLint size = 0;'
521 print ' GLenum type = 0;'
522 print ' GLcharARB name[256];'
523 # TODO: Use ACTIVE_ATTRIBUTE_MAX_LENGTH instead of 256
524 print ' __glGetActiveAttribARB(programObj, attrib, sizeof name, NULL, &size, &type, name);'
José Fonseca2a794f52011-05-26 20:54:29 +0100525 print " if (name[0] != 'g' || name[1] != 'l' || name[2] != '_') {"
526 print ' GLint location = __glGetAttribLocationARB(programObj, name);'
527 print ' if (location >= 0) {'
José Fonseca91492d22011-05-23 21:20:31 +0100528 bind_function = glapi.glapi.get_function_by_name('glBindAttribLocationARB')
529 self.fake_call(bind_function, ['programObj', 'location', 'name'])
José Fonseca2a794f52011-05-26 20:54:29 +0100530 print ' }'
José Fonseca91492d22011-05-23 21:20:31 +0100531 print ' }'
532 print ' }'
533
José Fonseca54f304a2012-01-14 19:33:08 +0000534 Tracer.traceFunctionImplBody(self, function)
José Fonseca73373602011-05-20 17:45:26 +0100535
José Fonseca8f34d342011-07-15 20:16:40 +0100536 gremedy_functions = [
537 'glStringMarkerGREMEDY',
538 'glFrameTerminatorGREMEDY',
539 ]
540
José Fonseca54f304a2012-01-14 19:33:08 +0000541 def invokeFunction(self, function):
José Fonseca91492d22011-05-23 21:20:31 +0100542 if function.name in ('glLinkProgram', 'glLinkProgramARB'):
543 # These functions have been dispatched already
544 return
545
José Fonseca1b3d3752011-07-15 10:15:19 +0100546 # We implement the GREMEDY extensions, not the driver
José Fonseca8f34d342011-07-15 20:16:40 +0100547 if function.name in self.gremedy_functions:
548 return
549
550 if function.name in ('glXGetProcAddress', 'glXGetProcAddressARB', 'wglGetProcAddress'):
551 if_ = 'if'
552 for gremedy_function in self.gremedy_functions:
553 print ' %s (strcmp("%s", (const char *)%s) == 0) {' % (if_, gremedy_function, function.args[0].name)
554 print ' __result = (%s)&%s;' % (function.type, gremedy_function)
555 print ' }'
556 if_ = 'else if'
557 print ' else {'
José Fonseca54f304a2012-01-14 19:33:08 +0000558 Tracer.invokeFunction(self, function)
José Fonseca8f34d342011-07-15 20:16:40 +0100559 print ' }'
José Fonseca1b3d3752011-07-15 10:15:19 +0100560 return
561
José Fonsecaa08d2752011-08-25 13:26:43 +0100562 # Override GL extensions
563 if function.name in ('glGetString', 'glGetIntegerv', 'glGetStringi'):
José Fonseca54f304a2012-01-14 19:33:08 +0000564 Tracer.invokeFunction(self, function, prefix = 'gltrace::__', suffix = '_override')
José Fonsecaa08d2752011-08-25 13:26:43 +0100565 return
566
José Fonseca54f304a2012-01-14 19:33:08 +0000567 Tracer.invokeFunction(self, function)
José Fonseca91492d22011-05-23 21:20:31 +0100568
José Fonseca73373602011-05-20 17:45:26 +0100569 def emit_memcpy(self, dest, src, length):
José Fonsecab4a3d142011-10-27 07:43:19 +0100570 print ' unsigned __call = trace::localWriter.beginEnter(&trace::memcpy_sig);'
571 print ' trace::localWriter.beginArg(0);'
572 print ' trace::localWriter.writeOpaque(%s);' % dest
573 print ' trace::localWriter.endArg();'
574 print ' trace::localWriter.beginArg(1);'
575 print ' trace::localWriter.writeBlob(%s, %s);' % (src, length)
576 print ' trace::localWriter.endArg();'
577 print ' trace::localWriter.beginArg(2);'
578 print ' trace::localWriter.writeUInt(%s);' % length
579 print ' trace::localWriter.endArg();'
580 print ' trace::localWriter.endEnter();'
581 print ' trace::localWriter.beginLeave(__call);'
582 print ' trace::localWriter.endLeave();'
José Fonseca867b1b72011-04-24 11:58:04 +0100583
584 buffer_targets = [
585 'ARRAY_BUFFER',
586 'ELEMENT_ARRAY_BUFFER',
587 'PIXEL_PACK_BUFFER',
588 'PIXEL_UNPACK_BUFFER',
José Fonseca7b20d672012-01-10 19:13:58 +0000589 'UNIFORM_BUFFER',
590 'TEXTURE_BUFFER',
591 'TRANSFORM_FEEDBACK_BUFFER',
592 'COPY_READ_BUFFER',
593 'COPY_WRITE_BUFFER',
594 'DRAW_INDIRECT_BUFFER',
595 'ATOMIC_COUNTER_BUFFER',
José Fonseca867b1b72011-04-24 11:58:04 +0100596 ]
597
José Fonseca54f304a2012-01-14 19:33:08 +0000598 def wrapRet(self, function, instance):
599 Tracer.wrapRet(self, function, instance)
José Fonseca1b3d3752011-07-15 10:15:19 +0100600
José Fonseca867b1b72011-04-24 11:58:04 +0100601
602 if function.name in ('glMapBuffer', 'glMapBufferARB'):
603 print ' struct buffer_mapping *mapping = get_buffer_mapping(target);'
604 print ' if (mapping) {'
605 print ' mapping->map = %s;' % (instance)
606 print ' mapping->length = 0;'
607 print ' __glGetBufferParameteriv(target, GL_BUFFER_SIZE, &mapping->length);'
608 print ' mapping->write = (access != GL_READ_ONLY);'
José Fonseca73373602011-05-20 17:45:26 +0100609 print ' mapping->explicit_flush = false;'
José Fonseca867b1b72011-04-24 11:58:04 +0100610 print ' }'
611
612 if function.name == 'glMapBufferRange':
613 print ' struct buffer_mapping *mapping = get_buffer_mapping(target);'
614 print ' if (mapping) {'
615 print ' mapping->map = %s;' % (instance)
616 print ' mapping->length = length;'
617 print ' mapping->write = access & GL_MAP_WRITE_BIT;'
José Fonseca73373602011-05-20 17:45:26 +0100618 print ' mapping->explicit_flush = access & GL_MAP_FLUSH_EXPLICIT_BIT;'
José Fonseca867b1b72011-04-24 11:58:04 +0100619 print ' }'
José Fonseca669b1222011-02-20 09:05:10 +0000620
José Fonsecac9f12232011-03-25 20:07:42 +0000621 boolean_names = [
622 'GL_FALSE',
623 'GL_TRUE',
624 ]
625
626 def gl_boolean(self, value):
627 return self.boolean_names[int(bool(value))]
628
José Fonsecac29f4f12011-06-11 12:19:05 +0100629 # Names of the functions that unpack from a pixel buffer object. See the
630 # ARB_pixel_buffer_object specification.
José Fonsecae97bab92011-06-02 23:15:11 +0100631 unpack_function_names = set([
632 'glBitmap',
José Fonsecac29f4f12011-06-11 12:19:05 +0100633 'glColorSubTable',
634 'glColorTable',
635 'glCompressedTexImage1D',
636 'glCompressedTexImage2D',
637 'glCompressedTexImage3D',
638 'glCompressedTexSubImage1D',
639 'glCompressedTexSubImage2D',
640 'glCompressedTexSubImage3D',
641 'glConvolutionFilter1D',
642 'glConvolutionFilter2D',
José Fonsecae97bab92011-06-02 23:15:11 +0100643 'glDrawPixels',
644 'glMultiTexImage1DEXT',
645 'glMultiTexImage2DEXT',
646 'glMultiTexImage3DEXT',
647 'glMultiTexSubImage1DEXT',
648 'glMultiTexSubImage2DEXT',
649 'glMultiTexSubImage3DEXT',
José Fonsecac29f4f12011-06-11 12:19:05 +0100650 'glPixelMapfv',
651 'glPixelMapuiv',
652 'glPixelMapusv',
José Fonsecae97bab92011-06-02 23:15:11 +0100653 'glPolygonStipple',
José Fonsecac29f4f12011-06-11 12:19:05 +0100654 'glSeparableFilter2D',
José Fonsecae97bab92011-06-02 23:15:11 +0100655 'glTexImage1D',
656 'glTexImage1DEXT',
657 'glTexImage2D',
658 'glTexImage2DEXT',
659 'glTexImage3D',
660 'glTexImage3DEXT',
661 'glTexSubImage1D',
662 'glTexSubImage1DEXT',
663 'glTexSubImage2D',
664 'glTexSubImage2DEXT',
665 'glTexSubImage3D',
666 'glTexSubImage3DEXT',
667 'glTextureImage1DEXT',
668 'glTextureImage2DEXT',
669 'glTextureImage3DEXT',
670 'glTextureSubImage1DEXT',
671 'glTextureSubImage2DEXT',
672 'glTextureSubImage3DEXT',
673 ])
674
José Fonseca54f304a2012-01-14 19:33:08 +0000675 def serializeArgValue(self, function, arg):
José Fonseca99221832011-03-22 22:15:46 +0000676 if function.name in self.draw_function_names and arg.name == 'indices':
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000677 print ' GLint __element_array_buffer = 0;'
678 print ' __glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &__element_array_buffer);'
679 print ' if (!__element_array_buffer) {'
José Fonseca5c749e32011-05-09 11:11:37 +0100680 if isinstance(arg.type, stdapi.Array):
José Fonsecab4a3d142011-10-27 07:43:19 +0100681 print ' trace::localWriter.beginArray(%s);' % arg.type.length
José Fonseca5c749e32011-05-09 11:11:37 +0100682 print ' for(GLsizei i = 0; i < %s; ++i) {' % arg.type.length
José Fonsecab4a3d142011-10-27 07:43:19 +0100683 print ' trace::localWriter.beginElement();'
684 print ' trace::localWriter.writeBlob(%s[i], count[i]*__gl_type_size(type));' % (arg.name)
685 print ' trace::localWriter.endElement();'
José Fonseca5c749e32011-05-09 11:11:37 +0100686 print ' }'
José Fonsecab4a3d142011-10-27 07:43:19 +0100687 print ' trace::localWriter.endArray();'
José Fonseca5c749e32011-05-09 11:11:37 +0100688 else:
José Fonsecab4a3d142011-10-27 07:43:19 +0100689 print ' trace::localWriter.writeBlob(%s, count*__gl_type_size(type));' % (arg.name)
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000690 print ' } else {'
José Fonseca54f304a2012-01-14 19:33:08 +0000691 Tracer.serializeArgValue(self, function, arg)
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000692 print ' }'
693 return
694
José Fonsecae97bab92011-06-02 23:15:11 +0100695 # Recognize offsets instead of blobs when a PBO is bound
696 if function.name in self.unpack_function_names \
697 and (isinstance(arg.type, stdapi.Blob) \
698 or (isinstance(arg.type, stdapi.Const) \
699 and isinstance(arg.type.type, stdapi.Blob))):
José Fonsecac29f4f12011-06-11 12:19:05 +0100700 print ' {'
Chia-I Wub3d218d2011-11-03 01:37:36 +0800701 print ' tracer_context *ctx = __get_context();'
José Fonsecac29f4f12011-06-11 12:19:05 +0100702 print ' GLint __unpack_buffer = 0;'
Chia-I Wub3d218d2011-11-03 01:37:36 +0800703 print ' if (ctx->profile == PROFILE_COMPAT)'
704 print ' __glGetIntegerv(GL_PIXEL_UNPACK_BUFFER_BINDING, &__unpack_buffer);'
José Fonsecac29f4f12011-06-11 12:19:05 +0100705 print ' if (__unpack_buffer) {'
José Fonsecab4a3d142011-10-27 07:43:19 +0100706 print ' trace::localWriter.writeOpaque(%s);' % arg.name
José Fonsecac29f4f12011-06-11 12:19:05 +0100707 print ' } else {'
José Fonseca54f304a2012-01-14 19:33:08 +0000708 Tracer.serializeArgValue(self, function, arg)
José Fonsecac29f4f12011-06-11 12:19:05 +0100709 print ' }'
José Fonsecae97bab92011-06-02 23:15:11 +0100710 print ' }'
711 return
712
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100713 # Several GL state functions take GLenum symbolic names as
714 # integer/floats; so dump the symbolic name whenever possible
José Fonseca3bcb33c2011-05-27 20:14:31 +0100715 if function.name.startswith('gl') \
José Fonsecae3571092011-10-13 08:26:27 +0100716 and arg.type in (glapi.GLint, glapi.GLfloat, glapi.GLdouble) \
José Fonseca3bcb33c2011-05-27 20:14:31 +0100717 and arg.name == 'param':
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100718 assert arg.index > 0
719 assert function.args[arg.index - 1].name == 'pname'
720 assert function.args[arg.index - 1].type == glapi.GLenum
721 print ' if (is_symbolic_pname(pname) && is_symbolic_param(%s)) {' % arg.name
José Fonseca54f304a2012-01-14 19:33:08 +0000722 self.serializeValue(glapi.GLenum, arg.name)
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100723 print ' } else {'
José Fonseca54f304a2012-01-14 19:33:08 +0000724 Tracer.serializeArgValue(self, function, arg)
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100725 print ' }'
726 return
727
José Fonseca54f304a2012-01-14 19:33:08 +0000728 Tracer.serializeArgValue(self, function, arg)
José Fonseca99221832011-03-22 22:15:46 +0000729
José Fonseca4c938c22011-04-30 22:44:38 +0100730 def footer(self, api):
731 Tracer.footer(self, api)
José Fonseca669b1222011-02-20 09:05:10 +0000732
José Fonseca4c938c22011-04-30 22:44:38 +0100733 # A simple state tracker to track the pointer values
José Fonseca669b1222011-02-20 09:05:10 +0000734 # update the state
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000735 print 'static void __trace_user_arrays(GLuint maxindex)'
José Fonseca669b1222011-02-20 09:05:10 +0000736 print '{'
Chia-I Wub3d218d2011-11-03 01:37:36 +0800737 print ' tracer_context *ctx = __get_context();'
José Fonseca1a2fdd22011-04-01 00:55:09 +0100738
José Fonseca99221832011-03-22 22:15:46 +0000739 for camelcase_name, uppercase_name in self.arrays:
Chia-I Wub3d218d2011-11-03 01:37:36 +0800740 # in which profile is the array available?
741 profile_check = 'ctx->profile == PROFILE_COMPAT'
742 if camelcase_name in self.arrays_es1:
743 profile_check = '(' + profile_check + ' || ctx->profile == PROFILE_ES1)';
744
José Fonseca99221832011-03-22 22:15:46 +0000745 function_name = 'gl%sPointer' % camelcase_name
746 enable_name = 'GL_%s_ARRAY' % uppercase_name
747 binding_name = 'GL_%s_ARRAY_BUFFER_BINDING' % uppercase_name
José Fonseca14c21bc2011-02-20 23:32:22 +0000748 function = api.get_function_by_name(function_name)
José Fonseca99221832011-03-22 22:15:46 +0000749
José Fonseca06e85192011-10-16 14:15:36 +0100750 print ' // %s' % function.prototype()
Chia-I Wub3d218d2011-11-03 01:37:36 +0800751 print ' if (%s) {' % profile_check
José Fonsecafb6744f2011-04-15 11:18:37 +0100752 self.array_trace_prolog(api, uppercase_name)
753 self.array_prolog(api, uppercase_name)
754 print ' if (__glIsEnabled(%s)) {' % enable_name
José Fonseca7f5163e2011-03-31 23:37:26 +0100755 print ' GLint __binding = 0;'
756 print ' __glGetIntegerv(%s, &__binding);' % binding_name
757 print ' if (!__binding) {'
José Fonseca99221832011-03-22 22:15:46 +0000758
759 # Get the arguments via glGet*
760 for arg in function.args:
761 arg_get_enum = 'GL_%s_ARRAY_%s' % (uppercase_name, arg.name.upper())
762 arg_get_function, arg_type = TypeGetter().visit(arg.type)
José Fonseca7f5163e2011-03-31 23:37:26 +0100763 print ' %s %s = 0;' % (arg_type, arg.name)
764 print ' __%s(%s, &%s);' % (arg_get_function, arg_get_enum, arg.name)
José Fonseca99221832011-03-22 22:15:46 +0000765
766 arg_names = ', '.join([arg.name for arg in function.args[:-1]])
José Fonseca7f5163e2011-03-31 23:37:26 +0100767 print ' size_t __size = __%s_size(%s, maxindex);' % (function.name, arg_names)
José Fonseca99221832011-03-22 22:15:46 +0000768
769 # Emit a fake function
José Fonsecafb6744f2011-04-15 11:18:37 +0100770 self.array_trace_intermezzo(api, uppercase_name)
José Fonsecab4a3d142011-10-27 07:43:19 +0100771 print ' unsigned __call = trace::localWriter.beginEnter(&__%s_sig);' % (function.name,)
José Fonseca669b1222011-02-20 09:05:10 +0000772 for arg in function.args:
773 assert not arg.output
José Fonsecab4a3d142011-10-27 07:43:19 +0100774 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
José Fonseca14c21bc2011-02-20 23:32:22 +0000775 if arg.name != 'pointer':
José Fonseca54f304a2012-01-14 19:33:08 +0000776 self.serializeValue(arg.type, arg.name)
José Fonseca14c21bc2011-02-20 23:32:22 +0000777 else:
José Fonsecab4a3d142011-10-27 07:43:19 +0100778 print ' trace::localWriter.writeBlob((const void *)%s, __size);' % (arg.name)
779 print ' trace::localWriter.endArg();'
José Fonseca99221832011-03-22 22:15:46 +0000780
José Fonsecab4a3d142011-10-27 07:43:19 +0100781 print ' trace::localWriter.endEnter();'
782 print ' trace::localWriter.beginLeave(__call);'
783 print ' trace::localWriter.endLeave();'
José Fonseca99221832011-03-22 22:15:46 +0000784 print ' }'
José Fonseca669b1222011-02-20 09:05:10 +0000785 print ' }'
José Fonsecafb6744f2011-04-15 11:18:37 +0100786 self.array_epilog(api, uppercase_name)
787 self.array_trace_epilog(api, uppercase_name)
Chia-I Wub3d218d2011-11-03 01:37:36 +0800788 print ' }'
José Fonseca99221832011-03-22 22:15:46 +0000789 print
José Fonseca1a2fdd22011-04-01 00:55:09 +0100790
José Fonseca1601c412011-05-10 10:38:19 +0100791 # Samething, but for glVertexAttribPointer*
792 #
793 # Some variants of glVertexAttribPointer alias conventional and generic attributes:
794 # - glVertexAttribPointer: no
795 # - glVertexAttribPointerARB: implementation dependent
796 # - glVertexAttribPointerNV: yes
797 #
798 # This means that the implementations of these functions do not always
799 # alias, and they need to be considered independently.
800 #
Chia-I Wub3d218d2011-11-03 01:37:36 +0800801 print ' // ES1 does not support generic vertex attributes'
802 print ' if (ctx->profile == PROFILE_ES1)'
803 print ' return;'
804 print
José Fonseca5a568a92011-06-29 16:43:36 +0100805 print ' vertex_attrib __vertex_attrib = __get_vertex_attrib();'
806 print
807 for suffix in ['', 'ARB', 'NV']:
808 if suffix:
José Fonsecad94aaac2011-06-28 20:50:49 +0100809 SUFFIX = '_' + suffix
José Fonsecad94aaac2011-06-28 20:50:49 +0100810 else:
José Fonseca5a568a92011-06-29 16:43:36 +0100811 SUFFIX = suffix
José Fonseca1601c412011-05-10 10:38:19 +0100812 function_name = 'glVertexAttribPointer' + suffix
José Fonseca06e85192011-10-16 14:15:36 +0100813 function = api.get_function_by_name(function_name)
814
815 print ' // %s' % function.prototype()
José Fonseca5a568a92011-06-29 16:43:36 +0100816 print ' if (__vertex_attrib == VERTEX_ATTRIB%s) {' % SUFFIX
817 if suffix == 'NV':
818 print ' GLint __max_vertex_attribs = 16;'
819 else:
820 print ' GLint __max_vertex_attribs = 0;'
821 print ' __glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &__max_vertex_attribs);'
822 print ' for (GLint index = 0; index < __max_vertex_attribs; ++index) {'
823 print ' GLint __enabled = 0;'
824 if suffix == 'NV':
825 print ' __glGetIntegerv(GL_VERTEX_ATTRIB_ARRAY0_NV + index, &__enabled);'
826 else:
827 print ' __glGetVertexAttribiv%s(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED%s, &__enabled);' % (suffix, SUFFIX)
828 print ' if (__enabled) {'
829 print ' GLint __binding = 0;'
830 if suffix != 'NV':
831 # It doesn't seem possible to use VBOs with NV_vertex_program.
832 print ' __glGetVertexAttribiv%s(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING%s, &__binding);' % (suffix, SUFFIX)
833 print ' if (!__binding) {'
José Fonseca1a2fdd22011-04-01 00:55:09 +0100834
José Fonseca1601c412011-05-10 10:38:19 +0100835 # Get the arguments via glGet*
836 for arg in function.args[1:]:
José Fonseca5a568a92011-06-29 16:43:36 +0100837 if suffix == 'NV':
838 arg_get_enum = 'GL_ATTRIB_ARRAY_%s%s' % (arg.name.upper(), SUFFIX)
839 else:
840 arg_get_enum = 'GL_VERTEX_ATTRIB_ARRAY_%s%s' % (arg.name.upper(), SUFFIX)
José Fonsecac493e3e2011-06-29 12:57:06 +0100841 arg_get_function, arg_type = TypeGetter('glGetVertexAttrib', False, suffix).visit(arg.type)
José Fonseca5a568a92011-06-29 16:43:36 +0100842 print ' %s %s = 0;' % (arg_type, arg.name)
843 print ' __%s(index, %s, &%s);' % (arg_get_function, arg_get_enum, arg.name)
José Fonseca1601c412011-05-10 10:38:19 +0100844
845 arg_names = ', '.join([arg.name for arg in function.args[1:-1]])
José Fonseca5a568a92011-06-29 16:43:36 +0100846 print ' size_t __size = __%s_size(%s, maxindex);' % (function.name, arg_names)
José Fonseca1a2fdd22011-04-01 00:55:09 +0100847
José Fonseca1601c412011-05-10 10:38:19 +0100848 # Emit a fake function
José Fonsecab4a3d142011-10-27 07:43:19 +0100849 print ' unsigned __call = trace::localWriter.beginEnter(&__%s_sig);' % (function.name,)
José Fonseca1601c412011-05-10 10:38:19 +0100850 for arg in function.args:
851 assert not arg.output
José Fonsecab4a3d142011-10-27 07:43:19 +0100852 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
José Fonseca1601c412011-05-10 10:38:19 +0100853 if arg.name != 'pointer':
José Fonseca54f304a2012-01-14 19:33:08 +0000854 self.serializeValue(arg.type, arg.name)
José Fonseca1601c412011-05-10 10:38:19 +0100855 else:
José Fonsecab4a3d142011-10-27 07:43:19 +0100856 print ' trace::localWriter.writeBlob((const void *)%s, __size);' % (arg.name)
857 print ' trace::localWriter.endArg();'
José Fonseca1601c412011-05-10 10:38:19 +0100858
José Fonsecab4a3d142011-10-27 07:43:19 +0100859 print ' trace::localWriter.endEnter();'
860 print ' trace::localWriter.beginLeave(__call);'
861 print ' trace::localWriter.endLeave();'
José Fonseca1601c412011-05-10 10:38:19 +0100862 print ' }'
863 print ' }'
864 print ' }'
865 print ' }'
866 print
José Fonseca1a2fdd22011-04-01 00:55:09 +0100867
José Fonseca669b1222011-02-20 09:05:10 +0000868 print '}'
869 print
870
José Fonsecafb6744f2011-04-15 11:18:37 +0100871 #
872 # Hooks for glTexCoordPointer, which is identical to the other array
873 # pointers except the fact that it is indexed by glClientActiveTexture.
874 #
875
876 def array_prolog(self, api, uppercase_name):
877 if uppercase_name == 'TEXTURE_COORD':
878 print ' GLint client_active_texture = 0;'
879 print ' __glGetIntegerv(GL_CLIENT_ACTIVE_TEXTURE, &client_active_texture);'
880 print ' GLint max_texture_coords = 0;'
Chia-I Wub3d218d2011-11-03 01:37:36 +0800881 print ' if (ctx->profile == PROFILE_COMPAT)'
882 print ' __glGetIntegerv(GL_MAX_TEXTURE_COORDS, &max_texture_coords);'
883 print ' else'
884 print ' __glGetIntegerv(GL_MAX_TEXTURE_UNITS, &max_texture_coords);'
José Fonsecafb6744f2011-04-15 11:18:37 +0100885 print ' for (GLint unit = 0; unit < max_texture_coords; ++unit) {'
José Fonseca7525e6f2011-09-28 09:04:56 +0100886 print ' GLint texture = GL_TEXTURE0 + unit;'
José Fonsecafb6744f2011-04-15 11:18:37 +0100887 print ' __glClientActiveTexture(texture);'
888
889 def array_trace_prolog(self, api, uppercase_name):
890 if uppercase_name == 'TEXTURE_COORD':
891 print ' bool client_active_texture_dirty = false;'
892
893 def array_epilog(self, api, uppercase_name):
894 if uppercase_name == 'TEXTURE_COORD':
895 print ' }'
896 self.array_cleanup(api, uppercase_name)
897
898 def array_cleanup(self, api, uppercase_name):
899 if uppercase_name == 'TEXTURE_COORD':
900 print ' __glClientActiveTexture(client_active_texture);'
901
902 def array_trace_intermezzo(self, api, uppercase_name):
903 if uppercase_name == 'TEXTURE_COORD':
904 print ' if (texture != client_active_texture || client_active_texture_dirty) {'
905 print ' client_active_texture_dirty = true;'
906 self.fake_glClientActiveTexture_call(api, "texture");
907 print ' }'
908
909 def array_trace_epilog(self, api, uppercase_name):
910 if uppercase_name == 'TEXTURE_COORD':
911 print ' if (client_active_texture_dirty) {'
912 self.fake_glClientActiveTexture_call(api, "client_active_texture");
913 print ' }'
914
915 def fake_glClientActiveTexture_call(self, api, texture):
916 function = api.get_function_by_name('glClientActiveTexture')
917 self.fake_call(function, [texture])
918
919 def fake_call(self, function, args):
José Fonsecab4a3d142011-10-27 07:43:19 +0100920 print ' unsigned __fake_call = trace::localWriter.beginEnter(&__%s_sig);' % (function.name,)
José Fonsecafb6744f2011-04-15 11:18:37 +0100921 for arg, instance in zip(function.args, args):
922 assert not arg.output
José Fonsecab4a3d142011-10-27 07:43:19 +0100923 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
José Fonseca54f304a2012-01-14 19:33:08 +0000924 self.serializeValue(arg.type, instance)
José Fonsecab4a3d142011-10-27 07:43:19 +0100925 print ' trace::localWriter.endArg();'
926 print ' trace::localWriter.endEnter();'
927 print ' trace::localWriter.beginLeave(__fake_call);'
928 print ' trace::localWriter.endLeave();'
José Fonsecafb6744f2011-04-15 11:18:37 +0100929
930
931
932
933
José Fonseca669b1222011-02-20 09:05:10 +0000934
935
936
937
938
939