blob: 21684f7cbf5f5342bf97e0a6ae5198ca2140bcd9 [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é Fonsecac5bf77a2014-08-14 16:10:02 +010030import re
31import sys
32
José Fonseca452d3252012-04-14 15:55:40 +010033from trace import Tracer
José Fonseca1b6c8752012-04-15 14:33:00 +010034from dispatch import function_pointer_type, function_pointer_value
José Fonsecabd86a222011-09-27 09:21:38 +010035import specs.stdapi as stdapi
36import specs.glapi as glapi
37import specs.glparams as glparams
38from specs.glxapi import glxapi
José Fonseca669b1222011-02-20 09:05:10 +000039
40
José Fonseca99221832011-03-22 22:15:46 +000041class TypeGetter(stdapi.Visitor):
42 '''Determine which glGet*v function that matches the specified type.'''
43
José Fonsecac493e3e2011-06-29 12:57:06 +010044 def __init__(self, prefix = 'glGet', long_suffix = True, ext_suffix = ''):
José Fonseca1a2fdd22011-04-01 00:55:09 +010045 self.prefix = prefix
46 self.long_suffix = long_suffix
José Fonsecac493e3e2011-06-29 12:57:06 +010047 self.ext_suffix = ext_suffix
José Fonseca1a2fdd22011-04-01 00:55:09 +010048
José Fonseca54f304a2012-01-14 19:33:08 +000049 def visitConst(self, const):
José Fonseca99221832011-03-22 22:15:46 +000050 return self.visit(const.type)
51
José Fonseca54f304a2012-01-14 19:33:08 +000052 def visitAlias(self, alias):
José Fonseca99221832011-03-22 22:15:46 +000053 if alias.expr == 'GLboolean':
José Fonseca1a2fdd22011-04-01 00:55:09 +010054 if self.long_suffix:
José Fonsecac493e3e2011-06-29 12:57:06 +010055 suffix = 'Booleanv'
56 arg_type = alias.expr
José Fonseca1a2fdd22011-04-01 00:55:09 +010057 else:
José Fonsecac493e3e2011-06-29 12:57:06 +010058 suffix = 'iv'
59 arg_type = 'GLint'
José Fonseca99221832011-03-22 22:15:46 +000060 elif alias.expr == 'GLdouble':
José Fonseca1a2fdd22011-04-01 00:55:09 +010061 if self.long_suffix:
José Fonsecac493e3e2011-06-29 12:57:06 +010062 suffix = 'Doublev'
63 arg_type = alias.expr
José Fonseca1a2fdd22011-04-01 00:55:09 +010064 else:
José Fonsecac493e3e2011-06-29 12:57:06 +010065 suffix = 'dv'
66 arg_type = alias.expr
José Fonseca99221832011-03-22 22:15:46 +000067 elif alias.expr == 'GLfloat':
José Fonseca1a2fdd22011-04-01 00:55:09 +010068 if self.long_suffix:
José Fonsecac493e3e2011-06-29 12:57:06 +010069 suffix = 'Floatv'
70 arg_type = alias.expr
José Fonseca1a2fdd22011-04-01 00:55:09 +010071 else:
José Fonsecac493e3e2011-06-29 12:57:06 +010072 suffix = 'fv'
73 arg_type = alias.expr
José Fonseca7f5163e2011-03-31 23:37:26 +010074 elif alias.expr in ('GLint', 'GLuint', 'GLsizei'):
José Fonseca1a2fdd22011-04-01 00:55:09 +010075 if self.long_suffix:
José Fonsecac493e3e2011-06-29 12:57:06 +010076 suffix = 'Integerv'
77 arg_type = 'GLint'
José Fonseca1a2fdd22011-04-01 00:55:09 +010078 else:
José Fonsecac493e3e2011-06-29 12:57:06 +010079 suffix = 'iv'
80 arg_type = 'GLint'
José Fonseca99221832011-03-22 22:15:46 +000081 else:
82 print alias.expr
83 assert False
José Fonsecac493e3e2011-06-29 12:57:06 +010084 function_name = self.prefix + suffix + self.ext_suffix
85 return function_name, arg_type
José Fonseca99221832011-03-22 22:15:46 +000086
José Fonseca54f304a2012-01-14 19:33:08 +000087 def visitEnum(self, enum):
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 visitBitmask(self, bitmask):
José Fonseca1a2fdd22011-04-01 00:55:09 +010091 return self.visit(glapi.GLint)
José Fonseca99221832011-03-22 22:15:46 +000092
José Fonseca54f304a2012-01-14 19:33:08 +000093 def visitOpaque(self, pointer):
José Fonsecac493e3e2011-06-29 12:57:06 +010094 return self.prefix + 'Pointerv' + self.ext_suffix, 'GLvoid *'
José Fonseca99221832011-03-22 22:15:46 +000095
96
José Fonseca669b1222011-02-20 09:05:10 +000097class GlTracer(Tracer):
98
José Fonseca99221832011-03-22 22:15:46 +000099 arrays = [
100 ("Vertex", "VERTEX"),
101 ("Normal", "NORMAL"),
102 ("Color", "COLOR"),
103 ("Index", "INDEX"),
104 ("TexCoord", "TEXTURE_COORD"),
105 ("EdgeFlag", "EDGE_FLAG"),
106 ("FogCoord", "FOG_COORD"),
107 ("SecondaryColor", "SECONDARY_COLOR"),
José Fonseca14c21bc2011-02-20 23:32:22 +0000108 ]
José Fonsecac9f12232011-03-25 20:07:42 +0000109 arrays.reverse()
José Fonseca669b1222011-02-20 09:05:10 +0000110
Chia-I Wub3d218d2011-11-03 01:37:36 +0800111 # arrays available in PROFILE_ES1
112 arrays_es1 = ("Vertex", "Normal", "Color", "TexCoord")
113
José Fonseca4c938c22011-04-30 22:44:38 +0100114 def header(self, api):
115 Tracer.header(self, api)
116
José Fonseca707630d2014-03-07 14:20:35 +0000117 print '#include <algorithm>'
118 print
José Fonseca1b3d3752011-07-15 10:15:19 +0100119 print '#include "gltrace.hpp"'
120 print
José Fonseca5a568a92011-06-29 16:43:36 +0100121
122 # Which glVertexAttrib* variant to use
123 print 'enum vertex_attrib {'
124 print ' VERTEX_ATTRIB,'
José Fonseca5a568a92011-06-29 16:43:36 +0100125 print ' VERTEX_ATTRIB_NV,'
126 print '};'
127 print
José Fonseca632a78d2012-04-19 07:18:59 +0100128 print 'static vertex_attrib _get_vertex_attrib(void) {'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000129 print ' gltrace::Context *ctx = gltrace::getContext();'
José Fonseca74b661a2014-07-17 19:10:24 +0100130 print ' if (ctx->user_arrays_nv) {'
José Fonseca632a78d2012-04-19 07:18:59 +0100131 print ' GLboolean _vertex_program = GL_FALSE;'
132 print ' _glGetBooleanv(GL_VERTEX_PROGRAM_ARB, &_vertex_program);'
133 print ' if (_vertex_program) {'
Chia-I Wu8ef66972011-11-03 01:19:46 +0800134 print ' if (ctx->user_arrays_nv) {'
José Fonseca26be8f92014-03-07 14:08:50 +0000135 print ' GLint _vertex_program_binding_nv = _glGetInteger(GL_VERTEX_PROGRAM_BINDING_NV);'
José Fonseca632a78d2012-04-19 07:18:59 +0100136 print ' if (_vertex_program_binding_nv) {'
José Fonseca5a568a92011-06-29 16:43:36 +0100137 print ' return VERTEX_ATTRIB_NV;'
138 print ' }'
139 print ' }'
José Fonseca5a568a92011-06-29 16:43:36 +0100140 print ' }'
141 print ' }'
142 print ' return VERTEX_ATTRIB;'
143 print '}'
144 print
145
Imre Deakd4937372012-04-24 14:06:48 +0300146 self.defineShadowBufferHelper()
147
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000148 # Whether we need user arrays
José Fonseca632a78d2012-04-19 07:18:59 +0100149 print 'static inline bool _need_user_arrays(void)'
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000150 print '{'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000151 print ' gltrace::Context *ctx = gltrace::getContext();'
Chia-I Wu8ef66972011-11-03 01:19:46 +0800152 print ' if (!ctx->user_arrays) {'
José Fonseca25ebe542011-04-24 10:08:22 +0100153 print ' return false;'
154 print ' }'
155 print
José Fonseca8b04b5a2014-07-17 19:25:21 +0100156 print ' enum gltrace::Profile profile = ctx->profile;'
157 print
José Fonseca1a2fdd22011-04-01 00:55:09 +0100158
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000159 for camelcase_name, uppercase_name in self.arrays:
Chia-I Wub3d218d2011-11-03 01:37:36 +0800160 # in which profile is the array available?
José Fonseca8b04b5a2014-07-17 19:25:21 +0100161 profile_check = 'profile == gltrace::PROFILE_COMPAT'
Chia-I Wub3d218d2011-11-03 01:37:36 +0800162 if camelcase_name in self.arrays_es1:
José Fonseca8b04b5a2014-07-17 19:25:21 +0100163 profile_check = '(' + profile_check + ' || profile == gltrace::PROFILE_ES1)';
Chia-I Wub3d218d2011-11-03 01:37:36 +0800164
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000165 function_name = 'gl%sPointer' % camelcase_name
166 enable_name = 'GL_%s_ARRAY' % uppercase_name
167 binding_name = 'GL_%s_ARRAY_BUFFER_BINDING' % uppercase_name
168 print ' // %s' % function_name
Chia-I Wub3d218d2011-11-03 01:37:36 +0800169 print ' if (%s) {' % profile_check
José Fonsecafb6744f2011-04-15 11:18:37 +0100170 self.array_prolog(api, uppercase_name)
José Fonseca8b04b5a2014-07-17 19:25:21 +0100171 print ' if (_glIsEnabled(%s) &&' % enable_name
172 print ' _glGetInteger(%s) == 0) {' % binding_name
José Fonsecafb6744f2011-04-15 11:18:37 +0100173 self.array_cleanup(api, uppercase_name)
José Fonseca8b04b5a2014-07-17 19:25:21 +0100174 print ' return true;'
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000175 print ' }'
José Fonsecafb6744f2011-04-15 11:18:37 +0100176 self.array_epilog(api, uppercase_name)
Chia-I Wub3d218d2011-11-03 01:37:36 +0800177 print ' }'
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000178 print
José Fonseca7f5163e2011-03-31 23:37:26 +0100179
Chia-I Wub3d218d2011-11-03 01:37:36 +0800180 print ' // ES1 does not support generic vertex attributes'
José Fonseca8b04b5a2014-07-17 19:25:21 +0100181 print ' if (profile == gltrace::PROFILE_ES1)'
Chia-I Wub3d218d2011-11-03 01:37:36 +0800182 print ' return false;'
183 print
José Fonseca632a78d2012-04-19 07:18:59 +0100184 print ' vertex_attrib _vertex_attrib = _get_vertex_attrib();'
José Fonseca5a568a92011-06-29 16:43:36 +0100185 print
186 print ' // glVertexAttribPointer'
José Fonseca632a78d2012-04-19 07:18:59 +0100187 print ' if (_vertex_attrib == VERTEX_ATTRIB) {'
José Fonseca26be8f92014-03-07 14:08:50 +0000188 print ' GLint _max_vertex_attribs = _glGetInteger(GL_MAX_VERTEX_ATTRIBS);'
José Fonseca632a78d2012-04-19 07:18:59 +0100189 print ' for (GLint index = 0; index < _max_vertex_attribs; ++index) {'
José Fonseca8b04b5a2014-07-17 19:25:21 +0100190 print ' if (_glGetVertexAttribi(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED) &&'
191 print ' _glGetVertexAttribi(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING) == 0) {'
192 print ' return true;'
José Fonseca5a568a92011-06-29 16:43:36 +0100193 print ' }'
194 print ' }'
195 print ' }'
196 print
José Fonseca5a568a92011-06-29 16:43:36 +0100197 print ' // glVertexAttribPointerNV'
José Fonseca632a78d2012-04-19 07:18:59 +0100198 print ' if (_vertex_attrib == VERTEX_ATTRIB_NV) {'
José Fonseca5a568a92011-06-29 16:43:36 +0100199 print ' for (GLint index = 0; index < 16; ++index) {'
José Fonseca8b04b5a2014-07-17 19:25:21 +0100200 print ' if (_glIsEnabled(GL_VERTEX_ATTRIB_ARRAY0_NV + index)) {'
José Fonseca5a568a92011-06-29 16:43:36 +0100201 print ' return true;'
José Fonseca1a2fdd22011-04-01 00:55:09 +0100202 print ' }'
203 print ' }'
204 print ' }'
205 print
206
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000207 print ' return false;'
208 print '}'
209 print
José Fonseca669b1222011-02-20 09:05:10 +0000210
José Fonseca14cb9ef2012-05-17 21:33:14 +0100211 print 'static void _trace_user_arrays(GLuint count);'
José Fonseca14c21bc2011-02-20 23:32:22 +0000212 print
José Fonseca867b1b72011-04-24 11:58:04 +0100213
José Fonseca707630d2014-03-07 14:20:35 +0000214 print '// whether glLockArraysEXT() has ever been called'
215 print 'static bool _checkLockArraysEXT = false;'
216 print
217
José Fonseca9c536b02012-02-29 20:54:13 +0000218 # Buffer mappings
219 print '// whether glMapBufferRange(GL_MAP_WRITE_BIT) has ever been called'
José Fonseca632a78d2012-04-19 07:18:59 +0100220 print 'static bool _checkBufferMapRange = false;'
José Fonseca9c536b02012-02-29 20:54:13 +0000221 print
222 print '// whether glBufferParameteriAPPLE(GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE) has ever been called'
José Fonseca632a78d2012-04-19 07:18:59 +0100223 print 'static bool _checkBufferFlushingUnmapAPPLE = false;'
José Fonseca9c536b02012-02-29 20:54:13 +0000224 print
225 # Buffer mapping information, necessary for old Mesa 2.1 drivers which
226 # do not support glGetBufferParameteriv(GL_BUFFER_ACCESS_FLAGS/GL_BUFFER_MAP_LENGTH)
José Fonseca867b1b72011-04-24 11:58:04 +0100227 print 'struct buffer_mapping {'
228 print ' void *map;'
229 print ' GLint length;'
230 print ' bool write;'
José Fonseca73373602011-05-20 17:45:26 +0100231 print ' bool explicit_flush;'
José Fonseca867b1b72011-04-24 11:58:04 +0100232 print '};'
233 print
234 for target in self.buffer_targets:
José Fonseca632a78d2012-04-19 07:18:59 +0100235 print 'struct buffer_mapping _%s_mapping;' % target.lower();
José Fonseca867b1b72011-04-24 11:58:04 +0100236 print
237 print 'static inline struct buffer_mapping *'
238 print 'get_buffer_mapping(GLenum target) {'
José Fonseca06e85192011-10-16 14:15:36 +0100239 print ' switch (target) {'
José Fonseca867b1b72011-04-24 11:58:04 +0100240 for target in self.buffer_targets:
241 print ' case GL_%s:' % target
José Fonseca632a78d2012-04-19 07:18:59 +0100242 print ' return & _%s_mapping;' % target.lower()
José Fonseca867b1b72011-04-24 11:58:04 +0100243 print ' default:'
José Fonseca559d5342011-10-27 08:10:56 +0100244 print ' os::log("apitrace: warning: unknown buffer target 0x%04X\\n", target);'
José Fonseca867b1b72011-04-24 11:58:04 +0100245 print ' return NULL;'
246 print ' }'
247 print '}'
248 print
249
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100250 # Generate a helper function to determine whether a parameter name
251 # refers to a symbolic value or not
252 print 'static bool'
253 print 'is_symbolic_pname(GLenum pname) {'
José Fonseca06e85192011-10-16 14:15:36 +0100254 print ' switch (pname) {'
José Fonseca5ea91872011-05-04 09:41:55 +0100255 for function, type, count, name in glparams.parameters:
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100256 if type is glapi.GLenum:
José Fonseca4c938c22011-04-30 22:44:38 +0100257 print ' case %s:' % name
258 print ' return true;'
259 print ' default:'
260 print ' return false;'
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100261 print ' }'
262 print '}'
263 print
264
265 # Generate a helper function to determine whether a parameter value is
266 # potentially symbolic or not; i.e., if the value can be represented in
267 # an enum or not
268 print 'template<class T>'
269 print 'static inline bool'
270 print 'is_symbolic_param(T param) {'
271 print ' return static_cast<T>(static_cast<GLenum>(param)) == param;'
272 print '}'
273 print
José Fonseca4c938c22011-04-30 22:44:38 +0100274
275 # Generate a helper function to know how many elements a parameter has
276 print 'static size_t'
José Fonseca632a78d2012-04-19 07:18:59 +0100277 print '_gl_param_size(GLenum pname) {'
José Fonseca06e85192011-10-16 14:15:36 +0100278 print ' switch (pname) {'
José Fonseca5ea91872011-05-04 09:41:55 +0100279 for function, type, count, name in glparams.parameters:
José Fonseca4c938c22011-04-30 22:44:38 +0100280 if type is not None:
José Fonsecaddf6d2c2012-12-20 15:34:50 +0000281 print ' case %s: return %s;' % (name, count)
José Fonseca4c938c22011-04-30 22:44:38 +0100282 print ' default:'
José Fonseca559d5342011-10-27 08:10:56 +0100283 print r' os::log("apitrace: warning: %s: unknown GLenum 0x%04X\n", __FUNCTION__, pname);'
José Fonseca4c938c22011-04-30 22:44:38 +0100284 print ' return 1;'
285 print ' }'
286 print '}'
287 print
288
Chia-I Wu335efb42011-11-03 01:59:22 +0800289 # states such as GL_UNPACK_ROW_LENGTH are not available in GLES
290 print 'static inline bool'
291 print 'can_unpack_subimage(void) {'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000292 print ' gltrace::Context *ctx = gltrace::getContext();'
293 print ' return (ctx->profile == gltrace::PROFILE_COMPAT);'
Chia-I Wu335efb42011-11-03 01:59:22 +0800294 print '}'
295 print
296
José Fonseca1b6c8752012-04-15 14:33:00 +0100297 getProcAddressFunctionNames = []
298
299 def traceApi(self, api):
300 if self.getProcAddressFunctionNames:
301 # Generate a function to wrap proc addresses
302 getProcAddressFunction = api.getFunctionByName(self.getProcAddressFunctionNames[0])
303 argType = getProcAddressFunction.args[0].type
304 retType = getProcAddressFunction.type
305
306 print 'static %s _wrapProcAddress(%s procName, %s procPtr);' % (retType, argType, retType)
307 print
308
309 Tracer.traceApi(self, api)
310
311 print 'static %s _wrapProcAddress(%s procName, %s procPtr) {' % (retType, argType, retType)
Peter Lohrmann0b5b75e2013-06-03 14:58:41 -0700312
313 # Provide fallback functions to missing debug functions
José Fonseca1b6c8752012-04-15 14:33:00 +0100314 print ' if (!procPtr) {'
Peter Lohrmann0b5b75e2013-06-03 14:58:41 -0700315 else_ = ''
316 for function_name in self.debug_functions:
317 if self.api.getFunctionByName(function_name):
318 print ' %sif (strcmp("%s", (const char *)procName) == 0) {' % (else_, function_name)
319 print ' return (%s)&%s;' % (retType, function_name)
320 print ' }'
321 else_ = 'else '
322 print ' %s{' % else_
323 print ' return NULL;'
324 print ' }'
José Fonseca1b6c8752012-04-15 14:33:00 +0100325 print ' }'
Peter Lohrmann0b5b75e2013-06-03 14:58:41 -0700326
José Fonseca81301932012-11-11 00:10:20 +0000327 for function in api.getAllFunctions():
José Fonseca1b6c8752012-04-15 14:33:00 +0100328 ptype = function_pointer_type(function)
329 pvalue = function_pointer_value(function)
330 print ' if (strcmp("%s", (const char *)procName) == 0) {' % function.name
331 print ' %s = (%s)procPtr;' % (pvalue, ptype)
332 print ' return (%s)&%s;' % (retType, function.name,)
333 print ' }'
334 print ' os::log("apitrace: warning: unknown function \\"%s\\"\\n", (const char *)procName);'
335 print ' return procPtr;'
336 print '}'
337 print
338 else:
339 Tracer.traceApi(self, api)
340
Imre Deakd4937372012-04-24 14:06:48 +0300341 def defineShadowBufferHelper(self):
342 print 'void _shadow_glGetBufferSubData(GLenum target, GLintptr offset,'
343 print ' GLsizeiptr size, GLvoid *data)'
344 print '{'
José Fonsecaa33d0bb2012-11-10 09:11:42 +0000345 print ' gltrace::Context *ctx = gltrace::getContext();'
Imre Deakd4937372012-04-24 14:06:48 +0300346 print ' if (!ctx->needsShadowBuffers() || target != GL_ELEMENT_ARRAY_BUFFER) {'
José Fonseca219c9f22012-11-03 10:13:17 +0000347 print ' _glGetBufferSubData(target, offset, size, data);'
Imre Deakd4937372012-04-24 14:06:48 +0300348 print ' return;'
349 print ' }'
350 print
José Fonseca26be8f92014-03-07 14:08:50 +0000351 print ' GLint buffer_binding = _glGetInteger(GL_ELEMENT_ARRAY_BUFFER_BINDING);'
José Fonseca219c9f22012-11-03 10:13:17 +0000352 print ' if (buffer_binding > 0) {'
353 print ' gltrace::Buffer & buf = ctx->buffers[buffer_binding];'
354 print ' buf.getSubData(offset, size, data);'
355 print ' }'
Imre Deakd4937372012-04-24 14:06:48 +0300356 print '}'
357
José Fonseca219c9f22012-11-03 10:13:17 +0000358 def shadowBufferMethod(self, method):
359 # Emit code to fetch the shadow buffer, and invoke a method
360 print ' gltrace::Context *ctx = gltrace::getContext();'
361 print ' if (ctx->needsShadowBuffers() && target == GL_ELEMENT_ARRAY_BUFFER) {'
José Fonseca26be8f92014-03-07 14:08:50 +0000362 print ' GLint buffer_binding = _glGetInteger(GL_ELEMENT_ARRAY_BUFFER_BINDING);'
José Fonseca219c9f22012-11-03 10:13:17 +0000363 print ' if (buffer_binding > 0) {'
364 print ' gltrace::Buffer & buf = ctx->buffers[buffer_binding];'
365 print ' buf.' + method + ';'
366 print ' }'
367 print ' }'
368 print
369
Imre Deakd4937372012-04-24 14:06:48 +0300370 def shadowBufferProlog(self, function):
371 if function.name == 'glBufferData':
José Fonseca219c9f22012-11-03 10:13:17 +0000372 self.shadowBufferMethod('bufferData(size, data)')
Imre Deakd4937372012-04-24 14:06:48 +0300373
374 if function.name == 'glBufferSubData':
José Fonseca219c9f22012-11-03 10:13:17 +0000375 self.shadowBufferMethod('bufferSubData(offset, size, data)')
Imre Deakd4937372012-04-24 14:06:48 +0300376
377 if function.name == 'glDeleteBuffers':
378 print ' gltrace::Context *ctx = gltrace::getContext();'
379 print ' if (ctx->needsShadowBuffers()) {'
José Fonseca219c9f22012-11-03 10:13:17 +0000380 print ' for (GLsizei i = 0; i < n; i++) {'
381 print ' ctx->buffers.erase(buffer[i]);'
Imre Deakd4937372012-04-24 14:06:48 +0300382 print ' }'
383 print ' }'
384
José Fonseca99221832011-03-22 22:15:46 +0000385 array_pointer_function_names = set((
386 "glVertexPointer",
387 "glNormalPointer",
388 "glColorPointer",
389 "glIndexPointer",
390 "glTexCoordPointer",
391 "glEdgeFlagPointer",
392 "glFogCoordPointer",
393 "glSecondaryColorPointer",
José Fonseca7f5163e2011-03-31 23:37:26 +0100394
José Fonsecaac5285b2011-05-04 11:09:08 +0100395 "glInterleavedArrays",
396
José Fonseca7e0bfd92011-04-30 23:09:03 +0100397 "glVertexPointerEXT",
398 "glNormalPointerEXT",
399 "glColorPointerEXT",
400 "glIndexPointerEXT",
401 "glTexCoordPointerEXT",
402 "glEdgeFlagPointerEXT",
403 "glFogCoordPointerEXT",
404 "glSecondaryColorPointerEXT",
José Fonseca99221832011-03-22 22:15:46 +0000405
José Fonseca7f5163e2011-03-31 23:37:26 +0100406 "glVertexAttribPointer",
407 "glVertexAttribPointerARB",
408 "glVertexAttribPointerNV",
José Fonsecaac5285b2011-05-04 11:09:08 +0100409 "glVertexAttribIPointer",
410 "glVertexAttribIPointerEXT",
José Fonseca7f5163e2011-03-31 23:37:26 +0100411 "glVertexAttribLPointer",
412 "glVertexAttribLPointerEXT",
José Fonseca99221832011-03-22 22:15:46 +0000413
414 #"glMatrixIndexPointerARB",
415 ))
416
José Fonsecac5bf77a2014-08-14 16:10:02 +0100417 # XXX: We currently ignore the gl*Draw*ElementArray* functions
418 draw_function_regex = re.compile(r'^gl([A-Z][a-z]+)*Draw(Range)?(Arrays|Elements)([A-Z][a-zA-Z]*)?$' )
José Fonseca99221832011-03-22 22:15:46 +0000419
José Fonsecac9f12232011-03-25 20:07:42 +0000420 interleaved_formats = [
421 'GL_V2F',
422 'GL_V3F',
423 'GL_C4UB_V2F',
424 'GL_C4UB_V3F',
425 'GL_C3F_V3F',
426 'GL_N3F_V3F',
427 'GL_C4F_N3F_V3F',
428 'GL_T2F_V3F',
429 'GL_T4F_V4F',
430 'GL_T2F_C4UB_V3F',
431 'GL_T2F_C3F_V3F',
432 'GL_T2F_N3F_V3F',
433 'GL_T2F_C4F_N3F_V3F',
434 'GL_T4F_C4F_N3F_V4F',
435 ]
436
José Fonseca54f304a2012-01-14 19:33:08 +0000437 def traceFunctionImplBody(self, function):
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000438 # Defer tracing of user array pointers...
José Fonseca99221832011-03-22 22:15:46 +0000439 if function.name in self.array_pointer_function_names:
José Fonseca26be8f92014-03-07 14:08:50 +0000440 print ' GLint _array_buffer = _glGetInteger(GL_ARRAY_BUFFER_BINDING);'
José Fonseca632a78d2012-04-19 07:18:59 +0100441 print ' if (!_array_buffer) {'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000442 print ' gltrace::Context *ctx = gltrace::getContext();'
Chia-I Wu8ef66972011-11-03 01:19:46 +0800443 print ' ctx->user_arrays = true;'
José Fonseca5a568a92011-06-29 16:43:36 +0100444 if function.name == "glVertexAttribPointerNV":
Chia-I Wu8ef66972011-11-03 01:19:46 +0800445 print ' ctx->user_arrays_nv = true;'
José Fonseca54f304a2012-01-14 19:33:08 +0000446 self.invokeFunction(function)
José Fonsecaac5285b2011-05-04 11:09:08 +0100447
448 # And also break down glInterleavedArrays into the individual calls
449 if function.name == 'glInterleavedArrays':
450 print
451
452 # Initialize the enable flags
453 for camelcase_name, uppercase_name in self.arrays:
José Fonseca632a78d2012-04-19 07:18:59 +0100454 flag_name = '_' + uppercase_name.lower()
José Fonsecaac5285b2011-05-04 11:09:08 +0100455 print ' GLboolean %s = GL_FALSE;' % flag_name
456 print
457
458 # Switch for the interleaved formats
459 print ' switch (format) {'
460 for format in self.interleaved_formats:
461 print ' case %s:' % format
462 for camelcase_name, uppercase_name in self.arrays:
José Fonseca632a78d2012-04-19 07:18:59 +0100463 flag_name = '_' + uppercase_name.lower()
José Fonsecaac5285b2011-05-04 11:09:08 +0100464 if format.find('_' + uppercase_name[0]) >= 0:
465 print ' %s = GL_TRUE;' % flag_name
466 print ' break;'
467 print ' default:'
468 print ' return;'
469 print ' }'
470 print
471
472 # Emit fake glEnableClientState/glDisableClientState flags
473 for camelcase_name, uppercase_name in self.arrays:
José Fonseca632a78d2012-04-19 07:18:59 +0100474 flag_name = '_' + uppercase_name.lower()
José Fonsecaac5285b2011-05-04 11:09:08 +0100475 enable_name = 'GL_%s_ARRAY' % uppercase_name
476
477 # Emit a fake function
478 print ' {'
José Fonseca632a78d2012-04-19 07:18:59 +0100479 print ' static const trace::FunctionSig &_sig = %s ? _glEnableClientState_sig : _glDisableClientState_sig;' % flag_name
José Fonseca7a5f23a2014-06-24 19:20:36 +0100480 print ' unsigned _call = trace::localWriter.beginEnter(&_sig, true);'
José Fonsecab4a3d142011-10-27 07:43:19 +0100481 print ' trace::localWriter.beginArg(0);'
José Fonseca54f304a2012-01-14 19:33:08 +0000482 self.serializeValue(glapi.GLenum, enable_name)
José Fonsecab4a3d142011-10-27 07:43:19 +0100483 print ' trace::localWriter.endArg();'
484 print ' trace::localWriter.endEnter();'
José Fonseca632a78d2012-04-19 07:18:59 +0100485 print ' trace::localWriter.beginLeave(_call);'
José Fonsecab4a3d142011-10-27 07:43:19 +0100486 print ' trace::localWriter.endLeave();'
José Fonsecaac5285b2011-05-04 11:09:08 +0100487 print ' }'
488
José Fonsecac629a8c2014-06-01 21:12:27 +0100489 # Warn about buggy glGet(GL_*ARRAY_SIZE) not returning GL_BGRA
490 buggyFunctions = {
491 'glColorPointer': ('glGetIntegerv', '', 'GL_COLOR_ARRAY_SIZE'),
492 'glSecondaryColorPointer': ('glGetIntegerv', '', 'GL_SECONDARY_COLOR_ARRAY_SIZE'),
493 'glVertexAttribPointer': ('glGetVertexAttribiv', 'index, ', 'GL_VERTEX_ATTRIB_ARRAY_SIZE'),
494 'glVertexAttribPointerARB': ('glGetVertexAttribivARB', 'index, ', 'GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB'),
495 }
496 if function.name in buggyFunctions:
497 getter, extraArg, pname = buggyFunctions[function.name]
498 print r' static bool _checked = false;'
499 print r' if (!_checked && size == GL_BGRA) {'
500 print r' GLint _size = 0;'
501 print r' _%s(%s%s, &_size);' % (getter, extraArg, pname)
502 print r' if (_size != GL_BGRA) {'
503 print r' os::log("apitrace: warning: %s(%s) does not return GL_BGRA; trace will be incorrect (https://github.com/apitrace/apitrace/issues/261)\n");' % (getter, pname)
504 print r' }'
505 print r' _checked = true;'
506 print r' }'
507
José Fonseca99221832011-03-22 22:15:46 +0000508 print ' return;'
509 print ' }'
José Fonseca14c21bc2011-02-20 23:32:22 +0000510
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000511 # ... to the draw calls
José Fonsecac5bf77a2014-08-14 16:10:02 +0100512 if self.draw_function_regex.match(function.name):
José Fonseca632a78d2012-04-19 07:18:59 +0100513 print ' if (_need_user_arrays()) {'
José Fonseca246508e2014-08-14 16:07:46 +0100514 if 'Indirect' in function.name:
515 print r' os::log("apitrace: warning: %s: indirect user arrays not supported\n");' % (function.name,)
516 else:
517 arg_names = ', '.join([arg.name for arg in function.args[1:]])
518 print ' GLuint _count = _%s_count(%s);' % (function.name, arg_names)
519 # Some apps, in particular Quake3, can tell the driver to lock more
520 # vertices than those actually required for the draw call.
521 print ' if (_checkLockArraysEXT) {'
522 print ' GLuint _locked_count = _glGetInteger(GL_ARRAY_ELEMENT_LOCK_FIRST_EXT)'
523 print ' + _glGetInteger(GL_ARRAY_ELEMENT_LOCK_COUNT_EXT);'
524 print ' _count = std::max(_count, _locked_count);'
525 print ' }'
526 print ' _trace_user_arrays(_count);'
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000527 print ' }'
José Fonseca707630d2014-03-07 14:20:35 +0000528 if function.name == 'glLockArraysEXT':
529 print ' _checkLockArraysEXT = true;'
José Fonseca4a7d8602014-06-18 16:03:44 +0100530
531 # Warn if user arrays are used with glBegin/glArrayElement/glEnd.
532 if function.name == 'glBegin':
José Fonseca7c39d012014-11-07 19:46:53 +0000533 print r' gltrace::Context *ctx = gltrace::getContext();'
534 print r' ctx->userArraysOnBegin = _need_user_arrays();'
535 if function.name.startswith('glArrayElement'):
536 print r' gltrace::Context *ctx = gltrace::getContext();'
537 print r' if (ctx->userArraysOnBegin) {'
José Fonseca4a7d8602014-06-18 16:03:44 +0100538 print r' os::log("apitrace: warning: user arrays with glArrayElement not supported (https://github.com/apitrace/apitrace/issues/276)\n");'
José Fonseca7c39d012014-11-07 19:46:53 +0000539 print r' ctx->userArraysOnBegin = false;'
José Fonseca4a7d8602014-06-18 16:03:44 +0100540 print r' }'
José Fonseca14c21bc2011-02-20 23:32:22 +0000541
José Fonseca73373602011-05-20 17:45:26 +0100542 # Emit a fake memcpy on buffer uploads
José Fonseca9c536b02012-02-29 20:54:13 +0000543 if function.name == 'glBufferParameteriAPPLE':
544 print ' if (pname == GL_BUFFER_FLUSHING_UNMAP_APPLE && param == GL_FALSE) {'
José Fonseca632a78d2012-04-19 07:18:59 +0100545 print ' _checkBufferFlushingUnmapAPPLE = true;'
José Fonseca9c536b02012-02-29 20:54:13 +0000546 print ' }'
José Fonsecacdc322c2012-02-29 19:29:51 +0000547 if function.name in ('glUnmapBuffer', 'glUnmapBufferARB'):
José Fonseca9c536b02012-02-29 20:54:13 +0000548 if function.name.endswith('ARB'):
549 suffix = 'ARB'
550 else:
551 suffix = ''
552 print ' GLint access = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100553 print ' _glGetBufferParameteriv%s(target, GL_BUFFER_ACCESS, &access);' % suffix
José Fonseca9c536b02012-02-29 20:54:13 +0000554 print ' if (access != GL_READ_ONLY) {'
555 print ' GLvoid *map = NULL;'
José Fonseca632a78d2012-04-19 07:18:59 +0100556 print ' _glGetBufferPointerv%s(target, GL_BUFFER_MAP_POINTER, &map);' % suffix
José Fonseca9c536b02012-02-29 20:54:13 +0000557 print ' if (map) {'
558 print ' GLint length = -1;'
559 print ' bool flush = true;'
José Fonseca632a78d2012-04-19 07:18:59 +0100560 print ' if (_checkBufferMapRange) {'
561 print ' _glGetBufferParameteriv%s(target, GL_BUFFER_MAP_LENGTH, &length);' % suffix
José Fonseca9c536b02012-02-29 20:54:13 +0000562 print ' GLint access_flags = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100563 print ' _glGetBufferParameteriv(target, GL_BUFFER_ACCESS_FLAGS, &access_flags);'
José Fonseca9c536b02012-02-29 20:54:13 +0000564 print ' flush = flush && !(access_flags & GL_MAP_FLUSH_EXPLICIT_BIT);'
565 print ' if (length == -1) {'
José Fonsecacb07e2d2014-02-04 15:14:09 +0000566 print ' // Mesa drivers refuse GL_BUFFER_MAP_LENGTH without GL 3.0 up-to'
567 print ' // http://cgit.freedesktop.org/mesa/mesa/commit/?id=ffee498fb848b253a7833373fe5430f8c7ca0c5f'
José Fonsecadb1ccce2012-02-29 21:09:24 +0000568 print ' static bool warned = false;'
569 print ' if (!warned) {'
570 print ' os::log("apitrace: warning: glGetBufferParameteriv%s(GL_BUFFER_MAP_LENGTH) failed\\n");' % suffix
571 print ' warned = true;'
572 print ' }'
José Fonseca9c536b02012-02-29 20:54:13 +0000573 print ' struct buffer_mapping *mapping = get_buffer_mapping(target);'
574 print ' if (mapping) {'
575 print ' length = mapping->length;'
576 print ' flush = flush && !mapping->explicit_flush;'
577 print ' } else {'
578 print ' length = 0;'
579 print ' flush = false;'
580 print ' }'
581 print ' }'
582 print ' } else {'
583 print ' length = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100584 print ' _glGetBufferParameteriv%s(target, GL_BUFFER_SIZE, &length);' % suffix
José Fonseca9c536b02012-02-29 20:54:13 +0000585 print ' }'
José Fonseca632a78d2012-04-19 07:18:59 +0100586 print ' if (_checkBufferFlushingUnmapAPPLE) {'
José Fonseca9c536b02012-02-29 20:54:13 +0000587 print ' GLint flushing_unmap = GL_TRUE;'
José Fonseca632a78d2012-04-19 07:18:59 +0100588 print ' _glGetBufferParameteriv%s(target, GL_BUFFER_FLUSHING_UNMAP_APPLE, &flushing_unmap);' % suffix
José Fonseca9c536b02012-02-29 20:54:13 +0000589 print ' flush = flush && flushing_unmap;'
590 print ' }'
591 print ' if (flush && length > 0) {'
José Fonseca6f0e3032014-06-25 01:00:35 +0100592 self.emit_memcpy('map', 'length')
José Fonseca9c536b02012-02-29 20:54:13 +0000593 print ' }'
594 print ' }'
595 print ' }'
José Fonsecacdc322c2012-02-29 19:29:51 +0000596 if function.name == 'glUnmapBufferOES':
597 print ' GLint access = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100598 print ' _glGetBufferParameteriv(target, GL_BUFFER_ACCESS_OES, &access);'
José Fonsecacdc322c2012-02-29 19:29:51 +0000599 print ' if (access == GL_WRITE_ONLY_OES) {'
600 print ' GLvoid *map = NULL;'
José Fonseca632a78d2012-04-19 07:18:59 +0100601 print ' _glGetBufferPointervOES(target, GL_BUFFER_MAP_POINTER_OES, &map);'
José Fonsecacdc322c2012-02-29 19:29:51 +0000602 print ' GLint size = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100603 print ' _glGetBufferParameteriv(target, GL_BUFFER_SIZE, &size);'
José Fonsecacdc322c2012-02-29 19:29:51 +0000604 print ' if (map && size > 0) {'
José Fonseca6f0e3032014-06-25 01:00:35 +0100605 self.emit_memcpy('map', 'size')
José Fonseca219c9f22012-11-03 10:13:17 +0000606 self.shadowBufferMethod('bufferSubData(0, size, map)')
José Fonsecacdc322c2012-02-29 19:29:51 +0000607 print ' }'
José Fonseca867b1b72011-04-24 11:58:04 +0100608 print ' }'
José Fonseca4920c302014-08-13 18:35:57 +0100609 if function.name == 'glUnmapNamedBuffer':
610 print ' GLint access_flags = 0;'
611 print ' _glGetNamedBufferParameteriv(buffer, GL_BUFFER_ACCESS_FLAGS, &access_flags);'
612 print ' if ((access_flags & GL_MAP_WRITE_BIT) && !(access_flags & GL_MAP_FLUSH_EXPLICIT_BIT)) {'
613 print ' GLvoid *map = NULL;'
614 print ' _glGetNamedBufferPointerv(buffer, GL_BUFFER_MAP_POINTER, &map);'
615 print ' GLint length = 0;'
616 print ' _glGetNamedBufferParameteriv(buffer, GL_BUFFER_MAP_LENGTH, &length);'
617 print ' if (map && length > 0) {'
618 self.emit_memcpy('map', 'length')
619 print ' }'
620 print ' }'
José Fonsecafb3bd602012-01-15 13:56:28 +0000621 if function.name == 'glUnmapNamedBufferEXT':
José Fonseca024aff42012-02-29 18:00:06 +0000622 print ' GLint access_flags = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100623 print ' _glGetNamedBufferParameterivEXT(buffer, GL_BUFFER_ACCESS_FLAGS, &access_flags);'
José Fonseca024aff42012-02-29 18:00:06 +0000624 print ' if ((access_flags & GL_MAP_WRITE_BIT) && !(access_flags & GL_MAP_FLUSH_EXPLICIT_BIT)) {'
José Fonsecafb3bd602012-01-15 13:56:28 +0000625 print ' GLvoid *map = NULL;'
José Fonseca632a78d2012-04-19 07:18:59 +0100626 print ' _glGetNamedBufferPointervEXT(buffer, GL_BUFFER_MAP_POINTER, &map);'
José Fonsecafb3bd602012-01-15 13:56:28 +0000627 print ' GLint length = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100628 print ' _glGetNamedBufferParameterivEXT(buffer, GL_BUFFER_MAP_LENGTH, &length);'
José Fonseca024aff42012-02-29 18:00:06 +0000629 print ' if (map && length > 0) {'
José Fonseca6f0e3032014-06-25 01:00:35 +0100630 self.emit_memcpy('map', 'length')
José Fonseca024aff42012-02-29 18:00:06 +0000631 print ' }'
José Fonsecafb3bd602012-01-15 13:56:28 +0000632 print ' }'
José Fonseca77ef0ce2012-02-29 18:08:48 +0000633 if function.name == 'glFlushMappedBufferRange':
634 print ' GLvoid *map = NULL;'
José Fonseca632a78d2012-04-19 07:18:59 +0100635 print ' _glGetBufferPointerv(target, GL_BUFFER_MAP_POINTER, &map);'
José Fonseca77ef0ce2012-02-29 18:08:48 +0000636 print ' if (map && length > 0) {'
José Fonseca6f0e3032014-06-25 01:00:35 +0100637 self.emit_memcpy('(const char *)map + offset', 'length')
José Fonseca77ef0ce2012-02-29 18:08:48 +0000638 print ' }'
639 if function.name == 'glFlushMappedBufferRangeAPPLE':
640 print ' GLvoid *map = NULL;'
José Fonseca632a78d2012-04-19 07:18:59 +0100641 print ' _glGetBufferPointerv(target, GL_BUFFER_MAP_POINTER, &map);'
José Fonseca77ef0ce2012-02-29 18:08:48 +0000642 print ' if (map && size > 0) {'
José Fonseca6f0e3032014-06-25 01:00:35 +0100643 self.emit_memcpy('(const char *)map + offset', 'size')
José Fonseca73373602011-05-20 17:45:26 +0100644 print ' }'
José Fonseca4920c302014-08-13 18:35:57 +0100645 if function.name == 'glFlushMappedNamedBufferRange':
646 print ' GLvoid *map = NULL;'
647 print ' _glGetNamedBufferPointerv(buffer, GL_BUFFER_MAP_POINTER, &map);'
648 print ' if (map && length > 0) {'
649 self.emit_memcpy('(const char *)map + offset', 'length')
650 print ' }'
José Fonsecafb3bd602012-01-15 13:56:28 +0000651 if function.name == 'glFlushMappedNamedBufferRangeEXT':
652 print ' GLvoid *map = NULL;'
José Fonseca632a78d2012-04-19 07:18:59 +0100653 print ' _glGetNamedBufferPointervEXT(buffer, GL_BUFFER_MAP_POINTER, &map);'
José Fonseca024aff42012-02-29 18:00:06 +0000654 print ' if (map && length > 0) {'
José Fonseca6f0e3032014-06-25 01:00:35 +0100655 self.emit_memcpy('(const char *)map + offset', 'length')
José Fonsecafb3bd602012-01-15 13:56:28 +0000656 print ' }'
José Fonseca867b1b72011-04-24 11:58:04 +0100657
José Fonseca3522cbd2014-02-28 14:45:32 +0000658 # FIXME: We don't support coherent/pinned memory mappings
659 # See https://github.com/apitrace/apitrace/issues/232
José Fonseca4920c302014-08-13 18:35:57 +0100660 if function.name in ('glBufferStorage', 'glNamedBufferStorage', 'glNamedBufferStorageEXT'):
José Fonseca3522cbd2014-02-28 14:45:32 +0000661 print r' if (flags & GL_MAP_COHERENT_BIT) {'
662 print r' os::log("apitrace: warning: coherent mappings not fully supported\n");'
663 print r' }'
664 if function.name in ('glBufferData', 'glBufferDataARB'):
665 print r' if (target == GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD) {'
666 print r' os::log("apitrace: warning: GL_AMD_pinned_memory not fully supported\n");'
667 print r' }'
668
José Fonseca91492d22011-05-23 21:20:31 +0100669 # Don't leave vertex attrib locations to chance. Instead emit fake
670 # glBindAttribLocation calls to ensure that the same locations will be
671 # used when retracing. Trying to remap locations after the fact would
672 # be an herculian task given that vertex attrib locations appear in
673 # many entry-points, including non-shader related ones.
674 if function.name == 'glLinkProgram':
José Fonseca54f304a2012-01-14 19:33:08 +0000675 Tracer.invokeFunction(self, function)
José Fonseca91492d22011-05-23 21:20:31 +0100676 print ' GLint active_attributes = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100677 print ' _glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &active_attributes);'
José Fonseca7525e6f2011-09-28 09:04:56 +0100678 print ' for (GLint attrib = 0; attrib < active_attributes; ++attrib) {'
José Fonseca91492d22011-05-23 21:20:31 +0100679 print ' GLint size = 0;'
680 print ' GLenum type = 0;'
681 print ' GLchar name[256];'
682 # TODO: Use ACTIVE_ATTRIBUTE_MAX_LENGTH instead of 256
José Fonseca632a78d2012-04-19 07:18:59 +0100683 print ' _glGetActiveAttrib(program, attrib, sizeof name, NULL, &size, &type, name);'
José Fonseca2a794f52011-05-26 20:54:29 +0100684 print " if (name[0] != 'g' || name[1] != 'l' || name[2] != '_') {"
José Fonseca632a78d2012-04-19 07:18:59 +0100685 print ' GLint location = _glGetAttribLocation(program, name);'
José Fonseca2a794f52011-05-26 20:54:29 +0100686 print ' if (location >= 0) {'
José Fonseca1b6c8752012-04-15 14:33:00 +0100687 bind_function = glapi.glapi.getFunctionByName('glBindAttribLocation')
José Fonseca91492d22011-05-23 21:20:31 +0100688 self.fake_call(bind_function, ['program', 'location', 'name'])
José Fonseca2a794f52011-05-26 20:54:29 +0100689 print ' }'
José Fonseca91492d22011-05-23 21:20:31 +0100690 print ' }'
691 print ' }'
692 if function.name == 'glLinkProgramARB':
José Fonseca54f304a2012-01-14 19:33:08 +0000693 Tracer.invokeFunction(self, function)
José Fonseca91492d22011-05-23 21:20:31 +0100694 print ' GLint active_attributes = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100695 print ' _glGetObjectParameterivARB(programObj, GL_OBJECT_ACTIVE_ATTRIBUTES_ARB, &active_attributes);'
José Fonseca7525e6f2011-09-28 09:04:56 +0100696 print ' for (GLint attrib = 0; attrib < active_attributes; ++attrib) {'
José Fonseca91492d22011-05-23 21:20:31 +0100697 print ' GLint size = 0;'
698 print ' GLenum type = 0;'
699 print ' GLcharARB name[256];'
700 # TODO: Use ACTIVE_ATTRIBUTE_MAX_LENGTH instead of 256
José Fonseca632a78d2012-04-19 07:18:59 +0100701 print ' _glGetActiveAttribARB(programObj, attrib, sizeof name, NULL, &size, &type, name);'
José Fonseca2a794f52011-05-26 20:54:29 +0100702 print " if (name[0] != 'g' || name[1] != 'l' || name[2] != '_') {"
José Fonseca632a78d2012-04-19 07:18:59 +0100703 print ' GLint location = _glGetAttribLocationARB(programObj, name);'
José Fonseca2a794f52011-05-26 20:54:29 +0100704 print ' if (location >= 0) {'
José Fonseca1b6c8752012-04-15 14:33:00 +0100705 bind_function = glapi.glapi.getFunctionByName('glBindAttribLocationARB')
José Fonseca91492d22011-05-23 21:20:31 +0100706 self.fake_call(bind_function, ['programObj', 'location', 'name'])
José Fonseca2a794f52011-05-26 20:54:29 +0100707 print ' }'
José Fonseca91492d22011-05-23 21:20:31 +0100708 print ' }'
709 print ' }'
710
Imre Deakd4937372012-04-24 14:06:48 +0300711 self.shadowBufferProlog(function)
712
José Fonseca54f304a2012-01-14 19:33:08 +0000713 Tracer.traceFunctionImplBody(self, function)
José Fonseca73373602011-05-20 17:45:26 +0100714
Peter Lohrmann0b5b75e2013-06-03 14:58:41 -0700715 # These entrypoints are only expected to be implemented by tools;
716 # drivers will probably not implement them.
José Fonsecaf028a8f2012-02-15 23:33:35 +0000717 marker_functions = [
718 # GL_GREMEDY_string_marker
José Fonseca8f34d342011-07-15 20:16:40 +0100719 'glStringMarkerGREMEDY',
José Fonsecaf028a8f2012-02-15 23:33:35 +0000720 # GL_GREMEDY_frame_terminator
José Fonseca8f34d342011-07-15 20:16:40 +0100721 'glFrameTerminatorGREMEDY',
722 ]
723
Peter Lohrmann0b5b75e2013-06-03 14:58:41 -0700724 # These entrypoints may be implemented by drivers, but are also very useful
725 # for debugging / analysis tools.
726 debug_functions = [
727 # GL_KHR_debug
728 'glDebugMessageControl',
729 'glDebugMessageInsert',
730 'glDebugMessageCallback',
731 'glGetDebugMessageLog',
732 'glPushDebugGroup',
733 'glPopDebugGroup',
734 'glObjectLabel',
735 'glGetObjectLabel',
736 'glObjectPtrLabel',
737 'glGetObjectPtrLabel',
738 # GL_ARB_debug_output
739 'glDebugMessageControlARB',
740 'glDebugMessageInsertARB',
741 'glDebugMessageCallbackARB',
742 'glGetDebugMessageLogARB',
743 # GL_AMD_debug_output
744 'glDebugMessageEnableAMD',
745 'glDebugMessageInsertAMD',
746 'glDebugMessageCallbackAMD',
747 'glGetDebugMessageLogAMD',
José Fonseca71f5a352014-07-28 12:19:50 +0100748 # GL_EXT_debug_label
749 'glLabelObjectEXT',
750 'glGetObjectLabelEXT',
751 # GL_EXT_debug_marker
752 'glInsertEventMarkerEXT',
753 'glPushGroupMarkerEXT',
754 'glPopGroupMarkerEXT',
Peter Lohrmann0b5b75e2013-06-03 14:58:41 -0700755 ]
756
José Fonseca54f304a2012-01-14 19:33:08 +0000757 def invokeFunction(self, function):
José Fonseca91492d22011-05-23 21:20:31 +0100758 if function.name in ('glLinkProgram', 'glLinkProgramARB'):
759 # These functions have been dispatched already
760 return
761
José Fonseca2cfa02c2013-06-10 08:05:29 +0100762 Tracer.invokeFunction(self, function)
763
764 def doInvokeFunction(self, function):
765 # Same as invokeFunction() but called both when trace is enabled or disabled.
766 #
767 # Used to modify the behavior of GL entry-points.
768
769 # Override GL extensions
770 if function.name in ('glGetString', 'glGetIntegerv', 'glGetStringi'):
771 Tracer.doInvokeFunction(self, function, prefix = 'gltrace::_', suffix = '_override')
772 return
773
José Fonseca71f5a352014-07-28 12:19:50 +0100774 # We implement GL_GREMEDY_*, etc., and not the driver
José Fonsecaf028a8f2012-02-15 23:33:35 +0000775 if function.name in self.marker_functions:
José Fonseca8f34d342011-07-15 20:16:40 +0100776 return
777
Peter Lohrmann9d9eb812013-07-12 16:15:25 -0400778 # We may be faking KHR_debug, so ensure the pointer queries result is
779 # always zeroed to prevent dereference of unitialized pointers
780 if function.name == 'glGetPointerv':
781 print ' if (params &&'
782 print ' (pname == GL_DEBUG_CALLBACK_FUNCTION ||'
783 print ' pname == GL_DEBUG_CALLBACK_USER_PARAM)) {'
784 print ' *params = NULL;'
785 print ' }'
786
José Fonseca2cfa02c2013-06-10 08:05:29 +0100787 if function.name in self.getProcAddressFunctionNames:
José Fonsecaf028a8f2012-02-15 23:33:35 +0000788 else_ = ''
789 for marker_function in self.marker_functions:
José Fonseca1b6c8752012-04-15 14:33:00 +0100790 if self.api.getFunctionByName(marker_function):
José Fonsecaf028a8f2012-02-15 23:33:35 +0000791 print ' %sif (strcmp("%s", (const char *)%s) == 0) {' % (else_, marker_function, function.args[0].name)
José Fonseca632a78d2012-04-19 07:18:59 +0100792 print ' _result = (%s)&%s;' % (function.type, marker_function)
José Fonsecaf028a8f2012-02-15 23:33:35 +0000793 print ' }'
794 else_ = 'else '
795 print ' %s{' % else_
José Fonseca2cfa02c2013-06-10 08:05:29 +0100796 Tracer.doInvokeFunction(self, function)
797
798 # Replace function addresses with ours
799 # XXX: Doing this here instead of wrapRet means that the trace will
800 # contain the addresses of the wrapper functions, and not the real
801 # functions, but in practice this should make no difference.
802 if function.name in self.getProcAddressFunctionNames:
803 print ' _result = _wrapProcAddress(%s, _result);' % (function.args[0].name,)
804
José Fonseca8f34d342011-07-15 20:16:40 +0100805 print ' }'
José Fonseca1b3d3752011-07-15 10:15:19 +0100806 return
807
José Fonseca2cfa02c2013-06-10 08:05:29 +0100808 Tracer.doInvokeFunction(self, function)
José Fonseca91492d22011-05-23 21:20:31 +0100809
José Fonseca867b1b72011-04-24 11:58:04 +0100810 buffer_targets = [
811 'ARRAY_BUFFER',
812 'ELEMENT_ARRAY_BUFFER',
813 'PIXEL_PACK_BUFFER',
814 'PIXEL_UNPACK_BUFFER',
José Fonseca7b20d672012-01-10 19:13:58 +0000815 'UNIFORM_BUFFER',
816 'TEXTURE_BUFFER',
817 'TRANSFORM_FEEDBACK_BUFFER',
818 'COPY_READ_BUFFER',
819 'COPY_WRITE_BUFFER',
820 'DRAW_INDIRECT_BUFFER',
821 'ATOMIC_COUNTER_BUFFER',
José Fonseca867b1b72011-04-24 11:58:04 +0100822 ]
823
José Fonseca54f304a2012-01-14 19:33:08 +0000824 def wrapRet(self, function, instance):
825 Tracer.wrapRet(self, function, instance)
José Fonseca1b3d3752011-07-15 10:15:19 +0100826
José Fonsecacdc322c2012-02-29 19:29:51 +0000827 # Keep track of buffer mappings
828 if function.name in ('glMapBuffer', 'glMapBufferARB'):
José Fonseca867b1b72011-04-24 11:58:04 +0100829 print ' struct buffer_mapping *mapping = get_buffer_mapping(target);'
830 print ' if (mapping) {'
831 print ' mapping->map = %s;' % (instance)
832 print ' mapping->length = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100833 print ' _glGetBufferParameteriv(target, GL_BUFFER_SIZE, &mapping->length);'
José Fonseca867b1b72011-04-24 11:58:04 +0100834 print ' mapping->write = (access != GL_READ_ONLY);'
José Fonseca73373602011-05-20 17:45:26 +0100835 print ' mapping->explicit_flush = false;'
José Fonseca867b1b72011-04-24 11:58:04 +0100836 print ' }'
José Fonseca867b1b72011-04-24 11:58:04 +0100837 if function.name == 'glMapBufferRange':
José Fonseca9c536b02012-02-29 20:54:13 +0000838 print ' if (access & GL_MAP_WRITE_BIT) {'
José Fonseca632a78d2012-04-19 07:18:59 +0100839 print ' _checkBufferMapRange = true;'
José Fonseca9c536b02012-02-29 20:54:13 +0000840 print ' }'
José Fonseca867b1b72011-04-24 11:58:04 +0100841 print ' struct buffer_mapping *mapping = get_buffer_mapping(target);'
842 print ' if (mapping) {'
843 print ' mapping->map = %s;' % (instance)
844 print ' mapping->length = length;'
845 print ' mapping->write = access & GL_MAP_WRITE_BIT;'
José Fonseca73373602011-05-20 17:45:26 +0100846 print ' mapping->explicit_flush = access & GL_MAP_FLUSH_EXPLICIT_BIT;'
José Fonseca867b1b72011-04-24 11:58:04 +0100847 print ' }'
José Fonseca669b1222011-02-20 09:05:10 +0000848
José Fonsecac9f12232011-03-25 20:07:42 +0000849 boolean_names = [
850 'GL_FALSE',
851 'GL_TRUE',
852 ]
853
854 def gl_boolean(self, value):
855 return self.boolean_names[int(bool(value))]
856
José Fonsecaa442a462014-11-12 21:16:22 +0000857 # Regular expression for the names of the functions that unpack from a
858 # pixel buffer object. See the ARB_pixel_buffer_object specification.
859 unpack_function_regex = re.compile(r'^gl(' + r'|'.join([
860 r'Bitmap',
861 r'PolygonStipple',
862 r'PixelMap[a-z]+v',
863 r'DrawPixels',
864 r'Color(Sub)?Table',
865 r'(Convolution|Separable)Filter[12]D',
866 r'(Compressed)?(Multi)?Tex(ture)?(Sub)?Image[1-4]D',
867 ]) + r')[0-9A-Z]*$')
José Fonsecae97bab92011-06-02 23:15:11 +0100868
José Fonseca54f304a2012-01-14 19:33:08 +0000869 def serializeArgValue(self, function, arg):
José Fonsecae97bab92011-06-02 23:15:11 +0100870 # Recognize offsets instead of blobs when a PBO is bound
José Fonsecaa442a462014-11-12 21:16:22 +0000871 if self.unpack_function_regex.match(function.name) \
José Fonsecae97bab92011-06-02 23:15:11 +0100872 and (isinstance(arg.type, stdapi.Blob) \
873 or (isinstance(arg.type, stdapi.Const) \
874 and isinstance(arg.type.type, stdapi.Blob))):
José Fonsecac29f4f12011-06-11 12:19:05 +0100875 print ' {'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000876 print ' gltrace::Context *ctx = gltrace::getContext();'
José Fonseca632a78d2012-04-19 07:18:59 +0100877 print ' GLint _unpack_buffer = 0;'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000878 print ' if (ctx->profile == gltrace::PROFILE_COMPAT)'
José Fonseca632a78d2012-04-19 07:18:59 +0100879 print ' _glGetIntegerv(GL_PIXEL_UNPACK_BUFFER_BINDING, &_unpack_buffer);'
880 print ' if (_unpack_buffer) {'
José Fonsecad559f022012-04-15 16:13:51 +0100881 print ' trace::localWriter.writePointer((uintptr_t)%s);' % arg.name
José Fonsecac29f4f12011-06-11 12:19:05 +0100882 print ' } else {'
José Fonseca54f304a2012-01-14 19:33:08 +0000883 Tracer.serializeArgValue(self, function, arg)
José Fonsecac29f4f12011-06-11 12:19:05 +0100884 print ' }'
José Fonsecae97bab92011-06-02 23:15:11 +0100885 print ' }'
886 return
887
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100888 # Several GL state functions take GLenum symbolic names as
889 # integer/floats; so dump the symbolic name whenever possible
José Fonseca3bcb33c2011-05-27 20:14:31 +0100890 if function.name.startswith('gl') \
José Fonsecae3571092011-10-13 08:26:27 +0100891 and arg.type in (glapi.GLint, glapi.GLfloat, glapi.GLdouble) \
José Fonseca3bcb33c2011-05-27 20:14:31 +0100892 and arg.name == 'param':
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100893 assert arg.index > 0
894 assert function.args[arg.index - 1].name == 'pname'
895 assert function.args[arg.index - 1].type == glapi.GLenum
896 print ' if (is_symbolic_pname(pname) && is_symbolic_param(%s)) {' % arg.name
José Fonseca54f304a2012-01-14 19:33:08 +0000897 self.serializeValue(glapi.GLenum, arg.name)
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100898 print ' } else {'
José Fonseca54f304a2012-01-14 19:33:08 +0000899 Tracer.serializeArgValue(self, function, arg)
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100900 print ' }'
901 return
902
José Fonseca54f304a2012-01-14 19:33:08 +0000903 Tracer.serializeArgValue(self, function, arg)
José Fonseca99221832011-03-22 22:15:46 +0000904
José Fonseca4c938c22011-04-30 22:44:38 +0100905 def footer(self, api):
906 Tracer.footer(self, api)
José Fonseca669b1222011-02-20 09:05:10 +0000907
José Fonseca4c938c22011-04-30 22:44:38 +0100908 # A simple state tracker to track the pointer values
José Fonseca669b1222011-02-20 09:05:10 +0000909 # update the state
José Fonseca14cb9ef2012-05-17 21:33:14 +0100910 print 'static void _trace_user_arrays(GLuint count)'
José Fonseca669b1222011-02-20 09:05:10 +0000911 print '{'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000912 print ' gltrace::Context *ctx = gltrace::getContext();'
José Fonseca8d1408b2014-02-03 19:57:18 +0000913 print
914
915 # Temporarily unbind the array buffer
José Fonseca26be8f92014-03-07 14:08:50 +0000916 print ' GLint _array_buffer = _glGetInteger(GL_ARRAY_BUFFER_BINDING);'
José Fonseca8d1408b2014-02-03 19:57:18 +0000917 print ' if (_array_buffer) {'
918 self.fake_glBindBuffer(api, 'GL_ARRAY_BUFFER', '0')
919 print ' }'
920 print
José Fonseca1a2fdd22011-04-01 00:55:09 +0100921
José Fonseca99221832011-03-22 22:15:46 +0000922 for camelcase_name, uppercase_name in self.arrays:
Chia-I Wub3d218d2011-11-03 01:37:36 +0800923 # in which profile is the array available?
José Fonsecaf028a8f2012-02-15 23:33:35 +0000924 profile_check = 'ctx->profile == gltrace::PROFILE_COMPAT'
Chia-I Wub3d218d2011-11-03 01:37:36 +0800925 if camelcase_name in self.arrays_es1:
José Fonsecaf028a8f2012-02-15 23:33:35 +0000926 profile_check = '(' + profile_check + ' || ctx->profile == gltrace::PROFILE_ES1)';
Chia-I Wub3d218d2011-11-03 01:37:36 +0800927
José Fonseca99221832011-03-22 22:15:46 +0000928 function_name = 'gl%sPointer' % camelcase_name
929 enable_name = 'GL_%s_ARRAY' % uppercase_name
930 binding_name = 'GL_%s_ARRAY_BUFFER_BINDING' % uppercase_name
José Fonseca1b6c8752012-04-15 14:33:00 +0100931 function = api.getFunctionByName(function_name)
José Fonseca99221832011-03-22 22:15:46 +0000932
José Fonseca06e85192011-10-16 14:15:36 +0100933 print ' // %s' % function.prototype()
Chia-I Wub3d218d2011-11-03 01:37:36 +0800934 print ' if (%s) {' % profile_check
José Fonsecafb6744f2011-04-15 11:18:37 +0100935 self.array_trace_prolog(api, uppercase_name)
936 self.array_prolog(api, uppercase_name)
José Fonseca632a78d2012-04-19 07:18:59 +0100937 print ' if (_glIsEnabled(%s)) {' % enable_name
José Fonseca26be8f92014-03-07 14:08:50 +0000938 print ' GLint _binding = _glGetInteger(%s);' % binding_name
José Fonseca632a78d2012-04-19 07:18:59 +0100939 print ' if (!_binding) {'
José Fonseca99221832011-03-22 22:15:46 +0000940
941 # Get the arguments via glGet*
942 for arg in function.args:
943 arg_get_enum = 'GL_%s_ARRAY_%s' % (uppercase_name, arg.name.upper())
944 arg_get_function, arg_type = TypeGetter().visit(arg.type)
José Fonseca7f5163e2011-03-31 23:37:26 +0100945 print ' %s %s = 0;' % (arg_type, arg.name)
José Fonseca632a78d2012-04-19 07:18:59 +0100946 print ' _%s(%s, &%s);' % (arg_get_function, arg_get_enum, arg.name)
José Fonseca99221832011-03-22 22:15:46 +0000947
948 arg_names = ', '.join([arg.name for arg in function.args[:-1]])
José Fonseca14cb9ef2012-05-17 21:33:14 +0100949 print ' size_t _size = _%s_size(%s, count);' % (function.name, arg_names)
José Fonseca99221832011-03-22 22:15:46 +0000950
951 # Emit a fake function
José Fonsecafb6744f2011-04-15 11:18:37 +0100952 self.array_trace_intermezzo(api, uppercase_name)
José Fonseca7a5f23a2014-06-24 19:20:36 +0100953 print ' unsigned _call = trace::localWriter.beginEnter(&_%s_sig, true);' % (function.name,)
José Fonseca669b1222011-02-20 09:05:10 +0000954 for arg in function.args:
955 assert not arg.output
José Fonsecab4a3d142011-10-27 07:43:19 +0100956 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
José Fonseca14c21bc2011-02-20 23:32:22 +0000957 if arg.name != 'pointer':
José Fonseca54f304a2012-01-14 19:33:08 +0000958 self.serializeValue(arg.type, arg.name)
José Fonseca14c21bc2011-02-20 23:32:22 +0000959 else:
José Fonseca632a78d2012-04-19 07:18:59 +0100960 print ' trace::localWriter.writeBlob((const void *)%s, _size);' % (arg.name)
José Fonsecab4a3d142011-10-27 07:43:19 +0100961 print ' trace::localWriter.endArg();'
José Fonseca99221832011-03-22 22:15:46 +0000962
José Fonsecab4a3d142011-10-27 07:43:19 +0100963 print ' trace::localWriter.endEnter();'
José Fonseca632a78d2012-04-19 07:18:59 +0100964 print ' trace::localWriter.beginLeave(_call);'
José Fonsecab4a3d142011-10-27 07:43:19 +0100965 print ' trace::localWriter.endLeave();'
José Fonseca99221832011-03-22 22:15:46 +0000966 print ' }'
José Fonseca669b1222011-02-20 09:05:10 +0000967 print ' }'
José Fonsecafb6744f2011-04-15 11:18:37 +0100968 self.array_epilog(api, uppercase_name)
969 self.array_trace_epilog(api, uppercase_name)
Chia-I Wub3d218d2011-11-03 01:37:36 +0800970 print ' }'
José Fonseca99221832011-03-22 22:15:46 +0000971 print
José Fonseca1a2fdd22011-04-01 00:55:09 +0100972
José Fonseca1601c412011-05-10 10:38:19 +0100973 # Samething, but for glVertexAttribPointer*
974 #
975 # Some variants of glVertexAttribPointer alias conventional and generic attributes:
976 # - glVertexAttribPointer: no
977 # - glVertexAttribPointerARB: implementation dependent
978 # - glVertexAttribPointerNV: yes
979 #
980 # This means that the implementations of these functions do not always
981 # alias, and they need to be considered independently.
982 #
Chia-I Wub3d218d2011-11-03 01:37:36 +0800983 print ' // ES1 does not support generic vertex attributes'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000984 print ' if (ctx->profile == gltrace::PROFILE_ES1)'
Chia-I Wub3d218d2011-11-03 01:37:36 +0800985 print ' return;'
986 print
José Fonseca632a78d2012-04-19 07:18:59 +0100987 print ' vertex_attrib _vertex_attrib = _get_vertex_attrib();'
José Fonseca5a568a92011-06-29 16:43:36 +0100988 print
José Fonseca74b661a2014-07-17 19:10:24 +0100989 for suffix in ['', 'NV']:
José Fonseca5a568a92011-06-29 16:43:36 +0100990 if suffix:
José Fonsecad94aaac2011-06-28 20:50:49 +0100991 SUFFIX = '_' + suffix
José Fonsecad94aaac2011-06-28 20:50:49 +0100992 else:
José Fonseca5a568a92011-06-29 16:43:36 +0100993 SUFFIX = suffix
José Fonseca1601c412011-05-10 10:38:19 +0100994 function_name = 'glVertexAttribPointer' + suffix
José Fonseca1b6c8752012-04-15 14:33:00 +0100995 function = api.getFunctionByName(function_name)
José Fonseca06e85192011-10-16 14:15:36 +0100996
997 print ' // %s' % function.prototype()
José Fonseca632a78d2012-04-19 07:18:59 +0100998 print ' if (_vertex_attrib == VERTEX_ATTRIB%s) {' % SUFFIX
José Fonseca5a568a92011-06-29 16:43:36 +0100999 if suffix == 'NV':
José Fonseca632a78d2012-04-19 07:18:59 +01001000 print ' GLint _max_vertex_attribs = 16;'
José Fonseca5a568a92011-06-29 16:43:36 +01001001 else:
José Fonseca26be8f92014-03-07 14:08:50 +00001002 print ' GLint _max_vertex_attribs = _glGetInteger(GL_MAX_VERTEX_ATTRIBS);'
José Fonseca632a78d2012-04-19 07:18:59 +01001003 print ' for (GLint index = 0; index < _max_vertex_attribs; ++index) {'
1004 print ' GLint _enabled = 0;'
José Fonseca5a568a92011-06-29 16:43:36 +01001005 if suffix == 'NV':
José Fonseca632a78d2012-04-19 07:18:59 +01001006 print ' _glGetIntegerv(GL_VERTEX_ATTRIB_ARRAY0_NV + index, &_enabled);'
José Fonseca5a568a92011-06-29 16:43:36 +01001007 else:
José Fonseca632a78d2012-04-19 07:18:59 +01001008 print ' _glGetVertexAttribiv%s(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED%s, &_enabled);' % (suffix, SUFFIX)
1009 print ' if (_enabled) {'
1010 print ' GLint _binding = 0;'
José Fonseca5a568a92011-06-29 16:43:36 +01001011 if suffix != 'NV':
1012 # It doesn't seem possible to use VBOs with NV_vertex_program.
José Fonseca632a78d2012-04-19 07:18:59 +01001013 print ' _glGetVertexAttribiv%s(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING%s, &_binding);' % (suffix, SUFFIX)
1014 print ' if (!_binding) {'
José Fonseca1a2fdd22011-04-01 00:55:09 +01001015
José Fonseca1601c412011-05-10 10:38:19 +01001016 # Get the arguments via glGet*
1017 for arg in function.args[1:]:
José Fonseca5a568a92011-06-29 16:43:36 +01001018 if suffix == 'NV':
1019 arg_get_enum = 'GL_ATTRIB_ARRAY_%s%s' % (arg.name.upper(), SUFFIX)
1020 else:
1021 arg_get_enum = 'GL_VERTEX_ATTRIB_ARRAY_%s%s' % (arg.name.upper(), SUFFIX)
José Fonsecac493e3e2011-06-29 12:57:06 +01001022 arg_get_function, arg_type = TypeGetter('glGetVertexAttrib', False, suffix).visit(arg.type)
José Fonseca5a568a92011-06-29 16:43:36 +01001023 print ' %s %s = 0;' % (arg_type, arg.name)
José Fonseca632a78d2012-04-19 07:18:59 +01001024 print ' _%s(index, %s, &%s);' % (arg_get_function, arg_get_enum, arg.name)
José Fonseca1601c412011-05-10 10:38:19 +01001025
1026 arg_names = ', '.join([arg.name for arg in function.args[1:-1]])
José Fonseca14cb9ef2012-05-17 21:33:14 +01001027 print ' size_t _size = _%s_size(%s, count);' % (function.name, arg_names)
José Fonseca1a2fdd22011-04-01 00:55:09 +01001028
José Fonseca1601c412011-05-10 10:38:19 +01001029 # Emit a fake function
José Fonseca7a5f23a2014-06-24 19:20:36 +01001030 print ' unsigned _call = trace::localWriter.beginEnter(&_%s_sig, true);' % (function.name,)
José Fonseca1601c412011-05-10 10:38:19 +01001031 for arg in function.args:
1032 assert not arg.output
José Fonsecab4a3d142011-10-27 07:43:19 +01001033 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
José Fonseca1601c412011-05-10 10:38:19 +01001034 if arg.name != 'pointer':
José Fonseca54f304a2012-01-14 19:33:08 +00001035 self.serializeValue(arg.type, arg.name)
José Fonseca1601c412011-05-10 10:38:19 +01001036 else:
José Fonseca632a78d2012-04-19 07:18:59 +01001037 print ' trace::localWriter.writeBlob((const void *)%s, _size);' % (arg.name)
José Fonsecab4a3d142011-10-27 07:43:19 +01001038 print ' trace::localWriter.endArg();'
José Fonseca1601c412011-05-10 10:38:19 +01001039
José Fonsecab4a3d142011-10-27 07:43:19 +01001040 print ' trace::localWriter.endEnter();'
José Fonseca632a78d2012-04-19 07:18:59 +01001041 print ' trace::localWriter.beginLeave(_call);'
José Fonsecab4a3d142011-10-27 07:43:19 +01001042 print ' trace::localWriter.endLeave();'
José Fonseca1601c412011-05-10 10:38:19 +01001043 print ' }'
1044 print ' }'
1045 print ' }'
1046 print ' }'
1047 print
José Fonseca1a2fdd22011-04-01 00:55:09 +01001048
José Fonseca8d1408b2014-02-03 19:57:18 +00001049 # Restore the original array_buffer
1050 print ' if (_array_buffer) {'
1051 self.fake_glBindBuffer(api, 'GL_ARRAY_BUFFER', '_array_buffer')
1052 print ' }'
1053 print
1054
José Fonseca669b1222011-02-20 09:05:10 +00001055 print '}'
1056 print
1057
José Fonsecafb6744f2011-04-15 11:18:37 +01001058 #
1059 # Hooks for glTexCoordPointer, which is identical to the other array
1060 # pointers except the fact that it is indexed by glClientActiveTexture.
1061 #
1062
1063 def array_prolog(self, api, uppercase_name):
1064 if uppercase_name == 'TEXTURE_COORD':
José Fonseca26be8f92014-03-07 14:08:50 +00001065 print ' GLint client_active_texture = _glGetInteger(GL_CLIENT_ACTIVE_TEXTURE);'
José Fonsecafb6744f2011-04-15 11:18:37 +01001066 print ' GLint max_texture_coords = 0;'
José Fonsecaf028a8f2012-02-15 23:33:35 +00001067 print ' if (ctx->profile == gltrace::PROFILE_COMPAT)'
José Fonseca632a78d2012-04-19 07:18:59 +01001068 print ' _glGetIntegerv(GL_MAX_TEXTURE_COORDS, &max_texture_coords);'
Chia-I Wub3d218d2011-11-03 01:37:36 +08001069 print ' else'
José Fonseca632a78d2012-04-19 07:18:59 +01001070 print ' _glGetIntegerv(GL_MAX_TEXTURE_UNITS, &max_texture_coords);'
José Fonsecafb6744f2011-04-15 11:18:37 +01001071 print ' for (GLint unit = 0; unit < max_texture_coords; ++unit) {'
José Fonseca7525e6f2011-09-28 09:04:56 +01001072 print ' GLint texture = GL_TEXTURE0 + unit;'
José Fonseca632a78d2012-04-19 07:18:59 +01001073 print ' _glClientActiveTexture(texture);'
José Fonsecafb6744f2011-04-15 11:18:37 +01001074
1075 def array_trace_prolog(self, api, uppercase_name):
1076 if uppercase_name == 'TEXTURE_COORD':
1077 print ' bool client_active_texture_dirty = false;'
1078
1079 def array_epilog(self, api, uppercase_name):
1080 if uppercase_name == 'TEXTURE_COORD':
1081 print ' }'
1082 self.array_cleanup(api, uppercase_name)
1083
1084 def array_cleanup(self, api, uppercase_name):
1085 if uppercase_name == 'TEXTURE_COORD':
José Fonseca632a78d2012-04-19 07:18:59 +01001086 print ' _glClientActiveTexture(client_active_texture);'
José Fonsecafb6744f2011-04-15 11:18:37 +01001087
1088 def array_trace_intermezzo(self, api, uppercase_name):
1089 if uppercase_name == 'TEXTURE_COORD':
1090 print ' if (texture != client_active_texture || client_active_texture_dirty) {'
1091 print ' client_active_texture_dirty = true;'
1092 self.fake_glClientActiveTexture_call(api, "texture");
1093 print ' }'
1094
1095 def array_trace_epilog(self, api, uppercase_name):
1096 if uppercase_name == 'TEXTURE_COORD':
1097 print ' if (client_active_texture_dirty) {'
1098 self.fake_glClientActiveTexture_call(api, "client_active_texture");
1099 print ' }'
1100
José Fonseca8d1408b2014-02-03 19:57:18 +00001101 def fake_glBindBuffer(self, api, target, buffer):
1102 function = api.getFunctionByName('glBindBuffer')
1103 self.fake_call(function, [target, buffer])
1104
José Fonsecafb6744f2011-04-15 11:18:37 +01001105 def fake_glClientActiveTexture_call(self, api, texture):
José Fonseca1b6c8752012-04-15 14:33:00 +01001106 function = api.getFunctionByName('glClientActiveTexture')
José Fonsecafb6744f2011-04-15 11:18:37 +01001107 self.fake_call(function, [texture])
1108
José Fonseca151c3702013-05-10 08:28:15 +01001109 def emitFakeTexture2D(self):
1110 function = glapi.glapi.getFunctionByName('glTexImage2D')
1111 instances = function.argNames()
José Fonseca7a5f23a2014-06-24 19:20:36 +01001112 print ' unsigned _fake_call = trace::localWriter.beginEnter(&_%s_sig, true);' % (function.name,)
José Fonseca151c3702013-05-10 08:28:15 +01001113 for arg in function.args:
1114 assert not arg.output
1115 self.serializeArg(function, arg)
1116 print ' trace::localWriter.endEnter();'
1117 print ' trace::localWriter.beginLeave(_fake_call);'
1118 print ' trace::localWriter.endLeave();'
José Fonsecafb6744f2011-04-15 11:18:37 +01001119
1120
1121
1122
1123
José Fonseca669b1222011-02-20 09:05:10 +00001124
1125
1126
1127
1128
1129