blob: 33485a7d6524394bb202dd094ca17f24cf3f1e02 [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,'
José Fonseca5a568a92011-06-29 16:43:36 +0100122 print ' VERTEX_ATTRIB_NV,'
123 print '};'
124 print
José Fonseca632a78d2012-04-19 07:18:59 +0100125 print 'static vertex_attrib _get_vertex_attrib(void) {'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000126 print ' gltrace::Context *ctx = gltrace::getContext();'
José Fonseca74b661a2014-07-17 19:10:24 +0100127 print ' if (ctx->user_arrays_nv) {'
José Fonseca632a78d2012-04-19 07:18:59 +0100128 print ' GLboolean _vertex_program = GL_FALSE;'
129 print ' _glGetBooleanv(GL_VERTEX_PROGRAM_ARB, &_vertex_program);'
130 print ' if (_vertex_program) {'
Chia-I Wu8ef66972011-11-03 01:19:46 +0800131 print ' if (ctx->user_arrays_nv) {'
José Fonseca26be8f92014-03-07 14:08:50 +0000132 print ' GLint _vertex_program_binding_nv = _glGetInteger(GL_VERTEX_PROGRAM_BINDING_NV);'
José Fonseca632a78d2012-04-19 07:18:59 +0100133 print ' if (_vertex_program_binding_nv) {'
José Fonseca5a568a92011-06-29 16:43:36 +0100134 print ' return VERTEX_ATTRIB_NV;'
135 print ' }'
136 print ' }'
José Fonseca5a568a92011-06-29 16:43:36 +0100137 print ' }'
138 print ' }'
139 print ' return VERTEX_ATTRIB;'
140 print '}'
141 print
142
Imre Deakd4937372012-04-24 14:06:48 +0300143 self.defineShadowBufferHelper()
144
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000145 # Whether we need user arrays
José Fonseca632a78d2012-04-19 07:18:59 +0100146 print 'static inline bool _need_user_arrays(void)'
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000147 print '{'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000148 print ' gltrace::Context *ctx = gltrace::getContext();'
Chia-I Wu8ef66972011-11-03 01:19:46 +0800149 print ' if (!ctx->user_arrays) {'
José Fonseca25ebe542011-04-24 10:08:22 +0100150 print ' return false;'
151 print ' }'
152 print
José Fonseca8b04b5a2014-07-17 19:25:21 +0100153 print ' enum gltrace::Profile profile = ctx->profile;'
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é Fonseca8b04b5a2014-07-17 19:25:21 +0100158 profile_check = 'profile == gltrace::PROFILE_COMPAT'
Chia-I Wub3d218d2011-11-03 01:37:36 +0800159 if camelcase_name in self.arrays_es1:
José Fonseca8b04b5a2014-07-17 19:25:21 +0100160 profile_check = '(' + profile_check + ' || 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é Fonseca8b04b5a2014-07-17 19:25:21 +0100168 print ' if (_glIsEnabled(%s) &&' % enable_name
169 print ' _glGetInteger(%s) == 0) {' % binding_name
José Fonsecafb6744f2011-04-15 11:18:37 +0100170 self.array_cleanup(api, uppercase_name)
José Fonseca8b04b5a2014-07-17 19:25:21 +0100171 print ' return true;'
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000172 print ' }'
José Fonsecafb6744f2011-04-15 11:18:37 +0100173 self.array_epilog(api, uppercase_name)
Chia-I Wub3d218d2011-11-03 01:37:36 +0800174 print ' }'
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000175 print
José Fonseca7f5163e2011-03-31 23:37:26 +0100176
Chia-I Wub3d218d2011-11-03 01:37:36 +0800177 print ' // ES1 does not support generic vertex attributes'
José Fonseca8b04b5a2014-07-17 19:25:21 +0100178 print ' if (profile == gltrace::PROFILE_ES1)'
Chia-I Wub3d218d2011-11-03 01:37:36 +0800179 print ' return false;'
180 print
José Fonseca632a78d2012-04-19 07:18:59 +0100181 print ' vertex_attrib _vertex_attrib = _get_vertex_attrib();'
José Fonseca5a568a92011-06-29 16:43:36 +0100182 print
183 print ' // glVertexAttribPointer'
José Fonseca632a78d2012-04-19 07:18:59 +0100184 print ' if (_vertex_attrib == VERTEX_ATTRIB) {'
José Fonseca26be8f92014-03-07 14:08:50 +0000185 print ' GLint _max_vertex_attribs = _glGetInteger(GL_MAX_VERTEX_ATTRIBS);'
José Fonseca632a78d2012-04-19 07:18:59 +0100186 print ' for (GLint index = 0; index < _max_vertex_attribs; ++index) {'
José Fonseca8b04b5a2014-07-17 19:25:21 +0100187 print ' if (_glGetVertexAttribi(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED) &&'
188 print ' _glGetVertexAttribi(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING) == 0) {'
189 print ' return true;'
José Fonseca5a568a92011-06-29 16:43:36 +0100190 print ' }'
191 print ' }'
192 print ' }'
193 print
José Fonseca5a568a92011-06-29 16:43:36 +0100194 print ' // glVertexAttribPointerNV'
José Fonseca632a78d2012-04-19 07:18:59 +0100195 print ' if (_vertex_attrib == VERTEX_ATTRIB_NV) {'
José Fonseca5a568a92011-06-29 16:43:36 +0100196 print ' for (GLint index = 0; index < 16; ++index) {'
José Fonseca8b04b5a2014-07-17 19:25:21 +0100197 print ' if (_glIsEnabled(GL_VERTEX_ATTRIB_ARRAY0_NV + index)) {'
José Fonseca5a568a92011-06-29 16:43:36 +0100198 print ' return true;'
José Fonseca1a2fdd22011-04-01 00:55:09 +0100199 print ' }'
200 print ' }'
201 print ' }'
202 print
203
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000204 print ' return false;'
205 print '}'
206 print
José Fonseca669b1222011-02-20 09:05:10 +0000207
José Fonseca14cb9ef2012-05-17 21:33:14 +0100208 print 'static void _trace_user_arrays(GLuint count);'
José Fonseca14c21bc2011-02-20 23:32:22 +0000209 print
José Fonseca867b1b72011-04-24 11:58:04 +0100210
José Fonseca707630d2014-03-07 14:20:35 +0000211 print '// whether glLockArraysEXT() has ever been called'
212 print 'static bool _checkLockArraysEXT = false;'
213 print
214
José Fonseca9c536b02012-02-29 20:54:13 +0000215 # Buffer mappings
216 print '// whether glMapBufferRange(GL_MAP_WRITE_BIT) has ever been called'
José Fonseca632a78d2012-04-19 07:18:59 +0100217 print 'static bool _checkBufferMapRange = false;'
José Fonseca9c536b02012-02-29 20:54:13 +0000218 print
219 print '// whether glBufferParameteriAPPLE(GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE) has ever been called'
José Fonseca632a78d2012-04-19 07:18:59 +0100220 print 'static bool _checkBufferFlushingUnmapAPPLE = false;'
José Fonseca9c536b02012-02-29 20:54:13 +0000221 print
222 # Buffer mapping information, necessary for old Mesa 2.1 drivers which
223 # do not support glGetBufferParameteriv(GL_BUFFER_ACCESS_FLAGS/GL_BUFFER_MAP_LENGTH)
José Fonseca867b1b72011-04-24 11:58:04 +0100224 print 'struct buffer_mapping {'
225 print ' void *map;'
226 print ' GLint length;'
227 print ' bool write;'
José Fonseca73373602011-05-20 17:45:26 +0100228 print ' bool explicit_flush;'
José Fonseca867b1b72011-04-24 11:58:04 +0100229 print '};'
230 print
231 for target in self.buffer_targets:
José Fonseca632a78d2012-04-19 07:18:59 +0100232 print 'struct buffer_mapping _%s_mapping;' % target.lower();
José Fonseca867b1b72011-04-24 11:58:04 +0100233 print
234 print 'static inline struct buffer_mapping *'
235 print 'get_buffer_mapping(GLenum target) {'
José Fonseca06e85192011-10-16 14:15:36 +0100236 print ' switch (target) {'
José Fonseca867b1b72011-04-24 11:58:04 +0100237 for target in self.buffer_targets:
238 print ' case GL_%s:' % target
José Fonseca632a78d2012-04-19 07:18:59 +0100239 print ' return & _%s_mapping;' % target.lower()
José Fonseca867b1b72011-04-24 11:58:04 +0100240 print ' default:'
José Fonseca559d5342011-10-27 08:10:56 +0100241 print ' os::log("apitrace: warning: unknown buffer target 0x%04X\\n", target);'
José Fonseca867b1b72011-04-24 11:58:04 +0100242 print ' return NULL;'
243 print ' }'
244 print '}'
245 print
246
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100247 # Generate a helper function to determine whether a parameter name
248 # refers to a symbolic value or not
249 print 'static bool'
250 print 'is_symbolic_pname(GLenum pname) {'
José Fonseca06e85192011-10-16 14:15:36 +0100251 print ' switch (pname) {'
José Fonseca5ea91872011-05-04 09:41:55 +0100252 for function, type, count, name in glparams.parameters:
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100253 if type is glapi.GLenum:
José Fonseca4c938c22011-04-30 22:44:38 +0100254 print ' case %s:' % name
255 print ' return true;'
256 print ' default:'
257 print ' return false;'
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100258 print ' }'
259 print '}'
260 print
261
262 # Generate a helper function to determine whether a parameter value is
263 # potentially symbolic or not; i.e., if the value can be represented in
264 # an enum or not
265 print 'template<class T>'
266 print 'static inline bool'
267 print 'is_symbolic_param(T param) {'
268 print ' return static_cast<T>(static_cast<GLenum>(param)) == param;'
269 print '}'
270 print
José Fonseca4c938c22011-04-30 22:44:38 +0100271
272 # Generate a helper function to know how many elements a parameter has
273 print 'static size_t'
José Fonseca632a78d2012-04-19 07:18:59 +0100274 print '_gl_param_size(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é Fonseca4c938c22011-04-30 22:44:38 +0100277 if type is not None:
José Fonsecaddf6d2c2012-12-20 15:34:50 +0000278 print ' case %s: return %s;' % (name, count)
José Fonseca4c938c22011-04-30 22:44:38 +0100279 print ' default:'
José Fonseca559d5342011-10-27 08:10:56 +0100280 print r' os::log("apitrace: warning: %s: unknown GLenum 0x%04X\n", __FUNCTION__, pname);'
José Fonseca4c938c22011-04-30 22:44:38 +0100281 print ' return 1;'
282 print ' }'
283 print '}'
284 print
285
Chia-I Wu335efb42011-11-03 01:59:22 +0800286 # states such as GL_UNPACK_ROW_LENGTH are not available in GLES
287 print 'static inline bool'
288 print 'can_unpack_subimage(void) {'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000289 print ' gltrace::Context *ctx = gltrace::getContext();'
290 print ' return (ctx->profile == gltrace::PROFILE_COMPAT);'
Chia-I Wu335efb42011-11-03 01:59:22 +0800291 print '}'
292 print
293
José Fonseca1b6c8752012-04-15 14:33:00 +0100294 getProcAddressFunctionNames = []
295
296 def traceApi(self, api):
297 if self.getProcAddressFunctionNames:
298 # Generate a function to wrap proc addresses
299 getProcAddressFunction = api.getFunctionByName(self.getProcAddressFunctionNames[0])
300 argType = getProcAddressFunction.args[0].type
301 retType = getProcAddressFunction.type
302
303 print 'static %s _wrapProcAddress(%s procName, %s procPtr);' % (retType, argType, retType)
304 print
305
306 Tracer.traceApi(self, api)
307
308 print 'static %s _wrapProcAddress(%s procName, %s procPtr) {' % (retType, argType, retType)
Peter Lohrmann0b5b75e2013-06-03 14:58:41 -0700309
310 # Provide fallback functions to missing debug functions
José Fonseca1b6c8752012-04-15 14:33:00 +0100311 print ' if (!procPtr) {'
Peter Lohrmann0b5b75e2013-06-03 14:58:41 -0700312 else_ = ''
313 for function_name in self.debug_functions:
314 if self.api.getFunctionByName(function_name):
315 print ' %sif (strcmp("%s", (const char *)procName) == 0) {' % (else_, function_name)
316 print ' return (%s)&%s;' % (retType, function_name)
317 print ' }'
318 else_ = 'else '
319 print ' %s{' % else_
320 print ' return NULL;'
321 print ' }'
José Fonseca1b6c8752012-04-15 14:33:00 +0100322 print ' }'
Peter Lohrmann0b5b75e2013-06-03 14:58:41 -0700323
José Fonseca81301932012-11-11 00:10:20 +0000324 for function in api.getAllFunctions():
José Fonseca1b6c8752012-04-15 14:33:00 +0100325 ptype = function_pointer_type(function)
326 pvalue = function_pointer_value(function)
327 print ' if (strcmp("%s", (const char *)procName) == 0) {' % function.name
328 print ' %s = (%s)procPtr;' % (pvalue, ptype)
329 print ' return (%s)&%s;' % (retType, function.name,)
330 print ' }'
331 print ' os::log("apitrace: warning: unknown function \\"%s\\"\\n", (const char *)procName);'
332 print ' return procPtr;'
333 print '}'
334 print
335 else:
336 Tracer.traceApi(self, api)
337
Imre Deakd4937372012-04-24 14:06:48 +0300338 def defineShadowBufferHelper(self):
339 print 'void _shadow_glGetBufferSubData(GLenum target, GLintptr offset,'
340 print ' GLsizeiptr size, GLvoid *data)'
341 print '{'
José Fonsecaa33d0bb2012-11-10 09:11:42 +0000342 print ' gltrace::Context *ctx = gltrace::getContext();'
Imre Deakd4937372012-04-24 14:06:48 +0300343 print ' if (!ctx->needsShadowBuffers() || target != GL_ELEMENT_ARRAY_BUFFER) {'
José Fonseca219c9f22012-11-03 10:13:17 +0000344 print ' _glGetBufferSubData(target, offset, size, data);'
Imre Deakd4937372012-04-24 14:06:48 +0300345 print ' return;'
346 print ' }'
347 print
José Fonseca26be8f92014-03-07 14:08:50 +0000348 print ' GLint buffer_binding = _glGetInteger(GL_ELEMENT_ARRAY_BUFFER_BINDING);'
José Fonseca219c9f22012-11-03 10:13:17 +0000349 print ' if (buffer_binding > 0) {'
350 print ' gltrace::Buffer & buf = ctx->buffers[buffer_binding];'
351 print ' buf.getSubData(offset, size, data);'
352 print ' }'
Imre Deakd4937372012-04-24 14:06:48 +0300353 print '}'
354
José Fonseca219c9f22012-11-03 10:13:17 +0000355 def shadowBufferMethod(self, method):
356 # Emit code to fetch the shadow buffer, and invoke a method
357 print ' gltrace::Context *ctx = gltrace::getContext();'
358 print ' if (ctx->needsShadowBuffers() && target == GL_ELEMENT_ARRAY_BUFFER) {'
José Fonseca26be8f92014-03-07 14:08:50 +0000359 print ' GLint buffer_binding = _glGetInteger(GL_ELEMENT_ARRAY_BUFFER_BINDING);'
José Fonseca219c9f22012-11-03 10:13:17 +0000360 print ' if (buffer_binding > 0) {'
361 print ' gltrace::Buffer & buf = ctx->buffers[buffer_binding];'
362 print ' buf.' + method + ';'
363 print ' }'
364 print ' }'
365 print
366
Imre Deakd4937372012-04-24 14:06:48 +0300367 def shadowBufferProlog(self, function):
368 if function.name == 'glBufferData':
José Fonseca219c9f22012-11-03 10:13:17 +0000369 self.shadowBufferMethod('bufferData(size, data)')
Imre Deakd4937372012-04-24 14:06:48 +0300370
371 if function.name == 'glBufferSubData':
José Fonseca219c9f22012-11-03 10:13:17 +0000372 self.shadowBufferMethod('bufferSubData(offset, size, data)')
Imre Deakd4937372012-04-24 14:06:48 +0300373
374 if function.name == 'glDeleteBuffers':
375 print ' gltrace::Context *ctx = gltrace::getContext();'
376 print ' if (ctx->needsShadowBuffers()) {'
José Fonseca219c9f22012-11-03 10:13:17 +0000377 print ' for (GLsizei i = 0; i < n; i++) {'
378 print ' ctx->buffers.erase(buffer[i]);'
Imre Deakd4937372012-04-24 14:06:48 +0300379 print ' }'
380 print ' }'
381
José Fonseca99221832011-03-22 22:15:46 +0000382 array_pointer_function_names = set((
383 "glVertexPointer",
384 "glNormalPointer",
385 "glColorPointer",
386 "glIndexPointer",
387 "glTexCoordPointer",
388 "glEdgeFlagPointer",
389 "glFogCoordPointer",
390 "glSecondaryColorPointer",
José Fonseca7f5163e2011-03-31 23:37:26 +0100391
José Fonsecaac5285b2011-05-04 11:09:08 +0100392 "glInterleavedArrays",
393
José Fonseca7e0bfd92011-04-30 23:09:03 +0100394 "glVertexPointerEXT",
395 "glNormalPointerEXT",
396 "glColorPointerEXT",
397 "glIndexPointerEXT",
398 "glTexCoordPointerEXT",
399 "glEdgeFlagPointerEXT",
400 "glFogCoordPointerEXT",
401 "glSecondaryColorPointerEXT",
José Fonseca99221832011-03-22 22:15:46 +0000402
José Fonseca7f5163e2011-03-31 23:37:26 +0100403 "glVertexAttribPointer",
404 "glVertexAttribPointerARB",
405 "glVertexAttribPointerNV",
José Fonsecaac5285b2011-05-04 11:09:08 +0100406 "glVertexAttribIPointer",
407 "glVertexAttribIPointerEXT",
José Fonseca7f5163e2011-03-31 23:37:26 +0100408 "glVertexAttribLPointer",
409 "glVertexAttribLPointerEXT",
José Fonseca99221832011-03-22 22:15:46 +0000410
411 #"glMatrixIndexPointerARB",
412 ))
413
414 draw_function_names = set((
415 'glDrawArrays',
416 'glDrawElements',
417 'glDrawRangeElements',
José Fonseca5c749e32011-05-09 11:11:37 +0100418 'glMultiDrawArrays',
419 'glMultiDrawElements',
420 'glDrawArraysInstanced',
José Fonsecaff8848b2011-10-09 01:04:17 +0100421 "glDrawArraysInstancedBaseInstance",
José Fonseca5c749e32011-05-09 11:11:37 +0100422 'glDrawElementsInstanced',
423 'glDrawArraysInstancedARB',
424 'glDrawElementsInstancedARB',
425 'glDrawElementsBaseVertex',
426 'glDrawRangeElementsBaseVertex',
427 'glDrawElementsInstancedBaseVertex',
José Fonsecaff8848b2011-10-09 01:04:17 +0100428 "glDrawElementsInstancedBaseInstance",
429 "glDrawElementsInstancedBaseVertexBaseInstance",
José Fonseca5c749e32011-05-09 11:11:37 +0100430 'glMultiDrawElementsBaseVertex',
431 'glDrawArraysIndirect',
432 'glDrawElementsIndirect',
José Fonseca29ac7c72013-04-14 15:40:01 +0100433 'glMultiDrawArraysIndirect',
434 'glMultiDrawArraysIndirectAMD',
435 'glMultiDrawElementsIndirect',
436 'glMultiDrawElementsIndirectAMD',
José Fonseca5c749e32011-05-09 11:11:37 +0100437 'glDrawArraysEXT',
José Fonseca7e0bfd92011-04-30 23:09:03 +0100438 'glDrawRangeElementsEXT',
José Fonseca5c749e32011-05-09 11:11:37 +0100439 'glDrawRangeElementsEXT_size',
440 'glMultiDrawArraysEXT',
441 'glMultiDrawElementsEXT',
442 'glMultiModeDrawArraysIBM',
443 'glMultiModeDrawElementsIBM',
444 'glDrawArraysInstancedEXT',
445 'glDrawElementsInstancedEXT',
José Fonseca99221832011-03-22 22:15:46 +0000446 ))
447
José Fonsecac9f12232011-03-25 20:07:42 +0000448 interleaved_formats = [
449 'GL_V2F',
450 'GL_V3F',
451 'GL_C4UB_V2F',
452 'GL_C4UB_V3F',
453 'GL_C3F_V3F',
454 'GL_N3F_V3F',
455 'GL_C4F_N3F_V3F',
456 'GL_T2F_V3F',
457 'GL_T4F_V4F',
458 'GL_T2F_C4UB_V3F',
459 'GL_T2F_C3F_V3F',
460 'GL_T2F_N3F_V3F',
461 'GL_T2F_C4F_N3F_V3F',
462 'GL_T4F_C4F_N3F_V4F',
463 ]
464
José Fonseca54f304a2012-01-14 19:33:08 +0000465 def traceFunctionImplBody(self, function):
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000466 # Defer tracing of user array pointers...
José Fonseca99221832011-03-22 22:15:46 +0000467 if function.name in self.array_pointer_function_names:
José Fonseca26be8f92014-03-07 14:08:50 +0000468 print ' GLint _array_buffer = _glGetInteger(GL_ARRAY_BUFFER_BINDING);'
José Fonseca632a78d2012-04-19 07:18:59 +0100469 print ' if (!_array_buffer) {'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000470 print ' gltrace::Context *ctx = gltrace::getContext();'
Chia-I Wu8ef66972011-11-03 01:19:46 +0800471 print ' ctx->user_arrays = true;'
José Fonseca5a568a92011-06-29 16:43:36 +0100472 if function.name == "glVertexAttribPointerNV":
Chia-I Wu8ef66972011-11-03 01:19:46 +0800473 print ' ctx->user_arrays_nv = true;'
José Fonseca54f304a2012-01-14 19:33:08 +0000474 self.invokeFunction(function)
José Fonsecaac5285b2011-05-04 11:09:08 +0100475
476 # And also break down glInterleavedArrays into the individual calls
477 if function.name == 'glInterleavedArrays':
478 print
479
480 # Initialize the enable flags
481 for camelcase_name, uppercase_name in self.arrays:
José Fonseca632a78d2012-04-19 07:18:59 +0100482 flag_name = '_' + uppercase_name.lower()
José Fonsecaac5285b2011-05-04 11:09:08 +0100483 print ' GLboolean %s = GL_FALSE;' % flag_name
484 print
485
486 # Switch for the interleaved formats
487 print ' switch (format) {'
488 for format in self.interleaved_formats:
489 print ' case %s:' % format
490 for camelcase_name, uppercase_name in self.arrays:
José Fonseca632a78d2012-04-19 07:18:59 +0100491 flag_name = '_' + uppercase_name.lower()
José Fonsecaac5285b2011-05-04 11:09:08 +0100492 if format.find('_' + uppercase_name[0]) >= 0:
493 print ' %s = GL_TRUE;' % flag_name
494 print ' break;'
495 print ' default:'
496 print ' return;'
497 print ' }'
498 print
499
500 # Emit fake glEnableClientState/glDisableClientState flags
501 for camelcase_name, uppercase_name in self.arrays:
José Fonseca632a78d2012-04-19 07:18:59 +0100502 flag_name = '_' + uppercase_name.lower()
José Fonsecaac5285b2011-05-04 11:09:08 +0100503 enable_name = 'GL_%s_ARRAY' % uppercase_name
504
505 # Emit a fake function
506 print ' {'
José Fonseca632a78d2012-04-19 07:18:59 +0100507 print ' static const trace::FunctionSig &_sig = %s ? _glEnableClientState_sig : _glDisableClientState_sig;' % flag_name
José Fonseca7a5f23a2014-06-24 19:20:36 +0100508 print ' unsigned _call = trace::localWriter.beginEnter(&_sig, true);'
José Fonsecab4a3d142011-10-27 07:43:19 +0100509 print ' trace::localWriter.beginArg(0);'
José Fonseca54f304a2012-01-14 19:33:08 +0000510 self.serializeValue(glapi.GLenum, enable_name)
José Fonsecab4a3d142011-10-27 07:43:19 +0100511 print ' trace::localWriter.endArg();'
512 print ' trace::localWriter.endEnter();'
José Fonseca632a78d2012-04-19 07:18:59 +0100513 print ' trace::localWriter.beginLeave(_call);'
José Fonsecab4a3d142011-10-27 07:43:19 +0100514 print ' trace::localWriter.endLeave();'
José Fonsecaac5285b2011-05-04 11:09:08 +0100515 print ' }'
516
José Fonsecac629a8c2014-06-01 21:12:27 +0100517 # Warn about buggy glGet(GL_*ARRAY_SIZE) not returning GL_BGRA
518 buggyFunctions = {
519 'glColorPointer': ('glGetIntegerv', '', 'GL_COLOR_ARRAY_SIZE'),
520 'glSecondaryColorPointer': ('glGetIntegerv', '', 'GL_SECONDARY_COLOR_ARRAY_SIZE'),
521 'glVertexAttribPointer': ('glGetVertexAttribiv', 'index, ', 'GL_VERTEX_ATTRIB_ARRAY_SIZE'),
522 'glVertexAttribPointerARB': ('glGetVertexAttribivARB', 'index, ', 'GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB'),
523 }
524 if function.name in buggyFunctions:
525 getter, extraArg, pname = buggyFunctions[function.name]
526 print r' static bool _checked = false;'
527 print r' if (!_checked && size == GL_BGRA) {'
528 print r' GLint _size = 0;'
529 print r' _%s(%s%s, &_size);' % (getter, extraArg, pname)
530 print r' if (_size != GL_BGRA) {'
531 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)
532 print r' }'
533 print r' _checked = true;'
534 print r' }'
535
José Fonseca99221832011-03-22 22:15:46 +0000536 print ' return;'
537 print ' }'
José Fonseca14c21bc2011-02-20 23:32:22 +0000538
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000539 # ... to the draw calls
José Fonseca99221832011-03-22 22:15:46 +0000540 if function.name in self.draw_function_names:
José Fonseca632a78d2012-04-19 07:18:59 +0100541 print ' if (_need_user_arrays()) {'
José Fonseca99221832011-03-22 22:15:46 +0000542 arg_names = ', '.join([arg.name for arg in function.args[1:]])
José Fonseca14cb9ef2012-05-17 21:33:14 +0100543 print ' GLuint _count = _%s_count(%s);' % (function.name, arg_names)
José Fonseca707630d2014-03-07 14:20:35 +0000544 # Some apps, in particular Quake3, can tell the driver to lock more
545 # vertices than those actually required for the draw call.
546 print ' if (_checkLockArraysEXT) {'
547 print ' GLuint _locked_count = _glGetInteger(GL_ARRAY_ELEMENT_LOCK_FIRST_EXT)'
548 print ' + _glGetInteger(GL_ARRAY_ELEMENT_LOCK_COUNT_EXT);'
549 print ' _count = std::max(_count, _locked_count);'
550 print ' }'
José Fonseca14cb9ef2012-05-17 21:33:14 +0100551 print ' _trace_user_arrays(_count);'
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000552 print ' }'
José Fonseca707630d2014-03-07 14:20:35 +0000553 if function.name == 'glLockArraysEXT':
554 print ' _checkLockArraysEXT = true;'
José Fonseca4a7d8602014-06-18 16:03:44 +0100555
556 # Warn if user arrays are used with glBegin/glArrayElement/glEnd.
557 if function.name == 'glBegin':
558 print r' if (_need_user_arrays()) {'
559 print r' os::log("apitrace: warning: user arrays with glArrayElement not supported (https://github.com/apitrace/apitrace/issues/276)\n");'
560 print r' }'
José Fonseca14c21bc2011-02-20 23:32:22 +0000561
José Fonseca73373602011-05-20 17:45:26 +0100562 # Emit a fake memcpy on buffer uploads
José Fonseca9c536b02012-02-29 20:54:13 +0000563 if function.name == 'glBufferParameteriAPPLE':
564 print ' if (pname == GL_BUFFER_FLUSHING_UNMAP_APPLE && param == GL_FALSE) {'
José Fonseca632a78d2012-04-19 07:18:59 +0100565 print ' _checkBufferFlushingUnmapAPPLE = true;'
José Fonseca9c536b02012-02-29 20:54:13 +0000566 print ' }'
José Fonsecacdc322c2012-02-29 19:29:51 +0000567 if function.name in ('glUnmapBuffer', 'glUnmapBufferARB'):
José Fonseca9c536b02012-02-29 20:54:13 +0000568 if function.name.endswith('ARB'):
569 suffix = 'ARB'
570 else:
571 suffix = ''
572 print ' GLint access = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100573 print ' _glGetBufferParameteriv%s(target, GL_BUFFER_ACCESS, &access);' % suffix
José Fonseca9c536b02012-02-29 20:54:13 +0000574 print ' if (access != GL_READ_ONLY) {'
575 print ' GLvoid *map = NULL;'
José Fonseca632a78d2012-04-19 07:18:59 +0100576 print ' _glGetBufferPointerv%s(target, GL_BUFFER_MAP_POINTER, &map);' % suffix
José Fonseca9c536b02012-02-29 20:54:13 +0000577 print ' if (map) {'
578 print ' GLint length = -1;'
579 print ' bool flush = true;'
José Fonseca632a78d2012-04-19 07:18:59 +0100580 print ' if (_checkBufferMapRange) {'
581 print ' _glGetBufferParameteriv%s(target, GL_BUFFER_MAP_LENGTH, &length);' % suffix
José Fonseca9c536b02012-02-29 20:54:13 +0000582 print ' GLint access_flags = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100583 print ' _glGetBufferParameteriv(target, GL_BUFFER_ACCESS_FLAGS, &access_flags);'
José Fonseca9c536b02012-02-29 20:54:13 +0000584 print ' flush = flush && !(access_flags & GL_MAP_FLUSH_EXPLICIT_BIT);'
585 print ' if (length == -1) {'
José Fonsecacb07e2d2014-02-04 15:14:09 +0000586 print ' // Mesa drivers refuse GL_BUFFER_MAP_LENGTH without GL 3.0 up-to'
587 print ' // http://cgit.freedesktop.org/mesa/mesa/commit/?id=ffee498fb848b253a7833373fe5430f8c7ca0c5f'
José Fonsecadb1ccce2012-02-29 21:09:24 +0000588 print ' static bool warned = false;'
589 print ' if (!warned) {'
590 print ' os::log("apitrace: warning: glGetBufferParameteriv%s(GL_BUFFER_MAP_LENGTH) failed\\n");' % suffix
591 print ' warned = true;'
592 print ' }'
José Fonseca9c536b02012-02-29 20:54:13 +0000593 print ' struct buffer_mapping *mapping = get_buffer_mapping(target);'
594 print ' if (mapping) {'
595 print ' length = mapping->length;'
596 print ' flush = flush && !mapping->explicit_flush;'
597 print ' } else {'
598 print ' length = 0;'
599 print ' flush = false;'
600 print ' }'
601 print ' }'
602 print ' } else {'
603 print ' length = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100604 print ' _glGetBufferParameteriv%s(target, GL_BUFFER_SIZE, &length);' % suffix
José Fonseca9c536b02012-02-29 20:54:13 +0000605 print ' }'
José Fonseca632a78d2012-04-19 07:18:59 +0100606 print ' if (_checkBufferFlushingUnmapAPPLE) {'
José Fonseca9c536b02012-02-29 20:54:13 +0000607 print ' GLint flushing_unmap = GL_TRUE;'
José Fonseca632a78d2012-04-19 07:18:59 +0100608 print ' _glGetBufferParameteriv%s(target, GL_BUFFER_FLUSHING_UNMAP_APPLE, &flushing_unmap);' % suffix
José Fonseca9c536b02012-02-29 20:54:13 +0000609 print ' flush = flush && flushing_unmap;'
610 print ' }'
611 print ' if (flush && length > 0) {'
José Fonseca6f0e3032014-06-25 01:00:35 +0100612 self.emit_memcpy('map', 'length')
José Fonseca9c536b02012-02-29 20:54:13 +0000613 print ' }'
614 print ' }'
615 print ' }'
José Fonsecacdc322c2012-02-29 19:29:51 +0000616 if function.name == 'glUnmapBufferOES':
617 print ' GLint access = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100618 print ' _glGetBufferParameteriv(target, GL_BUFFER_ACCESS_OES, &access);'
José Fonsecacdc322c2012-02-29 19:29:51 +0000619 print ' if (access == GL_WRITE_ONLY_OES) {'
620 print ' GLvoid *map = NULL;'
José Fonseca632a78d2012-04-19 07:18:59 +0100621 print ' _glGetBufferPointervOES(target, GL_BUFFER_MAP_POINTER_OES, &map);'
José Fonsecacdc322c2012-02-29 19:29:51 +0000622 print ' GLint size = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100623 print ' _glGetBufferParameteriv(target, GL_BUFFER_SIZE, &size);'
José Fonsecacdc322c2012-02-29 19:29:51 +0000624 print ' if (map && size > 0) {'
José Fonseca6f0e3032014-06-25 01:00:35 +0100625 self.emit_memcpy('map', 'size')
José Fonseca219c9f22012-11-03 10:13:17 +0000626 self.shadowBufferMethod('bufferSubData(0, size, map)')
José Fonsecacdc322c2012-02-29 19:29:51 +0000627 print ' }'
José Fonseca867b1b72011-04-24 11:58:04 +0100628 print ' }'
José Fonseca4920c302014-08-13 18:35:57 +0100629 if function.name == 'glUnmapNamedBuffer':
630 print ' GLint access_flags = 0;'
631 print ' _glGetNamedBufferParameteriv(buffer, GL_BUFFER_ACCESS_FLAGS, &access_flags);'
632 print ' if ((access_flags & GL_MAP_WRITE_BIT) && !(access_flags & GL_MAP_FLUSH_EXPLICIT_BIT)) {'
633 print ' GLvoid *map = NULL;'
634 print ' _glGetNamedBufferPointerv(buffer, GL_BUFFER_MAP_POINTER, &map);'
635 print ' GLint length = 0;'
636 print ' _glGetNamedBufferParameteriv(buffer, GL_BUFFER_MAP_LENGTH, &length);'
637 print ' if (map && length > 0) {'
638 self.emit_memcpy('map', 'length')
639 print ' }'
640 print ' }'
José Fonsecafb3bd602012-01-15 13:56:28 +0000641 if function.name == 'glUnmapNamedBufferEXT':
José Fonseca024aff42012-02-29 18:00:06 +0000642 print ' GLint access_flags = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100643 print ' _glGetNamedBufferParameterivEXT(buffer, GL_BUFFER_ACCESS_FLAGS, &access_flags);'
José Fonseca024aff42012-02-29 18:00:06 +0000644 print ' if ((access_flags & GL_MAP_WRITE_BIT) && !(access_flags & GL_MAP_FLUSH_EXPLICIT_BIT)) {'
José Fonsecafb3bd602012-01-15 13:56:28 +0000645 print ' GLvoid *map = NULL;'
José Fonseca632a78d2012-04-19 07:18:59 +0100646 print ' _glGetNamedBufferPointervEXT(buffer, GL_BUFFER_MAP_POINTER, &map);'
José Fonsecafb3bd602012-01-15 13:56:28 +0000647 print ' GLint length = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100648 print ' _glGetNamedBufferParameterivEXT(buffer, GL_BUFFER_MAP_LENGTH, &length);'
José Fonseca024aff42012-02-29 18:00:06 +0000649 print ' if (map && length > 0) {'
José Fonseca6f0e3032014-06-25 01:00:35 +0100650 self.emit_memcpy('map', 'length')
José Fonseca024aff42012-02-29 18:00:06 +0000651 print ' }'
José Fonsecafb3bd602012-01-15 13:56:28 +0000652 print ' }'
José Fonseca77ef0ce2012-02-29 18:08:48 +0000653 if function.name == 'glFlushMappedBufferRange':
654 print ' GLvoid *map = NULL;'
José Fonseca632a78d2012-04-19 07:18:59 +0100655 print ' _glGetBufferPointerv(target, GL_BUFFER_MAP_POINTER, &map);'
José Fonseca77ef0ce2012-02-29 18:08:48 +0000656 print ' if (map && length > 0) {'
José Fonseca6f0e3032014-06-25 01:00:35 +0100657 self.emit_memcpy('(const char *)map + offset', 'length')
José Fonseca77ef0ce2012-02-29 18:08:48 +0000658 print ' }'
659 if function.name == 'glFlushMappedBufferRangeAPPLE':
660 print ' GLvoid *map = NULL;'
José Fonseca632a78d2012-04-19 07:18:59 +0100661 print ' _glGetBufferPointerv(target, GL_BUFFER_MAP_POINTER, &map);'
José Fonseca77ef0ce2012-02-29 18:08:48 +0000662 print ' if (map && size > 0) {'
José Fonseca6f0e3032014-06-25 01:00:35 +0100663 self.emit_memcpy('(const char *)map + offset', 'size')
José Fonseca73373602011-05-20 17:45:26 +0100664 print ' }'
José Fonseca4920c302014-08-13 18:35:57 +0100665 if function.name == 'glFlushMappedNamedBufferRange':
666 print ' GLvoid *map = NULL;'
667 print ' _glGetNamedBufferPointerv(buffer, GL_BUFFER_MAP_POINTER, &map);'
668 print ' if (map && length > 0) {'
669 self.emit_memcpy('(const char *)map + offset', 'length')
670 print ' }'
José Fonsecafb3bd602012-01-15 13:56:28 +0000671 if function.name == 'glFlushMappedNamedBufferRangeEXT':
672 print ' GLvoid *map = NULL;'
José Fonseca632a78d2012-04-19 07:18:59 +0100673 print ' _glGetNamedBufferPointervEXT(buffer, GL_BUFFER_MAP_POINTER, &map);'
José Fonseca024aff42012-02-29 18:00:06 +0000674 print ' if (map && length > 0) {'
José Fonseca6f0e3032014-06-25 01:00:35 +0100675 self.emit_memcpy('(const char *)map + offset', 'length')
José Fonsecafb3bd602012-01-15 13:56:28 +0000676 print ' }'
José Fonseca867b1b72011-04-24 11:58:04 +0100677
José Fonseca3522cbd2014-02-28 14:45:32 +0000678 # FIXME: We don't support coherent/pinned memory mappings
679 # See https://github.com/apitrace/apitrace/issues/232
José Fonseca4920c302014-08-13 18:35:57 +0100680 if function.name in ('glBufferStorage', 'glNamedBufferStorage', 'glNamedBufferStorageEXT'):
José Fonseca3522cbd2014-02-28 14:45:32 +0000681 print r' if (flags & GL_MAP_COHERENT_BIT) {'
682 print r' os::log("apitrace: warning: coherent mappings not fully supported\n");'
683 print r' }'
684 if function.name in ('glBufferData', 'glBufferDataARB'):
685 print r' if (target == GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD) {'
686 print r' os::log("apitrace: warning: GL_AMD_pinned_memory not fully supported\n");'
687 print r' }'
688
José Fonseca91492d22011-05-23 21:20:31 +0100689 # Don't leave vertex attrib locations to chance. Instead emit fake
690 # glBindAttribLocation calls to ensure that the same locations will be
691 # used when retracing. Trying to remap locations after the fact would
692 # be an herculian task given that vertex attrib locations appear in
693 # many entry-points, including non-shader related ones.
694 if function.name == 'glLinkProgram':
José Fonseca54f304a2012-01-14 19:33:08 +0000695 Tracer.invokeFunction(self, function)
José Fonseca91492d22011-05-23 21:20:31 +0100696 print ' GLint active_attributes = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100697 print ' _glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &active_attributes);'
José Fonseca7525e6f2011-09-28 09:04:56 +0100698 print ' for (GLint attrib = 0; attrib < active_attributes; ++attrib) {'
José Fonseca91492d22011-05-23 21:20:31 +0100699 print ' GLint size = 0;'
700 print ' GLenum type = 0;'
701 print ' GLchar name[256];'
702 # TODO: Use ACTIVE_ATTRIBUTE_MAX_LENGTH instead of 256
José Fonseca632a78d2012-04-19 07:18:59 +0100703 print ' _glGetActiveAttrib(program, attrib, sizeof name, NULL, &size, &type, name);'
José Fonseca2a794f52011-05-26 20:54:29 +0100704 print " if (name[0] != 'g' || name[1] != 'l' || name[2] != '_') {"
José Fonseca632a78d2012-04-19 07:18:59 +0100705 print ' GLint location = _glGetAttribLocation(program, name);'
José Fonseca2a794f52011-05-26 20:54:29 +0100706 print ' if (location >= 0) {'
José Fonseca1b6c8752012-04-15 14:33:00 +0100707 bind_function = glapi.glapi.getFunctionByName('glBindAttribLocation')
José Fonseca91492d22011-05-23 21:20:31 +0100708 self.fake_call(bind_function, ['program', 'location', 'name'])
José Fonseca2a794f52011-05-26 20:54:29 +0100709 print ' }'
José Fonseca91492d22011-05-23 21:20:31 +0100710 print ' }'
711 print ' }'
712 if function.name == 'glLinkProgramARB':
José Fonseca54f304a2012-01-14 19:33:08 +0000713 Tracer.invokeFunction(self, function)
José Fonseca91492d22011-05-23 21:20:31 +0100714 print ' GLint active_attributes = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100715 print ' _glGetObjectParameterivARB(programObj, GL_OBJECT_ACTIVE_ATTRIBUTES_ARB, &active_attributes);'
José Fonseca7525e6f2011-09-28 09:04:56 +0100716 print ' for (GLint attrib = 0; attrib < active_attributes; ++attrib) {'
José Fonseca91492d22011-05-23 21:20:31 +0100717 print ' GLint size = 0;'
718 print ' GLenum type = 0;'
719 print ' GLcharARB name[256];'
720 # TODO: Use ACTIVE_ATTRIBUTE_MAX_LENGTH instead of 256
José Fonseca632a78d2012-04-19 07:18:59 +0100721 print ' _glGetActiveAttribARB(programObj, attrib, sizeof name, NULL, &size, &type, name);'
José Fonseca2a794f52011-05-26 20:54:29 +0100722 print " if (name[0] != 'g' || name[1] != 'l' || name[2] != '_') {"
José Fonseca632a78d2012-04-19 07:18:59 +0100723 print ' GLint location = _glGetAttribLocationARB(programObj, name);'
José Fonseca2a794f52011-05-26 20:54:29 +0100724 print ' if (location >= 0) {'
José Fonseca1b6c8752012-04-15 14:33:00 +0100725 bind_function = glapi.glapi.getFunctionByName('glBindAttribLocationARB')
José Fonseca91492d22011-05-23 21:20:31 +0100726 self.fake_call(bind_function, ['programObj', 'location', 'name'])
José Fonseca2a794f52011-05-26 20:54:29 +0100727 print ' }'
José Fonseca91492d22011-05-23 21:20:31 +0100728 print ' }'
729 print ' }'
730
Imre Deakd4937372012-04-24 14:06:48 +0300731 self.shadowBufferProlog(function)
732
José Fonseca54f304a2012-01-14 19:33:08 +0000733 Tracer.traceFunctionImplBody(self, function)
José Fonseca73373602011-05-20 17:45:26 +0100734
Peter Lohrmann0b5b75e2013-06-03 14:58:41 -0700735 # These entrypoints are only expected to be implemented by tools;
736 # drivers will probably not implement them.
José Fonsecaf028a8f2012-02-15 23:33:35 +0000737 marker_functions = [
738 # GL_GREMEDY_string_marker
José Fonseca8f34d342011-07-15 20:16:40 +0100739 'glStringMarkerGREMEDY',
José Fonsecaf028a8f2012-02-15 23:33:35 +0000740 # GL_GREMEDY_frame_terminator
José Fonseca8f34d342011-07-15 20:16:40 +0100741 'glFrameTerminatorGREMEDY',
742 ]
743
Peter Lohrmann0b5b75e2013-06-03 14:58:41 -0700744 # These entrypoints may be implemented by drivers, but are also very useful
745 # for debugging / analysis tools.
746 debug_functions = [
747 # GL_KHR_debug
748 'glDebugMessageControl',
749 'glDebugMessageInsert',
750 'glDebugMessageCallback',
751 'glGetDebugMessageLog',
752 'glPushDebugGroup',
753 'glPopDebugGroup',
754 'glObjectLabel',
755 'glGetObjectLabel',
756 'glObjectPtrLabel',
757 'glGetObjectPtrLabel',
758 # GL_ARB_debug_output
759 'glDebugMessageControlARB',
760 'glDebugMessageInsertARB',
761 'glDebugMessageCallbackARB',
762 'glGetDebugMessageLogARB',
763 # GL_AMD_debug_output
764 'glDebugMessageEnableAMD',
765 'glDebugMessageInsertAMD',
766 'glDebugMessageCallbackAMD',
767 'glGetDebugMessageLogAMD',
José Fonseca71f5a352014-07-28 12:19:50 +0100768 # GL_EXT_debug_label
769 'glLabelObjectEXT',
770 'glGetObjectLabelEXT',
771 # GL_EXT_debug_marker
772 'glInsertEventMarkerEXT',
773 'glPushGroupMarkerEXT',
774 'glPopGroupMarkerEXT',
Peter Lohrmann0b5b75e2013-06-03 14:58:41 -0700775 ]
776
José Fonseca54f304a2012-01-14 19:33:08 +0000777 def invokeFunction(self, function):
José Fonseca91492d22011-05-23 21:20:31 +0100778 if function.name in ('glLinkProgram', 'glLinkProgramARB'):
779 # These functions have been dispatched already
780 return
781
José Fonseca2cfa02c2013-06-10 08:05:29 +0100782 Tracer.invokeFunction(self, function)
783
784 def doInvokeFunction(self, function):
785 # Same as invokeFunction() but called both when trace is enabled or disabled.
786 #
787 # Used to modify the behavior of GL entry-points.
788
789 # Override GL extensions
790 if function.name in ('glGetString', 'glGetIntegerv', 'glGetStringi'):
791 Tracer.doInvokeFunction(self, function, prefix = 'gltrace::_', suffix = '_override')
792 return
793
José Fonseca71f5a352014-07-28 12:19:50 +0100794 # We implement GL_GREMEDY_*, etc., and not the driver
José Fonsecaf028a8f2012-02-15 23:33:35 +0000795 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é Fonseca4920c302014-08-13 18:35:57 +0100901 'glCompressedTextureImage1D',
José Fonsecad2bd4ca2013-04-12 11:41:00 +0100902 'glCompressedTextureImage1DEXT',
José Fonseca4920c302014-08-13 18:35:57 +0100903 'glCompressedTextureImage2D',
José Fonsecad2bd4ca2013-04-12 11:41:00 +0100904 'glCompressedTextureImage2DEXT',
José Fonseca4920c302014-08-13 18:35:57 +0100905 'glCompressedTextureImage3D',
José Fonsecad2bd4ca2013-04-12 11:41:00 +0100906 'glCompressedTextureImage3DEXT',
José Fonseca4920c302014-08-13 18:35:57 +0100907 'glCompressedTextureSubImage1D',
José Fonsecad2bd4ca2013-04-12 11:41:00 +0100908 'glCompressedTextureSubImage1DEXT',
José Fonseca4920c302014-08-13 18:35:57 +0100909 'glCompressedTextureSubImage2D',
José Fonsecad2bd4ca2013-04-12 11:41:00 +0100910 'glCompressedTextureSubImage2DEXT',
José Fonseca4920c302014-08-13 18:35:57 +0100911 'glCompressedTextureSubImage3D',
José Fonsecad2bd4ca2013-04-12 11:41:00 +0100912 'glCompressedTextureSubImage3DEXT',
José Fonsecac29f4f12011-06-11 12:19:05 +0100913 'glConvolutionFilter1D',
914 'glConvolutionFilter2D',
José Fonsecae97bab92011-06-02 23:15:11 +0100915 'glDrawPixels',
916 'glMultiTexImage1DEXT',
917 'glMultiTexImage2DEXT',
918 'glMultiTexImage3DEXT',
919 'glMultiTexSubImage1DEXT',
920 'glMultiTexSubImage2DEXT',
921 'glMultiTexSubImage3DEXT',
José Fonsecac29f4f12011-06-11 12:19:05 +0100922 'glPixelMapfv',
923 'glPixelMapuiv',
924 'glPixelMapusv',
José Fonsecae97bab92011-06-02 23:15:11 +0100925 'glPolygonStipple',
José Fonsecac29f4f12011-06-11 12:19:05 +0100926 'glSeparableFilter2D',
José Fonsecae97bab92011-06-02 23:15:11 +0100927 'glTexImage1D',
928 'glTexImage1DEXT',
929 'glTexImage2D',
930 'glTexImage2DEXT',
931 'glTexImage3D',
932 'glTexImage3DEXT',
933 'glTexSubImage1D',
934 'glTexSubImage1DEXT',
935 'glTexSubImage2D',
936 'glTexSubImage2DEXT',
937 'glTexSubImage3D',
938 'glTexSubImage3DEXT',
939 'glTextureImage1DEXT',
940 'glTextureImage2DEXT',
941 'glTextureImage3DEXT',
942 'glTextureSubImage1DEXT',
943 'glTextureSubImage2DEXT',
944 'glTextureSubImage3DEXT',
945 ])
946
José Fonseca54f304a2012-01-14 19:33:08 +0000947 def serializeArgValue(self, function, arg):
José Fonsecae97bab92011-06-02 23:15:11 +0100948 # Recognize offsets instead of blobs when a PBO is bound
949 if function.name in self.unpack_function_names \
950 and (isinstance(arg.type, stdapi.Blob) \
951 or (isinstance(arg.type, stdapi.Const) \
952 and isinstance(arg.type.type, stdapi.Blob))):
José Fonsecac29f4f12011-06-11 12:19:05 +0100953 print ' {'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000954 print ' gltrace::Context *ctx = gltrace::getContext();'
José Fonseca632a78d2012-04-19 07:18:59 +0100955 print ' GLint _unpack_buffer = 0;'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000956 print ' if (ctx->profile == gltrace::PROFILE_COMPAT)'
José Fonseca632a78d2012-04-19 07:18:59 +0100957 print ' _glGetIntegerv(GL_PIXEL_UNPACK_BUFFER_BINDING, &_unpack_buffer);'
958 print ' if (_unpack_buffer) {'
José Fonsecad559f022012-04-15 16:13:51 +0100959 print ' trace::localWriter.writePointer((uintptr_t)%s);' % arg.name
José Fonsecac29f4f12011-06-11 12:19:05 +0100960 print ' } else {'
José Fonseca54f304a2012-01-14 19:33:08 +0000961 Tracer.serializeArgValue(self, function, arg)
José Fonsecac29f4f12011-06-11 12:19:05 +0100962 print ' }'
José Fonsecae97bab92011-06-02 23:15:11 +0100963 print ' }'
964 return
965
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100966 # Several GL state functions take GLenum symbolic names as
967 # integer/floats; so dump the symbolic name whenever possible
José Fonseca3bcb33c2011-05-27 20:14:31 +0100968 if function.name.startswith('gl') \
José Fonsecae3571092011-10-13 08:26:27 +0100969 and arg.type in (glapi.GLint, glapi.GLfloat, glapi.GLdouble) \
José Fonseca3bcb33c2011-05-27 20:14:31 +0100970 and arg.name == 'param':
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100971 assert arg.index > 0
972 assert function.args[arg.index - 1].name == 'pname'
973 assert function.args[arg.index - 1].type == glapi.GLenum
974 print ' if (is_symbolic_pname(pname) && is_symbolic_param(%s)) {' % arg.name
José Fonseca54f304a2012-01-14 19:33:08 +0000975 self.serializeValue(glapi.GLenum, arg.name)
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100976 print ' } else {'
José Fonseca54f304a2012-01-14 19:33:08 +0000977 Tracer.serializeArgValue(self, function, arg)
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100978 print ' }'
979 return
980
José Fonseca54f304a2012-01-14 19:33:08 +0000981 Tracer.serializeArgValue(self, function, arg)
José Fonseca99221832011-03-22 22:15:46 +0000982
José Fonseca4c938c22011-04-30 22:44:38 +0100983 def footer(self, api):
984 Tracer.footer(self, api)
José Fonseca669b1222011-02-20 09:05:10 +0000985
José Fonseca4c938c22011-04-30 22:44:38 +0100986 # A simple state tracker to track the pointer values
José Fonseca669b1222011-02-20 09:05:10 +0000987 # update the state
José Fonseca14cb9ef2012-05-17 21:33:14 +0100988 print 'static void _trace_user_arrays(GLuint count)'
José Fonseca669b1222011-02-20 09:05:10 +0000989 print '{'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000990 print ' gltrace::Context *ctx = gltrace::getContext();'
José Fonseca8d1408b2014-02-03 19:57:18 +0000991 print
992
993 # Temporarily unbind the array buffer
José Fonseca26be8f92014-03-07 14:08:50 +0000994 print ' GLint _array_buffer = _glGetInteger(GL_ARRAY_BUFFER_BINDING);'
José Fonseca8d1408b2014-02-03 19:57:18 +0000995 print ' if (_array_buffer) {'
996 self.fake_glBindBuffer(api, 'GL_ARRAY_BUFFER', '0')
997 print ' }'
998 print
José Fonseca1a2fdd22011-04-01 00:55:09 +0100999
José Fonseca99221832011-03-22 22:15:46 +00001000 for camelcase_name, uppercase_name in self.arrays:
Chia-I Wub3d218d2011-11-03 01:37:36 +08001001 # in which profile is the array available?
José Fonsecaf028a8f2012-02-15 23:33:35 +00001002 profile_check = 'ctx->profile == gltrace::PROFILE_COMPAT'
Chia-I Wub3d218d2011-11-03 01:37:36 +08001003 if camelcase_name in self.arrays_es1:
José Fonsecaf028a8f2012-02-15 23:33:35 +00001004 profile_check = '(' + profile_check + ' || ctx->profile == gltrace::PROFILE_ES1)';
Chia-I Wub3d218d2011-11-03 01:37:36 +08001005
José Fonseca99221832011-03-22 22:15:46 +00001006 function_name = 'gl%sPointer' % camelcase_name
1007 enable_name = 'GL_%s_ARRAY' % uppercase_name
1008 binding_name = 'GL_%s_ARRAY_BUFFER_BINDING' % uppercase_name
José Fonseca1b6c8752012-04-15 14:33:00 +01001009 function = api.getFunctionByName(function_name)
José Fonseca99221832011-03-22 22:15:46 +00001010
José Fonseca06e85192011-10-16 14:15:36 +01001011 print ' // %s' % function.prototype()
Chia-I Wub3d218d2011-11-03 01:37:36 +08001012 print ' if (%s) {' % profile_check
José Fonsecafb6744f2011-04-15 11:18:37 +01001013 self.array_trace_prolog(api, uppercase_name)
1014 self.array_prolog(api, uppercase_name)
José Fonseca632a78d2012-04-19 07:18:59 +01001015 print ' if (_glIsEnabled(%s)) {' % enable_name
José Fonseca26be8f92014-03-07 14:08:50 +00001016 print ' GLint _binding = _glGetInteger(%s);' % binding_name
José Fonseca632a78d2012-04-19 07:18:59 +01001017 print ' if (!_binding) {'
José Fonseca99221832011-03-22 22:15:46 +00001018
1019 # Get the arguments via glGet*
1020 for arg in function.args:
1021 arg_get_enum = 'GL_%s_ARRAY_%s' % (uppercase_name, arg.name.upper())
1022 arg_get_function, arg_type = TypeGetter().visit(arg.type)
José Fonseca7f5163e2011-03-31 23:37:26 +01001023 print ' %s %s = 0;' % (arg_type, arg.name)
José Fonseca632a78d2012-04-19 07:18:59 +01001024 print ' _%s(%s, &%s);' % (arg_get_function, arg_get_enum, arg.name)
José Fonseca99221832011-03-22 22:15:46 +00001025
1026 arg_names = ', '.join([arg.name for arg in function.args[:-1]])
José Fonseca14cb9ef2012-05-17 21:33:14 +01001027 print ' size_t _size = _%s_size(%s, count);' % (function.name, arg_names)
José Fonseca99221832011-03-22 22:15:46 +00001028
1029 # Emit a fake function
José Fonsecafb6744f2011-04-15 11:18:37 +01001030 self.array_trace_intermezzo(api, uppercase_name)
José Fonseca7a5f23a2014-06-24 19:20:36 +01001031 print ' unsigned _call = trace::localWriter.beginEnter(&_%s_sig, true);' % (function.name,)
José Fonseca669b1222011-02-20 09:05:10 +00001032 for arg in function.args:
1033 assert not arg.output
José Fonsecab4a3d142011-10-27 07:43:19 +01001034 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
José Fonseca14c21bc2011-02-20 23:32:22 +00001035 if arg.name != 'pointer':
José Fonseca54f304a2012-01-14 19:33:08 +00001036 self.serializeValue(arg.type, arg.name)
José Fonseca14c21bc2011-02-20 23:32:22 +00001037 else:
José Fonseca632a78d2012-04-19 07:18:59 +01001038 print ' trace::localWriter.writeBlob((const void *)%s, _size);' % (arg.name)
José Fonsecab4a3d142011-10-27 07:43:19 +01001039 print ' trace::localWriter.endArg();'
José Fonseca99221832011-03-22 22:15:46 +00001040
José Fonsecab4a3d142011-10-27 07:43:19 +01001041 print ' trace::localWriter.endEnter();'
José Fonseca632a78d2012-04-19 07:18:59 +01001042 print ' trace::localWriter.beginLeave(_call);'
José Fonsecab4a3d142011-10-27 07:43:19 +01001043 print ' trace::localWriter.endLeave();'
José Fonseca99221832011-03-22 22:15:46 +00001044 print ' }'
José Fonseca669b1222011-02-20 09:05:10 +00001045 print ' }'
José Fonsecafb6744f2011-04-15 11:18:37 +01001046 self.array_epilog(api, uppercase_name)
1047 self.array_trace_epilog(api, uppercase_name)
Chia-I Wub3d218d2011-11-03 01:37:36 +08001048 print ' }'
José Fonseca99221832011-03-22 22:15:46 +00001049 print
José Fonseca1a2fdd22011-04-01 00:55:09 +01001050
José Fonseca1601c412011-05-10 10:38:19 +01001051 # Samething, but for glVertexAttribPointer*
1052 #
1053 # Some variants of glVertexAttribPointer alias conventional and generic attributes:
1054 # - glVertexAttribPointer: no
1055 # - glVertexAttribPointerARB: implementation dependent
1056 # - glVertexAttribPointerNV: yes
1057 #
1058 # This means that the implementations of these functions do not always
1059 # alias, and they need to be considered independently.
1060 #
Chia-I Wub3d218d2011-11-03 01:37:36 +08001061 print ' // ES1 does not support generic vertex attributes'
José Fonsecaf028a8f2012-02-15 23:33:35 +00001062 print ' if (ctx->profile == gltrace::PROFILE_ES1)'
Chia-I Wub3d218d2011-11-03 01:37:36 +08001063 print ' return;'
1064 print
José Fonseca632a78d2012-04-19 07:18:59 +01001065 print ' vertex_attrib _vertex_attrib = _get_vertex_attrib();'
José Fonseca5a568a92011-06-29 16:43:36 +01001066 print
José Fonseca74b661a2014-07-17 19:10:24 +01001067 for suffix in ['', 'NV']:
José Fonseca5a568a92011-06-29 16:43:36 +01001068 if suffix:
José Fonsecad94aaac2011-06-28 20:50:49 +01001069 SUFFIX = '_' + suffix
José Fonsecad94aaac2011-06-28 20:50:49 +01001070 else:
José Fonseca5a568a92011-06-29 16:43:36 +01001071 SUFFIX = suffix
José Fonseca1601c412011-05-10 10:38:19 +01001072 function_name = 'glVertexAttribPointer' + suffix
José Fonseca1b6c8752012-04-15 14:33:00 +01001073 function = api.getFunctionByName(function_name)
José Fonseca06e85192011-10-16 14:15:36 +01001074
1075 print ' // %s' % function.prototype()
José Fonseca632a78d2012-04-19 07:18:59 +01001076 print ' if (_vertex_attrib == VERTEX_ATTRIB%s) {' % SUFFIX
José Fonseca5a568a92011-06-29 16:43:36 +01001077 if suffix == 'NV':
José Fonseca632a78d2012-04-19 07:18:59 +01001078 print ' GLint _max_vertex_attribs = 16;'
José Fonseca5a568a92011-06-29 16:43:36 +01001079 else:
José Fonseca26be8f92014-03-07 14:08:50 +00001080 print ' GLint _max_vertex_attribs = _glGetInteger(GL_MAX_VERTEX_ATTRIBS);'
José Fonseca632a78d2012-04-19 07:18:59 +01001081 print ' for (GLint index = 0; index < _max_vertex_attribs; ++index) {'
1082 print ' GLint _enabled = 0;'
José Fonseca5a568a92011-06-29 16:43:36 +01001083 if suffix == 'NV':
José Fonseca632a78d2012-04-19 07:18:59 +01001084 print ' _glGetIntegerv(GL_VERTEX_ATTRIB_ARRAY0_NV + index, &_enabled);'
José Fonseca5a568a92011-06-29 16:43:36 +01001085 else:
José Fonseca632a78d2012-04-19 07:18:59 +01001086 print ' _glGetVertexAttribiv%s(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED%s, &_enabled);' % (suffix, SUFFIX)
1087 print ' if (_enabled) {'
1088 print ' GLint _binding = 0;'
José Fonseca5a568a92011-06-29 16:43:36 +01001089 if suffix != 'NV':
1090 # It doesn't seem possible to use VBOs with NV_vertex_program.
José Fonseca632a78d2012-04-19 07:18:59 +01001091 print ' _glGetVertexAttribiv%s(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING%s, &_binding);' % (suffix, SUFFIX)
1092 print ' if (!_binding) {'
José Fonseca1a2fdd22011-04-01 00:55:09 +01001093
José Fonseca1601c412011-05-10 10:38:19 +01001094 # Get the arguments via glGet*
1095 for arg in function.args[1:]:
José Fonseca5a568a92011-06-29 16:43:36 +01001096 if suffix == 'NV':
1097 arg_get_enum = 'GL_ATTRIB_ARRAY_%s%s' % (arg.name.upper(), SUFFIX)
1098 else:
1099 arg_get_enum = 'GL_VERTEX_ATTRIB_ARRAY_%s%s' % (arg.name.upper(), SUFFIX)
José Fonsecac493e3e2011-06-29 12:57:06 +01001100 arg_get_function, arg_type = TypeGetter('glGetVertexAttrib', False, suffix).visit(arg.type)
José Fonseca5a568a92011-06-29 16:43:36 +01001101 print ' %s %s = 0;' % (arg_type, arg.name)
José Fonseca632a78d2012-04-19 07:18:59 +01001102 print ' _%s(index, %s, &%s);' % (arg_get_function, arg_get_enum, arg.name)
José Fonseca1601c412011-05-10 10:38:19 +01001103
1104 arg_names = ', '.join([arg.name for arg in function.args[1:-1]])
José Fonseca14cb9ef2012-05-17 21:33:14 +01001105 print ' size_t _size = _%s_size(%s, count);' % (function.name, arg_names)
José Fonseca1a2fdd22011-04-01 00:55:09 +01001106
José Fonseca1601c412011-05-10 10:38:19 +01001107 # Emit a fake function
José Fonseca7a5f23a2014-06-24 19:20:36 +01001108 print ' unsigned _call = trace::localWriter.beginEnter(&_%s_sig, true);' % (function.name,)
José Fonseca1601c412011-05-10 10:38:19 +01001109 for arg in function.args:
1110 assert not arg.output
José Fonsecab4a3d142011-10-27 07:43:19 +01001111 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
José Fonseca1601c412011-05-10 10:38:19 +01001112 if arg.name != 'pointer':
José Fonseca54f304a2012-01-14 19:33:08 +00001113 self.serializeValue(arg.type, arg.name)
José Fonseca1601c412011-05-10 10:38:19 +01001114 else:
José Fonseca632a78d2012-04-19 07:18:59 +01001115 print ' trace::localWriter.writeBlob((const void *)%s, _size);' % (arg.name)
José Fonsecab4a3d142011-10-27 07:43:19 +01001116 print ' trace::localWriter.endArg();'
José Fonseca1601c412011-05-10 10:38:19 +01001117
José Fonsecab4a3d142011-10-27 07:43:19 +01001118 print ' trace::localWriter.endEnter();'
José Fonseca632a78d2012-04-19 07:18:59 +01001119 print ' trace::localWriter.beginLeave(_call);'
José Fonsecab4a3d142011-10-27 07:43:19 +01001120 print ' trace::localWriter.endLeave();'
José Fonseca1601c412011-05-10 10:38:19 +01001121 print ' }'
1122 print ' }'
1123 print ' }'
1124 print ' }'
1125 print
José Fonseca1a2fdd22011-04-01 00:55:09 +01001126
José Fonseca8d1408b2014-02-03 19:57:18 +00001127 # Restore the original array_buffer
1128 print ' if (_array_buffer) {'
1129 self.fake_glBindBuffer(api, 'GL_ARRAY_BUFFER', '_array_buffer')
1130 print ' }'
1131 print
1132
José Fonseca669b1222011-02-20 09:05:10 +00001133 print '}'
1134 print
1135
José Fonsecafb6744f2011-04-15 11:18:37 +01001136 #
1137 # Hooks for glTexCoordPointer, which is identical to the other array
1138 # pointers except the fact that it is indexed by glClientActiveTexture.
1139 #
1140
1141 def array_prolog(self, api, uppercase_name):
1142 if uppercase_name == 'TEXTURE_COORD':
José Fonseca26be8f92014-03-07 14:08:50 +00001143 print ' GLint client_active_texture = _glGetInteger(GL_CLIENT_ACTIVE_TEXTURE);'
José Fonsecafb6744f2011-04-15 11:18:37 +01001144 print ' GLint max_texture_coords = 0;'
José Fonsecaf028a8f2012-02-15 23:33:35 +00001145 print ' if (ctx->profile == gltrace::PROFILE_COMPAT)'
José Fonseca632a78d2012-04-19 07:18:59 +01001146 print ' _glGetIntegerv(GL_MAX_TEXTURE_COORDS, &max_texture_coords);'
Chia-I Wub3d218d2011-11-03 01:37:36 +08001147 print ' else'
José Fonseca632a78d2012-04-19 07:18:59 +01001148 print ' _glGetIntegerv(GL_MAX_TEXTURE_UNITS, &max_texture_coords);'
José Fonsecafb6744f2011-04-15 11:18:37 +01001149 print ' for (GLint unit = 0; unit < max_texture_coords; ++unit) {'
José Fonseca7525e6f2011-09-28 09:04:56 +01001150 print ' GLint texture = GL_TEXTURE0 + unit;'
José Fonseca632a78d2012-04-19 07:18:59 +01001151 print ' _glClientActiveTexture(texture);'
José Fonsecafb6744f2011-04-15 11:18:37 +01001152
1153 def array_trace_prolog(self, api, uppercase_name):
1154 if uppercase_name == 'TEXTURE_COORD':
1155 print ' bool client_active_texture_dirty = false;'
1156
1157 def array_epilog(self, api, uppercase_name):
1158 if uppercase_name == 'TEXTURE_COORD':
1159 print ' }'
1160 self.array_cleanup(api, uppercase_name)
1161
1162 def array_cleanup(self, api, uppercase_name):
1163 if uppercase_name == 'TEXTURE_COORD':
José Fonseca632a78d2012-04-19 07:18:59 +01001164 print ' _glClientActiveTexture(client_active_texture);'
José Fonsecafb6744f2011-04-15 11:18:37 +01001165
1166 def array_trace_intermezzo(self, api, uppercase_name):
1167 if uppercase_name == 'TEXTURE_COORD':
1168 print ' if (texture != client_active_texture || client_active_texture_dirty) {'
1169 print ' client_active_texture_dirty = true;'
1170 self.fake_glClientActiveTexture_call(api, "texture");
1171 print ' }'
1172
1173 def array_trace_epilog(self, api, uppercase_name):
1174 if uppercase_name == 'TEXTURE_COORD':
1175 print ' if (client_active_texture_dirty) {'
1176 self.fake_glClientActiveTexture_call(api, "client_active_texture");
1177 print ' }'
1178
José Fonseca8d1408b2014-02-03 19:57:18 +00001179 def fake_glBindBuffer(self, api, target, buffer):
1180 function = api.getFunctionByName('glBindBuffer')
1181 self.fake_call(function, [target, buffer])
1182
José Fonsecafb6744f2011-04-15 11:18:37 +01001183 def fake_glClientActiveTexture_call(self, api, texture):
José Fonseca1b6c8752012-04-15 14:33:00 +01001184 function = api.getFunctionByName('glClientActiveTexture')
José Fonsecafb6744f2011-04-15 11:18:37 +01001185 self.fake_call(function, [texture])
1186
José Fonseca151c3702013-05-10 08:28:15 +01001187 def emitFakeTexture2D(self):
1188 function = glapi.glapi.getFunctionByName('glTexImage2D')
1189 instances = function.argNames()
José Fonseca7a5f23a2014-06-24 19:20:36 +01001190 print ' unsigned _fake_call = trace::localWriter.beginEnter(&_%s_sig, true);' % (function.name,)
José Fonseca151c3702013-05-10 08:28:15 +01001191 for arg in function.args:
1192 assert not arg.output
1193 self.serializeArg(function, arg)
1194 print ' trace::localWriter.endEnter();'
1195 print ' trace::localWriter.beginLeave(_fake_call);'
1196 print ' trace::localWriter.endLeave();'
José Fonsecafb6744f2011-04-15 11:18:37 +01001197
1198
1199
1200
1201
José Fonseca669b1222011-02-20 09:05:10 +00001202
1203
1204
1205
1206
1207