blob: 26edb30aae8230b099cd140691d71a10088b2d1f [file] [log] [blame]
José Fonseca669b1222011-02-20 09:05:10 +00001##########################################################################
2#
3# Copyright 2008-2010 VMware, Inc.
4# All Rights Reserved.
5#
6# Permission is hereby granted, free of charge, to any person obtaining a copy
7# of this software and associated documentation files (the "Software"), to deal
8# in the Software without restriction, including without limitation the rights
9# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10# copies of the Software, and to permit persons to whom the Software is
11# furnished to do so, subject to the following conditions:
12#
13# The above copyright notice and this permission notice shall be included in
14# all copies or substantial portions of the Software.
15#
16# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22# THE SOFTWARE.
23#
24##########################################################################/
25
26
27"""GL tracing generator."""
28
29
José Fonseca452d3252012-04-14 15:55:40 +010030from trace import Tracer
José Fonseca1b6c8752012-04-15 14:33:00 +010031from dispatch import function_pointer_type, function_pointer_value
José Fonsecabd86a222011-09-27 09:21:38 +010032import specs.stdapi as stdapi
33import specs.glapi as glapi
34import specs.glparams as glparams
35from specs.glxapi import glxapi
José Fonseca669b1222011-02-20 09:05:10 +000036
37
José Fonseca99221832011-03-22 22:15:46 +000038class TypeGetter(stdapi.Visitor):
39 '''Determine which glGet*v function that matches the specified type.'''
40
José Fonsecac493e3e2011-06-29 12:57:06 +010041 def __init__(self, prefix = 'glGet', long_suffix = True, ext_suffix = ''):
José Fonseca1a2fdd22011-04-01 00:55:09 +010042 self.prefix = prefix
43 self.long_suffix = long_suffix
José Fonsecac493e3e2011-06-29 12:57:06 +010044 self.ext_suffix = ext_suffix
José Fonseca1a2fdd22011-04-01 00:55:09 +010045
José Fonseca54f304a2012-01-14 19:33:08 +000046 def visitConst(self, const):
José Fonseca99221832011-03-22 22:15:46 +000047 return self.visit(const.type)
48
José Fonseca54f304a2012-01-14 19:33:08 +000049 def visitAlias(self, alias):
José Fonseca99221832011-03-22 22:15:46 +000050 if alias.expr == 'GLboolean':
José Fonseca1a2fdd22011-04-01 00:55:09 +010051 if self.long_suffix:
José Fonsecac493e3e2011-06-29 12:57:06 +010052 suffix = 'Booleanv'
53 arg_type = alias.expr
José Fonseca1a2fdd22011-04-01 00:55:09 +010054 else:
José Fonsecac493e3e2011-06-29 12:57:06 +010055 suffix = 'iv'
56 arg_type = 'GLint'
José Fonseca99221832011-03-22 22:15:46 +000057 elif alias.expr == 'GLdouble':
José Fonseca1a2fdd22011-04-01 00:55:09 +010058 if self.long_suffix:
José Fonsecac493e3e2011-06-29 12:57:06 +010059 suffix = 'Doublev'
60 arg_type = alias.expr
José Fonseca1a2fdd22011-04-01 00:55:09 +010061 else:
José Fonsecac493e3e2011-06-29 12:57:06 +010062 suffix = 'dv'
63 arg_type = alias.expr
José Fonseca99221832011-03-22 22:15:46 +000064 elif alias.expr == 'GLfloat':
José Fonseca1a2fdd22011-04-01 00:55:09 +010065 if self.long_suffix:
José Fonsecac493e3e2011-06-29 12:57:06 +010066 suffix = 'Floatv'
67 arg_type = alias.expr
José Fonseca1a2fdd22011-04-01 00:55:09 +010068 else:
José Fonsecac493e3e2011-06-29 12:57:06 +010069 suffix = 'fv'
70 arg_type = alias.expr
José Fonseca7f5163e2011-03-31 23:37:26 +010071 elif alias.expr in ('GLint', 'GLuint', 'GLsizei'):
José Fonseca1a2fdd22011-04-01 00:55:09 +010072 if self.long_suffix:
José Fonsecac493e3e2011-06-29 12:57:06 +010073 suffix = 'Integerv'
74 arg_type = 'GLint'
José Fonseca1a2fdd22011-04-01 00:55:09 +010075 else:
José Fonsecac493e3e2011-06-29 12:57:06 +010076 suffix = 'iv'
77 arg_type = 'GLint'
José Fonseca99221832011-03-22 22:15:46 +000078 else:
79 print alias.expr
80 assert False
José Fonsecac493e3e2011-06-29 12:57:06 +010081 function_name = self.prefix + suffix + self.ext_suffix
82 return function_name, arg_type
José Fonseca99221832011-03-22 22:15:46 +000083
José Fonseca54f304a2012-01-14 19:33:08 +000084 def visitEnum(self, enum):
José Fonseca1a2fdd22011-04-01 00:55:09 +010085 return self.visit(glapi.GLint)
José Fonseca99221832011-03-22 22:15:46 +000086
José Fonseca54f304a2012-01-14 19:33:08 +000087 def visitBitmask(self, bitmask):
José Fonseca1a2fdd22011-04-01 00:55:09 +010088 return self.visit(glapi.GLint)
José Fonseca99221832011-03-22 22:15:46 +000089
José Fonseca54f304a2012-01-14 19:33:08 +000090 def visitOpaque(self, pointer):
José Fonsecac493e3e2011-06-29 12:57:06 +010091 return self.prefix + 'Pointerv' + self.ext_suffix, 'GLvoid *'
José Fonseca99221832011-03-22 22:15:46 +000092
93
José Fonseca669b1222011-02-20 09:05:10 +000094class GlTracer(Tracer):
95
José Fonseca99221832011-03-22 22:15:46 +000096 arrays = [
97 ("Vertex", "VERTEX"),
98 ("Normal", "NORMAL"),
99 ("Color", "COLOR"),
100 ("Index", "INDEX"),
101 ("TexCoord", "TEXTURE_COORD"),
102 ("EdgeFlag", "EDGE_FLAG"),
103 ("FogCoord", "FOG_COORD"),
104 ("SecondaryColor", "SECONDARY_COLOR"),
José Fonseca14c21bc2011-02-20 23:32:22 +0000105 ]
José Fonsecac9f12232011-03-25 20:07:42 +0000106 arrays.reverse()
José Fonseca669b1222011-02-20 09:05:10 +0000107
Chia-I Wub3d218d2011-11-03 01:37:36 +0800108 # arrays available in PROFILE_ES1
109 arrays_es1 = ("Vertex", "Normal", "Color", "TexCoord")
110
José Fonseca4c938c22011-04-30 22:44:38 +0100111 def header(self, api):
112 Tracer.header(self, api)
113
José Fonseca707630d2014-03-07 14:20:35 +0000114 print '#include <algorithm>'
115 print
José Fonseca1b3d3752011-07-15 10:15:19 +0100116 print '#include "gltrace.hpp"'
117 print
José Fonseca5a568a92011-06-29 16:43:36 +0100118
119 # Which glVertexAttrib* variant to use
120 print 'enum vertex_attrib {'
121 print ' VERTEX_ATTRIB,'
122 print ' VERTEX_ATTRIB_ARB,'
123 print ' VERTEX_ATTRIB_NV,'
124 print '};'
125 print
José Fonseca632a78d2012-04-19 07:18:59 +0100126 print 'static vertex_attrib _get_vertex_attrib(void) {'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000127 print ' gltrace::Context *ctx = gltrace::getContext();'
Chia-I Wu8ef66972011-11-03 01:19:46 +0800128 print ' if (ctx->user_arrays_arb || ctx->user_arrays_nv) {'
José Fonseca632a78d2012-04-19 07:18:59 +0100129 print ' GLboolean _vertex_program = GL_FALSE;'
130 print ' _glGetBooleanv(GL_VERTEX_PROGRAM_ARB, &_vertex_program);'
131 print ' if (_vertex_program) {'
Chia-I Wu8ef66972011-11-03 01:19:46 +0800132 print ' if (ctx->user_arrays_nv) {'
José Fonseca26be8f92014-03-07 14:08:50 +0000133 print ' GLint _vertex_program_binding_nv = _glGetInteger(GL_VERTEX_PROGRAM_BINDING_NV);'
José Fonseca632a78d2012-04-19 07:18:59 +0100134 print ' if (_vertex_program_binding_nv) {'
José Fonseca5a568a92011-06-29 16:43:36 +0100135 print ' return VERTEX_ATTRIB_NV;'
136 print ' }'
137 print ' }'
138 print ' return VERTEX_ATTRIB_ARB;'
139 print ' }'
140 print ' }'
141 print ' return VERTEX_ATTRIB;'
142 print '}'
143 print
144
Imre Deakd4937372012-04-24 14:06:48 +0300145 self.defineShadowBufferHelper()
146
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000147 # Whether we need user arrays
José Fonseca632a78d2012-04-19 07:18:59 +0100148 print 'static inline bool _need_user_arrays(void)'
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000149 print '{'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000150 print ' gltrace::Context *ctx = gltrace::getContext();'
Chia-I Wu8ef66972011-11-03 01:19:46 +0800151 print ' if (!ctx->user_arrays) {'
José Fonseca25ebe542011-04-24 10:08:22 +0100152 print ' return false;'
153 print ' }'
154 print
José Fonseca1a2fdd22011-04-01 00:55:09 +0100155
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000156 for camelcase_name, uppercase_name in self.arrays:
Chia-I Wub3d218d2011-11-03 01:37:36 +0800157 # in which profile is the array available?
José Fonsecaf028a8f2012-02-15 23:33:35 +0000158 profile_check = 'ctx->profile == gltrace::PROFILE_COMPAT'
Chia-I Wub3d218d2011-11-03 01:37:36 +0800159 if camelcase_name in self.arrays_es1:
José Fonsecaf028a8f2012-02-15 23:33:35 +0000160 profile_check = '(' + profile_check + ' || ctx->profile == gltrace::PROFILE_ES1)';
Chia-I Wub3d218d2011-11-03 01:37:36 +0800161
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000162 function_name = 'gl%sPointer' % camelcase_name
163 enable_name = 'GL_%s_ARRAY' % uppercase_name
164 binding_name = 'GL_%s_ARRAY_BUFFER_BINDING' % uppercase_name
165 print ' // %s' % function_name
Chia-I Wub3d218d2011-11-03 01:37:36 +0800166 print ' if (%s) {' % profile_check
José Fonsecafb6744f2011-04-15 11:18:37 +0100167 self.array_prolog(api, uppercase_name)
José Fonseca632a78d2012-04-19 07:18:59 +0100168 print ' if (_glIsEnabled(%s)) {' % enable_name
José Fonseca26be8f92014-03-07 14:08:50 +0000169 print ' GLint _binding = _glGetInteger(%s);' % binding_name
José Fonseca632a78d2012-04-19 07:18:59 +0100170 print ' if (!_binding) {'
José Fonsecafb6744f2011-04-15 11:18:37 +0100171 self.array_cleanup(api, uppercase_name)
José Fonseca7f5163e2011-03-31 23:37:26 +0100172 print ' return true;'
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000173 print ' }'
174 print ' }'
José Fonsecafb6744f2011-04-15 11:18:37 +0100175 self.array_epilog(api, uppercase_name)
Chia-I Wub3d218d2011-11-03 01:37:36 +0800176 print ' }'
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000177 print
José Fonseca7f5163e2011-03-31 23:37:26 +0100178
Chia-I Wub3d218d2011-11-03 01:37:36 +0800179 print ' // ES1 does not support generic vertex attributes'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000180 print ' if (ctx->profile == gltrace::PROFILE_ES1)'
Chia-I Wub3d218d2011-11-03 01:37:36 +0800181 print ' return false;'
182 print
José Fonseca632a78d2012-04-19 07:18:59 +0100183 print ' vertex_attrib _vertex_attrib = _get_vertex_attrib();'
José Fonseca5a568a92011-06-29 16:43:36 +0100184 print
185 print ' // glVertexAttribPointer'
José Fonseca632a78d2012-04-19 07:18:59 +0100186 print ' if (_vertex_attrib == VERTEX_ATTRIB) {'
José Fonseca26be8f92014-03-07 14:08:50 +0000187 print ' GLint _max_vertex_attribs = _glGetInteger(GL_MAX_VERTEX_ATTRIBS);'
José Fonseca632a78d2012-04-19 07:18:59 +0100188 print ' for (GLint index = 0; index < _max_vertex_attribs; ++index) {'
189 print ' GLint _enabled = 0;'
190 print ' _glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &_enabled);'
191 print ' if (_enabled) {'
192 print ' GLint _binding = 0;'
193 print ' _glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &_binding);'
194 print ' if (!_binding) {'
José Fonseca5a568a92011-06-29 16:43:36 +0100195 print ' return true;'
196 print ' }'
197 print ' }'
198 print ' }'
199 print ' }'
200 print
201 print ' // glVertexAttribPointerARB'
José Fonseca632a78d2012-04-19 07:18:59 +0100202 print ' if (_vertex_attrib == VERTEX_ATTRIB_ARB) {'
José Fonseca26be8f92014-03-07 14:08:50 +0000203 print ' GLint _max_vertex_attribs = _glGetInteger(GL_MAX_VERTEX_ATTRIBS_ARB);'
José Fonseca632a78d2012-04-19 07:18:59 +0100204 print ' for (GLint index = 0; index < _max_vertex_attribs; ++index) {'
205 print ' GLint _enabled = 0;'
206 print ' _glGetVertexAttribivARB(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB, &_enabled);'
207 print ' if (_enabled) {'
208 print ' GLint _binding = 0;'
209 print ' _glGetVertexAttribivARB(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB, &_binding);'
210 print ' if (!_binding) {'
José Fonsecad94aaac2011-06-28 20:50:49 +0100211 print ' return true;'
212 print ' }'
213 print ' }'
214 print ' }'
José Fonseca5a568a92011-06-29 16:43:36 +0100215 print ' }'
216 print
217 print ' // glVertexAttribPointerNV'
José Fonseca632a78d2012-04-19 07:18:59 +0100218 print ' if (_vertex_attrib == VERTEX_ATTRIB_NV) {'
José Fonseca5a568a92011-06-29 16:43:36 +0100219 print ' for (GLint index = 0; index < 16; ++index) {'
José Fonseca26be8f92014-03-07 14:08:50 +0000220 print ' GLboolean _enabled = _glIsEnabled(GL_VERTEX_ATTRIB_ARRAY0_NV);'
José Fonseca632a78d2012-04-19 07:18:59 +0100221 print ' if (_enabled) {'
José Fonseca5a568a92011-06-29 16:43:36 +0100222 print ' return true;'
José Fonseca1a2fdd22011-04-01 00:55:09 +0100223 print ' }'
224 print ' }'
225 print ' }'
226 print
227
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000228 print ' return false;'
229 print '}'
230 print
José Fonseca669b1222011-02-20 09:05:10 +0000231
José Fonseca14cb9ef2012-05-17 21:33:14 +0100232 print 'static void _trace_user_arrays(GLuint count);'
José Fonseca14c21bc2011-02-20 23:32:22 +0000233 print
José Fonseca867b1b72011-04-24 11:58:04 +0100234
José Fonseca707630d2014-03-07 14:20:35 +0000235 print '// whether glLockArraysEXT() has ever been called'
236 print 'static bool _checkLockArraysEXT = false;'
237 print
238
José Fonseca9c536b02012-02-29 20:54:13 +0000239 # Buffer mappings
240 print '// whether glMapBufferRange(GL_MAP_WRITE_BIT) has ever been called'
José Fonseca632a78d2012-04-19 07:18:59 +0100241 print 'static bool _checkBufferMapRange = false;'
José Fonseca9c536b02012-02-29 20:54:13 +0000242 print
243 print '// whether glBufferParameteriAPPLE(GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE) has ever been called'
José Fonseca632a78d2012-04-19 07:18:59 +0100244 print 'static bool _checkBufferFlushingUnmapAPPLE = false;'
José Fonseca9c536b02012-02-29 20:54:13 +0000245 print
246 # Buffer mapping information, necessary for old Mesa 2.1 drivers which
247 # do not support glGetBufferParameteriv(GL_BUFFER_ACCESS_FLAGS/GL_BUFFER_MAP_LENGTH)
José Fonseca867b1b72011-04-24 11:58:04 +0100248 print 'struct buffer_mapping {'
249 print ' void *map;'
250 print ' GLint length;'
251 print ' bool write;'
José Fonseca73373602011-05-20 17:45:26 +0100252 print ' bool explicit_flush;'
José Fonseca867b1b72011-04-24 11:58:04 +0100253 print '};'
254 print
255 for target in self.buffer_targets:
José Fonseca632a78d2012-04-19 07:18:59 +0100256 print 'struct buffer_mapping _%s_mapping;' % target.lower();
José Fonseca867b1b72011-04-24 11:58:04 +0100257 print
258 print 'static inline struct buffer_mapping *'
259 print 'get_buffer_mapping(GLenum target) {'
José Fonseca06e85192011-10-16 14:15:36 +0100260 print ' switch (target) {'
José Fonseca867b1b72011-04-24 11:58:04 +0100261 for target in self.buffer_targets:
262 print ' case GL_%s:' % target
José Fonseca632a78d2012-04-19 07:18:59 +0100263 print ' return & _%s_mapping;' % target.lower()
José Fonseca867b1b72011-04-24 11:58:04 +0100264 print ' default:'
José Fonseca559d5342011-10-27 08:10:56 +0100265 print ' os::log("apitrace: warning: unknown buffer target 0x%04X\\n", target);'
José Fonseca867b1b72011-04-24 11:58:04 +0100266 print ' return NULL;'
267 print ' }'
268 print '}'
269 print
270
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100271 # Generate a helper function to determine whether a parameter name
272 # refers to a symbolic value or not
273 print 'static bool'
274 print 'is_symbolic_pname(GLenum pname) {'
José Fonseca06e85192011-10-16 14:15:36 +0100275 print ' switch (pname) {'
José Fonseca5ea91872011-05-04 09:41:55 +0100276 for function, type, count, name in glparams.parameters:
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100277 if type is glapi.GLenum:
José Fonseca4c938c22011-04-30 22:44:38 +0100278 print ' case %s:' % name
279 print ' return true;'
280 print ' default:'
281 print ' return false;'
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100282 print ' }'
283 print '}'
284 print
285
286 # Generate a helper function to determine whether a parameter value is
287 # potentially symbolic or not; i.e., if the value can be represented in
288 # an enum or not
289 print 'template<class T>'
290 print 'static inline bool'
291 print 'is_symbolic_param(T param) {'
292 print ' return static_cast<T>(static_cast<GLenum>(param)) == param;'
293 print '}'
294 print
José Fonseca4c938c22011-04-30 22:44:38 +0100295
296 # Generate a helper function to know how many elements a parameter has
297 print 'static size_t'
José Fonseca632a78d2012-04-19 07:18:59 +0100298 print '_gl_param_size(GLenum pname) {'
José Fonseca06e85192011-10-16 14:15:36 +0100299 print ' switch (pname) {'
José Fonseca5ea91872011-05-04 09:41:55 +0100300 for function, type, count, name in glparams.parameters:
José Fonseca4c938c22011-04-30 22:44:38 +0100301 if type is not None:
José Fonsecaddf6d2c2012-12-20 15:34:50 +0000302 print ' case %s: return %s;' % (name, count)
José Fonseca4c938c22011-04-30 22:44:38 +0100303 print ' default:'
José Fonseca559d5342011-10-27 08:10:56 +0100304 print r' os::log("apitrace: warning: %s: unknown GLenum 0x%04X\n", __FUNCTION__, pname);'
José Fonseca4c938c22011-04-30 22:44:38 +0100305 print ' return 1;'
306 print ' }'
307 print '}'
308 print
309
Chia-I Wu335efb42011-11-03 01:59:22 +0800310 # states such as GL_UNPACK_ROW_LENGTH are not available in GLES
311 print 'static inline bool'
312 print 'can_unpack_subimage(void) {'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000313 print ' gltrace::Context *ctx = gltrace::getContext();'
314 print ' return (ctx->profile == gltrace::PROFILE_COMPAT);'
Chia-I Wu335efb42011-11-03 01:59:22 +0800315 print '}'
316 print
317
José Fonseca1b6c8752012-04-15 14:33:00 +0100318 getProcAddressFunctionNames = []
319
320 def traceApi(self, api):
321 if self.getProcAddressFunctionNames:
322 # Generate a function to wrap proc addresses
323 getProcAddressFunction = api.getFunctionByName(self.getProcAddressFunctionNames[0])
324 argType = getProcAddressFunction.args[0].type
325 retType = getProcAddressFunction.type
326
327 print 'static %s _wrapProcAddress(%s procName, %s procPtr);' % (retType, argType, retType)
328 print
329
330 Tracer.traceApi(self, api)
331
332 print 'static %s _wrapProcAddress(%s procName, %s procPtr) {' % (retType, argType, retType)
Peter Lohrmann0b5b75e2013-06-03 14:58:41 -0700333
334 # Provide fallback functions to missing debug functions
José Fonseca1b6c8752012-04-15 14:33:00 +0100335 print ' if (!procPtr) {'
Peter Lohrmann0b5b75e2013-06-03 14:58:41 -0700336 else_ = ''
337 for function_name in self.debug_functions:
338 if self.api.getFunctionByName(function_name):
339 print ' %sif (strcmp("%s", (const char *)procName) == 0) {' % (else_, function_name)
340 print ' return (%s)&%s;' % (retType, function_name)
341 print ' }'
342 else_ = 'else '
343 print ' %s{' % else_
344 print ' return NULL;'
345 print ' }'
José Fonseca1b6c8752012-04-15 14:33:00 +0100346 print ' }'
Peter Lohrmann0b5b75e2013-06-03 14:58:41 -0700347
José Fonseca81301932012-11-11 00:10:20 +0000348 for function in api.getAllFunctions():
José Fonseca1b6c8752012-04-15 14:33:00 +0100349 ptype = function_pointer_type(function)
350 pvalue = function_pointer_value(function)
351 print ' if (strcmp("%s", (const char *)procName) == 0) {' % function.name
352 print ' %s = (%s)procPtr;' % (pvalue, ptype)
353 print ' return (%s)&%s;' % (retType, function.name,)
354 print ' }'
355 print ' os::log("apitrace: warning: unknown function \\"%s\\"\\n", (const char *)procName);'
356 print ' return procPtr;'
357 print '}'
358 print
359 else:
360 Tracer.traceApi(self, api)
361
Imre Deakd4937372012-04-24 14:06:48 +0300362 def defineShadowBufferHelper(self):
363 print 'void _shadow_glGetBufferSubData(GLenum target, GLintptr offset,'
364 print ' GLsizeiptr size, GLvoid *data)'
365 print '{'
José Fonsecaa33d0bb2012-11-10 09:11:42 +0000366 print ' gltrace::Context *ctx = gltrace::getContext();'
Imre Deakd4937372012-04-24 14:06:48 +0300367 print ' if (!ctx->needsShadowBuffers() || target != GL_ELEMENT_ARRAY_BUFFER) {'
José Fonseca219c9f22012-11-03 10:13:17 +0000368 print ' _glGetBufferSubData(target, offset, size, data);'
Imre Deakd4937372012-04-24 14:06:48 +0300369 print ' return;'
370 print ' }'
371 print
José Fonseca26be8f92014-03-07 14:08:50 +0000372 print ' GLint buffer_binding = _glGetInteger(GL_ELEMENT_ARRAY_BUFFER_BINDING);'
José Fonseca219c9f22012-11-03 10:13:17 +0000373 print ' if (buffer_binding > 0) {'
374 print ' gltrace::Buffer & buf = ctx->buffers[buffer_binding];'
375 print ' buf.getSubData(offset, size, data);'
376 print ' }'
Imre Deakd4937372012-04-24 14:06:48 +0300377 print '}'
378
José Fonseca219c9f22012-11-03 10:13:17 +0000379 def shadowBufferMethod(self, method):
380 # Emit code to fetch the shadow buffer, and invoke a method
381 print ' gltrace::Context *ctx = gltrace::getContext();'
382 print ' if (ctx->needsShadowBuffers() && target == GL_ELEMENT_ARRAY_BUFFER) {'
José Fonseca26be8f92014-03-07 14:08:50 +0000383 print ' GLint buffer_binding = _glGetInteger(GL_ELEMENT_ARRAY_BUFFER_BINDING);'
José Fonseca219c9f22012-11-03 10:13:17 +0000384 print ' if (buffer_binding > 0) {'
385 print ' gltrace::Buffer & buf = ctx->buffers[buffer_binding];'
386 print ' buf.' + method + ';'
387 print ' }'
388 print ' }'
389 print
390
Imre Deakd4937372012-04-24 14:06:48 +0300391 def shadowBufferProlog(self, function):
392 if function.name == 'glBufferData':
José Fonseca219c9f22012-11-03 10:13:17 +0000393 self.shadowBufferMethod('bufferData(size, data)')
Imre Deakd4937372012-04-24 14:06:48 +0300394
395 if function.name == 'glBufferSubData':
José Fonseca219c9f22012-11-03 10:13:17 +0000396 self.shadowBufferMethod('bufferSubData(offset, size, data)')
Imre Deakd4937372012-04-24 14:06:48 +0300397
398 if function.name == 'glDeleteBuffers':
399 print ' gltrace::Context *ctx = gltrace::getContext();'
400 print ' if (ctx->needsShadowBuffers()) {'
José Fonseca219c9f22012-11-03 10:13:17 +0000401 print ' for (GLsizei i = 0; i < n; i++) {'
402 print ' ctx->buffers.erase(buffer[i]);'
Imre Deakd4937372012-04-24 14:06:48 +0300403 print ' }'
404 print ' }'
405
José Fonseca99221832011-03-22 22:15:46 +0000406 array_pointer_function_names = set((
407 "glVertexPointer",
408 "glNormalPointer",
409 "glColorPointer",
410 "glIndexPointer",
411 "glTexCoordPointer",
412 "glEdgeFlagPointer",
413 "glFogCoordPointer",
414 "glSecondaryColorPointer",
José Fonseca7f5163e2011-03-31 23:37:26 +0100415
José Fonsecaac5285b2011-05-04 11:09:08 +0100416 "glInterleavedArrays",
417
José Fonseca7e0bfd92011-04-30 23:09:03 +0100418 "glVertexPointerEXT",
419 "glNormalPointerEXT",
420 "glColorPointerEXT",
421 "glIndexPointerEXT",
422 "glTexCoordPointerEXT",
423 "glEdgeFlagPointerEXT",
424 "glFogCoordPointerEXT",
425 "glSecondaryColorPointerEXT",
José Fonseca99221832011-03-22 22:15:46 +0000426
José Fonseca7f5163e2011-03-31 23:37:26 +0100427 "glVertexAttribPointer",
428 "glVertexAttribPointerARB",
429 "glVertexAttribPointerNV",
José Fonsecaac5285b2011-05-04 11:09:08 +0100430 "glVertexAttribIPointer",
431 "glVertexAttribIPointerEXT",
José Fonseca7f5163e2011-03-31 23:37:26 +0100432 "glVertexAttribLPointer",
433 "glVertexAttribLPointerEXT",
José Fonseca99221832011-03-22 22:15:46 +0000434
435 #"glMatrixIndexPointerARB",
436 ))
437
438 draw_function_names = set((
439 'glDrawArrays',
440 'glDrawElements',
441 'glDrawRangeElements',
José Fonseca5c749e32011-05-09 11:11:37 +0100442 'glMultiDrawArrays',
443 'glMultiDrawElements',
444 'glDrawArraysInstanced',
José Fonsecaff8848b2011-10-09 01:04:17 +0100445 "glDrawArraysInstancedBaseInstance",
José Fonseca5c749e32011-05-09 11:11:37 +0100446 'glDrawElementsInstanced',
447 'glDrawArraysInstancedARB',
448 'glDrawElementsInstancedARB',
449 'glDrawElementsBaseVertex',
450 'glDrawRangeElementsBaseVertex',
451 'glDrawElementsInstancedBaseVertex',
José Fonsecaff8848b2011-10-09 01:04:17 +0100452 "glDrawElementsInstancedBaseInstance",
453 "glDrawElementsInstancedBaseVertexBaseInstance",
José Fonseca5c749e32011-05-09 11:11:37 +0100454 'glMultiDrawElementsBaseVertex',
455 'glDrawArraysIndirect',
456 'glDrawElementsIndirect',
José Fonseca29ac7c72013-04-14 15:40:01 +0100457 'glMultiDrawArraysIndirect',
458 'glMultiDrawArraysIndirectAMD',
459 'glMultiDrawElementsIndirect',
460 'glMultiDrawElementsIndirectAMD',
José Fonseca5c749e32011-05-09 11:11:37 +0100461 'glDrawArraysEXT',
José Fonseca7e0bfd92011-04-30 23:09:03 +0100462 'glDrawRangeElementsEXT',
José Fonseca5c749e32011-05-09 11:11:37 +0100463 'glDrawRangeElementsEXT_size',
464 'glMultiDrawArraysEXT',
465 'glMultiDrawElementsEXT',
466 'glMultiModeDrawArraysIBM',
467 'glMultiModeDrawElementsIBM',
468 'glDrawArraysInstancedEXT',
469 'glDrawElementsInstancedEXT',
José Fonseca99221832011-03-22 22:15:46 +0000470 ))
471
José Fonsecac9f12232011-03-25 20:07:42 +0000472 interleaved_formats = [
473 'GL_V2F',
474 'GL_V3F',
475 'GL_C4UB_V2F',
476 'GL_C4UB_V3F',
477 'GL_C3F_V3F',
478 'GL_N3F_V3F',
479 'GL_C4F_N3F_V3F',
480 'GL_T2F_V3F',
481 'GL_T4F_V4F',
482 'GL_T2F_C4UB_V3F',
483 'GL_T2F_C3F_V3F',
484 'GL_T2F_N3F_V3F',
485 'GL_T2F_C4F_N3F_V3F',
486 'GL_T4F_C4F_N3F_V4F',
487 ]
488
José Fonseca54f304a2012-01-14 19:33:08 +0000489 def traceFunctionImplBody(self, function):
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000490 # Defer tracing of user array pointers...
José Fonseca99221832011-03-22 22:15:46 +0000491 if function.name in self.array_pointer_function_names:
José Fonseca26be8f92014-03-07 14:08:50 +0000492 print ' GLint _array_buffer = _glGetInteger(GL_ARRAY_BUFFER_BINDING);'
José Fonseca632a78d2012-04-19 07:18:59 +0100493 print ' if (!_array_buffer) {'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000494 print ' gltrace::Context *ctx = gltrace::getContext();'
Chia-I Wu8ef66972011-11-03 01:19:46 +0800495 print ' ctx->user_arrays = true;'
José Fonseca5a568a92011-06-29 16:43:36 +0100496 if function.name == "glVertexAttribPointerARB":
Chia-I Wu8ef66972011-11-03 01:19:46 +0800497 print ' ctx->user_arrays_arb = true;'
José Fonseca5a568a92011-06-29 16:43:36 +0100498 if function.name == "glVertexAttribPointerNV":
Chia-I Wu8ef66972011-11-03 01:19:46 +0800499 print ' ctx->user_arrays_nv = true;'
José Fonseca54f304a2012-01-14 19:33:08 +0000500 self.invokeFunction(function)
José Fonsecaac5285b2011-05-04 11:09:08 +0100501
502 # And also break down glInterleavedArrays into the individual calls
503 if function.name == 'glInterleavedArrays':
504 print
505
506 # Initialize the enable flags
507 for camelcase_name, uppercase_name in self.arrays:
José Fonseca632a78d2012-04-19 07:18:59 +0100508 flag_name = '_' + uppercase_name.lower()
José Fonsecaac5285b2011-05-04 11:09:08 +0100509 print ' GLboolean %s = GL_FALSE;' % flag_name
510 print
511
512 # Switch for the interleaved formats
513 print ' switch (format) {'
514 for format in self.interleaved_formats:
515 print ' case %s:' % format
516 for camelcase_name, uppercase_name in self.arrays:
José Fonseca632a78d2012-04-19 07:18:59 +0100517 flag_name = '_' + uppercase_name.lower()
José Fonsecaac5285b2011-05-04 11:09:08 +0100518 if format.find('_' + uppercase_name[0]) >= 0:
519 print ' %s = GL_TRUE;' % flag_name
520 print ' break;'
521 print ' default:'
522 print ' return;'
523 print ' }'
524 print
525
526 # Emit fake glEnableClientState/glDisableClientState flags
527 for camelcase_name, uppercase_name in self.arrays:
José Fonseca632a78d2012-04-19 07:18:59 +0100528 flag_name = '_' + uppercase_name.lower()
José Fonsecaac5285b2011-05-04 11:09:08 +0100529 enable_name = 'GL_%s_ARRAY' % uppercase_name
530
531 # Emit a fake function
532 print ' {'
José Fonseca632a78d2012-04-19 07:18:59 +0100533 print ' static const trace::FunctionSig &_sig = %s ? _glEnableClientState_sig : _glDisableClientState_sig;' % flag_name
534 print ' unsigned _call = trace::localWriter.beginEnter(&_sig);'
José Fonsecab4a3d142011-10-27 07:43:19 +0100535 print ' trace::localWriter.beginArg(0);'
José Fonseca54f304a2012-01-14 19:33:08 +0000536 self.serializeValue(glapi.GLenum, enable_name)
José Fonsecab4a3d142011-10-27 07:43:19 +0100537 print ' trace::localWriter.endArg();'
538 print ' trace::localWriter.endEnter();'
José Fonseca632a78d2012-04-19 07:18:59 +0100539 print ' trace::localWriter.beginLeave(_call);'
José Fonsecab4a3d142011-10-27 07:43:19 +0100540 print ' trace::localWriter.endLeave();'
José Fonsecaac5285b2011-05-04 11:09:08 +0100541 print ' }'
542
José Fonsecac629a8c2014-06-01 21:12:27 +0100543 # Warn about buggy glGet(GL_*ARRAY_SIZE) not returning GL_BGRA
544 buggyFunctions = {
545 'glColorPointer': ('glGetIntegerv', '', 'GL_COLOR_ARRAY_SIZE'),
546 'glSecondaryColorPointer': ('glGetIntegerv', '', 'GL_SECONDARY_COLOR_ARRAY_SIZE'),
547 'glVertexAttribPointer': ('glGetVertexAttribiv', 'index, ', 'GL_VERTEX_ATTRIB_ARRAY_SIZE'),
548 'glVertexAttribPointerARB': ('glGetVertexAttribivARB', 'index, ', 'GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB'),
549 }
550 if function.name in buggyFunctions:
551 getter, extraArg, pname = buggyFunctions[function.name]
552 print r' static bool _checked = false;'
553 print r' if (!_checked && size == GL_BGRA) {'
554 print r' GLint _size = 0;'
555 print r' _%s(%s%s, &_size);' % (getter, extraArg, pname)
556 print r' if (_size != GL_BGRA) {'
557 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)
558 print r' }'
559 print r' _checked = true;'
560 print r' }'
561
José Fonseca99221832011-03-22 22:15:46 +0000562 print ' return;'
563 print ' }'
José Fonseca14c21bc2011-02-20 23:32:22 +0000564
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000565 # ... to the draw calls
José Fonseca99221832011-03-22 22:15:46 +0000566 if function.name in self.draw_function_names:
José Fonseca632a78d2012-04-19 07:18:59 +0100567 print ' if (_need_user_arrays()) {'
José Fonseca99221832011-03-22 22:15:46 +0000568 arg_names = ', '.join([arg.name for arg in function.args[1:]])
José Fonseca14cb9ef2012-05-17 21:33:14 +0100569 print ' GLuint _count = _%s_count(%s);' % (function.name, arg_names)
José Fonseca707630d2014-03-07 14:20:35 +0000570 # Some apps, in particular Quake3, can tell the driver to lock more
571 # vertices than those actually required for the draw call.
572 print ' if (_checkLockArraysEXT) {'
573 print ' GLuint _locked_count = _glGetInteger(GL_ARRAY_ELEMENT_LOCK_FIRST_EXT)'
574 print ' + _glGetInteger(GL_ARRAY_ELEMENT_LOCK_COUNT_EXT);'
575 print ' _count = std::max(_count, _locked_count);'
576 print ' }'
José Fonseca14cb9ef2012-05-17 21:33:14 +0100577 print ' _trace_user_arrays(_count);'
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000578 print ' }'
José Fonseca707630d2014-03-07 14:20:35 +0000579 if function.name == 'glLockArraysEXT':
580 print ' _checkLockArraysEXT = true;'
José Fonseca14c21bc2011-02-20 23:32:22 +0000581
José Fonseca73373602011-05-20 17:45:26 +0100582 # Emit a fake memcpy on buffer uploads
José Fonseca9c536b02012-02-29 20:54:13 +0000583 if function.name == 'glBufferParameteriAPPLE':
584 print ' if (pname == GL_BUFFER_FLUSHING_UNMAP_APPLE && param == GL_FALSE) {'
José Fonseca632a78d2012-04-19 07:18:59 +0100585 print ' _checkBufferFlushingUnmapAPPLE = true;'
José Fonseca9c536b02012-02-29 20:54:13 +0000586 print ' }'
José Fonsecacdc322c2012-02-29 19:29:51 +0000587 if function.name in ('glUnmapBuffer', 'glUnmapBufferARB'):
José Fonseca9c536b02012-02-29 20:54:13 +0000588 if function.name.endswith('ARB'):
589 suffix = 'ARB'
590 else:
591 suffix = ''
592 print ' GLint access = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100593 print ' _glGetBufferParameteriv%s(target, GL_BUFFER_ACCESS, &access);' % suffix
José Fonseca9c536b02012-02-29 20:54:13 +0000594 print ' if (access != GL_READ_ONLY) {'
595 print ' GLvoid *map = NULL;'
José Fonseca632a78d2012-04-19 07:18:59 +0100596 print ' _glGetBufferPointerv%s(target, GL_BUFFER_MAP_POINTER, &map);' % suffix
José Fonseca9c536b02012-02-29 20:54:13 +0000597 print ' if (map) {'
598 print ' GLint length = -1;'
599 print ' bool flush = true;'
José Fonseca632a78d2012-04-19 07:18:59 +0100600 print ' if (_checkBufferMapRange) {'
601 print ' _glGetBufferParameteriv%s(target, GL_BUFFER_MAP_LENGTH, &length);' % suffix
José Fonseca9c536b02012-02-29 20:54:13 +0000602 print ' GLint access_flags = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100603 print ' _glGetBufferParameteriv(target, GL_BUFFER_ACCESS_FLAGS, &access_flags);'
José Fonseca9c536b02012-02-29 20:54:13 +0000604 print ' flush = flush && !(access_flags & GL_MAP_FLUSH_EXPLICIT_BIT);'
605 print ' if (length == -1) {'
José Fonsecacb07e2d2014-02-04 15:14:09 +0000606 print ' // Mesa drivers refuse GL_BUFFER_MAP_LENGTH without GL 3.0 up-to'
607 print ' // http://cgit.freedesktop.org/mesa/mesa/commit/?id=ffee498fb848b253a7833373fe5430f8c7ca0c5f'
José Fonsecadb1ccce2012-02-29 21:09:24 +0000608 print ' static bool warned = false;'
609 print ' if (!warned) {'
610 print ' os::log("apitrace: warning: glGetBufferParameteriv%s(GL_BUFFER_MAP_LENGTH) failed\\n");' % suffix
611 print ' warned = true;'
612 print ' }'
José Fonseca9c536b02012-02-29 20:54:13 +0000613 print ' struct buffer_mapping *mapping = get_buffer_mapping(target);'
614 print ' if (mapping) {'
615 print ' length = mapping->length;'
616 print ' flush = flush && !mapping->explicit_flush;'
617 print ' } else {'
618 print ' length = 0;'
619 print ' flush = false;'
620 print ' }'
621 print ' }'
622 print ' } else {'
623 print ' length = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100624 print ' _glGetBufferParameteriv%s(target, GL_BUFFER_SIZE, &length);' % suffix
José Fonseca9c536b02012-02-29 20:54:13 +0000625 print ' }'
José Fonseca632a78d2012-04-19 07:18:59 +0100626 print ' if (_checkBufferFlushingUnmapAPPLE) {'
José Fonseca9c536b02012-02-29 20:54:13 +0000627 print ' GLint flushing_unmap = GL_TRUE;'
José Fonseca632a78d2012-04-19 07:18:59 +0100628 print ' _glGetBufferParameteriv%s(target, GL_BUFFER_FLUSHING_UNMAP_APPLE, &flushing_unmap);' % suffix
José Fonseca9c536b02012-02-29 20:54:13 +0000629 print ' flush = flush && flushing_unmap;'
630 print ' }'
631 print ' if (flush && length > 0) {'
632 self.emit_memcpy('map', 'map', 'length')
633 print ' }'
634 print ' }'
635 print ' }'
José Fonsecacdc322c2012-02-29 19:29:51 +0000636 if function.name == 'glUnmapBufferOES':
637 print ' GLint access = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100638 print ' _glGetBufferParameteriv(target, GL_BUFFER_ACCESS_OES, &access);'
José Fonsecacdc322c2012-02-29 19:29:51 +0000639 print ' if (access == GL_WRITE_ONLY_OES) {'
640 print ' GLvoid *map = NULL;'
José Fonseca632a78d2012-04-19 07:18:59 +0100641 print ' _glGetBufferPointervOES(target, GL_BUFFER_MAP_POINTER_OES, &map);'
José Fonsecacdc322c2012-02-29 19:29:51 +0000642 print ' GLint size = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100643 print ' _glGetBufferParameteriv(target, GL_BUFFER_SIZE, &size);'
José Fonsecacdc322c2012-02-29 19:29:51 +0000644 print ' if (map && size > 0) {'
645 self.emit_memcpy('map', 'map', 'size')
José Fonseca219c9f22012-11-03 10:13:17 +0000646 self.shadowBufferMethod('bufferSubData(0, size, map)')
José Fonsecacdc322c2012-02-29 19:29:51 +0000647 print ' }'
José Fonseca867b1b72011-04-24 11:58:04 +0100648 print ' }'
José Fonsecafb3bd602012-01-15 13:56:28 +0000649 if function.name == 'glUnmapNamedBufferEXT':
José Fonseca024aff42012-02-29 18:00:06 +0000650 print ' GLint access_flags = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100651 print ' _glGetNamedBufferParameterivEXT(buffer, GL_BUFFER_ACCESS_FLAGS, &access_flags);'
José Fonseca024aff42012-02-29 18:00:06 +0000652 print ' if ((access_flags & GL_MAP_WRITE_BIT) && !(access_flags & GL_MAP_FLUSH_EXPLICIT_BIT)) {'
José Fonsecafb3bd602012-01-15 13:56:28 +0000653 print ' GLvoid *map = NULL;'
José Fonseca632a78d2012-04-19 07:18:59 +0100654 print ' _glGetNamedBufferPointervEXT(buffer, GL_BUFFER_MAP_POINTER, &map);'
José Fonsecafb3bd602012-01-15 13:56:28 +0000655 print ' GLint length = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100656 print ' _glGetNamedBufferParameterivEXT(buffer, GL_BUFFER_MAP_LENGTH, &length);'
José Fonseca024aff42012-02-29 18:00:06 +0000657 print ' if (map && length > 0) {'
José Fonsecafb3bd602012-01-15 13:56:28 +0000658 self.emit_memcpy('map', 'map', 'length')
José Fonseca024aff42012-02-29 18:00:06 +0000659 print ' }'
José Fonsecafb3bd602012-01-15 13:56:28 +0000660 print ' }'
José Fonseca77ef0ce2012-02-29 18:08:48 +0000661 if function.name == 'glFlushMappedBufferRange':
662 print ' GLvoid *map = NULL;'
José Fonseca632a78d2012-04-19 07:18:59 +0100663 print ' _glGetBufferPointerv(target, GL_BUFFER_MAP_POINTER, &map);'
José Fonseca77ef0ce2012-02-29 18:08:48 +0000664 print ' if (map && length > 0) {'
665 self.emit_memcpy('(char *)map + offset', '(const char *)map + offset', 'length')
666 print ' }'
667 if function.name == 'glFlushMappedBufferRangeAPPLE':
668 print ' GLvoid *map = NULL;'
José Fonseca632a78d2012-04-19 07:18:59 +0100669 print ' _glGetBufferPointerv(target, GL_BUFFER_MAP_POINTER, &map);'
José Fonseca77ef0ce2012-02-29 18:08:48 +0000670 print ' if (map && size > 0) {'
671 self.emit_memcpy('(char *)map + offset', '(const char *)map + offset', 'size')
José Fonseca73373602011-05-20 17:45:26 +0100672 print ' }'
José Fonsecafb3bd602012-01-15 13:56:28 +0000673 if function.name == 'glFlushMappedNamedBufferRangeEXT':
674 print ' GLvoid *map = NULL;'
José Fonseca632a78d2012-04-19 07:18:59 +0100675 print ' _glGetNamedBufferPointervEXT(buffer, GL_BUFFER_MAP_POINTER, &map);'
José Fonseca024aff42012-02-29 18:00:06 +0000676 print ' if (map && length > 0) {'
José Fonsecafb3bd602012-01-15 13:56:28 +0000677 self.emit_memcpy('(char *)map + offset', '(const char *)map + offset', 'length')
678 print ' }'
José Fonseca867b1b72011-04-24 11:58:04 +0100679
José Fonseca3522cbd2014-02-28 14:45:32 +0000680 # FIXME: We don't support coherent/pinned memory mappings
681 # See https://github.com/apitrace/apitrace/issues/232
682 if function.name in ('glBufferStorage', 'glNamedBufferStorageEXT'):
683 print r' if (flags & GL_MAP_COHERENT_BIT) {'
684 print r' os::log("apitrace: warning: coherent mappings not fully supported\n");'
685 print r' }'
686 if function.name in ('glBufferData', 'glBufferDataARB'):
687 print r' if (target == GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD) {'
688 print r' os::log("apitrace: warning: GL_AMD_pinned_memory not fully supported\n");'
689 print r' }'
690
José Fonseca91492d22011-05-23 21:20:31 +0100691 # Don't leave vertex attrib locations to chance. Instead emit fake
692 # glBindAttribLocation calls to ensure that the same locations will be
693 # used when retracing. Trying to remap locations after the fact would
694 # be an herculian task given that vertex attrib locations appear in
695 # many entry-points, including non-shader related ones.
696 if function.name == 'glLinkProgram':
José Fonseca54f304a2012-01-14 19:33:08 +0000697 Tracer.invokeFunction(self, function)
José Fonseca91492d22011-05-23 21:20:31 +0100698 print ' GLint active_attributes = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100699 print ' _glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &active_attributes);'
José Fonseca7525e6f2011-09-28 09:04:56 +0100700 print ' for (GLint attrib = 0; attrib < active_attributes; ++attrib) {'
José Fonseca91492d22011-05-23 21:20:31 +0100701 print ' GLint size = 0;'
702 print ' GLenum type = 0;'
703 print ' GLchar name[256];'
704 # TODO: Use ACTIVE_ATTRIBUTE_MAX_LENGTH instead of 256
José Fonseca632a78d2012-04-19 07:18:59 +0100705 print ' _glGetActiveAttrib(program, attrib, sizeof name, NULL, &size, &type, name);'
José Fonseca2a794f52011-05-26 20:54:29 +0100706 print " if (name[0] != 'g' || name[1] != 'l' || name[2] != '_') {"
José Fonseca632a78d2012-04-19 07:18:59 +0100707 print ' GLint location = _glGetAttribLocation(program, name);'
José Fonseca2a794f52011-05-26 20:54:29 +0100708 print ' if (location >= 0) {'
José Fonseca1b6c8752012-04-15 14:33:00 +0100709 bind_function = glapi.glapi.getFunctionByName('glBindAttribLocation')
José Fonseca91492d22011-05-23 21:20:31 +0100710 self.fake_call(bind_function, ['program', 'location', 'name'])
José Fonseca2a794f52011-05-26 20:54:29 +0100711 print ' }'
José Fonseca91492d22011-05-23 21:20:31 +0100712 print ' }'
713 print ' }'
714 if function.name == 'glLinkProgramARB':
José Fonseca54f304a2012-01-14 19:33:08 +0000715 Tracer.invokeFunction(self, function)
José Fonseca91492d22011-05-23 21:20:31 +0100716 print ' GLint active_attributes = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100717 print ' _glGetObjectParameterivARB(programObj, GL_OBJECT_ACTIVE_ATTRIBUTES_ARB, &active_attributes);'
José Fonseca7525e6f2011-09-28 09:04:56 +0100718 print ' for (GLint attrib = 0; attrib < active_attributes; ++attrib) {'
José Fonseca91492d22011-05-23 21:20:31 +0100719 print ' GLint size = 0;'
720 print ' GLenum type = 0;'
721 print ' GLcharARB name[256];'
722 # TODO: Use ACTIVE_ATTRIBUTE_MAX_LENGTH instead of 256
José Fonseca632a78d2012-04-19 07:18:59 +0100723 print ' _glGetActiveAttribARB(programObj, attrib, sizeof name, NULL, &size, &type, name);'
José Fonseca2a794f52011-05-26 20:54:29 +0100724 print " if (name[0] != 'g' || name[1] != 'l' || name[2] != '_') {"
José Fonseca632a78d2012-04-19 07:18:59 +0100725 print ' GLint location = _glGetAttribLocationARB(programObj, name);'
José Fonseca2a794f52011-05-26 20:54:29 +0100726 print ' if (location >= 0) {'
José Fonseca1b6c8752012-04-15 14:33:00 +0100727 bind_function = glapi.glapi.getFunctionByName('glBindAttribLocationARB')
José Fonseca91492d22011-05-23 21:20:31 +0100728 self.fake_call(bind_function, ['programObj', 'location', 'name'])
José Fonseca2a794f52011-05-26 20:54:29 +0100729 print ' }'
José Fonseca91492d22011-05-23 21:20:31 +0100730 print ' }'
731 print ' }'
732
Imre Deakd4937372012-04-24 14:06:48 +0300733 self.shadowBufferProlog(function)
734
José Fonseca54f304a2012-01-14 19:33:08 +0000735 Tracer.traceFunctionImplBody(self, function)
José Fonseca73373602011-05-20 17:45:26 +0100736
Peter Lohrmann0b5b75e2013-06-03 14:58:41 -0700737 # These entrypoints are only expected to be implemented by tools;
738 # drivers will probably not implement them.
José Fonsecaf028a8f2012-02-15 23:33:35 +0000739 marker_functions = [
740 # GL_GREMEDY_string_marker
José Fonseca8f34d342011-07-15 20:16:40 +0100741 'glStringMarkerGREMEDY',
José Fonsecaf028a8f2012-02-15 23:33:35 +0000742 # GL_GREMEDY_frame_terminator
José Fonseca8f34d342011-07-15 20:16:40 +0100743 'glFrameTerminatorGREMEDY',
José Fonsecaf028a8f2012-02-15 23:33:35 +0000744 # GL_EXT_debug_marker
745 'glInsertEventMarkerEXT',
746 'glPushGroupMarkerEXT',
747 'glPopGroupMarkerEXT',
José Fonseca8f34d342011-07-15 20:16:40 +0100748 ]
749
Peter Lohrmann0b5b75e2013-06-03 14:58:41 -0700750 # These entrypoints may be implemented by drivers, but are also very useful
751 # for debugging / analysis tools.
752 debug_functions = [
753 # GL_KHR_debug
754 'glDebugMessageControl',
755 'glDebugMessageInsert',
756 'glDebugMessageCallback',
757 'glGetDebugMessageLog',
758 'glPushDebugGroup',
759 'glPopDebugGroup',
760 'glObjectLabel',
761 'glGetObjectLabel',
762 'glObjectPtrLabel',
763 'glGetObjectPtrLabel',
764 # GL_ARB_debug_output
765 'glDebugMessageControlARB',
766 'glDebugMessageInsertARB',
767 'glDebugMessageCallbackARB',
768 'glGetDebugMessageLogARB',
769 # GL_AMD_debug_output
770 'glDebugMessageEnableAMD',
771 'glDebugMessageInsertAMD',
772 'glDebugMessageCallbackAMD',
773 'glGetDebugMessageLogAMD',
774 ]
775
José Fonseca54f304a2012-01-14 19:33:08 +0000776 def invokeFunction(self, function):
José Fonseca91492d22011-05-23 21:20:31 +0100777 if function.name in ('glLinkProgram', 'glLinkProgramARB'):
778 # These functions have been dispatched already
779 return
780
José Fonseca2cfa02c2013-06-10 08:05:29 +0100781 Tracer.invokeFunction(self, function)
782
783 def doInvokeFunction(self, function):
784 # Same as invokeFunction() but called both when trace is enabled or disabled.
785 #
786 # Used to modify the behavior of GL entry-points.
787
788 # Override GL extensions
789 if function.name in ('glGetString', 'glGetIntegerv', 'glGetStringi'):
790 Tracer.doInvokeFunction(self, function, prefix = 'gltrace::_', suffix = '_override')
791 return
792
José Fonsecaf028a8f2012-02-15 23:33:35 +0000793 # We implement GL_EXT_debug_marker, GL_GREMEDY_*, etc., and not the
794 # driver
795 if function.name in self.marker_functions:
José Fonseca8f34d342011-07-15 20:16:40 +0100796 return
797
Peter Lohrmann9d9eb812013-07-12 16:15:25 -0400798 # We may be faking KHR_debug, so ensure the pointer queries result is
799 # always zeroed to prevent dereference of unitialized pointers
800 if function.name == 'glGetPointerv':
801 print ' if (params &&'
802 print ' (pname == GL_DEBUG_CALLBACK_FUNCTION ||'
803 print ' pname == GL_DEBUG_CALLBACK_USER_PARAM)) {'
804 print ' *params = NULL;'
805 print ' }'
806
José Fonseca2cfa02c2013-06-10 08:05:29 +0100807 if function.name in self.getProcAddressFunctionNames:
José Fonsecaf028a8f2012-02-15 23:33:35 +0000808 else_ = ''
809 for marker_function in self.marker_functions:
José Fonseca1b6c8752012-04-15 14:33:00 +0100810 if self.api.getFunctionByName(marker_function):
José Fonsecaf028a8f2012-02-15 23:33:35 +0000811 print ' %sif (strcmp("%s", (const char *)%s) == 0) {' % (else_, marker_function, function.args[0].name)
José Fonseca632a78d2012-04-19 07:18:59 +0100812 print ' _result = (%s)&%s;' % (function.type, marker_function)
José Fonsecaf028a8f2012-02-15 23:33:35 +0000813 print ' }'
814 else_ = 'else '
815 print ' %s{' % else_
José Fonseca2cfa02c2013-06-10 08:05:29 +0100816 Tracer.doInvokeFunction(self, function)
817
818 # Replace function addresses with ours
819 # XXX: Doing this here instead of wrapRet means that the trace will
820 # contain the addresses of the wrapper functions, and not the real
821 # functions, but in practice this should make no difference.
822 if function.name in self.getProcAddressFunctionNames:
823 print ' _result = _wrapProcAddress(%s, _result);' % (function.args[0].name,)
824
José Fonseca8f34d342011-07-15 20:16:40 +0100825 print ' }'
José Fonseca1b3d3752011-07-15 10:15:19 +0100826 return
827
José Fonseca2cfa02c2013-06-10 08:05:29 +0100828 Tracer.doInvokeFunction(self, function)
José Fonseca91492d22011-05-23 21:20:31 +0100829
José Fonseca867b1b72011-04-24 11:58:04 +0100830 buffer_targets = [
831 'ARRAY_BUFFER',
832 'ELEMENT_ARRAY_BUFFER',
833 'PIXEL_PACK_BUFFER',
834 'PIXEL_UNPACK_BUFFER',
José Fonseca7b20d672012-01-10 19:13:58 +0000835 'UNIFORM_BUFFER',
836 'TEXTURE_BUFFER',
837 'TRANSFORM_FEEDBACK_BUFFER',
838 'COPY_READ_BUFFER',
839 'COPY_WRITE_BUFFER',
840 'DRAW_INDIRECT_BUFFER',
841 'ATOMIC_COUNTER_BUFFER',
José Fonseca867b1b72011-04-24 11:58:04 +0100842 ]
843
José Fonseca54f304a2012-01-14 19:33:08 +0000844 def wrapRet(self, function, instance):
845 Tracer.wrapRet(self, function, instance)
José Fonseca1b3d3752011-07-15 10:15:19 +0100846
José Fonsecacdc322c2012-02-29 19:29:51 +0000847 # Keep track of buffer mappings
848 if function.name in ('glMapBuffer', 'glMapBufferARB'):
José Fonseca867b1b72011-04-24 11:58:04 +0100849 print ' struct buffer_mapping *mapping = get_buffer_mapping(target);'
850 print ' if (mapping) {'
851 print ' mapping->map = %s;' % (instance)
852 print ' mapping->length = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100853 print ' _glGetBufferParameteriv(target, GL_BUFFER_SIZE, &mapping->length);'
José Fonseca867b1b72011-04-24 11:58:04 +0100854 print ' mapping->write = (access != GL_READ_ONLY);'
José Fonseca73373602011-05-20 17:45:26 +0100855 print ' mapping->explicit_flush = false;'
José Fonseca867b1b72011-04-24 11:58:04 +0100856 print ' }'
José Fonseca867b1b72011-04-24 11:58:04 +0100857 if function.name == 'glMapBufferRange':
José Fonseca9c536b02012-02-29 20:54:13 +0000858 print ' if (access & GL_MAP_WRITE_BIT) {'
José Fonseca632a78d2012-04-19 07:18:59 +0100859 print ' _checkBufferMapRange = true;'
José Fonseca9c536b02012-02-29 20:54:13 +0000860 print ' }'
José Fonseca867b1b72011-04-24 11:58:04 +0100861 print ' struct buffer_mapping *mapping = get_buffer_mapping(target);'
862 print ' if (mapping) {'
863 print ' mapping->map = %s;' % (instance)
864 print ' mapping->length = length;'
865 print ' mapping->write = access & GL_MAP_WRITE_BIT;'
José Fonseca73373602011-05-20 17:45:26 +0100866 print ' mapping->explicit_flush = access & GL_MAP_FLUSH_EXPLICIT_BIT;'
José Fonseca867b1b72011-04-24 11:58:04 +0100867 print ' }'
José Fonseca669b1222011-02-20 09:05:10 +0000868
José Fonsecac9f12232011-03-25 20:07:42 +0000869 boolean_names = [
870 'GL_FALSE',
871 'GL_TRUE',
872 ]
873
874 def gl_boolean(self, value):
875 return self.boolean_names[int(bool(value))]
876
José Fonsecac29f4f12011-06-11 12:19:05 +0100877 # Names of the functions that unpack from a pixel buffer object. See the
878 # ARB_pixel_buffer_object specification.
José Fonsecae97bab92011-06-02 23:15:11 +0100879 unpack_function_names = set([
880 'glBitmap',
José Fonsecac29f4f12011-06-11 12:19:05 +0100881 'glColorSubTable',
882 'glColorTable',
José Fonsecad2bd4ca2013-04-12 11:41:00 +0100883 'glCompressedMultiTexImage1DEXT',
884 'glCompressedMultiTexImage2DEXT',
885 'glCompressedMultiTexImage3DEXT',
886 'glCompressedMultiTexSubImage1DEXT',
887 'glCompressedMultiTexSubImage2DEXT',
888 'glCompressedMultiTexSubImage3DEXT',
José Fonsecac29f4f12011-06-11 12:19:05 +0100889 'glCompressedTexImage1D',
idinevdb5ad3b2014-02-03 15:50:39 +0000890 'glCompressedTexImage1DARB',
José Fonsecac29f4f12011-06-11 12:19:05 +0100891 'glCompressedTexImage2D',
idinevdb5ad3b2014-02-03 15:50:39 +0000892 'glCompressedTexImage2DARB',
José Fonsecac29f4f12011-06-11 12:19:05 +0100893 'glCompressedTexImage3D',
idinevdb5ad3b2014-02-03 15:50:39 +0000894 'glCompressedTexImage3DARB',
José Fonsecac29f4f12011-06-11 12:19:05 +0100895 'glCompressedTexSubImage1D',
idinevdb5ad3b2014-02-03 15:50:39 +0000896 'glCompressedTexSubImage1DARB',
José Fonsecac29f4f12011-06-11 12:19:05 +0100897 'glCompressedTexSubImage2D',
idinevdb5ad3b2014-02-03 15:50:39 +0000898 'glCompressedTexSubImage2DARB',
José Fonsecac29f4f12011-06-11 12:19:05 +0100899 'glCompressedTexSubImage3D',
idinevdb5ad3b2014-02-03 15:50:39 +0000900 'glCompressedTexSubImage3DARB',
José Fonsecad2bd4ca2013-04-12 11:41:00 +0100901 'glCompressedTextureImage1DEXT',
902 'glCompressedTextureImage2DEXT',
903 'glCompressedTextureImage3DEXT',
904 'glCompressedTextureSubImage1DEXT',
905 'glCompressedTextureSubImage2DEXT',
906 'glCompressedTextureSubImage3DEXT',
José Fonsecac29f4f12011-06-11 12:19:05 +0100907 'glConvolutionFilter1D',
908 'glConvolutionFilter2D',
José Fonsecae97bab92011-06-02 23:15:11 +0100909 'glDrawPixels',
910 'glMultiTexImage1DEXT',
911 'glMultiTexImage2DEXT',
912 'glMultiTexImage3DEXT',
913 'glMultiTexSubImage1DEXT',
914 'glMultiTexSubImage2DEXT',
915 'glMultiTexSubImage3DEXT',
José Fonsecac29f4f12011-06-11 12:19:05 +0100916 'glPixelMapfv',
917 'glPixelMapuiv',
918 'glPixelMapusv',
José Fonsecae97bab92011-06-02 23:15:11 +0100919 'glPolygonStipple',
José Fonsecac29f4f12011-06-11 12:19:05 +0100920 'glSeparableFilter2D',
José Fonsecae97bab92011-06-02 23:15:11 +0100921 'glTexImage1D',
922 'glTexImage1DEXT',
923 'glTexImage2D',
924 'glTexImage2DEXT',
925 'glTexImage3D',
926 'glTexImage3DEXT',
927 'glTexSubImage1D',
928 'glTexSubImage1DEXT',
929 'glTexSubImage2D',
930 'glTexSubImage2DEXT',
931 'glTexSubImage3D',
932 'glTexSubImage3DEXT',
933 'glTextureImage1DEXT',
934 'glTextureImage2DEXT',
935 'glTextureImage3DEXT',
936 'glTextureSubImage1DEXT',
937 'glTextureSubImage2DEXT',
938 'glTextureSubImage3DEXT',
939 ])
940
José Fonseca54f304a2012-01-14 19:33:08 +0000941 def serializeArgValue(self, function, arg):
José Fonsecae97bab92011-06-02 23:15:11 +0100942 # Recognize offsets instead of blobs when a PBO is bound
943 if function.name in self.unpack_function_names \
944 and (isinstance(arg.type, stdapi.Blob) \
945 or (isinstance(arg.type, stdapi.Const) \
946 and isinstance(arg.type.type, stdapi.Blob))):
José Fonsecac29f4f12011-06-11 12:19:05 +0100947 print ' {'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000948 print ' gltrace::Context *ctx = gltrace::getContext();'
José Fonseca632a78d2012-04-19 07:18:59 +0100949 print ' GLint _unpack_buffer = 0;'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000950 print ' if (ctx->profile == gltrace::PROFILE_COMPAT)'
José Fonseca632a78d2012-04-19 07:18:59 +0100951 print ' _glGetIntegerv(GL_PIXEL_UNPACK_BUFFER_BINDING, &_unpack_buffer);'
952 print ' if (_unpack_buffer) {'
José Fonsecad559f022012-04-15 16:13:51 +0100953 print ' trace::localWriter.writePointer((uintptr_t)%s);' % arg.name
José Fonsecac29f4f12011-06-11 12:19:05 +0100954 print ' } else {'
José Fonseca54f304a2012-01-14 19:33:08 +0000955 Tracer.serializeArgValue(self, function, arg)
José Fonsecac29f4f12011-06-11 12:19:05 +0100956 print ' }'
José Fonsecae97bab92011-06-02 23:15:11 +0100957 print ' }'
958 return
959
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100960 # Several GL state functions take GLenum symbolic names as
961 # integer/floats; so dump the symbolic name whenever possible
José Fonseca3bcb33c2011-05-27 20:14:31 +0100962 if function.name.startswith('gl') \
José Fonsecae3571092011-10-13 08:26:27 +0100963 and arg.type in (glapi.GLint, glapi.GLfloat, glapi.GLdouble) \
José Fonseca3bcb33c2011-05-27 20:14:31 +0100964 and arg.name == 'param':
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100965 assert arg.index > 0
966 assert function.args[arg.index - 1].name == 'pname'
967 assert function.args[arg.index - 1].type == glapi.GLenum
968 print ' if (is_symbolic_pname(pname) && is_symbolic_param(%s)) {' % arg.name
José Fonseca54f304a2012-01-14 19:33:08 +0000969 self.serializeValue(glapi.GLenum, arg.name)
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100970 print ' } else {'
José Fonseca54f304a2012-01-14 19:33:08 +0000971 Tracer.serializeArgValue(self, function, arg)
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100972 print ' }'
973 return
974
José Fonseca54f304a2012-01-14 19:33:08 +0000975 Tracer.serializeArgValue(self, function, arg)
José Fonseca99221832011-03-22 22:15:46 +0000976
José Fonseca4c938c22011-04-30 22:44:38 +0100977 def footer(self, api):
978 Tracer.footer(self, api)
José Fonseca669b1222011-02-20 09:05:10 +0000979
José Fonseca4c938c22011-04-30 22:44:38 +0100980 # A simple state tracker to track the pointer values
José Fonseca669b1222011-02-20 09:05:10 +0000981 # update the state
José Fonseca14cb9ef2012-05-17 21:33:14 +0100982 print 'static void _trace_user_arrays(GLuint count)'
José Fonseca669b1222011-02-20 09:05:10 +0000983 print '{'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000984 print ' gltrace::Context *ctx = gltrace::getContext();'
José Fonseca8d1408b2014-02-03 19:57:18 +0000985 print
986
987 # Temporarily unbind the array buffer
José Fonseca26be8f92014-03-07 14:08:50 +0000988 print ' GLint _array_buffer = _glGetInteger(GL_ARRAY_BUFFER_BINDING);'
José Fonseca8d1408b2014-02-03 19:57:18 +0000989 print ' if (_array_buffer) {'
990 self.fake_glBindBuffer(api, 'GL_ARRAY_BUFFER', '0')
991 print ' }'
992 print
José Fonseca1a2fdd22011-04-01 00:55:09 +0100993
José Fonseca99221832011-03-22 22:15:46 +0000994 for camelcase_name, uppercase_name in self.arrays:
Chia-I Wub3d218d2011-11-03 01:37:36 +0800995 # in which profile is the array available?
José Fonsecaf028a8f2012-02-15 23:33:35 +0000996 profile_check = 'ctx->profile == gltrace::PROFILE_COMPAT'
Chia-I Wub3d218d2011-11-03 01:37:36 +0800997 if camelcase_name in self.arrays_es1:
José Fonsecaf028a8f2012-02-15 23:33:35 +0000998 profile_check = '(' + profile_check + ' || ctx->profile == gltrace::PROFILE_ES1)';
Chia-I Wub3d218d2011-11-03 01:37:36 +0800999
José Fonseca99221832011-03-22 22:15:46 +00001000 function_name = 'gl%sPointer' % camelcase_name
1001 enable_name = 'GL_%s_ARRAY' % uppercase_name
1002 binding_name = 'GL_%s_ARRAY_BUFFER_BINDING' % uppercase_name
José Fonseca1b6c8752012-04-15 14:33:00 +01001003 function = api.getFunctionByName(function_name)
José Fonseca99221832011-03-22 22:15:46 +00001004
José Fonseca06e85192011-10-16 14:15:36 +01001005 print ' // %s' % function.prototype()
Chia-I Wub3d218d2011-11-03 01:37:36 +08001006 print ' if (%s) {' % profile_check
José Fonsecafb6744f2011-04-15 11:18:37 +01001007 self.array_trace_prolog(api, uppercase_name)
1008 self.array_prolog(api, uppercase_name)
José Fonseca632a78d2012-04-19 07:18:59 +01001009 print ' if (_glIsEnabled(%s)) {' % enable_name
José Fonseca26be8f92014-03-07 14:08:50 +00001010 print ' GLint _binding = _glGetInteger(%s);' % binding_name
José Fonseca632a78d2012-04-19 07:18:59 +01001011 print ' if (!_binding) {'
José Fonseca99221832011-03-22 22:15:46 +00001012
1013 # Get the arguments via glGet*
1014 for arg in function.args:
1015 arg_get_enum = 'GL_%s_ARRAY_%s' % (uppercase_name, arg.name.upper())
1016 arg_get_function, arg_type = TypeGetter().visit(arg.type)
José Fonseca7f5163e2011-03-31 23:37:26 +01001017 print ' %s %s = 0;' % (arg_type, arg.name)
José Fonseca632a78d2012-04-19 07:18:59 +01001018 print ' _%s(%s, &%s);' % (arg_get_function, arg_get_enum, arg.name)
José Fonseca99221832011-03-22 22:15:46 +00001019
1020 arg_names = ', '.join([arg.name for arg in function.args[:-1]])
José Fonseca14cb9ef2012-05-17 21:33:14 +01001021 print ' size_t _size = _%s_size(%s, count);' % (function.name, arg_names)
José Fonseca99221832011-03-22 22:15:46 +00001022
1023 # Emit a fake function
José Fonsecafb6744f2011-04-15 11:18:37 +01001024 self.array_trace_intermezzo(api, uppercase_name)
José Fonseca632a78d2012-04-19 07:18:59 +01001025 print ' unsigned _call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,)
José Fonseca669b1222011-02-20 09:05:10 +00001026 for arg in function.args:
1027 assert not arg.output
José Fonsecab4a3d142011-10-27 07:43:19 +01001028 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
José Fonseca14c21bc2011-02-20 23:32:22 +00001029 if arg.name != 'pointer':
José Fonseca54f304a2012-01-14 19:33:08 +00001030 self.serializeValue(arg.type, arg.name)
José Fonseca14c21bc2011-02-20 23:32:22 +00001031 else:
José Fonseca632a78d2012-04-19 07:18:59 +01001032 print ' trace::localWriter.writeBlob((const void *)%s, _size);' % (arg.name)
José Fonsecab4a3d142011-10-27 07:43:19 +01001033 print ' trace::localWriter.endArg();'
José Fonseca99221832011-03-22 22:15:46 +00001034
José Fonsecab4a3d142011-10-27 07:43:19 +01001035 print ' trace::localWriter.endEnter();'
José Fonseca632a78d2012-04-19 07:18:59 +01001036 print ' trace::localWriter.beginLeave(_call);'
José Fonsecab4a3d142011-10-27 07:43:19 +01001037 print ' trace::localWriter.endLeave();'
José Fonseca99221832011-03-22 22:15:46 +00001038 print ' }'
José Fonseca669b1222011-02-20 09:05:10 +00001039 print ' }'
José Fonsecafb6744f2011-04-15 11:18:37 +01001040 self.array_epilog(api, uppercase_name)
1041 self.array_trace_epilog(api, uppercase_name)
Chia-I Wub3d218d2011-11-03 01:37:36 +08001042 print ' }'
José Fonseca99221832011-03-22 22:15:46 +00001043 print
José Fonseca1a2fdd22011-04-01 00:55:09 +01001044
José Fonseca1601c412011-05-10 10:38:19 +01001045 # Samething, but for glVertexAttribPointer*
1046 #
1047 # Some variants of glVertexAttribPointer alias conventional and generic attributes:
1048 # - glVertexAttribPointer: no
1049 # - glVertexAttribPointerARB: implementation dependent
1050 # - glVertexAttribPointerNV: yes
1051 #
1052 # This means that the implementations of these functions do not always
1053 # alias, and they need to be considered independently.
1054 #
Chia-I Wub3d218d2011-11-03 01:37:36 +08001055 print ' // ES1 does not support generic vertex attributes'
José Fonsecaf028a8f2012-02-15 23:33:35 +00001056 print ' if (ctx->profile == gltrace::PROFILE_ES1)'
Chia-I Wub3d218d2011-11-03 01:37:36 +08001057 print ' return;'
1058 print
José Fonseca632a78d2012-04-19 07:18:59 +01001059 print ' vertex_attrib _vertex_attrib = _get_vertex_attrib();'
José Fonseca5a568a92011-06-29 16:43:36 +01001060 print
1061 for suffix in ['', 'ARB', 'NV']:
1062 if suffix:
José Fonsecad94aaac2011-06-28 20:50:49 +01001063 SUFFIX = '_' + suffix
José Fonsecad94aaac2011-06-28 20:50:49 +01001064 else:
José Fonseca5a568a92011-06-29 16:43:36 +01001065 SUFFIX = suffix
José Fonseca1601c412011-05-10 10:38:19 +01001066 function_name = 'glVertexAttribPointer' + suffix
José Fonseca1b6c8752012-04-15 14:33:00 +01001067 function = api.getFunctionByName(function_name)
José Fonseca06e85192011-10-16 14:15:36 +01001068
1069 print ' // %s' % function.prototype()
José Fonseca632a78d2012-04-19 07:18:59 +01001070 print ' if (_vertex_attrib == VERTEX_ATTRIB%s) {' % SUFFIX
José Fonseca5a568a92011-06-29 16:43:36 +01001071 if suffix == 'NV':
José Fonseca632a78d2012-04-19 07:18:59 +01001072 print ' GLint _max_vertex_attribs = 16;'
José Fonseca5a568a92011-06-29 16:43:36 +01001073 else:
José Fonseca26be8f92014-03-07 14:08:50 +00001074 print ' GLint _max_vertex_attribs = _glGetInteger(GL_MAX_VERTEX_ATTRIBS);'
José Fonseca632a78d2012-04-19 07:18:59 +01001075 print ' for (GLint index = 0; index < _max_vertex_attribs; ++index) {'
1076 print ' GLint _enabled = 0;'
José Fonseca5a568a92011-06-29 16:43:36 +01001077 if suffix == 'NV':
José Fonseca632a78d2012-04-19 07:18:59 +01001078 print ' _glGetIntegerv(GL_VERTEX_ATTRIB_ARRAY0_NV + index, &_enabled);'
José Fonseca5a568a92011-06-29 16:43:36 +01001079 else:
José Fonseca632a78d2012-04-19 07:18:59 +01001080 print ' _glGetVertexAttribiv%s(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED%s, &_enabled);' % (suffix, SUFFIX)
1081 print ' if (_enabled) {'
1082 print ' GLint _binding = 0;'
José Fonseca5a568a92011-06-29 16:43:36 +01001083 if suffix != 'NV':
1084 # It doesn't seem possible to use VBOs with NV_vertex_program.
José Fonseca632a78d2012-04-19 07:18:59 +01001085 print ' _glGetVertexAttribiv%s(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING%s, &_binding);' % (suffix, SUFFIX)
1086 print ' if (!_binding) {'
José Fonseca1a2fdd22011-04-01 00:55:09 +01001087
José Fonseca1601c412011-05-10 10:38:19 +01001088 # Get the arguments via glGet*
1089 for arg in function.args[1:]:
José Fonseca5a568a92011-06-29 16:43:36 +01001090 if suffix == 'NV':
1091 arg_get_enum = 'GL_ATTRIB_ARRAY_%s%s' % (arg.name.upper(), SUFFIX)
1092 else:
1093 arg_get_enum = 'GL_VERTEX_ATTRIB_ARRAY_%s%s' % (arg.name.upper(), SUFFIX)
José Fonsecac493e3e2011-06-29 12:57:06 +01001094 arg_get_function, arg_type = TypeGetter('glGetVertexAttrib', False, suffix).visit(arg.type)
José Fonseca5a568a92011-06-29 16:43:36 +01001095 print ' %s %s = 0;' % (arg_type, arg.name)
José Fonseca632a78d2012-04-19 07:18:59 +01001096 print ' _%s(index, %s, &%s);' % (arg_get_function, arg_get_enum, arg.name)
José Fonseca1601c412011-05-10 10:38:19 +01001097
1098 arg_names = ', '.join([arg.name for arg in function.args[1:-1]])
José Fonseca14cb9ef2012-05-17 21:33:14 +01001099 print ' size_t _size = _%s_size(%s, count);' % (function.name, arg_names)
José Fonseca1a2fdd22011-04-01 00:55:09 +01001100
José Fonseca1601c412011-05-10 10:38:19 +01001101 # Emit a fake function
José Fonseca632a78d2012-04-19 07:18:59 +01001102 print ' unsigned _call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,)
José Fonseca1601c412011-05-10 10:38:19 +01001103 for arg in function.args:
1104 assert not arg.output
José Fonsecab4a3d142011-10-27 07:43:19 +01001105 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
José Fonseca1601c412011-05-10 10:38:19 +01001106 if arg.name != 'pointer':
José Fonseca54f304a2012-01-14 19:33:08 +00001107 self.serializeValue(arg.type, arg.name)
José Fonseca1601c412011-05-10 10:38:19 +01001108 else:
José Fonseca632a78d2012-04-19 07:18:59 +01001109 print ' trace::localWriter.writeBlob((const void *)%s, _size);' % (arg.name)
José Fonsecab4a3d142011-10-27 07:43:19 +01001110 print ' trace::localWriter.endArg();'
José Fonseca1601c412011-05-10 10:38:19 +01001111
José Fonsecab4a3d142011-10-27 07:43:19 +01001112 print ' trace::localWriter.endEnter();'
José Fonseca632a78d2012-04-19 07:18:59 +01001113 print ' trace::localWriter.beginLeave(_call);'
José Fonsecab4a3d142011-10-27 07:43:19 +01001114 print ' trace::localWriter.endLeave();'
José Fonseca1601c412011-05-10 10:38:19 +01001115 print ' }'
1116 print ' }'
1117 print ' }'
1118 print ' }'
1119 print
José Fonseca1a2fdd22011-04-01 00:55:09 +01001120
José Fonseca8d1408b2014-02-03 19:57:18 +00001121 # Restore the original array_buffer
1122 print ' if (_array_buffer) {'
1123 self.fake_glBindBuffer(api, 'GL_ARRAY_BUFFER', '_array_buffer')
1124 print ' }'
1125 print
1126
José Fonseca669b1222011-02-20 09:05:10 +00001127 print '}'
1128 print
1129
José Fonsecafb6744f2011-04-15 11:18:37 +01001130 #
1131 # Hooks for glTexCoordPointer, which is identical to the other array
1132 # pointers except the fact that it is indexed by glClientActiveTexture.
1133 #
1134
1135 def array_prolog(self, api, uppercase_name):
1136 if uppercase_name == 'TEXTURE_COORD':
José Fonseca26be8f92014-03-07 14:08:50 +00001137 print ' GLint client_active_texture = _glGetInteger(GL_CLIENT_ACTIVE_TEXTURE);'
José Fonsecafb6744f2011-04-15 11:18:37 +01001138 print ' GLint max_texture_coords = 0;'
José Fonsecaf028a8f2012-02-15 23:33:35 +00001139 print ' if (ctx->profile == gltrace::PROFILE_COMPAT)'
José Fonseca632a78d2012-04-19 07:18:59 +01001140 print ' _glGetIntegerv(GL_MAX_TEXTURE_COORDS, &max_texture_coords);'
Chia-I Wub3d218d2011-11-03 01:37:36 +08001141 print ' else'
José Fonseca632a78d2012-04-19 07:18:59 +01001142 print ' _glGetIntegerv(GL_MAX_TEXTURE_UNITS, &max_texture_coords);'
José Fonsecafb6744f2011-04-15 11:18:37 +01001143 print ' for (GLint unit = 0; unit < max_texture_coords; ++unit) {'
José Fonseca7525e6f2011-09-28 09:04:56 +01001144 print ' GLint texture = GL_TEXTURE0 + unit;'
José Fonseca632a78d2012-04-19 07:18:59 +01001145 print ' _glClientActiveTexture(texture);'
José Fonsecafb6744f2011-04-15 11:18:37 +01001146
1147 def array_trace_prolog(self, api, uppercase_name):
1148 if uppercase_name == 'TEXTURE_COORD':
1149 print ' bool client_active_texture_dirty = false;'
1150
1151 def array_epilog(self, api, uppercase_name):
1152 if uppercase_name == 'TEXTURE_COORD':
1153 print ' }'
1154 self.array_cleanup(api, uppercase_name)
1155
1156 def array_cleanup(self, api, uppercase_name):
1157 if uppercase_name == 'TEXTURE_COORD':
José Fonseca632a78d2012-04-19 07:18:59 +01001158 print ' _glClientActiveTexture(client_active_texture);'
José Fonsecafb6744f2011-04-15 11:18:37 +01001159
1160 def array_trace_intermezzo(self, api, uppercase_name):
1161 if uppercase_name == 'TEXTURE_COORD':
1162 print ' if (texture != client_active_texture || client_active_texture_dirty) {'
1163 print ' client_active_texture_dirty = true;'
1164 self.fake_glClientActiveTexture_call(api, "texture");
1165 print ' }'
1166
1167 def array_trace_epilog(self, api, uppercase_name):
1168 if uppercase_name == 'TEXTURE_COORD':
1169 print ' if (client_active_texture_dirty) {'
1170 self.fake_glClientActiveTexture_call(api, "client_active_texture");
1171 print ' }'
1172
José Fonseca8d1408b2014-02-03 19:57:18 +00001173 def fake_glBindBuffer(self, api, target, buffer):
1174 function = api.getFunctionByName('glBindBuffer')
1175 self.fake_call(function, [target, buffer])
1176
José Fonsecafb6744f2011-04-15 11:18:37 +01001177 def fake_glClientActiveTexture_call(self, api, texture):
José Fonseca1b6c8752012-04-15 14:33:00 +01001178 function = api.getFunctionByName('glClientActiveTexture')
José Fonsecafb6744f2011-04-15 11:18:37 +01001179 self.fake_call(function, [texture])
1180
José Fonseca151c3702013-05-10 08:28:15 +01001181 def emitFakeTexture2D(self):
1182 function = glapi.glapi.getFunctionByName('glTexImage2D')
1183 instances = function.argNames()
1184 print ' unsigned _fake_call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,)
1185 for arg in function.args:
1186 assert not arg.output
1187 self.serializeArg(function, arg)
1188 print ' trace::localWriter.endEnter();'
1189 print ' trace::localWriter.beginLeave(_fake_call);'
1190 print ' trace::localWriter.endLeave();'
José Fonsecafb6744f2011-04-15 11:18:37 +01001191
1192
1193
1194
1195
José Fonseca669b1222011-02-20 09:05:10 +00001196
1197
1198
1199
1200
1201