blob: 128568ffc42288f6166c25a6766907661273a76f [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é Fonseca452d3252012-04-14 15:55:40 +010030from trace import Tracer
José Fonsecabd86a222011-09-27 09:21:38 +010031import specs.stdapi as stdapi
32import specs.glapi as glapi
33import specs.glparams as glparams
34from specs.glxapi import glxapi
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
José Fonseca9c536b02012-02-29 20:54:13 +0000243 # Buffer mappings
244 print '// whether glMapBufferRange(GL_MAP_WRITE_BIT) has ever been called'
245 print 'static bool __checkBufferMapRange = false;'
246 print
247 print '// whether glBufferParameteriAPPLE(GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE) has ever been called'
248 print 'static bool __checkBufferFlushingUnmapAPPLE = false;'
249 print
250 # Buffer mapping information, necessary for old Mesa 2.1 drivers which
251 # do not support glGetBufferParameteriv(GL_BUFFER_ACCESS_FLAGS/GL_BUFFER_MAP_LENGTH)
José Fonseca867b1b72011-04-24 11:58:04 +0100252 print 'struct buffer_mapping {'
253 print ' void *map;'
254 print ' GLint length;'
255 print ' bool write;'
José Fonseca73373602011-05-20 17:45:26 +0100256 print ' bool explicit_flush;'
José Fonseca867b1b72011-04-24 11:58:04 +0100257 print '};'
258 print
259 for target in self.buffer_targets:
260 print 'struct buffer_mapping __%s_mapping;' % target.lower();
261 print
262 print 'static inline struct buffer_mapping *'
263 print 'get_buffer_mapping(GLenum target) {'
José Fonseca06e85192011-10-16 14:15:36 +0100264 print ' switch (target) {'
José Fonseca867b1b72011-04-24 11:58:04 +0100265 for target in self.buffer_targets:
266 print ' case GL_%s:' % target
267 print ' return & __%s_mapping;' % target.lower()
268 print ' default:'
José Fonseca559d5342011-10-27 08:10:56 +0100269 print ' os::log("apitrace: warning: unknown buffer target 0x%04X\\n", target);'
José Fonseca867b1b72011-04-24 11:58:04 +0100270 print ' return NULL;'
271 print ' }'
272 print '}'
273 print
274
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100275 # Generate a helper function to determine whether a parameter name
276 # refers to a symbolic value or not
277 print 'static bool'
278 print 'is_symbolic_pname(GLenum pname) {'
José Fonseca06e85192011-10-16 14:15:36 +0100279 print ' switch (pname) {'
José Fonseca5ea91872011-05-04 09:41:55 +0100280 for function, type, count, name in glparams.parameters:
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100281 if type is glapi.GLenum:
José Fonseca4c938c22011-04-30 22:44:38 +0100282 print ' case %s:' % name
283 print ' return true;'
284 print ' default:'
285 print ' return false;'
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100286 print ' }'
287 print '}'
288 print
289
290 # Generate a helper function to determine whether a parameter value is
291 # potentially symbolic or not; i.e., if the value can be represented in
292 # an enum or not
293 print 'template<class T>'
294 print 'static inline bool'
295 print 'is_symbolic_param(T param) {'
296 print ' return static_cast<T>(static_cast<GLenum>(param)) == param;'
297 print '}'
298 print
José Fonseca4c938c22011-04-30 22:44:38 +0100299
300 # Generate a helper function to know how many elements a parameter has
301 print 'static size_t'
José Fonsecaf4aca5d2011-05-08 08:29:30 +0100302 print '__gl_param_size(GLenum pname) {'
José Fonseca06e85192011-10-16 14:15:36 +0100303 print ' switch (pname) {'
José Fonseca5ea91872011-05-04 09:41:55 +0100304 for function, type, count, name in glparams.parameters:
José Fonseca4c938c22011-04-30 22:44:38 +0100305 if type is not None:
306 print ' case %s: return %u;' % (name, count)
307 print ' case GL_COMPRESSED_TEXTURE_FORMATS: {'
308 print ' GLint num_compressed_texture_formats = 0;'
309 print ' __glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &num_compressed_texture_formats);'
310 print ' return num_compressed_texture_formats;'
311 print ' }'
312 print ' default:'
José Fonseca559d5342011-10-27 08:10:56 +0100313 print r' os::log("apitrace: warning: %s: unknown GLenum 0x%04X\n", __FUNCTION__, pname);'
José Fonseca4c938c22011-04-30 22:44:38 +0100314 print ' return 1;'
315 print ' }'
316 print '}'
317 print
318
Chia-I Wu335efb42011-11-03 01:59:22 +0800319 # states such as GL_UNPACK_ROW_LENGTH are not available in GLES
320 print 'static inline bool'
321 print 'can_unpack_subimage(void) {'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000322 print ' gltrace::Context *ctx = gltrace::getContext();'
323 print ' return (ctx->profile == gltrace::PROFILE_COMPAT);'
Chia-I Wu335efb42011-11-03 01:59:22 +0800324 print '}'
325 print
326
José Fonseca99221832011-03-22 22:15:46 +0000327 array_pointer_function_names = set((
328 "glVertexPointer",
329 "glNormalPointer",
330 "glColorPointer",
331 "glIndexPointer",
332 "glTexCoordPointer",
333 "glEdgeFlagPointer",
334 "glFogCoordPointer",
335 "glSecondaryColorPointer",
José Fonseca7f5163e2011-03-31 23:37:26 +0100336
José Fonsecaac5285b2011-05-04 11:09:08 +0100337 "glInterleavedArrays",
338
José Fonseca7e0bfd92011-04-30 23:09:03 +0100339 "glVertexPointerEXT",
340 "glNormalPointerEXT",
341 "glColorPointerEXT",
342 "glIndexPointerEXT",
343 "glTexCoordPointerEXT",
344 "glEdgeFlagPointerEXT",
345 "glFogCoordPointerEXT",
346 "glSecondaryColorPointerEXT",
José Fonseca99221832011-03-22 22:15:46 +0000347
José Fonseca7f5163e2011-03-31 23:37:26 +0100348 "glVertexAttribPointer",
349 "glVertexAttribPointerARB",
350 "glVertexAttribPointerNV",
José Fonsecaac5285b2011-05-04 11:09:08 +0100351 "glVertexAttribIPointer",
352 "glVertexAttribIPointerEXT",
José Fonseca7f5163e2011-03-31 23:37:26 +0100353 "glVertexAttribLPointer",
354 "glVertexAttribLPointerEXT",
José Fonseca99221832011-03-22 22:15:46 +0000355
356 #"glMatrixIndexPointerARB",
357 ))
358
359 draw_function_names = set((
360 'glDrawArrays',
361 'glDrawElements',
362 'glDrawRangeElements',
José Fonseca5c749e32011-05-09 11:11:37 +0100363 'glMultiDrawArrays',
364 'glMultiDrawElements',
365 'glDrawArraysInstanced',
José Fonsecaff8848b2011-10-09 01:04:17 +0100366 "glDrawArraysInstancedBaseInstance",
José Fonseca5c749e32011-05-09 11:11:37 +0100367 'glDrawElementsInstanced',
368 'glDrawArraysInstancedARB',
369 'glDrawElementsInstancedARB',
370 'glDrawElementsBaseVertex',
371 'glDrawRangeElementsBaseVertex',
372 'glDrawElementsInstancedBaseVertex',
José Fonsecaff8848b2011-10-09 01:04:17 +0100373 "glDrawElementsInstancedBaseInstance",
374 "glDrawElementsInstancedBaseVertexBaseInstance",
José Fonseca5c749e32011-05-09 11:11:37 +0100375 'glMultiDrawElementsBaseVertex',
376 'glDrawArraysIndirect',
377 'glDrawElementsIndirect',
378 'glDrawArraysEXT',
José Fonseca7e0bfd92011-04-30 23:09:03 +0100379 'glDrawRangeElementsEXT',
José Fonseca5c749e32011-05-09 11:11:37 +0100380 'glDrawRangeElementsEXT_size',
381 'glMultiDrawArraysEXT',
382 'glMultiDrawElementsEXT',
383 'glMultiModeDrawArraysIBM',
384 'glMultiModeDrawElementsIBM',
385 'glDrawArraysInstancedEXT',
386 'glDrawElementsInstancedEXT',
José Fonseca99221832011-03-22 22:15:46 +0000387 ))
388
José Fonsecac9f12232011-03-25 20:07:42 +0000389 interleaved_formats = [
390 'GL_V2F',
391 'GL_V3F',
392 'GL_C4UB_V2F',
393 'GL_C4UB_V3F',
394 'GL_C3F_V3F',
395 'GL_N3F_V3F',
396 'GL_C4F_N3F_V3F',
397 'GL_T2F_V3F',
398 'GL_T4F_V4F',
399 'GL_T2F_C4UB_V3F',
400 'GL_T2F_C3F_V3F',
401 'GL_T2F_N3F_V3F',
402 'GL_T2F_C4F_N3F_V3F',
403 'GL_T4F_C4F_N3F_V4F',
404 ]
405
José Fonseca54f304a2012-01-14 19:33:08 +0000406 def traceFunctionImplBody(self, function):
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000407 # Defer tracing of user array pointers...
José Fonseca99221832011-03-22 22:15:46 +0000408 if function.name in self.array_pointer_function_names:
409 print ' GLint __array_buffer = 0;'
410 print ' __glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &__array_buffer);'
411 print ' if (!__array_buffer) {'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000412 print ' gltrace::Context *ctx = gltrace::getContext();'
Chia-I Wu8ef66972011-11-03 01:19:46 +0800413 print ' ctx->user_arrays = true;'
José Fonseca5a568a92011-06-29 16:43:36 +0100414 if function.name == "glVertexAttribPointerARB":
Chia-I Wu8ef66972011-11-03 01:19:46 +0800415 print ' ctx->user_arrays_arb = true;'
José Fonseca5a568a92011-06-29 16:43:36 +0100416 if function.name == "glVertexAttribPointerNV":
Chia-I Wu8ef66972011-11-03 01:19:46 +0800417 print ' ctx->user_arrays_nv = true;'
José Fonseca54f304a2012-01-14 19:33:08 +0000418 self.invokeFunction(function)
José Fonsecaac5285b2011-05-04 11:09:08 +0100419
420 # And also break down glInterleavedArrays into the individual calls
421 if function.name == 'glInterleavedArrays':
422 print
423
424 # Initialize the enable flags
425 for camelcase_name, uppercase_name in self.arrays:
426 flag_name = '__' + uppercase_name.lower()
427 print ' GLboolean %s = GL_FALSE;' % flag_name
428 print
429
430 # Switch for the interleaved formats
431 print ' switch (format) {'
432 for format in self.interleaved_formats:
433 print ' case %s:' % format
434 for camelcase_name, uppercase_name in self.arrays:
435 flag_name = '__' + uppercase_name.lower()
436 if format.find('_' + uppercase_name[0]) >= 0:
437 print ' %s = GL_TRUE;' % flag_name
438 print ' break;'
439 print ' default:'
440 print ' return;'
441 print ' }'
442 print
443
444 # Emit fake glEnableClientState/glDisableClientState flags
445 for camelcase_name, uppercase_name in self.arrays:
446 flag_name = '__' + uppercase_name.lower()
447 enable_name = 'GL_%s_ARRAY' % uppercase_name
448
449 # Emit a fake function
450 print ' {'
José Fonsecab4a3d142011-10-27 07:43:19 +0100451 print ' static const trace::FunctionSig &__sig = %s ? __glEnableClientState_sig : __glDisableClientState_sig;' % flag_name
452 print ' unsigned __call = trace::localWriter.beginEnter(&__sig);'
453 print ' trace::localWriter.beginArg(0);'
José Fonseca54f304a2012-01-14 19:33:08 +0000454 self.serializeValue(glapi.GLenum, enable_name)
José Fonsecab4a3d142011-10-27 07:43:19 +0100455 print ' trace::localWriter.endArg();'
456 print ' trace::localWriter.endEnter();'
457 print ' trace::localWriter.beginLeave(__call);'
458 print ' trace::localWriter.endLeave();'
José Fonsecaac5285b2011-05-04 11:09:08 +0100459 print ' }'
460
José Fonseca99221832011-03-22 22:15:46 +0000461 print ' return;'
462 print ' }'
José Fonseca14c21bc2011-02-20 23:32:22 +0000463
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000464 # ... to the draw calls
José Fonseca99221832011-03-22 22:15:46 +0000465 if function.name in self.draw_function_names:
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000466 print ' if (__need_user_arrays()) {'
José Fonseca99221832011-03-22 22:15:46 +0000467 arg_names = ', '.join([arg.name for arg in function.args[1:]])
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000468 print ' GLuint maxindex = __%s_maxindex(%s);' % (function.name, arg_names)
469 print ' __trace_user_arrays(maxindex);'
470 print ' }'
José Fonseca14c21bc2011-02-20 23:32:22 +0000471
José Fonseca73373602011-05-20 17:45:26 +0100472 # Emit a fake memcpy on buffer uploads
José Fonseca9c536b02012-02-29 20:54:13 +0000473 if function.name == 'glBufferParameteriAPPLE':
474 print ' if (pname == GL_BUFFER_FLUSHING_UNMAP_APPLE && param == GL_FALSE) {'
475 print ' __checkBufferFlushingUnmapAPPLE = true;'
476 print ' }'
José Fonsecacdc322c2012-02-29 19:29:51 +0000477 if function.name in ('glUnmapBuffer', 'glUnmapBufferARB'):
José Fonseca9c536b02012-02-29 20:54:13 +0000478 if function.name.endswith('ARB'):
479 suffix = 'ARB'
480 else:
481 suffix = ''
482 print ' GLint access = 0;'
483 print ' __glGetBufferParameteriv%s(target, GL_BUFFER_ACCESS, &access);' % suffix
484 print ' if (access != GL_READ_ONLY) {'
485 print ' GLvoid *map = NULL;'
486 print ' __glGetBufferPointerv%s(target, GL_BUFFER_MAP_POINTER, &map);' % suffix
487 print ' if (map) {'
488 print ' GLint length = -1;'
489 print ' bool flush = true;'
490 print ' if (__checkBufferMapRange) {'
491 print ' __glGetBufferParameteriv%s(target, GL_BUFFER_MAP_LENGTH, &length);' % suffix
492 print ' GLint access_flags = 0;'
493 print ' __glGetBufferParameteriv(target, GL_BUFFER_ACCESS_FLAGS, &access_flags);'
494 print ' flush = flush && !(access_flags & GL_MAP_FLUSH_EXPLICIT_BIT);'
495 print ' if (length == -1) {'
496 print ' // Mesa drivers refuse GL_BUFFER_MAP_LENGTH without GL 3.0'
José Fonsecadb1ccce2012-02-29 21:09:24 +0000497 print ' static bool warned = false;'
498 print ' if (!warned) {'
499 print ' os::log("apitrace: warning: glGetBufferParameteriv%s(GL_BUFFER_MAP_LENGTH) failed\\n");' % suffix
500 print ' warned = true;'
501 print ' }'
José Fonseca9c536b02012-02-29 20:54:13 +0000502 print ' struct buffer_mapping *mapping = get_buffer_mapping(target);'
503 print ' if (mapping) {'
504 print ' length = mapping->length;'
505 print ' flush = flush && !mapping->explicit_flush;'
506 print ' } else {'
507 print ' length = 0;'
508 print ' flush = false;'
509 print ' }'
510 print ' }'
511 print ' } else {'
512 print ' length = 0;'
513 print ' __glGetBufferParameteriv%s(target, GL_BUFFER_SIZE, &length);' % suffix
514 print ' }'
515 print ' if (__checkBufferFlushingUnmapAPPLE) {'
516 print ' GLint flushing_unmap = GL_TRUE;'
517 print ' __glGetBufferParameteriv%s(target, GL_BUFFER_FLUSHING_UNMAP_APPLE, &flushing_unmap);' % suffix
518 print ' flush = flush && flushing_unmap;'
519 print ' }'
520 print ' if (flush && length > 0) {'
521 self.emit_memcpy('map', 'map', 'length')
522 print ' }'
523 print ' }'
524 print ' }'
José Fonsecacdc322c2012-02-29 19:29:51 +0000525 if function.name == 'glUnmapBufferOES':
526 print ' GLint access = 0;'
527 print ' __glGetBufferParameteriv(target, GL_BUFFER_ACCESS_OES, &access);'
528 print ' if (access == GL_WRITE_ONLY_OES) {'
529 print ' GLvoid *map = NULL;'
530 print ' __glGetBufferPointervOES(target, GL_BUFFER_MAP_POINTER_OES, &map);'
531 print ' GLint size = 0;'
532 print ' __glGetBufferParameteriv(target, GL_BUFFER_SIZE, &size);'
533 print ' if (map && size > 0) {'
534 self.emit_memcpy('map', 'map', 'size')
535 print ' }'
José Fonseca867b1b72011-04-24 11:58:04 +0100536 print ' }'
José Fonsecafb3bd602012-01-15 13:56:28 +0000537 if function.name == 'glUnmapNamedBufferEXT':
José Fonseca024aff42012-02-29 18:00:06 +0000538 print ' GLint access_flags = 0;'
539 print ' __glGetNamedBufferParameterivEXT(buffer, GL_BUFFER_ACCESS_FLAGS, &access_flags);'
540 print ' if ((access_flags & GL_MAP_WRITE_BIT) && !(access_flags & GL_MAP_FLUSH_EXPLICIT_BIT)) {'
José Fonsecafb3bd602012-01-15 13:56:28 +0000541 print ' GLvoid *map = NULL;'
José Fonseca024aff42012-02-29 18:00:06 +0000542 print ' __glGetNamedBufferPointervEXT(buffer, GL_BUFFER_MAP_POINTER, &map);'
José Fonsecafb3bd602012-01-15 13:56:28 +0000543 print ' GLint length = 0;'
José Fonseca024aff42012-02-29 18:00:06 +0000544 print ' __glGetNamedBufferParameterivEXT(buffer, GL_BUFFER_MAP_LENGTH, &length);'
545 print ' if (map && length > 0) {'
José Fonsecafb3bd602012-01-15 13:56:28 +0000546 self.emit_memcpy('map', 'map', 'length')
José Fonseca024aff42012-02-29 18:00:06 +0000547 print ' }'
José Fonsecafb3bd602012-01-15 13:56:28 +0000548 print ' }'
José Fonseca77ef0ce2012-02-29 18:08:48 +0000549 if function.name == 'glFlushMappedBufferRange':
550 print ' GLvoid *map = NULL;'
551 print ' __glGetBufferPointerv(target, GL_BUFFER_MAP_POINTER, &map);'
552 print ' if (map && length > 0) {'
553 self.emit_memcpy('(char *)map + offset', '(const char *)map + offset', 'length')
554 print ' }'
555 if function.name == 'glFlushMappedBufferRangeAPPLE':
556 print ' GLvoid *map = NULL;'
557 print ' __glGetBufferPointerv(target, GL_BUFFER_MAP_POINTER, &map);'
558 print ' if (map && size > 0) {'
559 self.emit_memcpy('(char *)map + offset', '(const char *)map + offset', 'size')
José Fonseca73373602011-05-20 17:45:26 +0100560 print ' }'
José Fonsecafb3bd602012-01-15 13:56:28 +0000561 if function.name == 'glFlushMappedNamedBufferRangeEXT':
562 print ' GLvoid *map = NULL;'
José Fonseca024aff42012-02-29 18:00:06 +0000563 print ' __glGetNamedBufferPointervEXT(buffer, GL_BUFFER_MAP_POINTER, &map);'
564 print ' if (map && length > 0) {'
José Fonsecafb3bd602012-01-15 13:56:28 +0000565 self.emit_memcpy('(char *)map + offset', '(const char *)map + offset', 'length')
566 print ' }'
José Fonseca867b1b72011-04-24 11:58:04 +0100567
José Fonseca91492d22011-05-23 21:20:31 +0100568 # Don't leave vertex attrib locations to chance. Instead emit fake
569 # glBindAttribLocation calls to ensure that the same locations will be
570 # used when retracing. Trying to remap locations after the fact would
571 # be an herculian task given that vertex attrib locations appear in
572 # many entry-points, including non-shader related ones.
573 if function.name == 'glLinkProgram':
José Fonseca54f304a2012-01-14 19:33:08 +0000574 Tracer.invokeFunction(self, function)
José Fonseca91492d22011-05-23 21:20:31 +0100575 print ' GLint active_attributes = 0;'
576 print ' __glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &active_attributes);'
José Fonseca7525e6f2011-09-28 09:04:56 +0100577 print ' for (GLint attrib = 0; attrib < active_attributes; ++attrib) {'
José Fonseca91492d22011-05-23 21:20:31 +0100578 print ' GLint size = 0;'
579 print ' GLenum type = 0;'
580 print ' GLchar name[256];'
581 # TODO: Use ACTIVE_ATTRIBUTE_MAX_LENGTH instead of 256
582 print ' __glGetActiveAttrib(program, attrib, sizeof name, NULL, &size, &type, name);'
José Fonseca2a794f52011-05-26 20:54:29 +0100583 print " if (name[0] != 'g' || name[1] != 'l' || name[2] != '_') {"
584 print ' GLint location = __glGetAttribLocation(program, name);'
585 print ' if (location >= 0) {'
José Fonseca91492d22011-05-23 21:20:31 +0100586 bind_function = glapi.glapi.get_function_by_name('glBindAttribLocation')
587 self.fake_call(bind_function, ['program', 'location', 'name'])
José Fonseca2a794f52011-05-26 20:54:29 +0100588 print ' }'
José Fonseca91492d22011-05-23 21:20:31 +0100589 print ' }'
590 print ' }'
591 if function.name == 'glLinkProgramARB':
José Fonseca54f304a2012-01-14 19:33:08 +0000592 Tracer.invokeFunction(self, function)
José Fonseca91492d22011-05-23 21:20:31 +0100593 print ' GLint active_attributes = 0;'
594 print ' __glGetObjectParameterivARB(programObj, GL_OBJECT_ACTIVE_ATTRIBUTES_ARB, &active_attributes);'
José Fonseca7525e6f2011-09-28 09:04:56 +0100595 print ' for (GLint attrib = 0; attrib < active_attributes; ++attrib) {'
José Fonseca91492d22011-05-23 21:20:31 +0100596 print ' GLint size = 0;'
597 print ' GLenum type = 0;'
598 print ' GLcharARB name[256];'
599 # TODO: Use ACTIVE_ATTRIBUTE_MAX_LENGTH instead of 256
600 print ' __glGetActiveAttribARB(programObj, attrib, sizeof name, NULL, &size, &type, name);'
José Fonseca2a794f52011-05-26 20:54:29 +0100601 print " if (name[0] != 'g' || name[1] != 'l' || name[2] != '_') {"
602 print ' GLint location = __glGetAttribLocationARB(programObj, name);'
603 print ' if (location >= 0) {'
José Fonseca91492d22011-05-23 21:20:31 +0100604 bind_function = glapi.glapi.get_function_by_name('glBindAttribLocationARB')
605 self.fake_call(bind_function, ['programObj', 'location', 'name'])
José Fonseca2a794f52011-05-26 20:54:29 +0100606 print ' }'
José Fonseca91492d22011-05-23 21:20:31 +0100607 print ' }'
608 print ' }'
609
José Fonseca54f304a2012-01-14 19:33:08 +0000610 Tracer.traceFunctionImplBody(self, function)
José Fonseca73373602011-05-20 17:45:26 +0100611
José Fonsecaf028a8f2012-02-15 23:33:35 +0000612 marker_functions = [
613 # GL_GREMEDY_string_marker
José Fonseca8f34d342011-07-15 20:16:40 +0100614 'glStringMarkerGREMEDY',
José Fonsecaf028a8f2012-02-15 23:33:35 +0000615 # GL_GREMEDY_frame_terminator
José Fonseca8f34d342011-07-15 20:16:40 +0100616 'glFrameTerminatorGREMEDY',
José Fonsecaf028a8f2012-02-15 23:33:35 +0000617 # GL_EXT_debug_marker
618 'glInsertEventMarkerEXT',
619 'glPushGroupMarkerEXT',
620 'glPopGroupMarkerEXT',
José Fonseca8f34d342011-07-15 20:16:40 +0100621 ]
622
José Fonseca54f304a2012-01-14 19:33:08 +0000623 def invokeFunction(self, function):
José Fonseca91492d22011-05-23 21:20:31 +0100624 if function.name in ('glLinkProgram', 'glLinkProgramARB'):
625 # These functions have been dispatched already
626 return
627
José Fonsecaf028a8f2012-02-15 23:33:35 +0000628 # We implement GL_EXT_debug_marker, GL_GREMEDY_*, etc., and not the
629 # driver
630 if function.name in self.marker_functions:
José Fonseca8f34d342011-07-15 20:16:40 +0100631 return
632
633 if function.name in ('glXGetProcAddress', 'glXGetProcAddressARB', 'wglGetProcAddress'):
José Fonsecaf028a8f2012-02-15 23:33:35 +0000634 else_ = ''
635 for marker_function in self.marker_functions:
636 if self.api.get_function_by_name(marker_function):
637 print ' %sif (strcmp("%s", (const char *)%s) == 0) {' % (else_, marker_function, function.args[0].name)
638 print ' __result = (%s)&%s;' % (function.type, marker_function)
639 print ' }'
640 else_ = 'else '
641 print ' %s{' % else_
José Fonseca54f304a2012-01-14 19:33:08 +0000642 Tracer.invokeFunction(self, function)
José Fonseca8f34d342011-07-15 20:16:40 +0100643 print ' }'
José Fonseca1b3d3752011-07-15 10:15:19 +0100644 return
645
José Fonsecaa08d2752011-08-25 13:26:43 +0100646 # Override GL extensions
647 if function.name in ('glGetString', 'glGetIntegerv', 'glGetStringi'):
José Fonseca54f304a2012-01-14 19:33:08 +0000648 Tracer.invokeFunction(self, function, prefix = 'gltrace::__', suffix = '_override')
José Fonsecaa08d2752011-08-25 13:26:43 +0100649 return
650
José Fonseca54f304a2012-01-14 19:33:08 +0000651 Tracer.invokeFunction(self, function)
José Fonseca91492d22011-05-23 21:20:31 +0100652
José Fonseca867b1b72011-04-24 11:58:04 +0100653 buffer_targets = [
654 'ARRAY_BUFFER',
655 'ELEMENT_ARRAY_BUFFER',
656 'PIXEL_PACK_BUFFER',
657 'PIXEL_UNPACK_BUFFER',
José Fonseca7b20d672012-01-10 19:13:58 +0000658 'UNIFORM_BUFFER',
659 'TEXTURE_BUFFER',
660 'TRANSFORM_FEEDBACK_BUFFER',
661 'COPY_READ_BUFFER',
662 'COPY_WRITE_BUFFER',
663 'DRAW_INDIRECT_BUFFER',
664 'ATOMIC_COUNTER_BUFFER',
José Fonseca867b1b72011-04-24 11:58:04 +0100665 ]
666
José Fonseca54f304a2012-01-14 19:33:08 +0000667 def wrapRet(self, function, instance):
668 Tracer.wrapRet(self, function, instance)
José Fonseca1b3d3752011-07-15 10:15:19 +0100669
José Fonsecacdc322c2012-02-29 19:29:51 +0000670 # Keep track of buffer mappings
671 if function.name in ('glMapBuffer', 'glMapBufferARB'):
José Fonseca867b1b72011-04-24 11:58:04 +0100672 print ' struct buffer_mapping *mapping = get_buffer_mapping(target);'
673 print ' if (mapping) {'
674 print ' mapping->map = %s;' % (instance)
675 print ' mapping->length = 0;'
676 print ' __glGetBufferParameteriv(target, GL_BUFFER_SIZE, &mapping->length);'
677 print ' mapping->write = (access != GL_READ_ONLY);'
José Fonseca73373602011-05-20 17:45:26 +0100678 print ' mapping->explicit_flush = false;'
José Fonseca867b1b72011-04-24 11:58:04 +0100679 print ' }'
José Fonseca867b1b72011-04-24 11:58:04 +0100680 if function.name == 'glMapBufferRange':
José Fonseca9c536b02012-02-29 20:54:13 +0000681 print ' if (access & GL_MAP_WRITE_BIT) {'
682 print ' __checkBufferMapRange = true;'
683 print ' }'
José Fonseca867b1b72011-04-24 11:58:04 +0100684 print ' struct buffer_mapping *mapping = get_buffer_mapping(target);'
685 print ' if (mapping) {'
686 print ' mapping->map = %s;' % (instance)
687 print ' mapping->length = length;'
688 print ' mapping->write = access & GL_MAP_WRITE_BIT;'
José Fonseca73373602011-05-20 17:45:26 +0100689 print ' mapping->explicit_flush = access & GL_MAP_FLUSH_EXPLICIT_BIT;'
José Fonseca867b1b72011-04-24 11:58:04 +0100690 print ' }'
José Fonseca669b1222011-02-20 09:05:10 +0000691
José Fonsecac9f12232011-03-25 20:07:42 +0000692 boolean_names = [
693 'GL_FALSE',
694 'GL_TRUE',
695 ]
696
697 def gl_boolean(self, value):
698 return self.boolean_names[int(bool(value))]
699
José Fonsecac29f4f12011-06-11 12:19:05 +0100700 # Names of the functions that unpack from a pixel buffer object. See the
701 # ARB_pixel_buffer_object specification.
José Fonsecae97bab92011-06-02 23:15:11 +0100702 unpack_function_names = set([
703 'glBitmap',
José Fonsecac29f4f12011-06-11 12:19:05 +0100704 'glColorSubTable',
705 'glColorTable',
706 'glCompressedTexImage1D',
707 'glCompressedTexImage2D',
708 'glCompressedTexImage3D',
709 'glCompressedTexSubImage1D',
710 'glCompressedTexSubImage2D',
711 'glCompressedTexSubImage3D',
712 'glConvolutionFilter1D',
713 'glConvolutionFilter2D',
José Fonsecae97bab92011-06-02 23:15:11 +0100714 'glDrawPixels',
715 'glMultiTexImage1DEXT',
716 'glMultiTexImage2DEXT',
717 'glMultiTexImage3DEXT',
718 'glMultiTexSubImage1DEXT',
719 'glMultiTexSubImage2DEXT',
720 'glMultiTexSubImage3DEXT',
José Fonsecac29f4f12011-06-11 12:19:05 +0100721 'glPixelMapfv',
722 'glPixelMapuiv',
723 'glPixelMapusv',
José Fonsecae97bab92011-06-02 23:15:11 +0100724 'glPolygonStipple',
José Fonsecac29f4f12011-06-11 12:19:05 +0100725 'glSeparableFilter2D',
José Fonsecae97bab92011-06-02 23:15:11 +0100726 'glTexImage1D',
727 'glTexImage1DEXT',
728 'glTexImage2D',
729 'glTexImage2DEXT',
730 'glTexImage3D',
731 'glTexImage3DEXT',
732 'glTexSubImage1D',
733 'glTexSubImage1DEXT',
734 'glTexSubImage2D',
735 'glTexSubImage2DEXT',
736 'glTexSubImage3D',
737 'glTexSubImage3DEXT',
738 'glTextureImage1DEXT',
739 'glTextureImage2DEXT',
740 'glTextureImage3DEXT',
741 'glTextureSubImage1DEXT',
742 'glTextureSubImage2DEXT',
743 'glTextureSubImage3DEXT',
744 ])
745
José Fonseca54f304a2012-01-14 19:33:08 +0000746 def serializeArgValue(self, function, arg):
José Fonseca99221832011-03-22 22:15:46 +0000747 if function.name in self.draw_function_names and arg.name == 'indices':
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000748 print ' GLint __element_array_buffer = 0;'
749 print ' __glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &__element_array_buffer);'
750 print ' if (!__element_array_buffer) {'
José Fonseca5c749e32011-05-09 11:11:37 +0100751 if isinstance(arg.type, stdapi.Array):
José Fonsecab4a3d142011-10-27 07:43:19 +0100752 print ' trace::localWriter.beginArray(%s);' % arg.type.length
José Fonseca5c749e32011-05-09 11:11:37 +0100753 print ' for(GLsizei i = 0; i < %s; ++i) {' % arg.type.length
José Fonsecab4a3d142011-10-27 07:43:19 +0100754 print ' trace::localWriter.beginElement();'
755 print ' trace::localWriter.writeBlob(%s[i], count[i]*__gl_type_size(type));' % (arg.name)
756 print ' trace::localWriter.endElement();'
José Fonseca5c749e32011-05-09 11:11:37 +0100757 print ' }'
José Fonsecab4a3d142011-10-27 07:43:19 +0100758 print ' trace::localWriter.endArray();'
José Fonseca5c749e32011-05-09 11:11:37 +0100759 else:
José Fonsecab4a3d142011-10-27 07:43:19 +0100760 print ' trace::localWriter.writeBlob(%s, count*__gl_type_size(type));' % (arg.name)
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000761 print ' } else {'
José Fonseca54f304a2012-01-14 19:33:08 +0000762 Tracer.serializeArgValue(self, function, arg)
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000763 print ' }'
764 return
765
José Fonsecae97bab92011-06-02 23:15:11 +0100766 # Recognize offsets instead of blobs when a PBO is bound
767 if function.name in self.unpack_function_names \
768 and (isinstance(arg.type, stdapi.Blob) \
769 or (isinstance(arg.type, stdapi.Const) \
770 and isinstance(arg.type.type, stdapi.Blob))):
José Fonsecac29f4f12011-06-11 12:19:05 +0100771 print ' {'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000772 print ' gltrace::Context *ctx = gltrace::getContext();'
José Fonsecac29f4f12011-06-11 12:19:05 +0100773 print ' GLint __unpack_buffer = 0;'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000774 print ' if (ctx->profile == gltrace::PROFILE_COMPAT)'
Chia-I Wub3d218d2011-11-03 01:37:36 +0800775 print ' __glGetIntegerv(GL_PIXEL_UNPACK_BUFFER_BINDING, &__unpack_buffer);'
José Fonsecac29f4f12011-06-11 12:19:05 +0100776 print ' if (__unpack_buffer) {'
José Fonsecab4a3d142011-10-27 07:43:19 +0100777 print ' trace::localWriter.writeOpaque(%s);' % arg.name
José Fonsecac29f4f12011-06-11 12:19:05 +0100778 print ' } else {'
José Fonseca54f304a2012-01-14 19:33:08 +0000779 Tracer.serializeArgValue(self, function, arg)
José Fonsecac29f4f12011-06-11 12:19:05 +0100780 print ' }'
José Fonsecae97bab92011-06-02 23:15:11 +0100781 print ' }'
782 return
783
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100784 # Several GL state functions take GLenum symbolic names as
785 # integer/floats; so dump the symbolic name whenever possible
José Fonseca3bcb33c2011-05-27 20:14:31 +0100786 if function.name.startswith('gl') \
José Fonsecae3571092011-10-13 08:26:27 +0100787 and arg.type in (glapi.GLint, glapi.GLfloat, glapi.GLdouble) \
José Fonseca3bcb33c2011-05-27 20:14:31 +0100788 and arg.name == 'param':
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100789 assert arg.index > 0
790 assert function.args[arg.index - 1].name == 'pname'
791 assert function.args[arg.index - 1].type == glapi.GLenum
792 print ' if (is_symbolic_pname(pname) && is_symbolic_param(%s)) {' % arg.name
José Fonseca54f304a2012-01-14 19:33:08 +0000793 self.serializeValue(glapi.GLenum, arg.name)
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100794 print ' } else {'
José Fonseca54f304a2012-01-14 19:33:08 +0000795 Tracer.serializeArgValue(self, function, arg)
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100796 print ' }'
797 return
798
José Fonseca54f304a2012-01-14 19:33:08 +0000799 Tracer.serializeArgValue(self, function, arg)
José Fonseca99221832011-03-22 22:15:46 +0000800
José Fonseca4c938c22011-04-30 22:44:38 +0100801 def footer(self, api):
802 Tracer.footer(self, api)
José Fonseca669b1222011-02-20 09:05:10 +0000803
José Fonseca4c938c22011-04-30 22:44:38 +0100804 # A simple state tracker to track the pointer values
José Fonseca669b1222011-02-20 09:05:10 +0000805 # update the state
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000806 print 'static void __trace_user_arrays(GLuint maxindex)'
José Fonseca669b1222011-02-20 09:05:10 +0000807 print '{'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000808 print ' gltrace::Context *ctx = gltrace::getContext();'
José Fonseca1a2fdd22011-04-01 00:55:09 +0100809
José Fonseca99221832011-03-22 22:15:46 +0000810 for camelcase_name, uppercase_name in self.arrays:
Chia-I Wub3d218d2011-11-03 01:37:36 +0800811 # in which profile is the array available?
José Fonsecaf028a8f2012-02-15 23:33:35 +0000812 profile_check = 'ctx->profile == gltrace::PROFILE_COMPAT'
Chia-I Wub3d218d2011-11-03 01:37:36 +0800813 if camelcase_name in self.arrays_es1:
José Fonsecaf028a8f2012-02-15 23:33:35 +0000814 profile_check = '(' + profile_check + ' || ctx->profile == gltrace::PROFILE_ES1)';
Chia-I Wub3d218d2011-11-03 01:37:36 +0800815
José Fonseca99221832011-03-22 22:15:46 +0000816 function_name = 'gl%sPointer' % camelcase_name
817 enable_name = 'GL_%s_ARRAY' % uppercase_name
818 binding_name = 'GL_%s_ARRAY_BUFFER_BINDING' % uppercase_name
José Fonseca14c21bc2011-02-20 23:32:22 +0000819 function = api.get_function_by_name(function_name)
José Fonseca99221832011-03-22 22:15:46 +0000820
José Fonseca06e85192011-10-16 14:15:36 +0100821 print ' // %s' % function.prototype()
Chia-I Wub3d218d2011-11-03 01:37:36 +0800822 print ' if (%s) {' % profile_check
José Fonsecafb6744f2011-04-15 11:18:37 +0100823 self.array_trace_prolog(api, uppercase_name)
824 self.array_prolog(api, uppercase_name)
825 print ' if (__glIsEnabled(%s)) {' % enable_name
José Fonseca7f5163e2011-03-31 23:37:26 +0100826 print ' GLint __binding = 0;'
827 print ' __glGetIntegerv(%s, &__binding);' % binding_name
828 print ' if (!__binding) {'
José Fonseca99221832011-03-22 22:15:46 +0000829
830 # Get the arguments via glGet*
831 for arg in function.args:
832 arg_get_enum = 'GL_%s_ARRAY_%s' % (uppercase_name, arg.name.upper())
833 arg_get_function, arg_type = TypeGetter().visit(arg.type)
José Fonseca7f5163e2011-03-31 23:37:26 +0100834 print ' %s %s = 0;' % (arg_type, arg.name)
835 print ' __%s(%s, &%s);' % (arg_get_function, arg_get_enum, arg.name)
José Fonseca99221832011-03-22 22:15:46 +0000836
837 arg_names = ', '.join([arg.name for arg in function.args[:-1]])
José Fonseca7f5163e2011-03-31 23:37:26 +0100838 print ' size_t __size = __%s_size(%s, maxindex);' % (function.name, arg_names)
José Fonseca99221832011-03-22 22:15:46 +0000839
840 # Emit a fake function
José Fonsecafb6744f2011-04-15 11:18:37 +0100841 self.array_trace_intermezzo(api, uppercase_name)
José Fonsecab4a3d142011-10-27 07:43:19 +0100842 print ' unsigned __call = trace::localWriter.beginEnter(&__%s_sig);' % (function.name,)
José Fonseca669b1222011-02-20 09:05:10 +0000843 for arg in function.args:
844 assert not arg.output
José Fonsecab4a3d142011-10-27 07:43:19 +0100845 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
José Fonseca14c21bc2011-02-20 23:32:22 +0000846 if arg.name != 'pointer':
José Fonseca54f304a2012-01-14 19:33:08 +0000847 self.serializeValue(arg.type, arg.name)
José Fonseca14c21bc2011-02-20 23:32:22 +0000848 else:
José Fonsecab4a3d142011-10-27 07:43:19 +0100849 print ' trace::localWriter.writeBlob((const void *)%s, __size);' % (arg.name)
850 print ' trace::localWriter.endArg();'
José Fonseca99221832011-03-22 22:15:46 +0000851
José Fonsecab4a3d142011-10-27 07:43:19 +0100852 print ' trace::localWriter.endEnter();'
853 print ' trace::localWriter.beginLeave(__call);'
854 print ' trace::localWriter.endLeave();'
José Fonseca99221832011-03-22 22:15:46 +0000855 print ' }'
José Fonseca669b1222011-02-20 09:05:10 +0000856 print ' }'
José Fonsecafb6744f2011-04-15 11:18:37 +0100857 self.array_epilog(api, uppercase_name)
858 self.array_trace_epilog(api, uppercase_name)
Chia-I Wub3d218d2011-11-03 01:37:36 +0800859 print ' }'
José Fonseca99221832011-03-22 22:15:46 +0000860 print
José Fonseca1a2fdd22011-04-01 00:55:09 +0100861
José Fonseca1601c412011-05-10 10:38:19 +0100862 # Samething, but for glVertexAttribPointer*
863 #
864 # Some variants of glVertexAttribPointer alias conventional and generic attributes:
865 # - glVertexAttribPointer: no
866 # - glVertexAttribPointerARB: implementation dependent
867 # - glVertexAttribPointerNV: yes
868 #
869 # This means that the implementations of these functions do not always
870 # alias, and they need to be considered independently.
871 #
Chia-I Wub3d218d2011-11-03 01:37:36 +0800872 print ' // ES1 does not support generic vertex attributes'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000873 print ' if (ctx->profile == gltrace::PROFILE_ES1)'
Chia-I Wub3d218d2011-11-03 01:37:36 +0800874 print ' return;'
875 print
José Fonseca5a568a92011-06-29 16:43:36 +0100876 print ' vertex_attrib __vertex_attrib = __get_vertex_attrib();'
877 print
878 for suffix in ['', 'ARB', 'NV']:
879 if suffix:
José Fonsecad94aaac2011-06-28 20:50:49 +0100880 SUFFIX = '_' + suffix
José Fonsecad94aaac2011-06-28 20:50:49 +0100881 else:
José Fonseca5a568a92011-06-29 16:43:36 +0100882 SUFFIX = suffix
José Fonseca1601c412011-05-10 10:38:19 +0100883 function_name = 'glVertexAttribPointer' + suffix
José Fonseca06e85192011-10-16 14:15:36 +0100884 function = api.get_function_by_name(function_name)
885
886 print ' // %s' % function.prototype()
José Fonseca5a568a92011-06-29 16:43:36 +0100887 print ' if (__vertex_attrib == VERTEX_ATTRIB%s) {' % SUFFIX
888 if suffix == 'NV':
889 print ' GLint __max_vertex_attribs = 16;'
890 else:
891 print ' GLint __max_vertex_attribs = 0;'
892 print ' __glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &__max_vertex_attribs);'
893 print ' for (GLint index = 0; index < __max_vertex_attribs; ++index) {'
894 print ' GLint __enabled = 0;'
895 if suffix == 'NV':
896 print ' __glGetIntegerv(GL_VERTEX_ATTRIB_ARRAY0_NV + index, &__enabled);'
897 else:
898 print ' __glGetVertexAttribiv%s(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED%s, &__enabled);' % (suffix, SUFFIX)
899 print ' if (__enabled) {'
900 print ' GLint __binding = 0;'
901 if suffix != 'NV':
902 # It doesn't seem possible to use VBOs with NV_vertex_program.
903 print ' __glGetVertexAttribiv%s(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING%s, &__binding);' % (suffix, SUFFIX)
904 print ' if (!__binding) {'
José Fonseca1a2fdd22011-04-01 00:55:09 +0100905
José Fonseca1601c412011-05-10 10:38:19 +0100906 # Get the arguments via glGet*
907 for arg in function.args[1:]:
José Fonseca5a568a92011-06-29 16:43:36 +0100908 if suffix == 'NV':
909 arg_get_enum = 'GL_ATTRIB_ARRAY_%s%s' % (arg.name.upper(), SUFFIX)
910 else:
911 arg_get_enum = 'GL_VERTEX_ATTRIB_ARRAY_%s%s' % (arg.name.upper(), SUFFIX)
José Fonsecac493e3e2011-06-29 12:57:06 +0100912 arg_get_function, arg_type = TypeGetter('glGetVertexAttrib', False, suffix).visit(arg.type)
José Fonseca5a568a92011-06-29 16:43:36 +0100913 print ' %s %s = 0;' % (arg_type, arg.name)
914 print ' __%s(index, %s, &%s);' % (arg_get_function, arg_get_enum, arg.name)
José Fonseca1601c412011-05-10 10:38:19 +0100915
916 arg_names = ', '.join([arg.name for arg in function.args[1:-1]])
José Fonseca5a568a92011-06-29 16:43:36 +0100917 print ' size_t __size = __%s_size(%s, maxindex);' % (function.name, arg_names)
José Fonseca1a2fdd22011-04-01 00:55:09 +0100918
José Fonseca1601c412011-05-10 10:38:19 +0100919 # Emit a fake function
José Fonsecab4a3d142011-10-27 07:43:19 +0100920 print ' unsigned __call = trace::localWriter.beginEnter(&__%s_sig);' % (function.name,)
José Fonseca1601c412011-05-10 10:38:19 +0100921 for arg in function.args:
922 assert not arg.output
José Fonsecab4a3d142011-10-27 07:43:19 +0100923 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
José Fonseca1601c412011-05-10 10:38:19 +0100924 if arg.name != 'pointer':
José Fonseca54f304a2012-01-14 19:33:08 +0000925 self.serializeValue(arg.type, arg.name)
José Fonseca1601c412011-05-10 10:38:19 +0100926 else:
José Fonsecab4a3d142011-10-27 07:43:19 +0100927 print ' trace::localWriter.writeBlob((const void *)%s, __size);' % (arg.name)
928 print ' trace::localWriter.endArg();'
José Fonseca1601c412011-05-10 10:38:19 +0100929
José Fonsecab4a3d142011-10-27 07:43:19 +0100930 print ' trace::localWriter.endEnter();'
931 print ' trace::localWriter.beginLeave(__call);'
932 print ' trace::localWriter.endLeave();'
José Fonseca1601c412011-05-10 10:38:19 +0100933 print ' }'
934 print ' }'
935 print ' }'
936 print ' }'
937 print
José Fonseca1a2fdd22011-04-01 00:55:09 +0100938
José Fonseca669b1222011-02-20 09:05:10 +0000939 print '}'
940 print
941
José Fonsecafb6744f2011-04-15 11:18:37 +0100942 #
943 # Hooks for glTexCoordPointer, which is identical to the other array
944 # pointers except the fact that it is indexed by glClientActiveTexture.
945 #
946
947 def array_prolog(self, api, uppercase_name):
948 if uppercase_name == 'TEXTURE_COORD':
949 print ' GLint client_active_texture = 0;'
950 print ' __glGetIntegerv(GL_CLIENT_ACTIVE_TEXTURE, &client_active_texture);'
951 print ' GLint max_texture_coords = 0;'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000952 print ' if (ctx->profile == gltrace::PROFILE_COMPAT)'
Chia-I Wub3d218d2011-11-03 01:37:36 +0800953 print ' __glGetIntegerv(GL_MAX_TEXTURE_COORDS, &max_texture_coords);'
954 print ' else'
955 print ' __glGetIntegerv(GL_MAX_TEXTURE_UNITS, &max_texture_coords);'
José Fonsecafb6744f2011-04-15 11:18:37 +0100956 print ' for (GLint unit = 0; unit < max_texture_coords; ++unit) {'
José Fonseca7525e6f2011-09-28 09:04:56 +0100957 print ' GLint texture = GL_TEXTURE0 + unit;'
José Fonsecafb6744f2011-04-15 11:18:37 +0100958 print ' __glClientActiveTexture(texture);'
959
960 def array_trace_prolog(self, api, uppercase_name):
961 if uppercase_name == 'TEXTURE_COORD':
962 print ' bool client_active_texture_dirty = false;'
963
964 def array_epilog(self, api, uppercase_name):
965 if uppercase_name == 'TEXTURE_COORD':
966 print ' }'
967 self.array_cleanup(api, uppercase_name)
968
969 def array_cleanup(self, api, uppercase_name):
970 if uppercase_name == 'TEXTURE_COORD':
971 print ' __glClientActiveTexture(client_active_texture);'
972
973 def array_trace_intermezzo(self, api, uppercase_name):
974 if uppercase_name == 'TEXTURE_COORD':
975 print ' if (texture != client_active_texture || client_active_texture_dirty) {'
976 print ' client_active_texture_dirty = true;'
977 self.fake_glClientActiveTexture_call(api, "texture");
978 print ' }'
979
980 def array_trace_epilog(self, api, uppercase_name):
981 if uppercase_name == 'TEXTURE_COORD':
982 print ' if (client_active_texture_dirty) {'
983 self.fake_glClientActiveTexture_call(api, "client_active_texture");
984 print ' }'
985
986 def fake_glClientActiveTexture_call(self, api, texture):
987 function = api.get_function_by_name('glClientActiveTexture')
988 self.fake_call(function, [texture])
989
990 def fake_call(self, function, args):
José Fonsecab4a3d142011-10-27 07:43:19 +0100991 print ' unsigned __fake_call = trace::localWriter.beginEnter(&__%s_sig);' % (function.name,)
José Fonsecafb6744f2011-04-15 11:18:37 +0100992 for arg, instance in zip(function.args, args):
993 assert not arg.output
José Fonsecab4a3d142011-10-27 07:43:19 +0100994 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
José Fonseca54f304a2012-01-14 19:33:08 +0000995 self.serializeValue(arg.type, instance)
José Fonsecab4a3d142011-10-27 07:43:19 +0100996 print ' trace::localWriter.endArg();'
997 print ' trace::localWriter.endEnter();'
998 print ' trace::localWriter.beginLeave(__fake_call);'
999 print ' trace::localWriter.endLeave();'
José Fonsecafb6744f2011-04-15 11:18:37 +01001000
1001
1002
1003
1004
José Fonseca669b1222011-02-20 09:05:10 +00001005
1006
1007
1008
1009
1010