blob: 5a05e81bb82532ab120ee537ad9021d78e358834 [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é Fonseca246508e2014-08-14 16:07:46 +0100542 if 'Indirect' in function.name:
543 print r' os::log("apitrace: warning: %s: indirect user arrays not supported\n");' % (function.name,)
544 else:
545 arg_names = ', '.join([arg.name for arg in function.args[1:]])
546 print ' GLuint _count = _%s_count(%s);' % (function.name, arg_names)
547 # Some apps, in particular Quake3, can tell the driver to lock more
548 # vertices than those actually required for the draw call.
549 print ' if (_checkLockArraysEXT) {'
550 print ' GLuint _locked_count = _glGetInteger(GL_ARRAY_ELEMENT_LOCK_FIRST_EXT)'
551 print ' + _glGetInteger(GL_ARRAY_ELEMENT_LOCK_COUNT_EXT);'
552 print ' _count = std::max(_count, _locked_count);'
553 print ' }'
554 print ' _trace_user_arrays(_count);'
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000555 print ' }'
José Fonseca707630d2014-03-07 14:20:35 +0000556 if function.name == 'glLockArraysEXT':
557 print ' _checkLockArraysEXT = true;'
José Fonseca4a7d8602014-06-18 16:03:44 +0100558
559 # Warn if user arrays are used with glBegin/glArrayElement/glEnd.
560 if function.name == 'glBegin':
561 print r' if (_need_user_arrays()) {'
562 print r' os::log("apitrace: warning: user arrays with glArrayElement not supported (https://github.com/apitrace/apitrace/issues/276)\n");'
563 print r' }'
José Fonseca14c21bc2011-02-20 23:32:22 +0000564
José Fonseca73373602011-05-20 17:45:26 +0100565 # Emit a fake memcpy on buffer uploads
José Fonseca9c536b02012-02-29 20:54:13 +0000566 if function.name == 'glBufferParameteriAPPLE':
567 print ' if (pname == GL_BUFFER_FLUSHING_UNMAP_APPLE && param == GL_FALSE) {'
José Fonseca632a78d2012-04-19 07:18:59 +0100568 print ' _checkBufferFlushingUnmapAPPLE = true;'
José Fonseca9c536b02012-02-29 20:54:13 +0000569 print ' }'
José Fonsecacdc322c2012-02-29 19:29:51 +0000570 if function.name in ('glUnmapBuffer', 'glUnmapBufferARB'):
José Fonseca9c536b02012-02-29 20:54:13 +0000571 if function.name.endswith('ARB'):
572 suffix = 'ARB'
573 else:
574 suffix = ''
575 print ' GLint access = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100576 print ' _glGetBufferParameteriv%s(target, GL_BUFFER_ACCESS, &access);' % suffix
José Fonseca9c536b02012-02-29 20:54:13 +0000577 print ' if (access != GL_READ_ONLY) {'
578 print ' GLvoid *map = NULL;'
José Fonseca632a78d2012-04-19 07:18:59 +0100579 print ' _glGetBufferPointerv%s(target, GL_BUFFER_MAP_POINTER, &map);' % suffix
José Fonseca9c536b02012-02-29 20:54:13 +0000580 print ' if (map) {'
581 print ' GLint length = -1;'
582 print ' bool flush = true;'
José Fonseca632a78d2012-04-19 07:18:59 +0100583 print ' if (_checkBufferMapRange) {'
584 print ' _glGetBufferParameteriv%s(target, GL_BUFFER_MAP_LENGTH, &length);' % suffix
José Fonseca9c536b02012-02-29 20:54:13 +0000585 print ' GLint access_flags = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100586 print ' _glGetBufferParameteriv(target, GL_BUFFER_ACCESS_FLAGS, &access_flags);'
José Fonseca9c536b02012-02-29 20:54:13 +0000587 print ' flush = flush && !(access_flags & GL_MAP_FLUSH_EXPLICIT_BIT);'
588 print ' if (length == -1) {'
José Fonsecacb07e2d2014-02-04 15:14:09 +0000589 print ' // Mesa drivers refuse GL_BUFFER_MAP_LENGTH without GL 3.0 up-to'
590 print ' // http://cgit.freedesktop.org/mesa/mesa/commit/?id=ffee498fb848b253a7833373fe5430f8c7ca0c5f'
José Fonsecadb1ccce2012-02-29 21:09:24 +0000591 print ' static bool warned = false;'
592 print ' if (!warned) {'
593 print ' os::log("apitrace: warning: glGetBufferParameteriv%s(GL_BUFFER_MAP_LENGTH) failed\\n");' % suffix
594 print ' warned = true;'
595 print ' }'
José Fonseca9c536b02012-02-29 20:54:13 +0000596 print ' struct buffer_mapping *mapping = get_buffer_mapping(target);'
597 print ' if (mapping) {'
598 print ' length = mapping->length;'
599 print ' flush = flush && !mapping->explicit_flush;'
600 print ' } else {'
601 print ' length = 0;'
602 print ' flush = false;'
603 print ' }'
604 print ' }'
605 print ' } else {'
606 print ' length = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100607 print ' _glGetBufferParameteriv%s(target, GL_BUFFER_SIZE, &length);' % suffix
José Fonseca9c536b02012-02-29 20:54:13 +0000608 print ' }'
José Fonseca632a78d2012-04-19 07:18:59 +0100609 print ' if (_checkBufferFlushingUnmapAPPLE) {'
José Fonseca9c536b02012-02-29 20:54:13 +0000610 print ' GLint flushing_unmap = GL_TRUE;'
José Fonseca632a78d2012-04-19 07:18:59 +0100611 print ' _glGetBufferParameteriv%s(target, GL_BUFFER_FLUSHING_UNMAP_APPLE, &flushing_unmap);' % suffix
José Fonseca9c536b02012-02-29 20:54:13 +0000612 print ' flush = flush && flushing_unmap;'
613 print ' }'
614 print ' if (flush && length > 0) {'
José Fonseca6f0e3032014-06-25 01:00:35 +0100615 self.emit_memcpy('map', 'length')
José Fonseca9c536b02012-02-29 20:54:13 +0000616 print ' }'
617 print ' }'
618 print ' }'
José Fonsecacdc322c2012-02-29 19:29:51 +0000619 if function.name == 'glUnmapBufferOES':
620 print ' GLint access = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100621 print ' _glGetBufferParameteriv(target, GL_BUFFER_ACCESS_OES, &access);'
José Fonsecacdc322c2012-02-29 19:29:51 +0000622 print ' if (access == GL_WRITE_ONLY_OES) {'
623 print ' GLvoid *map = NULL;'
José Fonseca632a78d2012-04-19 07:18:59 +0100624 print ' _glGetBufferPointervOES(target, GL_BUFFER_MAP_POINTER_OES, &map);'
José Fonsecacdc322c2012-02-29 19:29:51 +0000625 print ' GLint size = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100626 print ' _glGetBufferParameteriv(target, GL_BUFFER_SIZE, &size);'
José Fonsecacdc322c2012-02-29 19:29:51 +0000627 print ' if (map && size > 0) {'
José Fonseca6f0e3032014-06-25 01:00:35 +0100628 self.emit_memcpy('map', 'size')
José Fonseca219c9f22012-11-03 10:13:17 +0000629 self.shadowBufferMethod('bufferSubData(0, size, map)')
José Fonsecacdc322c2012-02-29 19:29:51 +0000630 print ' }'
José Fonseca867b1b72011-04-24 11:58:04 +0100631 print ' }'
José Fonseca4920c302014-08-13 18:35:57 +0100632 if function.name == 'glUnmapNamedBuffer':
633 print ' GLint access_flags = 0;'
634 print ' _glGetNamedBufferParameteriv(buffer, GL_BUFFER_ACCESS_FLAGS, &access_flags);'
635 print ' if ((access_flags & GL_MAP_WRITE_BIT) && !(access_flags & GL_MAP_FLUSH_EXPLICIT_BIT)) {'
636 print ' GLvoid *map = NULL;'
637 print ' _glGetNamedBufferPointerv(buffer, GL_BUFFER_MAP_POINTER, &map);'
638 print ' GLint length = 0;'
639 print ' _glGetNamedBufferParameteriv(buffer, GL_BUFFER_MAP_LENGTH, &length);'
640 print ' if (map && length > 0) {'
641 self.emit_memcpy('map', 'length')
642 print ' }'
643 print ' }'
José Fonsecafb3bd602012-01-15 13:56:28 +0000644 if function.name == 'glUnmapNamedBufferEXT':
José Fonseca024aff42012-02-29 18:00:06 +0000645 print ' GLint access_flags = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100646 print ' _glGetNamedBufferParameterivEXT(buffer, GL_BUFFER_ACCESS_FLAGS, &access_flags);'
José Fonseca024aff42012-02-29 18:00:06 +0000647 print ' if ((access_flags & GL_MAP_WRITE_BIT) && !(access_flags & GL_MAP_FLUSH_EXPLICIT_BIT)) {'
José Fonsecafb3bd602012-01-15 13:56:28 +0000648 print ' GLvoid *map = NULL;'
José Fonseca632a78d2012-04-19 07:18:59 +0100649 print ' _glGetNamedBufferPointervEXT(buffer, GL_BUFFER_MAP_POINTER, &map);'
José Fonsecafb3bd602012-01-15 13:56:28 +0000650 print ' GLint length = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100651 print ' _glGetNamedBufferParameterivEXT(buffer, GL_BUFFER_MAP_LENGTH, &length);'
José Fonseca024aff42012-02-29 18:00:06 +0000652 print ' if (map && length > 0) {'
José Fonseca6f0e3032014-06-25 01:00:35 +0100653 self.emit_memcpy('map', 'length')
José Fonseca024aff42012-02-29 18:00:06 +0000654 print ' }'
José Fonsecafb3bd602012-01-15 13:56:28 +0000655 print ' }'
José Fonseca77ef0ce2012-02-29 18:08:48 +0000656 if function.name == 'glFlushMappedBufferRange':
657 print ' GLvoid *map = NULL;'
José Fonseca632a78d2012-04-19 07:18:59 +0100658 print ' _glGetBufferPointerv(target, GL_BUFFER_MAP_POINTER, &map);'
José Fonseca77ef0ce2012-02-29 18:08:48 +0000659 print ' if (map && length > 0) {'
José Fonseca6f0e3032014-06-25 01:00:35 +0100660 self.emit_memcpy('(const char *)map + offset', 'length')
José Fonseca77ef0ce2012-02-29 18:08:48 +0000661 print ' }'
662 if function.name == 'glFlushMappedBufferRangeAPPLE':
663 print ' GLvoid *map = NULL;'
José Fonseca632a78d2012-04-19 07:18:59 +0100664 print ' _glGetBufferPointerv(target, GL_BUFFER_MAP_POINTER, &map);'
José Fonseca77ef0ce2012-02-29 18:08:48 +0000665 print ' if (map && size > 0) {'
José Fonseca6f0e3032014-06-25 01:00:35 +0100666 self.emit_memcpy('(const char *)map + offset', 'size')
José Fonseca73373602011-05-20 17:45:26 +0100667 print ' }'
José Fonseca4920c302014-08-13 18:35:57 +0100668 if function.name == 'glFlushMappedNamedBufferRange':
669 print ' GLvoid *map = NULL;'
670 print ' _glGetNamedBufferPointerv(buffer, GL_BUFFER_MAP_POINTER, &map);'
671 print ' if (map && length > 0) {'
672 self.emit_memcpy('(const char *)map + offset', 'length')
673 print ' }'
José Fonsecafb3bd602012-01-15 13:56:28 +0000674 if function.name == 'glFlushMappedNamedBufferRangeEXT':
675 print ' GLvoid *map = NULL;'
José Fonseca632a78d2012-04-19 07:18:59 +0100676 print ' _glGetNamedBufferPointervEXT(buffer, GL_BUFFER_MAP_POINTER, &map);'
José Fonseca024aff42012-02-29 18:00:06 +0000677 print ' if (map && length > 0) {'
José Fonseca6f0e3032014-06-25 01:00:35 +0100678 self.emit_memcpy('(const char *)map + offset', 'length')
José Fonsecafb3bd602012-01-15 13:56:28 +0000679 print ' }'
José Fonseca867b1b72011-04-24 11:58:04 +0100680
José Fonseca3522cbd2014-02-28 14:45:32 +0000681 # FIXME: We don't support coherent/pinned memory mappings
682 # See https://github.com/apitrace/apitrace/issues/232
José Fonseca4920c302014-08-13 18:35:57 +0100683 if function.name in ('glBufferStorage', 'glNamedBufferStorage', 'glNamedBufferStorageEXT'):
José Fonseca3522cbd2014-02-28 14:45:32 +0000684 print r' if (flags & GL_MAP_COHERENT_BIT) {'
685 print r' os::log("apitrace: warning: coherent mappings not fully supported\n");'
686 print r' }'
687 if function.name in ('glBufferData', 'glBufferDataARB'):
688 print r' if (target == GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD) {'
689 print r' os::log("apitrace: warning: GL_AMD_pinned_memory not fully supported\n");'
690 print r' }'
691
José Fonseca91492d22011-05-23 21:20:31 +0100692 # Don't leave vertex attrib locations to chance. Instead emit fake
693 # glBindAttribLocation calls to ensure that the same locations will be
694 # used when retracing. Trying to remap locations after the fact would
695 # be an herculian task given that vertex attrib locations appear in
696 # many entry-points, including non-shader related ones.
697 if function.name == 'glLinkProgram':
José Fonseca54f304a2012-01-14 19:33:08 +0000698 Tracer.invokeFunction(self, function)
José Fonseca91492d22011-05-23 21:20:31 +0100699 print ' GLint active_attributes = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100700 print ' _glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &active_attributes);'
José Fonseca7525e6f2011-09-28 09:04:56 +0100701 print ' for (GLint attrib = 0; attrib < active_attributes; ++attrib) {'
José Fonseca91492d22011-05-23 21:20:31 +0100702 print ' GLint size = 0;'
703 print ' GLenum type = 0;'
704 print ' GLchar name[256];'
705 # TODO: Use ACTIVE_ATTRIBUTE_MAX_LENGTH instead of 256
José Fonseca632a78d2012-04-19 07:18:59 +0100706 print ' _glGetActiveAttrib(program, attrib, sizeof name, NULL, &size, &type, name);'
José Fonseca2a794f52011-05-26 20:54:29 +0100707 print " if (name[0] != 'g' || name[1] != 'l' || name[2] != '_') {"
José Fonseca632a78d2012-04-19 07:18:59 +0100708 print ' GLint location = _glGetAttribLocation(program, name);'
José Fonseca2a794f52011-05-26 20:54:29 +0100709 print ' if (location >= 0) {'
José Fonseca1b6c8752012-04-15 14:33:00 +0100710 bind_function = glapi.glapi.getFunctionByName('glBindAttribLocation')
José Fonseca91492d22011-05-23 21:20:31 +0100711 self.fake_call(bind_function, ['program', 'location', 'name'])
José Fonseca2a794f52011-05-26 20:54:29 +0100712 print ' }'
José Fonseca91492d22011-05-23 21:20:31 +0100713 print ' }'
714 print ' }'
715 if function.name == 'glLinkProgramARB':
José Fonseca54f304a2012-01-14 19:33:08 +0000716 Tracer.invokeFunction(self, function)
José Fonseca91492d22011-05-23 21:20:31 +0100717 print ' GLint active_attributes = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100718 print ' _glGetObjectParameterivARB(programObj, GL_OBJECT_ACTIVE_ATTRIBUTES_ARB, &active_attributes);'
José Fonseca7525e6f2011-09-28 09:04:56 +0100719 print ' for (GLint attrib = 0; attrib < active_attributes; ++attrib) {'
José Fonseca91492d22011-05-23 21:20:31 +0100720 print ' GLint size = 0;'
721 print ' GLenum type = 0;'
722 print ' GLcharARB name[256];'
723 # TODO: Use ACTIVE_ATTRIBUTE_MAX_LENGTH instead of 256
José Fonseca632a78d2012-04-19 07:18:59 +0100724 print ' _glGetActiveAttribARB(programObj, attrib, sizeof name, NULL, &size, &type, name);'
José Fonseca2a794f52011-05-26 20:54:29 +0100725 print " if (name[0] != 'g' || name[1] != 'l' || name[2] != '_') {"
José Fonseca632a78d2012-04-19 07:18:59 +0100726 print ' GLint location = _glGetAttribLocationARB(programObj, name);'
José Fonseca2a794f52011-05-26 20:54:29 +0100727 print ' if (location >= 0) {'
José Fonseca1b6c8752012-04-15 14:33:00 +0100728 bind_function = glapi.glapi.getFunctionByName('glBindAttribLocationARB')
José Fonseca91492d22011-05-23 21:20:31 +0100729 self.fake_call(bind_function, ['programObj', 'location', 'name'])
José Fonseca2a794f52011-05-26 20:54:29 +0100730 print ' }'
José Fonseca91492d22011-05-23 21:20:31 +0100731 print ' }'
732 print ' }'
733
Imre Deakd4937372012-04-24 14:06:48 +0300734 self.shadowBufferProlog(function)
735
José Fonseca54f304a2012-01-14 19:33:08 +0000736 Tracer.traceFunctionImplBody(self, function)
José Fonseca73373602011-05-20 17:45:26 +0100737
Peter Lohrmann0b5b75e2013-06-03 14:58:41 -0700738 # These entrypoints are only expected to be implemented by tools;
739 # drivers will probably not implement them.
José Fonsecaf028a8f2012-02-15 23:33:35 +0000740 marker_functions = [
741 # GL_GREMEDY_string_marker
José Fonseca8f34d342011-07-15 20:16:40 +0100742 'glStringMarkerGREMEDY',
José Fonsecaf028a8f2012-02-15 23:33:35 +0000743 # GL_GREMEDY_frame_terminator
José Fonseca8f34d342011-07-15 20:16:40 +0100744 'glFrameTerminatorGREMEDY',
745 ]
746
Peter Lohrmann0b5b75e2013-06-03 14:58:41 -0700747 # These entrypoints may be implemented by drivers, but are also very useful
748 # for debugging / analysis tools.
749 debug_functions = [
750 # GL_KHR_debug
751 'glDebugMessageControl',
752 'glDebugMessageInsert',
753 'glDebugMessageCallback',
754 'glGetDebugMessageLog',
755 'glPushDebugGroup',
756 'glPopDebugGroup',
757 'glObjectLabel',
758 'glGetObjectLabel',
759 'glObjectPtrLabel',
760 'glGetObjectPtrLabel',
761 # GL_ARB_debug_output
762 'glDebugMessageControlARB',
763 'glDebugMessageInsertARB',
764 'glDebugMessageCallbackARB',
765 'glGetDebugMessageLogARB',
766 # GL_AMD_debug_output
767 'glDebugMessageEnableAMD',
768 'glDebugMessageInsertAMD',
769 'glDebugMessageCallbackAMD',
770 'glGetDebugMessageLogAMD',
José Fonseca71f5a352014-07-28 12:19:50 +0100771 # GL_EXT_debug_label
772 'glLabelObjectEXT',
773 'glGetObjectLabelEXT',
774 # GL_EXT_debug_marker
775 'glInsertEventMarkerEXT',
776 'glPushGroupMarkerEXT',
777 'glPopGroupMarkerEXT',
Peter Lohrmann0b5b75e2013-06-03 14:58:41 -0700778 ]
779
José Fonseca54f304a2012-01-14 19:33:08 +0000780 def invokeFunction(self, function):
José Fonseca91492d22011-05-23 21:20:31 +0100781 if function.name in ('glLinkProgram', 'glLinkProgramARB'):
782 # These functions have been dispatched already
783 return
784
José Fonseca2cfa02c2013-06-10 08:05:29 +0100785 Tracer.invokeFunction(self, function)
786
787 def doInvokeFunction(self, function):
788 # Same as invokeFunction() but called both when trace is enabled or disabled.
789 #
790 # Used to modify the behavior of GL entry-points.
791
792 # Override GL extensions
793 if function.name in ('glGetString', 'glGetIntegerv', 'glGetStringi'):
794 Tracer.doInvokeFunction(self, function, prefix = 'gltrace::_', suffix = '_override')
795 return
796
José Fonseca71f5a352014-07-28 12:19:50 +0100797 # We implement GL_GREMEDY_*, etc., and not the driver
José Fonsecaf028a8f2012-02-15 23:33:35 +0000798 if function.name in self.marker_functions:
José Fonseca8f34d342011-07-15 20:16:40 +0100799 return
800
Peter Lohrmann9d9eb812013-07-12 16:15:25 -0400801 # We may be faking KHR_debug, so ensure the pointer queries result is
802 # always zeroed to prevent dereference of unitialized pointers
803 if function.name == 'glGetPointerv':
804 print ' if (params &&'
805 print ' (pname == GL_DEBUG_CALLBACK_FUNCTION ||'
806 print ' pname == GL_DEBUG_CALLBACK_USER_PARAM)) {'
807 print ' *params = NULL;'
808 print ' }'
809
José Fonseca2cfa02c2013-06-10 08:05:29 +0100810 if function.name in self.getProcAddressFunctionNames:
José Fonsecaf028a8f2012-02-15 23:33:35 +0000811 else_ = ''
812 for marker_function in self.marker_functions:
José Fonseca1b6c8752012-04-15 14:33:00 +0100813 if self.api.getFunctionByName(marker_function):
José Fonsecaf028a8f2012-02-15 23:33:35 +0000814 print ' %sif (strcmp("%s", (const char *)%s) == 0) {' % (else_, marker_function, function.args[0].name)
José Fonseca632a78d2012-04-19 07:18:59 +0100815 print ' _result = (%s)&%s;' % (function.type, marker_function)
José Fonsecaf028a8f2012-02-15 23:33:35 +0000816 print ' }'
817 else_ = 'else '
818 print ' %s{' % else_
José Fonseca2cfa02c2013-06-10 08:05:29 +0100819 Tracer.doInvokeFunction(self, function)
820
821 # Replace function addresses with ours
822 # XXX: Doing this here instead of wrapRet means that the trace will
823 # contain the addresses of the wrapper functions, and not the real
824 # functions, but in practice this should make no difference.
825 if function.name in self.getProcAddressFunctionNames:
826 print ' _result = _wrapProcAddress(%s, _result);' % (function.args[0].name,)
827
José Fonseca8f34d342011-07-15 20:16:40 +0100828 print ' }'
José Fonseca1b3d3752011-07-15 10:15:19 +0100829 return
830
José Fonseca2cfa02c2013-06-10 08:05:29 +0100831 Tracer.doInvokeFunction(self, function)
José Fonseca91492d22011-05-23 21:20:31 +0100832
José Fonseca867b1b72011-04-24 11:58:04 +0100833 buffer_targets = [
834 'ARRAY_BUFFER',
835 'ELEMENT_ARRAY_BUFFER',
836 'PIXEL_PACK_BUFFER',
837 'PIXEL_UNPACK_BUFFER',
José Fonseca7b20d672012-01-10 19:13:58 +0000838 'UNIFORM_BUFFER',
839 'TEXTURE_BUFFER',
840 'TRANSFORM_FEEDBACK_BUFFER',
841 'COPY_READ_BUFFER',
842 'COPY_WRITE_BUFFER',
843 'DRAW_INDIRECT_BUFFER',
844 'ATOMIC_COUNTER_BUFFER',
José Fonseca867b1b72011-04-24 11:58:04 +0100845 ]
846
José Fonseca54f304a2012-01-14 19:33:08 +0000847 def wrapRet(self, function, instance):
848 Tracer.wrapRet(self, function, instance)
José Fonseca1b3d3752011-07-15 10:15:19 +0100849
José Fonsecacdc322c2012-02-29 19:29:51 +0000850 # Keep track of buffer mappings
851 if function.name in ('glMapBuffer', 'glMapBufferARB'):
José Fonseca867b1b72011-04-24 11:58:04 +0100852 print ' struct buffer_mapping *mapping = get_buffer_mapping(target);'
853 print ' if (mapping) {'
854 print ' mapping->map = %s;' % (instance)
855 print ' mapping->length = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100856 print ' _glGetBufferParameteriv(target, GL_BUFFER_SIZE, &mapping->length);'
José Fonseca867b1b72011-04-24 11:58:04 +0100857 print ' mapping->write = (access != GL_READ_ONLY);'
José Fonseca73373602011-05-20 17:45:26 +0100858 print ' mapping->explicit_flush = false;'
José Fonseca867b1b72011-04-24 11:58:04 +0100859 print ' }'
José Fonseca867b1b72011-04-24 11:58:04 +0100860 if function.name == 'glMapBufferRange':
José Fonseca9c536b02012-02-29 20:54:13 +0000861 print ' if (access & GL_MAP_WRITE_BIT) {'
José Fonseca632a78d2012-04-19 07:18:59 +0100862 print ' _checkBufferMapRange = true;'
José Fonseca9c536b02012-02-29 20:54:13 +0000863 print ' }'
José Fonseca867b1b72011-04-24 11:58:04 +0100864 print ' struct buffer_mapping *mapping = get_buffer_mapping(target);'
865 print ' if (mapping) {'
866 print ' mapping->map = %s;' % (instance)
867 print ' mapping->length = length;'
868 print ' mapping->write = access & GL_MAP_WRITE_BIT;'
José Fonseca73373602011-05-20 17:45:26 +0100869 print ' mapping->explicit_flush = access & GL_MAP_FLUSH_EXPLICIT_BIT;'
José Fonseca867b1b72011-04-24 11:58:04 +0100870 print ' }'
José Fonseca669b1222011-02-20 09:05:10 +0000871
José Fonsecac9f12232011-03-25 20:07:42 +0000872 boolean_names = [
873 'GL_FALSE',
874 'GL_TRUE',
875 ]
876
877 def gl_boolean(self, value):
878 return self.boolean_names[int(bool(value))]
879
José Fonsecac29f4f12011-06-11 12:19:05 +0100880 # Names of the functions that unpack from a pixel buffer object. See the
881 # ARB_pixel_buffer_object specification.
José Fonsecae97bab92011-06-02 23:15:11 +0100882 unpack_function_names = set([
883 'glBitmap',
José Fonsecac29f4f12011-06-11 12:19:05 +0100884 'glColorSubTable',
885 'glColorTable',
José Fonsecad2bd4ca2013-04-12 11:41:00 +0100886 'glCompressedMultiTexImage1DEXT',
887 'glCompressedMultiTexImage2DEXT',
888 'glCompressedMultiTexImage3DEXT',
889 'glCompressedMultiTexSubImage1DEXT',
890 'glCompressedMultiTexSubImage2DEXT',
891 'glCompressedMultiTexSubImage3DEXT',
José Fonsecac29f4f12011-06-11 12:19:05 +0100892 'glCompressedTexImage1D',
idinevdb5ad3b2014-02-03 15:50:39 +0000893 'glCompressedTexImage1DARB',
José Fonsecac29f4f12011-06-11 12:19:05 +0100894 'glCompressedTexImage2D',
idinevdb5ad3b2014-02-03 15:50:39 +0000895 'glCompressedTexImage2DARB',
José Fonsecac29f4f12011-06-11 12:19:05 +0100896 'glCompressedTexImage3D',
idinevdb5ad3b2014-02-03 15:50:39 +0000897 'glCompressedTexImage3DARB',
José Fonsecac29f4f12011-06-11 12:19:05 +0100898 'glCompressedTexSubImage1D',
idinevdb5ad3b2014-02-03 15:50:39 +0000899 'glCompressedTexSubImage1DARB',
José Fonsecac29f4f12011-06-11 12:19:05 +0100900 'glCompressedTexSubImage2D',
idinevdb5ad3b2014-02-03 15:50:39 +0000901 'glCompressedTexSubImage2DARB',
José Fonsecac29f4f12011-06-11 12:19:05 +0100902 'glCompressedTexSubImage3D',
idinevdb5ad3b2014-02-03 15:50:39 +0000903 'glCompressedTexSubImage3DARB',
José Fonseca4920c302014-08-13 18:35:57 +0100904 'glCompressedTextureImage1D',
José Fonsecad2bd4ca2013-04-12 11:41:00 +0100905 'glCompressedTextureImage1DEXT',
José Fonseca4920c302014-08-13 18:35:57 +0100906 'glCompressedTextureImage2D',
José Fonsecad2bd4ca2013-04-12 11:41:00 +0100907 'glCompressedTextureImage2DEXT',
José Fonseca4920c302014-08-13 18:35:57 +0100908 'glCompressedTextureImage3D',
José Fonsecad2bd4ca2013-04-12 11:41:00 +0100909 'glCompressedTextureImage3DEXT',
José Fonseca4920c302014-08-13 18:35:57 +0100910 'glCompressedTextureSubImage1D',
José Fonsecad2bd4ca2013-04-12 11:41:00 +0100911 'glCompressedTextureSubImage1DEXT',
José Fonseca4920c302014-08-13 18:35:57 +0100912 'glCompressedTextureSubImage2D',
José Fonsecad2bd4ca2013-04-12 11:41:00 +0100913 'glCompressedTextureSubImage2DEXT',
José Fonseca4920c302014-08-13 18:35:57 +0100914 'glCompressedTextureSubImage3D',
José Fonsecad2bd4ca2013-04-12 11:41:00 +0100915 'glCompressedTextureSubImage3DEXT',
José Fonsecac29f4f12011-06-11 12:19:05 +0100916 'glConvolutionFilter1D',
917 'glConvolutionFilter2D',
José Fonsecae97bab92011-06-02 23:15:11 +0100918 'glDrawPixels',
919 'glMultiTexImage1DEXT',
920 'glMultiTexImage2DEXT',
921 'glMultiTexImage3DEXT',
922 'glMultiTexSubImage1DEXT',
923 'glMultiTexSubImage2DEXT',
924 'glMultiTexSubImage3DEXT',
José Fonsecac29f4f12011-06-11 12:19:05 +0100925 'glPixelMapfv',
926 'glPixelMapuiv',
927 'glPixelMapusv',
José Fonsecae97bab92011-06-02 23:15:11 +0100928 'glPolygonStipple',
José Fonsecac29f4f12011-06-11 12:19:05 +0100929 'glSeparableFilter2D',
José Fonsecae97bab92011-06-02 23:15:11 +0100930 'glTexImage1D',
931 'glTexImage1DEXT',
932 'glTexImage2D',
933 'glTexImage2DEXT',
934 'glTexImage3D',
935 'glTexImage3DEXT',
936 'glTexSubImage1D',
937 'glTexSubImage1DEXT',
938 'glTexSubImage2D',
939 'glTexSubImage2DEXT',
940 'glTexSubImage3D',
941 'glTexSubImage3DEXT',
942 'glTextureImage1DEXT',
943 'glTextureImage2DEXT',
944 'glTextureImage3DEXT',
945 'glTextureSubImage1DEXT',
946 'glTextureSubImage2DEXT',
947 'glTextureSubImage3DEXT',
948 ])
949
José Fonseca54f304a2012-01-14 19:33:08 +0000950 def serializeArgValue(self, function, arg):
José Fonsecae97bab92011-06-02 23:15:11 +0100951 # Recognize offsets instead of blobs when a PBO is bound
952 if function.name in self.unpack_function_names \
953 and (isinstance(arg.type, stdapi.Blob) \
954 or (isinstance(arg.type, stdapi.Const) \
955 and isinstance(arg.type.type, stdapi.Blob))):
José Fonsecac29f4f12011-06-11 12:19:05 +0100956 print ' {'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000957 print ' gltrace::Context *ctx = gltrace::getContext();'
José Fonseca632a78d2012-04-19 07:18:59 +0100958 print ' GLint _unpack_buffer = 0;'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000959 print ' if (ctx->profile == gltrace::PROFILE_COMPAT)'
José Fonseca632a78d2012-04-19 07:18:59 +0100960 print ' _glGetIntegerv(GL_PIXEL_UNPACK_BUFFER_BINDING, &_unpack_buffer);'
961 print ' if (_unpack_buffer) {'
José Fonsecad559f022012-04-15 16:13:51 +0100962 print ' trace::localWriter.writePointer((uintptr_t)%s);' % arg.name
José Fonsecac29f4f12011-06-11 12:19:05 +0100963 print ' } else {'
José Fonseca54f304a2012-01-14 19:33:08 +0000964 Tracer.serializeArgValue(self, function, arg)
José Fonsecac29f4f12011-06-11 12:19:05 +0100965 print ' }'
José Fonsecae97bab92011-06-02 23:15:11 +0100966 print ' }'
967 return
968
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100969 # Several GL state functions take GLenum symbolic names as
970 # integer/floats; so dump the symbolic name whenever possible
José Fonseca3bcb33c2011-05-27 20:14:31 +0100971 if function.name.startswith('gl') \
José Fonsecae3571092011-10-13 08:26:27 +0100972 and arg.type in (glapi.GLint, glapi.GLfloat, glapi.GLdouble) \
José Fonseca3bcb33c2011-05-27 20:14:31 +0100973 and arg.name == 'param':
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100974 assert arg.index > 0
975 assert function.args[arg.index - 1].name == 'pname'
976 assert function.args[arg.index - 1].type == glapi.GLenum
977 print ' if (is_symbolic_pname(pname) && is_symbolic_param(%s)) {' % arg.name
José Fonseca54f304a2012-01-14 19:33:08 +0000978 self.serializeValue(glapi.GLenum, arg.name)
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100979 print ' } else {'
José Fonseca54f304a2012-01-14 19:33:08 +0000980 Tracer.serializeArgValue(self, function, arg)
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100981 print ' }'
982 return
983
José Fonseca54f304a2012-01-14 19:33:08 +0000984 Tracer.serializeArgValue(self, function, arg)
José Fonseca99221832011-03-22 22:15:46 +0000985
José Fonseca4c938c22011-04-30 22:44:38 +0100986 def footer(self, api):
987 Tracer.footer(self, api)
José Fonseca669b1222011-02-20 09:05:10 +0000988
José Fonseca4c938c22011-04-30 22:44:38 +0100989 # A simple state tracker to track the pointer values
José Fonseca669b1222011-02-20 09:05:10 +0000990 # update the state
José Fonseca14cb9ef2012-05-17 21:33:14 +0100991 print 'static void _trace_user_arrays(GLuint count)'
José Fonseca669b1222011-02-20 09:05:10 +0000992 print '{'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000993 print ' gltrace::Context *ctx = gltrace::getContext();'
José Fonseca8d1408b2014-02-03 19:57:18 +0000994 print
995
996 # Temporarily unbind the array buffer
José Fonseca26be8f92014-03-07 14:08:50 +0000997 print ' GLint _array_buffer = _glGetInteger(GL_ARRAY_BUFFER_BINDING);'
José Fonseca8d1408b2014-02-03 19:57:18 +0000998 print ' if (_array_buffer) {'
999 self.fake_glBindBuffer(api, 'GL_ARRAY_BUFFER', '0')
1000 print ' }'
1001 print
José Fonseca1a2fdd22011-04-01 00:55:09 +01001002
José Fonseca99221832011-03-22 22:15:46 +00001003 for camelcase_name, uppercase_name in self.arrays:
Chia-I Wub3d218d2011-11-03 01:37:36 +08001004 # in which profile is the array available?
José Fonsecaf028a8f2012-02-15 23:33:35 +00001005 profile_check = 'ctx->profile == gltrace::PROFILE_COMPAT'
Chia-I Wub3d218d2011-11-03 01:37:36 +08001006 if camelcase_name in self.arrays_es1:
José Fonsecaf028a8f2012-02-15 23:33:35 +00001007 profile_check = '(' + profile_check + ' || ctx->profile == gltrace::PROFILE_ES1)';
Chia-I Wub3d218d2011-11-03 01:37:36 +08001008
José Fonseca99221832011-03-22 22:15:46 +00001009 function_name = 'gl%sPointer' % camelcase_name
1010 enable_name = 'GL_%s_ARRAY' % uppercase_name
1011 binding_name = 'GL_%s_ARRAY_BUFFER_BINDING' % uppercase_name
José Fonseca1b6c8752012-04-15 14:33:00 +01001012 function = api.getFunctionByName(function_name)
José Fonseca99221832011-03-22 22:15:46 +00001013
José Fonseca06e85192011-10-16 14:15:36 +01001014 print ' // %s' % function.prototype()
Chia-I Wub3d218d2011-11-03 01:37:36 +08001015 print ' if (%s) {' % profile_check
José Fonsecafb6744f2011-04-15 11:18:37 +01001016 self.array_trace_prolog(api, uppercase_name)
1017 self.array_prolog(api, uppercase_name)
José Fonseca632a78d2012-04-19 07:18:59 +01001018 print ' if (_glIsEnabled(%s)) {' % enable_name
José Fonseca26be8f92014-03-07 14:08:50 +00001019 print ' GLint _binding = _glGetInteger(%s);' % binding_name
José Fonseca632a78d2012-04-19 07:18:59 +01001020 print ' if (!_binding) {'
José Fonseca99221832011-03-22 22:15:46 +00001021
1022 # Get the arguments via glGet*
1023 for arg in function.args:
1024 arg_get_enum = 'GL_%s_ARRAY_%s' % (uppercase_name, arg.name.upper())
1025 arg_get_function, arg_type = TypeGetter().visit(arg.type)
José Fonseca7f5163e2011-03-31 23:37:26 +01001026 print ' %s %s = 0;' % (arg_type, arg.name)
José Fonseca632a78d2012-04-19 07:18:59 +01001027 print ' _%s(%s, &%s);' % (arg_get_function, arg_get_enum, arg.name)
José Fonseca99221832011-03-22 22:15:46 +00001028
1029 arg_names = ', '.join([arg.name for arg in function.args[:-1]])
José Fonseca14cb9ef2012-05-17 21:33:14 +01001030 print ' size_t _size = _%s_size(%s, count);' % (function.name, arg_names)
José Fonseca99221832011-03-22 22:15:46 +00001031
1032 # Emit a fake function
José Fonsecafb6744f2011-04-15 11:18:37 +01001033 self.array_trace_intermezzo(api, uppercase_name)
José Fonseca7a5f23a2014-06-24 19:20:36 +01001034 print ' unsigned _call = trace::localWriter.beginEnter(&_%s_sig, true);' % (function.name,)
José Fonseca669b1222011-02-20 09:05:10 +00001035 for arg in function.args:
1036 assert not arg.output
José Fonsecab4a3d142011-10-27 07:43:19 +01001037 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
José Fonseca14c21bc2011-02-20 23:32:22 +00001038 if arg.name != 'pointer':
José Fonseca54f304a2012-01-14 19:33:08 +00001039 self.serializeValue(arg.type, arg.name)
José Fonseca14c21bc2011-02-20 23:32:22 +00001040 else:
José Fonseca632a78d2012-04-19 07:18:59 +01001041 print ' trace::localWriter.writeBlob((const void *)%s, _size);' % (arg.name)
José Fonsecab4a3d142011-10-27 07:43:19 +01001042 print ' trace::localWriter.endArg();'
José Fonseca99221832011-03-22 22:15:46 +00001043
José Fonsecab4a3d142011-10-27 07:43:19 +01001044 print ' trace::localWriter.endEnter();'
José Fonseca632a78d2012-04-19 07:18:59 +01001045 print ' trace::localWriter.beginLeave(_call);'
José Fonsecab4a3d142011-10-27 07:43:19 +01001046 print ' trace::localWriter.endLeave();'
José Fonseca99221832011-03-22 22:15:46 +00001047 print ' }'
José Fonseca669b1222011-02-20 09:05:10 +00001048 print ' }'
José Fonsecafb6744f2011-04-15 11:18:37 +01001049 self.array_epilog(api, uppercase_name)
1050 self.array_trace_epilog(api, uppercase_name)
Chia-I Wub3d218d2011-11-03 01:37:36 +08001051 print ' }'
José Fonseca99221832011-03-22 22:15:46 +00001052 print
José Fonseca1a2fdd22011-04-01 00:55:09 +01001053
José Fonseca1601c412011-05-10 10:38:19 +01001054 # Samething, but for glVertexAttribPointer*
1055 #
1056 # Some variants of glVertexAttribPointer alias conventional and generic attributes:
1057 # - glVertexAttribPointer: no
1058 # - glVertexAttribPointerARB: implementation dependent
1059 # - glVertexAttribPointerNV: yes
1060 #
1061 # This means that the implementations of these functions do not always
1062 # alias, and they need to be considered independently.
1063 #
Chia-I Wub3d218d2011-11-03 01:37:36 +08001064 print ' // ES1 does not support generic vertex attributes'
José Fonsecaf028a8f2012-02-15 23:33:35 +00001065 print ' if (ctx->profile == gltrace::PROFILE_ES1)'
Chia-I Wub3d218d2011-11-03 01:37:36 +08001066 print ' return;'
1067 print
José Fonseca632a78d2012-04-19 07:18:59 +01001068 print ' vertex_attrib _vertex_attrib = _get_vertex_attrib();'
José Fonseca5a568a92011-06-29 16:43:36 +01001069 print
José Fonseca74b661a2014-07-17 19:10:24 +01001070 for suffix in ['', 'NV']:
José Fonseca5a568a92011-06-29 16:43:36 +01001071 if suffix:
José Fonsecad94aaac2011-06-28 20:50:49 +01001072 SUFFIX = '_' + suffix
José Fonsecad94aaac2011-06-28 20:50:49 +01001073 else:
José Fonseca5a568a92011-06-29 16:43:36 +01001074 SUFFIX = suffix
José Fonseca1601c412011-05-10 10:38:19 +01001075 function_name = 'glVertexAttribPointer' + suffix
José Fonseca1b6c8752012-04-15 14:33:00 +01001076 function = api.getFunctionByName(function_name)
José Fonseca06e85192011-10-16 14:15:36 +01001077
1078 print ' // %s' % function.prototype()
José Fonseca632a78d2012-04-19 07:18:59 +01001079 print ' if (_vertex_attrib == VERTEX_ATTRIB%s) {' % SUFFIX
José Fonseca5a568a92011-06-29 16:43:36 +01001080 if suffix == 'NV':
José Fonseca632a78d2012-04-19 07:18:59 +01001081 print ' GLint _max_vertex_attribs = 16;'
José Fonseca5a568a92011-06-29 16:43:36 +01001082 else:
José Fonseca26be8f92014-03-07 14:08:50 +00001083 print ' GLint _max_vertex_attribs = _glGetInteger(GL_MAX_VERTEX_ATTRIBS);'
José Fonseca632a78d2012-04-19 07:18:59 +01001084 print ' for (GLint index = 0; index < _max_vertex_attribs; ++index) {'
1085 print ' GLint _enabled = 0;'
José Fonseca5a568a92011-06-29 16:43:36 +01001086 if suffix == 'NV':
José Fonseca632a78d2012-04-19 07:18:59 +01001087 print ' _glGetIntegerv(GL_VERTEX_ATTRIB_ARRAY0_NV + index, &_enabled);'
José Fonseca5a568a92011-06-29 16:43:36 +01001088 else:
José Fonseca632a78d2012-04-19 07:18:59 +01001089 print ' _glGetVertexAttribiv%s(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED%s, &_enabled);' % (suffix, SUFFIX)
1090 print ' if (_enabled) {'
1091 print ' GLint _binding = 0;'
José Fonseca5a568a92011-06-29 16:43:36 +01001092 if suffix != 'NV':
1093 # It doesn't seem possible to use VBOs with NV_vertex_program.
José Fonseca632a78d2012-04-19 07:18:59 +01001094 print ' _glGetVertexAttribiv%s(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING%s, &_binding);' % (suffix, SUFFIX)
1095 print ' if (!_binding) {'
José Fonseca1a2fdd22011-04-01 00:55:09 +01001096
José Fonseca1601c412011-05-10 10:38:19 +01001097 # Get the arguments via glGet*
1098 for arg in function.args[1:]:
José Fonseca5a568a92011-06-29 16:43:36 +01001099 if suffix == 'NV':
1100 arg_get_enum = 'GL_ATTRIB_ARRAY_%s%s' % (arg.name.upper(), SUFFIX)
1101 else:
1102 arg_get_enum = 'GL_VERTEX_ATTRIB_ARRAY_%s%s' % (arg.name.upper(), SUFFIX)
José Fonsecac493e3e2011-06-29 12:57:06 +01001103 arg_get_function, arg_type = TypeGetter('glGetVertexAttrib', False, suffix).visit(arg.type)
José Fonseca5a568a92011-06-29 16:43:36 +01001104 print ' %s %s = 0;' % (arg_type, arg.name)
José Fonseca632a78d2012-04-19 07:18:59 +01001105 print ' _%s(index, %s, &%s);' % (arg_get_function, arg_get_enum, arg.name)
José Fonseca1601c412011-05-10 10:38:19 +01001106
1107 arg_names = ', '.join([arg.name for arg in function.args[1:-1]])
José Fonseca14cb9ef2012-05-17 21:33:14 +01001108 print ' size_t _size = _%s_size(%s, count);' % (function.name, arg_names)
José Fonseca1a2fdd22011-04-01 00:55:09 +01001109
José Fonseca1601c412011-05-10 10:38:19 +01001110 # Emit a fake function
José Fonseca7a5f23a2014-06-24 19:20:36 +01001111 print ' unsigned _call = trace::localWriter.beginEnter(&_%s_sig, true);' % (function.name,)
José Fonseca1601c412011-05-10 10:38:19 +01001112 for arg in function.args:
1113 assert not arg.output
José Fonsecab4a3d142011-10-27 07:43:19 +01001114 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
José Fonseca1601c412011-05-10 10:38:19 +01001115 if arg.name != 'pointer':
José Fonseca54f304a2012-01-14 19:33:08 +00001116 self.serializeValue(arg.type, arg.name)
José Fonseca1601c412011-05-10 10:38:19 +01001117 else:
José Fonseca632a78d2012-04-19 07:18:59 +01001118 print ' trace::localWriter.writeBlob((const void *)%s, _size);' % (arg.name)
José Fonsecab4a3d142011-10-27 07:43:19 +01001119 print ' trace::localWriter.endArg();'
José Fonseca1601c412011-05-10 10:38:19 +01001120
José Fonsecab4a3d142011-10-27 07:43:19 +01001121 print ' trace::localWriter.endEnter();'
José Fonseca632a78d2012-04-19 07:18:59 +01001122 print ' trace::localWriter.beginLeave(_call);'
José Fonsecab4a3d142011-10-27 07:43:19 +01001123 print ' trace::localWriter.endLeave();'
José Fonseca1601c412011-05-10 10:38:19 +01001124 print ' }'
1125 print ' }'
1126 print ' }'
1127 print ' }'
1128 print
José Fonseca1a2fdd22011-04-01 00:55:09 +01001129
José Fonseca8d1408b2014-02-03 19:57:18 +00001130 # Restore the original array_buffer
1131 print ' if (_array_buffer) {'
1132 self.fake_glBindBuffer(api, 'GL_ARRAY_BUFFER', '_array_buffer')
1133 print ' }'
1134 print
1135
José Fonseca669b1222011-02-20 09:05:10 +00001136 print '}'
1137 print
1138
José Fonsecafb6744f2011-04-15 11:18:37 +01001139 #
1140 # Hooks for glTexCoordPointer, which is identical to the other array
1141 # pointers except the fact that it is indexed by glClientActiveTexture.
1142 #
1143
1144 def array_prolog(self, api, uppercase_name):
1145 if uppercase_name == 'TEXTURE_COORD':
José Fonseca26be8f92014-03-07 14:08:50 +00001146 print ' GLint client_active_texture = _glGetInteger(GL_CLIENT_ACTIVE_TEXTURE);'
José Fonsecafb6744f2011-04-15 11:18:37 +01001147 print ' GLint max_texture_coords = 0;'
José Fonsecaf028a8f2012-02-15 23:33:35 +00001148 print ' if (ctx->profile == gltrace::PROFILE_COMPAT)'
José Fonseca632a78d2012-04-19 07:18:59 +01001149 print ' _glGetIntegerv(GL_MAX_TEXTURE_COORDS, &max_texture_coords);'
Chia-I Wub3d218d2011-11-03 01:37:36 +08001150 print ' else'
José Fonseca632a78d2012-04-19 07:18:59 +01001151 print ' _glGetIntegerv(GL_MAX_TEXTURE_UNITS, &max_texture_coords);'
José Fonsecafb6744f2011-04-15 11:18:37 +01001152 print ' for (GLint unit = 0; unit < max_texture_coords; ++unit) {'
José Fonseca7525e6f2011-09-28 09:04:56 +01001153 print ' GLint texture = GL_TEXTURE0 + unit;'
José Fonseca632a78d2012-04-19 07:18:59 +01001154 print ' _glClientActiveTexture(texture);'
José Fonsecafb6744f2011-04-15 11:18:37 +01001155
1156 def array_trace_prolog(self, api, uppercase_name):
1157 if uppercase_name == 'TEXTURE_COORD':
1158 print ' bool client_active_texture_dirty = false;'
1159
1160 def array_epilog(self, api, uppercase_name):
1161 if uppercase_name == 'TEXTURE_COORD':
1162 print ' }'
1163 self.array_cleanup(api, uppercase_name)
1164
1165 def array_cleanup(self, api, uppercase_name):
1166 if uppercase_name == 'TEXTURE_COORD':
José Fonseca632a78d2012-04-19 07:18:59 +01001167 print ' _glClientActiveTexture(client_active_texture);'
José Fonsecafb6744f2011-04-15 11:18:37 +01001168
1169 def array_trace_intermezzo(self, api, uppercase_name):
1170 if uppercase_name == 'TEXTURE_COORD':
1171 print ' if (texture != client_active_texture || client_active_texture_dirty) {'
1172 print ' client_active_texture_dirty = true;'
1173 self.fake_glClientActiveTexture_call(api, "texture");
1174 print ' }'
1175
1176 def array_trace_epilog(self, api, uppercase_name):
1177 if uppercase_name == 'TEXTURE_COORD':
1178 print ' if (client_active_texture_dirty) {'
1179 self.fake_glClientActiveTexture_call(api, "client_active_texture");
1180 print ' }'
1181
José Fonseca8d1408b2014-02-03 19:57:18 +00001182 def fake_glBindBuffer(self, api, target, buffer):
1183 function = api.getFunctionByName('glBindBuffer')
1184 self.fake_call(function, [target, buffer])
1185
José Fonsecafb6744f2011-04-15 11:18:37 +01001186 def fake_glClientActiveTexture_call(self, api, texture):
José Fonseca1b6c8752012-04-15 14:33:00 +01001187 function = api.getFunctionByName('glClientActiveTexture')
José Fonsecafb6744f2011-04-15 11:18:37 +01001188 self.fake_call(function, [texture])
1189
José Fonseca151c3702013-05-10 08:28:15 +01001190 def emitFakeTexture2D(self):
1191 function = glapi.glapi.getFunctionByName('glTexImage2D')
1192 instances = function.argNames()
José Fonseca7a5f23a2014-06-24 19:20:36 +01001193 print ' unsigned _fake_call = trace::localWriter.beginEnter(&_%s_sig, true);' % (function.name,)
José Fonseca151c3702013-05-10 08:28:15 +01001194 for arg in function.args:
1195 assert not arg.output
1196 self.serializeArg(function, arg)
1197 print ' trace::localWriter.endEnter();'
1198 print ' trace::localWriter.beginLeave(_fake_call);'
1199 print ' trace::localWriter.endLeave();'
José Fonsecafb6744f2011-04-15 11:18:37 +01001200
1201
1202
1203
1204
José Fonseca669b1222011-02-20 09:05:10 +00001205
1206
1207
1208
1209
1210