blob: 465c7088de69f7971c13449def7be25e04e9b845 [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é Fonsecac29f4f12011-06-11 12:19:05 +0100857 # Names of the functions that unpack from a pixel buffer object. See the
858 # ARB_pixel_buffer_object specification.
José Fonsecae97bab92011-06-02 23:15:11 +0100859 unpack_function_names = set([
860 'glBitmap',
José Fonsecac29f4f12011-06-11 12:19:05 +0100861 'glColorSubTable',
862 'glColorTable',
José Fonsecad2bd4ca2013-04-12 11:41:00 +0100863 'glCompressedMultiTexImage1DEXT',
864 'glCompressedMultiTexImage2DEXT',
865 'glCompressedMultiTexImage3DEXT',
866 'glCompressedMultiTexSubImage1DEXT',
867 'glCompressedMultiTexSubImage2DEXT',
868 'glCompressedMultiTexSubImage3DEXT',
José Fonsecac29f4f12011-06-11 12:19:05 +0100869 'glCompressedTexImage1D',
idinevdb5ad3b2014-02-03 15:50:39 +0000870 'glCompressedTexImage1DARB',
José Fonsecac29f4f12011-06-11 12:19:05 +0100871 'glCompressedTexImage2D',
idinevdb5ad3b2014-02-03 15:50:39 +0000872 'glCompressedTexImage2DARB',
José Fonsecac29f4f12011-06-11 12:19:05 +0100873 'glCompressedTexImage3D',
idinevdb5ad3b2014-02-03 15:50:39 +0000874 'glCompressedTexImage3DARB',
José Fonsecac29f4f12011-06-11 12:19:05 +0100875 'glCompressedTexSubImage1D',
idinevdb5ad3b2014-02-03 15:50:39 +0000876 'glCompressedTexSubImage1DARB',
José Fonsecac29f4f12011-06-11 12:19:05 +0100877 'glCompressedTexSubImage2D',
idinevdb5ad3b2014-02-03 15:50:39 +0000878 'glCompressedTexSubImage2DARB',
José Fonsecac29f4f12011-06-11 12:19:05 +0100879 'glCompressedTexSubImage3D',
idinevdb5ad3b2014-02-03 15:50:39 +0000880 'glCompressedTexSubImage3DARB',
José Fonseca4920c302014-08-13 18:35:57 +0100881 'glCompressedTextureImage1D',
José Fonsecad2bd4ca2013-04-12 11:41:00 +0100882 'glCompressedTextureImage1DEXT',
José Fonseca4920c302014-08-13 18:35:57 +0100883 'glCompressedTextureImage2D',
José Fonsecad2bd4ca2013-04-12 11:41:00 +0100884 'glCompressedTextureImage2DEXT',
José Fonseca4920c302014-08-13 18:35:57 +0100885 'glCompressedTextureImage3D',
José Fonsecad2bd4ca2013-04-12 11:41:00 +0100886 'glCompressedTextureImage3DEXT',
José Fonseca4920c302014-08-13 18:35:57 +0100887 'glCompressedTextureSubImage1D',
José Fonsecad2bd4ca2013-04-12 11:41:00 +0100888 'glCompressedTextureSubImage1DEXT',
José Fonseca4920c302014-08-13 18:35:57 +0100889 'glCompressedTextureSubImage2D',
José Fonsecad2bd4ca2013-04-12 11:41:00 +0100890 'glCompressedTextureSubImage2DEXT',
José Fonseca4920c302014-08-13 18:35:57 +0100891 'glCompressedTextureSubImage3D',
José Fonsecad2bd4ca2013-04-12 11:41:00 +0100892 'glCompressedTextureSubImage3DEXT',
José Fonsecac29f4f12011-06-11 12:19:05 +0100893 'glConvolutionFilter1D',
894 'glConvolutionFilter2D',
José Fonsecae97bab92011-06-02 23:15:11 +0100895 'glDrawPixels',
896 'glMultiTexImage1DEXT',
897 'glMultiTexImage2DEXT',
898 'glMultiTexImage3DEXT',
899 'glMultiTexSubImage1DEXT',
900 'glMultiTexSubImage2DEXT',
901 'glMultiTexSubImage3DEXT',
José Fonsecac29f4f12011-06-11 12:19:05 +0100902 'glPixelMapfv',
903 'glPixelMapuiv',
904 'glPixelMapusv',
José Fonsecae97bab92011-06-02 23:15:11 +0100905 'glPolygonStipple',
José Fonsecac29f4f12011-06-11 12:19:05 +0100906 'glSeparableFilter2D',
José Fonsecae97bab92011-06-02 23:15:11 +0100907 'glTexImage1D',
908 'glTexImage1DEXT',
909 'glTexImage2D',
910 'glTexImage2DEXT',
911 'glTexImage3D',
912 'glTexImage3DEXT',
913 'glTexSubImage1D',
914 'glTexSubImage1DEXT',
915 'glTexSubImage2D',
916 'glTexSubImage2DEXT',
917 'glTexSubImage3D',
918 'glTexSubImage3DEXT',
919 'glTextureImage1DEXT',
920 'glTextureImage2DEXT',
921 'glTextureImage3DEXT',
922 'glTextureSubImage1DEXT',
923 'glTextureSubImage2DEXT',
924 'glTextureSubImage3DEXT',
925 ])
926
José Fonseca54f304a2012-01-14 19:33:08 +0000927 def serializeArgValue(self, function, arg):
José Fonsecae97bab92011-06-02 23:15:11 +0100928 # Recognize offsets instead of blobs when a PBO is bound
929 if function.name in self.unpack_function_names \
930 and (isinstance(arg.type, stdapi.Blob) \
931 or (isinstance(arg.type, stdapi.Const) \
932 and isinstance(arg.type.type, stdapi.Blob))):
José Fonsecac29f4f12011-06-11 12:19:05 +0100933 print ' {'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000934 print ' gltrace::Context *ctx = gltrace::getContext();'
José Fonseca632a78d2012-04-19 07:18:59 +0100935 print ' GLint _unpack_buffer = 0;'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000936 print ' if (ctx->profile == gltrace::PROFILE_COMPAT)'
José Fonseca632a78d2012-04-19 07:18:59 +0100937 print ' _glGetIntegerv(GL_PIXEL_UNPACK_BUFFER_BINDING, &_unpack_buffer);'
938 print ' if (_unpack_buffer) {'
José Fonsecad559f022012-04-15 16:13:51 +0100939 print ' trace::localWriter.writePointer((uintptr_t)%s);' % arg.name
José Fonsecac29f4f12011-06-11 12:19:05 +0100940 print ' } else {'
José Fonseca54f304a2012-01-14 19:33:08 +0000941 Tracer.serializeArgValue(self, function, arg)
José Fonsecac29f4f12011-06-11 12:19:05 +0100942 print ' }'
José Fonsecae97bab92011-06-02 23:15:11 +0100943 print ' }'
944 return
945
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100946 # Several GL state functions take GLenum symbolic names as
947 # integer/floats; so dump the symbolic name whenever possible
José Fonseca3bcb33c2011-05-27 20:14:31 +0100948 if function.name.startswith('gl') \
José Fonsecae3571092011-10-13 08:26:27 +0100949 and arg.type in (glapi.GLint, glapi.GLfloat, glapi.GLdouble) \
José Fonseca3bcb33c2011-05-27 20:14:31 +0100950 and arg.name == 'param':
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100951 assert arg.index > 0
952 assert function.args[arg.index - 1].name == 'pname'
953 assert function.args[arg.index - 1].type == glapi.GLenum
954 print ' if (is_symbolic_pname(pname) && is_symbolic_param(%s)) {' % arg.name
José Fonseca54f304a2012-01-14 19:33:08 +0000955 self.serializeValue(glapi.GLenum, arg.name)
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100956 print ' } else {'
José Fonseca54f304a2012-01-14 19:33:08 +0000957 Tracer.serializeArgValue(self, function, arg)
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100958 print ' }'
959 return
960
José Fonseca54f304a2012-01-14 19:33:08 +0000961 Tracer.serializeArgValue(self, function, arg)
José Fonseca99221832011-03-22 22:15:46 +0000962
José Fonseca4c938c22011-04-30 22:44:38 +0100963 def footer(self, api):
964 Tracer.footer(self, api)
José Fonseca669b1222011-02-20 09:05:10 +0000965
José Fonseca4c938c22011-04-30 22:44:38 +0100966 # A simple state tracker to track the pointer values
José Fonseca669b1222011-02-20 09:05:10 +0000967 # update the state
José Fonseca14cb9ef2012-05-17 21:33:14 +0100968 print 'static void _trace_user_arrays(GLuint count)'
José Fonseca669b1222011-02-20 09:05:10 +0000969 print '{'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000970 print ' gltrace::Context *ctx = gltrace::getContext();'
José Fonseca8d1408b2014-02-03 19:57:18 +0000971 print
972
973 # Temporarily unbind the array buffer
José Fonseca26be8f92014-03-07 14:08:50 +0000974 print ' GLint _array_buffer = _glGetInteger(GL_ARRAY_BUFFER_BINDING);'
José Fonseca8d1408b2014-02-03 19:57:18 +0000975 print ' if (_array_buffer) {'
976 self.fake_glBindBuffer(api, 'GL_ARRAY_BUFFER', '0')
977 print ' }'
978 print
José Fonseca1a2fdd22011-04-01 00:55:09 +0100979
José Fonseca99221832011-03-22 22:15:46 +0000980 for camelcase_name, uppercase_name in self.arrays:
Chia-I Wub3d218d2011-11-03 01:37:36 +0800981 # in which profile is the array available?
José Fonsecaf028a8f2012-02-15 23:33:35 +0000982 profile_check = 'ctx->profile == gltrace::PROFILE_COMPAT'
Chia-I Wub3d218d2011-11-03 01:37:36 +0800983 if camelcase_name in self.arrays_es1:
José Fonsecaf028a8f2012-02-15 23:33:35 +0000984 profile_check = '(' + profile_check + ' || ctx->profile == gltrace::PROFILE_ES1)';
Chia-I Wub3d218d2011-11-03 01:37:36 +0800985
José Fonseca99221832011-03-22 22:15:46 +0000986 function_name = 'gl%sPointer' % camelcase_name
987 enable_name = 'GL_%s_ARRAY' % uppercase_name
988 binding_name = 'GL_%s_ARRAY_BUFFER_BINDING' % uppercase_name
José Fonseca1b6c8752012-04-15 14:33:00 +0100989 function = api.getFunctionByName(function_name)
José Fonseca99221832011-03-22 22:15:46 +0000990
José Fonseca06e85192011-10-16 14:15:36 +0100991 print ' // %s' % function.prototype()
Chia-I Wub3d218d2011-11-03 01:37:36 +0800992 print ' if (%s) {' % profile_check
José Fonsecafb6744f2011-04-15 11:18:37 +0100993 self.array_trace_prolog(api, uppercase_name)
994 self.array_prolog(api, uppercase_name)
José Fonseca632a78d2012-04-19 07:18:59 +0100995 print ' if (_glIsEnabled(%s)) {' % enable_name
José Fonseca26be8f92014-03-07 14:08:50 +0000996 print ' GLint _binding = _glGetInteger(%s);' % binding_name
José Fonseca632a78d2012-04-19 07:18:59 +0100997 print ' if (!_binding) {'
José Fonseca99221832011-03-22 22:15:46 +0000998
999 # Get the arguments via glGet*
1000 for arg in function.args:
1001 arg_get_enum = 'GL_%s_ARRAY_%s' % (uppercase_name, arg.name.upper())
1002 arg_get_function, arg_type = TypeGetter().visit(arg.type)
José Fonseca7f5163e2011-03-31 23:37:26 +01001003 print ' %s %s = 0;' % (arg_type, arg.name)
José Fonseca632a78d2012-04-19 07:18:59 +01001004 print ' _%s(%s, &%s);' % (arg_get_function, arg_get_enum, arg.name)
José Fonseca99221832011-03-22 22:15:46 +00001005
1006 arg_names = ', '.join([arg.name for arg in function.args[:-1]])
José Fonseca14cb9ef2012-05-17 21:33:14 +01001007 print ' size_t _size = _%s_size(%s, count);' % (function.name, arg_names)
José Fonseca99221832011-03-22 22:15:46 +00001008
1009 # Emit a fake function
José Fonsecafb6744f2011-04-15 11:18:37 +01001010 self.array_trace_intermezzo(api, uppercase_name)
José Fonseca7a5f23a2014-06-24 19:20:36 +01001011 print ' unsigned _call = trace::localWriter.beginEnter(&_%s_sig, true);' % (function.name,)
José Fonseca669b1222011-02-20 09:05:10 +00001012 for arg in function.args:
1013 assert not arg.output
José Fonsecab4a3d142011-10-27 07:43:19 +01001014 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
José Fonseca14c21bc2011-02-20 23:32:22 +00001015 if arg.name != 'pointer':
José Fonseca54f304a2012-01-14 19:33:08 +00001016 self.serializeValue(arg.type, arg.name)
José Fonseca14c21bc2011-02-20 23:32:22 +00001017 else:
José Fonseca632a78d2012-04-19 07:18:59 +01001018 print ' trace::localWriter.writeBlob((const void *)%s, _size);' % (arg.name)
José Fonsecab4a3d142011-10-27 07:43:19 +01001019 print ' trace::localWriter.endArg();'
José Fonseca99221832011-03-22 22:15:46 +00001020
José Fonsecab4a3d142011-10-27 07:43:19 +01001021 print ' trace::localWriter.endEnter();'
José Fonseca632a78d2012-04-19 07:18:59 +01001022 print ' trace::localWriter.beginLeave(_call);'
José Fonsecab4a3d142011-10-27 07:43:19 +01001023 print ' trace::localWriter.endLeave();'
José Fonseca99221832011-03-22 22:15:46 +00001024 print ' }'
José Fonseca669b1222011-02-20 09:05:10 +00001025 print ' }'
José Fonsecafb6744f2011-04-15 11:18:37 +01001026 self.array_epilog(api, uppercase_name)
1027 self.array_trace_epilog(api, uppercase_name)
Chia-I Wub3d218d2011-11-03 01:37:36 +08001028 print ' }'
José Fonseca99221832011-03-22 22:15:46 +00001029 print
José Fonseca1a2fdd22011-04-01 00:55:09 +01001030
José Fonseca1601c412011-05-10 10:38:19 +01001031 # Samething, but for glVertexAttribPointer*
1032 #
1033 # Some variants of glVertexAttribPointer alias conventional and generic attributes:
1034 # - glVertexAttribPointer: no
1035 # - glVertexAttribPointerARB: implementation dependent
1036 # - glVertexAttribPointerNV: yes
1037 #
1038 # This means that the implementations of these functions do not always
1039 # alias, and they need to be considered independently.
1040 #
Chia-I Wub3d218d2011-11-03 01:37:36 +08001041 print ' // ES1 does not support generic vertex attributes'
José Fonsecaf028a8f2012-02-15 23:33:35 +00001042 print ' if (ctx->profile == gltrace::PROFILE_ES1)'
Chia-I Wub3d218d2011-11-03 01:37:36 +08001043 print ' return;'
1044 print
José Fonseca632a78d2012-04-19 07:18:59 +01001045 print ' vertex_attrib _vertex_attrib = _get_vertex_attrib();'
José Fonseca5a568a92011-06-29 16:43:36 +01001046 print
José Fonseca74b661a2014-07-17 19:10:24 +01001047 for suffix in ['', 'NV']:
José Fonseca5a568a92011-06-29 16:43:36 +01001048 if suffix:
José Fonsecad94aaac2011-06-28 20:50:49 +01001049 SUFFIX = '_' + suffix
José Fonsecad94aaac2011-06-28 20:50:49 +01001050 else:
José Fonseca5a568a92011-06-29 16:43:36 +01001051 SUFFIX = suffix
José Fonseca1601c412011-05-10 10:38:19 +01001052 function_name = 'glVertexAttribPointer' + suffix
José Fonseca1b6c8752012-04-15 14:33:00 +01001053 function = api.getFunctionByName(function_name)
José Fonseca06e85192011-10-16 14:15:36 +01001054
1055 print ' // %s' % function.prototype()
José Fonseca632a78d2012-04-19 07:18:59 +01001056 print ' if (_vertex_attrib == VERTEX_ATTRIB%s) {' % SUFFIX
José Fonseca5a568a92011-06-29 16:43:36 +01001057 if suffix == 'NV':
José Fonseca632a78d2012-04-19 07:18:59 +01001058 print ' GLint _max_vertex_attribs = 16;'
José Fonseca5a568a92011-06-29 16:43:36 +01001059 else:
José Fonseca26be8f92014-03-07 14:08:50 +00001060 print ' GLint _max_vertex_attribs = _glGetInteger(GL_MAX_VERTEX_ATTRIBS);'
José Fonseca632a78d2012-04-19 07:18:59 +01001061 print ' for (GLint index = 0; index < _max_vertex_attribs; ++index) {'
1062 print ' GLint _enabled = 0;'
José Fonseca5a568a92011-06-29 16:43:36 +01001063 if suffix == 'NV':
José Fonseca632a78d2012-04-19 07:18:59 +01001064 print ' _glGetIntegerv(GL_VERTEX_ATTRIB_ARRAY0_NV + index, &_enabled);'
José Fonseca5a568a92011-06-29 16:43:36 +01001065 else:
José Fonseca632a78d2012-04-19 07:18:59 +01001066 print ' _glGetVertexAttribiv%s(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED%s, &_enabled);' % (suffix, SUFFIX)
1067 print ' if (_enabled) {'
1068 print ' GLint _binding = 0;'
José Fonseca5a568a92011-06-29 16:43:36 +01001069 if suffix != 'NV':
1070 # It doesn't seem possible to use VBOs with NV_vertex_program.
José Fonseca632a78d2012-04-19 07:18:59 +01001071 print ' _glGetVertexAttribiv%s(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING%s, &_binding);' % (suffix, SUFFIX)
1072 print ' if (!_binding) {'
José Fonseca1a2fdd22011-04-01 00:55:09 +01001073
José Fonseca1601c412011-05-10 10:38:19 +01001074 # Get the arguments via glGet*
1075 for arg in function.args[1:]:
José Fonseca5a568a92011-06-29 16:43:36 +01001076 if suffix == 'NV':
1077 arg_get_enum = 'GL_ATTRIB_ARRAY_%s%s' % (arg.name.upper(), SUFFIX)
1078 else:
1079 arg_get_enum = 'GL_VERTEX_ATTRIB_ARRAY_%s%s' % (arg.name.upper(), SUFFIX)
José Fonsecac493e3e2011-06-29 12:57:06 +01001080 arg_get_function, arg_type = TypeGetter('glGetVertexAttrib', False, suffix).visit(arg.type)
José Fonseca5a568a92011-06-29 16:43:36 +01001081 print ' %s %s = 0;' % (arg_type, arg.name)
José Fonseca632a78d2012-04-19 07:18:59 +01001082 print ' _%s(index, %s, &%s);' % (arg_get_function, arg_get_enum, arg.name)
José Fonseca1601c412011-05-10 10:38:19 +01001083
1084 arg_names = ', '.join([arg.name for arg in function.args[1:-1]])
José Fonseca14cb9ef2012-05-17 21:33:14 +01001085 print ' size_t _size = _%s_size(%s, count);' % (function.name, arg_names)
José Fonseca1a2fdd22011-04-01 00:55:09 +01001086
José Fonseca1601c412011-05-10 10:38:19 +01001087 # Emit a fake function
José Fonseca7a5f23a2014-06-24 19:20:36 +01001088 print ' unsigned _call = trace::localWriter.beginEnter(&_%s_sig, true);' % (function.name,)
José Fonseca1601c412011-05-10 10:38:19 +01001089 for arg in function.args:
1090 assert not arg.output
José Fonsecab4a3d142011-10-27 07:43:19 +01001091 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
José Fonseca1601c412011-05-10 10:38:19 +01001092 if arg.name != 'pointer':
José Fonseca54f304a2012-01-14 19:33:08 +00001093 self.serializeValue(arg.type, arg.name)
José Fonseca1601c412011-05-10 10:38:19 +01001094 else:
José Fonseca632a78d2012-04-19 07:18:59 +01001095 print ' trace::localWriter.writeBlob((const void *)%s, _size);' % (arg.name)
José Fonsecab4a3d142011-10-27 07:43:19 +01001096 print ' trace::localWriter.endArg();'
José Fonseca1601c412011-05-10 10:38:19 +01001097
José Fonsecab4a3d142011-10-27 07:43:19 +01001098 print ' trace::localWriter.endEnter();'
José Fonseca632a78d2012-04-19 07:18:59 +01001099 print ' trace::localWriter.beginLeave(_call);'
José Fonsecab4a3d142011-10-27 07:43:19 +01001100 print ' trace::localWriter.endLeave();'
José Fonseca1601c412011-05-10 10:38:19 +01001101 print ' }'
1102 print ' }'
1103 print ' }'
1104 print ' }'
1105 print
José Fonseca1a2fdd22011-04-01 00:55:09 +01001106
José Fonseca8d1408b2014-02-03 19:57:18 +00001107 # Restore the original array_buffer
1108 print ' if (_array_buffer) {'
1109 self.fake_glBindBuffer(api, 'GL_ARRAY_BUFFER', '_array_buffer')
1110 print ' }'
1111 print
1112
José Fonseca669b1222011-02-20 09:05:10 +00001113 print '}'
1114 print
1115
José Fonsecafb6744f2011-04-15 11:18:37 +01001116 #
1117 # Hooks for glTexCoordPointer, which is identical to the other array
1118 # pointers except the fact that it is indexed by glClientActiveTexture.
1119 #
1120
1121 def array_prolog(self, api, uppercase_name):
1122 if uppercase_name == 'TEXTURE_COORD':
José Fonseca26be8f92014-03-07 14:08:50 +00001123 print ' GLint client_active_texture = _glGetInteger(GL_CLIENT_ACTIVE_TEXTURE);'
José Fonsecafb6744f2011-04-15 11:18:37 +01001124 print ' GLint max_texture_coords = 0;'
José Fonsecaf028a8f2012-02-15 23:33:35 +00001125 print ' if (ctx->profile == gltrace::PROFILE_COMPAT)'
José Fonseca632a78d2012-04-19 07:18:59 +01001126 print ' _glGetIntegerv(GL_MAX_TEXTURE_COORDS, &max_texture_coords);'
Chia-I Wub3d218d2011-11-03 01:37:36 +08001127 print ' else'
José Fonseca632a78d2012-04-19 07:18:59 +01001128 print ' _glGetIntegerv(GL_MAX_TEXTURE_UNITS, &max_texture_coords);'
José Fonsecafb6744f2011-04-15 11:18:37 +01001129 print ' for (GLint unit = 0; unit < max_texture_coords; ++unit) {'
José Fonseca7525e6f2011-09-28 09:04:56 +01001130 print ' GLint texture = GL_TEXTURE0 + unit;'
José Fonseca632a78d2012-04-19 07:18:59 +01001131 print ' _glClientActiveTexture(texture);'
José Fonsecafb6744f2011-04-15 11:18:37 +01001132
1133 def array_trace_prolog(self, api, uppercase_name):
1134 if uppercase_name == 'TEXTURE_COORD':
1135 print ' bool client_active_texture_dirty = false;'
1136
1137 def array_epilog(self, api, uppercase_name):
1138 if uppercase_name == 'TEXTURE_COORD':
1139 print ' }'
1140 self.array_cleanup(api, uppercase_name)
1141
1142 def array_cleanup(self, api, uppercase_name):
1143 if uppercase_name == 'TEXTURE_COORD':
José Fonseca632a78d2012-04-19 07:18:59 +01001144 print ' _glClientActiveTexture(client_active_texture);'
José Fonsecafb6744f2011-04-15 11:18:37 +01001145
1146 def array_trace_intermezzo(self, api, uppercase_name):
1147 if uppercase_name == 'TEXTURE_COORD':
1148 print ' if (texture != client_active_texture || client_active_texture_dirty) {'
1149 print ' client_active_texture_dirty = true;'
1150 self.fake_glClientActiveTexture_call(api, "texture");
1151 print ' }'
1152
1153 def array_trace_epilog(self, api, uppercase_name):
1154 if uppercase_name == 'TEXTURE_COORD':
1155 print ' if (client_active_texture_dirty) {'
1156 self.fake_glClientActiveTexture_call(api, "client_active_texture");
1157 print ' }'
1158
José Fonseca8d1408b2014-02-03 19:57:18 +00001159 def fake_glBindBuffer(self, api, target, buffer):
1160 function = api.getFunctionByName('glBindBuffer')
1161 self.fake_call(function, [target, buffer])
1162
José Fonsecafb6744f2011-04-15 11:18:37 +01001163 def fake_glClientActiveTexture_call(self, api, texture):
José Fonseca1b6c8752012-04-15 14:33:00 +01001164 function = api.getFunctionByName('glClientActiveTexture')
José Fonsecafb6744f2011-04-15 11:18:37 +01001165 self.fake_call(function, [texture])
1166
José Fonseca151c3702013-05-10 08:28:15 +01001167 def emitFakeTexture2D(self):
1168 function = glapi.glapi.getFunctionByName('glTexImage2D')
1169 instances = function.argNames()
José Fonseca7a5f23a2014-06-24 19:20:36 +01001170 print ' unsigned _fake_call = trace::localWriter.beginEnter(&_%s_sig, true);' % (function.name,)
José Fonseca151c3702013-05-10 08:28:15 +01001171 for arg in function.args:
1172 assert not arg.output
1173 self.serializeArg(function, arg)
1174 print ' trace::localWriter.endEnter();'
1175 print ' trace::localWriter.beginLeave(_fake_call);'
1176 print ' trace::localWriter.endLeave();'
José Fonsecafb6744f2011-04-15 11:18:37 +01001177
1178
1179
1180
1181
José Fonseca669b1222011-02-20 09:05:10 +00001182
1183
1184
1185
1186
1187