blob: 96c71efc9582b9df0ed1b6e6523dc1aa6aa5bb05 [file] [log] [blame]
José Fonseca669b1222011-02-20 09:05:10 +00001##########################################################################
2#
3# Copyright 2008-2010 VMware, Inc.
4# All Rights Reserved.
5#
6# Permission is hereby granted, free of charge, to any person obtaining a copy
7# of this software and associated documentation files (the "Software"), to deal
8# in the Software without restriction, including without limitation the rights
9# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10# copies of the Software, and to permit persons to whom the Software is
11# furnished to do so, subject to the following conditions:
12#
13# The above copyright notice and this permission notice shall be included in
14# all copies or substantial portions of the Software.
15#
16# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22# THE SOFTWARE.
23#
24##########################################################################/
25
26
27"""GL tracing generator."""
28
29
José Fonseca452d3252012-04-14 15:55:40 +010030from trace import Tracer
José Fonseca1b6c8752012-04-15 14:33:00 +010031from dispatch import function_pointer_type, function_pointer_value
José Fonsecabd86a222011-09-27 09:21:38 +010032import specs.stdapi as stdapi
33import specs.glapi as glapi
34import specs.glparams as glparams
35from specs.glxapi import glxapi
José Fonseca669b1222011-02-20 09:05:10 +000036
37
José Fonseca99221832011-03-22 22:15:46 +000038class TypeGetter(stdapi.Visitor):
39 '''Determine which glGet*v function that matches the specified type.'''
40
José Fonsecac493e3e2011-06-29 12:57:06 +010041 def __init__(self, prefix = 'glGet', long_suffix = True, ext_suffix = ''):
José Fonseca1a2fdd22011-04-01 00:55:09 +010042 self.prefix = prefix
43 self.long_suffix = long_suffix
José Fonsecac493e3e2011-06-29 12:57:06 +010044 self.ext_suffix = ext_suffix
José Fonseca1a2fdd22011-04-01 00:55:09 +010045
José Fonseca54f304a2012-01-14 19:33:08 +000046 def visitConst(self, const):
José Fonseca99221832011-03-22 22:15:46 +000047 return self.visit(const.type)
48
José Fonseca54f304a2012-01-14 19:33:08 +000049 def visitAlias(self, alias):
José Fonseca99221832011-03-22 22:15:46 +000050 if alias.expr == 'GLboolean':
José Fonseca1a2fdd22011-04-01 00:55:09 +010051 if self.long_suffix:
José Fonsecac493e3e2011-06-29 12:57:06 +010052 suffix = 'Booleanv'
53 arg_type = alias.expr
José Fonseca1a2fdd22011-04-01 00:55:09 +010054 else:
José Fonsecac493e3e2011-06-29 12:57:06 +010055 suffix = 'iv'
56 arg_type = 'GLint'
José Fonseca99221832011-03-22 22:15:46 +000057 elif alias.expr == 'GLdouble':
José Fonseca1a2fdd22011-04-01 00:55:09 +010058 if self.long_suffix:
José Fonsecac493e3e2011-06-29 12:57:06 +010059 suffix = 'Doublev'
60 arg_type = alias.expr
José Fonseca1a2fdd22011-04-01 00:55:09 +010061 else:
José Fonsecac493e3e2011-06-29 12:57:06 +010062 suffix = 'dv'
63 arg_type = alias.expr
José Fonseca99221832011-03-22 22:15:46 +000064 elif alias.expr == 'GLfloat':
José Fonseca1a2fdd22011-04-01 00:55:09 +010065 if self.long_suffix:
José Fonsecac493e3e2011-06-29 12:57:06 +010066 suffix = 'Floatv'
67 arg_type = alias.expr
José Fonseca1a2fdd22011-04-01 00:55:09 +010068 else:
José Fonsecac493e3e2011-06-29 12:57:06 +010069 suffix = 'fv'
70 arg_type = alias.expr
José Fonseca7f5163e2011-03-31 23:37:26 +010071 elif alias.expr in ('GLint', 'GLuint', 'GLsizei'):
José Fonseca1a2fdd22011-04-01 00:55:09 +010072 if self.long_suffix:
José Fonsecac493e3e2011-06-29 12:57:06 +010073 suffix = 'Integerv'
74 arg_type = 'GLint'
José Fonseca1a2fdd22011-04-01 00:55:09 +010075 else:
José Fonsecac493e3e2011-06-29 12:57:06 +010076 suffix = 'iv'
77 arg_type = 'GLint'
José Fonseca99221832011-03-22 22:15:46 +000078 else:
79 print alias.expr
80 assert False
José Fonsecac493e3e2011-06-29 12:57:06 +010081 function_name = self.prefix + suffix + self.ext_suffix
82 return function_name, arg_type
José Fonseca99221832011-03-22 22:15:46 +000083
José Fonseca54f304a2012-01-14 19:33:08 +000084 def visitEnum(self, enum):
José Fonseca1a2fdd22011-04-01 00:55:09 +010085 return self.visit(glapi.GLint)
José Fonseca99221832011-03-22 22:15:46 +000086
José Fonseca54f304a2012-01-14 19:33:08 +000087 def visitBitmask(self, bitmask):
José Fonseca1a2fdd22011-04-01 00:55:09 +010088 return self.visit(glapi.GLint)
José Fonseca99221832011-03-22 22:15:46 +000089
José Fonseca54f304a2012-01-14 19:33:08 +000090 def visitOpaque(self, pointer):
José Fonsecac493e3e2011-06-29 12:57:06 +010091 return self.prefix + 'Pointerv' + self.ext_suffix, 'GLvoid *'
José Fonseca99221832011-03-22 22:15:46 +000092
93
José Fonseca669b1222011-02-20 09:05:10 +000094class GlTracer(Tracer):
95
José Fonseca99221832011-03-22 22:15:46 +000096 arrays = [
97 ("Vertex", "VERTEX"),
98 ("Normal", "NORMAL"),
99 ("Color", "COLOR"),
100 ("Index", "INDEX"),
101 ("TexCoord", "TEXTURE_COORD"),
102 ("EdgeFlag", "EDGE_FLAG"),
103 ("FogCoord", "FOG_COORD"),
104 ("SecondaryColor", "SECONDARY_COLOR"),
José Fonseca14c21bc2011-02-20 23:32:22 +0000105 ]
José Fonsecac9f12232011-03-25 20:07:42 +0000106 arrays.reverse()
José Fonseca669b1222011-02-20 09:05:10 +0000107
Chia-I Wub3d218d2011-11-03 01:37:36 +0800108 # arrays available in PROFILE_ES1
109 arrays_es1 = ("Vertex", "Normal", "Color", "TexCoord")
110
José Fonseca4c938c22011-04-30 22:44:38 +0100111 def header(self, api):
112 Tracer.header(self, api)
113
José Fonseca1b3d3752011-07-15 10:15:19 +0100114 print '#include "gltrace.hpp"'
115 print
José Fonseca5a568a92011-06-29 16:43:36 +0100116
117 # Which glVertexAttrib* variant to use
118 print 'enum vertex_attrib {'
119 print ' VERTEX_ATTRIB,'
120 print ' VERTEX_ATTRIB_ARB,'
121 print ' VERTEX_ATTRIB_NV,'
122 print '};'
123 print
José Fonseca632a78d2012-04-19 07:18:59 +0100124 print 'static vertex_attrib _get_vertex_attrib(void) {'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000125 print ' gltrace::Context *ctx = gltrace::getContext();'
Chia-I Wu8ef66972011-11-03 01:19:46 +0800126 print ' if (ctx->user_arrays_arb || ctx->user_arrays_nv) {'
José Fonseca632a78d2012-04-19 07:18:59 +0100127 print ' GLboolean _vertex_program = GL_FALSE;'
128 print ' _glGetBooleanv(GL_VERTEX_PROGRAM_ARB, &_vertex_program);'
129 print ' if (_vertex_program) {'
Chia-I Wu8ef66972011-11-03 01:19:46 +0800130 print ' if (ctx->user_arrays_nv) {'
José Fonseca632a78d2012-04-19 07:18:59 +0100131 print ' GLint _vertex_program_binding_nv = 0;'
132 print ' _glGetIntegerv(GL_VERTEX_PROGRAM_BINDING_NV, &_vertex_program_binding_nv);'
133 print ' if (_vertex_program_binding_nv) {'
José Fonseca5a568a92011-06-29 16:43:36 +0100134 print ' return VERTEX_ATTRIB_NV;'
135 print ' }'
136 print ' }'
137 print ' return VERTEX_ATTRIB_ARB;'
138 print ' }'
139 print ' }'
140 print ' return VERTEX_ATTRIB;'
141 print '}'
142 print
143
Imre Deakd4937372012-04-24 14:06:48 +0300144 self.defineShadowBufferHelper()
145
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000146 # Whether we need user arrays
José Fonseca632a78d2012-04-19 07:18:59 +0100147 print 'static inline bool _need_user_arrays(void)'
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000148 print '{'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000149 print ' gltrace::Context *ctx = gltrace::getContext();'
Chia-I Wu8ef66972011-11-03 01:19:46 +0800150 print ' if (!ctx->user_arrays) {'
José Fonseca25ebe542011-04-24 10:08:22 +0100151 print ' return false;'
152 print ' }'
153 print
José Fonseca1a2fdd22011-04-01 00:55:09 +0100154
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000155 for camelcase_name, uppercase_name in self.arrays:
Chia-I Wub3d218d2011-11-03 01:37:36 +0800156 # in which profile is the array available?
José Fonsecaf028a8f2012-02-15 23:33:35 +0000157 profile_check = 'ctx->profile == gltrace::PROFILE_COMPAT'
Chia-I Wub3d218d2011-11-03 01:37:36 +0800158 if camelcase_name in self.arrays_es1:
José Fonsecaf028a8f2012-02-15 23:33:35 +0000159 profile_check = '(' + profile_check + ' || ctx->profile == gltrace::PROFILE_ES1)';
Chia-I Wub3d218d2011-11-03 01:37:36 +0800160
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000161 function_name = 'gl%sPointer' % camelcase_name
162 enable_name = 'GL_%s_ARRAY' % uppercase_name
163 binding_name = 'GL_%s_ARRAY_BUFFER_BINDING' % uppercase_name
164 print ' // %s' % function_name
Chia-I Wub3d218d2011-11-03 01:37:36 +0800165 print ' if (%s) {' % profile_check
José Fonsecafb6744f2011-04-15 11:18:37 +0100166 self.array_prolog(api, uppercase_name)
José Fonseca632a78d2012-04-19 07:18:59 +0100167 print ' if (_glIsEnabled(%s)) {' % enable_name
168 print ' GLint _binding = 0;'
169 print ' _glGetIntegerv(%s, &_binding);' % binding_name
170 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) {'
187 print ' GLint _max_vertex_attribs = 0;'
188 print ' _glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &_max_vertex_attribs);'
189 print ' for (GLint index = 0; index < _max_vertex_attribs; ++index) {'
190 print ' GLint _enabled = 0;'
191 print ' _glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &_enabled);'
192 print ' if (_enabled) {'
193 print ' GLint _binding = 0;'
194 print ' _glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &_binding);'
195 print ' if (!_binding) {'
José Fonseca5a568a92011-06-29 16:43:36 +0100196 print ' return true;'
197 print ' }'
198 print ' }'
199 print ' }'
200 print ' }'
201 print
202 print ' // glVertexAttribPointerARB'
José Fonseca632a78d2012-04-19 07:18:59 +0100203 print ' if (_vertex_attrib == VERTEX_ATTRIB_ARB) {'
204 print ' GLint _max_vertex_attribs = 0;'
205 print ' _glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &_max_vertex_attribs);'
206 print ' for (GLint index = 0; index < _max_vertex_attribs; ++index) {'
207 print ' GLint _enabled = 0;'
208 print ' _glGetVertexAttribivARB(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB, &_enabled);'
209 print ' if (_enabled) {'
210 print ' GLint _binding = 0;'
211 print ' _glGetVertexAttribivARB(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB, &_binding);'
212 print ' if (!_binding) {'
José Fonsecad94aaac2011-06-28 20:50:49 +0100213 print ' return true;'
214 print ' }'
215 print ' }'
216 print ' }'
José Fonseca5a568a92011-06-29 16:43:36 +0100217 print ' }'
218 print
219 print ' // glVertexAttribPointerNV'
José Fonseca632a78d2012-04-19 07:18:59 +0100220 print ' if (_vertex_attrib == VERTEX_ATTRIB_NV) {'
José Fonseca5a568a92011-06-29 16:43:36 +0100221 print ' for (GLint index = 0; index < 16; ++index) {'
José Fonseca632a78d2012-04-19 07:18:59 +0100222 print ' GLint _enabled = 0;'
223 print ' _glGetIntegerv(GL_VERTEX_ATTRIB_ARRAY0_NV + index, &_enabled);'
224 print ' if (_enabled) {'
José Fonseca5a568a92011-06-29 16:43:36 +0100225 print ' return true;'
José Fonseca1a2fdd22011-04-01 00:55:09 +0100226 print ' }'
227 print ' }'
228 print ' }'
229 print
230
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000231 print ' return false;'
232 print '}'
233 print
José Fonseca669b1222011-02-20 09:05:10 +0000234
José Fonseca14cb9ef2012-05-17 21:33:14 +0100235 print 'static void _trace_user_arrays(GLuint count);'
José Fonseca14c21bc2011-02-20 23:32:22 +0000236 print
José Fonseca867b1b72011-04-24 11:58:04 +0100237
José Fonseca9c536b02012-02-29 20:54:13 +0000238 # Buffer mappings
239 print '// whether glMapBufferRange(GL_MAP_WRITE_BIT) has ever been called'
José Fonseca632a78d2012-04-19 07:18:59 +0100240 print 'static bool _checkBufferMapRange = false;'
José Fonseca9c536b02012-02-29 20:54:13 +0000241 print
242 print '// whether glBufferParameteriAPPLE(GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE) has ever been called'
José Fonseca632a78d2012-04-19 07:18:59 +0100243 print 'static bool _checkBufferFlushingUnmapAPPLE = false;'
José Fonseca9c536b02012-02-29 20:54:13 +0000244 print
245 # Buffer mapping information, necessary for old Mesa 2.1 drivers which
246 # do not support glGetBufferParameteriv(GL_BUFFER_ACCESS_FLAGS/GL_BUFFER_MAP_LENGTH)
José Fonseca867b1b72011-04-24 11:58:04 +0100247 print 'struct buffer_mapping {'
248 print ' void *map;'
249 print ' GLint length;'
250 print ' bool write;'
José Fonseca73373602011-05-20 17:45:26 +0100251 print ' bool explicit_flush;'
José Fonseca867b1b72011-04-24 11:58:04 +0100252 print '};'
253 print
254 for target in self.buffer_targets:
José Fonseca632a78d2012-04-19 07:18:59 +0100255 print 'struct buffer_mapping _%s_mapping;' % target.lower();
José Fonseca867b1b72011-04-24 11:58:04 +0100256 print
257 print 'static inline struct buffer_mapping *'
258 print 'get_buffer_mapping(GLenum target) {'
José Fonseca06e85192011-10-16 14:15:36 +0100259 print ' switch (target) {'
José Fonseca867b1b72011-04-24 11:58:04 +0100260 for target in self.buffer_targets:
261 print ' case GL_%s:' % target
José Fonseca632a78d2012-04-19 07:18:59 +0100262 print ' return & _%s_mapping;' % target.lower()
José Fonseca867b1b72011-04-24 11:58:04 +0100263 print ' default:'
José Fonseca559d5342011-10-27 08:10:56 +0100264 print ' os::log("apitrace: warning: unknown buffer target 0x%04X\\n", target);'
José Fonseca867b1b72011-04-24 11:58:04 +0100265 print ' return NULL;'
266 print ' }'
267 print '}'
268 print
269
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100270 # Generate a helper function to determine whether a parameter name
271 # refers to a symbolic value or not
272 print 'static bool'
273 print 'is_symbolic_pname(GLenum pname) {'
José Fonseca06e85192011-10-16 14:15:36 +0100274 print ' switch (pname) {'
José Fonseca5ea91872011-05-04 09:41:55 +0100275 for function, type, count, name in glparams.parameters:
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100276 if type is glapi.GLenum:
José Fonseca4c938c22011-04-30 22:44:38 +0100277 print ' case %s:' % name
278 print ' return true;'
279 print ' default:'
280 print ' return false;'
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100281 print ' }'
282 print '}'
283 print
284
285 # Generate a helper function to determine whether a parameter value is
286 # potentially symbolic or not; i.e., if the value can be represented in
287 # an enum or not
288 print 'template<class T>'
289 print 'static inline bool'
290 print 'is_symbolic_param(T param) {'
291 print ' return static_cast<T>(static_cast<GLenum>(param)) == param;'
292 print '}'
293 print
José Fonseca4c938c22011-04-30 22:44:38 +0100294
295 # Generate a helper function to know how many elements a parameter has
296 print 'static size_t'
José Fonseca632a78d2012-04-19 07:18:59 +0100297 print '_gl_param_size(GLenum pname) {'
José Fonseca06e85192011-10-16 14:15:36 +0100298 print ' switch (pname) {'
José Fonseca5ea91872011-05-04 09:41:55 +0100299 for function, type, count, name in glparams.parameters:
José Fonseca4c938c22011-04-30 22:44:38 +0100300 if type is not None:
José Fonsecaddf6d2c2012-12-20 15:34:50 +0000301 print ' case %s: return %s;' % (name, count)
José Fonseca4c938c22011-04-30 22:44:38 +0100302 print ' default:'
José Fonseca559d5342011-10-27 08:10:56 +0100303 print r' os::log("apitrace: warning: %s: unknown GLenum 0x%04X\n", __FUNCTION__, pname);'
José Fonseca4c938c22011-04-30 22:44:38 +0100304 print ' return 1;'
305 print ' }'
306 print '}'
307 print
308
Chia-I Wu335efb42011-11-03 01:59:22 +0800309 # states such as GL_UNPACK_ROW_LENGTH are not available in GLES
310 print 'static inline bool'
311 print 'can_unpack_subimage(void) {'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000312 print ' gltrace::Context *ctx = gltrace::getContext();'
313 print ' return (ctx->profile == gltrace::PROFILE_COMPAT);'
Chia-I Wu335efb42011-11-03 01:59:22 +0800314 print '}'
315 print
316
José Fonseca1b6c8752012-04-15 14:33:00 +0100317 getProcAddressFunctionNames = []
318
319 def traceApi(self, api):
320 if self.getProcAddressFunctionNames:
321 # Generate a function to wrap proc addresses
322 getProcAddressFunction = api.getFunctionByName(self.getProcAddressFunctionNames[0])
323 argType = getProcAddressFunction.args[0].type
324 retType = getProcAddressFunction.type
325
326 print 'static %s _wrapProcAddress(%s procName, %s procPtr);' % (retType, argType, retType)
327 print
328
329 Tracer.traceApi(self, api)
330
331 print 'static %s _wrapProcAddress(%s procName, %s procPtr) {' % (retType, argType, retType)
Peter Lohrmann0b5b75e2013-06-03 14:58:41 -0700332
333 # Provide fallback functions to missing debug functions
José Fonseca1b6c8752012-04-15 14:33:00 +0100334 print ' if (!procPtr) {'
Peter Lohrmann0b5b75e2013-06-03 14:58:41 -0700335 else_ = ''
336 for function_name in self.debug_functions:
337 if self.api.getFunctionByName(function_name):
338 print ' %sif (strcmp("%s", (const char *)procName) == 0) {' % (else_, function_name)
339 print ' return (%s)&%s;' % (retType, function_name)
340 print ' }'
341 else_ = 'else '
342 print ' %s{' % else_
343 print ' return NULL;'
344 print ' }'
José Fonseca1b6c8752012-04-15 14:33:00 +0100345 print ' }'
Peter Lohrmann0b5b75e2013-06-03 14:58:41 -0700346
José Fonseca81301932012-11-11 00:10:20 +0000347 for function in api.getAllFunctions():
José Fonseca1b6c8752012-04-15 14:33:00 +0100348 ptype = function_pointer_type(function)
349 pvalue = function_pointer_value(function)
350 print ' if (strcmp("%s", (const char *)procName) == 0) {' % function.name
351 print ' %s = (%s)procPtr;' % (pvalue, ptype)
352 print ' return (%s)&%s;' % (retType, function.name,)
353 print ' }'
354 print ' os::log("apitrace: warning: unknown function \\"%s\\"\\n", (const char *)procName);'
355 print ' return procPtr;'
356 print '}'
357 print
358 else:
359 Tracer.traceApi(self, api)
360
Imre Deakd4937372012-04-24 14:06:48 +0300361 def defineShadowBufferHelper(self):
362 print 'void _shadow_glGetBufferSubData(GLenum target, GLintptr offset,'
363 print ' GLsizeiptr size, GLvoid *data)'
364 print '{'
José Fonsecaa33d0bb2012-11-10 09:11:42 +0000365 print ' gltrace::Context *ctx = gltrace::getContext();'
Imre Deakd4937372012-04-24 14:06:48 +0300366 print ' if (!ctx->needsShadowBuffers() || target != GL_ELEMENT_ARRAY_BUFFER) {'
José Fonseca219c9f22012-11-03 10:13:17 +0000367 print ' _glGetBufferSubData(target, offset, size, data);'
Imre Deakd4937372012-04-24 14:06:48 +0300368 print ' return;'
369 print ' }'
370 print
José Fonseca219c9f22012-11-03 10:13:17 +0000371 print ' GLint buffer_binding = 0;'
Mike Stroyan5a67d492013-05-06 13:14:22 -0600372 print ' _glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &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) {'
383 print ' GLint buffer_binding = 0;'
384 print ' _glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &buffer_binding);'
385 print ' if (buffer_binding > 0) {'
386 print ' gltrace::Buffer & buf = ctx->buffers[buffer_binding];'
387 print ' buf.' + method + ';'
388 print ' }'
389 print ' }'
390 print
391
Imre Deakd4937372012-04-24 14:06:48 +0300392 def shadowBufferProlog(self, function):
393 if function.name == 'glBufferData':
José Fonseca219c9f22012-11-03 10:13:17 +0000394 self.shadowBufferMethod('bufferData(size, data)')
Imre Deakd4937372012-04-24 14:06:48 +0300395
396 if function.name == 'glBufferSubData':
José Fonseca219c9f22012-11-03 10:13:17 +0000397 self.shadowBufferMethod('bufferSubData(offset, size, data)')
Imre Deakd4937372012-04-24 14:06:48 +0300398
399 if function.name == 'glDeleteBuffers':
400 print ' gltrace::Context *ctx = gltrace::getContext();'
401 print ' if (ctx->needsShadowBuffers()) {'
José Fonseca219c9f22012-11-03 10:13:17 +0000402 print ' for (GLsizei i = 0; i < n; i++) {'
403 print ' ctx->buffers.erase(buffer[i]);'
Imre Deakd4937372012-04-24 14:06:48 +0300404 print ' }'
405 print ' }'
406
José Fonseca99221832011-03-22 22:15:46 +0000407 array_pointer_function_names = set((
408 "glVertexPointer",
409 "glNormalPointer",
410 "glColorPointer",
411 "glIndexPointer",
412 "glTexCoordPointer",
413 "glEdgeFlagPointer",
414 "glFogCoordPointer",
415 "glSecondaryColorPointer",
José Fonseca7f5163e2011-03-31 23:37:26 +0100416
José Fonsecaac5285b2011-05-04 11:09:08 +0100417 "glInterleavedArrays",
418
José Fonseca7e0bfd92011-04-30 23:09:03 +0100419 "glVertexPointerEXT",
420 "glNormalPointerEXT",
421 "glColorPointerEXT",
422 "glIndexPointerEXT",
423 "glTexCoordPointerEXT",
424 "glEdgeFlagPointerEXT",
425 "glFogCoordPointerEXT",
426 "glSecondaryColorPointerEXT",
José Fonseca99221832011-03-22 22:15:46 +0000427
José Fonseca7f5163e2011-03-31 23:37:26 +0100428 "glVertexAttribPointer",
429 "glVertexAttribPointerARB",
430 "glVertexAttribPointerNV",
José Fonsecaac5285b2011-05-04 11:09:08 +0100431 "glVertexAttribIPointer",
432 "glVertexAttribIPointerEXT",
José Fonseca7f5163e2011-03-31 23:37:26 +0100433 "glVertexAttribLPointer",
434 "glVertexAttribLPointerEXT",
José Fonseca99221832011-03-22 22:15:46 +0000435
436 #"glMatrixIndexPointerARB",
437 ))
438
439 draw_function_names = set((
440 'glDrawArrays',
441 'glDrawElements',
442 'glDrawRangeElements',
José Fonseca5c749e32011-05-09 11:11:37 +0100443 'glMultiDrawArrays',
444 'glMultiDrawElements',
445 'glDrawArraysInstanced',
José Fonsecaff8848b2011-10-09 01:04:17 +0100446 "glDrawArraysInstancedBaseInstance",
José Fonseca5c749e32011-05-09 11:11:37 +0100447 'glDrawElementsInstanced',
448 'glDrawArraysInstancedARB',
449 'glDrawElementsInstancedARB',
450 'glDrawElementsBaseVertex',
451 'glDrawRangeElementsBaseVertex',
452 'glDrawElementsInstancedBaseVertex',
José Fonsecaff8848b2011-10-09 01:04:17 +0100453 "glDrawElementsInstancedBaseInstance",
454 "glDrawElementsInstancedBaseVertexBaseInstance",
José Fonseca5c749e32011-05-09 11:11:37 +0100455 'glMultiDrawElementsBaseVertex',
456 'glDrawArraysIndirect',
457 'glDrawElementsIndirect',
José Fonseca29ac7c72013-04-14 15:40:01 +0100458 'glMultiDrawArraysIndirect',
459 'glMultiDrawArraysIndirectAMD',
460 'glMultiDrawElementsIndirect',
461 'glMultiDrawElementsIndirectAMD',
José Fonseca5c749e32011-05-09 11:11:37 +0100462 'glDrawArraysEXT',
José Fonseca7e0bfd92011-04-30 23:09:03 +0100463 'glDrawRangeElementsEXT',
José Fonseca5c749e32011-05-09 11:11:37 +0100464 'glDrawRangeElementsEXT_size',
465 'glMultiDrawArraysEXT',
466 'glMultiDrawElementsEXT',
467 'glMultiModeDrawArraysIBM',
468 'glMultiModeDrawElementsIBM',
469 'glDrawArraysInstancedEXT',
470 'glDrawElementsInstancedEXT',
José Fonseca99221832011-03-22 22:15:46 +0000471 ))
472
José Fonsecac9f12232011-03-25 20:07:42 +0000473 interleaved_formats = [
474 'GL_V2F',
475 'GL_V3F',
476 'GL_C4UB_V2F',
477 'GL_C4UB_V3F',
478 'GL_C3F_V3F',
479 'GL_N3F_V3F',
480 'GL_C4F_N3F_V3F',
481 'GL_T2F_V3F',
482 'GL_T4F_V4F',
483 'GL_T2F_C4UB_V3F',
484 'GL_T2F_C3F_V3F',
485 'GL_T2F_N3F_V3F',
486 'GL_T2F_C4F_N3F_V3F',
487 'GL_T4F_C4F_N3F_V4F',
488 ]
489
José Fonseca54f304a2012-01-14 19:33:08 +0000490 def traceFunctionImplBody(self, function):
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000491 # Defer tracing of user array pointers...
José Fonseca99221832011-03-22 22:15:46 +0000492 if function.name in self.array_pointer_function_names:
José Fonseca632a78d2012-04-19 07:18:59 +0100493 print ' GLint _array_buffer = 0;'
494 print ' _glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &_array_buffer);'
495 print ' if (!_array_buffer) {'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000496 print ' gltrace::Context *ctx = gltrace::getContext();'
Chia-I Wu8ef66972011-11-03 01:19:46 +0800497 print ' ctx->user_arrays = true;'
José Fonseca5a568a92011-06-29 16:43:36 +0100498 if function.name == "glVertexAttribPointerARB":
Chia-I Wu8ef66972011-11-03 01:19:46 +0800499 print ' ctx->user_arrays_arb = true;'
José Fonseca5a568a92011-06-29 16:43:36 +0100500 if function.name == "glVertexAttribPointerNV":
Chia-I Wu8ef66972011-11-03 01:19:46 +0800501 print ' ctx->user_arrays_nv = true;'
José Fonseca54f304a2012-01-14 19:33:08 +0000502 self.invokeFunction(function)
José Fonsecaac5285b2011-05-04 11:09:08 +0100503
504 # And also break down glInterleavedArrays into the individual calls
505 if function.name == 'glInterleavedArrays':
506 print
507
508 # Initialize the enable flags
509 for camelcase_name, uppercase_name in self.arrays:
José Fonseca632a78d2012-04-19 07:18:59 +0100510 flag_name = '_' + uppercase_name.lower()
José Fonsecaac5285b2011-05-04 11:09:08 +0100511 print ' GLboolean %s = GL_FALSE;' % flag_name
512 print
513
514 # Switch for the interleaved formats
515 print ' switch (format) {'
516 for format in self.interleaved_formats:
517 print ' case %s:' % format
518 for camelcase_name, uppercase_name in self.arrays:
José Fonseca632a78d2012-04-19 07:18:59 +0100519 flag_name = '_' + uppercase_name.lower()
José Fonsecaac5285b2011-05-04 11:09:08 +0100520 if format.find('_' + uppercase_name[0]) >= 0:
521 print ' %s = GL_TRUE;' % flag_name
522 print ' break;'
523 print ' default:'
524 print ' return;'
525 print ' }'
526 print
527
528 # Emit fake glEnableClientState/glDisableClientState flags
529 for camelcase_name, uppercase_name in self.arrays:
José Fonseca632a78d2012-04-19 07:18:59 +0100530 flag_name = '_' + uppercase_name.lower()
José Fonsecaac5285b2011-05-04 11:09:08 +0100531 enable_name = 'GL_%s_ARRAY' % uppercase_name
532
533 # Emit a fake function
534 print ' {'
José Fonseca632a78d2012-04-19 07:18:59 +0100535 print ' static const trace::FunctionSig &_sig = %s ? _glEnableClientState_sig : _glDisableClientState_sig;' % flag_name
536 print ' unsigned _call = trace::localWriter.beginEnter(&_sig);'
José Fonsecab4a3d142011-10-27 07:43:19 +0100537 print ' trace::localWriter.beginArg(0);'
José Fonseca54f304a2012-01-14 19:33:08 +0000538 self.serializeValue(glapi.GLenum, enable_name)
José Fonsecab4a3d142011-10-27 07:43:19 +0100539 print ' trace::localWriter.endArg();'
540 print ' trace::localWriter.endEnter();'
José Fonseca632a78d2012-04-19 07:18:59 +0100541 print ' trace::localWriter.beginLeave(_call);'
José Fonsecab4a3d142011-10-27 07:43:19 +0100542 print ' trace::localWriter.endLeave();'
José Fonsecaac5285b2011-05-04 11:09:08 +0100543 print ' }'
544
José Fonseca99221832011-03-22 22:15:46 +0000545 print ' return;'
546 print ' }'
José Fonseca14c21bc2011-02-20 23:32:22 +0000547
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000548 # ... to the draw calls
José Fonseca99221832011-03-22 22:15:46 +0000549 if function.name in self.draw_function_names:
José Fonseca632a78d2012-04-19 07:18:59 +0100550 print ' if (_need_user_arrays()) {'
José Fonseca99221832011-03-22 22:15:46 +0000551 arg_names = ', '.join([arg.name for arg in function.args[1:]])
José Fonseca14cb9ef2012-05-17 21:33:14 +0100552 print ' GLuint _count = _%s_count(%s);' % (function.name, arg_names)
553 print ' _trace_user_arrays(_count);'
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000554 print ' }'
José Fonseca14c21bc2011-02-20 23:32:22 +0000555
José Fonseca73373602011-05-20 17:45:26 +0100556 # Emit a fake memcpy on buffer uploads
José Fonseca9c536b02012-02-29 20:54:13 +0000557 if function.name == 'glBufferParameteriAPPLE':
558 print ' if (pname == GL_BUFFER_FLUSHING_UNMAP_APPLE && param == GL_FALSE) {'
José Fonseca632a78d2012-04-19 07:18:59 +0100559 print ' _checkBufferFlushingUnmapAPPLE = true;'
José Fonseca9c536b02012-02-29 20:54:13 +0000560 print ' }'
José Fonsecacdc322c2012-02-29 19:29:51 +0000561 if function.name in ('glUnmapBuffer', 'glUnmapBufferARB'):
José Fonseca9c536b02012-02-29 20:54:13 +0000562 if function.name.endswith('ARB'):
563 suffix = 'ARB'
564 else:
565 suffix = ''
566 print ' GLint access = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100567 print ' _glGetBufferParameteriv%s(target, GL_BUFFER_ACCESS, &access);' % suffix
José Fonseca9c536b02012-02-29 20:54:13 +0000568 print ' if (access != GL_READ_ONLY) {'
569 print ' GLvoid *map = NULL;'
José Fonseca632a78d2012-04-19 07:18:59 +0100570 print ' _glGetBufferPointerv%s(target, GL_BUFFER_MAP_POINTER, &map);' % suffix
José Fonseca9c536b02012-02-29 20:54:13 +0000571 print ' if (map) {'
572 print ' GLint length = -1;'
573 print ' bool flush = true;'
José Fonseca632a78d2012-04-19 07:18:59 +0100574 print ' if (_checkBufferMapRange) {'
575 print ' _glGetBufferParameteriv%s(target, GL_BUFFER_MAP_LENGTH, &length);' % suffix
José Fonseca9c536b02012-02-29 20:54:13 +0000576 print ' GLint access_flags = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100577 print ' _glGetBufferParameteriv(target, GL_BUFFER_ACCESS_FLAGS, &access_flags);'
José Fonseca9c536b02012-02-29 20:54:13 +0000578 print ' flush = flush && !(access_flags & GL_MAP_FLUSH_EXPLICIT_BIT);'
579 print ' if (length == -1) {'
José Fonsecacb07e2d2014-02-04 15:14:09 +0000580 print ' // Mesa drivers refuse GL_BUFFER_MAP_LENGTH without GL 3.0 up-to'
581 print ' // http://cgit.freedesktop.org/mesa/mesa/commit/?id=ffee498fb848b253a7833373fe5430f8c7ca0c5f'
José Fonsecadb1ccce2012-02-29 21:09:24 +0000582 print ' static bool warned = false;'
583 print ' if (!warned) {'
584 print ' os::log("apitrace: warning: glGetBufferParameteriv%s(GL_BUFFER_MAP_LENGTH) failed\\n");' % suffix
585 print ' warned = true;'
586 print ' }'
José Fonseca9c536b02012-02-29 20:54:13 +0000587 print ' struct buffer_mapping *mapping = get_buffer_mapping(target);'
588 print ' if (mapping) {'
589 print ' length = mapping->length;'
590 print ' flush = flush && !mapping->explicit_flush;'
591 print ' } else {'
592 print ' length = 0;'
593 print ' flush = false;'
594 print ' }'
595 print ' }'
596 print ' } else {'
597 print ' length = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100598 print ' _glGetBufferParameteriv%s(target, GL_BUFFER_SIZE, &length);' % suffix
José Fonseca9c536b02012-02-29 20:54:13 +0000599 print ' }'
José Fonseca632a78d2012-04-19 07:18:59 +0100600 print ' if (_checkBufferFlushingUnmapAPPLE) {'
José Fonseca9c536b02012-02-29 20:54:13 +0000601 print ' GLint flushing_unmap = GL_TRUE;'
José Fonseca632a78d2012-04-19 07:18:59 +0100602 print ' _glGetBufferParameteriv%s(target, GL_BUFFER_FLUSHING_UNMAP_APPLE, &flushing_unmap);' % suffix
José Fonseca9c536b02012-02-29 20:54:13 +0000603 print ' flush = flush && flushing_unmap;'
604 print ' }'
605 print ' if (flush && length > 0) {'
606 self.emit_memcpy('map', 'map', 'length')
607 print ' }'
608 print ' }'
609 print ' }'
José Fonsecacdc322c2012-02-29 19:29:51 +0000610 if function.name == 'glUnmapBufferOES':
611 print ' GLint access = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100612 print ' _glGetBufferParameteriv(target, GL_BUFFER_ACCESS_OES, &access);'
José Fonsecacdc322c2012-02-29 19:29:51 +0000613 print ' if (access == GL_WRITE_ONLY_OES) {'
614 print ' GLvoid *map = NULL;'
José Fonseca632a78d2012-04-19 07:18:59 +0100615 print ' _glGetBufferPointervOES(target, GL_BUFFER_MAP_POINTER_OES, &map);'
José Fonsecacdc322c2012-02-29 19:29:51 +0000616 print ' GLint size = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100617 print ' _glGetBufferParameteriv(target, GL_BUFFER_SIZE, &size);'
José Fonsecacdc322c2012-02-29 19:29:51 +0000618 print ' if (map && size > 0) {'
619 self.emit_memcpy('map', 'map', 'size')
José Fonseca219c9f22012-11-03 10:13:17 +0000620 self.shadowBufferMethod('bufferSubData(0, size, map)')
José Fonsecacdc322c2012-02-29 19:29:51 +0000621 print ' }'
José Fonseca867b1b72011-04-24 11:58:04 +0100622 print ' }'
José Fonsecafb3bd602012-01-15 13:56:28 +0000623 if function.name == 'glUnmapNamedBufferEXT':
José Fonseca024aff42012-02-29 18:00:06 +0000624 print ' GLint access_flags = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100625 print ' _glGetNamedBufferParameterivEXT(buffer, GL_BUFFER_ACCESS_FLAGS, &access_flags);'
José Fonseca024aff42012-02-29 18:00:06 +0000626 print ' if ((access_flags & GL_MAP_WRITE_BIT) && !(access_flags & GL_MAP_FLUSH_EXPLICIT_BIT)) {'
José Fonsecafb3bd602012-01-15 13:56:28 +0000627 print ' GLvoid *map = NULL;'
José Fonseca632a78d2012-04-19 07:18:59 +0100628 print ' _glGetNamedBufferPointervEXT(buffer, GL_BUFFER_MAP_POINTER, &map);'
José Fonsecafb3bd602012-01-15 13:56:28 +0000629 print ' GLint length = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100630 print ' _glGetNamedBufferParameterivEXT(buffer, GL_BUFFER_MAP_LENGTH, &length);'
José Fonseca024aff42012-02-29 18:00:06 +0000631 print ' if (map && length > 0) {'
José Fonsecafb3bd602012-01-15 13:56:28 +0000632 self.emit_memcpy('map', 'map', 'length')
José Fonseca024aff42012-02-29 18:00:06 +0000633 print ' }'
José Fonsecafb3bd602012-01-15 13:56:28 +0000634 print ' }'
José Fonseca77ef0ce2012-02-29 18:08:48 +0000635 if function.name == 'glFlushMappedBufferRange':
636 print ' GLvoid *map = NULL;'
José Fonseca632a78d2012-04-19 07:18:59 +0100637 print ' _glGetBufferPointerv(target, GL_BUFFER_MAP_POINTER, &map);'
José Fonseca77ef0ce2012-02-29 18:08:48 +0000638 print ' if (map && length > 0) {'
639 self.emit_memcpy('(char *)map + offset', '(const char *)map + offset', 'length')
640 print ' }'
641 if function.name == 'glFlushMappedBufferRangeAPPLE':
642 print ' GLvoid *map = NULL;'
José Fonseca632a78d2012-04-19 07:18:59 +0100643 print ' _glGetBufferPointerv(target, GL_BUFFER_MAP_POINTER, &map);'
José Fonseca77ef0ce2012-02-29 18:08:48 +0000644 print ' if (map && size > 0) {'
645 self.emit_memcpy('(char *)map + offset', '(const char *)map + offset', 'size')
José Fonseca73373602011-05-20 17:45:26 +0100646 print ' }'
José Fonsecafb3bd602012-01-15 13:56:28 +0000647 if function.name == 'glFlushMappedNamedBufferRangeEXT':
648 print ' GLvoid *map = NULL;'
José Fonseca632a78d2012-04-19 07:18:59 +0100649 print ' _glGetNamedBufferPointervEXT(buffer, GL_BUFFER_MAP_POINTER, &map);'
José Fonseca024aff42012-02-29 18:00:06 +0000650 print ' if (map && length > 0) {'
José Fonsecafb3bd602012-01-15 13:56:28 +0000651 self.emit_memcpy('(char *)map + offset', '(const char *)map + offset', 'length')
652 print ' }'
José Fonseca867b1b72011-04-24 11:58:04 +0100653
José Fonseca3522cbd2014-02-28 14:45:32 +0000654 # FIXME: We don't support coherent/pinned memory mappings
655 # See https://github.com/apitrace/apitrace/issues/232
656 if function.name in ('glBufferStorage', 'glNamedBufferStorageEXT'):
657 print r' if (flags & GL_MAP_COHERENT_BIT) {'
658 print r' os::log("apitrace: warning: coherent mappings not fully supported\n");'
659 print r' }'
660 if function.name in ('glBufferData', 'glBufferDataARB'):
661 print r' if (target == GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD) {'
662 print r' os::log("apitrace: warning: GL_AMD_pinned_memory not fully supported\n");'
663 print r' }'
664
José Fonseca91492d22011-05-23 21:20:31 +0100665 # Don't leave vertex attrib locations to chance. Instead emit fake
666 # glBindAttribLocation calls to ensure that the same locations will be
667 # used when retracing. Trying to remap locations after the fact would
668 # be an herculian task given that vertex attrib locations appear in
669 # many entry-points, including non-shader related ones.
670 if function.name == 'glLinkProgram':
José Fonseca54f304a2012-01-14 19:33:08 +0000671 Tracer.invokeFunction(self, function)
José Fonseca91492d22011-05-23 21:20:31 +0100672 print ' GLint active_attributes = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100673 print ' _glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &active_attributes);'
José Fonseca7525e6f2011-09-28 09:04:56 +0100674 print ' for (GLint attrib = 0; attrib < active_attributes; ++attrib) {'
José Fonseca91492d22011-05-23 21:20:31 +0100675 print ' GLint size = 0;'
676 print ' GLenum type = 0;'
677 print ' GLchar name[256];'
678 # TODO: Use ACTIVE_ATTRIBUTE_MAX_LENGTH instead of 256
José Fonseca632a78d2012-04-19 07:18:59 +0100679 print ' _glGetActiveAttrib(program, attrib, sizeof name, NULL, &size, &type, name);'
José Fonseca2a794f52011-05-26 20:54:29 +0100680 print " if (name[0] != 'g' || name[1] != 'l' || name[2] != '_') {"
José Fonseca632a78d2012-04-19 07:18:59 +0100681 print ' GLint location = _glGetAttribLocation(program, name);'
José Fonseca2a794f52011-05-26 20:54:29 +0100682 print ' if (location >= 0) {'
José Fonseca1b6c8752012-04-15 14:33:00 +0100683 bind_function = glapi.glapi.getFunctionByName('glBindAttribLocation')
José Fonseca91492d22011-05-23 21:20:31 +0100684 self.fake_call(bind_function, ['program', 'location', 'name'])
José Fonseca2a794f52011-05-26 20:54:29 +0100685 print ' }'
José Fonseca91492d22011-05-23 21:20:31 +0100686 print ' }'
687 print ' }'
688 if function.name == 'glLinkProgramARB':
José Fonseca54f304a2012-01-14 19:33:08 +0000689 Tracer.invokeFunction(self, function)
José Fonseca91492d22011-05-23 21:20:31 +0100690 print ' GLint active_attributes = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100691 print ' _glGetObjectParameterivARB(programObj, GL_OBJECT_ACTIVE_ATTRIBUTES_ARB, &active_attributes);'
José Fonseca7525e6f2011-09-28 09:04:56 +0100692 print ' for (GLint attrib = 0; attrib < active_attributes; ++attrib) {'
José Fonseca91492d22011-05-23 21:20:31 +0100693 print ' GLint size = 0;'
694 print ' GLenum type = 0;'
695 print ' GLcharARB name[256];'
696 # TODO: Use ACTIVE_ATTRIBUTE_MAX_LENGTH instead of 256
José Fonseca632a78d2012-04-19 07:18:59 +0100697 print ' _glGetActiveAttribARB(programObj, attrib, sizeof name, NULL, &size, &type, name);'
José Fonseca2a794f52011-05-26 20:54:29 +0100698 print " if (name[0] != 'g' || name[1] != 'l' || name[2] != '_') {"
José Fonseca632a78d2012-04-19 07:18:59 +0100699 print ' GLint location = _glGetAttribLocationARB(programObj, name);'
José Fonseca2a794f52011-05-26 20:54:29 +0100700 print ' if (location >= 0) {'
José Fonseca1b6c8752012-04-15 14:33:00 +0100701 bind_function = glapi.glapi.getFunctionByName('glBindAttribLocationARB')
José Fonseca91492d22011-05-23 21:20:31 +0100702 self.fake_call(bind_function, ['programObj', 'location', 'name'])
José Fonseca2a794f52011-05-26 20:54:29 +0100703 print ' }'
José Fonseca91492d22011-05-23 21:20:31 +0100704 print ' }'
705 print ' }'
706
Imre Deakd4937372012-04-24 14:06:48 +0300707 self.shadowBufferProlog(function)
708
José Fonseca54f304a2012-01-14 19:33:08 +0000709 Tracer.traceFunctionImplBody(self, function)
José Fonseca73373602011-05-20 17:45:26 +0100710
Peter Lohrmann0b5b75e2013-06-03 14:58:41 -0700711 # These entrypoints are only expected to be implemented by tools;
712 # drivers will probably not implement them.
José Fonsecaf028a8f2012-02-15 23:33:35 +0000713 marker_functions = [
714 # GL_GREMEDY_string_marker
José Fonseca8f34d342011-07-15 20:16:40 +0100715 'glStringMarkerGREMEDY',
José Fonsecaf028a8f2012-02-15 23:33:35 +0000716 # GL_GREMEDY_frame_terminator
José Fonseca8f34d342011-07-15 20:16:40 +0100717 'glFrameTerminatorGREMEDY',
José Fonsecaf028a8f2012-02-15 23:33:35 +0000718 # GL_EXT_debug_marker
719 'glInsertEventMarkerEXT',
720 'glPushGroupMarkerEXT',
721 'glPopGroupMarkerEXT',
José Fonseca8f34d342011-07-15 20:16:40 +0100722 ]
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',
748 ]
749
José Fonseca54f304a2012-01-14 19:33:08 +0000750 def invokeFunction(self, function):
José Fonseca91492d22011-05-23 21:20:31 +0100751 if function.name in ('glLinkProgram', 'glLinkProgramARB'):
752 # These functions have been dispatched already
753 return
754
José Fonseca2cfa02c2013-06-10 08:05:29 +0100755 Tracer.invokeFunction(self, function)
756
757 def doInvokeFunction(self, function):
758 # Same as invokeFunction() but called both when trace is enabled or disabled.
759 #
760 # Used to modify the behavior of GL entry-points.
761
762 # Override GL extensions
763 if function.name in ('glGetString', 'glGetIntegerv', 'glGetStringi'):
764 Tracer.doInvokeFunction(self, function, prefix = 'gltrace::_', suffix = '_override')
765 return
766
José Fonsecaf028a8f2012-02-15 23:33:35 +0000767 # We implement GL_EXT_debug_marker, GL_GREMEDY_*, etc., and not the
768 # driver
769 if function.name in self.marker_functions:
José Fonseca8f34d342011-07-15 20:16:40 +0100770 return
771
Peter Lohrmann9d9eb812013-07-12 16:15:25 -0400772 # We may be faking KHR_debug, so ensure the pointer queries result is
773 # always zeroed to prevent dereference of unitialized pointers
774 if function.name == 'glGetPointerv':
775 print ' if (params &&'
776 print ' (pname == GL_DEBUG_CALLBACK_FUNCTION ||'
777 print ' pname == GL_DEBUG_CALLBACK_USER_PARAM)) {'
778 print ' *params = NULL;'
779 print ' }'
780
José Fonseca2cfa02c2013-06-10 08:05:29 +0100781 if function.name in self.getProcAddressFunctionNames:
José Fonsecaf028a8f2012-02-15 23:33:35 +0000782 else_ = ''
783 for marker_function in self.marker_functions:
José Fonseca1b6c8752012-04-15 14:33:00 +0100784 if self.api.getFunctionByName(marker_function):
José Fonsecaf028a8f2012-02-15 23:33:35 +0000785 print ' %sif (strcmp("%s", (const char *)%s) == 0) {' % (else_, marker_function, function.args[0].name)
José Fonseca632a78d2012-04-19 07:18:59 +0100786 print ' _result = (%s)&%s;' % (function.type, marker_function)
José Fonsecaf028a8f2012-02-15 23:33:35 +0000787 print ' }'
788 else_ = 'else '
789 print ' %s{' % else_
José Fonseca2cfa02c2013-06-10 08:05:29 +0100790 Tracer.doInvokeFunction(self, function)
791
792 # Replace function addresses with ours
793 # XXX: Doing this here instead of wrapRet means that the trace will
794 # contain the addresses of the wrapper functions, and not the real
795 # functions, but in practice this should make no difference.
796 if function.name in self.getProcAddressFunctionNames:
797 print ' _result = _wrapProcAddress(%s, _result);' % (function.args[0].name,)
798
José Fonseca8f34d342011-07-15 20:16:40 +0100799 print ' }'
José Fonseca1b3d3752011-07-15 10:15:19 +0100800 return
801
José Fonseca2cfa02c2013-06-10 08:05:29 +0100802 Tracer.doInvokeFunction(self, function)
José Fonseca91492d22011-05-23 21:20:31 +0100803
José Fonseca867b1b72011-04-24 11:58:04 +0100804 buffer_targets = [
805 'ARRAY_BUFFER',
806 'ELEMENT_ARRAY_BUFFER',
807 'PIXEL_PACK_BUFFER',
808 'PIXEL_UNPACK_BUFFER',
José Fonseca7b20d672012-01-10 19:13:58 +0000809 'UNIFORM_BUFFER',
810 'TEXTURE_BUFFER',
811 'TRANSFORM_FEEDBACK_BUFFER',
812 'COPY_READ_BUFFER',
813 'COPY_WRITE_BUFFER',
814 'DRAW_INDIRECT_BUFFER',
815 'ATOMIC_COUNTER_BUFFER',
José Fonseca867b1b72011-04-24 11:58:04 +0100816 ]
817
José Fonseca54f304a2012-01-14 19:33:08 +0000818 def wrapRet(self, function, instance):
819 Tracer.wrapRet(self, function, instance)
José Fonseca1b3d3752011-07-15 10:15:19 +0100820
José Fonsecacdc322c2012-02-29 19:29:51 +0000821 # Keep track of buffer mappings
822 if function.name in ('glMapBuffer', 'glMapBufferARB'):
José Fonseca867b1b72011-04-24 11:58:04 +0100823 print ' struct buffer_mapping *mapping = get_buffer_mapping(target);'
824 print ' if (mapping) {'
825 print ' mapping->map = %s;' % (instance)
826 print ' mapping->length = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100827 print ' _glGetBufferParameteriv(target, GL_BUFFER_SIZE, &mapping->length);'
José Fonseca867b1b72011-04-24 11:58:04 +0100828 print ' mapping->write = (access != GL_READ_ONLY);'
José Fonseca73373602011-05-20 17:45:26 +0100829 print ' mapping->explicit_flush = false;'
José Fonseca867b1b72011-04-24 11:58:04 +0100830 print ' }'
José Fonseca867b1b72011-04-24 11:58:04 +0100831 if function.name == 'glMapBufferRange':
José Fonseca9c536b02012-02-29 20:54:13 +0000832 print ' if (access & GL_MAP_WRITE_BIT) {'
José Fonseca632a78d2012-04-19 07:18:59 +0100833 print ' _checkBufferMapRange = true;'
José Fonseca9c536b02012-02-29 20:54:13 +0000834 print ' }'
José Fonseca867b1b72011-04-24 11:58:04 +0100835 print ' struct buffer_mapping *mapping = get_buffer_mapping(target);'
836 print ' if (mapping) {'
837 print ' mapping->map = %s;' % (instance)
838 print ' mapping->length = length;'
839 print ' mapping->write = access & GL_MAP_WRITE_BIT;'
José Fonseca73373602011-05-20 17:45:26 +0100840 print ' mapping->explicit_flush = access & GL_MAP_FLUSH_EXPLICIT_BIT;'
José Fonseca867b1b72011-04-24 11:58:04 +0100841 print ' }'
José Fonseca669b1222011-02-20 09:05:10 +0000842
José Fonsecac9f12232011-03-25 20:07:42 +0000843 boolean_names = [
844 'GL_FALSE',
845 'GL_TRUE',
846 ]
847
848 def gl_boolean(self, value):
849 return self.boolean_names[int(bool(value))]
850
José Fonsecac29f4f12011-06-11 12:19:05 +0100851 # Names of the functions that unpack from a pixel buffer object. See the
852 # ARB_pixel_buffer_object specification.
José Fonsecae97bab92011-06-02 23:15:11 +0100853 unpack_function_names = set([
854 'glBitmap',
José Fonsecac29f4f12011-06-11 12:19:05 +0100855 'glColorSubTable',
856 'glColorTable',
José Fonsecad2bd4ca2013-04-12 11:41:00 +0100857 'glCompressedMultiTexImage1DEXT',
858 'glCompressedMultiTexImage2DEXT',
859 'glCompressedMultiTexImage3DEXT',
860 'glCompressedMultiTexSubImage1DEXT',
861 'glCompressedMultiTexSubImage2DEXT',
862 'glCompressedMultiTexSubImage3DEXT',
José Fonsecac29f4f12011-06-11 12:19:05 +0100863 'glCompressedTexImage1D',
idinevdb5ad3b2014-02-03 15:50:39 +0000864 'glCompressedTexImage1DARB',
José Fonsecac29f4f12011-06-11 12:19:05 +0100865 'glCompressedTexImage2D',
idinevdb5ad3b2014-02-03 15:50:39 +0000866 'glCompressedTexImage2DARB',
José Fonsecac29f4f12011-06-11 12:19:05 +0100867 'glCompressedTexImage3D',
idinevdb5ad3b2014-02-03 15:50:39 +0000868 'glCompressedTexImage3DARB',
José Fonsecac29f4f12011-06-11 12:19:05 +0100869 'glCompressedTexSubImage1D',
idinevdb5ad3b2014-02-03 15:50:39 +0000870 'glCompressedTexSubImage1DARB',
José Fonsecac29f4f12011-06-11 12:19:05 +0100871 'glCompressedTexSubImage2D',
idinevdb5ad3b2014-02-03 15:50:39 +0000872 'glCompressedTexSubImage2DARB',
José Fonsecac29f4f12011-06-11 12:19:05 +0100873 'glCompressedTexSubImage3D',
idinevdb5ad3b2014-02-03 15:50:39 +0000874 'glCompressedTexSubImage3DARB',
José Fonsecad2bd4ca2013-04-12 11:41:00 +0100875 'glCompressedTextureImage1DEXT',
876 'glCompressedTextureImage2DEXT',
877 'glCompressedTextureImage3DEXT',
878 'glCompressedTextureSubImage1DEXT',
879 'glCompressedTextureSubImage2DEXT',
880 'glCompressedTextureSubImage3DEXT',
José Fonsecac29f4f12011-06-11 12:19:05 +0100881 'glConvolutionFilter1D',
882 'glConvolutionFilter2D',
José Fonsecae97bab92011-06-02 23:15:11 +0100883 'glDrawPixels',
884 'glMultiTexImage1DEXT',
885 'glMultiTexImage2DEXT',
886 'glMultiTexImage3DEXT',
887 'glMultiTexSubImage1DEXT',
888 'glMultiTexSubImage2DEXT',
889 'glMultiTexSubImage3DEXT',
José Fonsecac29f4f12011-06-11 12:19:05 +0100890 'glPixelMapfv',
891 'glPixelMapuiv',
892 'glPixelMapusv',
José Fonsecae97bab92011-06-02 23:15:11 +0100893 'glPolygonStipple',
José Fonsecac29f4f12011-06-11 12:19:05 +0100894 'glSeparableFilter2D',
José Fonsecae97bab92011-06-02 23:15:11 +0100895 'glTexImage1D',
896 'glTexImage1DEXT',
897 'glTexImage2D',
898 'glTexImage2DEXT',
899 'glTexImage3D',
900 'glTexImage3DEXT',
901 'glTexSubImage1D',
902 'glTexSubImage1DEXT',
903 'glTexSubImage2D',
904 'glTexSubImage2DEXT',
905 'glTexSubImage3D',
906 'glTexSubImage3DEXT',
907 'glTextureImage1DEXT',
908 'glTextureImage2DEXT',
909 'glTextureImage3DEXT',
910 'glTextureSubImage1DEXT',
911 'glTextureSubImage2DEXT',
912 'glTextureSubImage3DEXT',
913 ])
914
José Fonseca54f304a2012-01-14 19:33:08 +0000915 def serializeArgValue(self, function, arg):
José Fonsecae97bab92011-06-02 23:15:11 +0100916 # Recognize offsets instead of blobs when a PBO is bound
917 if function.name in self.unpack_function_names \
918 and (isinstance(arg.type, stdapi.Blob) \
919 or (isinstance(arg.type, stdapi.Const) \
920 and isinstance(arg.type.type, stdapi.Blob))):
José Fonsecac29f4f12011-06-11 12:19:05 +0100921 print ' {'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000922 print ' gltrace::Context *ctx = gltrace::getContext();'
José Fonseca632a78d2012-04-19 07:18:59 +0100923 print ' GLint _unpack_buffer = 0;'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000924 print ' if (ctx->profile == gltrace::PROFILE_COMPAT)'
José Fonseca632a78d2012-04-19 07:18:59 +0100925 print ' _glGetIntegerv(GL_PIXEL_UNPACK_BUFFER_BINDING, &_unpack_buffer);'
926 print ' if (_unpack_buffer) {'
José Fonsecad559f022012-04-15 16:13:51 +0100927 print ' trace::localWriter.writePointer((uintptr_t)%s);' % arg.name
José Fonsecac29f4f12011-06-11 12:19:05 +0100928 print ' } else {'
José Fonseca54f304a2012-01-14 19:33:08 +0000929 Tracer.serializeArgValue(self, function, arg)
José Fonsecac29f4f12011-06-11 12:19:05 +0100930 print ' }'
José Fonsecae97bab92011-06-02 23:15:11 +0100931 print ' }'
932 return
933
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100934 # Several GL state functions take GLenum symbolic names as
935 # integer/floats; so dump the symbolic name whenever possible
José Fonseca3bcb33c2011-05-27 20:14:31 +0100936 if function.name.startswith('gl') \
José Fonsecae3571092011-10-13 08:26:27 +0100937 and arg.type in (glapi.GLint, glapi.GLfloat, glapi.GLdouble) \
José Fonseca3bcb33c2011-05-27 20:14:31 +0100938 and arg.name == 'param':
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100939 assert arg.index > 0
940 assert function.args[arg.index - 1].name == 'pname'
941 assert function.args[arg.index - 1].type == glapi.GLenum
942 print ' if (is_symbolic_pname(pname) && is_symbolic_param(%s)) {' % arg.name
José Fonseca54f304a2012-01-14 19:33:08 +0000943 self.serializeValue(glapi.GLenum, arg.name)
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100944 print ' } else {'
José Fonseca54f304a2012-01-14 19:33:08 +0000945 Tracer.serializeArgValue(self, function, arg)
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100946 print ' }'
947 return
948
José Fonseca54f304a2012-01-14 19:33:08 +0000949 Tracer.serializeArgValue(self, function, arg)
José Fonseca99221832011-03-22 22:15:46 +0000950
José Fonseca4c938c22011-04-30 22:44:38 +0100951 def footer(self, api):
952 Tracer.footer(self, api)
José Fonseca669b1222011-02-20 09:05:10 +0000953
José Fonseca4c938c22011-04-30 22:44:38 +0100954 # A simple state tracker to track the pointer values
José Fonseca669b1222011-02-20 09:05:10 +0000955 # update the state
José Fonseca14cb9ef2012-05-17 21:33:14 +0100956 print 'static void _trace_user_arrays(GLuint count)'
José Fonseca669b1222011-02-20 09:05:10 +0000957 print '{'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000958 print ' gltrace::Context *ctx = gltrace::getContext();'
José Fonseca8d1408b2014-02-03 19:57:18 +0000959 print
960
961 # Temporarily unbind the array buffer
962 print ' GLint _array_buffer = 0;'
963 print ' _glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &_array_buffer);'
964 print ' if (_array_buffer) {'
965 self.fake_glBindBuffer(api, 'GL_ARRAY_BUFFER', '0')
966 print ' }'
967 print
José Fonseca1a2fdd22011-04-01 00:55:09 +0100968
José Fonseca99221832011-03-22 22:15:46 +0000969 for camelcase_name, uppercase_name in self.arrays:
Chia-I Wub3d218d2011-11-03 01:37:36 +0800970 # in which profile is the array available?
José Fonsecaf028a8f2012-02-15 23:33:35 +0000971 profile_check = 'ctx->profile == gltrace::PROFILE_COMPAT'
Chia-I Wub3d218d2011-11-03 01:37:36 +0800972 if camelcase_name in self.arrays_es1:
José Fonsecaf028a8f2012-02-15 23:33:35 +0000973 profile_check = '(' + profile_check + ' || ctx->profile == gltrace::PROFILE_ES1)';
Chia-I Wub3d218d2011-11-03 01:37:36 +0800974
José Fonseca99221832011-03-22 22:15:46 +0000975 function_name = 'gl%sPointer' % camelcase_name
976 enable_name = 'GL_%s_ARRAY' % uppercase_name
977 binding_name = 'GL_%s_ARRAY_BUFFER_BINDING' % uppercase_name
José Fonseca1b6c8752012-04-15 14:33:00 +0100978 function = api.getFunctionByName(function_name)
José Fonseca99221832011-03-22 22:15:46 +0000979
José Fonseca06e85192011-10-16 14:15:36 +0100980 print ' // %s' % function.prototype()
Chia-I Wub3d218d2011-11-03 01:37:36 +0800981 print ' if (%s) {' % profile_check
José Fonsecafb6744f2011-04-15 11:18:37 +0100982 self.array_trace_prolog(api, uppercase_name)
983 self.array_prolog(api, uppercase_name)
José Fonseca632a78d2012-04-19 07:18:59 +0100984 print ' if (_glIsEnabled(%s)) {' % enable_name
985 print ' GLint _binding = 0;'
986 print ' _glGetIntegerv(%s, &_binding);' % binding_name
987 print ' if (!_binding) {'
José Fonseca99221832011-03-22 22:15:46 +0000988
989 # Get the arguments via glGet*
990 for arg in function.args:
991 arg_get_enum = 'GL_%s_ARRAY_%s' % (uppercase_name, arg.name.upper())
992 arg_get_function, arg_type = TypeGetter().visit(arg.type)
José Fonseca7f5163e2011-03-31 23:37:26 +0100993 print ' %s %s = 0;' % (arg_type, arg.name)
José Fonseca632a78d2012-04-19 07:18:59 +0100994 print ' _%s(%s, &%s);' % (arg_get_function, arg_get_enum, arg.name)
José Fonseca99221832011-03-22 22:15:46 +0000995
996 arg_names = ', '.join([arg.name for arg in function.args[:-1]])
José Fonseca14cb9ef2012-05-17 21:33:14 +0100997 print ' size_t _size = _%s_size(%s, count);' % (function.name, arg_names)
José Fonseca99221832011-03-22 22:15:46 +0000998
999 # Emit a fake function
José Fonsecafb6744f2011-04-15 11:18:37 +01001000 self.array_trace_intermezzo(api, uppercase_name)
José Fonseca632a78d2012-04-19 07:18:59 +01001001 print ' unsigned _call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,)
José Fonseca669b1222011-02-20 09:05:10 +00001002 for arg in function.args:
1003 assert not arg.output
José Fonsecab4a3d142011-10-27 07:43:19 +01001004 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
José Fonseca14c21bc2011-02-20 23:32:22 +00001005 if arg.name != 'pointer':
José Fonseca54f304a2012-01-14 19:33:08 +00001006 self.serializeValue(arg.type, arg.name)
José Fonseca14c21bc2011-02-20 23:32:22 +00001007 else:
José Fonseca632a78d2012-04-19 07:18:59 +01001008 print ' trace::localWriter.writeBlob((const void *)%s, _size);' % (arg.name)
José Fonsecab4a3d142011-10-27 07:43:19 +01001009 print ' trace::localWriter.endArg();'
José Fonseca99221832011-03-22 22:15:46 +00001010
José Fonsecab4a3d142011-10-27 07:43:19 +01001011 print ' trace::localWriter.endEnter();'
José Fonseca632a78d2012-04-19 07:18:59 +01001012 print ' trace::localWriter.beginLeave(_call);'
José Fonsecab4a3d142011-10-27 07:43:19 +01001013 print ' trace::localWriter.endLeave();'
José Fonseca99221832011-03-22 22:15:46 +00001014 print ' }'
José Fonseca669b1222011-02-20 09:05:10 +00001015 print ' }'
José Fonsecafb6744f2011-04-15 11:18:37 +01001016 self.array_epilog(api, uppercase_name)
1017 self.array_trace_epilog(api, uppercase_name)
Chia-I Wub3d218d2011-11-03 01:37:36 +08001018 print ' }'
José Fonseca99221832011-03-22 22:15:46 +00001019 print
José Fonseca1a2fdd22011-04-01 00:55:09 +01001020
José Fonseca1601c412011-05-10 10:38:19 +01001021 # Samething, but for glVertexAttribPointer*
1022 #
1023 # Some variants of glVertexAttribPointer alias conventional and generic attributes:
1024 # - glVertexAttribPointer: no
1025 # - glVertexAttribPointerARB: implementation dependent
1026 # - glVertexAttribPointerNV: yes
1027 #
1028 # This means that the implementations of these functions do not always
1029 # alias, and they need to be considered independently.
1030 #
Chia-I Wub3d218d2011-11-03 01:37:36 +08001031 print ' // ES1 does not support generic vertex attributes'
José Fonsecaf028a8f2012-02-15 23:33:35 +00001032 print ' if (ctx->profile == gltrace::PROFILE_ES1)'
Chia-I Wub3d218d2011-11-03 01:37:36 +08001033 print ' return;'
1034 print
José Fonseca632a78d2012-04-19 07:18:59 +01001035 print ' vertex_attrib _vertex_attrib = _get_vertex_attrib();'
José Fonseca5a568a92011-06-29 16:43:36 +01001036 print
1037 for suffix in ['', 'ARB', 'NV']:
1038 if suffix:
José Fonsecad94aaac2011-06-28 20:50:49 +01001039 SUFFIX = '_' + suffix
José Fonsecad94aaac2011-06-28 20:50:49 +01001040 else:
José Fonseca5a568a92011-06-29 16:43:36 +01001041 SUFFIX = suffix
José Fonseca1601c412011-05-10 10:38:19 +01001042 function_name = 'glVertexAttribPointer' + suffix
José Fonseca1b6c8752012-04-15 14:33:00 +01001043 function = api.getFunctionByName(function_name)
José Fonseca06e85192011-10-16 14:15:36 +01001044
1045 print ' // %s' % function.prototype()
José Fonseca632a78d2012-04-19 07:18:59 +01001046 print ' if (_vertex_attrib == VERTEX_ATTRIB%s) {' % SUFFIX
José Fonseca5a568a92011-06-29 16:43:36 +01001047 if suffix == 'NV':
José Fonseca632a78d2012-04-19 07:18:59 +01001048 print ' GLint _max_vertex_attribs = 16;'
José Fonseca5a568a92011-06-29 16:43:36 +01001049 else:
José Fonseca632a78d2012-04-19 07:18:59 +01001050 print ' GLint _max_vertex_attribs = 0;'
1051 print ' _glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &_max_vertex_attribs);'
1052 print ' for (GLint index = 0; index < _max_vertex_attribs; ++index) {'
1053 print ' GLint _enabled = 0;'
José Fonseca5a568a92011-06-29 16:43:36 +01001054 if suffix == 'NV':
José Fonseca632a78d2012-04-19 07:18:59 +01001055 print ' _glGetIntegerv(GL_VERTEX_ATTRIB_ARRAY0_NV + index, &_enabled);'
José Fonseca5a568a92011-06-29 16:43:36 +01001056 else:
José Fonseca632a78d2012-04-19 07:18:59 +01001057 print ' _glGetVertexAttribiv%s(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED%s, &_enabled);' % (suffix, SUFFIX)
1058 print ' if (_enabled) {'
1059 print ' GLint _binding = 0;'
José Fonseca5a568a92011-06-29 16:43:36 +01001060 if suffix != 'NV':
1061 # It doesn't seem possible to use VBOs with NV_vertex_program.
José Fonseca632a78d2012-04-19 07:18:59 +01001062 print ' _glGetVertexAttribiv%s(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING%s, &_binding);' % (suffix, SUFFIX)
1063 print ' if (!_binding) {'
José Fonseca1a2fdd22011-04-01 00:55:09 +01001064
José Fonseca1601c412011-05-10 10:38:19 +01001065 # Get the arguments via glGet*
1066 for arg in function.args[1:]:
José Fonseca5a568a92011-06-29 16:43:36 +01001067 if suffix == 'NV':
1068 arg_get_enum = 'GL_ATTRIB_ARRAY_%s%s' % (arg.name.upper(), SUFFIX)
1069 else:
1070 arg_get_enum = 'GL_VERTEX_ATTRIB_ARRAY_%s%s' % (arg.name.upper(), SUFFIX)
José Fonsecac493e3e2011-06-29 12:57:06 +01001071 arg_get_function, arg_type = TypeGetter('glGetVertexAttrib', False, suffix).visit(arg.type)
José Fonseca5a568a92011-06-29 16:43:36 +01001072 print ' %s %s = 0;' % (arg_type, arg.name)
José Fonseca632a78d2012-04-19 07:18:59 +01001073 print ' _%s(index, %s, &%s);' % (arg_get_function, arg_get_enum, arg.name)
José Fonseca1601c412011-05-10 10:38:19 +01001074
1075 arg_names = ', '.join([arg.name for arg in function.args[1:-1]])
José Fonseca14cb9ef2012-05-17 21:33:14 +01001076 print ' size_t _size = _%s_size(%s, count);' % (function.name, arg_names)
José Fonseca1a2fdd22011-04-01 00:55:09 +01001077
José Fonseca1601c412011-05-10 10:38:19 +01001078 # Emit a fake function
José Fonseca632a78d2012-04-19 07:18:59 +01001079 print ' unsigned _call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,)
José Fonseca1601c412011-05-10 10:38:19 +01001080 for arg in function.args:
1081 assert not arg.output
José Fonsecab4a3d142011-10-27 07:43:19 +01001082 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
José Fonseca1601c412011-05-10 10:38:19 +01001083 if arg.name != 'pointer':
José Fonseca54f304a2012-01-14 19:33:08 +00001084 self.serializeValue(arg.type, arg.name)
José Fonseca1601c412011-05-10 10:38:19 +01001085 else:
José Fonseca632a78d2012-04-19 07:18:59 +01001086 print ' trace::localWriter.writeBlob((const void *)%s, _size);' % (arg.name)
José Fonsecab4a3d142011-10-27 07:43:19 +01001087 print ' trace::localWriter.endArg();'
José Fonseca1601c412011-05-10 10:38:19 +01001088
José Fonsecab4a3d142011-10-27 07:43:19 +01001089 print ' trace::localWriter.endEnter();'
José Fonseca632a78d2012-04-19 07:18:59 +01001090 print ' trace::localWriter.beginLeave(_call);'
José Fonsecab4a3d142011-10-27 07:43:19 +01001091 print ' trace::localWriter.endLeave();'
José Fonseca1601c412011-05-10 10:38:19 +01001092 print ' }'
1093 print ' }'
1094 print ' }'
1095 print ' }'
1096 print
José Fonseca1a2fdd22011-04-01 00:55:09 +01001097
José Fonseca8d1408b2014-02-03 19:57:18 +00001098 # Restore the original array_buffer
1099 print ' if (_array_buffer) {'
1100 self.fake_glBindBuffer(api, 'GL_ARRAY_BUFFER', '_array_buffer')
1101 print ' }'
1102 print
1103
José Fonseca669b1222011-02-20 09:05:10 +00001104 print '}'
1105 print
1106
José Fonsecafb6744f2011-04-15 11:18:37 +01001107 #
1108 # Hooks for glTexCoordPointer, which is identical to the other array
1109 # pointers except the fact that it is indexed by glClientActiveTexture.
1110 #
1111
1112 def array_prolog(self, api, uppercase_name):
1113 if uppercase_name == 'TEXTURE_COORD':
1114 print ' GLint client_active_texture = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +01001115 print ' _glGetIntegerv(GL_CLIENT_ACTIVE_TEXTURE, &client_active_texture);'
José Fonsecafb6744f2011-04-15 11:18:37 +01001116 print ' GLint max_texture_coords = 0;'
José Fonsecaf028a8f2012-02-15 23:33:35 +00001117 print ' if (ctx->profile == gltrace::PROFILE_COMPAT)'
José Fonseca632a78d2012-04-19 07:18:59 +01001118 print ' _glGetIntegerv(GL_MAX_TEXTURE_COORDS, &max_texture_coords);'
Chia-I Wub3d218d2011-11-03 01:37:36 +08001119 print ' else'
José Fonseca632a78d2012-04-19 07:18:59 +01001120 print ' _glGetIntegerv(GL_MAX_TEXTURE_UNITS, &max_texture_coords);'
José Fonsecafb6744f2011-04-15 11:18:37 +01001121 print ' for (GLint unit = 0; unit < max_texture_coords; ++unit) {'
José Fonseca7525e6f2011-09-28 09:04:56 +01001122 print ' GLint texture = GL_TEXTURE0 + unit;'
José Fonseca632a78d2012-04-19 07:18:59 +01001123 print ' _glClientActiveTexture(texture);'
José Fonsecafb6744f2011-04-15 11:18:37 +01001124
1125 def array_trace_prolog(self, api, uppercase_name):
1126 if uppercase_name == 'TEXTURE_COORD':
1127 print ' bool client_active_texture_dirty = false;'
1128
1129 def array_epilog(self, api, uppercase_name):
1130 if uppercase_name == 'TEXTURE_COORD':
1131 print ' }'
1132 self.array_cleanup(api, uppercase_name)
1133
1134 def array_cleanup(self, api, uppercase_name):
1135 if uppercase_name == 'TEXTURE_COORD':
José Fonseca632a78d2012-04-19 07:18:59 +01001136 print ' _glClientActiveTexture(client_active_texture);'
José Fonsecafb6744f2011-04-15 11:18:37 +01001137
1138 def array_trace_intermezzo(self, api, uppercase_name):
1139 if uppercase_name == 'TEXTURE_COORD':
1140 print ' if (texture != client_active_texture || client_active_texture_dirty) {'
1141 print ' client_active_texture_dirty = true;'
1142 self.fake_glClientActiveTexture_call(api, "texture");
1143 print ' }'
1144
1145 def array_trace_epilog(self, api, uppercase_name):
1146 if uppercase_name == 'TEXTURE_COORD':
1147 print ' if (client_active_texture_dirty) {'
1148 self.fake_glClientActiveTexture_call(api, "client_active_texture");
1149 print ' }'
1150
José Fonseca8d1408b2014-02-03 19:57:18 +00001151 def fake_glBindBuffer(self, api, target, buffer):
1152 function = api.getFunctionByName('glBindBuffer')
1153 self.fake_call(function, [target, buffer])
1154
José Fonsecafb6744f2011-04-15 11:18:37 +01001155 def fake_glClientActiveTexture_call(self, api, texture):
José Fonseca1b6c8752012-04-15 14:33:00 +01001156 function = api.getFunctionByName('glClientActiveTexture')
José Fonsecafb6744f2011-04-15 11:18:37 +01001157 self.fake_call(function, [texture])
1158
José Fonseca151c3702013-05-10 08:28:15 +01001159 def emitFakeTexture2D(self):
1160 function = glapi.glapi.getFunctionByName('glTexImage2D')
1161 instances = function.argNames()
1162 print ' unsigned _fake_call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,)
1163 for arg in function.args:
1164 assert not arg.output
1165 self.serializeArg(function, arg)
1166 print ' trace::localWriter.endEnter();'
1167 print ' trace::localWriter.beginLeave(_fake_call);'
1168 print ' trace::localWriter.endLeave();'
José Fonsecafb6744f2011-04-15 11:18:37 +01001169
1170
1171
1172
1173
José Fonseca669b1222011-02-20 09:05:10 +00001174
1175
1176
1177
1178
1179