blob: f964bc892bdd27e01e07928a4e0b0698283d5278 [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
José Fonseca5a568a92011-06-29 16:43:36 +0100115
116 # Which glVertexAttrib* variant to use
117 print 'enum vertex_attrib {'
118 print ' VERTEX_ATTRIB,'
119 print ' VERTEX_ATTRIB_ARB,'
120 print ' VERTEX_ATTRIB_NV,'
121 print '};'
122 print
José Fonsecaf028a8f2012-02-15 23:33:35 +0000123 print 'gltrace::Context *'
124 print 'gltrace::getContext(void)'
Chia-I Wu8ef66972011-11-03 01:19:46 +0800125 print '{'
126 print ' // TODO return the context set by other APIs (GLX, EGL, and etc.)'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000127 print ' static gltrace::Context __ctx = { gltrace::PROFILE_COMPAT, false, false, false };'
Chia-I Wu8ef66972011-11-03 01:19:46 +0800128 print ' return &__ctx;'
129 print '}'
130 print
José Fonseca5a568a92011-06-29 16:43:36 +0100131 print 'static vertex_attrib __get_vertex_attrib(void) {'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000132 print ' gltrace::Context *ctx = gltrace::getContext();'
Chia-I Wu8ef66972011-11-03 01:19:46 +0800133 print ' if (ctx->user_arrays_arb || ctx->user_arrays_nv) {'
José Fonseca5a568a92011-06-29 16:43:36 +0100134 print ' GLboolean __vertex_program = GL_FALSE;'
135 print ' __glGetBooleanv(GL_VERTEX_PROGRAM_ARB, &__vertex_program);'
136 print ' if (__vertex_program) {'
Chia-I Wu8ef66972011-11-03 01:19:46 +0800137 print ' if (ctx->user_arrays_nv) {'
José Fonseca5a568a92011-06-29 16:43:36 +0100138 print ' GLint __vertex_program_binding_nv = 0;'
139 print ' __glGetIntegerv(GL_VERTEX_PROGRAM_BINDING_NV, &__vertex_program_binding_nv);'
140 print ' if (__vertex_program_binding_nv) {'
141 print ' return VERTEX_ATTRIB_NV;'
142 print ' }'
143 print ' }'
144 print ' return VERTEX_ATTRIB_ARB;'
145 print ' }'
146 print ' }'
147 print ' return VERTEX_ATTRIB;'
148 print '}'
149 print
150
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000151 # Whether we need user arrays
152 print 'static inline bool __need_user_arrays(void)'
153 print '{'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000154 print ' gltrace::Context *ctx = gltrace::getContext();'
Chia-I Wu8ef66972011-11-03 01:19:46 +0800155 print ' if (!ctx->user_arrays) {'
José Fonseca25ebe542011-04-24 10:08:22 +0100156 print ' return false;'
157 print ' }'
158 print
José Fonseca1a2fdd22011-04-01 00:55:09 +0100159
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000160 for camelcase_name, uppercase_name in self.arrays:
Chia-I Wub3d218d2011-11-03 01:37:36 +0800161 # in which profile is the array available?
José Fonsecaf028a8f2012-02-15 23:33:35 +0000162 profile_check = 'ctx->profile == gltrace::PROFILE_COMPAT'
Chia-I Wub3d218d2011-11-03 01:37:36 +0800163 if camelcase_name in self.arrays_es1:
José Fonsecaf028a8f2012-02-15 23:33:35 +0000164 profile_check = '(' + profile_check + ' || ctx->profile == gltrace::PROFILE_ES1)';
Chia-I Wub3d218d2011-11-03 01:37:36 +0800165
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000166 function_name = 'gl%sPointer' % camelcase_name
167 enable_name = 'GL_%s_ARRAY' % uppercase_name
168 binding_name = 'GL_%s_ARRAY_BUFFER_BINDING' % uppercase_name
169 print ' // %s' % function_name
Chia-I Wub3d218d2011-11-03 01:37:36 +0800170 print ' if (%s) {' % profile_check
José Fonsecafb6744f2011-04-15 11:18:37 +0100171 self.array_prolog(api, uppercase_name)
José Fonseca7f5163e2011-03-31 23:37:26 +0100172 print ' if (__glIsEnabled(%s)) {' % enable_name
173 print ' GLint __binding = 0;'
174 print ' __glGetIntegerv(%s, &__binding);' % binding_name
175 print ' if (!__binding) {'
José Fonsecafb6744f2011-04-15 11:18:37 +0100176 self.array_cleanup(api, uppercase_name)
José Fonseca7f5163e2011-03-31 23:37:26 +0100177 print ' return true;'
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000178 print ' }'
179 print ' }'
José Fonsecafb6744f2011-04-15 11:18:37 +0100180 self.array_epilog(api, uppercase_name)
Chia-I Wub3d218d2011-11-03 01:37:36 +0800181 print ' }'
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000182 print
José Fonseca7f5163e2011-03-31 23:37:26 +0100183
Chia-I Wub3d218d2011-11-03 01:37:36 +0800184 print ' // ES1 does not support generic vertex attributes'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000185 print ' if (ctx->profile == gltrace::PROFILE_ES1)'
Chia-I Wub3d218d2011-11-03 01:37:36 +0800186 print ' return false;'
187 print
José Fonseca5a568a92011-06-29 16:43:36 +0100188 print ' vertex_attrib __vertex_attrib = __get_vertex_attrib();'
189 print
190 print ' // glVertexAttribPointer'
191 print ' if (__vertex_attrib == VERTEX_ATTRIB) {'
192 print ' GLint __max_vertex_attribs = 0;'
193 print ' __glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &__max_vertex_attribs);'
194 print ' for (GLint index = 0; index < __max_vertex_attribs; ++index) {'
195 print ' GLint __enabled = 0;'
196 print ' __glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &__enabled);'
197 print ' if (__enabled) {'
198 print ' GLint __binding = 0;'
199 print ' __glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &__binding);'
200 print ' if (!__binding) {'
201 print ' return true;'
202 print ' }'
203 print ' }'
204 print ' }'
205 print ' }'
206 print
207 print ' // glVertexAttribPointerARB'
208 print ' if (__vertex_attrib == VERTEX_ATTRIB_ARB) {'
José Fonsecad94aaac2011-06-28 20:50:49 +0100209 print ' GLint __max_vertex_attribs = 0;'
210 print ' __glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &__max_vertex_attribs);'
211 print ' for (GLint index = 0; index < __max_vertex_attribs; ++index) {'
212 print ' GLint __enabled = 0;'
213 print ' __glGetVertexAttribivARB(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB, &__enabled);'
214 print ' if (__enabled) {'
215 print ' GLint __binding = 0;'
216 print ' __glGetVertexAttribivARB(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB, &__binding);'
217 print ' if (!__binding) {'
218 print ' return true;'
219 print ' }'
220 print ' }'
221 print ' }'
José Fonseca5a568a92011-06-29 16:43:36 +0100222 print ' }'
223 print
224 print ' // glVertexAttribPointerNV'
225 print ' if (__vertex_attrib == VERTEX_ATTRIB_NV) {'
226 print ' for (GLint index = 0; index < 16; ++index) {'
José Fonsecad94aaac2011-06-28 20:50:49 +0100227 print ' GLint __enabled = 0;'
José Fonseca5a568a92011-06-29 16:43:36 +0100228 print ' __glGetIntegerv(GL_VERTEX_ATTRIB_ARRAY0_NV + index, &__enabled);'
José Fonsecad94aaac2011-06-28 20:50:49 +0100229 print ' if (__enabled) {'
José Fonseca5a568a92011-06-29 16:43:36 +0100230 print ' return true;'
José Fonseca1a2fdd22011-04-01 00:55:09 +0100231 print ' }'
232 print ' }'
233 print ' }'
234 print
235
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000236 print ' return false;'
237 print '}'
238 print
José Fonseca669b1222011-02-20 09:05:10 +0000239
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000240 print 'static void __trace_user_arrays(GLuint maxindex);'
José Fonseca14c21bc2011-02-20 23:32:22 +0000241 print
José Fonseca867b1b72011-04-24 11:58:04 +0100242
243 print 'struct buffer_mapping {'
244 print ' void *map;'
245 print ' GLint length;'
246 print ' bool write;'
José Fonseca73373602011-05-20 17:45:26 +0100247 print ' bool explicit_flush;'
José Fonseca867b1b72011-04-24 11:58:04 +0100248 print '};'
249 print
250 for target in self.buffer_targets:
251 print 'struct buffer_mapping __%s_mapping;' % target.lower();
252 print
253 print 'static inline struct buffer_mapping *'
254 print 'get_buffer_mapping(GLenum target) {'
José Fonseca06e85192011-10-16 14:15:36 +0100255 print ' switch (target) {'
José Fonseca867b1b72011-04-24 11:58:04 +0100256 for target in self.buffer_targets:
257 print ' case GL_%s:' % target
258 print ' return & __%s_mapping;' % target.lower()
259 print ' default:'
José Fonseca559d5342011-10-27 08:10:56 +0100260 print ' os::log("apitrace: warning: unknown buffer target 0x%04X\\n", target);'
José Fonseca867b1b72011-04-24 11:58:04 +0100261 print ' return NULL;'
262 print ' }'
263 print '}'
264 print
265
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100266 # Generate a helper function to determine whether a parameter name
267 # refers to a symbolic value or not
268 print 'static bool'
269 print 'is_symbolic_pname(GLenum pname) {'
José Fonseca06e85192011-10-16 14:15:36 +0100270 print ' switch (pname) {'
José Fonseca5ea91872011-05-04 09:41:55 +0100271 for function, type, count, name in glparams.parameters:
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100272 if type is glapi.GLenum:
José Fonseca4c938c22011-04-30 22:44:38 +0100273 print ' case %s:' % name
274 print ' return true;'
275 print ' default:'
276 print ' return false;'
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100277 print ' }'
278 print '}'
279 print
280
281 # Generate a helper function to determine whether a parameter value is
282 # potentially symbolic or not; i.e., if the value can be represented in
283 # an enum or not
284 print 'template<class T>'
285 print 'static inline bool'
286 print 'is_symbolic_param(T param) {'
287 print ' return static_cast<T>(static_cast<GLenum>(param)) == param;'
288 print '}'
289 print
José Fonseca4c938c22011-04-30 22:44:38 +0100290
291 # Generate a helper function to know how many elements a parameter has
292 print 'static size_t'
José Fonsecaf4aca5d2011-05-08 08:29:30 +0100293 print '__gl_param_size(GLenum pname) {'
José Fonseca06e85192011-10-16 14:15:36 +0100294 print ' switch (pname) {'
José Fonseca5ea91872011-05-04 09:41:55 +0100295 for function, type, count, name in glparams.parameters:
José Fonseca4c938c22011-04-30 22:44:38 +0100296 if type is not None:
297 print ' case %s: return %u;' % (name, count)
298 print ' case GL_COMPRESSED_TEXTURE_FORMATS: {'
299 print ' GLint num_compressed_texture_formats = 0;'
300 print ' __glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &num_compressed_texture_formats);'
301 print ' return num_compressed_texture_formats;'
302 print ' }'
303 print ' default:'
José Fonseca559d5342011-10-27 08:10:56 +0100304 print r' os::log("apitrace: warning: %s: unknown GLenum 0x%04X\n", __FUNCTION__, pname);'
José Fonseca4c938c22011-04-30 22:44:38 +0100305 print ' return 1;'
306 print ' }'
307 print '}'
308 print
309
Chia-I Wu335efb42011-11-03 01:59:22 +0800310 # states such as GL_UNPACK_ROW_LENGTH are not available in GLES
311 print 'static inline bool'
312 print 'can_unpack_subimage(void) {'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000313 print ' gltrace::Context *ctx = gltrace::getContext();'
314 print ' return (ctx->profile == gltrace::PROFILE_COMPAT);'
Chia-I Wu335efb42011-11-03 01:59:22 +0800315 print '}'
316 print
317
José Fonseca99221832011-03-22 22:15:46 +0000318 array_pointer_function_names = set((
319 "glVertexPointer",
320 "glNormalPointer",
321 "glColorPointer",
322 "glIndexPointer",
323 "glTexCoordPointer",
324 "glEdgeFlagPointer",
325 "glFogCoordPointer",
326 "glSecondaryColorPointer",
José Fonseca7f5163e2011-03-31 23:37:26 +0100327
José Fonsecaac5285b2011-05-04 11:09:08 +0100328 "glInterleavedArrays",
329
José Fonseca7e0bfd92011-04-30 23:09:03 +0100330 "glVertexPointerEXT",
331 "glNormalPointerEXT",
332 "glColorPointerEXT",
333 "glIndexPointerEXT",
334 "glTexCoordPointerEXT",
335 "glEdgeFlagPointerEXT",
336 "glFogCoordPointerEXT",
337 "glSecondaryColorPointerEXT",
José Fonseca99221832011-03-22 22:15:46 +0000338
José Fonseca7f5163e2011-03-31 23:37:26 +0100339 "glVertexAttribPointer",
340 "glVertexAttribPointerARB",
341 "glVertexAttribPointerNV",
José Fonsecaac5285b2011-05-04 11:09:08 +0100342 "glVertexAttribIPointer",
343 "glVertexAttribIPointerEXT",
José Fonseca7f5163e2011-03-31 23:37:26 +0100344 "glVertexAttribLPointer",
345 "glVertexAttribLPointerEXT",
José Fonseca99221832011-03-22 22:15:46 +0000346
347 #"glMatrixIndexPointerARB",
348 ))
349
350 draw_function_names = set((
351 'glDrawArrays',
352 'glDrawElements',
353 'glDrawRangeElements',
José Fonseca5c749e32011-05-09 11:11:37 +0100354 'glMultiDrawArrays',
355 'glMultiDrawElements',
356 'glDrawArraysInstanced',
José Fonsecaff8848b2011-10-09 01:04:17 +0100357 "glDrawArraysInstancedBaseInstance",
José Fonseca5c749e32011-05-09 11:11:37 +0100358 'glDrawElementsInstanced',
359 'glDrawArraysInstancedARB',
360 'glDrawElementsInstancedARB',
361 'glDrawElementsBaseVertex',
362 'glDrawRangeElementsBaseVertex',
363 'glDrawElementsInstancedBaseVertex',
José Fonsecaff8848b2011-10-09 01:04:17 +0100364 "glDrawElementsInstancedBaseInstance",
365 "glDrawElementsInstancedBaseVertexBaseInstance",
José Fonseca5c749e32011-05-09 11:11:37 +0100366 'glMultiDrawElementsBaseVertex',
367 'glDrawArraysIndirect',
368 'glDrawElementsIndirect',
369 'glDrawArraysEXT',
José Fonseca7e0bfd92011-04-30 23:09:03 +0100370 'glDrawRangeElementsEXT',
José Fonseca5c749e32011-05-09 11:11:37 +0100371 'glDrawRangeElementsEXT_size',
372 'glMultiDrawArraysEXT',
373 'glMultiDrawElementsEXT',
374 'glMultiModeDrawArraysIBM',
375 'glMultiModeDrawElementsIBM',
376 'glDrawArraysInstancedEXT',
377 'glDrawElementsInstancedEXT',
José Fonseca99221832011-03-22 22:15:46 +0000378 ))
379
José Fonsecac9f12232011-03-25 20:07:42 +0000380 interleaved_formats = [
381 'GL_V2F',
382 'GL_V3F',
383 'GL_C4UB_V2F',
384 'GL_C4UB_V3F',
385 'GL_C3F_V3F',
386 'GL_N3F_V3F',
387 'GL_C4F_N3F_V3F',
388 'GL_T2F_V3F',
389 'GL_T4F_V4F',
390 'GL_T2F_C4UB_V3F',
391 'GL_T2F_C3F_V3F',
392 'GL_T2F_N3F_V3F',
393 'GL_T2F_C4F_N3F_V3F',
394 'GL_T4F_C4F_N3F_V4F',
395 ]
396
José Fonseca54f304a2012-01-14 19:33:08 +0000397 def traceFunctionImplBody(self, function):
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000398 # Defer tracing of user array pointers...
José Fonseca99221832011-03-22 22:15:46 +0000399 if function.name in self.array_pointer_function_names:
400 print ' GLint __array_buffer = 0;'
401 print ' __glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &__array_buffer);'
402 print ' if (!__array_buffer) {'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000403 print ' gltrace::Context *ctx = gltrace::getContext();'
Chia-I Wu8ef66972011-11-03 01:19:46 +0800404 print ' ctx->user_arrays = true;'
José Fonseca5a568a92011-06-29 16:43:36 +0100405 if function.name == "glVertexAttribPointerARB":
Chia-I Wu8ef66972011-11-03 01:19:46 +0800406 print ' ctx->user_arrays_arb = true;'
José Fonseca5a568a92011-06-29 16:43:36 +0100407 if function.name == "glVertexAttribPointerNV":
Chia-I Wu8ef66972011-11-03 01:19:46 +0800408 print ' ctx->user_arrays_nv = true;'
José Fonseca54f304a2012-01-14 19:33:08 +0000409 self.invokeFunction(function)
José Fonsecaac5285b2011-05-04 11:09:08 +0100410
411 # And also break down glInterleavedArrays into the individual calls
412 if function.name == 'glInterleavedArrays':
413 print
414
415 # Initialize the enable flags
416 for camelcase_name, uppercase_name in self.arrays:
417 flag_name = '__' + uppercase_name.lower()
418 print ' GLboolean %s = GL_FALSE;' % flag_name
419 print
420
421 # Switch for the interleaved formats
422 print ' switch (format) {'
423 for format in self.interleaved_formats:
424 print ' case %s:' % format
425 for camelcase_name, uppercase_name in self.arrays:
426 flag_name = '__' + uppercase_name.lower()
427 if format.find('_' + uppercase_name[0]) >= 0:
428 print ' %s = GL_TRUE;' % flag_name
429 print ' break;'
430 print ' default:'
431 print ' return;'
432 print ' }'
433 print
434
435 # Emit fake glEnableClientState/glDisableClientState flags
436 for camelcase_name, uppercase_name in self.arrays:
437 flag_name = '__' + uppercase_name.lower()
438 enable_name = 'GL_%s_ARRAY' % uppercase_name
439
440 # Emit a fake function
441 print ' {'
José Fonsecab4a3d142011-10-27 07:43:19 +0100442 print ' static const trace::FunctionSig &__sig = %s ? __glEnableClientState_sig : __glDisableClientState_sig;' % flag_name
443 print ' unsigned __call = trace::localWriter.beginEnter(&__sig);'
444 print ' trace::localWriter.beginArg(0);'
José Fonseca54f304a2012-01-14 19:33:08 +0000445 self.serializeValue(glapi.GLenum, enable_name)
José Fonsecab4a3d142011-10-27 07:43:19 +0100446 print ' trace::localWriter.endArg();'
447 print ' trace::localWriter.endEnter();'
448 print ' trace::localWriter.beginLeave(__call);'
449 print ' trace::localWriter.endLeave();'
José Fonsecaac5285b2011-05-04 11:09:08 +0100450 print ' }'
451
José Fonseca99221832011-03-22 22:15:46 +0000452 print ' return;'
453 print ' }'
José Fonseca14c21bc2011-02-20 23:32:22 +0000454
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000455 # ... to the draw calls
José Fonseca99221832011-03-22 22:15:46 +0000456 if function.name in self.draw_function_names:
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000457 print ' if (__need_user_arrays()) {'
José Fonseca99221832011-03-22 22:15:46 +0000458 arg_names = ', '.join([arg.name for arg in function.args[1:]])
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000459 print ' GLuint maxindex = __%s_maxindex(%s);' % (function.name, arg_names)
460 print ' __trace_user_arrays(maxindex);'
461 print ' }'
José Fonseca14c21bc2011-02-20 23:32:22 +0000462
José Fonseca73373602011-05-20 17:45:26 +0100463 # Emit a fake memcpy on buffer uploads
José Fonsecacdc322c2012-02-29 19:29:51 +0000464 if function.name in ('glUnmapBuffer', 'glUnmapBufferARB'):
José Fonseca867b1b72011-04-24 11:58:04 +0100465 print ' struct buffer_mapping *mapping = get_buffer_mapping(target);'
José Fonseca73373602011-05-20 17:45:26 +0100466 print ' if (mapping && mapping->write && !mapping->explicit_flush) {'
467 self.emit_memcpy('mapping->map', 'mapping->map', 'mapping->length')
José Fonsecacdc322c2012-02-29 19:29:51 +0000468 if function.name == 'glUnmapBufferOES':
469 print ' GLint access = 0;'
470 print ' __glGetBufferParameteriv(target, GL_BUFFER_ACCESS_OES, &access);'
471 print ' if (access == GL_WRITE_ONLY_OES) {'
472 print ' GLvoid *map = NULL;'
473 print ' __glGetBufferPointervOES(target, GL_BUFFER_MAP_POINTER_OES, &map);'
474 print ' GLint size = 0;'
475 print ' __glGetBufferParameteriv(target, GL_BUFFER_SIZE, &size);'
476 print ' if (map && size > 0) {'
477 self.emit_memcpy('map', 'map', 'size')
478 print ' }'
José Fonseca867b1b72011-04-24 11:58:04 +0100479 print ' }'
José Fonsecafb3bd602012-01-15 13:56:28 +0000480 if function.name == 'glUnmapNamedBufferEXT':
José Fonseca024aff42012-02-29 18:00:06 +0000481 print ' GLint access_flags = 0;'
482 print ' __glGetNamedBufferParameterivEXT(buffer, GL_BUFFER_ACCESS_FLAGS, &access_flags);'
483 print ' if ((access_flags & GL_MAP_WRITE_BIT) && !(access_flags & GL_MAP_FLUSH_EXPLICIT_BIT)) {'
José Fonsecafb3bd602012-01-15 13:56:28 +0000484 print ' GLvoid *map = NULL;'
José Fonseca024aff42012-02-29 18:00:06 +0000485 print ' __glGetNamedBufferPointervEXT(buffer, GL_BUFFER_MAP_POINTER, &map);'
José Fonsecafb3bd602012-01-15 13:56:28 +0000486 print ' GLint length = 0;'
José Fonseca024aff42012-02-29 18:00:06 +0000487 print ' __glGetNamedBufferParameterivEXT(buffer, GL_BUFFER_MAP_LENGTH, &length);'
488 print ' if (map && length > 0) {'
José Fonsecafb3bd602012-01-15 13:56:28 +0000489 self.emit_memcpy('map', 'map', 'length')
José Fonseca024aff42012-02-29 18:00:06 +0000490 print ' }'
José Fonsecafb3bd602012-01-15 13:56:28 +0000491 print ' }'
José Fonseca77ef0ce2012-02-29 18:08:48 +0000492 if function.name == 'glFlushMappedBufferRange':
493 print ' GLvoid *map = NULL;'
494 print ' __glGetBufferPointerv(target, GL_BUFFER_MAP_POINTER, &map);'
495 print ' if (map && length > 0) {'
496 self.emit_memcpy('(char *)map + offset', '(const char *)map + offset', 'length')
497 print ' }'
498 if function.name == 'glFlushMappedBufferRangeAPPLE':
499 print ' GLvoid *map = NULL;'
500 print ' __glGetBufferPointerv(target, GL_BUFFER_MAP_POINTER, &map);'
501 print ' if (map && size > 0) {'
502 self.emit_memcpy('(char *)map + offset', '(const char *)map + offset', 'size')
José Fonseca73373602011-05-20 17:45:26 +0100503 print ' }'
José Fonsecafb3bd602012-01-15 13:56:28 +0000504 if function.name == 'glFlushMappedNamedBufferRangeEXT':
505 print ' GLvoid *map = NULL;'
José Fonseca024aff42012-02-29 18:00:06 +0000506 print ' __glGetNamedBufferPointervEXT(buffer, GL_BUFFER_MAP_POINTER, &map);'
507 print ' if (map && length > 0) {'
José Fonsecafb3bd602012-01-15 13:56:28 +0000508 self.emit_memcpy('(char *)map + offset', '(const char *)map + offset', 'length')
509 print ' }'
José Fonseca867b1b72011-04-24 11:58:04 +0100510
José Fonseca91492d22011-05-23 21:20:31 +0100511 # Don't leave vertex attrib locations to chance. Instead emit fake
512 # glBindAttribLocation calls to ensure that the same locations will be
513 # used when retracing. Trying to remap locations after the fact would
514 # be an herculian task given that vertex attrib locations appear in
515 # many entry-points, including non-shader related ones.
516 if function.name == 'glLinkProgram':
José Fonseca54f304a2012-01-14 19:33:08 +0000517 Tracer.invokeFunction(self, function)
José Fonseca91492d22011-05-23 21:20:31 +0100518 print ' GLint active_attributes = 0;'
519 print ' __glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &active_attributes);'
José Fonseca7525e6f2011-09-28 09:04:56 +0100520 print ' for (GLint attrib = 0; attrib < active_attributes; ++attrib) {'
José Fonseca91492d22011-05-23 21:20:31 +0100521 print ' GLint size = 0;'
522 print ' GLenum type = 0;'
523 print ' GLchar name[256];'
524 # TODO: Use ACTIVE_ATTRIBUTE_MAX_LENGTH instead of 256
525 print ' __glGetActiveAttrib(program, attrib, sizeof name, NULL, &size, &type, name);'
José Fonseca2a794f52011-05-26 20:54:29 +0100526 print " if (name[0] != 'g' || name[1] != 'l' || name[2] != '_') {"
527 print ' GLint location = __glGetAttribLocation(program, name);'
528 print ' if (location >= 0) {'
José Fonseca91492d22011-05-23 21:20:31 +0100529 bind_function = glapi.glapi.get_function_by_name('glBindAttribLocation')
530 self.fake_call(bind_function, ['program', 'location', 'name'])
José Fonseca2a794f52011-05-26 20:54:29 +0100531 print ' }'
José Fonseca91492d22011-05-23 21:20:31 +0100532 print ' }'
533 print ' }'
534 if function.name == 'glLinkProgramARB':
José Fonseca54f304a2012-01-14 19:33:08 +0000535 Tracer.invokeFunction(self, function)
José Fonseca91492d22011-05-23 21:20:31 +0100536 print ' GLint active_attributes = 0;'
537 print ' __glGetObjectParameterivARB(programObj, GL_OBJECT_ACTIVE_ATTRIBUTES_ARB, &active_attributes);'
José Fonseca7525e6f2011-09-28 09:04:56 +0100538 print ' for (GLint attrib = 0; attrib < active_attributes; ++attrib) {'
José Fonseca91492d22011-05-23 21:20:31 +0100539 print ' GLint size = 0;'
540 print ' GLenum type = 0;'
541 print ' GLcharARB name[256];'
542 # TODO: Use ACTIVE_ATTRIBUTE_MAX_LENGTH instead of 256
543 print ' __glGetActiveAttribARB(programObj, attrib, sizeof name, NULL, &size, &type, name);'
José Fonseca2a794f52011-05-26 20:54:29 +0100544 print " if (name[0] != 'g' || name[1] != 'l' || name[2] != '_') {"
545 print ' GLint location = __glGetAttribLocationARB(programObj, name);'
546 print ' if (location >= 0) {'
José Fonseca91492d22011-05-23 21:20:31 +0100547 bind_function = glapi.glapi.get_function_by_name('glBindAttribLocationARB')
548 self.fake_call(bind_function, ['programObj', 'location', 'name'])
José Fonseca2a794f52011-05-26 20:54:29 +0100549 print ' }'
José Fonseca91492d22011-05-23 21:20:31 +0100550 print ' }'
551 print ' }'
552
José Fonseca54f304a2012-01-14 19:33:08 +0000553 Tracer.traceFunctionImplBody(self, function)
José Fonseca73373602011-05-20 17:45:26 +0100554
José Fonsecaf028a8f2012-02-15 23:33:35 +0000555 marker_functions = [
556 # GL_GREMEDY_string_marker
José Fonseca8f34d342011-07-15 20:16:40 +0100557 'glStringMarkerGREMEDY',
José Fonsecaf028a8f2012-02-15 23:33:35 +0000558 # GL_GREMEDY_frame_terminator
José Fonseca8f34d342011-07-15 20:16:40 +0100559 'glFrameTerminatorGREMEDY',
José Fonsecaf028a8f2012-02-15 23:33:35 +0000560 # GL_EXT_debug_marker
561 'glInsertEventMarkerEXT',
562 'glPushGroupMarkerEXT',
563 'glPopGroupMarkerEXT',
José Fonseca8f34d342011-07-15 20:16:40 +0100564 ]
565
José Fonseca54f304a2012-01-14 19:33:08 +0000566 def invokeFunction(self, function):
José Fonseca91492d22011-05-23 21:20:31 +0100567 if function.name in ('glLinkProgram', 'glLinkProgramARB'):
568 # These functions have been dispatched already
569 return
570
José Fonsecaf028a8f2012-02-15 23:33:35 +0000571 # We implement GL_EXT_debug_marker, GL_GREMEDY_*, etc., and not the
572 # driver
573 if function.name in self.marker_functions:
José Fonseca8f34d342011-07-15 20:16:40 +0100574 return
575
576 if function.name in ('glXGetProcAddress', 'glXGetProcAddressARB', 'wglGetProcAddress'):
José Fonsecaf028a8f2012-02-15 23:33:35 +0000577 else_ = ''
578 for marker_function in self.marker_functions:
579 if self.api.get_function_by_name(marker_function):
580 print ' %sif (strcmp("%s", (const char *)%s) == 0) {' % (else_, marker_function, function.args[0].name)
581 print ' __result = (%s)&%s;' % (function.type, marker_function)
582 print ' }'
583 else_ = 'else '
584 print ' %s{' % else_
José Fonseca54f304a2012-01-14 19:33:08 +0000585 Tracer.invokeFunction(self, function)
José Fonseca8f34d342011-07-15 20:16:40 +0100586 print ' }'
José Fonseca1b3d3752011-07-15 10:15:19 +0100587 return
588
José Fonsecaa08d2752011-08-25 13:26:43 +0100589 # Override GL extensions
590 if function.name in ('glGetString', 'glGetIntegerv', 'glGetStringi'):
José Fonseca54f304a2012-01-14 19:33:08 +0000591 Tracer.invokeFunction(self, function, prefix = 'gltrace::__', suffix = '_override')
José Fonsecaa08d2752011-08-25 13:26:43 +0100592 return
593
José Fonseca54f304a2012-01-14 19:33:08 +0000594 Tracer.invokeFunction(self, function)
José Fonseca91492d22011-05-23 21:20:31 +0100595
José Fonseca867b1b72011-04-24 11:58:04 +0100596 buffer_targets = [
597 'ARRAY_BUFFER',
598 'ELEMENT_ARRAY_BUFFER',
599 'PIXEL_PACK_BUFFER',
600 'PIXEL_UNPACK_BUFFER',
José Fonseca7b20d672012-01-10 19:13:58 +0000601 'UNIFORM_BUFFER',
602 'TEXTURE_BUFFER',
603 'TRANSFORM_FEEDBACK_BUFFER',
604 'COPY_READ_BUFFER',
605 'COPY_WRITE_BUFFER',
606 'DRAW_INDIRECT_BUFFER',
607 'ATOMIC_COUNTER_BUFFER',
José Fonseca867b1b72011-04-24 11:58:04 +0100608 ]
609
José Fonseca54f304a2012-01-14 19:33:08 +0000610 def wrapRet(self, function, instance):
611 Tracer.wrapRet(self, function, instance)
José Fonseca1b3d3752011-07-15 10:15:19 +0100612
José Fonsecacdc322c2012-02-29 19:29:51 +0000613 # Keep track of buffer mappings
614 if function.name in ('glMapBuffer', 'glMapBufferARB'):
José Fonseca867b1b72011-04-24 11:58:04 +0100615 print ' struct buffer_mapping *mapping = get_buffer_mapping(target);'
616 print ' if (mapping) {'
617 print ' mapping->map = %s;' % (instance)
618 print ' mapping->length = 0;'
619 print ' __glGetBufferParameteriv(target, GL_BUFFER_SIZE, &mapping->length);'
620 print ' mapping->write = (access != GL_READ_ONLY);'
José Fonseca73373602011-05-20 17:45:26 +0100621 print ' mapping->explicit_flush = false;'
José Fonseca867b1b72011-04-24 11:58:04 +0100622 print ' }'
José Fonseca867b1b72011-04-24 11:58:04 +0100623 if function.name == 'glMapBufferRange':
624 print ' struct buffer_mapping *mapping = get_buffer_mapping(target);'
625 print ' if (mapping) {'
626 print ' mapping->map = %s;' % (instance)
627 print ' mapping->length = length;'
628 print ' mapping->write = access & GL_MAP_WRITE_BIT;'
José Fonseca73373602011-05-20 17:45:26 +0100629 print ' mapping->explicit_flush = access & GL_MAP_FLUSH_EXPLICIT_BIT;'
José Fonseca867b1b72011-04-24 11:58:04 +0100630 print ' }'
José Fonseca669b1222011-02-20 09:05:10 +0000631
José Fonsecac9f12232011-03-25 20:07:42 +0000632 boolean_names = [
633 'GL_FALSE',
634 'GL_TRUE',
635 ]
636
637 def gl_boolean(self, value):
638 return self.boolean_names[int(bool(value))]
639
José Fonsecac29f4f12011-06-11 12:19:05 +0100640 # Names of the functions that unpack from a pixel buffer object. See the
641 # ARB_pixel_buffer_object specification.
José Fonsecae97bab92011-06-02 23:15:11 +0100642 unpack_function_names = set([
643 'glBitmap',
José Fonsecac29f4f12011-06-11 12:19:05 +0100644 'glColorSubTable',
645 'glColorTable',
646 'glCompressedTexImage1D',
647 'glCompressedTexImage2D',
648 'glCompressedTexImage3D',
649 'glCompressedTexSubImage1D',
650 'glCompressedTexSubImage2D',
651 'glCompressedTexSubImage3D',
652 'glConvolutionFilter1D',
653 'glConvolutionFilter2D',
José Fonsecae97bab92011-06-02 23:15:11 +0100654 'glDrawPixels',
655 'glMultiTexImage1DEXT',
656 'glMultiTexImage2DEXT',
657 'glMultiTexImage3DEXT',
658 'glMultiTexSubImage1DEXT',
659 'glMultiTexSubImage2DEXT',
660 'glMultiTexSubImage3DEXT',
José Fonsecac29f4f12011-06-11 12:19:05 +0100661 'glPixelMapfv',
662 'glPixelMapuiv',
663 'glPixelMapusv',
José Fonsecae97bab92011-06-02 23:15:11 +0100664 'glPolygonStipple',
José Fonsecac29f4f12011-06-11 12:19:05 +0100665 'glSeparableFilter2D',
José Fonsecae97bab92011-06-02 23:15:11 +0100666 'glTexImage1D',
667 'glTexImage1DEXT',
668 'glTexImage2D',
669 'glTexImage2DEXT',
670 'glTexImage3D',
671 'glTexImage3DEXT',
672 'glTexSubImage1D',
673 'glTexSubImage1DEXT',
674 'glTexSubImage2D',
675 'glTexSubImage2DEXT',
676 'glTexSubImage3D',
677 'glTexSubImage3DEXT',
678 'glTextureImage1DEXT',
679 'glTextureImage2DEXT',
680 'glTextureImage3DEXT',
681 'glTextureSubImage1DEXT',
682 'glTextureSubImage2DEXT',
683 'glTextureSubImage3DEXT',
684 ])
685
José Fonseca54f304a2012-01-14 19:33:08 +0000686 def serializeArgValue(self, function, arg):
José Fonseca99221832011-03-22 22:15:46 +0000687 if function.name in self.draw_function_names and arg.name == 'indices':
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000688 print ' GLint __element_array_buffer = 0;'
689 print ' __glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &__element_array_buffer);'
690 print ' if (!__element_array_buffer) {'
José Fonseca5c749e32011-05-09 11:11:37 +0100691 if isinstance(arg.type, stdapi.Array):
José Fonsecab4a3d142011-10-27 07:43:19 +0100692 print ' trace::localWriter.beginArray(%s);' % arg.type.length
José Fonseca5c749e32011-05-09 11:11:37 +0100693 print ' for(GLsizei i = 0; i < %s; ++i) {' % arg.type.length
José Fonsecab4a3d142011-10-27 07:43:19 +0100694 print ' trace::localWriter.beginElement();'
695 print ' trace::localWriter.writeBlob(%s[i], count[i]*__gl_type_size(type));' % (arg.name)
696 print ' trace::localWriter.endElement();'
José Fonseca5c749e32011-05-09 11:11:37 +0100697 print ' }'
José Fonsecab4a3d142011-10-27 07:43:19 +0100698 print ' trace::localWriter.endArray();'
José Fonseca5c749e32011-05-09 11:11:37 +0100699 else:
José Fonsecab4a3d142011-10-27 07:43:19 +0100700 print ' trace::localWriter.writeBlob(%s, count*__gl_type_size(type));' % (arg.name)
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000701 print ' } else {'
José Fonseca54f304a2012-01-14 19:33:08 +0000702 Tracer.serializeArgValue(self, function, arg)
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000703 print ' }'
704 return
705
José Fonsecae97bab92011-06-02 23:15:11 +0100706 # Recognize offsets instead of blobs when a PBO is bound
707 if function.name in self.unpack_function_names \
708 and (isinstance(arg.type, stdapi.Blob) \
709 or (isinstance(arg.type, stdapi.Const) \
710 and isinstance(arg.type.type, stdapi.Blob))):
José Fonsecac29f4f12011-06-11 12:19:05 +0100711 print ' {'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000712 print ' gltrace::Context *ctx = gltrace::getContext();'
José Fonsecac29f4f12011-06-11 12:19:05 +0100713 print ' GLint __unpack_buffer = 0;'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000714 print ' if (ctx->profile == gltrace::PROFILE_COMPAT)'
Chia-I Wub3d218d2011-11-03 01:37:36 +0800715 print ' __glGetIntegerv(GL_PIXEL_UNPACK_BUFFER_BINDING, &__unpack_buffer);'
José Fonsecac29f4f12011-06-11 12:19:05 +0100716 print ' if (__unpack_buffer) {'
José Fonsecab4a3d142011-10-27 07:43:19 +0100717 print ' trace::localWriter.writeOpaque(%s);' % arg.name
José Fonsecac29f4f12011-06-11 12:19:05 +0100718 print ' } else {'
José Fonseca54f304a2012-01-14 19:33:08 +0000719 Tracer.serializeArgValue(self, function, arg)
José Fonsecac29f4f12011-06-11 12:19:05 +0100720 print ' }'
José Fonsecae97bab92011-06-02 23:15:11 +0100721 print ' }'
722 return
723
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100724 # Several GL state functions take GLenum symbolic names as
725 # integer/floats; so dump the symbolic name whenever possible
José Fonseca3bcb33c2011-05-27 20:14:31 +0100726 if function.name.startswith('gl') \
José Fonsecae3571092011-10-13 08:26:27 +0100727 and arg.type in (glapi.GLint, glapi.GLfloat, glapi.GLdouble) \
José Fonseca3bcb33c2011-05-27 20:14:31 +0100728 and arg.name == 'param':
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100729 assert arg.index > 0
730 assert function.args[arg.index - 1].name == 'pname'
731 assert function.args[arg.index - 1].type == glapi.GLenum
732 print ' if (is_symbolic_pname(pname) && is_symbolic_param(%s)) {' % arg.name
José Fonseca54f304a2012-01-14 19:33:08 +0000733 self.serializeValue(glapi.GLenum, arg.name)
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100734 print ' } else {'
José Fonseca54f304a2012-01-14 19:33:08 +0000735 Tracer.serializeArgValue(self, function, arg)
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100736 print ' }'
737 return
738
José Fonseca54f304a2012-01-14 19:33:08 +0000739 Tracer.serializeArgValue(self, function, arg)
José Fonseca99221832011-03-22 22:15:46 +0000740
José Fonseca4c938c22011-04-30 22:44:38 +0100741 def footer(self, api):
742 Tracer.footer(self, api)
José Fonseca669b1222011-02-20 09:05:10 +0000743
José Fonseca4c938c22011-04-30 22:44:38 +0100744 # A simple state tracker to track the pointer values
José Fonseca669b1222011-02-20 09:05:10 +0000745 # update the state
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000746 print 'static void __trace_user_arrays(GLuint maxindex)'
José Fonseca669b1222011-02-20 09:05:10 +0000747 print '{'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000748 print ' gltrace::Context *ctx = gltrace::getContext();'
José Fonseca1a2fdd22011-04-01 00:55:09 +0100749
José Fonseca99221832011-03-22 22:15:46 +0000750 for camelcase_name, uppercase_name in self.arrays:
Chia-I Wub3d218d2011-11-03 01:37:36 +0800751 # in which profile is the array available?
José Fonsecaf028a8f2012-02-15 23:33:35 +0000752 profile_check = 'ctx->profile == gltrace::PROFILE_COMPAT'
Chia-I Wub3d218d2011-11-03 01:37:36 +0800753 if camelcase_name in self.arrays_es1:
José Fonsecaf028a8f2012-02-15 23:33:35 +0000754 profile_check = '(' + profile_check + ' || ctx->profile == gltrace::PROFILE_ES1)';
Chia-I Wub3d218d2011-11-03 01:37:36 +0800755
José Fonseca99221832011-03-22 22:15:46 +0000756 function_name = 'gl%sPointer' % camelcase_name
757 enable_name = 'GL_%s_ARRAY' % uppercase_name
758 binding_name = 'GL_%s_ARRAY_BUFFER_BINDING' % uppercase_name
José Fonseca14c21bc2011-02-20 23:32:22 +0000759 function = api.get_function_by_name(function_name)
José Fonseca99221832011-03-22 22:15:46 +0000760
José Fonseca06e85192011-10-16 14:15:36 +0100761 print ' // %s' % function.prototype()
Chia-I Wub3d218d2011-11-03 01:37:36 +0800762 print ' if (%s) {' % profile_check
José Fonsecafb6744f2011-04-15 11:18:37 +0100763 self.array_trace_prolog(api, uppercase_name)
764 self.array_prolog(api, uppercase_name)
765 print ' if (__glIsEnabled(%s)) {' % enable_name
José Fonseca7f5163e2011-03-31 23:37:26 +0100766 print ' GLint __binding = 0;'
767 print ' __glGetIntegerv(%s, &__binding);' % binding_name
768 print ' if (!__binding) {'
José Fonseca99221832011-03-22 22:15:46 +0000769
770 # Get the arguments via glGet*
771 for arg in function.args:
772 arg_get_enum = 'GL_%s_ARRAY_%s' % (uppercase_name, arg.name.upper())
773 arg_get_function, arg_type = TypeGetter().visit(arg.type)
José Fonseca7f5163e2011-03-31 23:37:26 +0100774 print ' %s %s = 0;' % (arg_type, arg.name)
775 print ' __%s(%s, &%s);' % (arg_get_function, arg_get_enum, arg.name)
José Fonseca99221832011-03-22 22:15:46 +0000776
777 arg_names = ', '.join([arg.name for arg in function.args[:-1]])
José Fonseca7f5163e2011-03-31 23:37:26 +0100778 print ' size_t __size = __%s_size(%s, maxindex);' % (function.name, arg_names)
José Fonseca99221832011-03-22 22:15:46 +0000779
780 # Emit a fake function
José Fonsecafb6744f2011-04-15 11:18:37 +0100781 self.array_trace_intermezzo(api, uppercase_name)
José Fonsecab4a3d142011-10-27 07:43:19 +0100782 print ' unsigned __call = trace::localWriter.beginEnter(&__%s_sig);' % (function.name,)
José Fonseca669b1222011-02-20 09:05:10 +0000783 for arg in function.args:
784 assert not arg.output
José Fonsecab4a3d142011-10-27 07:43:19 +0100785 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
José Fonseca14c21bc2011-02-20 23:32:22 +0000786 if arg.name != 'pointer':
José Fonseca54f304a2012-01-14 19:33:08 +0000787 self.serializeValue(arg.type, arg.name)
José Fonseca14c21bc2011-02-20 23:32:22 +0000788 else:
José Fonsecab4a3d142011-10-27 07:43:19 +0100789 print ' trace::localWriter.writeBlob((const void *)%s, __size);' % (arg.name)
790 print ' trace::localWriter.endArg();'
José Fonseca99221832011-03-22 22:15:46 +0000791
José Fonsecab4a3d142011-10-27 07:43:19 +0100792 print ' trace::localWriter.endEnter();'
793 print ' trace::localWriter.beginLeave(__call);'
794 print ' trace::localWriter.endLeave();'
José Fonseca99221832011-03-22 22:15:46 +0000795 print ' }'
José Fonseca669b1222011-02-20 09:05:10 +0000796 print ' }'
José Fonsecafb6744f2011-04-15 11:18:37 +0100797 self.array_epilog(api, uppercase_name)
798 self.array_trace_epilog(api, uppercase_name)
Chia-I Wub3d218d2011-11-03 01:37:36 +0800799 print ' }'
José Fonseca99221832011-03-22 22:15:46 +0000800 print
José Fonseca1a2fdd22011-04-01 00:55:09 +0100801
José Fonseca1601c412011-05-10 10:38:19 +0100802 # Samething, but for glVertexAttribPointer*
803 #
804 # Some variants of glVertexAttribPointer alias conventional and generic attributes:
805 # - glVertexAttribPointer: no
806 # - glVertexAttribPointerARB: implementation dependent
807 # - glVertexAttribPointerNV: yes
808 #
809 # This means that the implementations of these functions do not always
810 # alias, and they need to be considered independently.
811 #
Chia-I Wub3d218d2011-11-03 01:37:36 +0800812 print ' // ES1 does not support generic vertex attributes'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000813 print ' if (ctx->profile == gltrace::PROFILE_ES1)'
Chia-I Wub3d218d2011-11-03 01:37:36 +0800814 print ' return;'
815 print
José Fonseca5a568a92011-06-29 16:43:36 +0100816 print ' vertex_attrib __vertex_attrib = __get_vertex_attrib();'
817 print
818 for suffix in ['', 'ARB', 'NV']:
819 if suffix:
José Fonsecad94aaac2011-06-28 20:50:49 +0100820 SUFFIX = '_' + suffix
José Fonsecad94aaac2011-06-28 20:50:49 +0100821 else:
José Fonseca5a568a92011-06-29 16:43:36 +0100822 SUFFIX = suffix
José Fonseca1601c412011-05-10 10:38:19 +0100823 function_name = 'glVertexAttribPointer' + suffix
José Fonseca06e85192011-10-16 14:15:36 +0100824 function = api.get_function_by_name(function_name)
825
826 print ' // %s' % function.prototype()
José Fonseca5a568a92011-06-29 16:43:36 +0100827 print ' if (__vertex_attrib == VERTEX_ATTRIB%s) {' % SUFFIX
828 if suffix == 'NV':
829 print ' GLint __max_vertex_attribs = 16;'
830 else:
831 print ' GLint __max_vertex_attribs = 0;'
832 print ' __glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &__max_vertex_attribs);'
833 print ' for (GLint index = 0; index < __max_vertex_attribs; ++index) {'
834 print ' GLint __enabled = 0;'
835 if suffix == 'NV':
836 print ' __glGetIntegerv(GL_VERTEX_ATTRIB_ARRAY0_NV + index, &__enabled);'
837 else:
838 print ' __glGetVertexAttribiv%s(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED%s, &__enabled);' % (suffix, SUFFIX)
839 print ' if (__enabled) {'
840 print ' GLint __binding = 0;'
841 if suffix != 'NV':
842 # It doesn't seem possible to use VBOs with NV_vertex_program.
843 print ' __glGetVertexAttribiv%s(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING%s, &__binding);' % (suffix, SUFFIX)
844 print ' if (!__binding) {'
José Fonseca1a2fdd22011-04-01 00:55:09 +0100845
José Fonseca1601c412011-05-10 10:38:19 +0100846 # Get the arguments via glGet*
847 for arg in function.args[1:]:
José Fonseca5a568a92011-06-29 16:43:36 +0100848 if suffix == 'NV':
849 arg_get_enum = 'GL_ATTRIB_ARRAY_%s%s' % (arg.name.upper(), SUFFIX)
850 else:
851 arg_get_enum = 'GL_VERTEX_ATTRIB_ARRAY_%s%s' % (arg.name.upper(), SUFFIX)
José Fonsecac493e3e2011-06-29 12:57:06 +0100852 arg_get_function, arg_type = TypeGetter('glGetVertexAttrib', False, suffix).visit(arg.type)
José Fonseca5a568a92011-06-29 16:43:36 +0100853 print ' %s %s = 0;' % (arg_type, arg.name)
854 print ' __%s(index, %s, &%s);' % (arg_get_function, arg_get_enum, arg.name)
José Fonseca1601c412011-05-10 10:38:19 +0100855
856 arg_names = ', '.join([arg.name for arg in function.args[1:-1]])
José Fonseca5a568a92011-06-29 16:43:36 +0100857 print ' size_t __size = __%s_size(%s, maxindex);' % (function.name, arg_names)
José Fonseca1a2fdd22011-04-01 00:55:09 +0100858
José Fonseca1601c412011-05-10 10:38:19 +0100859 # Emit a fake function
José Fonsecab4a3d142011-10-27 07:43:19 +0100860 print ' unsigned __call = trace::localWriter.beginEnter(&__%s_sig);' % (function.name,)
José Fonseca1601c412011-05-10 10:38:19 +0100861 for arg in function.args:
862 assert not arg.output
José Fonsecab4a3d142011-10-27 07:43:19 +0100863 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
José Fonseca1601c412011-05-10 10:38:19 +0100864 if arg.name != 'pointer':
José Fonseca54f304a2012-01-14 19:33:08 +0000865 self.serializeValue(arg.type, arg.name)
José Fonseca1601c412011-05-10 10:38:19 +0100866 else:
José Fonsecab4a3d142011-10-27 07:43:19 +0100867 print ' trace::localWriter.writeBlob((const void *)%s, __size);' % (arg.name)
868 print ' trace::localWriter.endArg();'
José Fonseca1601c412011-05-10 10:38:19 +0100869
José Fonsecab4a3d142011-10-27 07:43:19 +0100870 print ' trace::localWriter.endEnter();'
871 print ' trace::localWriter.beginLeave(__call);'
872 print ' trace::localWriter.endLeave();'
José Fonseca1601c412011-05-10 10:38:19 +0100873 print ' }'
874 print ' }'
875 print ' }'
876 print ' }'
877 print
José Fonseca1a2fdd22011-04-01 00:55:09 +0100878
José Fonseca669b1222011-02-20 09:05:10 +0000879 print '}'
880 print
881
José Fonsecafb6744f2011-04-15 11:18:37 +0100882 #
883 # Hooks for glTexCoordPointer, which is identical to the other array
884 # pointers except the fact that it is indexed by glClientActiveTexture.
885 #
886
887 def array_prolog(self, api, uppercase_name):
888 if uppercase_name == 'TEXTURE_COORD':
889 print ' GLint client_active_texture = 0;'
890 print ' __glGetIntegerv(GL_CLIENT_ACTIVE_TEXTURE, &client_active_texture);'
891 print ' GLint max_texture_coords = 0;'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000892 print ' if (ctx->profile == gltrace::PROFILE_COMPAT)'
Chia-I Wub3d218d2011-11-03 01:37:36 +0800893 print ' __glGetIntegerv(GL_MAX_TEXTURE_COORDS, &max_texture_coords);'
894 print ' else'
895 print ' __glGetIntegerv(GL_MAX_TEXTURE_UNITS, &max_texture_coords);'
José Fonsecafb6744f2011-04-15 11:18:37 +0100896 print ' for (GLint unit = 0; unit < max_texture_coords; ++unit) {'
José Fonseca7525e6f2011-09-28 09:04:56 +0100897 print ' GLint texture = GL_TEXTURE0 + unit;'
José Fonsecafb6744f2011-04-15 11:18:37 +0100898 print ' __glClientActiveTexture(texture);'
899
900 def array_trace_prolog(self, api, uppercase_name):
901 if uppercase_name == 'TEXTURE_COORD':
902 print ' bool client_active_texture_dirty = false;'
903
904 def array_epilog(self, api, uppercase_name):
905 if uppercase_name == 'TEXTURE_COORD':
906 print ' }'
907 self.array_cleanup(api, uppercase_name)
908
909 def array_cleanup(self, api, uppercase_name):
910 if uppercase_name == 'TEXTURE_COORD':
911 print ' __glClientActiveTexture(client_active_texture);'
912
913 def array_trace_intermezzo(self, api, uppercase_name):
914 if uppercase_name == 'TEXTURE_COORD':
915 print ' if (texture != client_active_texture || client_active_texture_dirty) {'
916 print ' client_active_texture_dirty = true;'
917 self.fake_glClientActiveTexture_call(api, "texture");
918 print ' }'
919
920 def array_trace_epilog(self, api, uppercase_name):
921 if uppercase_name == 'TEXTURE_COORD':
922 print ' if (client_active_texture_dirty) {'
923 self.fake_glClientActiveTexture_call(api, "client_active_texture");
924 print ' }'
925
926 def fake_glClientActiveTexture_call(self, api, texture):
927 function = api.get_function_by_name('glClientActiveTexture')
928 self.fake_call(function, [texture])
929
930 def fake_call(self, function, args):
José Fonsecab4a3d142011-10-27 07:43:19 +0100931 print ' unsigned __fake_call = trace::localWriter.beginEnter(&__%s_sig);' % (function.name,)
José Fonsecafb6744f2011-04-15 11:18:37 +0100932 for arg, instance in zip(function.args, args):
933 assert not arg.output
José Fonsecab4a3d142011-10-27 07:43:19 +0100934 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
José Fonseca54f304a2012-01-14 19:33:08 +0000935 self.serializeValue(arg.type, instance)
José Fonsecab4a3d142011-10-27 07:43:19 +0100936 print ' trace::localWriter.endArg();'
937 print ' trace::localWriter.endEnter();'
938 print ' trace::localWriter.beginLeave(__fake_call);'
939 print ' trace::localWriter.endLeave();'
José Fonsecafb6744f2011-04-15 11:18:37 +0100940
941
942
943
944
José Fonseca669b1222011-02-20 09:05:10 +0000945
946
947
948
949
950