blob: c0798e4a75551808217514179f9b08f51f98107e [file] [log] [blame]
José Fonseca669b1222011-02-20 09:05:10 +00001##########################################################################
2#
3# Copyright 2008-2010 VMware, Inc.
4# All Rights Reserved.
5#
6# Permission is hereby granted, free of charge, to any person obtaining a copy
7# of this software and associated documentation files (the "Software"), to deal
8# in the Software without restriction, including without limitation the rights
9# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10# copies of the Software, and to permit persons to whom the Software is
11# furnished to do so, subject to the following conditions:
12#
13# The above copyright notice and this permission notice shall be included in
14# all copies or substantial portions of the Software.
15#
16# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22# THE SOFTWARE.
23#
24##########################################################################/
25
26
27"""GL tracing generator."""
28
29
José Fonseca452d3252012-04-14 15:55:40 +010030from trace import Tracer
José Fonseca1b6c8752012-04-15 14:33:00 +010031from dispatch import function_pointer_type, function_pointer_value
José Fonsecabd86a222011-09-27 09:21:38 +010032import specs.stdapi as stdapi
33import specs.glapi as glapi
34import specs.glparams as glparams
35from specs.glxapi import glxapi
José Fonseca669b1222011-02-20 09:05:10 +000036
37
José Fonseca99221832011-03-22 22:15:46 +000038class TypeGetter(stdapi.Visitor):
39 '''Determine which glGet*v function that matches the specified type.'''
40
José Fonsecac493e3e2011-06-29 12:57:06 +010041 def __init__(self, prefix = 'glGet', long_suffix = True, ext_suffix = ''):
José Fonseca1a2fdd22011-04-01 00:55:09 +010042 self.prefix = prefix
43 self.long_suffix = long_suffix
José Fonsecac493e3e2011-06-29 12:57:06 +010044 self.ext_suffix = ext_suffix
José Fonseca1a2fdd22011-04-01 00:55:09 +010045
José Fonseca54f304a2012-01-14 19:33:08 +000046 def visitConst(self, const):
José Fonseca99221832011-03-22 22:15:46 +000047 return self.visit(const.type)
48
José Fonseca54f304a2012-01-14 19:33:08 +000049 def visitAlias(self, alias):
José Fonseca99221832011-03-22 22:15:46 +000050 if alias.expr == 'GLboolean':
José Fonseca1a2fdd22011-04-01 00:55:09 +010051 if self.long_suffix:
José Fonsecac493e3e2011-06-29 12:57:06 +010052 suffix = 'Booleanv'
53 arg_type = alias.expr
José Fonseca1a2fdd22011-04-01 00:55:09 +010054 else:
José Fonsecac493e3e2011-06-29 12:57:06 +010055 suffix = 'iv'
56 arg_type = 'GLint'
José Fonseca99221832011-03-22 22:15:46 +000057 elif alias.expr == 'GLdouble':
José Fonseca1a2fdd22011-04-01 00:55:09 +010058 if self.long_suffix:
José Fonsecac493e3e2011-06-29 12:57:06 +010059 suffix = 'Doublev'
60 arg_type = alias.expr
José Fonseca1a2fdd22011-04-01 00:55:09 +010061 else:
José Fonsecac493e3e2011-06-29 12:57:06 +010062 suffix = 'dv'
63 arg_type = alias.expr
José Fonseca99221832011-03-22 22:15:46 +000064 elif alias.expr == 'GLfloat':
José Fonseca1a2fdd22011-04-01 00:55:09 +010065 if self.long_suffix:
José Fonsecac493e3e2011-06-29 12:57:06 +010066 suffix = 'Floatv'
67 arg_type = alias.expr
José Fonseca1a2fdd22011-04-01 00:55:09 +010068 else:
José Fonsecac493e3e2011-06-29 12:57:06 +010069 suffix = 'fv'
70 arg_type = alias.expr
José Fonseca7f5163e2011-03-31 23:37:26 +010071 elif alias.expr in ('GLint', 'GLuint', 'GLsizei'):
José Fonseca1a2fdd22011-04-01 00:55:09 +010072 if self.long_suffix:
José Fonsecac493e3e2011-06-29 12:57:06 +010073 suffix = 'Integerv'
74 arg_type = 'GLint'
José Fonseca1a2fdd22011-04-01 00:55:09 +010075 else:
José Fonsecac493e3e2011-06-29 12:57:06 +010076 suffix = 'iv'
77 arg_type = 'GLint'
José Fonseca99221832011-03-22 22:15:46 +000078 else:
79 print alias.expr
80 assert False
José Fonsecac493e3e2011-06-29 12:57:06 +010081 function_name = self.prefix + suffix + self.ext_suffix
82 return function_name, arg_type
José Fonseca99221832011-03-22 22:15:46 +000083
José Fonseca54f304a2012-01-14 19:33:08 +000084 def visitEnum(self, enum):
José Fonseca1a2fdd22011-04-01 00:55:09 +010085 return self.visit(glapi.GLint)
José Fonseca99221832011-03-22 22:15:46 +000086
José Fonseca54f304a2012-01-14 19:33:08 +000087 def visitBitmask(self, bitmask):
José Fonseca1a2fdd22011-04-01 00:55:09 +010088 return self.visit(glapi.GLint)
José Fonseca99221832011-03-22 22:15:46 +000089
José Fonseca54f304a2012-01-14 19:33:08 +000090 def visitOpaque(self, pointer):
José Fonsecac493e3e2011-06-29 12:57:06 +010091 return self.prefix + 'Pointerv' + self.ext_suffix, 'GLvoid *'
José Fonseca99221832011-03-22 22:15:46 +000092
93
José Fonseca669b1222011-02-20 09:05:10 +000094class GlTracer(Tracer):
95
José Fonseca99221832011-03-22 22:15:46 +000096 arrays = [
97 ("Vertex", "VERTEX"),
98 ("Normal", "NORMAL"),
99 ("Color", "COLOR"),
100 ("Index", "INDEX"),
101 ("TexCoord", "TEXTURE_COORD"),
102 ("EdgeFlag", "EDGE_FLAG"),
103 ("FogCoord", "FOG_COORD"),
104 ("SecondaryColor", "SECONDARY_COLOR"),
José Fonseca14c21bc2011-02-20 23:32:22 +0000105 ]
José Fonsecac9f12232011-03-25 20:07:42 +0000106 arrays.reverse()
José Fonseca669b1222011-02-20 09:05:10 +0000107
Chia-I Wub3d218d2011-11-03 01:37:36 +0800108 # arrays available in PROFILE_ES1
109 arrays_es1 = ("Vertex", "Normal", "Color", "TexCoord")
110
José Fonseca4c938c22011-04-30 22:44:38 +0100111 def header(self, api):
112 Tracer.header(self, api)
113
José Fonseca707630d2014-03-07 14:20:35 +0000114 print '#include <algorithm>'
115 print
José Fonseca1b3d3752011-07-15 10:15:19 +0100116 print '#include "gltrace.hpp"'
117 print
José Fonseca5a568a92011-06-29 16:43:36 +0100118
119 # Which glVertexAttrib* variant to use
120 print 'enum vertex_attrib {'
121 print ' VERTEX_ATTRIB,'
122 print ' VERTEX_ATTRIB_ARB,'
123 print ' VERTEX_ATTRIB_NV,'
124 print '};'
125 print
José Fonseca632a78d2012-04-19 07:18:59 +0100126 print 'static vertex_attrib _get_vertex_attrib(void) {'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000127 print ' gltrace::Context *ctx = gltrace::getContext();'
Chia-I Wu8ef66972011-11-03 01:19:46 +0800128 print ' if (ctx->user_arrays_arb || ctx->user_arrays_nv) {'
José Fonseca632a78d2012-04-19 07:18:59 +0100129 print ' GLboolean _vertex_program = GL_FALSE;'
130 print ' _glGetBooleanv(GL_VERTEX_PROGRAM_ARB, &_vertex_program);'
131 print ' if (_vertex_program) {'
Chia-I Wu8ef66972011-11-03 01:19:46 +0800132 print ' if (ctx->user_arrays_nv) {'
José Fonseca26be8f92014-03-07 14:08:50 +0000133 print ' GLint _vertex_program_binding_nv = _glGetInteger(GL_VERTEX_PROGRAM_BINDING_NV);'
José Fonseca632a78d2012-04-19 07:18:59 +0100134 print ' if (_vertex_program_binding_nv) {'
José Fonseca5a568a92011-06-29 16:43:36 +0100135 print ' return VERTEX_ATTRIB_NV;'
136 print ' }'
137 print ' }'
138 print ' return VERTEX_ATTRIB_ARB;'
139 print ' }'
140 print ' }'
141 print ' return VERTEX_ATTRIB;'
142 print '}'
143 print
144
Imre Deakd4937372012-04-24 14:06:48 +0300145 self.defineShadowBufferHelper()
146
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000147 # Whether we need user arrays
José Fonseca632a78d2012-04-19 07:18:59 +0100148 print 'static inline bool _need_user_arrays(void)'
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000149 print '{'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000150 print ' gltrace::Context *ctx = gltrace::getContext();'
Chia-I Wu8ef66972011-11-03 01:19:46 +0800151 print ' if (!ctx->user_arrays) {'
José Fonseca25ebe542011-04-24 10:08:22 +0100152 print ' return false;'
153 print ' }'
154 print
José Fonseca1a2fdd22011-04-01 00:55:09 +0100155
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000156 for camelcase_name, uppercase_name in self.arrays:
Chia-I Wub3d218d2011-11-03 01:37:36 +0800157 # in which profile is the array available?
José Fonsecaf028a8f2012-02-15 23:33:35 +0000158 profile_check = 'ctx->profile == gltrace::PROFILE_COMPAT'
Chia-I Wub3d218d2011-11-03 01:37:36 +0800159 if camelcase_name in self.arrays_es1:
José Fonsecaf028a8f2012-02-15 23:33:35 +0000160 profile_check = '(' + profile_check + ' || ctx->profile == gltrace::PROFILE_ES1)';
Chia-I Wub3d218d2011-11-03 01:37:36 +0800161
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000162 function_name = 'gl%sPointer' % camelcase_name
163 enable_name = 'GL_%s_ARRAY' % uppercase_name
164 binding_name = 'GL_%s_ARRAY_BUFFER_BINDING' % uppercase_name
165 print ' // %s' % function_name
Chia-I Wub3d218d2011-11-03 01:37:36 +0800166 print ' if (%s) {' % profile_check
José Fonsecafb6744f2011-04-15 11:18:37 +0100167 self.array_prolog(api, uppercase_name)
José Fonseca632a78d2012-04-19 07:18:59 +0100168 print ' if (_glIsEnabled(%s)) {' % enable_name
José Fonseca26be8f92014-03-07 14:08:50 +0000169 print ' GLint _binding = _glGetInteger(%s);' % binding_name
José Fonseca632a78d2012-04-19 07:18:59 +0100170 print ' if (!_binding) {'
José Fonsecafb6744f2011-04-15 11:18:37 +0100171 self.array_cleanup(api, uppercase_name)
José Fonseca7f5163e2011-03-31 23:37:26 +0100172 print ' return true;'
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000173 print ' }'
174 print ' }'
José Fonsecafb6744f2011-04-15 11:18:37 +0100175 self.array_epilog(api, uppercase_name)
Chia-I Wub3d218d2011-11-03 01:37:36 +0800176 print ' }'
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000177 print
José Fonseca7f5163e2011-03-31 23:37:26 +0100178
Chia-I Wub3d218d2011-11-03 01:37:36 +0800179 print ' // ES1 does not support generic vertex attributes'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000180 print ' if (ctx->profile == gltrace::PROFILE_ES1)'
Chia-I Wub3d218d2011-11-03 01:37:36 +0800181 print ' return false;'
182 print
José Fonseca632a78d2012-04-19 07:18:59 +0100183 print ' vertex_attrib _vertex_attrib = _get_vertex_attrib();'
José Fonseca5a568a92011-06-29 16:43:36 +0100184 print
185 print ' // glVertexAttribPointer'
José Fonseca632a78d2012-04-19 07:18:59 +0100186 print ' if (_vertex_attrib == VERTEX_ATTRIB) {'
José Fonseca26be8f92014-03-07 14:08:50 +0000187 print ' GLint _max_vertex_attribs = _glGetInteger(GL_MAX_VERTEX_ATTRIBS);'
José Fonseca632a78d2012-04-19 07:18:59 +0100188 print ' for (GLint index = 0; index < _max_vertex_attribs; ++index) {'
189 print ' GLint _enabled = 0;'
190 print ' _glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &_enabled);'
191 print ' if (_enabled) {'
192 print ' GLint _binding = 0;'
193 print ' _glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &_binding);'
194 print ' if (!_binding) {'
José Fonseca5a568a92011-06-29 16:43:36 +0100195 print ' return true;'
196 print ' }'
197 print ' }'
198 print ' }'
199 print ' }'
200 print
201 print ' // glVertexAttribPointerARB'
José Fonseca632a78d2012-04-19 07:18:59 +0100202 print ' if (_vertex_attrib == VERTEX_ATTRIB_ARB) {'
José Fonseca26be8f92014-03-07 14:08:50 +0000203 print ' GLint _max_vertex_attribs = _glGetInteger(GL_MAX_VERTEX_ATTRIBS_ARB);'
José Fonseca632a78d2012-04-19 07:18:59 +0100204 print ' for (GLint index = 0; index < _max_vertex_attribs; ++index) {'
205 print ' GLint _enabled = 0;'
206 print ' _glGetVertexAttribivARB(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB, &_enabled);'
207 print ' if (_enabled) {'
208 print ' GLint _binding = 0;'
209 print ' _glGetVertexAttribivARB(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB, &_binding);'
210 print ' if (!_binding) {'
José Fonsecad94aaac2011-06-28 20:50:49 +0100211 print ' return true;'
212 print ' }'
213 print ' }'
214 print ' }'
José Fonseca5a568a92011-06-29 16:43:36 +0100215 print ' }'
216 print
217 print ' // glVertexAttribPointerNV'
José Fonseca632a78d2012-04-19 07:18:59 +0100218 print ' if (_vertex_attrib == VERTEX_ATTRIB_NV) {'
José Fonseca5a568a92011-06-29 16:43:36 +0100219 print ' for (GLint index = 0; index < 16; ++index) {'
José Fonseca26be8f92014-03-07 14:08:50 +0000220 print ' GLboolean _enabled = _glIsEnabled(GL_VERTEX_ATTRIB_ARRAY0_NV);'
José Fonseca632a78d2012-04-19 07:18:59 +0100221 print ' if (_enabled) {'
José Fonseca5a568a92011-06-29 16:43:36 +0100222 print ' return true;'
José Fonseca1a2fdd22011-04-01 00:55:09 +0100223 print ' }'
224 print ' }'
225 print ' }'
226 print
227
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000228 print ' return false;'
229 print '}'
230 print
José Fonseca669b1222011-02-20 09:05:10 +0000231
José Fonseca14cb9ef2012-05-17 21:33:14 +0100232 print 'static void _trace_user_arrays(GLuint count);'
José Fonseca14c21bc2011-02-20 23:32:22 +0000233 print
José Fonseca867b1b72011-04-24 11:58:04 +0100234
José Fonseca707630d2014-03-07 14:20:35 +0000235 print '// whether glLockArraysEXT() has ever been called'
236 print 'static bool _checkLockArraysEXT = false;'
237 print
238
José Fonseca9c536b02012-02-29 20:54:13 +0000239 # Buffer mappings
240 print '// whether glMapBufferRange(GL_MAP_WRITE_BIT) has ever been called'
José Fonseca632a78d2012-04-19 07:18:59 +0100241 print 'static bool _checkBufferMapRange = false;'
José Fonseca9c536b02012-02-29 20:54:13 +0000242 print
243 print '// whether glBufferParameteriAPPLE(GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE) has ever been called'
José Fonseca632a78d2012-04-19 07:18:59 +0100244 print 'static bool _checkBufferFlushingUnmapAPPLE = false;'
José Fonseca9c536b02012-02-29 20:54:13 +0000245 print
246 # Buffer mapping information, necessary for old Mesa 2.1 drivers which
247 # do not support glGetBufferParameteriv(GL_BUFFER_ACCESS_FLAGS/GL_BUFFER_MAP_LENGTH)
José Fonseca867b1b72011-04-24 11:58:04 +0100248 print 'struct buffer_mapping {'
249 print ' void *map;'
250 print ' GLint length;'
251 print ' bool write;'
José Fonseca73373602011-05-20 17:45:26 +0100252 print ' bool explicit_flush;'
José Fonseca867b1b72011-04-24 11:58:04 +0100253 print '};'
254 print
255 for target in self.buffer_targets:
José Fonseca632a78d2012-04-19 07:18:59 +0100256 print 'struct buffer_mapping _%s_mapping;' % target.lower();
José Fonseca867b1b72011-04-24 11:58:04 +0100257 print
258 print 'static inline struct buffer_mapping *'
259 print 'get_buffer_mapping(GLenum target) {'
José Fonseca06e85192011-10-16 14:15:36 +0100260 print ' switch (target) {'
José Fonseca867b1b72011-04-24 11:58:04 +0100261 for target in self.buffer_targets:
262 print ' case GL_%s:' % target
José Fonseca632a78d2012-04-19 07:18:59 +0100263 print ' return & _%s_mapping;' % target.lower()
José Fonseca867b1b72011-04-24 11:58:04 +0100264 print ' default:'
José Fonseca559d5342011-10-27 08:10:56 +0100265 print ' os::log("apitrace: warning: unknown buffer target 0x%04X\\n", target);'
José Fonseca867b1b72011-04-24 11:58:04 +0100266 print ' return NULL;'
267 print ' }'
268 print '}'
269 print
270
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100271 # Generate a helper function to determine whether a parameter name
272 # refers to a symbolic value or not
273 print 'static bool'
274 print 'is_symbolic_pname(GLenum pname) {'
José Fonseca06e85192011-10-16 14:15:36 +0100275 print ' switch (pname) {'
José Fonseca5ea91872011-05-04 09:41:55 +0100276 for function, type, count, name in glparams.parameters:
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100277 if type is glapi.GLenum:
José Fonseca4c938c22011-04-30 22:44:38 +0100278 print ' case %s:' % name
279 print ' return true;'
280 print ' default:'
281 print ' return false;'
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100282 print ' }'
283 print '}'
284 print
285
286 # Generate a helper function to determine whether a parameter value is
287 # potentially symbolic or not; i.e., if the value can be represented in
288 # an enum or not
289 print 'template<class T>'
290 print 'static inline bool'
291 print 'is_symbolic_param(T param) {'
292 print ' return static_cast<T>(static_cast<GLenum>(param)) == param;'
293 print '}'
294 print
José Fonseca4c938c22011-04-30 22:44:38 +0100295
296 # Generate a helper function to know how many elements a parameter has
297 print 'static size_t'
José Fonseca632a78d2012-04-19 07:18:59 +0100298 print '_gl_param_size(GLenum pname) {'
José Fonseca06e85192011-10-16 14:15:36 +0100299 print ' switch (pname) {'
José Fonseca5ea91872011-05-04 09:41:55 +0100300 for function, type, count, name in glparams.parameters:
José Fonseca4c938c22011-04-30 22:44:38 +0100301 if type is not None:
José Fonsecaddf6d2c2012-12-20 15:34:50 +0000302 print ' case %s: return %s;' % (name, count)
José Fonseca4c938c22011-04-30 22:44:38 +0100303 print ' default:'
José Fonseca559d5342011-10-27 08:10:56 +0100304 print r' os::log("apitrace: warning: %s: unknown GLenum 0x%04X\n", __FUNCTION__, pname);'
José Fonseca4c938c22011-04-30 22:44:38 +0100305 print ' return 1;'
306 print ' }'
307 print '}'
308 print
309
Chia-I Wu335efb42011-11-03 01:59:22 +0800310 # states such as GL_UNPACK_ROW_LENGTH are not available in GLES
311 print 'static inline bool'
312 print 'can_unpack_subimage(void) {'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000313 print ' gltrace::Context *ctx = gltrace::getContext();'
314 print ' return (ctx->profile == gltrace::PROFILE_COMPAT);'
Chia-I Wu335efb42011-11-03 01:59:22 +0800315 print '}'
316 print
317
José Fonseca1b6c8752012-04-15 14:33:00 +0100318 getProcAddressFunctionNames = []
319
320 def traceApi(self, api):
321 if self.getProcAddressFunctionNames:
322 # Generate a function to wrap proc addresses
323 getProcAddressFunction = api.getFunctionByName(self.getProcAddressFunctionNames[0])
324 argType = getProcAddressFunction.args[0].type
325 retType = getProcAddressFunction.type
326
327 print 'static %s _wrapProcAddress(%s procName, %s procPtr);' % (retType, argType, retType)
328 print
329
330 Tracer.traceApi(self, api)
331
332 print 'static %s _wrapProcAddress(%s procName, %s procPtr) {' % (retType, argType, retType)
Peter Lohrmann0b5b75e2013-06-03 14:58:41 -0700333
334 # Provide fallback functions to missing debug functions
José Fonseca1b6c8752012-04-15 14:33:00 +0100335 print ' if (!procPtr) {'
Peter Lohrmann0b5b75e2013-06-03 14:58:41 -0700336 else_ = ''
337 for function_name in self.debug_functions:
338 if self.api.getFunctionByName(function_name):
339 print ' %sif (strcmp("%s", (const char *)procName) == 0) {' % (else_, function_name)
340 print ' return (%s)&%s;' % (retType, function_name)
341 print ' }'
342 else_ = 'else '
343 print ' %s{' % else_
344 print ' return NULL;'
345 print ' }'
José Fonseca1b6c8752012-04-15 14:33:00 +0100346 print ' }'
Peter Lohrmann0b5b75e2013-06-03 14:58:41 -0700347
José Fonseca81301932012-11-11 00:10:20 +0000348 for function in api.getAllFunctions():
José Fonseca1b6c8752012-04-15 14:33:00 +0100349 ptype = function_pointer_type(function)
350 pvalue = function_pointer_value(function)
351 print ' if (strcmp("%s", (const char *)procName) == 0) {' % function.name
352 print ' %s = (%s)procPtr;' % (pvalue, ptype)
353 print ' return (%s)&%s;' % (retType, function.name,)
354 print ' }'
355 print ' os::log("apitrace: warning: unknown function \\"%s\\"\\n", (const char *)procName);'
356 print ' return procPtr;'
357 print '}'
358 print
359 else:
360 Tracer.traceApi(self, api)
361
Imre Deakd4937372012-04-24 14:06:48 +0300362 def defineShadowBufferHelper(self):
363 print 'void _shadow_glGetBufferSubData(GLenum target, GLintptr offset,'
364 print ' GLsizeiptr size, GLvoid *data)'
365 print '{'
José Fonsecaa33d0bb2012-11-10 09:11:42 +0000366 print ' gltrace::Context *ctx = gltrace::getContext();'
Imre Deakd4937372012-04-24 14:06:48 +0300367 print ' if (!ctx->needsShadowBuffers() || target != GL_ELEMENT_ARRAY_BUFFER) {'
José Fonseca219c9f22012-11-03 10:13:17 +0000368 print ' _glGetBufferSubData(target, offset, size, data);'
Imre Deakd4937372012-04-24 14:06:48 +0300369 print ' return;'
370 print ' }'
371 print
José Fonseca26be8f92014-03-07 14:08:50 +0000372 print ' GLint buffer_binding = _glGetInteger(GL_ELEMENT_ARRAY_BUFFER_BINDING);'
José Fonseca219c9f22012-11-03 10:13:17 +0000373 print ' if (buffer_binding > 0) {'
374 print ' gltrace::Buffer & buf = ctx->buffers[buffer_binding];'
375 print ' buf.getSubData(offset, size, data);'
376 print ' }'
Imre Deakd4937372012-04-24 14:06:48 +0300377 print '}'
378
José Fonseca219c9f22012-11-03 10:13:17 +0000379 def shadowBufferMethod(self, method):
380 # Emit code to fetch the shadow buffer, and invoke a method
381 print ' gltrace::Context *ctx = gltrace::getContext();'
382 print ' if (ctx->needsShadowBuffers() && target == GL_ELEMENT_ARRAY_BUFFER) {'
José Fonseca26be8f92014-03-07 14:08:50 +0000383 print ' GLint buffer_binding = _glGetInteger(GL_ELEMENT_ARRAY_BUFFER_BINDING);'
José Fonseca219c9f22012-11-03 10:13:17 +0000384 print ' if (buffer_binding > 0) {'
385 print ' gltrace::Buffer & buf = ctx->buffers[buffer_binding];'
386 print ' buf.' + method + ';'
387 print ' }'
388 print ' }'
389 print
390
Imre Deakd4937372012-04-24 14:06:48 +0300391 def shadowBufferProlog(self, function):
392 if function.name == 'glBufferData':
José Fonseca219c9f22012-11-03 10:13:17 +0000393 self.shadowBufferMethod('bufferData(size, data)')
Imre Deakd4937372012-04-24 14:06:48 +0300394
395 if function.name == 'glBufferSubData':
José Fonseca219c9f22012-11-03 10:13:17 +0000396 self.shadowBufferMethod('bufferSubData(offset, size, data)')
Imre Deakd4937372012-04-24 14:06:48 +0300397
398 if function.name == 'glDeleteBuffers':
399 print ' gltrace::Context *ctx = gltrace::getContext();'
400 print ' if (ctx->needsShadowBuffers()) {'
José Fonseca219c9f22012-11-03 10:13:17 +0000401 print ' for (GLsizei i = 0; i < n; i++) {'
402 print ' ctx->buffers.erase(buffer[i]);'
Imre Deakd4937372012-04-24 14:06:48 +0300403 print ' }'
404 print ' }'
405
José Fonseca99221832011-03-22 22:15:46 +0000406 array_pointer_function_names = set((
407 "glVertexPointer",
408 "glNormalPointer",
409 "glColorPointer",
410 "glIndexPointer",
411 "glTexCoordPointer",
412 "glEdgeFlagPointer",
413 "glFogCoordPointer",
414 "glSecondaryColorPointer",
José Fonseca7f5163e2011-03-31 23:37:26 +0100415
José Fonsecaac5285b2011-05-04 11:09:08 +0100416 "glInterleavedArrays",
417
José Fonseca7e0bfd92011-04-30 23:09:03 +0100418 "glVertexPointerEXT",
419 "glNormalPointerEXT",
420 "glColorPointerEXT",
421 "glIndexPointerEXT",
422 "glTexCoordPointerEXT",
423 "glEdgeFlagPointerEXT",
424 "glFogCoordPointerEXT",
425 "glSecondaryColorPointerEXT",
José Fonseca99221832011-03-22 22:15:46 +0000426
José Fonseca7f5163e2011-03-31 23:37:26 +0100427 "glVertexAttribPointer",
428 "glVertexAttribPointerARB",
429 "glVertexAttribPointerNV",
José Fonsecaac5285b2011-05-04 11:09:08 +0100430 "glVertexAttribIPointer",
431 "glVertexAttribIPointerEXT",
José Fonseca7f5163e2011-03-31 23:37:26 +0100432 "glVertexAttribLPointer",
433 "glVertexAttribLPointerEXT",
José Fonseca99221832011-03-22 22:15:46 +0000434
435 #"glMatrixIndexPointerARB",
436 ))
437
438 draw_function_names = set((
439 'glDrawArrays',
440 'glDrawElements',
441 'glDrawRangeElements',
José Fonseca5c749e32011-05-09 11:11:37 +0100442 'glMultiDrawArrays',
443 'glMultiDrawElements',
444 'glDrawArraysInstanced',
José Fonsecaff8848b2011-10-09 01:04:17 +0100445 "glDrawArraysInstancedBaseInstance",
José Fonseca5c749e32011-05-09 11:11:37 +0100446 'glDrawElementsInstanced',
447 'glDrawArraysInstancedARB',
448 'glDrawElementsInstancedARB',
449 'glDrawElementsBaseVertex',
450 'glDrawRangeElementsBaseVertex',
451 'glDrawElementsInstancedBaseVertex',
José Fonsecaff8848b2011-10-09 01:04:17 +0100452 "glDrawElementsInstancedBaseInstance",
453 "glDrawElementsInstancedBaseVertexBaseInstance",
José Fonseca5c749e32011-05-09 11:11:37 +0100454 'glMultiDrawElementsBaseVertex',
455 'glDrawArraysIndirect',
456 'glDrawElementsIndirect',
José Fonseca29ac7c72013-04-14 15:40:01 +0100457 'glMultiDrawArraysIndirect',
458 'glMultiDrawArraysIndirectAMD',
459 'glMultiDrawElementsIndirect',
460 'glMultiDrawElementsIndirectAMD',
José Fonseca5c749e32011-05-09 11:11:37 +0100461 'glDrawArraysEXT',
José Fonseca7e0bfd92011-04-30 23:09:03 +0100462 'glDrawRangeElementsEXT',
José Fonseca5c749e32011-05-09 11:11:37 +0100463 'glDrawRangeElementsEXT_size',
464 'glMultiDrawArraysEXT',
465 'glMultiDrawElementsEXT',
466 'glMultiModeDrawArraysIBM',
467 'glMultiModeDrawElementsIBM',
468 'glDrawArraysInstancedEXT',
469 'glDrawElementsInstancedEXT',
José Fonseca99221832011-03-22 22:15:46 +0000470 ))
471
José Fonsecac9f12232011-03-25 20:07:42 +0000472 interleaved_formats = [
473 'GL_V2F',
474 'GL_V3F',
475 'GL_C4UB_V2F',
476 'GL_C4UB_V3F',
477 'GL_C3F_V3F',
478 'GL_N3F_V3F',
479 'GL_C4F_N3F_V3F',
480 'GL_T2F_V3F',
481 'GL_T4F_V4F',
482 'GL_T2F_C4UB_V3F',
483 'GL_T2F_C3F_V3F',
484 'GL_T2F_N3F_V3F',
485 'GL_T2F_C4F_N3F_V3F',
486 'GL_T4F_C4F_N3F_V4F',
487 ]
488
José Fonseca54f304a2012-01-14 19:33:08 +0000489 def traceFunctionImplBody(self, function):
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000490 # Defer tracing of user array pointers...
José Fonseca99221832011-03-22 22:15:46 +0000491 if function.name in self.array_pointer_function_names:
José Fonseca26be8f92014-03-07 14:08:50 +0000492 print ' GLint _array_buffer = _glGetInteger(GL_ARRAY_BUFFER_BINDING);'
José Fonseca632a78d2012-04-19 07:18:59 +0100493 print ' if (!_array_buffer) {'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000494 print ' gltrace::Context *ctx = gltrace::getContext();'
Chia-I Wu8ef66972011-11-03 01:19:46 +0800495 print ' ctx->user_arrays = true;'
José Fonseca5a568a92011-06-29 16:43:36 +0100496 if function.name == "glVertexAttribPointerARB":
Chia-I Wu8ef66972011-11-03 01:19:46 +0800497 print ' ctx->user_arrays_arb = true;'
José Fonseca5a568a92011-06-29 16:43:36 +0100498 if function.name == "glVertexAttribPointerNV":
Chia-I Wu8ef66972011-11-03 01:19:46 +0800499 print ' ctx->user_arrays_nv = true;'
José Fonseca54f304a2012-01-14 19:33:08 +0000500 self.invokeFunction(function)
José Fonsecaac5285b2011-05-04 11:09:08 +0100501
502 # And also break down glInterleavedArrays into the individual calls
503 if function.name == 'glInterleavedArrays':
504 print
505
506 # Initialize the enable flags
507 for camelcase_name, uppercase_name in self.arrays:
José Fonseca632a78d2012-04-19 07:18:59 +0100508 flag_name = '_' + uppercase_name.lower()
José Fonsecaac5285b2011-05-04 11:09:08 +0100509 print ' GLboolean %s = GL_FALSE;' % flag_name
510 print
511
512 # Switch for the interleaved formats
513 print ' switch (format) {'
514 for format in self.interleaved_formats:
515 print ' case %s:' % format
516 for camelcase_name, uppercase_name in self.arrays:
José Fonseca632a78d2012-04-19 07:18:59 +0100517 flag_name = '_' + uppercase_name.lower()
José Fonsecaac5285b2011-05-04 11:09:08 +0100518 if format.find('_' + uppercase_name[0]) >= 0:
519 print ' %s = GL_TRUE;' % flag_name
520 print ' break;'
521 print ' default:'
522 print ' return;'
523 print ' }'
524 print
525
526 # Emit fake glEnableClientState/glDisableClientState flags
527 for camelcase_name, uppercase_name in self.arrays:
José Fonseca632a78d2012-04-19 07:18:59 +0100528 flag_name = '_' + uppercase_name.lower()
José Fonsecaac5285b2011-05-04 11:09:08 +0100529 enable_name = 'GL_%s_ARRAY' % uppercase_name
530
531 # Emit a fake function
532 print ' {'
José Fonseca632a78d2012-04-19 07:18:59 +0100533 print ' static const trace::FunctionSig &_sig = %s ? _glEnableClientState_sig : _glDisableClientState_sig;' % flag_name
534 print ' unsigned _call = trace::localWriter.beginEnter(&_sig);'
José Fonsecab4a3d142011-10-27 07:43:19 +0100535 print ' trace::localWriter.beginArg(0);'
José Fonseca54f304a2012-01-14 19:33:08 +0000536 self.serializeValue(glapi.GLenum, enable_name)
José Fonsecab4a3d142011-10-27 07:43:19 +0100537 print ' trace::localWriter.endArg();'
538 print ' trace::localWriter.endEnter();'
José Fonseca632a78d2012-04-19 07:18:59 +0100539 print ' trace::localWriter.beginLeave(_call);'
José Fonsecab4a3d142011-10-27 07:43:19 +0100540 print ' trace::localWriter.endLeave();'
José Fonsecaac5285b2011-05-04 11:09:08 +0100541 print ' }'
542
José Fonsecac629a8c2014-06-01 21:12:27 +0100543 # Warn about buggy glGet(GL_*ARRAY_SIZE) not returning GL_BGRA
544 buggyFunctions = {
545 'glColorPointer': ('glGetIntegerv', '', 'GL_COLOR_ARRAY_SIZE'),
546 'glSecondaryColorPointer': ('glGetIntegerv', '', 'GL_SECONDARY_COLOR_ARRAY_SIZE'),
547 'glVertexAttribPointer': ('glGetVertexAttribiv', 'index, ', 'GL_VERTEX_ATTRIB_ARRAY_SIZE'),
548 'glVertexAttribPointerARB': ('glGetVertexAttribivARB', 'index, ', 'GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB'),
549 }
550 if function.name in buggyFunctions:
551 getter, extraArg, pname = buggyFunctions[function.name]
552 print r' static bool _checked = false;'
553 print r' if (!_checked && size == GL_BGRA) {'
554 print r' GLint _size = 0;'
555 print r' _%s(%s%s, &_size);' % (getter, extraArg, pname)
556 print r' if (_size != GL_BGRA) {'
557 print r' os::log("apitrace: warning: %s(%s) does not return GL_BGRA; trace will be incorrect (https://github.com/apitrace/apitrace/issues/261)\n");' % (getter, pname)
558 print r' }'
559 print r' _checked = true;'
560 print r' }'
561
José Fonseca99221832011-03-22 22:15:46 +0000562 print ' return;'
563 print ' }'
José Fonseca14c21bc2011-02-20 23:32:22 +0000564
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000565 # ... to the draw calls
José Fonseca99221832011-03-22 22:15:46 +0000566 if function.name in self.draw_function_names:
José Fonseca632a78d2012-04-19 07:18:59 +0100567 print ' if (_need_user_arrays()) {'
José Fonseca99221832011-03-22 22:15:46 +0000568 arg_names = ', '.join([arg.name for arg in function.args[1:]])
José Fonseca14cb9ef2012-05-17 21:33:14 +0100569 print ' GLuint _count = _%s_count(%s);' % (function.name, arg_names)
José Fonseca707630d2014-03-07 14:20:35 +0000570 # Some apps, in particular Quake3, can tell the driver to lock more
571 # vertices than those actually required for the draw call.
572 print ' if (_checkLockArraysEXT) {'
573 print ' GLuint _locked_count = _glGetInteger(GL_ARRAY_ELEMENT_LOCK_FIRST_EXT)'
574 print ' + _glGetInteger(GL_ARRAY_ELEMENT_LOCK_COUNT_EXT);'
575 print ' _count = std::max(_count, _locked_count);'
576 print ' }'
José Fonseca14cb9ef2012-05-17 21:33:14 +0100577 print ' _trace_user_arrays(_count);'
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000578 print ' }'
José Fonseca707630d2014-03-07 14:20:35 +0000579 if function.name == 'glLockArraysEXT':
580 print ' _checkLockArraysEXT = true;'
José Fonseca4a7d8602014-06-18 16:03:44 +0100581
582 # Warn if user arrays are used with glBegin/glArrayElement/glEnd.
583 if function.name == 'glBegin':
584 print r' if (_need_user_arrays()) {'
585 print r' os::log("apitrace: warning: user arrays with glArrayElement not supported (https://github.com/apitrace/apitrace/issues/276)\n");'
586 print r' }'
José Fonseca14c21bc2011-02-20 23:32:22 +0000587
José Fonseca73373602011-05-20 17:45:26 +0100588 # Emit a fake memcpy on buffer uploads
José Fonseca9c536b02012-02-29 20:54:13 +0000589 if function.name == 'glBufferParameteriAPPLE':
590 print ' if (pname == GL_BUFFER_FLUSHING_UNMAP_APPLE && param == GL_FALSE) {'
José Fonseca632a78d2012-04-19 07:18:59 +0100591 print ' _checkBufferFlushingUnmapAPPLE = true;'
José Fonseca9c536b02012-02-29 20:54:13 +0000592 print ' }'
José Fonsecacdc322c2012-02-29 19:29:51 +0000593 if function.name in ('glUnmapBuffer', 'glUnmapBufferARB'):
José Fonseca9c536b02012-02-29 20:54:13 +0000594 if function.name.endswith('ARB'):
595 suffix = 'ARB'
596 else:
597 suffix = ''
598 print ' GLint access = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100599 print ' _glGetBufferParameteriv%s(target, GL_BUFFER_ACCESS, &access);' % suffix
José Fonseca9c536b02012-02-29 20:54:13 +0000600 print ' if (access != GL_READ_ONLY) {'
601 print ' GLvoid *map = NULL;'
José Fonseca632a78d2012-04-19 07:18:59 +0100602 print ' _glGetBufferPointerv%s(target, GL_BUFFER_MAP_POINTER, &map);' % suffix
José Fonseca9c536b02012-02-29 20:54:13 +0000603 print ' if (map) {'
604 print ' GLint length = -1;'
605 print ' bool flush = true;'
José Fonseca632a78d2012-04-19 07:18:59 +0100606 print ' if (_checkBufferMapRange) {'
607 print ' _glGetBufferParameteriv%s(target, GL_BUFFER_MAP_LENGTH, &length);' % suffix
José Fonseca9c536b02012-02-29 20:54:13 +0000608 print ' GLint access_flags = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100609 print ' _glGetBufferParameteriv(target, GL_BUFFER_ACCESS_FLAGS, &access_flags);'
José Fonseca9c536b02012-02-29 20:54:13 +0000610 print ' flush = flush && !(access_flags & GL_MAP_FLUSH_EXPLICIT_BIT);'
611 print ' if (length == -1) {'
José Fonsecacb07e2d2014-02-04 15:14:09 +0000612 print ' // Mesa drivers refuse GL_BUFFER_MAP_LENGTH without GL 3.0 up-to'
613 print ' // http://cgit.freedesktop.org/mesa/mesa/commit/?id=ffee498fb848b253a7833373fe5430f8c7ca0c5f'
José Fonsecadb1ccce2012-02-29 21:09:24 +0000614 print ' static bool warned = false;'
615 print ' if (!warned) {'
616 print ' os::log("apitrace: warning: glGetBufferParameteriv%s(GL_BUFFER_MAP_LENGTH) failed\\n");' % suffix
617 print ' warned = true;'
618 print ' }'
José Fonseca9c536b02012-02-29 20:54:13 +0000619 print ' struct buffer_mapping *mapping = get_buffer_mapping(target);'
620 print ' if (mapping) {'
621 print ' length = mapping->length;'
622 print ' flush = flush && !mapping->explicit_flush;'
623 print ' } else {'
624 print ' length = 0;'
625 print ' flush = false;'
626 print ' }'
627 print ' }'
628 print ' } else {'
629 print ' length = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100630 print ' _glGetBufferParameteriv%s(target, GL_BUFFER_SIZE, &length);' % suffix
José Fonseca9c536b02012-02-29 20:54:13 +0000631 print ' }'
José Fonseca632a78d2012-04-19 07:18:59 +0100632 print ' if (_checkBufferFlushingUnmapAPPLE) {'
José Fonseca9c536b02012-02-29 20:54:13 +0000633 print ' GLint flushing_unmap = GL_TRUE;'
José Fonseca632a78d2012-04-19 07:18:59 +0100634 print ' _glGetBufferParameteriv%s(target, GL_BUFFER_FLUSHING_UNMAP_APPLE, &flushing_unmap);' % suffix
José Fonseca9c536b02012-02-29 20:54:13 +0000635 print ' flush = flush && flushing_unmap;'
636 print ' }'
637 print ' if (flush && length > 0) {'
638 self.emit_memcpy('map', 'map', 'length')
639 print ' }'
640 print ' }'
641 print ' }'
José Fonsecacdc322c2012-02-29 19:29:51 +0000642 if function.name == 'glUnmapBufferOES':
643 print ' GLint access = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100644 print ' _glGetBufferParameteriv(target, GL_BUFFER_ACCESS_OES, &access);'
José Fonsecacdc322c2012-02-29 19:29:51 +0000645 print ' if (access == GL_WRITE_ONLY_OES) {'
646 print ' GLvoid *map = NULL;'
José Fonseca632a78d2012-04-19 07:18:59 +0100647 print ' _glGetBufferPointervOES(target, GL_BUFFER_MAP_POINTER_OES, &map);'
José Fonsecacdc322c2012-02-29 19:29:51 +0000648 print ' GLint size = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100649 print ' _glGetBufferParameteriv(target, GL_BUFFER_SIZE, &size);'
José Fonsecacdc322c2012-02-29 19:29:51 +0000650 print ' if (map && size > 0) {'
651 self.emit_memcpy('map', 'map', 'size')
José Fonseca219c9f22012-11-03 10:13:17 +0000652 self.shadowBufferMethod('bufferSubData(0, size, map)')
José Fonsecacdc322c2012-02-29 19:29:51 +0000653 print ' }'
José Fonseca867b1b72011-04-24 11:58:04 +0100654 print ' }'
José Fonsecafb3bd602012-01-15 13:56:28 +0000655 if function.name == 'glUnmapNamedBufferEXT':
José Fonseca024aff42012-02-29 18:00:06 +0000656 print ' GLint access_flags = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100657 print ' _glGetNamedBufferParameterivEXT(buffer, GL_BUFFER_ACCESS_FLAGS, &access_flags);'
José Fonseca024aff42012-02-29 18:00:06 +0000658 print ' if ((access_flags & GL_MAP_WRITE_BIT) && !(access_flags & GL_MAP_FLUSH_EXPLICIT_BIT)) {'
José Fonsecafb3bd602012-01-15 13:56:28 +0000659 print ' GLvoid *map = NULL;'
José Fonseca632a78d2012-04-19 07:18:59 +0100660 print ' _glGetNamedBufferPointervEXT(buffer, GL_BUFFER_MAP_POINTER, &map);'
José Fonsecafb3bd602012-01-15 13:56:28 +0000661 print ' GLint length = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100662 print ' _glGetNamedBufferParameterivEXT(buffer, GL_BUFFER_MAP_LENGTH, &length);'
José Fonseca024aff42012-02-29 18:00:06 +0000663 print ' if (map && length > 0) {'
José Fonsecafb3bd602012-01-15 13:56:28 +0000664 self.emit_memcpy('map', 'map', 'length')
José Fonseca024aff42012-02-29 18:00:06 +0000665 print ' }'
José Fonsecafb3bd602012-01-15 13:56:28 +0000666 print ' }'
José Fonseca77ef0ce2012-02-29 18:08:48 +0000667 if function.name == 'glFlushMappedBufferRange':
668 print ' GLvoid *map = NULL;'
José Fonseca632a78d2012-04-19 07:18:59 +0100669 print ' _glGetBufferPointerv(target, GL_BUFFER_MAP_POINTER, &map);'
José Fonseca77ef0ce2012-02-29 18:08:48 +0000670 print ' if (map && length > 0) {'
671 self.emit_memcpy('(char *)map + offset', '(const char *)map + offset', 'length')
672 print ' }'
673 if function.name == 'glFlushMappedBufferRangeAPPLE':
674 print ' GLvoid *map = NULL;'
José Fonseca632a78d2012-04-19 07:18:59 +0100675 print ' _glGetBufferPointerv(target, GL_BUFFER_MAP_POINTER, &map);'
José Fonseca77ef0ce2012-02-29 18:08:48 +0000676 print ' if (map && size > 0) {'
677 self.emit_memcpy('(char *)map + offset', '(const char *)map + offset', 'size')
José Fonseca73373602011-05-20 17:45:26 +0100678 print ' }'
José Fonsecafb3bd602012-01-15 13:56:28 +0000679 if function.name == 'glFlushMappedNamedBufferRangeEXT':
680 print ' GLvoid *map = NULL;'
José Fonseca632a78d2012-04-19 07:18:59 +0100681 print ' _glGetNamedBufferPointervEXT(buffer, GL_BUFFER_MAP_POINTER, &map);'
José Fonseca024aff42012-02-29 18:00:06 +0000682 print ' if (map && length > 0) {'
José Fonsecafb3bd602012-01-15 13:56:28 +0000683 self.emit_memcpy('(char *)map + offset', '(const char *)map + offset', 'length')
684 print ' }'
José Fonseca867b1b72011-04-24 11:58:04 +0100685
José Fonseca3522cbd2014-02-28 14:45:32 +0000686 # FIXME: We don't support coherent/pinned memory mappings
687 # See https://github.com/apitrace/apitrace/issues/232
688 if function.name in ('glBufferStorage', 'glNamedBufferStorageEXT'):
689 print r' if (flags & GL_MAP_COHERENT_BIT) {'
690 print r' os::log("apitrace: warning: coherent mappings not fully supported\n");'
691 print r' }'
692 if function.name in ('glBufferData', 'glBufferDataARB'):
693 print r' if (target == GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD) {'
694 print r' os::log("apitrace: warning: GL_AMD_pinned_memory not fully supported\n");'
695 print r' }'
696
José Fonseca91492d22011-05-23 21:20:31 +0100697 # Don't leave vertex attrib locations to chance. Instead emit fake
698 # glBindAttribLocation calls to ensure that the same locations will be
699 # used when retracing. Trying to remap locations after the fact would
700 # be an herculian task given that vertex attrib locations appear in
701 # many entry-points, including non-shader related ones.
702 if function.name == 'glLinkProgram':
José Fonseca54f304a2012-01-14 19:33:08 +0000703 Tracer.invokeFunction(self, function)
José Fonseca91492d22011-05-23 21:20:31 +0100704 print ' GLint active_attributes = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100705 print ' _glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &active_attributes);'
José Fonseca7525e6f2011-09-28 09:04:56 +0100706 print ' for (GLint attrib = 0; attrib < active_attributes; ++attrib) {'
José Fonseca91492d22011-05-23 21:20:31 +0100707 print ' GLint size = 0;'
708 print ' GLenum type = 0;'
709 print ' GLchar name[256];'
710 # TODO: Use ACTIVE_ATTRIBUTE_MAX_LENGTH instead of 256
José Fonseca632a78d2012-04-19 07:18:59 +0100711 print ' _glGetActiveAttrib(program, attrib, sizeof name, NULL, &size, &type, name);'
José Fonseca2a794f52011-05-26 20:54:29 +0100712 print " if (name[0] != 'g' || name[1] != 'l' || name[2] != '_') {"
José Fonseca632a78d2012-04-19 07:18:59 +0100713 print ' GLint location = _glGetAttribLocation(program, name);'
José Fonseca2a794f52011-05-26 20:54:29 +0100714 print ' if (location >= 0) {'
José Fonseca1b6c8752012-04-15 14:33:00 +0100715 bind_function = glapi.glapi.getFunctionByName('glBindAttribLocation')
José Fonseca91492d22011-05-23 21:20:31 +0100716 self.fake_call(bind_function, ['program', 'location', 'name'])
José Fonseca2a794f52011-05-26 20:54:29 +0100717 print ' }'
José Fonseca91492d22011-05-23 21:20:31 +0100718 print ' }'
719 print ' }'
720 if function.name == 'glLinkProgramARB':
José Fonseca54f304a2012-01-14 19:33:08 +0000721 Tracer.invokeFunction(self, function)
José Fonseca91492d22011-05-23 21:20:31 +0100722 print ' GLint active_attributes = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100723 print ' _glGetObjectParameterivARB(programObj, GL_OBJECT_ACTIVE_ATTRIBUTES_ARB, &active_attributes);'
José Fonseca7525e6f2011-09-28 09:04:56 +0100724 print ' for (GLint attrib = 0; attrib < active_attributes; ++attrib) {'
José Fonseca91492d22011-05-23 21:20:31 +0100725 print ' GLint size = 0;'
726 print ' GLenum type = 0;'
727 print ' GLcharARB name[256];'
728 # TODO: Use ACTIVE_ATTRIBUTE_MAX_LENGTH instead of 256
José Fonseca632a78d2012-04-19 07:18:59 +0100729 print ' _glGetActiveAttribARB(programObj, attrib, sizeof name, NULL, &size, &type, name);'
José Fonseca2a794f52011-05-26 20:54:29 +0100730 print " if (name[0] != 'g' || name[1] != 'l' || name[2] != '_') {"
José Fonseca632a78d2012-04-19 07:18:59 +0100731 print ' GLint location = _glGetAttribLocationARB(programObj, name);'
José Fonseca2a794f52011-05-26 20:54:29 +0100732 print ' if (location >= 0) {'
José Fonseca1b6c8752012-04-15 14:33:00 +0100733 bind_function = glapi.glapi.getFunctionByName('glBindAttribLocationARB')
José Fonseca91492d22011-05-23 21:20:31 +0100734 self.fake_call(bind_function, ['programObj', 'location', 'name'])
José Fonseca2a794f52011-05-26 20:54:29 +0100735 print ' }'
José Fonseca91492d22011-05-23 21:20:31 +0100736 print ' }'
737 print ' }'
738
Imre Deakd4937372012-04-24 14:06:48 +0300739 self.shadowBufferProlog(function)
740
José Fonseca54f304a2012-01-14 19:33:08 +0000741 Tracer.traceFunctionImplBody(self, function)
José Fonseca73373602011-05-20 17:45:26 +0100742
Peter Lohrmann0b5b75e2013-06-03 14:58:41 -0700743 # These entrypoints are only expected to be implemented by tools;
744 # drivers will probably not implement them.
José Fonsecaf028a8f2012-02-15 23:33:35 +0000745 marker_functions = [
746 # GL_GREMEDY_string_marker
José Fonseca8f34d342011-07-15 20:16:40 +0100747 'glStringMarkerGREMEDY',
José Fonsecaf028a8f2012-02-15 23:33:35 +0000748 # GL_GREMEDY_frame_terminator
José Fonseca8f34d342011-07-15 20:16:40 +0100749 'glFrameTerminatorGREMEDY',
José Fonsecaf028a8f2012-02-15 23:33:35 +0000750 # GL_EXT_debug_marker
751 'glInsertEventMarkerEXT',
752 'glPushGroupMarkerEXT',
753 'glPopGroupMarkerEXT',
José Fonseca8f34d342011-07-15 20:16:40 +0100754 ]
755
Peter Lohrmann0b5b75e2013-06-03 14:58:41 -0700756 # These entrypoints may be implemented by drivers, but are also very useful
757 # for debugging / analysis tools.
758 debug_functions = [
759 # GL_KHR_debug
760 'glDebugMessageControl',
761 'glDebugMessageInsert',
762 'glDebugMessageCallback',
763 'glGetDebugMessageLog',
764 'glPushDebugGroup',
765 'glPopDebugGroup',
766 'glObjectLabel',
767 'glGetObjectLabel',
768 'glObjectPtrLabel',
769 'glGetObjectPtrLabel',
770 # GL_ARB_debug_output
771 'glDebugMessageControlARB',
772 'glDebugMessageInsertARB',
773 'glDebugMessageCallbackARB',
774 'glGetDebugMessageLogARB',
775 # GL_AMD_debug_output
776 'glDebugMessageEnableAMD',
777 'glDebugMessageInsertAMD',
778 'glDebugMessageCallbackAMD',
779 'glGetDebugMessageLogAMD',
780 ]
781
José Fonseca54f304a2012-01-14 19:33:08 +0000782 def invokeFunction(self, function):
José Fonseca91492d22011-05-23 21:20:31 +0100783 if function.name in ('glLinkProgram', 'glLinkProgramARB'):
784 # These functions have been dispatched already
785 return
786
José Fonseca2cfa02c2013-06-10 08:05:29 +0100787 Tracer.invokeFunction(self, function)
788
789 def doInvokeFunction(self, function):
790 # Same as invokeFunction() but called both when trace is enabled or disabled.
791 #
792 # Used to modify the behavior of GL entry-points.
793
794 # Override GL extensions
795 if function.name in ('glGetString', 'glGetIntegerv', 'glGetStringi'):
796 Tracer.doInvokeFunction(self, function, prefix = 'gltrace::_', suffix = '_override')
797 return
798
José Fonsecaf028a8f2012-02-15 23:33:35 +0000799 # We implement GL_EXT_debug_marker, GL_GREMEDY_*, etc., and not the
800 # driver
801 if function.name in self.marker_functions:
José Fonseca8f34d342011-07-15 20:16:40 +0100802 return
803
Peter Lohrmann9d9eb812013-07-12 16:15:25 -0400804 # We may be faking KHR_debug, so ensure the pointer queries result is
805 # always zeroed to prevent dereference of unitialized pointers
806 if function.name == 'glGetPointerv':
807 print ' if (params &&'
808 print ' (pname == GL_DEBUG_CALLBACK_FUNCTION ||'
809 print ' pname == GL_DEBUG_CALLBACK_USER_PARAM)) {'
810 print ' *params = NULL;'
811 print ' }'
812
José Fonseca2cfa02c2013-06-10 08:05:29 +0100813 if function.name in self.getProcAddressFunctionNames:
José Fonsecaf028a8f2012-02-15 23:33:35 +0000814 else_ = ''
815 for marker_function in self.marker_functions:
José Fonseca1b6c8752012-04-15 14:33:00 +0100816 if self.api.getFunctionByName(marker_function):
José Fonsecaf028a8f2012-02-15 23:33:35 +0000817 print ' %sif (strcmp("%s", (const char *)%s) == 0) {' % (else_, marker_function, function.args[0].name)
José Fonseca632a78d2012-04-19 07:18:59 +0100818 print ' _result = (%s)&%s;' % (function.type, marker_function)
José Fonsecaf028a8f2012-02-15 23:33:35 +0000819 print ' }'
820 else_ = 'else '
821 print ' %s{' % else_
José Fonseca2cfa02c2013-06-10 08:05:29 +0100822 Tracer.doInvokeFunction(self, function)
823
824 # Replace function addresses with ours
825 # XXX: Doing this here instead of wrapRet means that the trace will
826 # contain the addresses of the wrapper functions, and not the real
827 # functions, but in practice this should make no difference.
828 if function.name in self.getProcAddressFunctionNames:
829 print ' _result = _wrapProcAddress(%s, _result);' % (function.args[0].name,)
830
José Fonseca8f34d342011-07-15 20:16:40 +0100831 print ' }'
José Fonseca1b3d3752011-07-15 10:15:19 +0100832 return
833
José Fonseca2cfa02c2013-06-10 08:05:29 +0100834 Tracer.doInvokeFunction(self, function)
José Fonseca91492d22011-05-23 21:20:31 +0100835
José Fonseca867b1b72011-04-24 11:58:04 +0100836 buffer_targets = [
837 'ARRAY_BUFFER',
838 'ELEMENT_ARRAY_BUFFER',
839 'PIXEL_PACK_BUFFER',
840 'PIXEL_UNPACK_BUFFER',
José Fonseca7b20d672012-01-10 19:13:58 +0000841 'UNIFORM_BUFFER',
842 'TEXTURE_BUFFER',
843 'TRANSFORM_FEEDBACK_BUFFER',
844 'COPY_READ_BUFFER',
845 'COPY_WRITE_BUFFER',
846 'DRAW_INDIRECT_BUFFER',
847 'ATOMIC_COUNTER_BUFFER',
José Fonseca867b1b72011-04-24 11:58:04 +0100848 ]
849
José Fonseca54f304a2012-01-14 19:33:08 +0000850 def wrapRet(self, function, instance):
851 Tracer.wrapRet(self, function, instance)
José Fonseca1b3d3752011-07-15 10:15:19 +0100852
José Fonsecacdc322c2012-02-29 19:29:51 +0000853 # Keep track of buffer mappings
854 if function.name in ('glMapBuffer', 'glMapBufferARB'):
José Fonseca867b1b72011-04-24 11:58:04 +0100855 print ' struct buffer_mapping *mapping = get_buffer_mapping(target);'
856 print ' if (mapping) {'
857 print ' mapping->map = %s;' % (instance)
858 print ' mapping->length = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100859 print ' _glGetBufferParameteriv(target, GL_BUFFER_SIZE, &mapping->length);'
José Fonseca867b1b72011-04-24 11:58:04 +0100860 print ' mapping->write = (access != GL_READ_ONLY);'
José Fonseca73373602011-05-20 17:45:26 +0100861 print ' mapping->explicit_flush = false;'
José Fonseca867b1b72011-04-24 11:58:04 +0100862 print ' }'
José Fonseca867b1b72011-04-24 11:58:04 +0100863 if function.name == 'glMapBufferRange':
José Fonseca9c536b02012-02-29 20:54:13 +0000864 print ' if (access & GL_MAP_WRITE_BIT) {'
José Fonseca632a78d2012-04-19 07:18:59 +0100865 print ' _checkBufferMapRange = true;'
José Fonseca9c536b02012-02-29 20:54:13 +0000866 print ' }'
José Fonseca867b1b72011-04-24 11:58:04 +0100867 print ' struct buffer_mapping *mapping = get_buffer_mapping(target);'
868 print ' if (mapping) {'
869 print ' mapping->map = %s;' % (instance)
870 print ' mapping->length = length;'
871 print ' mapping->write = access & GL_MAP_WRITE_BIT;'
José Fonseca73373602011-05-20 17:45:26 +0100872 print ' mapping->explicit_flush = access & GL_MAP_FLUSH_EXPLICIT_BIT;'
José Fonseca867b1b72011-04-24 11:58:04 +0100873 print ' }'
José Fonseca669b1222011-02-20 09:05:10 +0000874
José Fonsecac9f12232011-03-25 20:07:42 +0000875 boolean_names = [
876 'GL_FALSE',
877 'GL_TRUE',
878 ]
879
880 def gl_boolean(self, value):
881 return self.boolean_names[int(bool(value))]
882
José Fonsecac29f4f12011-06-11 12:19:05 +0100883 # Names of the functions that unpack from a pixel buffer object. See the
884 # ARB_pixel_buffer_object specification.
José Fonsecae97bab92011-06-02 23:15:11 +0100885 unpack_function_names = set([
886 'glBitmap',
José Fonsecac29f4f12011-06-11 12:19:05 +0100887 'glColorSubTable',
888 'glColorTable',
José Fonsecad2bd4ca2013-04-12 11:41:00 +0100889 'glCompressedMultiTexImage1DEXT',
890 'glCompressedMultiTexImage2DEXT',
891 'glCompressedMultiTexImage3DEXT',
892 'glCompressedMultiTexSubImage1DEXT',
893 'glCompressedMultiTexSubImage2DEXT',
894 'glCompressedMultiTexSubImage3DEXT',
José Fonsecac29f4f12011-06-11 12:19:05 +0100895 'glCompressedTexImage1D',
idinevdb5ad3b2014-02-03 15:50:39 +0000896 'glCompressedTexImage1DARB',
José Fonsecac29f4f12011-06-11 12:19:05 +0100897 'glCompressedTexImage2D',
idinevdb5ad3b2014-02-03 15:50:39 +0000898 'glCompressedTexImage2DARB',
José Fonsecac29f4f12011-06-11 12:19:05 +0100899 'glCompressedTexImage3D',
idinevdb5ad3b2014-02-03 15:50:39 +0000900 'glCompressedTexImage3DARB',
José Fonsecac29f4f12011-06-11 12:19:05 +0100901 'glCompressedTexSubImage1D',
idinevdb5ad3b2014-02-03 15:50:39 +0000902 'glCompressedTexSubImage1DARB',
José Fonsecac29f4f12011-06-11 12:19:05 +0100903 'glCompressedTexSubImage2D',
idinevdb5ad3b2014-02-03 15:50:39 +0000904 'glCompressedTexSubImage2DARB',
José Fonsecac29f4f12011-06-11 12:19:05 +0100905 'glCompressedTexSubImage3D',
idinevdb5ad3b2014-02-03 15:50:39 +0000906 'glCompressedTexSubImage3DARB',
José Fonsecad2bd4ca2013-04-12 11:41:00 +0100907 'glCompressedTextureImage1DEXT',
908 'glCompressedTextureImage2DEXT',
909 'glCompressedTextureImage3DEXT',
910 'glCompressedTextureSubImage1DEXT',
911 'glCompressedTextureSubImage2DEXT',
912 'glCompressedTextureSubImage3DEXT',
José Fonsecac29f4f12011-06-11 12:19:05 +0100913 'glConvolutionFilter1D',
914 'glConvolutionFilter2D',
José Fonsecae97bab92011-06-02 23:15:11 +0100915 'glDrawPixels',
916 'glMultiTexImage1DEXT',
917 'glMultiTexImage2DEXT',
918 'glMultiTexImage3DEXT',
919 'glMultiTexSubImage1DEXT',
920 'glMultiTexSubImage2DEXT',
921 'glMultiTexSubImage3DEXT',
José Fonsecac29f4f12011-06-11 12:19:05 +0100922 'glPixelMapfv',
923 'glPixelMapuiv',
924 'glPixelMapusv',
José Fonsecae97bab92011-06-02 23:15:11 +0100925 'glPolygonStipple',
José Fonsecac29f4f12011-06-11 12:19:05 +0100926 'glSeparableFilter2D',
José Fonsecae97bab92011-06-02 23:15:11 +0100927 'glTexImage1D',
928 'glTexImage1DEXT',
929 'glTexImage2D',
930 'glTexImage2DEXT',
931 'glTexImage3D',
932 'glTexImage3DEXT',
933 'glTexSubImage1D',
934 'glTexSubImage1DEXT',
935 'glTexSubImage2D',
936 'glTexSubImage2DEXT',
937 'glTexSubImage3D',
938 'glTexSubImage3DEXT',
939 'glTextureImage1DEXT',
940 'glTextureImage2DEXT',
941 'glTextureImage3DEXT',
942 'glTextureSubImage1DEXT',
943 'glTextureSubImage2DEXT',
944 'glTextureSubImage3DEXT',
945 ])
946
José Fonseca54f304a2012-01-14 19:33:08 +0000947 def serializeArgValue(self, function, arg):
José Fonsecae97bab92011-06-02 23:15:11 +0100948 # Recognize offsets instead of blobs when a PBO is bound
949 if function.name in self.unpack_function_names \
950 and (isinstance(arg.type, stdapi.Blob) \
951 or (isinstance(arg.type, stdapi.Const) \
952 and isinstance(arg.type.type, stdapi.Blob))):
José Fonsecac29f4f12011-06-11 12:19:05 +0100953 print ' {'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000954 print ' gltrace::Context *ctx = gltrace::getContext();'
José Fonseca632a78d2012-04-19 07:18:59 +0100955 print ' GLint _unpack_buffer = 0;'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000956 print ' if (ctx->profile == gltrace::PROFILE_COMPAT)'
José Fonseca632a78d2012-04-19 07:18:59 +0100957 print ' _glGetIntegerv(GL_PIXEL_UNPACK_BUFFER_BINDING, &_unpack_buffer);'
958 print ' if (_unpack_buffer) {'
José Fonsecad559f022012-04-15 16:13:51 +0100959 print ' trace::localWriter.writePointer((uintptr_t)%s);' % arg.name
José Fonsecac29f4f12011-06-11 12:19:05 +0100960 print ' } else {'
José Fonseca54f304a2012-01-14 19:33:08 +0000961 Tracer.serializeArgValue(self, function, arg)
José Fonsecac29f4f12011-06-11 12:19:05 +0100962 print ' }'
José Fonsecae97bab92011-06-02 23:15:11 +0100963 print ' }'
964 return
965
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100966 # Several GL state functions take GLenum symbolic names as
967 # integer/floats; so dump the symbolic name whenever possible
José Fonseca3bcb33c2011-05-27 20:14:31 +0100968 if function.name.startswith('gl') \
José Fonsecae3571092011-10-13 08:26:27 +0100969 and arg.type in (glapi.GLint, glapi.GLfloat, glapi.GLdouble) \
José Fonseca3bcb33c2011-05-27 20:14:31 +0100970 and arg.name == 'param':
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100971 assert arg.index > 0
972 assert function.args[arg.index - 1].name == 'pname'
973 assert function.args[arg.index - 1].type == glapi.GLenum
974 print ' if (is_symbolic_pname(pname) && is_symbolic_param(%s)) {' % arg.name
José Fonseca54f304a2012-01-14 19:33:08 +0000975 self.serializeValue(glapi.GLenum, arg.name)
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100976 print ' } else {'
José Fonseca54f304a2012-01-14 19:33:08 +0000977 Tracer.serializeArgValue(self, function, arg)
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100978 print ' }'
979 return
980
José Fonseca54f304a2012-01-14 19:33:08 +0000981 Tracer.serializeArgValue(self, function, arg)
José Fonseca99221832011-03-22 22:15:46 +0000982
José Fonseca4c938c22011-04-30 22:44:38 +0100983 def footer(self, api):
984 Tracer.footer(self, api)
José Fonseca669b1222011-02-20 09:05:10 +0000985
José Fonseca4c938c22011-04-30 22:44:38 +0100986 # A simple state tracker to track the pointer values
José Fonseca669b1222011-02-20 09:05:10 +0000987 # update the state
José Fonseca14cb9ef2012-05-17 21:33:14 +0100988 print 'static void _trace_user_arrays(GLuint count)'
José Fonseca669b1222011-02-20 09:05:10 +0000989 print '{'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000990 print ' gltrace::Context *ctx = gltrace::getContext();'
José Fonseca8d1408b2014-02-03 19:57:18 +0000991 print
992
993 # Temporarily unbind the array buffer
José Fonseca26be8f92014-03-07 14:08:50 +0000994 print ' GLint _array_buffer = _glGetInteger(GL_ARRAY_BUFFER_BINDING);'
José Fonseca8d1408b2014-02-03 19:57:18 +0000995 print ' if (_array_buffer) {'
996 self.fake_glBindBuffer(api, 'GL_ARRAY_BUFFER', '0')
997 print ' }'
998 print
José Fonseca1a2fdd22011-04-01 00:55:09 +0100999
José Fonseca99221832011-03-22 22:15:46 +00001000 for camelcase_name, uppercase_name in self.arrays:
Chia-I Wub3d218d2011-11-03 01:37:36 +08001001 # in which profile is the array available?
José Fonsecaf028a8f2012-02-15 23:33:35 +00001002 profile_check = 'ctx->profile == gltrace::PROFILE_COMPAT'
Chia-I Wub3d218d2011-11-03 01:37:36 +08001003 if camelcase_name in self.arrays_es1:
José Fonsecaf028a8f2012-02-15 23:33:35 +00001004 profile_check = '(' + profile_check + ' || ctx->profile == gltrace::PROFILE_ES1)';
Chia-I Wub3d218d2011-11-03 01:37:36 +08001005
José Fonseca99221832011-03-22 22:15:46 +00001006 function_name = 'gl%sPointer' % camelcase_name
1007 enable_name = 'GL_%s_ARRAY' % uppercase_name
1008 binding_name = 'GL_%s_ARRAY_BUFFER_BINDING' % uppercase_name
José Fonseca1b6c8752012-04-15 14:33:00 +01001009 function = api.getFunctionByName(function_name)
José Fonseca99221832011-03-22 22:15:46 +00001010
José Fonseca06e85192011-10-16 14:15:36 +01001011 print ' // %s' % function.prototype()
Chia-I Wub3d218d2011-11-03 01:37:36 +08001012 print ' if (%s) {' % profile_check
José Fonsecafb6744f2011-04-15 11:18:37 +01001013 self.array_trace_prolog(api, uppercase_name)
1014 self.array_prolog(api, uppercase_name)
José Fonseca632a78d2012-04-19 07:18:59 +01001015 print ' if (_glIsEnabled(%s)) {' % enable_name
José Fonseca26be8f92014-03-07 14:08:50 +00001016 print ' GLint _binding = _glGetInteger(%s);' % binding_name
José Fonseca632a78d2012-04-19 07:18:59 +01001017 print ' if (!_binding) {'
José Fonseca99221832011-03-22 22:15:46 +00001018
1019 # Get the arguments via glGet*
1020 for arg in function.args:
1021 arg_get_enum = 'GL_%s_ARRAY_%s' % (uppercase_name, arg.name.upper())
1022 arg_get_function, arg_type = TypeGetter().visit(arg.type)
José Fonseca7f5163e2011-03-31 23:37:26 +01001023 print ' %s %s = 0;' % (arg_type, arg.name)
José Fonseca632a78d2012-04-19 07:18:59 +01001024 print ' _%s(%s, &%s);' % (arg_get_function, arg_get_enum, arg.name)
José Fonseca99221832011-03-22 22:15:46 +00001025
1026 arg_names = ', '.join([arg.name for arg in function.args[:-1]])
José Fonseca14cb9ef2012-05-17 21:33:14 +01001027 print ' size_t _size = _%s_size(%s, count);' % (function.name, arg_names)
José Fonseca99221832011-03-22 22:15:46 +00001028
1029 # Emit a fake function
José Fonsecafb6744f2011-04-15 11:18:37 +01001030 self.array_trace_intermezzo(api, uppercase_name)
José Fonseca632a78d2012-04-19 07:18:59 +01001031 print ' unsigned _call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,)
José Fonseca669b1222011-02-20 09:05:10 +00001032 for arg in function.args:
1033 assert not arg.output
José Fonsecab4a3d142011-10-27 07:43:19 +01001034 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
José Fonseca14c21bc2011-02-20 23:32:22 +00001035 if arg.name != 'pointer':
José Fonseca54f304a2012-01-14 19:33:08 +00001036 self.serializeValue(arg.type, arg.name)
José Fonseca14c21bc2011-02-20 23:32:22 +00001037 else:
José Fonseca632a78d2012-04-19 07:18:59 +01001038 print ' trace::localWriter.writeBlob((const void *)%s, _size);' % (arg.name)
José Fonsecab4a3d142011-10-27 07:43:19 +01001039 print ' trace::localWriter.endArg();'
José Fonseca99221832011-03-22 22:15:46 +00001040
José Fonsecab4a3d142011-10-27 07:43:19 +01001041 print ' trace::localWriter.endEnter();'
José Fonseca632a78d2012-04-19 07:18:59 +01001042 print ' trace::localWriter.beginLeave(_call);'
José Fonsecab4a3d142011-10-27 07:43:19 +01001043 print ' trace::localWriter.endLeave();'
José Fonseca99221832011-03-22 22:15:46 +00001044 print ' }'
José Fonseca669b1222011-02-20 09:05:10 +00001045 print ' }'
José Fonsecafb6744f2011-04-15 11:18:37 +01001046 self.array_epilog(api, uppercase_name)
1047 self.array_trace_epilog(api, uppercase_name)
Chia-I Wub3d218d2011-11-03 01:37:36 +08001048 print ' }'
José Fonseca99221832011-03-22 22:15:46 +00001049 print
José Fonseca1a2fdd22011-04-01 00:55:09 +01001050
José Fonseca1601c412011-05-10 10:38:19 +01001051 # Samething, but for glVertexAttribPointer*
1052 #
1053 # Some variants of glVertexAttribPointer alias conventional and generic attributes:
1054 # - glVertexAttribPointer: no
1055 # - glVertexAttribPointerARB: implementation dependent
1056 # - glVertexAttribPointerNV: yes
1057 #
1058 # This means that the implementations of these functions do not always
1059 # alias, and they need to be considered independently.
1060 #
Chia-I Wub3d218d2011-11-03 01:37:36 +08001061 print ' // ES1 does not support generic vertex attributes'
José Fonsecaf028a8f2012-02-15 23:33:35 +00001062 print ' if (ctx->profile == gltrace::PROFILE_ES1)'
Chia-I Wub3d218d2011-11-03 01:37:36 +08001063 print ' return;'
1064 print
José Fonseca632a78d2012-04-19 07:18:59 +01001065 print ' vertex_attrib _vertex_attrib = _get_vertex_attrib();'
José Fonseca5a568a92011-06-29 16:43:36 +01001066 print
1067 for suffix in ['', 'ARB', 'NV']:
1068 if suffix:
José Fonsecad94aaac2011-06-28 20:50:49 +01001069 SUFFIX = '_' + suffix
José Fonsecad94aaac2011-06-28 20:50:49 +01001070 else:
José Fonseca5a568a92011-06-29 16:43:36 +01001071 SUFFIX = suffix
José Fonseca1601c412011-05-10 10:38:19 +01001072 function_name = 'glVertexAttribPointer' + suffix
José Fonseca1b6c8752012-04-15 14:33:00 +01001073 function = api.getFunctionByName(function_name)
José Fonseca06e85192011-10-16 14:15:36 +01001074
1075 print ' // %s' % function.prototype()
José Fonseca632a78d2012-04-19 07:18:59 +01001076 print ' if (_vertex_attrib == VERTEX_ATTRIB%s) {' % SUFFIX
José Fonseca5a568a92011-06-29 16:43:36 +01001077 if suffix == 'NV':
José Fonseca632a78d2012-04-19 07:18:59 +01001078 print ' GLint _max_vertex_attribs = 16;'
José Fonseca5a568a92011-06-29 16:43:36 +01001079 else:
José Fonseca26be8f92014-03-07 14:08:50 +00001080 print ' GLint _max_vertex_attribs = _glGetInteger(GL_MAX_VERTEX_ATTRIBS);'
José Fonseca632a78d2012-04-19 07:18:59 +01001081 print ' for (GLint index = 0; index < _max_vertex_attribs; ++index) {'
1082 print ' GLint _enabled = 0;'
José Fonseca5a568a92011-06-29 16:43:36 +01001083 if suffix == 'NV':
José Fonseca632a78d2012-04-19 07:18:59 +01001084 print ' _glGetIntegerv(GL_VERTEX_ATTRIB_ARRAY0_NV + index, &_enabled);'
José Fonseca5a568a92011-06-29 16:43:36 +01001085 else:
José Fonseca632a78d2012-04-19 07:18:59 +01001086 print ' _glGetVertexAttribiv%s(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED%s, &_enabled);' % (suffix, SUFFIX)
1087 print ' if (_enabled) {'
1088 print ' GLint _binding = 0;'
José Fonseca5a568a92011-06-29 16:43:36 +01001089 if suffix != 'NV':
1090 # It doesn't seem possible to use VBOs with NV_vertex_program.
José Fonseca632a78d2012-04-19 07:18:59 +01001091 print ' _glGetVertexAttribiv%s(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING%s, &_binding);' % (suffix, SUFFIX)
1092 print ' if (!_binding) {'
José Fonseca1a2fdd22011-04-01 00:55:09 +01001093
José Fonseca1601c412011-05-10 10:38:19 +01001094 # Get the arguments via glGet*
1095 for arg in function.args[1:]:
José Fonseca5a568a92011-06-29 16:43:36 +01001096 if suffix == 'NV':
1097 arg_get_enum = 'GL_ATTRIB_ARRAY_%s%s' % (arg.name.upper(), SUFFIX)
1098 else:
1099 arg_get_enum = 'GL_VERTEX_ATTRIB_ARRAY_%s%s' % (arg.name.upper(), SUFFIX)
José Fonsecac493e3e2011-06-29 12:57:06 +01001100 arg_get_function, arg_type = TypeGetter('glGetVertexAttrib', False, suffix).visit(arg.type)
José Fonseca5a568a92011-06-29 16:43:36 +01001101 print ' %s %s = 0;' % (arg_type, arg.name)
José Fonseca632a78d2012-04-19 07:18:59 +01001102 print ' _%s(index, %s, &%s);' % (arg_get_function, arg_get_enum, arg.name)
José Fonseca1601c412011-05-10 10:38:19 +01001103
1104 arg_names = ', '.join([arg.name for arg in function.args[1:-1]])
José Fonseca14cb9ef2012-05-17 21:33:14 +01001105 print ' size_t _size = _%s_size(%s, count);' % (function.name, arg_names)
José Fonseca1a2fdd22011-04-01 00:55:09 +01001106
José Fonseca1601c412011-05-10 10:38:19 +01001107 # Emit a fake function
José Fonseca632a78d2012-04-19 07:18:59 +01001108 print ' unsigned _call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,)
José Fonseca1601c412011-05-10 10:38:19 +01001109 for arg in function.args:
1110 assert not arg.output
José Fonsecab4a3d142011-10-27 07:43:19 +01001111 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
José Fonseca1601c412011-05-10 10:38:19 +01001112 if arg.name != 'pointer':
José Fonseca54f304a2012-01-14 19:33:08 +00001113 self.serializeValue(arg.type, arg.name)
José Fonseca1601c412011-05-10 10:38:19 +01001114 else:
José Fonseca632a78d2012-04-19 07:18:59 +01001115 print ' trace::localWriter.writeBlob((const void *)%s, _size);' % (arg.name)
José Fonsecab4a3d142011-10-27 07:43:19 +01001116 print ' trace::localWriter.endArg();'
José Fonseca1601c412011-05-10 10:38:19 +01001117
José Fonsecab4a3d142011-10-27 07:43:19 +01001118 print ' trace::localWriter.endEnter();'
José Fonseca632a78d2012-04-19 07:18:59 +01001119 print ' trace::localWriter.beginLeave(_call);'
José Fonsecab4a3d142011-10-27 07:43:19 +01001120 print ' trace::localWriter.endLeave();'
José Fonseca1601c412011-05-10 10:38:19 +01001121 print ' }'
1122 print ' }'
1123 print ' }'
1124 print ' }'
1125 print
José Fonseca1a2fdd22011-04-01 00:55:09 +01001126
José Fonseca8d1408b2014-02-03 19:57:18 +00001127 # Restore the original array_buffer
1128 print ' if (_array_buffer) {'
1129 self.fake_glBindBuffer(api, 'GL_ARRAY_BUFFER', '_array_buffer')
1130 print ' }'
1131 print
1132
José Fonseca669b1222011-02-20 09:05:10 +00001133 print '}'
1134 print
1135
José Fonsecafb6744f2011-04-15 11:18:37 +01001136 #
1137 # Hooks for glTexCoordPointer, which is identical to the other array
1138 # pointers except the fact that it is indexed by glClientActiveTexture.
1139 #
1140
1141 def array_prolog(self, api, uppercase_name):
1142 if uppercase_name == 'TEXTURE_COORD':
José Fonseca26be8f92014-03-07 14:08:50 +00001143 print ' GLint client_active_texture = _glGetInteger(GL_CLIENT_ACTIVE_TEXTURE);'
José Fonsecafb6744f2011-04-15 11:18:37 +01001144 print ' GLint max_texture_coords = 0;'
José Fonsecaf028a8f2012-02-15 23:33:35 +00001145 print ' if (ctx->profile == gltrace::PROFILE_COMPAT)'
José Fonseca632a78d2012-04-19 07:18:59 +01001146 print ' _glGetIntegerv(GL_MAX_TEXTURE_COORDS, &max_texture_coords);'
Chia-I Wub3d218d2011-11-03 01:37:36 +08001147 print ' else'
José Fonseca632a78d2012-04-19 07:18:59 +01001148 print ' _glGetIntegerv(GL_MAX_TEXTURE_UNITS, &max_texture_coords);'
José Fonsecafb6744f2011-04-15 11:18:37 +01001149 print ' for (GLint unit = 0; unit < max_texture_coords; ++unit) {'
José Fonseca7525e6f2011-09-28 09:04:56 +01001150 print ' GLint texture = GL_TEXTURE0 + unit;'
José Fonseca632a78d2012-04-19 07:18:59 +01001151 print ' _glClientActiveTexture(texture);'
José Fonsecafb6744f2011-04-15 11:18:37 +01001152
1153 def array_trace_prolog(self, api, uppercase_name):
1154 if uppercase_name == 'TEXTURE_COORD':
1155 print ' bool client_active_texture_dirty = false;'
1156
1157 def array_epilog(self, api, uppercase_name):
1158 if uppercase_name == 'TEXTURE_COORD':
1159 print ' }'
1160 self.array_cleanup(api, uppercase_name)
1161
1162 def array_cleanup(self, api, uppercase_name):
1163 if uppercase_name == 'TEXTURE_COORD':
José Fonseca632a78d2012-04-19 07:18:59 +01001164 print ' _glClientActiveTexture(client_active_texture);'
José Fonsecafb6744f2011-04-15 11:18:37 +01001165
1166 def array_trace_intermezzo(self, api, uppercase_name):
1167 if uppercase_name == 'TEXTURE_COORD':
1168 print ' if (texture != client_active_texture || client_active_texture_dirty) {'
1169 print ' client_active_texture_dirty = true;'
1170 self.fake_glClientActiveTexture_call(api, "texture");
1171 print ' }'
1172
1173 def array_trace_epilog(self, api, uppercase_name):
1174 if uppercase_name == 'TEXTURE_COORD':
1175 print ' if (client_active_texture_dirty) {'
1176 self.fake_glClientActiveTexture_call(api, "client_active_texture");
1177 print ' }'
1178
José Fonseca8d1408b2014-02-03 19:57:18 +00001179 def fake_glBindBuffer(self, api, target, buffer):
1180 function = api.getFunctionByName('glBindBuffer')
1181 self.fake_call(function, [target, buffer])
1182
José Fonsecafb6744f2011-04-15 11:18:37 +01001183 def fake_glClientActiveTexture_call(self, api, texture):
José Fonseca1b6c8752012-04-15 14:33:00 +01001184 function = api.getFunctionByName('glClientActiveTexture')
José Fonsecafb6744f2011-04-15 11:18:37 +01001185 self.fake_call(function, [texture])
1186
José Fonseca151c3702013-05-10 08:28:15 +01001187 def emitFakeTexture2D(self):
1188 function = glapi.glapi.getFunctionByName('glTexImage2D')
1189 instances = function.argNames()
1190 print ' unsigned _fake_call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,)
1191 for arg in function.args:
1192 assert not arg.output
1193 self.serializeArg(function, arg)
1194 print ' trace::localWriter.endEnter();'
1195 print ' trace::localWriter.beginLeave(_fake_call);'
1196 print ' trace::localWriter.endLeave();'
José Fonsecafb6744f2011-04-15 11:18:37 +01001197
1198
1199
1200
1201
José Fonseca669b1222011-02-20 09:05:10 +00001202
1203
1204
1205
1206
1207