blob: 81375f7bc25d9f54dfe5b1cfe34c65883c2fe33b [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é Fonseca99221832011-03-22 22:15:46 +0000543 print ' return;'
544 print ' }'
José Fonseca14c21bc2011-02-20 23:32:22 +0000545
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000546 # ... to the draw calls
José Fonseca99221832011-03-22 22:15:46 +0000547 if function.name in self.draw_function_names:
José Fonseca632a78d2012-04-19 07:18:59 +0100548 print ' if (_need_user_arrays()) {'
José Fonseca99221832011-03-22 22:15:46 +0000549 arg_names = ', '.join([arg.name for arg in function.args[1:]])
José Fonseca14cb9ef2012-05-17 21:33:14 +0100550 print ' GLuint _count = _%s_count(%s);' % (function.name, arg_names)
José Fonseca707630d2014-03-07 14:20:35 +0000551 # Some apps, in particular Quake3, can tell the driver to lock more
552 # vertices than those actually required for the draw call.
553 print ' if (_checkLockArraysEXT) {'
554 print ' GLuint _locked_count = _glGetInteger(GL_ARRAY_ELEMENT_LOCK_FIRST_EXT)'
555 print ' + _glGetInteger(GL_ARRAY_ELEMENT_LOCK_COUNT_EXT);'
556 print ' _count = std::max(_count, _locked_count);'
557 print ' }'
José Fonseca14cb9ef2012-05-17 21:33:14 +0100558 print ' _trace_user_arrays(_count);'
José Fonseca8a6c6cb2011-03-23 16:44:30 +0000559 print ' }'
José Fonseca707630d2014-03-07 14:20:35 +0000560 if function.name == 'glLockArraysEXT':
561 print ' _checkLockArraysEXT = true;'
José Fonseca14c21bc2011-02-20 23:32:22 +0000562
José Fonseca73373602011-05-20 17:45:26 +0100563 # Emit a fake memcpy on buffer uploads
José Fonseca9c536b02012-02-29 20:54:13 +0000564 if function.name == 'glBufferParameteriAPPLE':
565 print ' if (pname == GL_BUFFER_FLUSHING_UNMAP_APPLE && param == GL_FALSE) {'
José Fonseca632a78d2012-04-19 07:18:59 +0100566 print ' _checkBufferFlushingUnmapAPPLE = true;'
José Fonseca9c536b02012-02-29 20:54:13 +0000567 print ' }'
José Fonsecacdc322c2012-02-29 19:29:51 +0000568 if function.name in ('glUnmapBuffer', 'glUnmapBufferARB'):
José Fonseca9c536b02012-02-29 20:54:13 +0000569 if function.name.endswith('ARB'):
570 suffix = 'ARB'
571 else:
572 suffix = ''
573 print ' GLint access = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100574 print ' _glGetBufferParameteriv%s(target, GL_BUFFER_ACCESS, &access);' % suffix
José Fonseca9c536b02012-02-29 20:54:13 +0000575 print ' if (access != GL_READ_ONLY) {'
576 print ' GLvoid *map = NULL;'
José Fonseca632a78d2012-04-19 07:18:59 +0100577 print ' _glGetBufferPointerv%s(target, GL_BUFFER_MAP_POINTER, &map);' % suffix
José Fonseca9c536b02012-02-29 20:54:13 +0000578 print ' if (map) {'
579 print ' GLint length = -1;'
580 print ' bool flush = true;'
José Fonseca632a78d2012-04-19 07:18:59 +0100581 print ' if (_checkBufferMapRange) {'
582 print ' _glGetBufferParameteriv%s(target, GL_BUFFER_MAP_LENGTH, &length);' % suffix
José Fonseca9c536b02012-02-29 20:54:13 +0000583 print ' GLint access_flags = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100584 print ' _glGetBufferParameteriv(target, GL_BUFFER_ACCESS_FLAGS, &access_flags);'
José Fonseca9c536b02012-02-29 20:54:13 +0000585 print ' flush = flush && !(access_flags & GL_MAP_FLUSH_EXPLICIT_BIT);'
586 print ' if (length == -1) {'
José Fonsecacb07e2d2014-02-04 15:14:09 +0000587 print ' // Mesa drivers refuse GL_BUFFER_MAP_LENGTH without GL 3.0 up-to'
588 print ' // http://cgit.freedesktop.org/mesa/mesa/commit/?id=ffee498fb848b253a7833373fe5430f8c7ca0c5f'
José Fonsecadb1ccce2012-02-29 21:09:24 +0000589 print ' static bool warned = false;'
590 print ' if (!warned) {'
591 print ' os::log("apitrace: warning: glGetBufferParameteriv%s(GL_BUFFER_MAP_LENGTH) failed\\n");' % suffix
592 print ' warned = true;'
593 print ' }'
José Fonseca9c536b02012-02-29 20:54:13 +0000594 print ' struct buffer_mapping *mapping = get_buffer_mapping(target);'
595 print ' if (mapping) {'
596 print ' length = mapping->length;'
597 print ' flush = flush && !mapping->explicit_flush;'
598 print ' } else {'
599 print ' length = 0;'
600 print ' flush = false;'
601 print ' }'
602 print ' }'
603 print ' } else {'
604 print ' length = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100605 print ' _glGetBufferParameteriv%s(target, GL_BUFFER_SIZE, &length);' % suffix
José Fonseca9c536b02012-02-29 20:54:13 +0000606 print ' }'
José Fonseca632a78d2012-04-19 07:18:59 +0100607 print ' if (_checkBufferFlushingUnmapAPPLE) {'
José Fonseca9c536b02012-02-29 20:54:13 +0000608 print ' GLint flushing_unmap = GL_TRUE;'
José Fonseca632a78d2012-04-19 07:18:59 +0100609 print ' _glGetBufferParameteriv%s(target, GL_BUFFER_FLUSHING_UNMAP_APPLE, &flushing_unmap);' % suffix
José Fonseca9c536b02012-02-29 20:54:13 +0000610 print ' flush = flush && flushing_unmap;'
611 print ' }'
612 print ' if (flush && length > 0) {'
613 self.emit_memcpy('map', 'map', 'length')
614 print ' }'
615 print ' }'
616 print ' }'
José Fonsecacdc322c2012-02-29 19:29:51 +0000617 if function.name == 'glUnmapBufferOES':
618 print ' GLint access = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100619 print ' _glGetBufferParameteriv(target, GL_BUFFER_ACCESS_OES, &access);'
José Fonsecacdc322c2012-02-29 19:29:51 +0000620 print ' if (access == GL_WRITE_ONLY_OES) {'
621 print ' GLvoid *map = NULL;'
José Fonseca632a78d2012-04-19 07:18:59 +0100622 print ' _glGetBufferPointervOES(target, GL_BUFFER_MAP_POINTER_OES, &map);'
José Fonsecacdc322c2012-02-29 19:29:51 +0000623 print ' GLint size = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100624 print ' _glGetBufferParameteriv(target, GL_BUFFER_SIZE, &size);'
José Fonsecacdc322c2012-02-29 19:29:51 +0000625 print ' if (map && size > 0) {'
626 self.emit_memcpy('map', 'map', 'size')
José Fonseca219c9f22012-11-03 10:13:17 +0000627 self.shadowBufferMethod('bufferSubData(0, size, map)')
José Fonsecacdc322c2012-02-29 19:29:51 +0000628 print ' }'
José Fonseca867b1b72011-04-24 11:58:04 +0100629 print ' }'
José Fonsecafb3bd602012-01-15 13:56:28 +0000630 if function.name == 'glUnmapNamedBufferEXT':
José Fonseca024aff42012-02-29 18:00:06 +0000631 print ' GLint access_flags = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100632 print ' _glGetNamedBufferParameterivEXT(buffer, GL_BUFFER_ACCESS_FLAGS, &access_flags);'
José Fonseca024aff42012-02-29 18:00:06 +0000633 print ' if ((access_flags & GL_MAP_WRITE_BIT) && !(access_flags & GL_MAP_FLUSH_EXPLICIT_BIT)) {'
José Fonsecafb3bd602012-01-15 13:56:28 +0000634 print ' GLvoid *map = NULL;'
José Fonseca632a78d2012-04-19 07:18:59 +0100635 print ' _glGetNamedBufferPointervEXT(buffer, GL_BUFFER_MAP_POINTER, &map);'
José Fonsecafb3bd602012-01-15 13:56:28 +0000636 print ' GLint length = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100637 print ' _glGetNamedBufferParameterivEXT(buffer, GL_BUFFER_MAP_LENGTH, &length);'
José Fonseca024aff42012-02-29 18:00:06 +0000638 print ' if (map && length > 0) {'
José Fonsecafb3bd602012-01-15 13:56:28 +0000639 self.emit_memcpy('map', 'map', 'length')
José Fonseca024aff42012-02-29 18:00:06 +0000640 print ' }'
José Fonsecafb3bd602012-01-15 13:56:28 +0000641 print ' }'
José Fonseca77ef0ce2012-02-29 18:08:48 +0000642 if function.name == 'glFlushMappedBufferRange':
643 print ' GLvoid *map = NULL;'
José Fonseca632a78d2012-04-19 07:18:59 +0100644 print ' _glGetBufferPointerv(target, GL_BUFFER_MAP_POINTER, &map);'
José Fonseca77ef0ce2012-02-29 18:08:48 +0000645 print ' if (map && length > 0) {'
646 self.emit_memcpy('(char *)map + offset', '(const char *)map + offset', 'length')
647 print ' }'
648 if function.name == 'glFlushMappedBufferRangeAPPLE':
649 print ' GLvoid *map = NULL;'
José Fonseca632a78d2012-04-19 07:18:59 +0100650 print ' _glGetBufferPointerv(target, GL_BUFFER_MAP_POINTER, &map);'
José Fonseca77ef0ce2012-02-29 18:08:48 +0000651 print ' if (map && size > 0) {'
652 self.emit_memcpy('(char *)map + offset', '(const char *)map + offset', 'size')
José Fonseca73373602011-05-20 17:45:26 +0100653 print ' }'
José Fonsecafb3bd602012-01-15 13:56:28 +0000654 if function.name == 'glFlushMappedNamedBufferRangeEXT':
655 print ' GLvoid *map = NULL;'
José Fonseca632a78d2012-04-19 07:18:59 +0100656 print ' _glGetNamedBufferPointervEXT(buffer, GL_BUFFER_MAP_POINTER, &map);'
José Fonseca024aff42012-02-29 18:00:06 +0000657 print ' if (map && length > 0) {'
José Fonsecafb3bd602012-01-15 13:56:28 +0000658 self.emit_memcpy('(char *)map + offset', '(const char *)map + offset', 'length')
659 print ' }'
José Fonseca867b1b72011-04-24 11:58:04 +0100660
José Fonseca3522cbd2014-02-28 14:45:32 +0000661 # FIXME: We don't support coherent/pinned memory mappings
662 # See https://github.com/apitrace/apitrace/issues/232
663 if function.name in ('glBufferStorage', 'glNamedBufferStorageEXT'):
664 print r' if (flags & GL_MAP_COHERENT_BIT) {'
665 print r' os::log("apitrace: warning: coherent mappings not fully supported\n");'
666 print r' }'
667 if function.name in ('glBufferData', 'glBufferDataARB'):
668 print r' if (target == GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD) {'
669 print r' os::log("apitrace: warning: GL_AMD_pinned_memory not fully supported\n");'
670 print r' }'
671
José Fonseca91492d22011-05-23 21:20:31 +0100672 # Don't leave vertex attrib locations to chance. Instead emit fake
673 # glBindAttribLocation calls to ensure that the same locations will be
674 # used when retracing. Trying to remap locations after the fact would
675 # be an herculian task given that vertex attrib locations appear in
676 # many entry-points, including non-shader related ones.
677 if function.name == 'glLinkProgram':
José Fonseca54f304a2012-01-14 19:33:08 +0000678 Tracer.invokeFunction(self, function)
José Fonseca91492d22011-05-23 21:20:31 +0100679 print ' GLint active_attributes = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100680 print ' _glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &active_attributes);'
José Fonseca7525e6f2011-09-28 09:04:56 +0100681 print ' for (GLint attrib = 0; attrib < active_attributes; ++attrib) {'
José Fonseca91492d22011-05-23 21:20:31 +0100682 print ' GLint size = 0;'
683 print ' GLenum type = 0;'
684 print ' GLchar name[256];'
685 # TODO: Use ACTIVE_ATTRIBUTE_MAX_LENGTH instead of 256
José Fonseca632a78d2012-04-19 07:18:59 +0100686 print ' _glGetActiveAttrib(program, attrib, sizeof name, NULL, &size, &type, name);'
José Fonseca2a794f52011-05-26 20:54:29 +0100687 print " if (name[0] != 'g' || name[1] != 'l' || name[2] != '_') {"
José Fonseca632a78d2012-04-19 07:18:59 +0100688 print ' GLint location = _glGetAttribLocation(program, name);'
José Fonseca2a794f52011-05-26 20:54:29 +0100689 print ' if (location >= 0) {'
José Fonseca1b6c8752012-04-15 14:33:00 +0100690 bind_function = glapi.glapi.getFunctionByName('glBindAttribLocation')
José Fonseca91492d22011-05-23 21:20:31 +0100691 self.fake_call(bind_function, ['program', 'location', 'name'])
José Fonseca2a794f52011-05-26 20:54:29 +0100692 print ' }'
José Fonseca91492d22011-05-23 21:20:31 +0100693 print ' }'
694 print ' }'
695 if function.name == 'glLinkProgramARB':
José Fonseca54f304a2012-01-14 19:33:08 +0000696 Tracer.invokeFunction(self, function)
José Fonseca91492d22011-05-23 21:20:31 +0100697 print ' GLint active_attributes = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100698 print ' _glGetObjectParameterivARB(programObj, GL_OBJECT_ACTIVE_ATTRIBUTES_ARB, &active_attributes);'
José Fonseca7525e6f2011-09-28 09:04:56 +0100699 print ' for (GLint attrib = 0; attrib < active_attributes; ++attrib) {'
José Fonseca91492d22011-05-23 21:20:31 +0100700 print ' GLint size = 0;'
701 print ' GLenum type = 0;'
702 print ' GLcharARB name[256];'
703 # TODO: Use ACTIVE_ATTRIBUTE_MAX_LENGTH instead of 256
José Fonseca632a78d2012-04-19 07:18:59 +0100704 print ' _glGetActiveAttribARB(programObj, attrib, sizeof name, NULL, &size, &type, name);'
José Fonseca2a794f52011-05-26 20:54:29 +0100705 print " if (name[0] != 'g' || name[1] != 'l' || name[2] != '_') {"
José Fonseca632a78d2012-04-19 07:18:59 +0100706 print ' GLint location = _glGetAttribLocationARB(programObj, name);'
José Fonseca2a794f52011-05-26 20:54:29 +0100707 print ' if (location >= 0) {'
José Fonseca1b6c8752012-04-15 14:33:00 +0100708 bind_function = glapi.glapi.getFunctionByName('glBindAttribLocationARB')
José Fonseca91492d22011-05-23 21:20:31 +0100709 self.fake_call(bind_function, ['programObj', 'location', 'name'])
José Fonseca2a794f52011-05-26 20:54:29 +0100710 print ' }'
José Fonseca91492d22011-05-23 21:20:31 +0100711 print ' }'
712 print ' }'
713
Imre Deakd4937372012-04-24 14:06:48 +0300714 self.shadowBufferProlog(function)
715
José Fonseca54f304a2012-01-14 19:33:08 +0000716 Tracer.traceFunctionImplBody(self, function)
José Fonseca73373602011-05-20 17:45:26 +0100717
Peter Lohrmann0b5b75e2013-06-03 14:58:41 -0700718 # These entrypoints are only expected to be implemented by tools;
719 # drivers will probably not implement them.
José Fonsecaf028a8f2012-02-15 23:33:35 +0000720 marker_functions = [
721 # GL_GREMEDY_string_marker
José Fonseca8f34d342011-07-15 20:16:40 +0100722 'glStringMarkerGREMEDY',
José Fonsecaf028a8f2012-02-15 23:33:35 +0000723 # GL_GREMEDY_frame_terminator
José Fonseca8f34d342011-07-15 20:16:40 +0100724 'glFrameTerminatorGREMEDY',
José Fonsecaf028a8f2012-02-15 23:33:35 +0000725 # GL_EXT_debug_marker
726 'glInsertEventMarkerEXT',
727 'glPushGroupMarkerEXT',
728 'glPopGroupMarkerEXT',
José Fonseca8f34d342011-07-15 20:16:40 +0100729 ]
730
Peter Lohrmann0b5b75e2013-06-03 14:58:41 -0700731 # These entrypoints may be implemented by drivers, but are also very useful
732 # for debugging / analysis tools.
733 debug_functions = [
734 # GL_KHR_debug
735 'glDebugMessageControl',
736 'glDebugMessageInsert',
737 'glDebugMessageCallback',
738 'glGetDebugMessageLog',
739 'glPushDebugGroup',
740 'glPopDebugGroup',
741 'glObjectLabel',
742 'glGetObjectLabel',
743 'glObjectPtrLabel',
744 'glGetObjectPtrLabel',
745 # GL_ARB_debug_output
746 'glDebugMessageControlARB',
747 'glDebugMessageInsertARB',
748 'glDebugMessageCallbackARB',
749 'glGetDebugMessageLogARB',
750 # GL_AMD_debug_output
751 'glDebugMessageEnableAMD',
752 'glDebugMessageInsertAMD',
753 'glDebugMessageCallbackAMD',
754 'glGetDebugMessageLogAMD',
755 ]
756
José Fonseca54f304a2012-01-14 19:33:08 +0000757 def invokeFunction(self, function):
José Fonseca91492d22011-05-23 21:20:31 +0100758 if function.name in ('glLinkProgram', 'glLinkProgramARB'):
759 # These functions have been dispatched already
760 return
761
José Fonseca2cfa02c2013-06-10 08:05:29 +0100762 Tracer.invokeFunction(self, function)
763
764 def doInvokeFunction(self, function):
765 # Same as invokeFunction() but called both when trace is enabled or disabled.
766 #
767 # Used to modify the behavior of GL entry-points.
768
769 # Override GL extensions
770 if function.name in ('glGetString', 'glGetIntegerv', 'glGetStringi'):
771 Tracer.doInvokeFunction(self, function, prefix = 'gltrace::_', suffix = '_override')
772 return
773
José Fonsecaf028a8f2012-02-15 23:33:35 +0000774 # We implement GL_EXT_debug_marker, GL_GREMEDY_*, etc., and not the
775 # driver
776 if function.name in self.marker_functions:
José Fonseca8f34d342011-07-15 20:16:40 +0100777 return
778
Peter Lohrmann9d9eb812013-07-12 16:15:25 -0400779 # We may be faking KHR_debug, so ensure the pointer queries result is
780 # always zeroed to prevent dereference of unitialized pointers
781 if function.name == 'glGetPointerv':
782 print ' if (params &&'
783 print ' (pname == GL_DEBUG_CALLBACK_FUNCTION ||'
784 print ' pname == GL_DEBUG_CALLBACK_USER_PARAM)) {'
785 print ' *params = NULL;'
786 print ' }'
787
José Fonseca2cfa02c2013-06-10 08:05:29 +0100788 if function.name in self.getProcAddressFunctionNames:
José Fonsecaf028a8f2012-02-15 23:33:35 +0000789 else_ = ''
790 for marker_function in self.marker_functions:
José Fonseca1b6c8752012-04-15 14:33:00 +0100791 if self.api.getFunctionByName(marker_function):
José Fonsecaf028a8f2012-02-15 23:33:35 +0000792 print ' %sif (strcmp("%s", (const char *)%s) == 0) {' % (else_, marker_function, function.args[0].name)
José Fonseca632a78d2012-04-19 07:18:59 +0100793 print ' _result = (%s)&%s;' % (function.type, marker_function)
José Fonsecaf028a8f2012-02-15 23:33:35 +0000794 print ' }'
795 else_ = 'else '
796 print ' %s{' % else_
José Fonseca2cfa02c2013-06-10 08:05:29 +0100797 Tracer.doInvokeFunction(self, function)
798
799 # Replace function addresses with ours
800 # XXX: Doing this here instead of wrapRet means that the trace will
801 # contain the addresses of the wrapper functions, and not the real
802 # functions, but in practice this should make no difference.
803 if function.name in self.getProcAddressFunctionNames:
804 print ' _result = _wrapProcAddress(%s, _result);' % (function.args[0].name,)
805
José Fonseca8f34d342011-07-15 20:16:40 +0100806 print ' }'
José Fonseca1b3d3752011-07-15 10:15:19 +0100807 return
808
José Fonseca2cfa02c2013-06-10 08:05:29 +0100809 Tracer.doInvokeFunction(self, function)
José Fonseca91492d22011-05-23 21:20:31 +0100810
José Fonseca867b1b72011-04-24 11:58:04 +0100811 buffer_targets = [
812 'ARRAY_BUFFER',
813 'ELEMENT_ARRAY_BUFFER',
814 'PIXEL_PACK_BUFFER',
815 'PIXEL_UNPACK_BUFFER',
José Fonseca7b20d672012-01-10 19:13:58 +0000816 'UNIFORM_BUFFER',
817 'TEXTURE_BUFFER',
818 'TRANSFORM_FEEDBACK_BUFFER',
819 'COPY_READ_BUFFER',
820 'COPY_WRITE_BUFFER',
821 'DRAW_INDIRECT_BUFFER',
822 'ATOMIC_COUNTER_BUFFER',
José Fonseca867b1b72011-04-24 11:58:04 +0100823 ]
824
José Fonseca54f304a2012-01-14 19:33:08 +0000825 def wrapRet(self, function, instance):
826 Tracer.wrapRet(self, function, instance)
José Fonseca1b3d3752011-07-15 10:15:19 +0100827
José Fonsecacdc322c2012-02-29 19:29:51 +0000828 # Keep track of buffer mappings
829 if function.name in ('glMapBuffer', 'glMapBufferARB'):
José Fonseca867b1b72011-04-24 11:58:04 +0100830 print ' struct buffer_mapping *mapping = get_buffer_mapping(target);'
831 print ' if (mapping) {'
832 print ' mapping->map = %s;' % (instance)
833 print ' mapping->length = 0;'
José Fonseca632a78d2012-04-19 07:18:59 +0100834 print ' _glGetBufferParameteriv(target, GL_BUFFER_SIZE, &mapping->length);'
José Fonseca867b1b72011-04-24 11:58:04 +0100835 print ' mapping->write = (access != GL_READ_ONLY);'
José Fonseca73373602011-05-20 17:45:26 +0100836 print ' mapping->explicit_flush = false;'
José Fonseca867b1b72011-04-24 11:58:04 +0100837 print ' }'
José Fonseca867b1b72011-04-24 11:58:04 +0100838 if function.name == 'glMapBufferRange':
José Fonseca9c536b02012-02-29 20:54:13 +0000839 print ' if (access & GL_MAP_WRITE_BIT) {'
José Fonseca632a78d2012-04-19 07:18:59 +0100840 print ' _checkBufferMapRange = true;'
José Fonseca9c536b02012-02-29 20:54:13 +0000841 print ' }'
José Fonseca867b1b72011-04-24 11:58:04 +0100842 print ' struct buffer_mapping *mapping = get_buffer_mapping(target);'
843 print ' if (mapping) {'
844 print ' mapping->map = %s;' % (instance)
845 print ' mapping->length = length;'
846 print ' mapping->write = access & GL_MAP_WRITE_BIT;'
José Fonseca73373602011-05-20 17:45:26 +0100847 print ' mapping->explicit_flush = access & GL_MAP_FLUSH_EXPLICIT_BIT;'
José Fonseca867b1b72011-04-24 11:58:04 +0100848 print ' }'
José Fonseca669b1222011-02-20 09:05:10 +0000849
José Fonsecac9f12232011-03-25 20:07:42 +0000850 boolean_names = [
851 'GL_FALSE',
852 'GL_TRUE',
853 ]
854
855 def gl_boolean(self, value):
856 return self.boolean_names[int(bool(value))]
857
José Fonsecac29f4f12011-06-11 12:19:05 +0100858 # Names of the functions that unpack from a pixel buffer object. See the
859 # ARB_pixel_buffer_object specification.
José Fonsecae97bab92011-06-02 23:15:11 +0100860 unpack_function_names = set([
861 'glBitmap',
José Fonsecac29f4f12011-06-11 12:19:05 +0100862 'glColorSubTable',
863 'glColorTable',
José Fonsecad2bd4ca2013-04-12 11:41:00 +0100864 'glCompressedMultiTexImage1DEXT',
865 'glCompressedMultiTexImage2DEXT',
866 'glCompressedMultiTexImage3DEXT',
867 'glCompressedMultiTexSubImage1DEXT',
868 'glCompressedMultiTexSubImage2DEXT',
869 'glCompressedMultiTexSubImage3DEXT',
José Fonsecac29f4f12011-06-11 12:19:05 +0100870 'glCompressedTexImage1D',
idinevdb5ad3b2014-02-03 15:50:39 +0000871 'glCompressedTexImage1DARB',
José Fonsecac29f4f12011-06-11 12:19:05 +0100872 'glCompressedTexImage2D',
idinevdb5ad3b2014-02-03 15:50:39 +0000873 'glCompressedTexImage2DARB',
José Fonsecac29f4f12011-06-11 12:19:05 +0100874 'glCompressedTexImage3D',
idinevdb5ad3b2014-02-03 15:50:39 +0000875 'glCompressedTexImage3DARB',
José Fonsecac29f4f12011-06-11 12:19:05 +0100876 'glCompressedTexSubImage1D',
idinevdb5ad3b2014-02-03 15:50:39 +0000877 'glCompressedTexSubImage1DARB',
José Fonsecac29f4f12011-06-11 12:19:05 +0100878 'glCompressedTexSubImage2D',
idinevdb5ad3b2014-02-03 15:50:39 +0000879 'glCompressedTexSubImage2DARB',
José Fonsecac29f4f12011-06-11 12:19:05 +0100880 'glCompressedTexSubImage3D',
idinevdb5ad3b2014-02-03 15:50:39 +0000881 'glCompressedTexSubImage3DARB',
José Fonsecad2bd4ca2013-04-12 11:41:00 +0100882 'glCompressedTextureImage1DEXT',
883 'glCompressedTextureImage2DEXT',
884 'glCompressedTextureImage3DEXT',
885 'glCompressedTextureSubImage1DEXT',
886 'glCompressedTextureSubImage2DEXT',
887 'glCompressedTextureSubImage3DEXT',
José Fonsecac29f4f12011-06-11 12:19:05 +0100888 'glConvolutionFilter1D',
889 'glConvolutionFilter2D',
José Fonsecae97bab92011-06-02 23:15:11 +0100890 'glDrawPixels',
891 'glMultiTexImage1DEXT',
892 'glMultiTexImage2DEXT',
893 'glMultiTexImage3DEXT',
894 'glMultiTexSubImage1DEXT',
895 'glMultiTexSubImage2DEXT',
896 'glMultiTexSubImage3DEXT',
José Fonsecac29f4f12011-06-11 12:19:05 +0100897 'glPixelMapfv',
898 'glPixelMapuiv',
899 'glPixelMapusv',
José Fonsecae97bab92011-06-02 23:15:11 +0100900 'glPolygonStipple',
José Fonsecac29f4f12011-06-11 12:19:05 +0100901 'glSeparableFilter2D',
José Fonsecae97bab92011-06-02 23:15:11 +0100902 'glTexImage1D',
903 'glTexImage1DEXT',
904 'glTexImage2D',
905 'glTexImage2DEXT',
906 'glTexImage3D',
907 'glTexImage3DEXT',
908 'glTexSubImage1D',
909 'glTexSubImage1DEXT',
910 'glTexSubImage2D',
911 'glTexSubImage2DEXT',
912 'glTexSubImage3D',
913 'glTexSubImage3DEXT',
914 'glTextureImage1DEXT',
915 'glTextureImage2DEXT',
916 'glTextureImage3DEXT',
917 'glTextureSubImage1DEXT',
918 'glTextureSubImage2DEXT',
919 'glTextureSubImage3DEXT',
920 ])
921
José Fonseca54f304a2012-01-14 19:33:08 +0000922 def serializeArgValue(self, function, arg):
José Fonsecae97bab92011-06-02 23:15:11 +0100923 # Recognize offsets instead of blobs when a PBO is bound
924 if function.name in self.unpack_function_names \
925 and (isinstance(arg.type, stdapi.Blob) \
926 or (isinstance(arg.type, stdapi.Const) \
927 and isinstance(arg.type.type, stdapi.Blob))):
José Fonsecac29f4f12011-06-11 12:19:05 +0100928 print ' {'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000929 print ' gltrace::Context *ctx = gltrace::getContext();'
José Fonseca632a78d2012-04-19 07:18:59 +0100930 print ' GLint _unpack_buffer = 0;'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000931 print ' if (ctx->profile == gltrace::PROFILE_COMPAT)'
José Fonseca632a78d2012-04-19 07:18:59 +0100932 print ' _glGetIntegerv(GL_PIXEL_UNPACK_BUFFER_BINDING, &_unpack_buffer);'
933 print ' if (_unpack_buffer) {'
José Fonsecad559f022012-04-15 16:13:51 +0100934 print ' trace::localWriter.writePointer((uintptr_t)%s);' % arg.name
José Fonsecac29f4f12011-06-11 12:19:05 +0100935 print ' } else {'
José Fonseca54f304a2012-01-14 19:33:08 +0000936 Tracer.serializeArgValue(self, function, arg)
José Fonsecac29f4f12011-06-11 12:19:05 +0100937 print ' }'
José Fonsecae97bab92011-06-02 23:15:11 +0100938 print ' }'
939 return
940
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100941 # Several GL state functions take GLenum symbolic names as
942 # integer/floats; so dump the symbolic name whenever possible
José Fonseca3bcb33c2011-05-27 20:14:31 +0100943 if function.name.startswith('gl') \
José Fonsecae3571092011-10-13 08:26:27 +0100944 and arg.type in (glapi.GLint, glapi.GLfloat, glapi.GLdouble) \
José Fonseca3bcb33c2011-05-27 20:14:31 +0100945 and arg.name == 'param':
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100946 assert arg.index > 0
947 assert function.args[arg.index - 1].name == 'pname'
948 assert function.args[arg.index - 1].type == glapi.GLenum
949 print ' if (is_symbolic_pname(pname) && is_symbolic_param(%s)) {' % arg.name
José Fonseca54f304a2012-01-14 19:33:08 +0000950 self.serializeValue(glapi.GLenum, arg.name)
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100951 print ' } else {'
José Fonseca54f304a2012-01-14 19:33:08 +0000952 Tracer.serializeArgValue(self, function, arg)
José Fonsecaa3f89ae2011-04-26 08:50:32 +0100953 print ' }'
954 return
955
José Fonseca54f304a2012-01-14 19:33:08 +0000956 Tracer.serializeArgValue(self, function, arg)
José Fonseca99221832011-03-22 22:15:46 +0000957
José Fonseca4c938c22011-04-30 22:44:38 +0100958 def footer(self, api):
959 Tracer.footer(self, api)
José Fonseca669b1222011-02-20 09:05:10 +0000960
José Fonseca4c938c22011-04-30 22:44:38 +0100961 # A simple state tracker to track the pointer values
José Fonseca669b1222011-02-20 09:05:10 +0000962 # update the state
José Fonseca14cb9ef2012-05-17 21:33:14 +0100963 print 'static void _trace_user_arrays(GLuint count)'
José Fonseca669b1222011-02-20 09:05:10 +0000964 print '{'
José Fonsecaf028a8f2012-02-15 23:33:35 +0000965 print ' gltrace::Context *ctx = gltrace::getContext();'
José Fonseca8d1408b2014-02-03 19:57:18 +0000966 print
967
968 # Temporarily unbind the array buffer
José Fonseca26be8f92014-03-07 14:08:50 +0000969 print ' GLint _array_buffer = _glGetInteger(GL_ARRAY_BUFFER_BINDING);'
José Fonseca8d1408b2014-02-03 19:57:18 +0000970 print ' if (_array_buffer) {'
971 self.fake_glBindBuffer(api, 'GL_ARRAY_BUFFER', '0')
972 print ' }'
973 print
José Fonseca1a2fdd22011-04-01 00:55:09 +0100974
José Fonseca99221832011-03-22 22:15:46 +0000975 for camelcase_name, uppercase_name in self.arrays:
Chia-I Wub3d218d2011-11-03 01:37:36 +0800976 # in which profile is the array available?
José Fonsecaf028a8f2012-02-15 23:33:35 +0000977 profile_check = 'ctx->profile == gltrace::PROFILE_COMPAT'
Chia-I Wub3d218d2011-11-03 01:37:36 +0800978 if camelcase_name in self.arrays_es1:
José Fonsecaf028a8f2012-02-15 23:33:35 +0000979 profile_check = '(' + profile_check + ' || ctx->profile == gltrace::PROFILE_ES1)';
Chia-I Wub3d218d2011-11-03 01:37:36 +0800980
José Fonseca99221832011-03-22 22:15:46 +0000981 function_name = 'gl%sPointer' % camelcase_name
982 enable_name = 'GL_%s_ARRAY' % uppercase_name
983 binding_name = 'GL_%s_ARRAY_BUFFER_BINDING' % uppercase_name
José Fonseca1b6c8752012-04-15 14:33:00 +0100984 function = api.getFunctionByName(function_name)
José Fonseca99221832011-03-22 22:15:46 +0000985
José Fonseca06e85192011-10-16 14:15:36 +0100986 print ' // %s' % function.prototype()
Chia-I Wub3d218d2011-11-03 01:37:36 +0800987 print ' if (%s) {' % profile_check
José Fonsecafb6744f2011-04-15 11:18:37 +0100988 self.array_trace_prolog(api, uppercase_name)
989 self.array_prolog(api, uppercase_name)
José Fonseca632a78d2012-04-19 07:18:59 +0100990 print ' if (_glIsEnabled(%s)) {' % enable_name
José Fonseca26be8f92014-03-07 14:08:50 +0000991 print ' GLint _binding = _glGetInteger(%s);' % binding_name
José Fonseca632a78d2012-04-19 07:18:59 +0100992 print ' if (!_binding) {'
José Fonseca99221832011-03-22 22:15:46 +0000993
994 # Get the arguments via glGet*
995 for arg in function.args:
996 arg_get_enum = 'GL_%s_ARRAY_%s' % (uppercase_name, arg.name.upper())
997 arg_get_function, arg_type = TypeGetter().visit(arg.type)
José Fonseca7f5163e2011-03-31 23:37:26 +0100998 print ' %s %s = 0;' % (arg_type, arg.name)
José Fonseca632a78d2012-04-19 07:18:59 +0100999 print ' _%s(%s, &%s);' % (arg_get_function, arg_get_enum, arg.name)
José Fonseca99221832011-03-22 22:15:46 +00001000
1001 arg_names = ', '.join([arg.name for arg in function.args[:-1]])
José Fonseca14cb9ef2012-05-17 21:33:14 +01001002 print ' size_t _size = _%s_size(%s, count);' % (function.name, arg_names)
José Fonseca99221832011-03-22 22:15:46 +00001003
1004 # Emit a fake function
José Fonsecafb6744f2011-04-15 11:18:37 +01001005 self.array_trace_intermezzo(api, uppercase_name)
José Fonseca632a78d2012-04-19 07:18:59 +01001006 print ' unsigned _call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,)
José Fonseca669b1222011-02-20 09:05:10 +00001007 for arg in function.args:
1008 assert not arg.output
José Fonsecab4a3d142011-10-27 07:43:19 +01001009 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
José Fonseca14c21bc2011-02-20 23:32:22 +00001010 if arg.name != 'pointer':
José Fonseca54f304a2012-01-14 19:33:08 +00001011 self.serializeValue(arg.type, arg.name)
José Fonseca14c21bc2011-02-20 23:32:22 +00001012 else:
José Fonseca632a78d2012-04-19 07:18:59 +01001013 print ' trace::localWriter.writeBlob((const void *)%s, _size);' % (arg.name)
José Fonsecab4a3d142011-10-27 07:43:19 +01001014 print ' trace::localWriter.endArg();'
José Fonseca99221832011-03-22 22:15:46 +00001015
José Fonsecab4a3d142011-10-27 07:43:19 +01001016 print ' trace::localWriter.endEnter();'
José Fonseca632a78d2012-04-19 07:18:59 +01001017 print ' trace::localWriter.beginLeave(_call);'
José Fonsecab4a3d142011-10-27 07:43:19 +01001018 print ' trace::localWriter.endLeave();'
José Fonseca99221832011-03-22 22:15:46 +00001019 print ' }'
José Fonseca669b1222011-02-20 09:05:10 +00001020 print ' }'
José Fonsecafb6744f2011-04-15 11:18:37 +01001021 self.array_epilog(api, uppercase_name)
1022 self.array_trace_epilog(api, uppercase_name)
Chia-I Wub3d218d2011-11-03 01:37:36 +08001023 print ' }'
José Fonseca99221832011-03-22 22:15:46 +00001024 print
José Fonseca1a2fdd22011-04-01 00:55:09 +01001025
José Fonseca1601c412011-05-10 10:38:19 +01001026 # Samething, but for glVertexAttribPointer*
1027 #
1028 # Some variants of glVertexAttribPointer alias conventional and generic attributes:
1029 # - glVertexAttribPointer: no
1030 # - glVertexAttribPointerARB: implementation dependent
1031 # - glVertexAttribPointerNV: yes
1032 #
1033 # This means that the implementations of these functions do not always
1034 # alias, and they need to be considered independently.
1035 #
Chia-I Wub3d218d2011-11-03 01:37:36 +08001036 print ' // ES1 does not support generic vertex attributes'
José Fonsecaf028a8f2012-02-15 23:33:35 +00001037 print ' if (ctx->profile == gltrace::PROFILE_ES1)'
Chia-I Wub3d218d2011-11-03 01:37:36 +08001038 print ' return;'
1039 print
José Fonseca632a78d2012-04-19 07:18:59 +01001040 print ' vertex_attrib _vertex_attrib = _get_vertex_attrib();'
José Fonseca5a568a92011-06-29 16:43:36 +01001041 print
1042 for suffix in ['', 'ARB', 'NV']:
1043 if suffix:
José Fonsecad94aaac2011-06-28 20:50:49 +01001044 SUFFIX = '_' + suffix
José Fonsecad94aaac2011-06-28 20:50:49 +01001045 else:
José Fonseca5a568a92011-06-29 16:43:36 +01001046 SUFFIX = suffix
José Fonseca1601c412011-05-10 10:38:19 +01001047 function_name = 'glVertexAttribPointer' + suffix
José Fonseca1b6c8752012-04-15 14:33:00 +01001048 function = api.getFunctionByName(function_name)
José Fonseca06e85192011-10-16 14:15:36 +01001049
1050 print ' // %s' % function.prototype()
José Fonseca632a78d2012-04-19 07:18:59 +01001051 print ' if (_vertex_attrib == VERTEX_ATTRIB%s) {' % SUFFIX
José Fonseca5a568a92011-06-29 16:43:36 +01001052 if suffix == 'NV':
José Fonseca632a78d2012-04-19 07:18:59 +01001053 print ' GLint _max_vertex_attribs = 16;'
José Fonseca5a568a92011-06-29 16:43:36 +01001054 else:
José Fonseca26be8f92014-03-07 14:08:50 +00001055 print ' GLint _max_vertex_attribs = _glGetInteger(GL_MAX_VERTEX_ATTRIBS);'
José Fonseca632a78d2012-04-19 07:18:59 +01001056 print ' for (GLint index = 0; index < _max_vertex_attribs; ++index) {'
1057 print ' GLint _enabled = 0;'
José Fonseca5a568a92011-06-29 16:43:36 +01001058 if suffix == 'NV':
José Fonseca632a78d2012-04-19 07:18:59 +01001059 print ' _glGetIntegerv(GL_VERTEX_ATTRIB_ARRAY0_NV + index, &_enabled);'
José Fonseca5a568a92011-06-29 16:43:36 +01001060 else:
José Fonseca632a78d2012-04-19 07:18:59 +01001061 print ' _glGetVertexAttribiv%s(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED%s, &_enabled);' % (suffix, SUFFIX)
1062 print ' if (_enabled) {'
1063 print ' GLint _binding = 0;'
José Fonseca5a568a92011-06-29 16:43:36 +01001064 if suffix != 'NV':
1065 # It doesn't seem possible to use VBOs with NV_vertex_program.
José Fonseca632a78d2012-04-19 07:18:59 +01001066 print ' _glGetVertexAttribiv%s(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING%s, &_binding);' % (suffix, SUFFIX)
1067 print ' if (!_binding) {'
José Fonseca1a2fdd22011-04-01 00:55:09 +01001068
José Fonseca1601c412011-05-10 10:38:19 +01001069 # Get the arguments via glGet*
1070 for arg in function.args[1:]:
José Fonseca5a568a92011-06-29 16:43:36 +01001071 if suffix == 'NV':
1072 arg_get_enum = 'GL_ATTRIB_ARRAY_%s%s' % (arg.name.upper(), SUFFIX)
1073 else:
1074 arg_get_enum = 'GL_VERTEX_ATTRIB_ARRAY_%s%s' % (arg.name.upper(), SUFFIX)
José Fonsecac493e3e2011-06-29 12:57:06 +01001075 arg_get_function, arg_type = TypeGetter('glGetVertexAttrib', False, suffix).visit(arg.type)
José Fonseca5a568a92011-06-29 16:43:36 +01001076 print ' %s %s = 0;' % (arg_type, arg.name)
José Fonseca632a78d2012-04-19 07:18:59 +01001077 print ' _%s(index, %s, &%s);' % (arg_get_function, arg_get_enum, arg.name)
José Fonseca1601c412011-05-10 10:38:19 +01001078
1079 arg_names = ', '.join([arg.name for arg in function.args[1:-1]])
José Fonseca14cb9ef2012-05-17 21:33:14 +01001080 print ' size_t _size = _%s_size(%s, count);' % (function.name, arg_names)
José Fonseca1a2fdd22011-04-01 00:55:09 +01001081
José Fonseca1601c412011-05-10 10:38:19 +01001082 # Emit a fake function
José Fonseca632a78d2012-04-19 07:18:59 +01001083 print ' unsigned _call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,)
José Fonseca1601c412011-05-10 10:38:19 +01001084 for arg in function.args:
1085 assert not arg.output
José Fonsecab4a3d142011-10-27 07:43:19 +01001086 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
José Fonseca1601c412011-05-10 10:38:19 +01001087 if arg.name != 'pointer':
José Fonseca54f304a2012-01-14 19:33:08 +00001088 self.serializeValue(arg.type, arg.name)
José Fonseca1601c412011-05-10 10:38:19 +01001089 else:
José Fonseca632a78d2012-04-19 07:18:59 +01001090 print ' trace::localWriter.writeBlob((const void *)%s, _size);' % (arg.name)
José Fonsecab4a3d142011-10-27 07:43:19 +01001091 print ' trace::localWriter.endArg();'
José Fonseca1601c412011-05-10 10:38:19 +01001092
José Fonsecab4a3d142011-10-27 07:43:19 +01001093 print ' trace::localWriter.endEnter();'
José Fonseca632a78d2012-04-19 07:18:59 +01001094 print ' trace::localWriter.beginLeave(_call);'
José Fonsecab4a3d142011-10-27 07:43:19 +01001095 print ' trace::localWriter.endLeave();'
José Fonseca1601c412011-05-10 10:38:19 +01001096 print ' }'
1097 print ' }'
1098 print ' }'
1099 print ' }'
1100 print
José Fonseca1a2fdd22011-04-01 00:55:09 +01001101
José Fonseca8d1408b2014-02-03 19:57:18 +00001102 # Restore the original array_buffer
1103 print ' if (_array_buffer) {'
1104 self.fake_glBindBuffer(api, 'GL_ARRAY_BUFFER', '_array_buffer')
1105 print ' }'
1106 print
1107
José Fonseca669b1222011-02-20 09:05:10 +00001108 print '}'
1109 print
1110
José Fonsecafb6744f2011-04-15 11:18:37 +01001111 #
1112 # Hooks for glTexCoordPointer, which is identical to the other array
1113 # pointers except the fact that it is indexed by glClientActiveTexture.
1114 #
1115
1116 def array_prolog(self, api, uppercase_name):
1117 if uppercase_name == 'TEXTURE_COORD':
José Fonseca26be8f92014-03-07 14:08:50 +00001118 print ' GLint client_active_texture = _glGetInteger(GL_CLIENT_ACTIVE_TEXTURE);'
José Fonsecafb6744f2011-04-15 11:18:37 +01001119 print ' GLint max_texture_coords = 0;'
José Fonsecaf028a8f2012-02-15 23:33:35 +00001120 print ' if (ctx->profile == gltrace::PROFILE_COMPAT)'
José Fonseca632a78d2012-04-19 07:18:59 +01001121 print ' _glGetIntegerv(GL_MAX_TEXTURE_COORDS, &max_texture_coords);'
Chia-I Wub3d218d2011-11-03 01:37:36 +08001122 print ' else'
José Fonseca632a78d2012-04-19 07:18:59 +01001123 print ' _glGetIntegerv(GL_MAX_TEXTURE_UNITS, &max_texture_coords);'
José Fonsecafb6744f2011-04-15 11:18:37 +01001124 print ' for (GLint unit = 0; unit < max_texture_coords; ++unit) {'
José Fonseca7525e6f2011-09-28 09:04:56 +01001125 print ' GLint texture = GL_TEXTURE0 + unit;'
José Fonseca632a78d2012-04-19 07:18:59 +01001126 print ' _glClientActiveTexture(texture);'
José Fonsecafb6744f2011-04-15 11:18:37 +01001127
1128 def array_trace_prolog(self, api, uppercase_name):
1129 if uppercase_name == 'TEXTURE_COORD':
1130 print ' bool client_active_texture_dirty = false;'
1131
1132 def array_epilog(self, api, uppercase_name):
1133 if uppercase_name == 'TEXTURE_COORD':
1134 print ' }'
1135 self.array_cleanup(api, uppercase_name)
1136
1137 def array_cleanup(self, api, uppercase_name):
1138 if uppercase_name == 'TEXTURE_COORD':
José Fonseca632a78d2012-04-19 07:18:59 +01001139 print ' _glClientActiveTexture(client_active_texture);'
José Fonsecafb6744f2011-04-15 11:18:37 +01001140
1141 def array_trace_intermezzo(self, api, uppercase_name):
1142 if uppercase_name == 'TEXTURE_COORD':
1143 print ' if (texture != client_active_texture || client_active_texture_dirty) {'
1144 print ' client_active_texture_dirty = true;'
1145 self.fake_glClientActiveTexture_call(api, "texture");
1146 print ' }'
1147
1148 def array_trace_epilog(self, api, uppercase_name):
1149 if uppercase_name == 'TEXTURE_COORD':
1150 print ' if (client_active_texture_dirty) {'
1151 self.fake_glClientActiveTexture_call(api, "client_active_texture");
1152 print ' }'
1153
José Fonseca8d1408b2014-02-03 19:57:18 +00001154 def fake_glBindBuffer(self, api, target, buffer):
1155 function = api.getFunctionByName('glBindBuffer')
1156 self.fake_call(function, [target, buffer])
1157
José Fonsecafb6744f2011-04-15 11:18:37 +01001158 def fake_glClientActiveTexture_call(self, api, texture):
José Fonseca1b6c8752012-04-15 14:33:00 +01001159 function = api.getFunctionByName('glClientActiveTexture')
José Fonsecafb6744f2011-04-15 11:18:37 +01001160 self.fake_call(function, [texture])
1161
José Fonseca151c3702013-05-10 08:28:15 +01001162 def emitFakeTexture2D(self):
1163 function = glapi.glapi.getFunctionByName('glTexImage2D')
1164 instances = function.argNames()
1165 print ' unsigned _fake_call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,)
1166 for arg in function.args:
1167 assert not arg.output
1168 self.serializeArg(function, arg)
1169 print ' trace::localWriter.endEnter();'
1170 print ' trace::localWriter.beginLeave(_fake_call);'
1171 print ' trace::localWriter.endLeave();'
José Fonsecafb6744f2011-04-15 11:18:37 +01001172
1173
1174
1175
1176
José Fonseca669b1222011-02-20 09:05:10 +00001177
1178
1179
1180
1181
1182