blob: 9f60acb9b1a21ebea851c2047f230e9e3badd134 [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é Fonseca1b6c8752012-04-15 14:33:00 +010031from dispatch import function_pointer_type, function_pointer_value
José Fonsecabd86a222011-09-27 09:21:38 +010032import specs.stdapi as stdapi
33import specs.glapi as glapi
34import specs.glparams as glparams
35from specs.glxapi import glxapi
José Fonseca669b1222011-02-20 09:05:10 +000036
37
José Fonseca99221832011-03-22 22:15:46 +000038class TypeGetter(stdapi.Visitor):
39 '''Determine which glGet*v function that matches the specified type.'''
40
José Fonsecac493e3e2011-06-29 12:57:06 +010041 def __init__(self, prefix = 'glGet', long_suffix = True, ext_suffix = ''):
José Fonseca1a2fdd22011-04-01 00:55:09 +010042 self.prefix = prefix
43 self.long_suffix = long_suffix
José Fonsecac493e3e2011-06-29 12:57:06 +010044 self.ext_suffix = ext_suffix
José Fonseca1a2fdd22011-04-01 00:55:09 +010045
José Fonseca54f304a2012-01-14 19:33:08 +000046 def visitConst(self, const):
José Fonseca99221832011-03-22 22:15:46 +000047 return self.visit(const.type)
48
José Fonseca54f304a2012-01-14 19:33:08 +000049 def visitAlias(self, alias):
José Fonseca99221832011-03-22 22:15:46 +000050 if alias.expr == 'GLboolean':
José Fonseca1a2fdd22011-04-01 00:55:09 +010051 if self.long_suffix:
José Fonsecac493e3e2011-06-29 12:57:06 +010052 suffix = 'Booleanv'
53 arg_type = alias.expr
José Fonseca1a2fdd22011-04-01 00:55:09 +010054 else:
José Fonsecac493e3e2011-06-29 12:57:06 +010055 suffix = 'iv'
56 arg_type = 'GLint'
José Fonseca99221832011-03-22 22:15:46 +000057 elif alias.expr == 'GLdouble':
José Fonseca1a2fdd22011-04-01 00:55:09 +010058 if self.long_suffix:
José Fonsecac493e3e2011-06-29 12:57:06 +010059 suffix = 'Doublev'
60 arg_type = alias.expr
José Fonseca1a2fdd22011-04-01 00:55:09 +010061 else:
José Fonsecac493e3e2011-06-29 12:57:06 +010062 suffix = 'dv'
63 arg_type = alias.expr
José Fonseca99221832011-03-22 22:15:46 +000064 elif alias.expr == 'GLfloat':
José Fonseca1a2fdd22011-04-01 00:55:09 +010065 if self.long_suffix:
José Fonsecac493e3e2011-06-29 12:57:06 +010066 suffix = 'Floatv'
67 arg_type = alias.expr
José Fonseca1a2fdd22011-04-01 00:55:09 +010068 else:
José Fonsecac493e3e2011-06-29 12:57:06 +010069 suffix = 'fv'
70 arg_type = alias.expr
José Fonseca7f5163e2011-03-31 23:37:26 +010071 elif alias.expr in ('GLint', 'GLuint', 'GLsizei'):
José Fonseca1a2fdd22011-04-01 00:55:09 +010072 if self.long_suffix:
José Fonsecac493e3e2011-06-29 12:57:06 +010073 suffix = 'Integerv'
74 arg_type = 'GLint'
José Fonseca1a2fdd22011-04-01 00:55:09 +010075 else:
José Fonsecac493e3e2011-06-29 12:57:06 +010076 suffix = 'iv'
77 arg_type = 'GLint'
José Fonseca99221832011-03-22 22:15:46 +000078 else:
79 print alias.expr
80 assert False
José Fonsecac493e3e2011-06-29 12:57:06 +010081 function_name = self.prefix + suffix + self.ext_suffix
82 return function_name, arg_type
José Fonseca99221832011-03-22 22:15:46 +000083
José Fonseca54f304a2012-01-14 19:33:08 +000084 def visitEnum(self, enum):
José Fonseca1a2fdd22011-04-01 00:55:09 +010085 return self.visit(glapi.GLint)
José Fonseca99221832011-03-22 22:15:46 +000086
José Fonseca54f304a2012-01-14 19:33:08 +000087 def visitBitmask(self, bitmask):
José Fonseca1a2fdd22011-04-01 00:55:09 +010088 return self.visit(glapi.GLint)
José Fonseca99221832011-03-22 22:15:46 +000089
José Fonseca54f304a2012-01-14 19:33:08 +000090 def visitOpaque(self, pointer):
José Fonsecac493e3e2011-06-29 12:57:06 +010091 return self.prefix + 'Pointerv' + self.ext_suffix, 'GLvoid *'
José Fonseca99221832011-03-22 22:15:46 +000092
93
José Fonseca669b1222011-02-20 09:05:10 +000094class GlTracer(Tracer):
95
José Fonseca99221832011-03-22 22:15:46 +000096 arrays = [
97 ("Vertex", "VERTEX"),
98 ("Normal", "NORMAL"),
99 ("Color", "COLOR"),
100 ("Index", "INDEX"),
101 ("TexCoord", "TEXTURE_COORD"),
102 ("EdgeFlag", "EDGE_FLAG"),
103 ("FogCoord", "FOG_COORD"),
104 ("SecondaryColor", "SECONDARY_COLOR"),
José Fonseca14c21bc2011-02-20 23:32:22 +0000105 ]
José Fonsecac9f12232011-03-25 20:07:42 +0000106 arrays.reverse()
José Fonseca669b1222011-02-20 09:05:10 +0000107
Chia-I Wub3d218d2011-11-03 01:37:36 +0800108 # arrays available in PROFILE_ES1
109 arrays_es1 = ("Vertex", "Normal", "Color", "TexCoord")
110
José Fonseca4c938c22011-04-30 22:44:38 +0100111 def header(self, api):
112 Tracer.header(self, api)
113
José Fonseca1b3d3752011-07-15 10:15:19 +0100114 print '#include "gltrace.hpp"'
115 print
José Fonseca5a568a92011-06-29 16:43:36 +0100116
117 # Which glVertexAttrib* variant to use
118 print 'enum vertex_attrib {'
119 print ' VERTEX_ATTRIB,'
120 print ' VERTEX_ATTRIB_ARB,'
121 print ' VERTEX_ATTRIB_NV,'
122 print '};'
123 print
José Fonsecaf028a8f2012-02-15 23:33:35 +0000124 print 'gltrace::Context *'
125 print 'gltrace::getContext(void)'
Chia-I Wu8ef66972011-11-03 01:19:46 +0800126 print '{'
127 print ' // TODO return the context set by other APIs (GLX, EGL, and etc.)'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000128 print ' static gltrace::Context __ctx = { gltrace::PROFILE_COMPAT, false, false, false };'
Chia-I Wu8ef66972011-11-03 01:19:46 +0800129 print ' return &__ctx;'
130 print '}'
131 print
José Fonseca5a568a92011-06-29 16:43:36 +0100132 print 'static vertex_attrib __get_vertex_attrib(void) {'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000133 print ' gltrace::Context *ctx = gltrace::getContext();'
Chia-I Wu8ef66972011-11-03 01:19:46 +0800134 print ' if (ctx->user_arrays_arb || ctx->user_arrays_nv) {'
José Fonseca5a568a92011-06-29 16:43:36 +0100135 print ' GLboolean __vertex_program = GL_FALSE;'
136 print ' __glGetBooleanv(GL_VERTEX_PROGRAM_ARB, &__vertex_program);'
137 print ' if (__vertex_program) {'
Chia-I Wu8ef66972011-11-03 01:19:46 +0800138 print ' if (ctx->user_arrays_nv) {'
José Fonseca5a568a92011-06-29 16:43:36 +0100139 print ' GLint __vertex_program_binding_nv = 0;'
140 print ' __glGetIntegerv(GL_VERTEX_PROGRAM_BINDING_NV, &__vertex_program_binding_nv);'
141 print ' if (__vertex_program_binding_nv) {'
142 print ' return VERTEX_ATTRIB_NV;'
143 print ' }'
144 print ' }'
145 print ' return VERTEX_ATTRIB_ARB;'
146 print ' }'
147 print ' }'
148 print ' return VERTEX_ATTRIB;'
149 print '}'
150 print
151
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000152 # Whether we need user arrays
153 print 'static inline bool __need_user_arrays(void)'
154 print '{'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000155 print ' gltrace::Context *ctx = gltrace::getContext();'
Chia-I Wu8ef66972011-11-03 01:19:46 +0800156 print ' if (!ctx->user_arrays) {'
José Fonseca25ebe542011-04-24 10:08:22 +0100157 print ' return false;'
158 print ' }'
159 print
José Fonseca1a2fdd22011-04-01 00:55:09 +0100160
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000161 for camelcase_name, uppercase_name in self.arrays:
Chia-I Wub3d218d2011-11-03 01:37:36 +0800162 # in which profile is the array available?
José Fonsecaf028a8f2012-02-15 23:33:35 +0000163 profile_check = 'ctx->profile == gltrace::PROFILE_COMPAT'
Chia-I Wub3d218d2011-11-03 01:37:36 +0800164 if camelcase_name in self.arrays_es1:
José Fonsecaf028a8f2012-02-15 23:33:35 +0000165 profile_check = '(' + profile_check + ' || ctx->profile == gltrace::PROFILE_ES1)';
Chia-I Wub3d218d2011-11-03 01:37:36 +0800166
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000167 function_name = 'gl%sPointer' % camelcase_name
168 enable_name = 'GL_%s_ARRAY' % uppercase_name
169 binding_name = 'GL_%s_ARRAY_BUFFER_BINDING' % uppercase_name
170 print ' // %s' % function_name
Chia-I Wub3d218d2011-11-03 01:37:36 +0800171 print ' if (%s) {' % profile_check
José Fonsecafb6744f2011-04-15 11:18:37 +0100172 self.array_prolog(api, uppercase_name)
José Fonseca7f5163e2011-03-31 23:37:26 +0100173 print ' if (__glIsEnabled(%s)) {' % enable_name
174 print ' GLint __binding = 0;'
175 print ' __glGetIntegerv(%s, &__binding);' % binding_name
176 print ' if (!__binding) {'
José Fonsecafb6744f2011-04-15 11:18:37 +0100177 self.array_cleanup(api, uppercase_name)
José Fonseca7f5163e2011-03-31 23:37:26 +0100178 print ' return true;'
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000179 print ' }'
180 print ' }'
José Fonsecafb6744f2011-04-15 11:18:37 +0100181 self.array_epilog(api, uppercase_name)
Chia-I Wub3d218d2011-11-03 01:37:36 +0800182 print ' }'
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000183 print
José Fonseca7f5163e2011-03-31 23:37:26 +0100184
Chia-I Wub3d218d2011-11-03 01:37:36 +0800185 print ' // ES1 does not support generic vertex attributes'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000186 print ' if (ctx->profile == gltrace::PROFILE_ES1)'
Chia-I Wub3d218d2011-11-03 01:37:36 +0800187 print ' return false;'
188 print
José Fonseca5a568a92011-06-29 16:43:36 +0100189 print ' vertex_attrib __vertex_attrib = __get_vertex_attrib();'
190 print
191 print ' // glVertexAttribPointer'
192 print ' if (__vertex_attrib == VERTEX_ATTRIB) {'
193 print ' GLint __max_vertex_attribs = 0;'
194 print ' __glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &__max_vertex_attribs);'
195 print ' for (GLint index = 0; index < __max_vertex_attribs; ++index) {'
196 print ' GLint __enabled = 0;'
197 print ' __glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &__enabled);'
198 print ' if (__enabled) {'
199 print ' GLint __binding = 0;'
200 print ' __glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &__binding);'
201 print ' if (!__binding) {'
202 print ' return true;'
203 print ' }'
204 print ' }'
205 print ' }'
206 print ' }'
207 print
208 print ' // glVertexAttribPointerARB'
209 print ' if (__vertex_attrib == VERTEX_ATTRIB_ARB) {'
José Fonsecad94aaac2011-06-28 20:50:49 +0100210 print ' GLint __max_vertex_attribs = 0;'
211 print ' __glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &__max_vertex_attribs);'
212 print ' for (GLint index = 0; index < __max_vertex_attribs; ++index) {'
213 print ' GLint __enabled = 0;'
214 print ' __glGetVertexAttribivARB(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB, &__enabled);'
215 print ' if (__enabled) {'
216 print ' GLint __binding = 0;'
217 print ' __glGetVertexAttribivARB(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB, &__binding);'
218 print ' if (!__binding) {'
219 print ' return true;'
220 print ' }'
221 print ' }'
222 print ' }'
José Fonseca5a568a92011-06-29 16:43:36 +0100223 print ' }'
224 print
225 print ' // glVertexAttribPointerNV'
226 print ' if (__vertex_attrib == VERTEX_ATTRIB_NV) {'
227 print ' for (GLint index = 0; index < 16; ++index) {'
José Fonsecad94aaac2011-06-28 20:50:49 +0100228 print ' GLint __enabled = 0;'
José Fonseca5a568a92011-06-29 16:43:36 +0100229 print ' __glGetIntegerv(GL_VERTEX_ATTRIB_ARRAY0_NV + index, &__enabled);'
José Fonsecad94aaac2011-06-28 20:50:49 +0100230 print ' if (__enabled) {'
José Fonseca5a568a92011-06-29 16:43:36 +0100231 print ' return true;'
José Fonseca1a2fdd22011-04-01 00:55:09 +0100232 print ' }'
233 print ' }'
234 print ' }'
235 print
236
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000237 print ' return false;'
238 print '}'
239 print
José Fonseca669b1222011-02-20 09:05:10 +0000240
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000241 print 'static void __trace_user_arrays(GLuint maxindex);'
José Fonseca14c21bc2011-02-20 23:32:22 +0000242 print
José Fonseca867b1b72011-04-24 11:58:04 +0100243
José Fonseca9c536b02012-02-29 20:54:13 +0000244 # Buffer mappings
245 print '// whether glMapBufferRange(GL_MAP_WRITE_BIT) has ever been called'
246 print 'static bool __checkBufferMapRange = false;'
247 print
248 print '// whether glBufferParameteriAPPLE(GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE) has ever been called'
249 print 'static bool __checkBufferFlushingUnmapAPPLE = false;'
250 print
251 # Buffer mapping information, necessary for old Mesa 2.1 drivers which
252 # do not support glGetBufferParameteriv(GL_BUFFER_ACCESS_FLAGS/GL_BUFFER_MAP_LENGTH)
José Fonseca867b1b72011-04-24 11:58:04 +0100253 print 'struct buffer_mapping {'
254 print ' void *map;'
255 print ' GLint length;'
256 print ' bool write;'
José Fonseca73373602011-05-20 17:45:26 +0100257 print ' bool explicit_flush;'
José Fonseca867b1b72011-04-24 11:58:04 +0100258 print '};'
259 print
260 for target in self.buffer_targets:
261 print 'struct buffer_mapping __%s_mapping;' % target.lower();
262 print
263 print 'static inline struct buffer_mapping *'
264 print 'get_buffer_mapping(GLenum target) {'
José Fonseca06e85192011-10-16 14:15:36 +0100265 print ' switch (target) {'
José Fonseca867b1b72011-04-24 11:58:04 +0100266 for target in self.buffer_targets:
267 print ' case GL_%s:' % target
268 print ' return & __%s_mapping;' % target.lower()
269 print ' default:'
José Fonseca559d5342011-10-27 08:10:56 +0100270 print ' os::log("apitrace: warning: unknown buffer target 0x%04X\\n", target);'
José Fonseca867b1b72011-04-24 11:58:04 +0100271 print ' return NULL;'
272 print ' }'
273 print '}'
274 print
275
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100276 # Generate a helper function to determine whether a parameter name
277 # refers to a symbolic value or not
278 print 'static bool'
279 print 'is_symbolic_pname(GLenum pname) {'
José Fonseca06e85192011-10-16 14:15:36 +0100280 print ' switch (pname) {'
José Fonseca5ea91872011-05-04 09:41:55 +0100281 for function, type, count, name in glparams.parameters:
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100282 if type is glapi.GLenum:
José Fonseca4c938c22011-04-30 22:44:38 +0100283 print ' case %s:' % name
284 print ' return true;'
285 print ' default:'
286 print ' return false;'
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100287 print ' }'
288 print '}'
289 print
290
291 # Generate a helper function to determine whether a parameter value is
292 # potentially symbolic or not; i.e., if the value can be represented in
293 # an enum or not
294 print 'template<class T>'
295 print 'static inline bool'
296 print 'is_symbolic_param(T param) {'
297 print ' return static_cast<T>(static_cast<GLenum>(param)) == param;'
298 print '}'
299 print
José Fonseca4c938c22011-04-30 22:44:38 +0100300
301 # Generate a helper function to know how many elements a parameter has
302 print 'static size_t'
José Fonsecaf4aca5d2011-05-08 08:29:30 +0100303 print '__gl_param_size(GLenum pname) {'
José Fonseca06e85192011-10-16 14:15:36 +0100304 print ' switch (pname) {'
José Fonseca5ea91872011-05-04 09:41:55 +0100305 for function, type, count, name in glparams.parameters:
José Fonseca4c938c22011-04-30 22:44:38 +0100306 if type is not None:
307 print ' case %s: return %u;' % (name, count)
308 print ' case GL_COMPRESSED_TEXTURE_FORMATS: {'
309 print ' GLint num_compressed_texture_formats = 0;'
310 print ' __glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &num_compressed_texture_formats);'
311 print ' return num_compressed_texture_formats;'
312 print ' }'
313 print ' default:'
José Fonseca559d5342011-10-27 08:10:56 +0100314 print r' os::log("apitrace: warning: %s: unknown GLenum 0x%04X\n", __FUNCTION__, pname);'
José Fonseca4c938c22011-04-30 22:44:38 +0100315 print ' return 1;'
316 print ' }'
317 print '}'
318 print
319
Chia-I Wu335efb42011-11-03 01:59:22 +0800320 # states such as GL_UNPACK_ROW_LENGTH are not available in GLES
321 print 'static inline bool'
322 print 'can_unpack_subimage(void) {'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000323 print ' gltrace::Context *ctx = gltrace::getContext();'
324 print ' return (ctx->profile == gltrace::PROFILE_COMPAT);'
Chia-I Wu335efb42011-11-03 01:59:22 +0800325 print '}'
326 print
327
José Fonseca1b6c8752012-04-15 14:33:00 +0100328 getProcAddressFunctionNames = []
329
330 def traceApi(self, api):
331 if self.getProcAddressFunctionNames:
332 # Generate a function to wrap proc addresses
333 getProcAddressFunction = api.getFunctionByName(self.getProcAddressFunctionNames[0])
334 argType = getProcAddressFunction.args[0].type
335 retType = getProcAddressFunction.type
336
337 print 'static %s _wrapProcAddress(%s procName, %s procPtr);' % (retType, argType, retType)
338 print
339
340 Tracer.traceApi(self, api)
341
342 print 'static %s _wrapProcAddress(%s procName, %s procPtr) {' % (retType, argType, retType)
343 print ' if (!procPtr) {'
344 print ' return procPtr;'
345 print ' }'
346 for function in api.functions:
347 ptype = function_pointer_type(function)
348 pvalue = function_pointer_value(function)
349 print ' if (strcmp("%s", (const char *)procName) == 0) {' % function.name
350 print ' %s = (%s)procPtr;' % (pvalue, ptype)
351 print ' return (%s)&%s;' % (retType, function.name,)
352 print ' }'
353 print ' os::log("apitrace: warning: unknown function \\"%s\\"\\n", (const char *)procName);'
354 print ' return procPtr;'
355 print '}'
356 print
357 else:
358 Tracer.traceApi(self, api)
359
José Fonseca99221832011-03-22 22:15:46 +0000360 array_pointer_function_names = set((
361 "glVertexPointer",
362 "glNormalPointer",
363 "glColorPointer",
364 "glIndexPointer",
365 "glTexCoordPointer",
366 "glEdgeFlagPointer",
367 "glFogCoordPointer",
368 "glSecondaryColorPointer",
José Fonseca7f5163e2011-03-31 23:37:26 +0100369
José Fonsecaac5285b2011-05-04 11:09:08 +0100370 "glInterleavedArrays",
371
José Fonseca7e0bfd92011-04-30 23:09:03 +0100372 "glVertexPointerEXT",
373 "glNormalPointerEXT",
374 "glColorPointerEXT",
375 "glIndexPointerEXT",
376 "glTexCoordPointerEXT",
377 "glEdgeFlagPointerEXT",
378 "glFogCoordPointerEXT",
379 "glSecondaryColorPointerEXT",
José Fonseca99221832011-03-22 22:15:46 +0000380
José Fonseca7f5163e2011-03-31 23:37:26 +0100381 "glVertexAttribPointer",
382 "glVertexAttribPointerARB",
383 "glVertexAttribPointerNV",
José Fonsecaac5285b2011-05-04 11:09:08 +0100384 "glVertexAttribIPointer",
385 "glVertexAttribIPointerEXT",
José Fonseca7f5163e2011-03-31 23:37:26 +0100386 "glVertexAttribLPointer",
387 "glVertexAttribLPointerEXT",
José Fonseca99221832011-03-22 22:15:46 +0000388
389 #"glMatrixIndexPointerARB",
390 ))
391
392 draw_function_names = set((
393 'glDrawArrays',
394 'glDrawElements',
395 'glDrawRangeElements',
José Fonseca5c749e32011-05-09 11:11:37 +0100396 'glMultiDrawArrays',
397 'glMultiDrawElements',
398 'glDrawArraysInstanced',
José Fonsecaff8848b2011-10-09 01:04:17 +0100399 "glDrawArraysInstancedBaseInstance",
José Fonseca5c749e32011-05-09 11:11:37 +0100400 'glDrawElementsInstanced',
401 'glDrawArraysInstancedARB',
402 'glDrawElementsInstancedARB',
403 'glDrawElementsBaseVertex',
404 'glDrawRangeElementsBaseVertex',
405 'glDrawElementsInstancedBaseVertex',
José Fonsecaff8848b2011-10-09 01:04:17 +0100406 "glDrawElementsInstancedBaseInstance",
407 "glDrawElementsInstancedBaseVertexBaseInstance",
José Fonseca5c749e32011-05-09 11:11:37 +0100408 'glMultiDrawElementsBaseVertex',
409 'glDrawArraysIndirect',
410 'glDrawElementsIndirect',
411 'glDrawArraysEXT',
José Fonseca7e0bfd92011-04-30 23:09:03 +0100412 'glDrawRangeElementsEXT',
José Fonseca5c749e32011-05-09 11:11:37 +0100413 'glDrawRangeElementsEXT_size',
414 'glMultiDrawArraysEXT',
415 'glMultiDrawElementsEXT',
416 'glMultiModeDrawArraysIBM',
417 'glMultiModeDrawElementsIBM',
418 'glDrawArraysInstancedEXT',
419 'glDrawElementsInstancedEXT',
José Fonseca99221832011-03-22 22:15:46 +0000420 ))
421
José Fonsecac9f12232011-03-25 20:07:42 +0000422 interleaved_formats = [
423 'GL_V2F',
424 'GL_V3F',
425 'GL_C4UB_V2F',
426 'GL_C4UB_V3F',
427 'GL_C3F_V3F',
428 'GL_N3F_V3F',
429 'GL_C4F_N3F_V3F',
430 'GL_T2F_V3F',
431 'GL_T4F_V4F',
432 'GL_T2F_C4UB_V3F',
433 'GL_T2F_C3F_V3F',
434 'GL_T2F_N3F_V3F',
435 'GL_T2F_C4F_N3F_V3F',
436 'GL_T4F_C4F_N3F_V4F',
437 ]
438
José Fonseca54f304a2012-01-14 19:33:08 +0000439 def traceFunctionImplBody(self, function):
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000440 # Defer tracing of user array pointers...
José Fonseca99221832011-03-22 22:15:46 +0000441 if function.name in self.array_pointer_function_names:
442 print ' GLint __array_buffer = 0;'
443 print ' __glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &__array_buffer);'
444 print ' if (!__array_buffer) {'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000445 print ' gltrace::Context *ctx = gltrace::getContext();'
Chia-I Wu8ef66972011-11-03 01:19:46 +0800446 print ' ctx->user_arrays = true;'
José Fonseca5a568a92011-06-29 16:43:36 +0100447 if function.name == "glVertexAttribPointerARB":
Chia-I Wu8ef66972011-11-03 01:19:46 +0800448 print ' ctx->user_arrays_arb = true;'
José Fonseca5a568a92011-06-29 16:43:36 +0100449 if function.name == "glVertexAttribPointerNV":
Chia-I Wu8ef66972011-11-03 01:19:46 +0800450 print ' ctx->user_arrays_nv = true;'
José Fonseca54f304a2012-01-14 19:33:08 +0000451 self.invokeFunction(function)
José Fonsecaac5285b2011-05-04 11:09:08 +0100452
453 # And also break down glInterleavedArrays into the individual calls
454 if function.name == 'glInterleavedArrays':
455 print
456
457 # Initialize the enable flags
458 for camelcase_name, uppercase_name in self.arrays:
459 flag_name = '__' + uppercase_name.lower()
460 print ' GLboolean %s = GL_FALSE;' % flag_name
461 print
462
463 # Switch for the interleaved formats
464 print ' switch (format) {'
465 for format in self.interleaved_formats:
466 print ' case %s:' % format
467 for camelcase_name, uppercase_name in self.arrays:
468 flag_name = '__' + uppercase_name.lower()
469 if format.find('_' + uppercase_name[0]) >= 0:
470 print ' %s = GL_TRUE;' % flag_name
471 print ' break;'
472 print ' default:'
473 print ' return;'
474 print ' }'
475 print
476
477 # Emit fake glEnableClientState/glDisableClientState flags
478 for camelcase_name, uppercase_name in self.arrays:
479 flag_name = '__' + uppercase_name.lower()
480 enable_name = 'GL_%s_ARRAY' % uppercase_name
481
482 # Emit a fake function
483 print ' {'
José Fonsecab4a3d142011-10-27 07:43:19 +0100484 print ' static const trace::FunctionSig &__sig = %s ? __glEnableClientState_sig : __glDisableClientState_sig;' % flag_name
485 print ' unsigned __call = trace::localWriter.beginEnter(&__sig);'
486 print ' trace::localWriter.beginArg(0);'
José Fonseca54f304a2012-01-14 19:33:08 +0000487 self.serializeValue(glapi.GLenum, enable_name)
José Fonsecab4a3d142011-10-27 07:43:19 +0100488 print ' trace::localWriter.endArg();'
489 print ' trace::localWriter.endEnter();'
490 print ' trace::localWriter.beginLeave(__call);'
491 print ' trace::localWriter.endLeave();'
José Fonsecaac5285b2011-05-04 11:09:08 +0100492 print ' }'
493
José Fonseca99221832011-03-22 22:15:46 +0000494 print ' return;'
495 print ' }'
José Fonseca14c21bc2011-02-20 23:32:22 +0000496
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000497 # ... to the draw calls
José Fonseca99221832011-03-22 22:15:46 +0000498 if function.name in self.draw_function_names:
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000499 print ' if (__need_user_arrays()) {'
José Fonseca99221832011-03-22 22:15:46 +0000500 arg_names = ', '.join([arg.name for arg in function.args[1:]])
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000501 print ' GLuint maxindex = __%s_maxindex(%s);' % (function.name, arg_names)
502 print ' __trace_user_arrays(maxindex);'
503 print ' }'
José Fonseca14c21bc2011-02-20 23:32:22 +0000504
José Fonseca73373602011-05-20 17:45:26 +0100505 # Emit a fake memcpy on buffer uploads
José Fonseca9c536b02012-02-29 20:54:13 +0000506 if function.name == 'glBufferParameteriAPPLE':
507 print ' if (pname == GL_BUFFER_FLUSHING_UNMAP_APPLE && param == GL_FALSE) {'
508 print ' __checkBufferFlushingUnmapAPPLE = true;'
509 print ' }'
José Fonsecacdc322c2012-02-29 19:29:51 +0000510 if function.name in ('glUnmapBuffer', 'glUnmapBufferARB'):
José Fonseca9c536b02012-02-29 20:54:13 +0000511 if function.name.endswith('ARB'):
512 suffix = 'ARB'
513 else:
514 suffix = ''
515 print ' GLint access = 0;'
516 print ' __glGetBufferParameteriv%s(target, GL_BUFFER_ACCESS, &access);' % suffix
517 print ' if (access != GL_READ_ONLY) {'
518 print ' GLvoid *map = NULL;'
519 print ' __glGetBufferPointerv%s(target, GL_BUFFER_MAP_POINTER, &map);' % suffix
520 print ' if (map) {'
521 print ' GLint length = -1;'
522 print ' bool flush = true;'
523 print ' if (__checkBufferMapRange) {'
524 print ' __glGetBufferParameteriv%s(target, GL_BUFFER_MAP_LENGTH, &length);' % suffix
525 print ' GLint access_flags = 0;'
526 print ' __glGetBufferParameteriv(target, GL_BUFFER_ACCESS_FLAGS, &access_flags);'
527 print ' flush = flush && !(access_flags & GL_MAP_FLUSH_EXPLICIT_BIT);'
528 print ' if (length == -1) {'
529 print ' // Mesa drivers refuse GL_BUFFER_MAP_LENGTH without GL 3.0'
José Fonsecadb1ccce2012-02-29 21:09:24 +0000530 print ' static bool warned = false;'
531 print ' if (!warned) {'
532 print ' os::log("apitrace: warning: glGetBufferParameteriv%s(GL_BUFFER_MAP_LENGTH) failed\\n");' % suffix
533 print ' warned = true;'
534 print ' }'
José Fonseca9c536b02012-02-29 20:54:13 +0000535 print ' struct buffer_mapping *mapping = get_buffer_mapping(target);'
536 print ' if (mapping) {'
537 print ' length = mapping->length;'
538 print ' flush = flush && !mapping->explicit_flush;'
539 print ' } else {'
540 print ' length = 0;'
541 print ' flush = false;'
542 print ' }'
543 print ' }'
544 print ' } else {'
545 print ' length = 0;'
546 print ' __glGetBufferParameteriv%s(target, GL_BUFFER_SIZE, &length);' % suffix
547 print ' }'
548 print ' if (__checkBufferFlushingUnmapAPPLE) {'
549 print ' GLint flushing_unmap = GL_TRUE;'
550 print ' __glGetBufferParameteriv%s(target, GL_BUFFER_FLUSHING_UNMAP_APPLE, &flushing_unmap);' % suffix
551 print ' flush = flush && flushing_unmap;'
552 print ' }'
553 print ' if (flush && length > 0) {'
554 self.emit_memcpy('map', 'map', 'length')
555 print ' }'
556 print ' }'
557 print ' }'
José Fonsecacdc322c2012-02-29 19:29:51 +0000558 if function.name == 'glUnmapBufferOES':
559 print ' GLint access = 0;'
560 print ' __glGetBufferParameteriv(target, GL_BUFFER_ACCESS_OES, &access);'
561 print ' if (access == GL_WRITE_ONLY_OES) {'
562 print ' GLvoid *map = NULL;'
563 print ' __glGetBufferPointervOES(target, GL_BUFFER_MAP_POINTER_OES, &map);'
564 print ' GLint size = 0;'
565 print ' __glGetBufferParameteriv(target, GL_BUFFER_SIZE, &size);'
566 print ' if (map && size > 0) {'
567 self.emit_memcpy('map', 'map', 'size')
568 print ' }'
José Fonseca867b1b72011-04-24 11:58:04 +0100569 print ' }'
José Fonsecafb3bd602012-01-15 13:56:28 +0000570 if function.name == 'glUnmapNamedBufferEXT':
José Fonseca024aff42012-02-29 18:00:06 +0000571 print ' GLint access_flags = 0;'
572 print ' __glGetNamedBufferParameterivEXT(buffer, GL_BUFFER_ACCESS_FLAGS, &access_flags);'
573 print ' if ((access_flags & GL_MAP_WRITE_BIT) && !(access_flags & GL_MAP_FLUSH_EXPLICIT_BIT)) {'
José Fonsecafb3bd602012-01-15 13:56:28 +0000574 print ' GLvoid *map = NULL;'
José Fonseca024aff42012-02-29 18:00:06 +0000575 print ' __glGetNamedBufferPointervEXT(buffer, GL_BUFFER_MAP_POINTER, &map);'
José Fonsecafb3bd602012-01-15 13:56:28 +0000576 print ' GLint length = 0;'
José Fonseca024aff42012-02-29 18:00:06 +0000577 print ' __glGetNamedBufferParameterivEXT(buffer, GL_BUFFER_MAP_LENGTH, &length);'
578 print ' if (map && length > 0) {'
José Fonsecafb3bd602012-01-15 13:56:28 +0000579 self.emit_memcpy('map', 'map', 'length')
José Fonseca024aff42012-02-29 18:00:06 +0000580 print ' }'
José Fonsecafb3bd602012-01-15 13:56:28 +0000581 print ' }'
José Fonseca77ef0ce2012-02-29 18:08:48 +0000582 if function.name == 'glFlushMappedBufferRange':
583 print ' GLvoid *map = NULL;'
584 print ' __glGetBufferPointerv(target, GL_BUFFER_MAP_POINTER, &map);'
585 print ' if (map && length > 0) {'
586 self.emit_memcpy('(char *)map + offset', '(const char *)map + offset', 'length')
587 print ' }'
588 if function.name == 'glFlushMappedBufferRangeAPPLE':
589 print ' GLvoid *map = NULL;'
590 print ' __glGetBufferPointerv(target, GL_BUFFER_MAP_POINTER, &map);'
591 print ' if (map && size > 0) {'
592 self.emit_memcpy('(char *)map + offset', '(const char *)map + offset', 'size')
José Fonseca73373602011-05-20 17:45:26 +0100593 print ' }'
José Fonsecafb3bd602012-01-15 13:56:28 +0000594 if function.name == 'glFlushMappedNamedBufferRangeEXT':
595 print ' GLvoid *map = NULL;'
José Fonseca024aff42012-02-29 18:00:06 +0000596 print ' __glGetNamedBufferPointervEXT(buffer, GL_BUFFER_MAP_POINTER, &map);'
597 print ' if (map && length > 0) {'
José Fonsecafb3bd602012-01-15 13:56:28 +0000598 self.emit_memcpy('(char *)map + offset', '(const char *)map + offset', 'length')
599 print ' }'
José Fonseca867b1b72011-04-24 11:58:04 +0100600
José Fonseca91492d22011-05-23 21:20:31 +0100601 # Don't leave vertex attrib locations to chance. Instead emit fake
602 # glBindAttribLocation calls to ensure that the same locations will be
603 # used when retracing. Trying to remap locations after the fact would
604 # be an herculian task given that vertex attrib locations appear in
605 # many entry-points, including non-shader related ones.
606 if function.name == 'glLinkProgram':
José Fonseca54f304a2012-01-14 19:33:08 +0000607 Tracer.invokeFunction(self, function)
José Fonseca91492d22011-05-23 21:20:31 +0100608 print ' GLint active_attributes = 0;'
609 print ' __glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &active_attributes);'
José Fonseca7525e6f2011-09-28 09:04:56 +0100610 print ' for (GLint attrib = 0; attrib < active_attributes; ++attrib) {'
José Fonseca91492d22011-05-23 21:20:31 +0100611 print ' GLint size = 0;'
612 print ' GLenum type = 0;'
613 print ' GLchar name[256];'
614 # TODO: Use ACTIVE_ATTRIBUTE_MAX_LENGTH instead of 256
615 print ' __glGetActiveAttrib(program, attrib, sizeof name, NULL, &size, &type, name);'
José Fonseca2a794f52011-05-26 20:54:29 +0100616 print " if (name[0] != 'g' || name[1] != 'l' || name[2] != '_') {"
617 print ' GLint location = __glGetAttribLocation(program, name);'
618 print ' if (location >= 0) {'
José Fonseca1b6c8752012-04-15 14:33:00 +0100619 bind_function = glapi.glapi.getFunctionByName('glBindAttribLocation')
José Fonseca91492d22011-05-23 21:20:31 +0100620 self.fake_call(bind_function, ['program', 'location', 'name'])
José Fonseca2a794f52011-05-26 20:54:29 +0100621 print ' }'
José Fonseca91492d22011-05-23 21:20:31 +0100622 print ' }'
623 print ' }'
624 if function.name == 'glLinkProgramARB':
José Fonseca54f304a2012-01-14 19:33:08 +0000625 Tracer.invokeFunction(self, function)
José Fonseca91492d22011-05-23 21:20:31 +0100626 print ' GLint active_attributes = 0;'
627 print ' __glGetObjectParameterivARB(programObj, GL_OBJECT_ACTIVE_ATTRIBUTES_ARB, &active_attributes);'
José Fonseca7525e6f2011-09-28 09:04:56 +0100628 print ' for (GLint attrib = 0; attrib < active_attributes; ++attrib) {'
José Fonseca91492d22011-05-23 21:20:31 +0100629 print ' GLint size = 0;'
630 print ' GLenum type = 0;'
631 print ' GLcharARB name[256];'
632 # TODO: Use ACTIVE_ATTRIBUTE_MAX_LENGTH instead of 256
633 print ' __glGetActiveAttribARB(programObj, attrib, sizeof name, NULL, &size, &type, name);'
José Fonseca2a794f52011-05-26 20:54:29 +0100634 print " if (name[0] != 'g' || name[1] != 'l' || name[2] != '_') {"
635 print ' GLint location = __glGetAttribLocationARB(programObj, name);'
636 print ' if (location >= 0) {'
José Fonseca1b6c8752012-04-15 14:33:00 +0100637 bind_function = glapi.glapi.getFunctionByName('glBindAttribLocationARB')
José Fonseca91492d22011-05-23 21:20:31 +0100638 self.fake_call(bind_function, ['programObj', 'location', 'name'])
José Fonseca2a794f52011-05-26 20:54:29 +0100639 print ' }'
José Fonseca91492d22011-05-23 21:20:31 +0100640 print ' }'
641 print ' }'
642
José Fonseca54f304a2012-01-14 19:33:08 +0000643 Tracer.traceFunctionImplBody(self, function)
José Fonseca73373602011-05-20 17:45:26 +0100644
José Fonsecaf028a8f2012-02-15 23:33:35 +0000645 marker_functions = [
646 # GL_GREMEDY_string_marker
José Fonseca8f34d342011-07-15 20:16:40 +0100647 'glStringMarkerGREMEDY',
José Fonsecaf028a8f2012-02-15 23:33:35 +0000648 # GL_GREMEDY_frame_terminator
José Fonseca8f34d342011-07-15 20:16:40 +0100649 'glFrameTerminatorGREMEDY',
José Fonsecaf028a8f2012-02-15 23:33:35 +0000650 # GL_EXT_debug_marker
651 'glInsertEventMarkerEXT',
652 'glPushGroupMarkerEXT',
653 'glPopGroupMarkerEXT',
José Fonseca8f34d342011-07-15 20:16:40 +0100654 ]
655
José Fonseca54f304a2012-01-14 19:33:08 +0000656 def invokeFunction(self, function):
José Fonseca91492d22011-05-23 21:20:31 +0100657 if function.name in ('glLinkProgram', 'glLinkProgramARB'):
658 # These functions have been dispatched already
659 return
660
José Fonsecaf028a8f2012-02-15 23:33:35 +0000661 # We implement GL_EXT_debug_marker, GL_GREMEDY_*, etc., and not the
662 # driver
663 if function.name in self.marker_functions:
José Fonseca8f34d342011-07-15 20:16:40 +0100664 return
665
666 if function.name in ('glXGetProcAddress', 'glXGetProcAddressARB', 'wglGetProcAddress'):
José Fonsecaf028a8f2012-02-15 23:33:35 +0000667 else_ = ''
668 for marker_function in self.marker_functions:
José Fonseca1b6c8752012-04-15 14:33:00 +0100669 if self.api.getFunctionByName(marker_function):
José Fonsecaf028a8f2012-02-15 23:33:35 +0000670 print ' %sif (strcmp("%s", (const char *)%s) == 0) {' % (else_, marker_function, function.args[0].name)
671 print ' __result = (%s)&%s;' % (function.type, marker_function)
672 print ' }'
673 else_ = 'else '
674 print ' %s{' % else_
José Fonseca54f304a2012-01-14 19:33:08 +0000675 Tracer.invokeFunction(self, function)
José Fonseca8f34d342011-07-15 20:16:40 +0100676 print ' }'
José Fonseca1b3d3752011-07-15 10:15:19 +0100677 return
678
José Fonsecaa08d2752011-08-25 13:26:43 +0100679 # Override GL extensions
680 if function.name in ('glGetString', 'glGetIntegerv', 'glGetStringi'):
José Fonseca54f304a2012-01-14 19:33:08 +0000681 Tracer.invokeFunction(self, function, prefix = 'gltrace::__', suffix = '_override')
José Fonsecaa08d2752011-08-25 13:26:43 +0100682 return
683
José Fonseca54f304a2012-01-14 19:33:08 +0000684 Tracer.invokeFunction(self, function)
José Fonseca91492d22011-05-23 21:20:31 +0100685
José Fonseca867b1b72011-04-24 11:58:04 +0100686 buffer_targets = [
687 'ARRAY_BUFFER',
688 'ELEMENT_ARRAY_BUFFER',
689 'PIXEL_PACK_BUFFER',
690 'PIXEL_UNPACK_BUFFER',
José Fonseca7b20d672012-01-10 19:13:58 +0000691 'UNIFORM_BUFFER',
692 'TEXTURE_BUFFER',
693 'TRANSFORM_FEEDBACK_BUFFER',
694 'COPY_READ_BUFFER',
695 'COPY_WRITE_BUFFER',
696 'DRAW_INDIRECT_BUFFER',
697 'ATOMIC_COUNTER_BUFFER',
José Fonseca867b1b72011-04-24 11:58:04 +0100698 ]
699
José Fonseca54f304a2012-01-14 19:33:08 +0000700 def wrapRet(self, function, instance):
701 Tracer.wrapRet(self, function, instance)
José Fonseca1b3d3752011-07-15 10:15:19 +0100702
José Fonseca1b6c8752012-04-15 14:33:00 +0100703 # Replace function addresses with ours
704 if function.name in self.getProcAddressFunctionNames:
705 print ' %s = _wrapProcAddress(%s, %s);' % (instance, function.args[0].name, instance)
706
José Fonsecacdc322c2012-02-29 19:29:51 +0000707 # Keep track of buffer mappings
708 if function.name in ('glMapBuffer', 'glMapBufferARB'):
José Fonseca867b1b72011-04-24 11:58:04 +0100709 print ' struct buffer_mapping *mapping = get_buffer_mapping(target);'
710 print ' if (mapping) {'
711 print ' mapping->map = %s;' % (instance)
712 print ' mapping->length = 0;'
713 print ' __glGetBufferParameteriv(target, GL_BUFFER_SIZE, &mapping->length);'
714 print ' mapping->write = (access != GL_READ_ONLY);'
José Fonseca73373602011-05-20 17:45:26 +0100715 print ' mapping->explicit_flush = false;'
José Fonseca867b1b72011-04-24 11:58:04 +0100716 print ' }'
José Fonseca867b1b72011-04-24 11:58:04 +0100717 if function.name == 'glMapBufferRange':
José Fonseca9c536b02012-02-29 20:54:13 +0000718 print ' if (access & GL_MAP_WRITE_BIT) {'
719 print ' __checkBufferMapRange = true;'
720 print ' }'
José Fonseca867b1b72011-04-24 11:58:04 +0100721 print ' struct buffer_mapping *mapping = get_buffer_mapping(target);'
722 print ' if (mapping) {'
723 print ' mapping->map = %s;' % (instance)
724 print ' mapping->length = length;'
725 print ' mapping->write = access & GL_MAP_WRITE_BIT;'
José Fonseca73373602011-05-20 17:45:26 +0100726 print ' mapping->explicit_flush = access & GL_MAP_FLUSH_EXPLICIT_BIT;'
José Fonseca867b1b72011-04-24 11:58:04 +0100727 print ' }'
José Fonseca669b1222011-02-20 09:05:10 +0000728
José Fonsecac9f12232011-03-25 20:07:42 +0000729 boolean_names = [
730 'GL_FALSE',
731 'GL_TRUE',
732 ]
733
734 def gl_boolean(self, value):
735 return self.boolean_names[int(bool(value))]
736
José Fonsecac29f4f12011-06-11 12:19:05 +0100737 # Names of the functions that unpack from a pixel buffer object. See the
738 # ARB_pixel_buffer_object specification.
José Fonsecae97bab92011-06-02 23:15:11 +0100739 unpack_function_names = set([
740 'glBitmap',
José Fonsecac29f4f12011-06-11 12:19:05 +0100741 'glColorSubTable',
742 'glColorTable',
743 'glCompressedTexImage1D',
744 'glCompressedTexImage2D',
745 'glCompressedTexImage3D',
746 'glCompressedTexSubImage1D',
747 'glCompressedTexSubImage2D',
748 'glCompressedTexSubImage3D',
749 'glConvolutionFilter1D',
750 'glConvolutionFilter2D',
José Fonsecae97bab92011-06-02 23:15:11 +0100751 'glDrawPixels',
752 'glMultiTexImage1DEXT',
753 'glMultiTexImage2DEXT',
754 'glMultiTexImage3DEXT',
755 'glMultiTexSubImage1DEXT',
756 'glMultiTexSubImage2DEXT',
757 'glMultiTexSubImage3DEXT',
José Fonsecac29f4f12011-06-11 12:19:05 +0100758 'glPixelMapfv',
759 'glPixelMapuiv',
760 'glPixelMapusv',
José Fonsecae97bab92011-06-02 23:15:11 +0100761 'glPolygonStipple',
José Fonsecac29f4f12011-06-11 12:19:05 +0100762 'glSeparableFilter2D',
José Fonsecae97bab92011-06-02 23:15:11 +0100763 'glTexImage1D',
764 'glTexImage1DEXT',
765 'glTexImage2D',
766 'glTexImage2DEXT',
767 'glTexImage3D',
768 'glTexImage3DEXT',
769 'glTexSubImage1D',
770 'glTexSubImage1DEXT',
771 'glTexSubImage2D',
772 'glTexSubImage2DEXT',
773 'glTexSubImage3D',
774 'glTexSubImage3DEXT',
775 'glTextureImage1DEXT',
776 'glTextureImage2DEXT',
777 'glTextureImage3DEXT',
778 'glTextureSubImage1DEXT',
779 'glTextureSubImage2DEXT',
780 'glTextureSubImage3DEXT',
781 ])
782
José Fonseca54f304a2012-01-14 19:33:08 +0000783 def serializeArgValue(self, function, arg):
José Fonseca99221832011-03-22 22:15:46 +0000784 if function.name in self.draw_function_names and arg.name == 'indices':
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000785 print ' GLint __element_array_buffer = 0;'
786 print ' __glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &__element_array_buffer);'
787 print ' if (!__element_array_buffer) {'
José Fonseca5c749e32011-05-09 11:11:37 +0100788 if isinstance(arg.type, stdapi.Array):
José Fonsecab4a3d142011-10-27 07:43:19 +0100789 print ' trace::localWriter.beginArray(%s);' % arg.type.length
José Fonseca5c749e32011-05-09 11:11:37 +0100790 print ' for(GLsizei i = 0; i < %s; ++i) {' % arg.type.length
José Fonsecab4a3d142011-10-27 07:43:19 +0100791 print ' trace::localWriter.beginElement();'
792 print ' trace::localWriter.writeBlob(%s[i], count[i]*__gl_type_size(type));' % (arg.name)
793 print ' trace::localWriter.endElement();'
José Fonseca5c749e32011-05-09 11:11:37 +0100794 print ' }'
José Fonsecab4a3d142011-10-27 07:43:19 +0100795 print ' trace::localWriter.endArray();'
José Fonseca5c749e32011-05-09 11:11:37 +0100796 else:
José Fonsecab4a3d142011-10-27 07:43:19 +0100797 print ' trace::localWriter.writeBlob(%s, count*__gl_type_size(type));' % (arg.name)
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000798 print ' } else {'
José Fonseca54f304a2012-01-14 19:33:08 +0000799 Tracer.serializeArgValue(self, function, arg)
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000800 print ' }'
801 return
802
José Fonsecae97bab92011-06-02 23:15:11 +0100803 # Recognize offsets instead of blobs when a PBO is bound
804 if function.name in self.unpack_function_names \
805 and (isinstance(arg.type, stdapi.Blob) \
806 or (isinstance(arg.type, stdapi.Const) \
807 and isinstance(arg.type.type, stdapi.Blob))):
José Fonsecac29f4f12011-06-11 12:19:05 +0100808 print ' {'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000809 print ' gltrace::Context *ctx = gltrace::getContext();'
José Fonsecac29f4f12011-06-11 12:19:05 +0100810 print ' GLint __unpack_buffer = 0;'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000811 print ' if (ctx->profile == gltrace::PROFILE_COMPAT)'
Chia-I Wub3d218d2011-11-03 01:37:36 +0800812 print ' __glGetIntegerv(GL_PIXEL_UNPACK_BUFFER_BINDING, &__unpack_buffer);'
José Fonsecac29f4f12011-06-11 12:19:05 +0100813 print ' if (__unpack_buffer) {'
José Fonsecab4a3d142011-10-27 07:43:19 +0100814 print ' trace::localWriter.writeOpaque(%s);' % arg.name
José Fonsecac29f4f12011-06-11 12:19:05 +0100815 print ' } else {'
José Fonseca54f304a2012-01-14 19:33:08 +0000816 Tracer.serializeArgValue(self, function, arg)
José Fonsecac29f4f12011-06-11 12:19:05 +0100817 print ' }'
José Fonsecae97bab92011-06-02 23:15:11 +0100818 print ' }'
819 return
820
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100821 # Several GL state functions take GLenum symbolic names as
822 # integer/floats; so dump the symbolic name whenever possible
José Fonseca3bcb33c2011-05-27 20:14:31 +0100823 if function.name.startswith('gl') \
José Fonsecae3571092011-10-13 08:26:27 +0100824 and arg.type in (glapi.GLint, glapi.GLfloat, glapi.GLdouble) \
José Fonseca3bcb33c2011-05-27 20:14:31 +0100825 and arg.name == 'param':
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100826 assert arg.index > 0
827 assert function.args[arg.index - 1].name == 'pname'
828 assert function.args[arg.index - 1].type == glapi.GLenum
829 print ' if (is_symbolic_pname(pname) && is_symbolic_param(%s)) {' % arg.name
José Fonseca54f304a2012-01-14 19:33:08 +0000830 self.serializeValue(glapi.GLenum, arg.name)
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100831 print ' } else {'
José Fonseca54f304a2012-01-14 19:33:08 +0000832 Tracer.serializeArgValue(self, function, arg)
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100833 print ' }'
834 return
835
José Fonseca54f304a2012-01-14 19:33:08 +0000836 Tracer.serializeArgValue(self, function, arg)
José Fonseca99221832011-03-22 22:15:46 +0000837
José Fonseca4c938c22011-04-30 22:44:38 +0100838 def footer(self, api):
839 Tracer.footer(self, api)
José Fonseca669b1222011-02-20 09:05:10 +0000840
José Fonseca4c938c22011-04-30 22:44:38 +0100841 # A simple state tracker to track the pointer values
José Fonseca669b1222011-02-20 09:05:10 +0000842 # update the state
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000843 print 'static void __trace_user_arrays(GLuint maxindex)'
José Fonseca669b1222011-02-20 09:05:10 +0000844 print '{'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000845 print ' gltrace::Context *ctx = gltrace::getContext();'
José Fonseca1a2fdd22011-04-01 00:55:09 +0100846
José Fonseca99221832011-03-22 22:15:46 +0000847 for camelcase_name, uppercase_name in self.arrays:
Chia-I Wub3d218d2011-11-03 01:37:36 +0800848 # in which profile is the array available?
José Fonsecaf028a8f2012-02-15 23:33:35 +0000849 profile_check = 'ctx->profile == gltrace::PROFILE_COMPAT'
Chia-I Wub3d218d2011-11-03 01:37:36 +0800850 if camelcase_name in self.arrays_es1:
José Fonsecaf028a8f2012-02-15 23:33:35 +0000851 profile_check = '(' + profile_check + ' || ctx->profile == gltrace::PROFILE_ES1)';
Chia-I Wub3d218d2011-11-03 01:37:36 +0800852
José Fonseca99221832011-03-22 22:15:46 +0000853 function_name = 'gl%sPointer' % camelcase_name
854 enable_name = 'GL_%s_ARRAY' % uppercase_name
855 binding_name = 'GL_%s_ARRAY_BUFFER_BINDING' % uppercase_name
José Fonseca1b6c8752012-04-15 14:33:00 +0100856 function = api.getFunctionByName(function_name)
José Fonseca99221832011-03-22 22:15:46 +0000857
José Fonseca06e85192011-10-16 14:15:36 +0100858 print ' // %s' % function.prototype()
Chia-I Wub3d218d2011-11-03 01:37:36 +0800859 print ' if (%s) {' % profile_check
José Fonsecafb6744f2011-04-15 11:18:37 +0100860 self.array_trace_prolog(api, uppercase_name)
861 self.array_prolog(api, uppercase_name)
862 print ' if (__glIsEnabled(%s)) {' % enable_name
José Fonseca7f5163e2011-03-31 23:37:26 +0100863 print ' GLint __binding = 0;'
864 print ' __glGetIntegerv(%s, &__binding);' % binding_name
865 print ' if (!__binding) {'
José Fonseca99221832011-03-22 22:15:46 +0000866
867 # Get the arguments via glGet*
868 for arg in function.args:
869 arg_get_enum = 'GL_%s_ARRAY_%s' % (uppercase_name, arg.name.upper())
870 arg_get_function, arg_type = TypeGetter().visit(arg.type)
José Fonseca7f5163e2011-03-31 23:37:26 +0100871 print ' %s %s = 0;' % (arg_type, arg.name)
872 print ' __%s(%s, &%s);' % (arg_get_function, arg_get_enum, arg.name)
José Fonseca99221832011-03-22 22:15:46 +0000873
874 arg_names = ', '.join([arg.name for arg in function.args[:-1]])
José Fonseca7f5163e2011-03-31 23:37:26 +0100875 print ' size_t __size = __%s_size(%s, maxindex);' % (function.name, arg_names)
José Fonseca99221832011-03-22 22:15:46 +0000876
877 # Emit a fake function
José Fonsecafb6744f2011-04-15 11:18:37 +0100878 self.array_trace_intermezzo(api, uppercase_name)
José Fonsecab4a3d142011-10-27 07:43:19 +0100879 print ' unsigned __call = trace::localWriter.beginEnter(&__%s_sig);' % (function.name,)
José Fonseca669b1222011-02-20 09:05:10 +0000880 for arg in function.args:
881 assert not arg.output
José Fonsecab4a3d142011-10-27 07:43:19 +0100882 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
José Fonseca14c21bc2011-02-20 23:32:22 +0000883 if arg.name != 'pointer':
José Fonseca54f304a2012-01-14 19:33:08 +0000884 self.serializeValue(arg.type, arg.name)
José Fonseca14c21bc2011-02-20 23:32:22 +0000885 else:
José Fonsecab4a3d142011-10-27 07:43:19 +0100886 print ' trace::localWriter.writeBlob((const void *)%s, __size);' % (arg.name)
887 print ' trace::localWriter.endArg();'
José Fonseca99221832011-03-22 22:15:46 +0000888
José Fonsecab4a3d142011-10-27 07:43:19 +0100889 print ' trace::localWriter.endEnter();'
890 print ' trace::localWriter.beginLeave(__call);'
891 print ' trace::localWriter.endLeave();'
José Fonseca99221832011-03-22 22:15:46 +0000892 print ' }'
José Fonseca669b1222011-02-20 09:05:10 +0000893 print ' }'
José Fonsecafb6744f2011-04-15 11:18:37 +0100894 self.array_epilog(api, uppercase_name)
895 self.array_trace_epilog(api, uppercase_name)
Chia-I Wub3d218d2011-11-03 01:37:36 +0800896 print ' }'
José Fonseca99221832011-03-22 22:15:46 +0000897 print
José Fonseca1a2fdd22011-04-01 00:55:09 +0100898
José Fonseca1601c412011-05-10 10:38:19 +0100899 # Samething, but for glVertexAttribPointer*
900 #
901 # Some variants of glVertexAttribPointer alias conventional and generic attributes:
902 # - glVertexAttribPointer: no
903 # - glVertexAttribPointerARB: implementation dependent
904 # - glVertexAttribPointerNV: yes
905 #
906 # This means that the implementations of these functions do not always
907 # alias, and they need to be considered independently.
908 #
Chia-I Wub3d218d2011-11-03 01:37:36 +0800909 print ' // ES1 does not support generic vertex attributes'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000910 print ' if (ctx->profile == gltrace::PROFILE_ES1)'
Chia-I Wub3d218d2011-11-03 01:37:36 +0800911 print ' return;'
912 print
José Fonseca5a568a92011-06-29 16:43:36 +0100913 print ' vertex_attrib __vertex_attrib = __get_vertex_attrib();'
914 print
915 for suffix in ['', 'ARB', 'NV']:
916 if suffix:
José Fonsecad94aaac2011-06-28 20:50:49 +0100917 SUFFIX = '_' + suffix
José Fonsecad94aaac2011-06-28 20:50:49 +0100918 else:
José Fonseca5a568a92011-06-29 16:43:36 +0100919 SUFFIX = suffix
José Fonseca1601c412011-05-10 10:38:19 +0100920 function_name = 'glVertexAttribPointer' + suffix
José Fonseca1b6c8752012-04-15 14:33:00 +0100921 function = api.getFunctionByName(function_name)
José Fonseca06e85192011-10-16 14:15:36 +0100922
923 print ' // %s' % function.prototype()
José Fonseca5a568a92011-06-29 16:43:36 +0100924 print ' if (__vertex_attrib == VERTEX_ATTRIB%s) {' % SUFFIX
925 if suffix == 'NV':
926 print ' GLint __max_vertex_attribs = 16;'
927 else:
928 print ' GLint __max_vertex_attribs = 0;'
929 print ' __glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &__max_vertex_attribs);'
930 print ' for (GLint index = 0; index < __max_vertex_attribs; ++index) {'
931 print ' GLint __enabled = 0;'
932 if suffix == 'NV':
933 print ' __glGetIntegerv(GL_VERTEX_ATTRIB_ARRAY0_NV + index, &__enabled);'
934 else:
935 print ' __glGetVertexAttribiv%s(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED%s, &__enabled);' % (suffix, SUFFIX)
936 print ' if (__enabled) {'
937 print ' GLint __binding = 0;'
938 if suffix != 'NV':
939 # It doesn't seem possible to use VBOs with NV_vertex_program.
940 print ' __glGetVertexAttribiv%s(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING%s, &__binding);' % (suffix, SUFFIX)
941 print ' if (!__binding) {'
José Fonseca1a2fdd22011-04-01 00:55:09 +0100942
José Fonseca1601c412011-05-10 10:38:19 +0100943 # Get the arguments via glGet*
944 for arg in function.args[1:]:
José Fonseca5a568a92011-06-29 16:43:36 +0100945 if suffix == 'NV':
946 arg_get_enum = 'GL_ATTRIB_ARRAY_%s%s' % (arg.name.upper(), SUFFIX)
947 else:
948 arg_get_enum = 'GL_VERTEX_ATTRIB_ARRAY_%s%s' % (arg.name.upper(), SUFFIX)
José Fonsecac493e3e2011-06-29 12:57:06 +0100949 arg_get_function, arg_type = TypeGetter('glGetVertexAttrib', False, suffix).visit(arg.type)
José Fonseca5a568a92011-06-29 16:43:36 +0100950 print ' %s %s = 0;' % (arg_type, arg.name)
951 print ' __%s(index, %s, &%s);' % (arg_get_function, arg_get_enum, arg.name)
José Fonseca1601c412011-05-10 10:38:19 +0100952
953 arg_names = ', '.join([arg.name for arg in function.args[1:-1]])
José Fonseca5a568a92011-06-29 16:43:36 +0100954 print ' size_t __size = __%s_size(%s, maxindex);' % (function.name, arg_names)
José Fonseca1a2fdd22011-04-01 00:55:09 +0100955
José Fonseca1601c412011-05-10 10:38:19 +0100956 # Emit a fake function
José Fonsecab4a3d142011-10-27 07:43:19 +0100957 print ' unsigned __call = trace::localWriter.beginEnter(&__%s_sig);' % (function.name,)
José Fonseca1601c412011-05-10 10:38:19 +0100958 for arg in function.args:
959 assert not arg.output
José Fonsecab4a3d142011-10-27 07:43:19 +0100960 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
José Fonseca1601c412011-05-10 10:38:19 +0100961 if arg.name != 'pointer':
José Fonseca54f304a2012-01-14 19:33:08 +0000962 self.serializeValue(arg.type, arg.name)
José Fonseca1601c412011-05-10 10:38:19 +0100963 else:
José Fonsecab4a3d142011-10-27 07:43:19 +0100964 print ' trace::localWriter.writeBlob((const void *)%s, __size);' % (arg.name)
965 print ' trace::localWriter.endArg();'
José Fonseca1601c412011-05-10 10:38:19 +0100966
José Fonsecab4a3d142011-10-27 07:43:19 +0100967 print ' trace::localWriter.endEnter();'
968 print ' trace::localWriter.beginLeave(__call);'
969 print ' trace::localWriter.endLeave();'
José Fonseca1601c412011-05-10 10:38:19 +0100970 print ' }'
971 print ' }'
972 print ' }'
973 print ' }'
974 print
José Fonseca1a2fdd22011-04-01 00:55:09 +0100975
José Fonseca669b1222011-02-20 09:05:10 +0000976 print '}'
977 print
978
José Fonsecafb6744f2011-04-15 11:18:37 +0100979 #
980 # Hooks for glTexCoordPointer, which is identical to the other array
981 # pointers except the fact that it is indexed by glClientActiveTexture.
982 #
983
984 def array_prolog(self, api, uppercase_name):
985 if uppercase_name == 'TEXTURE_COORD':
986 print ' GLint client_active_texture = 0;'
987 print ' __glGetIntegerv(GL_CLIENT_ACTIVE_TEXTURE, &client_active_texture);'
988 print ' GLint max_texture_coords = 0;'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000989 print ' if (ctx->profile == gltrace::PROFILE_COMPAT)'
Chia-I Wub3d218d2011-11-03 01:37:36 +0800990 print ' __glGetIntegerv(GL_MAX_TEXTURE_COORDS, &max_texture_coords);'
991 print ' else'
992 print ' __glGetIntegerv(GL_MAX_TEXTURE_UNITS, &max_texture_coords);'
José Fonsecafb6744f2011-04-15 11:18:37 +0100993 print ' for (GLint unit = 0; unit < max_texture_coords; ++unit) {'
José Fonseca7525e6f2011-09-28 09:04:56 +0100994 print ' GLint texture = GL_TEXTURE0 + unit;'
José Fonsecafb6744f2011-04-15 11:18:37 +0100995 print ' __glClientActiveTexture(texture);'
996
997 def array_trace_prolog(self, api, uppercase_name):
998 if uppercase_name == 'TEXTURE_COORD':
999 print ' bool client_active_texture_dirty = false;'
1000
1001 def array_epilog(self, api, uppercase_name):
1002 if uppercase_name == 'TEXTURE_COORD':
1003 print ' }'
1004 self.array_cleanup(api, uppercase_name)
1005
1006 def array_cleanup(self, api, uppercase_name):
1007 if uppercase_name == 'TEXTURE_COORD':
1008 print ' __glClientActiveTexture(client_active_texture);'
1009
1010 def array_trace_intermezzo(self, api, uppercase_name):
1011 if uppercase_name == 'TEXTURE_COORD':
1012 print ' if (texture != client_active_texture || client_active_texture_dirty) {'
1013 print ' client_active_texture_dirty = true;'
1014 self.fake_glClientActiveTexture_call(api, "texture");
1015 print ' }'
1016
1017 def array_trace_epilog(self, api, uppercase_name):
1018 if uppercase_name == 'TEXTURE_COORD':
1019 print ' if (client_active_texture_dirty) {'
1020 self.fake_glClientActiveTexture_call(api, "client_active_texture");
1021 print ' }'
1022
1023 def fake_glClientActiveTexture_call(self, api, texture):
José Fonseca1b6c8752012-04-15 14:33:00 +01001024 function = api.getFunctionByName('glClientActiveTexture')
José Fonsecafb6744f2011-04-15 11:18:37 +01001025 self.fake_call(function, [texture])
1026
1027 def fake_call(self, function, args):
José Fonsecab4a3d142011-10-27 07:43:19 +01001028 print ' unsigned __fake_call = trace::localWriter.beginEnter(&__%s_sig);' % (function.name,)
José Fonsecafb6744f2011-04-15 11:18:37 +01001029 for arg, instance in zip(function.args, args):
1030 assert not arg.output
José Fonsecab4a3d142011-10-27 07:43:19 +01001031 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
José Fonseca54f304a2012-01-14 19:33:08 +00001032 self.serializeValue(arg.type, instance)
José Fonsecab4a3d142011-10-27 07:43:19 +01001033 print ' trace::localWriter.endArg();'
1034 print ' trace::localWriter.endEnter();'
1035 print ' trace::localWriter.beginLeave(__fake_call);'
1036 print ' trace::localWriter.endLeave();'
José Fonsecafb6744f2011-04-15 11:18:37 +01001037
1038
1039
1040
1041
José Fonseca669b1222011-02-20 09:05:10 +00001042
1043
1044
1045
1046
1047