blob: bfeefd5e449e1455cdfc04d923d9ef08107ed2a8 [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é Fonseca1a2fdd22011-04-01 00:55:09 +0100153
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000154 for camelcase_name, uppercase_name in self.arrays:
Chia-I Wub3d218d2011-11-03 01:37:36 +0800155 # in which profile is the array available?
José Fonsecaf028a8f2012-02-15 23:33:35 +0000156 profile_check = 'ctx->profile == gltrace::PROFILE_COMPAT'
Chia-I Wub3d218d2011-11-03 01:37:36 +0800157 if camelcase_name in self.arrays_es1:
José Fonsecaf028a8f2012-02-15 23:33:35 +0000158 profile_check = '(' + profile_check + ' || ctx->profile == gltrace::PROFILE_ES1)';
Chia-I Wub3d218d2011-11-03 01:37:36 +0800159
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000160 function_name = 'gl%sPointer' % camelcase_name
161 enable_name = 'GL_%s_ARRAY' % uppercase_name
162 binding_name = 'GL_%s_ARRAY_BUFFER_BINDING' % uppercase_name
163 print ' // %s' % function_name
Chia-I Wub3d218d2011-11-03 01:37:36 +0800164 print ' if (%s) {' % profile_check
José Fonsecafb6744f2011-04-15 11:18:37 +0100165 self.array_prolog(api, uppercase_name)
José Fonseca632a78d2012-04-19 07:18:59 +0100166 print ' if (_glIsEnabled(%s)) {' % enable_name
José Fonseca26be8f92014-03-07 14:08:50 +0000167 print ' GLint _binding = _glGetInteger(%s);' % binding_name
José Fonseca632a78d2012-04-19 07:18:59 +0100168 print ' if (!_binding) {'
José Fonsecafb6744f2011-04-15 11:18:37 +0100169 self.array_cleanup(api, uppercase_name)
José Fonseca7f5163e2011-03-31 23:37:26 +0100170 print ' return true;'
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000171 print ' }'
172 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é Fonsecaf028a8f2012-02-15 23:33:35 +0000178 print ' if (ctx->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) {'
187 print ' GLint _enabled = 0;'
188 print ' _glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &_enabled);'
189 print ' if (_enabled) {'
190 print ' GLint _binding = 0;'
191 print ' _glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &_binding);'
192 print ' if (!_binding) {'
José Fonseca5a568a92011-06-29 16:43:36 +0100193 print ' return true;'
194 print ' }'
195 print ' }'
196 print ' }'
197 print ' }'
198 print
José Fonseca5a568a92011-06-29 16:43:36 +0100199 print ' // glVertexAttribPointerNV'
José Fonseca632a78d2012-04-19 07:18:59 +0100200 print ' if (_vertex_attrib == VERTEX_ATTRIB_NV) {'
José Fonseca5a568a92011-06-29 16:43:36 +0100201 print ' for (GLint index = 0; index < 16; ++index) {'
José Fonseca26be8f92014-03-07 14:08:50 +0000202 print ' GLboolean _enabled = _glIsEnabled(GL_VERTEX_ATTRIB_ARRAY0_NV);'
José Fonseca632a78d2012-04-19 07:18:59 +0100203 print ' if (_enabled) {'
José Fonseca5a568a92011-06-29 16:43:36 +0100204 print ' return true;'
José Fonseca1a2fdd22011-04-01 00:55:09 +0100205 print ' }'
206 print ' }'
207 print ' }'
208 print
209
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000210 print ' return false;'
211 print '}'
212 print
José Fonseca669b1222011-02-20 09:05:10 +0000213
José Fonseca14cb9ef2012-05-17 21:33:14 +0100214 print 'static void _trace_user_arrays(GLuint count);'
José Fonseca14c21bc2011-02-20 23:32:22 +0000215 print
José Fonseca867b1b72011-04-24 11:58:04 +0100216
José Fonseca707630d2014-03-07 14:20:35 +0000217 print '// whether glLockArraysEXT() has ever been called'
218 print 'static bool _checkLockArraysEXT = false;'
219 print
220
José Fonseca9c536b02012-02-29 20:54:13 +0000221 # Buffer mappings
222 print '// whether glMapBufferRange(GL_MAP_WRITE_BIT) has ever been called'
José Fonseca632a78d2012-04-19 07:18:59 +0100223 print 'static bool _checkBufferMapRange = false;'
José Fonseca9c536b02012-02-29 20:54:13 +0000224 print
225 print '// whether glBufferParameteriAPPLE(GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE) has ever been called'
José Fonseca632a78d2012-04-19 07:18:59 +0100226 print 'static bool _checkBufferFlushingUnmapAPPLE = false;'
José Fonseca9c536b02012-02-29 20:54:13 +0000227 print
228 # Buffer mapping information, necessary for old Mesa 2.1 drivers which
229 # do not support glGetBufferParameteriv(GL_BUFFER_ACCESS_FLAGS/GL_BUFFER_MAP_LENGTH)
José Fonseca867b1b72011-04-24 11:58:04 +0100230 print 'struct buffer_mapping {'
231 print ' void *map;'
232 print ' GLint length;'
233 print ' bool write;'
José Fonseca73373602011-05-20 17:45:26 +0100234 print ' bool explicit_flush;'
José Fonseca867b1b72011-04-24 11:58:04 +0100235 print '};'
236 print
237 for target in self.buffer_targets:
José Fonseca632a78d2012-04-19 07:18:59 +0100238 print 'struct buffer_mapping _%s_mapping;' % target.lower();
José Fonseca867b1b72011-04-24 11:58:04 +0100239 print
240 print 'static inline struct buffer_mapping *'
241 print 'get_buffer_mapping(GLenum target) {'
José Fonseca06e85192011-10-16 14:15:36 +0100242 print ' switch (target) {'
José Fonseca867b1b72011-04-24 11:58:04 +0100243 for target in self.buffer_targets:
244 print ' case GL_%s:' % target
José Fonseca632a78d2012-04-19 07:18:59 +0100245 print ' return & _%s_mapping;' % target.lower()
José Fonseca867b1b72011-04-24 11:58:04 +0100246 print ' default:'
José Fonseca559d5342011-10-27 08:10:56 +0100247 print ' os::log("apitrace: warning: unknown buffer target 0x%04X\\n", target);'
José Fonseca867b1b72011-04-24 11:58:04 +0100248 print ' return NULL;'
249 print ' }'
250 print '}'
251 print
252
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100253 # Generate a helper function to determine whether a parameter name
254 # refers to a symbolic value or not
255 print 'static bool'
256 print 'is_symbolic_pname(GLenum pname) {'
José Fonseca06e85192011-10-16 14:15:36 +0100257 print ' switch (pname) {'
José Fonseca5ea91872011-05-04 09:41:55 +0100258 for function, type, count, name in glparams.parameters:
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100259 if type is glapi.GLenum:
José Fonseca4c938c22011-04-30 22:44:38 +0100260 print ' case %s:' % name
261 print ' return true;'
262 print ' default:'
263 print ' return false;'
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100264 print ' }'
265 print '}'
266 print
267
268 # Generate a helper function to determine whether a parameter value is
269 # potentially symbolic or not; i.e., if the value can be represented in
270 # an enum or not
271 print 'template<class T>'
272 print 'static inline bool'
273 print 'is_symbolic_param(T param) {'
274 print ' return static_cast<T>(static_cast<GLenum>(param)) == param;'
275 print '}'
276 print
José Fonseca4c938c22011-04-30 22:44:38 +0100277
278 # Generate a helper function to know how many elements a parameter has
279 print 'static size_t'
José Fonseca632a78d2012-04-19 07:18:59 +0100280 print '_gl_param_size(GLenum pname) {'
José Fonseca06e85192011-10-16 14:15:36 +0100281 print ' switch (pname) {'
José Fonseca5ea91872011-05-04 09:41:55 +0100282 for function, type, count, name in glparams.parameters:
José Fonseca4c938c22011-04-30 22:44:38 +0100283 if type is not None:
José Fonsecaddf6d2c2012-12-20 15:34:50 +0000284 print ' case %s: return %s;' % (name, count)
José Fonseca4c938c22011-04-30 22:44:38 +0100285 print ' default:'
José Fonseca559d5342011-10-27 08:10:56 +0100286 print r' os::log("apitrace: warning: %s: unknown GLenum 0x%04X\n", __FUNCTION__, pname);'
José Fonseca4c938c22011-04-30 22:44:38 +0100287 print ' return 1;'
288 print ' }'
289 print '}'
290 print
291
Chia-I Wu335efb42011-11-03 01:59:22 +0800292 # states such as GL_UNPACK_ROW_LENGTH are not available in GLES
293 print 'static inline bool'
294 print 'can_unpack_subimage(void) {'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000295 print ' gltrace::Context *ctx = gltrace::getContext();'
296 print ' return (ctx->profile == gltrace::PROFILE_COMPAT);'
Chia-I Wu335efb42011-11-03 01:59:22 +0800297 print '}'
298 print
299
José Fonseca1b6c8752012-04-15 14:33:00 +0100300 getProcAddressFunctionNames = []
301
302 def traceApi(self, api):
303 if self.getProcAddressFunctionNames:
304 # Generate a function to wrap proc addresses
305 getProcAddressFunction = api.getFunctionByName(self.getProcAddressFunctionNames[0])
306 argType = getProcAddressFunction.args[0].type
307 retType = getProcAddressFunction.type
308
309 print 'static %s _wrapProcAddress(%s procName, %s procPtr);' % (retType, argType, retType)
310 print
311
312 Tracer.traceApi(self, api)
313
314 print 'static %s _wrapProcAddress(%s procName, %s procPtr) {' % (retType, argType, retType)
Peter Lohrmann0b5b75e2013-06-03 14:58:41 -0700315
316 # Provide fallback functions to missing debug functions
José Fonseca1b6c8752012-04-15 14:33:00 +0100317 print ' if (!procPtr) {'
Peter Lohrmann0b5b75e2013-06-03 14:58:41 -0700318 else_ = ''
319 for function_name in self.debug_functions:
320 if self.api.getFunctionByName(function_name):
321 print ' %sif (strcmp("%s", (const char *)procName) == 0) {' % (else_, function_name)
322 print ' return (%s)&%s;' % (retType, function_name)
323 print ' }'
324 else_ = 'else '
325 print ' %s{' % else_
326 print ' return NULL;'
327 print ' }'
José Fonseca1b6c8752012-04-15 14:33:00 +0100328 print ' }'
Peter Lohrmann0b5b75e2013-06-03 14:58:41 -0700329
José Fonseca81301932012-11-11 00:10:20 +0000330 for function in api.getAllFunctions():
José Fonseca1b6c8752012-04-15 14:33:00 +0100331 ptype = function_pointer_type(function)
332 pvalue = function_pointer_value(function)
333 print ' if (strcmp("%s", (const char *)procName) == 0) {' % function.name
334 print ' %s = (%s)procPtr;' % (pvalue, ptype)
335 print ' return (%s)&%s;' % (retType, function.name,)
336 print ' }'
337 print ' os::log("apitrace: warning: unknown function \\"%s\\"\\n", (const char *)procName);'
338 print ' return procPtr;'
339 print '}'
340 print
341 else:
342 Tracer.traceApi(self, api)
343
Imre Deakd4937372012-04-24 14:06:48 +0300344 def defineShadowBufferHelper(self):
345 print 'void _shadow_glGetBufferSubData(GLenum target, GLintptr offset,'
346 print ' GLsizeiptr size, GLvoid *data)'
347 print '{'
José Fonsecaa33d0bb2012-11-10 09:11:42 +0000348 print ' gltrace::Context *ctx = gltrace::getContext();'
Imre Deakd4937372012-04-24 14:06:48 +0300349 print ' if (!ctx->needsShadowBuffers() || target != GL_ELEMENT_ARRAY_BUFFER) {'
José Fonseca219c9f22012-11-03 10:13:17 +0000350 print ' _glGetBufferSubData(target, offset, size, data);'
Imre Deakd4937372012-04-24 14:06:48 +0300351 print ' return;'
352 print ' }'
353 print
José Fonseca26be8f92014-03-07 14:08:50 +0000354 print ' GLint buffer_binding = _glGetInteger(GL_ELEMENT_ARRAY_BUFFER_BINDING);'
José Fonseca219c9f22012-11-03 10:13:17 +0000355 print ' if (buffer_binding > 0) {'
356 print ' gltrace::Buffer & buf = ctx->buffers[buffer_binding];'
357 print ' buf.getSubData(offset, size, data);'
358 print ' }'
Imre Deakd4937372012-04-24 14:06:48 +0300359 print '}'
360
José Fonseca219c9f22012-11-03 10:13:17 +0000361 def shadowBufferMethod(self, method):
362 # Emit code to fetch the shadow buffer, and invoke a method
363 print ' gltrace::Context *ctx = gltrace::getContext();'
364 print ' if (ctx->needsShadowBuffers() && target == GL_ELEMENT_ARRAY_BUFFER) {'
José Fonseca26be8f92014-03-07 14:08:50 +0000365 print ' GLint buffer_binding = _glGetInteger(GL_ELEMENT_ARRAY_BUFFER_BINDING);'
José Fonseca219c9f22012-11-03 10:13:17 +0000366 print ' if (buffer_binding > 0) {'
367 print ' gltrace::Buffer & buf = ctx->buffers[buffer_binding];'
368 print ' buf.' + method + ';'
369 print ' }'
370 print ' }'
371 print
372
Imre Deakd4937372012-04-24 14:06:48 +0300373 def shadowBufferProlog(self, function):
374 if function.name == 'glBufferData':
José Fonseca219c9f22012-11-03 10:13:17 +0000375 self.shadowBufferMethod('bufferData(size, data)')
Imre Deakd4937372012-04-24 14:06:48 +0300376
377 if function.name == 'glBufferSubData':
José Fonseca219c9f22012-11-03 10:13:17 +0000378 self.shadowBufferMethod('bufferSubData(offset, size, data)')
Imre Deakd4937372012-04-24 14:06:48 +0300379
380 if function.name == 'glDeleteBuffers':
381 print ' gltrace::Context *ctx = gltrace::getContext();'
382 print ' if (ctx->needsShadowBuffers()) {'
José Fonseca219c9f22012-11-03 10:13:17 +0000383 print ' for (GLsizei i = 0; i < n; i++) {'
384 print ' ctx->buffers.erase(buffer[i]);'
Imre Deakd4937372012-04-24 14:06:48 +0300385 print ' }'
386 print ' }'
387
José Fonseca99221832011-03-22 22:15:46 +0000388 array_pointer_function_names = set((
389 "glVertexPointer",
390 "glNormalPointer",
391 "glColorPointer",
392 "glIndexPointer",
393 "glTexCoordPointer",
394 "glEdgeFlagPointer",
395 "glFogCoordPointer",
396 "glSecondaryColorPointer",
José Fonseca7f5163e2011-03-31 23:37:26 +0100397
José Fonsecaac5285b2011-05-04 11:09:08 +0100398 "glInterleavedArrays",
399
José Fonseca7e0bfd92011-04-30 23:09:03 +0100400 "glVertexPointerEXT",
401 "glNormalPointerEXT",
402 "glColorPointerEXT",
403 "glIndexPointerEXT",
404 "glTexCoordPointerEXT",
405 "glEdgeFlagPointerEXT",
406 "glFogCoordPointerEXT",
407 "glSecondaryColorPointerEXT",
José Fonseca99221832011-03-22 22:15:46 +0000408
José Fonseca7f5163e2011-03-31 23:37:26 +0100409 "glVertexAttribPointer",
410 "glVertexAttribPointerARB",
411 "glVertexAttribPointerNV",
José Fonsecaac5285b2011-05-04 11:09:08 +0100412 "glVertexAttribIPointer",
413 "glVertexAttribIPointerEXT",
José Fonseca7f5163e2011-03-31 23:37:26 +0100414 "glVertexAttribLPointer",
415 "glVertexAttribLPointerEXT",
José Fonseca99221832011-03-22 22:15:46 +0000416
417 #"glMatrixIndexPointerARB",
418 ))
419
420 draw_function_names = set((
421 'glDrawArrays',
422 'glDrawElements',
423 'glDrawRangeElements',
José Fonseca5c749e32011-05-09 11:11:37 +0100424 'glMultiDrawArrays',
425 'glMultiDrawElements',
426 'glDrawArraysInstanced',
José Fonsecaff8848b2011-10-09 01:04:17 +0100427 "glDrawArraysInstancedBaseInstance",
José Fonseca5c749e32011-05-09 11:11:37 +0100428 'glDrawElementsInstanced',
429 'glDrawArraysInstancedARB',
430 'glDrawElementsInstancedARB',
431 'glDrawElementsBaseVertex',
432 'glDrawRangeElementsBaseVertex',
433 'glDrawElementsInstancedBaseVertex',
José Fonsecaff8848b2011-10-09 01:04:17 +0100434 "glDrawElementsInstancedBaseInstance",
435 "glDrawElementsInstancedBaseVertexBaseInstance",
José Fonseca5c749e32011-05-09 11:11:37 +0100436 'glMultiDrawElementsBaseVertex',
437 'glDrawArraysIndirect',
438 'glDrawElementsIndirect',
José Fonseca29ac7c72013-04-14 15:40:01 +0100439 'glMultiDrawArraysIndirect',
440 'glMultiDrawArraysIndirectAMD',
441 'glMultiDrawElementsIndirect',
442 'glMultiDrawElementsIndirectAMD',
José Fonseca5c749e32011-05-09 11:11:37 +0100443 'glDrawArraysEXT',
José Fonseca7e0bfd92011-04-30 23:09:03 +0100444 'glDrawRangeElementsEXT',
José Fonseca5c749e32011-05-09 11:11:37 +0100445 'glDrawRangeElementsEXT_size',
446 'glMultiDrawArraysEXT',
447 'glMultiDrawElementsEXT',
448 'glMultiModeDrawArraysIBM',
449 'glMultiModeDrawElementsIBM',
450 'glDrawArraysInstancedEXT',
451 'glDrawElementsInstancedEXT',
José Fonseca99221832011-03-22 22:15:46 +0000452 ))
453
José Fonsecac9f12232011-03-25 20:07:42 +0000454 interleaved_formats = [
455 'GL_V2F',
456 'GL_V3F',
457 'GL_C4UB_V2F',
458 'GL_C4UB_V3F',
459 'GL_C3F_V3F',
460 'GL_N3F_V3F',
461 'GL_C4F_N3F_V3F',
462 'GL_T2F_V3F',
463 'GL_T4F_V4F',
464 'GL_T2F_C4UB_V3F',
465 'GL_T2F_C3F_V3F',
466 'GL_T2F_N3F_V3F',
467 'GL_T2F_C4F_N3F_V3F',
468 'GL_T4F_C4F_N3F_V4F',
469 ]
470
José Fonseca54f304a2012-01-14 19:33:08 +0000471 def traceFunctionImplBody(self, function):
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000472 # Defer tracing of user array pointers...
José Fonseca99221832011-03-22 22:15:46 +0000473 if function.name in self.array_pointer_function_names:
José Fonseca26be8f92014-03-07 14:08:50 +0000474 print ' GLint _array_buffer = _glGetInteger(GL_ARRAY_BUFFER_BINDING);'
José Fonseca632a78d2012-04-19 07:18:59 +0100475 print ' if (!_array_buffer) {'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000476 print ' gltrace::Context *ctx = gltrace::getContext();'
Chia-I Wu8ef66972011-11-03 01:19:46 +0800477 print ' ctx->user_arrays = true;'
José Fonseca5a568a92011-06-29 16:43:36 +0100478 if function.name == "glVertexAttribPointerNV":
Chia-I Wu8ef66972011-11-03 01:19:46 +0800479 print ' ctx->user_arrays_nv = true;'
José Fonseca54f304a2012-01-14 19:33:08 +0000480 self.invokeFunction(function)
José Fonsecaac5285b2011-05-04 11:09:08 +0100481
482 # And also break down glInterleavedArrays into the individual calls
483 if function.name == 'glInterleavedArrays':
484 print
485
486 # Initialize the enable flags
487 for camelcase_name, uppercase_name in self.arrays:
José Fonseca632a78d2012-04-19 07:18:59 +0100488 flag_name = '_' + uppercase_name.lower()
José Fonsecaac5285b2011-05-04 11:09:08 +0100489 print ' GLboolean %s = GL_FALSE;' % flag_name
490 print
491
492 # Switch for the interleaved formats
493 print ' switch (format) {'
494 for format in self.interleaved_formats:
495 print ' case %s:' % format
496 for camelcase_name, uppercase_name in self.arrays:
José Fonseca632a78d2012-04-19 07:18:59 +0100497 flag_name = '_' + uppercase_name.lower()
José Fonsecaac5285b2011-05-04 11:09:08 +0100498 if format.find('_' + uppercase_name[0]) >= 0:
499 print ' %s = GL_TRUE;' % flag_name
500 print ' break;'
501 print ' default:'
502 print ' return;'
503 print ' }'
504 print
505
506 # Emit fake glEnableClientState/glDisableClientState flags
507 for camelcase_name, uppercase_name in self.arrays:
José Fonseca632a78d2012-04-19 07:18:59 +0100508 flag_name = '_' + uppercase_name.lower()
José Fonsecaac5285b2011-05-04 11:09:08 +0100509 enable_name = 'GL_%s_ARRAY' % uppercase_name
510
511 # Emit a fake function
512 print ' {'
José Fonseca632a78d2012-04-19 07:18:59 +0100513 print ' static const trace::FunctionSig &_sig = %s ? _glEnableClientState_sig : _glDisableClientState_sig;' % flag_name
José Fonseca7a5f23a2014-06-24 19:20:36 +0100514 print ' unsigned _call = trace::localWriter.beginEnter(&_sig, true);'
José Fonsecab4a3d142011-10-27 07:43:19 +0100515 print ' trace::localWriter.beginArg(0);'
José Fonseca54f304a2012-01-14 19:33:08 +0000516 self.serializeValue(glapi.GLenum, enable_name)
José Fonsecab4a3d142011-10-27 07:43:19 +0100517 print ' trace::localWriter.endArg();'
518 print ' trace::localWriter.endEnter();'
José Fonseca632a78d2012-04-19 07:18:59 +0100519 print ' trace::localWriter.beginLeave(_call);'
José Fonsecab4a3d142011-10-27 07:43:19 +0100520 print ' trace::localWriter.endLeave();'
José Fonsecaac5285b2011-05-04 11:09:08 +0100521 print ' }'
522
José Fonsecac629a8c2014-06-01 21:12:27 +0100523 # Warn about buggy glGet(GL_*ARRAY_SIZE) not returning GL_BGRA
524 buggyFunctions = {
525 'glColorPointer': ('glGetIntegerv', '', 'GL_COLOR_ARRAY_SIZE'),
526 'glSecondaryColorPointer': ('glGetIntegerv', '', 'GL_SECONDARY_COLOR_ARRAY_SIZE'),
527 'glVertexAttribPointer': ('glGetVertexAttribiv', 'index, ', 'GL_VERTEX_ATTRIB_ARRAY_SIZE'),
528 'glVertexAttribPointerARB': ('glGetVertexAttribivARB', 'index, ', 'GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB'),
529 }
530 if function.name in buggyFunctions:
531 getter, extraArg, pname = buggyFunctions[function.name]
532 print r' static bool _checked = false;'
533 print r' if (!_checked && size == GL_BGRA) {'
534 print r' GLint _size = 0;'
535 print r' _%s(%s%s, &_size);' % (getter, extraArg, pname)
536 print r' if (_size != GL_BGRA) {'
537 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)
538 print r' }'
539 print r' _checked = true;'
540 print r' }'
541
José Fonseca99221832011-03-22 22:15:46 +0000542 print ' return;'
543 print ' }'
José Fonseca14c21bc2011-02-20 23:32:22 +0000544
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000545 # ... to the draw calls
José Fonseca99221832011-03-22 22:15:46 +0000546 if function.name in self.draw_function_names:
José Fonseca632a78d2012-04-19 07:18:59 +0100547 print ' if (_need_user_arrays()) {'
José Fonseca99221832011-03-22 22:15:46 +0000548 arg_names = ', '.join([arg.name for arg in function.args[1:]])
José Fonseca14cb9ef2012-05-17 21:33:14 +0100549 print ' GLuint _count = _%s_count(%s);' % (function.name, arg_names)
José Fonseca707630d2014-03-07 14:20:35 +0000550 # Some apps, in particular Quake3, can tell the driver to lock more
551 # vertices than those actually required for the draw call.
552 print ' if (_checkLockArraysEXT) {'
553 print ' GLuint _locked_count = _glGetInteger(GL_ARRAY_ELEMENT_LOCK_FIRST_EXT)'
554 print ' + _glGetInteger(GL_ARRAY_ELEMENT_LOCK_COUNT_EXT);'
555 print ' _count = std::max(_count, _locked_count);'
556 print ' }'
José Fonseca14cb9ef2012-05-17 21:33:14 +0100557 print ' _trace_user_arrays(_count);'
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000558 print ' }'
José Fonseca707630d2014-03-07 14:20:35 +0000559 if function.name == 'glLockArraysEXT':
560 print ' _checkLockArraysEXT = true;'
José Fonseca4a7d8602014-06-18 16:03:44 +0100561
562 # Warn if user arrays are used with glBegin/glArrayElement/glEnd.
563 if function.name == 'glBegin':
564 print r' if (_need_user_arrays()) {'
565 print r' os::log("apitrace: warning: user arrays with glArrayElement not supported (https://github.com/apitrace/apitrace/issues/276)\n");'
566 print r' }'
José Fonseca14c21bc2011-02-20 23:32:22 +0000567
José Fonseca73373602011-05-20 17:45:26 +0100568 # Emit a fake memcpy on buffer uploads
José Fonseca9c536b02012-02-29 20:54:13 +0000569 if function.name == 'glBufferParameteriAPPLE':
570 print ' if (pname == GL_BUFFER_FLUSHING_UNMAP_APPLE && param == GL_FALSE) {'
José Fonseca632a78d2012-04-19 07:18:59 +0100571 print ' _checkBufferFlushingUnmapAPPLE = true;'
José Fonseca9c536b02012-02-29 20:54:13 +0000572 print ' }'
José Fonsecacdc322c2012-02-29 19:29:51 +0000573 if function.name in ('glUnmapBuffer', 'glUnmapBufferARB'):
José Fonseca9c536b02012-02-29 20:54:13 +0000574 if function.name.endswith('ARB'):
575 suffix = 'ARB'
576 else:
577 suffix = ''
578 print ' GLint access = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100579 print ' _glGetBufferParameteriv%s(target, GL_BUFFER_ACCESS, &access);' % suffix
José Fonseca9c536b02012-02-29 20:54:13 +0000580 print ' if (access != GL_READ_ONLY) {'
581 print ' GLvoid *map = NULL;'
José Fonseca632a78d2012-04-19 07:18:59 +0100582 print ' _glGetBufferPointerv%s(target, GL_BUFFER_MAP_POINTER, &map);' % suffix
José Fonseca9c536b02012-02-29 20:54:13 +0000583 print ' if (map) {'
584 print ' GLint length = -1;'
585 print ' bool flush = true;'
José Fonseca632a78d2012-04-19 07:18:59 +0100586 print ' if (_checkBufferMapRange) {'
587 print ' _glGetBufferParameteriv%s(target, GL_BUFFER_MAP_LENGTH, &length);' % suffix
José Fonseca9c536b02012-02-29 20:54:13 +0000588 print ' GLint access_flags = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100589 print ' _glGetBufferParameteriv(target, GL_BUFFER_ACCESS_FLAGS, &access_flags);'
José Fonseca9c536b02012-02-29 20:54:13 +0000590 print ' flush = flush && !(access_flags & GL_MAP_FLUSH_EXPLICIT_BIT);'
591 print ' if (length == -1) {'
José Fonsecacb07e2d2014-02-04 15:14:09 +0000592 print ' // Mesa drivers refuse GL_BUFFER_MAP_LENGTH without GL 3.0 up-to'
593 print ' // http://cgit.freedesktop.org/mesa/mesa/commit/?id=ffee498fb848b253a7833373fe5430f8c7ca0c5f'
José Fonsecadb1ccce2012-02-29 21:09:24 +0000594 print ' static bool warned = false;'
595 print ' if (!warned) {'
596 print ' os::log("apitrace: warning: glGetBufferParameteriv%s(GL_BUFFER_MAP_LENGTH) failed\\n");' % suffix
597 print ' warned = true;'
598 print ' }'
José Fonseca9c536b02012-02-29 20:54:13 +0000599 print ' struct buffer_mapping *mapping = get_buffer_mapping(target);'
600 print ' if (mapping) {'
601 print ' length = mapping->length;'
602 print ' flush = flush && !mapping->explicit_flush;'
603 print ' } else {'
604 print ' length = 0;'
605 print ' flush = false;'
606 print ' }'
607 print ' }'
608 print ' } else {'
609 print ' length = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100610 print ' _glGetBufferParameteriv%s(target, GL_BUFFER_SIZE, &length);' % suffix
José Fonseca9c536b02012-02-29 20:54:13 +0000611 print ' }'
José Fonseca632a78d2012-04-19 07:18:59 +0100612 print ' if (_checkBufferFlushingUnmapAPPLE) {'
José Fonseca9c536b02012-02-29 20:54:13 +0000613 print ' GLint flushing_unmap = GL_TRUE;'
José Fonseca632a78d2012-04-19 07:18:59 +0100614 print ' _glGetBufferParameteriv%s(target, GL_BUFFER_FLUSHING_UNMAP_APPLE, &flushing_unmap);' % suffix
José Fonseca9c536b02012-02-29 20:54:13 +0000615 print ' flush = flush && flushing_unmap;'
616 print ' }'
617 print ' if (flush && length > 0) {'
José Fonseca6f0e3032014-06-25 01:00:35 +0100618 self.emit_memcpy('map', 'length')
José Fonseca9c536b02012-02-29 20:54:13 +0000619 print ' }'
620 print ' }'
621 print ' }'
José Fonsecacdc322c2012-02-29 19:29:51 +0000622 if function.name == 'glUnmapBufferOES':
623 print ' GLint access = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100624 print ' _glGetBufferParameteriv(target, GL_BUFFER_ACCESS_OES, &access);'
José Fonsecacdc322c2012-02-29 19:29:51 +0000625 print ' if (access == GL_WRITE_ONLY_OES) {'
626 print ' GLvoid *map = NULL;'
José Fonseca632a78d2012-04-19 07:18:59 +0100627 print ' _glGetBufferPointervOES(target, GL_BUFFER_MAP_POINTER_OES, &map);'
José Fonsecacdc322c2012-02-29 19:29:51 +0000628 print ' GLint size = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100629 print ' _glGetBufferParameteriv(target, GL_BUFFER_SIZE, &size);'
José Fonsecacdc322c2012-02-29 19:29:51 +0000630 print ' if (map && size > 0) {'
José Fonseca6f0e3032014-06-25 01:00:35 +0100631 self.emit_memcpy('map', 'size')
José Fonseca219c9f22012-11-03 10:13:17 +0000632 self.shadowBufferMethod('bufferSubData(0, size, map)')
José Fonsecacdc322c2012-02-29 19:29:51 +0000633 print ' }'
José Fonseca867b1b72011-04-24 11:58:04 +0100634 print ' }'
José Fonsecafb3bd602012-01-15 13:56:28 +0000635 if function.name == 'glUnmapNamedBufferEXT':
José Fonseca024aff42012-02-29 18:00:06 +0000636 print ' GLint access_flags = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100637 print ' _glGetNamedBufferParameterivEXT(buffer, GL_BUFFER_ACCESS_FLAGS, &access_flags);'
José Fonseca024aff42012-02-29 18:00:06 +0000638 print ' if ((access_flags & GL_MAP_WRITE_BIT) && !(access_flags & GL_MAP_FLUSH_EXPLICIT_BIT)) {'
José Fonsecafb3bd602012-01-15 13:56:28 +0000639 print ' GLvoid *map = NULL;'
José Fonseca632a78d2012-04-19 07:18:59 +0100640 print ' _glGetNamedBufferPointervEXT(buffer, GL_BUFFER_MAP_POINTER, &map);'
José Fonsecafb3bd602012-01-15 13:56:28 +0000641 print ' GLint length = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100642 print ' _glGetNamedBufferParameterivEXT(buffer, GL_BUFFER_MAP_LENGTH, &length);'
José Fonseca024aff42012-02-29 18:00:06 +0000643 print ' if (map && length > 0) {'
José Fonseca6f0e3032014-06-25 01:00:35 +0100644 self.emit_memcpy('map', 'length')
José Fonseca024aff42012-02-29 18:00:06 +0000645 print ' }'
José Fonsecafb3bd602012-01-15 13:56:28 +0000646 print ' }'
José Fonseca77ef0ce2012-02-29 18:08:48 +0000647 if function.name == 'glFlushMappedBufferRange':
648 print ' GLvoid *map = NULL;'
José Fonseca632a78d2012-04-19 07:18:59 +0100649 print ' _glGetBufferPointerv(target, GL_BUFFER_MAP_POINTER, &map);'
José Fonseca77ef0ce2012-02-29 18:08:48 +0000650 print ' if (map && length > 0) {'
José Fonseca6f0e3032014-06-25 01:00:35 +0100651 self.emit_memcpy('(const char *)map + offset', 'length')
José Fonseca77ef0ce2012-02-29 18:08:48 +0000652 print ' }'
653 if function.name == 'glFlushMappedBufferRangeAPPLE':
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 && size > 0) {'
José Fonseca6f0e3032014-06-25 01:00:35 +0100657 self.emit_memcpy('(const char *)map + offset', 'size')
José Fonseca73373602011-05-20 17:45:26 +0100658 print ' }'
José Fonsecafb3bd602012-01-15 13:56:28 +0000659 if function.name == 'glFlushMappedNamedBufferRangeEXT':
660 print ' GLvoid *map = NULL;'
José Fonseca632a78d2012-04-19 07:18:59 +0100661 print ' _glGetNamedBufferPointervEXT(buffer, GL_BUFFER_MAP_POINTER, &map);'
José Fonseca024aff42012-02-29 18:00:06 +0000662 print ' if (map && length > 0) {'
José Fonseca6f0e3032014-06-25 01:00:35 +0100663 self.emit_memcpy('(const char *)map + offset', 'length')
José Fonsecafb3bd602012-01-15 13:56:28 +0000664 print ' }'
José Fonseca867b1b72011-04-24 11:58:04 +0100665
José Fonseca3522cbd2014-02-28 14:45:32 +0000666 # FIXME: We don't support coherent/pinned memory mappings
667 # See https://github.com/apitrace/apitrace/issues/232
668 if function.name in ('glBufferStorage', 'glNamedBufferStorageEXT'):
669 print r' if (flags & GL_MAP_COHERENT_BIT) {'
670 print r' os::log("apitrace: warning: coherent mappings not fully supported\n");'
671 print r' }'
672 if function.name in ('glBufferData', 'glBufferDataARB'):
673 print r' if (target == GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD) {'
674 print r' os::log("apitrace: warning: GL_AMD_pinned_memory not fully supported\n");'
675 print r' }'
676
José Fonseca91492d22011-05-23 21:20:31 +0100677 # Don't leave vertex attrib locations to chance. Instead emit fake
678 # glBindAttribLocation calls to ensure that the same locations will be
679 # used when retracing. Trying to remap locations after the fact would
680 # be an herculian task given that vertex attrib locations appear in
681 # many entry-points, including non-shader related ones.
682 if function.name == 'glLinkProgram':
José Fonseca54f304a2012-01-14 19:33:08 +0000683 Tracer.invokeFunction(self, function)
José Fonseca91492d22011-05-23 21:20:31 +0100684 print ' GLint active_attributes = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100685 print ' _glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &active_attributes);'
José Fonseca7525e6f2011-09-28 09:04:56 +0100686 print ' for (GLint attrib = 0; attrib < active_attributes; ++attrib) {'
José Fonseca91492d22011-05-23 21:20:31 +0100687 print ' GLint size = 0;'
688 print ' GLenum type = 0;'
689 print ' GLchar name[256];'
690 # TODO: Use ACTIVE_ATTRIBUTE_MAX_LENGTH instead of 256
José Fonseca632a78d2012-04-19 07:18:59 +0100691 print ' _glGetActiveAttrib(program, attrib, sizeof name, NULL, &size, &type, name);'
José Fonseca2a794f52011-05-26 20:54:29 +0100692 print " if (name[0] != 'g' || name[1] != 'l' || name[2] != '_') {"
José Fonseca632a78d2012-04-19 07:18:59 +0100693 print ' GLint location = _glGetAttribLocation(program, name);'
José Fonseca2a794f52011-05-26 20:54:29 +0100694 print ' if (location >= 0) {'
José Fonseca1b6c8752012-04-15 14:33:00 +0100695 bind_function = glapi.glapi.getFunctionByName('glBindAttribLocation')
José Fonseca91492d22011-05-23 21:20:31 +0100696 self.fake_call(bind_function, ['program', 'location', 'name'])
José Fonseca2a794f52011-05-26 20:54:29 +0100697 print ' }'
José Fonseca91492d22011-05-23 21:20:31 +0100698 print ' }'
699 print ' }'
700 if function.name == 'glLinkProgramARB':
José Fonseca54f304a2012-01-14 19:33:08 +0000701 Tracer.invokeFunction(self, function)
José Fonseca91492d22011-05-23 21:20:31 +0100702 print ' GLint active_attributes = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100703 print ' _glGetObjectParameterivARB(programObj, GL_OBJECT_ACTIVE_ATTRIBUTES_ARB, &active_attributes);'
José Fonseca7525e6f2011-09-28 09:04:56 +0100704 print ' for (GLint attrib = 0; attrib < active_attributes; ++attrib) {'
José Fonseca91492d22011-05-23 21:20:31 +0100705 print ' GLint size = 0;'
706 print ' GLenum type = 0;'
707 print ' GLcharARB name[256];'
708 # TODO: Use ACTIVE_ATTRIBUTE_MAX_LENGTH instead of 256
José Fonseca632a78d2012-04-19 07:18:59 +0100709 print ' _glGetActiveAttribARB(programObj, attrib, sizeof name, NULL, &size, &type, name);'
José Fonseca2a794f52011-05-26 20:54:29 +0100710 print " if (name[0] != 'g' || name[1] != 'l' || name[2] != '_') {"
José Fonseca632a78d2012-04-19 07:18:59 +0100711 print ' GLint location = _glGetAttribLocationARB(programObj, name);'
José Fonseca2a794f52011-05-26 20:54:29 +0100712 print ' if (location >= 0) {'
José Fonseca1b6c8752012-04-15 14:33:00 +0100713 bind_function = glapi.glapi.getFunctionByName('glBindAttribLocationARB')
José Fonseca91492d22011-05-23 21:20:31 +0100714 self.fake_call(bind_function, ['programObj', 'location', 'name'])
José Fonseca2a794f52011-05-26 20:54:29 +0100715 print ' }'
José Fonseca91492d22011-05-23 21:20:31 +0100716 print ' }'
717 print ' }'
718
Imre Deakd4937372012-04-24 14:06:48 +0300719 self.shadowBufferProlog(function)
720
José Fonseca54f304a2012-01-14 19:33:08 +0000721 Tracer.traceFunctionImplBody(self, function)
José Fonseca73373602011-05-20 17:45:26 +0100722
Peter Lohrmann0b5b75e2013-06-03 14:58:41 -0700723 # These entrypoints are only expected to be implemented by tools;
724 # drivers will probably not implement them.
José Fonsecaf028a8f2012-02-15 23:33:35 +0000725 marker_functions = [
726 # GL_GREMEDY_string_marker
José Fonseca8f34d342011-07-15 20:16:40 +0100727 'glStringMarkerGREMEDY',
José Fonsecaf028a8f2012-02-15 23:33:35 +0000728 # GL_GREMEDY_frame_terminator
José Fonseca8f34d342011-07-15 20:16:40 +0100729 'glFrameTerminatorGREMEDY',
José Fonsecaf028a8f2012-02-15 23:33:35 +0000730 # GL_EXT_debug_marker
731 'glInsertEventMarkerEXT',
732 'glPushGroupMarkerEXT',
733 'glPopGroupMarkerEXT',
José Fonseca8f34d342011-07-15 20:16:40 +0100734 ]
735
Peter Lohrmann0b5b75e2013-06-03 14:58:41 -0700736 # These entrypoints may be implemented by drivers, but are also very useful
737 # for debugging / analysis tools.
738 debug_functions = [
739 # GL_KHR_debug
740 'glDebugMessageControl',
741 'glDebugMessageInsert',
742 'glDebugMessageCallback',
743 'glGetDebugMessageLog',
744 'glPushDebugGroup',
745 'glPopDebugGroup',
746 'glObjectLabel',
747 'glGetObjectLabel',
748 'glObjectPtrLabel',
749 'glGetObjectPtrLabel',
750 # GL_ARB_debug_output
751 'glDebugMessageControlARB',
752 'glDebugMessageInsertARB',
753 'glDebugMessageCallbackARB',
754 'glGetDebugMessageLogARB',
755 # GL_AMD_debug_output
756 'glDebugMessageEnableAMD',
757 'glDebugMessageInsertAMD',
758 'glDebugMessageCallbackAMD',
759 'glGetDebugMessageLogAMD',
760 ]
761
José Fonseca54f304a2012-01-14 19:33:08 +0000762 def invokeFunction(self, function):
José Fonseca91492d22011-05-23 21:20:31 +0100763 if function.name in ('glLinkProgram', 'glLinkProgramARB'):
764 # These functions have been dispatched already
765 return
766
José Fonseca2cfa02c2013-06-10 08:05:29 +0100767 Tracer.invokeFunction(self, function)
768
769 def doInvokeFunction(self, function):
770 # Same as invokeFunction() but called both when trace is enabled or disabled.
771 #
772 # Used to modify the behavior of GL entry-points.
773
774 # Override GL extensions
775 if function.name in ('glGetString', 'glGetIntegerv', 'glGetStringi'):
776 Tracer.doInvokeFunction(self, function, prefix = 'gltrace::_', suffix = '_override')
777 return
778
José Fonsecaf028a8f2012-02-15 23:33:35 +0000779 # We implement GL_EXT_debug_marker, GL_GREMEDY_*, etc., and not the
780 # driver
781 if function.name in self.marker_functions:
José Fonseca8f34d342011-07-15 20:16:40 +0100782 return
783
Peter Lohrmann9d9eb812013-07-12 16:15:25 -0400784 # We may be faking KHR_debug, so ensure the pointer queries result is
785 # always zeroed to prevent dereference of unitialized pointers
786 if function.name == 'glGetPointerv':
787 print ' if (params &&'
788 print ' (pname == GL_DEBUG_CALLBACK_FUNCTION ||'
789 print ' pname == GL_DEBUG_CALLBACK_USER_PARAM)) {'
790 print ' *params = NULL;'
791 print ' }'
792
José Fonseca2cfa02c2013-06-10 08:05:29 +0100793 if function.name in self.getProcAddressFunctionNames:
José Fonsecaf028a8f2012-02-15 23:33:35 +0000794 else_ = ''
795 for marker_function in self.marker_functions:
José Fonseca1b6c8752012-04-15 14:33:00 +0100796 if self.api.getFunctionByName(marker_function):
José Fonsecaf028a8f2012-02-15 23:33:35 +0000797 print ' %sif (strcmp("%s", (const char *)%s) == 0) {' % (else_, marker_function, function.args[0].name)
José Fonseca632a78d2012-04-19 07:18:59 +0100798 print ' _result = (%s)&%s;' % (function.type, marker_function)
José Fonsecaf028a8f2012-02-15 23:33:35 +0000799 print ' }'
800 else_ = 'else '
801 print ' %s{' % else_
José Fonseca2cfa02c2013-06-10 08:05:29 +0100802 Tracer.doInvokeFunction(self, function)
803
804 # Replace function addresses with ours
805 # XXX: Doing this here instead of wrapRet means that the trace will
806 # contain the addresses of the wrapper functions, and not the real
807 # functions, but in practice this should make no difference.
808 if function.name in self.getProcAddressFunctionNames:
809 print ' _result = _wrapProcAddress(%s, _result);' % (function.args[0].name,)
810
José Fonseca8f34d342011-07-15 20:16:40 +0100811 print ' }'
José Fonseca1b3d3752011-07-15 10:15:19 +0100812 return
813
José Fonseca2cfa02c2013-06-10 08:05:29 +0100814 Tracer.doInvokeFunction(self, function)
José Fonseca91492d22011-05-23 21:20:31 +0100815
José Fonseca867b1b72011-04-24 11:58:04 +0100816 buffer_targets = [
817 'ARRAY_BUFFER',
818 'ELEMENT_ARRAY_BUFFER',
819 'PIXEL_PACK_BUFFER',
820 'PIXEL_UNPACK_BUFFER',
José Fonseca7b20d672012-01-10 19:13:58 +0000821 'UNIFORM_BUFFER',
822 'TEXTURE_BUFFER',
823 'TRANSFORM_FEEDBACK_BUFFER',
824 'COPY_READ_BUFFER',
825 'COPY_WRITE_BUFFER',
826 'DRAW_INDIRECT_BUFFER',
827 'ATOMIC_COUNTER_BUFFER',
José Fonseca867b1b72011-04-24 11:58:04 +0100828 ]
829
José Fonseca54f304a2012-01-14 19:33:08 +0000830 def wrapRet(self, function, instance):
831 Tracer.wrapRet(self, function, instance)
José Fonseca1b3d3752011-07-15 10:15:19 +0100832
José Fonsecacdc322c2012-02-29 19:29:51 +0000833 # Keep track of buffer mappings
834 if function.name in ('glMapBuffer', 'glMapBufferARB'):
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 = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100839 print ' _glGetBufferParameteriv(target, GL_BUFFER_SIZE, &mapping->length);'
José Fonseca867b1b72011-04-24 11:58:04 +0100840 print ' mapping->write = (access != GL_READ_ONLY);'
José Fonseca73373602011-05-20 17:45:26 +0100841 print ' mapping->explicit_flush = false;'
José Fonseca867b1b72011-04-24 11:58:04 +0100842 print ' }'
José Fonseca867b1b72011-04-24 11:58:04 +0100843 if function.name == 'glMapBufferRange':
José Fonseca9c536b02012-02-29 20:54:13 +0000844 print ' if (access & GL_MAP_WRITE_BIT) {'
José Fonseca632a78d2012-04-19 07:18:59 +0100845 print ' _checkBufferMapRange = true;'
José Fonseca9c536b02012-02-29 20:54:13 +0000846 print ' }'
José Fonseca867b1b72011-04-24 11:58:04 +0100847 print ' struct buffer_mapping *mapping = get_buffer_mapping(target);'
848 print ' if (mapping) {'
849 print ' mapping->map = %s;' % (instance)
850 print ' mapping->length = length;'
851 print ' mapping->write = access & GL_MAP_WRITE_BIT;'
José Fonseca73373602011-05-20 17:45:26 +0100852 print ' mapping->explicit_flush = access & GL_MAP_FLUSH_EXPLICIT_BIT;'
José Fonseca867b1b72011-04-24 11:58:04 +0100853 print ' }'
José Fonseca669b1222011-02-20 09:05:10 +0000854
José Fonsecac9f12232011-03-25 20:07:42 +0000855 boolean_names = [
856 'GL_FALSE',
857 'GL_TRUE',
858 ]
859
860 def gl_boolean(self, value):
861 return self.boolean_names[int(bool(value))]
862
José Fonsecac29f4f12011-06-11 12:19:05 +0100863 # Names of the functions that unpack from a pixel buffer object. See the
864 # ARB_pixel_buffer_object specification.
José Fonsecae97bab92011-06-02 23:15:11 +0100865 unpack_function_names = set([
866 'glBitmap',
José Fonsecac29f4f12011-06-11 12:19:05 +0100867 'glColorSubTable',
868 'glColorTable',
José Fonsecad2bd4ca2013-04-12 11:41:00 +0100869 'glCompressedMultiTexImage1DEXT',
870 'glCompressedMultiTexImage2DEXT',
871 'glCompressedMultiTexImage3DEXT',
872 'glCompressedMultiTexSubImage1DEXT',
873 'glCompressedMultiTexSubImage2DEXT',
874 'glCompressedMultiTexSubImage3DEXT',
José Fonsecac29f4f12011-06-11 12:19:05 +0100875 'glCompressedTexImage1D',
idinevdb5ad3b2014-02-03 15:50:39 +0000876 'glCompressedTexImage1DARB',
José Fonsecac29f4f12011-06-11 12:19:05 +0100877 'glCompressedTexImage2D',
idinevdb5ad3b2014-02-03 15:50:39 +0000878 'glCompressedTexImage2DARB',
José Fonsecac29f4f12011-06-11 12:19:05 +0100879 'glCompressedTexImage3D',
idinevdb5ad3b2014-02-03 15:50:39 +0000880 'glCompressedTexImage3DARB',
José Fonsecac29f4f12011-06-11 12:19:05 +0100881 'glCompressedTexSubImage1D',
idinevdb5ad3b2014-02-03 15:50:39 +0000882 'glCompressedTexSubImage1DARB',
José Fonsecac29f4f12011-06-11 12:19:05 +0100883 'glCompressedTexSubImage2D',
idinevdb5ad3b2014-02-03 15:50:39 +0000884 'glCompressedTexSubImage2DARB',
José Fonsecac29f4f12011-06-11 12:19:05 +0100885 'glCompressedTexSubImage3D',
idinevdb5ad3b2014-02-03 15:50:39 +0000886 'glCompressedTexSubImage3DARB',
José Fonsecad2bd4ca2013-04-12 11:41:00 +0100887 'glCompressedTextureImage1DEXT',
888 'glCompressedTextureImage2DEXT',
889 'glCompressedTextureImage3DEXT',
890 'glCompressedTextureSubImage1DEXT',
891 'glCompressedTextureSubImage2DEXT',
892 'glCompressedTextureSubImage3DEXT',
José Fonsecac29f4f12011-06-11 12:19:05 +0100893 'glConvolutionFilter1D',
894 'glConvolutionFilter2D',
José Fonsecae97bab92011-06-02 23:15:11 +0100895 'glDrawPixels',
896 'glMultiTexImage1DEXT',
897 'glMultiTexImage2DEXT',
898 'glMultiTexImage3DEXT',
899 'glMultiTexSubImage1DEXT',
900 'glMultiTexSubImage2DEXT',
901 'glMultiTexSubImage3DEXT',
José Fonsecac29f4f12011-06-11 12:19:05 +0100902 'glPixelMapfv',
903 'glPixelMapuiv',
904 'glPixelMapusv',
José Fonsecae97bab92011-06-02 23:15:11 +0100905 'glPolygonStipple',
José Fonsecac29f4f12011-06-11 12:19:05 +0100906 'glSeparableFilter2D',
José Fonsecae97bab92011-06-02 23:15:11 +0100907 'glTexImage1D',
908 'glTexImage1DEXT',
909 'glTexImage2D',
910 'glTexImage2DEXT',
911 'glTexImage3D',
912 'glTexImage3DEXT',
913 'glTexSubImage1D',
914 'glTexSubImage1DEXT',
915 'glTexSubImage2D',
916 'glTexSubImage2DEXT',
917 'glTexSubImage3D',
918 'glTexSubImage3DEXT',
919 'glTextureImage1DEXT',
920 'glTextureImage2DEXT',
921 'glTextureImage3DEXT',
922 'glTextureSubImage1DEXT',
923 'glTextureSubImage2DEXT',
924 'glTextureSubImage3DEXT',
925 ])
926
José Fonseca54f304a2012-01-14 19:33:08 +0000927 def serializeArgValue(self, function, arg):
José Fonsecae97bab92011-06-02 23:15:11 +0100928 # Recognize offsets instead of blobs when a PBO is bound
929 if function.name in self.unpack_function_names \
930 and (isinstance(arg.type, stdapi.Blob) \
931 or (isinstance(arg.type, stdapi.Const) \
932 and isinstance(arg.type.type, stdapi.Blob))):
José Fonsecac29f4f12011-06-11 12:19:05 +0100933 print ' {'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000934 print ' gltrace::Context *ctx = gltrace::getContext();'
José Fonseca632a78d2012-04-19 07:18:59 +0100935 print ' GLint _unpack_buffer = 0;'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000936 print ' if (ctx->profile == gltrace::PROFILE_COMPAT)'
José Fonseca632a78d2012-04-19 07:18:59 +0100937 print ' _glGetIntegerv(GL_PIXEL_UNPACK_BUFFER_BINDING, &_unpack_buffer);'
938 print ' if (_unpack_buffer) {'
José Fonsecad559f022012-04-15 16:13:51 +0100939 print ' trace::localWriter.writePointer((uintptr_t)%s);' % arg.name
José Fonsecac29f4f12011-06-11 12:19:05 +0100940 print ' } else {'
José Fonseca54f304a2012-01-14 19:33:08 +0000941 Tracer.serializeArgValue(self, function, arg)
José Fonsecac29f4f12011-06-11 12:19:05 +0100942 print ' }'
José Fonsecae97bab92011-06-02 23:15:11 +0100943 print ' }'
944 return
945
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100946 # Several GL state functions take GLenum symbolic names as
947 # integer/floats; so dump the symbolic name whenever possible
José Fonseca3bcb33c2011-05-27 20:14:31 +0100948 if function.name.startswith('gl') \
José Fonsecae3571092011-10-13 08:26:27 +0100949 and arg.type in (glapi.GLint, glapi.GLfloat, glapi.GLdouble) \
José Fonseca3bcb33c2011-05-27 20:14:31 +0100950 and arg.name == 'param':
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100951 assert arg.index > 0
952 assert function.args[arg.index - 1].name == 'pname'
953 assert function.args[arg.index - 1].type == glapi.GLenum
954 print ' if (is_symbolic_pname(pname) && is_symbolic_param(%s)) {' % arg.name
José Fonseca54f304a2012-01-14 19:33:08 +0000955 self.serializeValue(glapi.GLenum, arg.name)
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100956 print ' } else {'
José Fonseca54f304a2012-01-14 19:33:08 +0000957 Tracer.serializeArgValue(self, function, arg)
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100958 print ' }'
959 return
960
José Fonseca54f304a2012-01-14 19:33:08 +0000961 Tracer.serializeArgValue(self, function, arg)
José Fonseca99221832011-03-22 22:15:46 +0000962
José Fonseca4c938c22011-04-30 22:44:38 +0100963 def footer(self, api):
964 Tracer.footer(self, api)
José Fonseca669b1222011-02-20 09:05:10 +0000965
José Fonseca4c938c22011-04-30 22:44:38 +0100966 # A simple state tracker to track the pointer values
José Fonseca669b1222011-02-20 09:05:10 +0000967 # update the state
José Fonseca14cb9ef2012-05-17 21:33:14 +0100968 print 'static void _trace_user_arrays(GLuint count)'
José Fonseca669b1222011-02-20 09:05:10 +0000969 print '{'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000970 print ' gltrace::Context *ctx = gltrace::getContext();'
José Fonseca8d1408b2014-02-03 19:57:18 +0000971 print
972
973 # Temporarily unbind the array buffer
José Fonseca26be8f92014-03-07 14:08:50 +0000974 print ' GLint _array_buffer = _glGetInteger(GL_ARRAY_BUFFER_BINDING);'
José Fonseca8d1408b2014-02-03 19:57:18 +0000975 print ' if (_array_buffer) {'
976 self.fake_glBindBuffer(api, 'GL_ARRAY_BUFFER', '0')
977 print ' }'
978 print
José Fonseca1a2fdd22011-04-01 00:55:09 +0100979
José Fonseca99221832011-03-22 22:15:46 +0000980 for camelcase_name, uppercase_name in self.arrays:
Chia-I Wub3d218d2011-11-03 01:37:36 +0800981 # in which profile is the array available?
José Fonsecaf028a8f2012-02-15 23:33:35 +0000982 profile_check = 'ctx->profile == gltrace::PROFILE_COMPAT'
Chia-I Wub3d218d2011-11-03 01:37:36 +0800983 if camelcase_name in self.arrays_es1:
José Fonsecaf028a8f2012-02-15 23:33:35 +0000984 profile_check = '(' + profile_check + ' || ctx->profile == gltrace::PROFILE_ES1)';
Chia-I Wub3d218d2011-11-03 01:37:36 +0800985
José Fonseca99221832011-03-22 22:15:46 +0000986 function_name = 'gl%sPointer' % camelcase_name
987 enable_name = 'GL_%s_ARRAY' % uppercase_name
988 binding_name = 'GL_%s_ARRAY_BUFFER_BINDING' % uppercase_name
José Fonseca1b6c8752012-04-15 14:33:00 +0100989 function = api.getFunctionByName(function_name)
José Fonseca99221832011-03-22 22:15:46 +0000990
José Fonseca06e85192011-10-16 14:15:36 +0100991 print ' // %s' % function.prototype()
Chia-I Wub3d218d2011-11-03 01:37:36 +0800992 print ' if (%s) {' % profile_check
José Fonsecafb6744f2011-04-15 11:18:37 +0100993 self.array_trace_prolog(api, uppercase_name)
994 self.array_prolog(api, uppercase_name)
José Fonseca632a78d2012-04-19 07:18:59 +0100995 print ' if (_glIsEnabled(%s)) {' % enable_name
José Fonseca26be8f92014-03-07 14:08:50 +0000996 print ' GLint _binding = _glGetInteger(%s);' % binding_name
José Fonseca632a78d2012-04-19 07:18:59 +0100997 print ' if (!_binding) {'
José Fonseca99221832011-03-22 22:15:46 +0000998
999 # Get the arguments via glGet*
1000 for arg in function.args:
1001 arg_get_enum = 'GL_%s_ARRAY_%s' % (uppercase_name, arg.name.upper())
1002 arg_get_function, arg_type = TypeGetter().visit(arg.type)
José Fonseca7f5163e2011-03-31 23:37:26 +01001003 print ' %s %s = 0;' % (arg_type, arg.name)
José Fonseca632a78d2012-04-19 07:18:59 +01001004 print ' _%s(%s, &%s);' % (arg_get_function, arg_get_enum, arg.name)
José Fonseca99221832011-03-22 22:15:46 +00001005
1006 arg_names = ', '.join([arg.name for arg in function.args[:-1]])
José Fonseca14cb9ef2012-05-17 21:33:14 +01001007 print ' size_t _size = _%s_size(%s, count);' % (function.name, arg_names)
José Fonseca99221832011-03-22 22:15:46 +00001008
1009 # Emit a fake function
José Fonsecafb6744f2011-04-15 11:18:37 +01001010 self.array_trace_intermezzo(api, uppercase_name)
José Fonseca7a5f23a2014-06-24 19:20:36 +01001011 print ' unsigned _call = trace::localWriter.beginEnter(&_%s_sig, true);' % (function.name,)
José Fonseca669b1222011-02-20 09:05:10 +00001012 for arg in function.args:
1013 assert not arg.output
José Fonsecab4a3d142011-10-27 07:43:19 +01001014 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
José Fonseca14c21bc2011-02-20 23:32:22 +00001015 if arg.name != 'pointer':
José Fonseca54f304a2012-01-14 19:33:08 +00001016 self.serializeValue(arg.type, arg.name)
José Fonseca14c21bc2011-02-20 23:32:22 +00001017 else:
José Fonseca632a78d2012-04-19 07:18:59 +01001018 print ' trace::localWriter.writeBlob((const void *)%s, _size);' % (arg.name)
José Fonsecab4a3d142011-10-27 07:43:19 +01001019 print ' trace::localWriter.endArg();'
José Fonseca99221832011-03-22 22:15:46 +00001020
José Fonsecab4a3d142011-10-27 07:43:19 +01001021 print ' trace::localWriter.endEnter();'
José Fonseca632a78d2012-04-19 07:18:59 +01001022 print ' trace::localWriter.beginLeave(_call);'
José Fonsecab4a3d142011-10-27 07:43:19 +01001023 print ' trace::localWriter.endLeave();'
José Fonseca99221832011-03-22 22:15:46 +00001024 print ' }'
José Fonseca669b1222011-02-20 09:05:10 +00001025 print ' }'
José Fonsecafb6744f2011-04-15 11:18:37 +01001026 self.array_epilog(api, uppercase_name)
1027 self.array_trace_epilog(api, uppercase_name)
Chia-I Wub3d218d2011-11-03 01:37:36 +08001028 print ' }'
José Fonseca99221832011-03-22 22:15:46 +00001029 print
José Fonseca1a2fdd22011-04-01 00:55:09 +01001030
José Fonseca1601c412011-05-10 10:38:19 +01001031 # Samething, but for glVertexAttribPointer*
1032 #
1033 # Some variants of glVertexAttribPointer alias conventional and generic attributes:
1034 # - glVertexAttribPointer: no
1035 # - glVertexAttribPointerARB: implementation dependent
1036 # - glVertexAttribPointerNV: yes
1037 #
1038 # This means that the implementations of these functions do not always
1039 # alias, and they need to be considered independently.
1040 #
Chia-I Wub3d218d2011-11-03 01:37:36 +08001041 print ' // ES1 does not support generic vertex attributes'
José Fonsecaf028a8f2012-02-15 23:33:35 +00001042 print ' if (ctx->profile == gltrace::PROFILE_ES1)'
Chia-I Wub3d218d2011-11-03 01:37:36 +08001043 print ' return;'
1044 print
José Fonseca632a78d2012-04-19 07:18:59 +01001045 print ' vertex_attrib _vertex_attrib = _get_vertex_attrib();'
José Fonseca5a568a92011-06-29 16:43:36 +01001046 print
José Fonseca74b661a2014-07-17 19:10:24 +01001047 for suffix in ['', 'NV']:
José Fonseca5a568a92011-06-29 16:43:36 +01001048 if suffix:
José Fonsecad94aaac2011-06-28 20:50:49 +01001049 SUFFIX = '_' + suffix
José Fonsecad94aaac2011-06-28 20:50:49 +01001050 else:
José Fonseca5a568a92011-06-29 16:43:36 +01001051 SUFFIX = suffix
José Fonseca1601c412011-05-10 10:38:19 +01001052 function_name = 'glVertexAttribPointer' + suffix
José Fonseca1b6c8752012-04-15 14:33:00 +01001053 function = api.getFunctionByName(function_name)
José Fonseca06e85192011-10-16 14:15:36 +01001054
1055 print ' // %s' % function.prototype()
José Fonseca632a78d2012-04-19 07:18:59 +01001056 print ' if (_vertex_attrib == VERTEX_ATTRIB%s) {' % SUFFIX
José Fonseca5a568a92011-06-29 16:43:36 +01001057 if suffix == 'NV':
José Fonseca632a78d2012-04-19 07:18:59 +01001058 print ' GLint _max_vertex_attribs = 16;'
José Fonseca5a568a92011-06-29 16:43:36 +01001059 else:
José Fonseca26be8f92014-03-07 14:08:50 +00001060 print ' GLint _max_vertex_attribs = _glGetInteger(GL_MAX_VERTEX_ATTRIBS);'
José Fonseca632a78d2012-04-19 07:18:59 +01001061 print ' for (GLint index = 0; index < _max_vertex_attribs; ++index) {'
1062 print ' GLint _enabled = 0;'
José Fonseca5a568a92011-06-29 16:43:36 +01001063 if suffix == 'NV':
José Fonseca632a78d2012-04-19 07:18:59 +01001064 print ' _glGetIntegerv(GL_VERTEX_ATTRIB_ARRAY0_NV + index, &_enabled);'
José Fonseca5a568a92011-06-29 16:43:36 +01001065 else:
José Fonseca632a78d2012-04-19 07:18:59 +01001066 print ' _glGetVertexAttribiv%s(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED%s, &_enabled);' % (suffix, SUFFIX)
1067 print ' if (_enabled) {'
1068 print ' GLint _binding = 0;'
José Fonseca5a568a92011-06-29 16:43:36 +01001069 if suffix != 'NV':
1070 # It doesn't seem possible to use VBOs with NV_vertex_program.
José Fonseca632a78d2012-04-19 07:18:59 +01001071 print ' _glGetVertexAttribiv%s(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING%s, &_binding);' % (suffix, SUFFIX)
1072 print ' if (!_binding) {'
José Fonseca1a2fdd22011-04-01 00:55:09 +01001073
José Fonseca1601c412011-05-10 10:38:19 +01001074 # Get the arguments via glGet*
1075 for arg in function.args[1:]:
José Fonseca5a568a92011-06-29 16:43:36 +01001076 if suffix == 'NV':
1077 arg_get_enum = 'GL_ATTRIB_ARRAY_%s%s' % (arg.name.upper(), SUFFIX)
1078 else:
1079 arg_get_enum = 'GL_VERTEX_ATTRIB_ARRAY_%s%s' % (arg.name.upper(), SUFFIX)
José Fonsecac493e3e2011-06-29 12:57:06 +01001080 arg_get_function, arg_type = TypeGetter('glGetVertexAttrib', False, suffix).visit(arg.type)
José Fonseca5a568a92011-06-29 16:43:36 +01001081 print ' %s %s = 0;' % (arg_type, arg.name)
José Fonseca632a78d2012-04-19 07:18:59 +01001082 print ' _%s(index, %s, &%s);' % (arg_get_function, arg_get_enum, arg.name)
José Fonseca1601c412011-05-10 10:38:19 +01001083
1084 arg_names = ', '.join([arg.name for arg in function.args[1:-1]])
José Fonseca14cb9ef2012-05-17 21:33:14 +01001085 print ' size_t _size = _%s_size(%s, count);' % (function.name, arg_names)
José Fonseca1a2fdd22011-04-01 00:55:09 +01001086
José Fonseca1601c412011-05-10 10:38:19 +01001087 # Emit a fake function
José Fonseca7a5f23a2014-06-24 19:20:36 +01001088 print ' unsigned _call = trace::localWriter.beginEnter(&_%s_sig, true);' % (function.name,)
José Fonseca1601c412011-05-10 10:38:19 +01001089 for arg in function.args:
1090 assert not arg.output
José Fonsecab4a3d142011-10-27 07:43:19 +01001091 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
José Fonseca1601c412011-05-10 10:38:19 +01001092 if arg.name != 'pointer':
José Fonseca54f304a2012-01-14 19:33:08 +00001093 self.serializeValue(arg.type, arg.name)
José Fonseca1601c412011-05-10 10:38:19 +01001094 else:
José Fonseca632a78d2012-04-19 07:18:59 +01001095 print ' trace::localWriter.writeBlob((const void *)%s, _size);' % (arg.name)
José Fonsecab4a3d142011-10-27 07:43:19 +01001096 print ' trace::localWriter.endArg();'
José Fonseca1601c412011-05-10 10:38:19 +01001097
José Fonsecab4a3d142011-10-27 07:43:19 +01001098 print ' trace::localWriter.endEnter();'
José Fonseca632a78d2012-04-19 07:18:59 +01001099 print ' trace::localWriter.beginLeave(_call);'
José Fonsecab4a3d142011-10-27 07:43:19 +01001100 print ' trace::localWriter.endLeave();'
José Fonseca1601c412011-05-10 10:38:19 +01001101 print ' }'
1102 print ' }'
1103 print ' }'
1104 print ' }'
1105 print
José Fonseca1a2fdd22011-04-01 00:55:09 +01001106
José Fonseca8d1408b2014-02-03 19:57:18 +00001107 # Restore the original array_buffer
1108 print ' if (_array_buffer) {'
1109 self.fake_glBindBuffer(api, 'GL_ARRAY_BUFFER', '_array_buffer')
1110 print ' }'
1111 print
1112
José Fonseca669b1222011-02-20 09:05:10 +00001113 print '}'
1114 print
1115
José Fonsecafb6744f2011-04-15 11:18:37 +01001116 #
1117 # Hooks for glTexCoordPointer, which is identical to the other array
1118 # pointers except the fact that it is indexed by glClientActiveTexture.
1119 #
1120
1121 def array_prolog(self, api, uppercase_name):
1122 if uppercase_name == 'TEXTURE_COORD':
José Fonseca26be8f92014-03-07 14:08:50 +00001123 print ' GLint client_active_texture = _glGetInteger(GL_CLIENT_ACTIVE_TEXTURE);'
José Fonsecafb6744f2011-04-15 11:18:37 +01001124 print ' GLint max_texture_coords = 0;'
José Fonsecaf028a8f2012-02-15 23:33:35 +00001125 print ' if (ctx->profile == gltrace::PROFILE_COMPAT)'
José Fonseca632a78d2012-04-19 07:18:59 +01001126 print ' _glGetIntegerv(GL_MAX_TEXTURE_COORDS, &max_texture_coords);'
Chia-I Wub3d218d2011-11-03 01:37:36 +08001127 print ' else'
José Fonseca632a78d2012-04-19 07:18:59 +01001128 print ' _glGetIntegerv(GL_MAX_TEXTURE_UNITS, &max_texture_coords);'
José Fonsecafb6744f2011-04-15 11:18:37 +01001129 print ' for (GLint unit = 0; unit < max_texture_coords; ++unit) {'
José Fonseca7525e6f2011-09-28 09:04:56 +01001130 print ' GLint texture = GL_TEXTURE0 + unit;'
José Fonseca632a78d2012-04-19 07:18:59 +01001131 print ' _glClientActiveTexture(texture);'
José Fonsecafb6744f2011-04-15 11:18:37 +01001132
1133 def array_trace_prolog(self, api, uppercase_name):
1134 if uppercase_name == 'TEXTURE_COORD':
1135 print ' bool client_active_texture_dirty = false;'
1136
1137 def array_epilog(self, api, uppercase_name):
1138 if uppercase_name == 'TEXTURE_COORD':
1139 print ' }'
1140 self.array_cleanup(api, uppercase_name)
1141
1142 def array_cleanup(self, api, uppercase_name):
1143 if uppercase_name == 'TEXTURE_COORD':
José Fonseca632a78d2012-04-19 07:18:59 +01001144 print ' _glClientActiveTexture(client_active_texture);'
José Fonsecafb6744f2011-04-15 11:18:37 +01001145
1146 def array_trace_intermezzo(self, api, uppercase_name):
1147 if uppercase_name == 'TEXTURE_COORD':
1148 print ' if (texture != client_active_texture || client_active_texture_dirty) {'
1149 print ' client_active_texture_dirty = true;'
1150 self.fake_glClientActiveTexture_call(api, "texture");
1151 print ' }'
1152
1153 def array_trace_epilog(self, api, uppercase_name):
1154 if uppercase_name == 'TEXTURE_COORD':
1155 print ' if (client_active_texture_dirty) {'
1156 self.fake_glClientActiveTexture_call(api, "client_active_texture");
1157 print ' }'
1158
José Fonseca8d1408b2014-02-03 19:57:18 +00001159 def fake_glBindBuffer(self, api, target, buffer):
1160 function = api.getFunctionByName('glBindBuffer')
1161 self.fake_call(function, [target, buffer])
1162
José Fonsecafb6744f2011-04-15 11:18:37 +01001163 def fake_glClientActiveTexture_call(self, api, texture):
José Fonseca1b6c8752012-04-15 14:33:00 +01001164 function = api.getFunctionByName('glClientActiveTexture')
José Fonsecafb6744f2011-04-15 11:18:37 +01001165 self.fake_call(function, [texture])
1166
José Fonseca151c3702013-05-10 08:28:15 +01001167 def emitFakeTexture2D(self):
1168 function = glapi.glapi.getFunctionByName('glTexImage2D')
1169 instances = function.argNames()
José Fonseca7a5f23a2014-06-24 19:20:36 +01001170 print ' unsigned _fake_call = trace::localWriter.beginEnter(&_%s_sig, true);' % (function.name,)
José Fonseca151c3702013-05-10 08:28:15 +01001171 for arg in function.args:
1172 assert not arg.output
1173 self.serializeArg(function, arg)
1174 print ' trace::localWriter.endEnter();'
1175 print ' trace::localWriter.beginLeave(_fake_call);'
1176 print ' trace::localWriter.endLeave();'
José Fonsecafb6744f2011-04-15 11:18:37 +01001177
1178
1179
1180
1181
José Fonseca669b1222011-02-20 09:05:10 +00001182
1183
1184
1185
1186
1187