]> git.cworth.org Git - apitrace/blob - wrappers/gltrace.py
trace: Additional support for GL_KHR_debug, GL_ARB_debug_output, and GL_AMD_debug_output.
[apitrace] / wrappers / gltrace.py
1 ##########################################################################
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
30 from trace import Tracer
31 from dispatch import function_pointer_type, function_pointer_value
32 import specs.stdapi as stdapi
33 import specs.glapi as glapi
34 import specs.glparams as glparams
35 from specs.glxapi import glxapi
36
37
38 class TypeGetter(stdapi.Visitor):
39     '''Determine which glGet*v function that matches the specified type.'''
40
41     def __init__(self, prefix = 'glGet', long_suffix = True, ext_suffix = ''):
42         self.prefix = prefix
43         self.long_suffix = long_suffix
44         self.ext_suffix = ext_suffix
45
46     def visitConst(self, const):
47         return self.visit(const.type)
48
49     def visitAlias(self, alias):
50         if alias.expr == 'GLboolean':
51             if self.long_suffix:
52                 suffix = 'Booleanv'
53                 arg_type = alias.expr
54             else:
55                 suffix = 'iv'
56                 arg_type = 'GLint'
57         elif alias.expr == 'GLdouble':
58             if self.long_suffix:
59                 suffix = 'Doublev'
60                 arg_type = alias.expr
61             else:
62                 suffix = 'dv'
63                 arg_type = alias.expr
64         elif alias.expr == 'GLfloat':
65             if self.long_suffix:
66                 suffix = 'Floatv'
67                 arg_type = alias.expr
68             else:
69                 suffix = 'fv'
70                 arg_type = alias.expr
71         elif alias.expr in ('GLint', 'GLuint', 'GLsizei'):
72             if self.long_suffix:
73                 suffix = 'Integerv'
74                 arg_type = 'GLint'
75             else:
76                 suffix = 'iv'
77                 arg_type = 'GLint'
78         else:
79             print alias.expr
80             assert False
81         function_name = self.prefix + suffix + self.ext_suffix
82         return function_name, arg_type
83     
84     def visitEnum(self, enum):
85         return self.visit(glapi.GLint)
86
87     def visitBitmask(self, bitmask):
88         return self.visit(glapi.GLint)
89
90     def visitOpaque(self, pointer):
91         return self.prefix + 'Pointerv' + self.ext_suffix, 'GLvoid *'
92
93
94 class GlTracer(Tracer):
95
96     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"),
105     ]
106     arrays.reverse()
107
108     # arrays available in PROFILE_ES1
109     arrays_es1 = ("Vertex", "Normal", "Color", "TexCoord")
110
111     def header(self, api):
112         Tracer.header(self, api)
113
114         print '#include "gltrace.hpp"'
115         print
116         
117         # Which glVertexAttrib* variant to use
118         print 'enum vertex_attrib {'
119         print '    VERTEX_ATTRIB,'
120         print '    VERTEX_ATTRIB_ARB,'
121         print '    VERTEX_ATTRIB_NV,'
122         print '};'
123         print
124         print 'static vertex_attrib _get_vertex_attrib(void) {'
125         print '    gltrace::Context *ctx = gltrace::getContext();'
126         print '    if (ctx->user_arrays_arb || ctx->user_arrays_nv) {'
127         print '        GLboolean _vertex_program = GL_FALSE;'
128         print '        _glGetBooleanv(GL_VERTEX_PROGRAM_ARB, &_vertex_program);'
129         print '        if (_vertex_program) {'
130         print '            if (ctx->user_arrays_nv) {'
131         print '                GLint _vertex_program_binding_nv = 0;'
132         print '                _glGetIntegerv(GL_VERTEX_PROGRAM_BINDING_NV, &_vertex_program_binding_nv);'
133         print '                if (_vertex_program_binding_nv) {'
134         print '                    return VERTEX_ATTRIB_NV;'
135         print '                }'
136         print '            }'
137         print '            return VERTEX_ATTRIB_ARB;'
138         print '        }'
139         print '    }'
140         print '    return VERTEX_ATTRIB;'
141         print '}'
142         print
143
144         self.defineShadowBufferHelper()
145
146         # Whether we need user arrays
147         print 'static inline bool _need_user_arrays(void)'
148         print '{'
149         print '    gltrace::Context *ctx = gltrace::getContext();'
150         print '    if (!ctx->user_arrays) {'
151         print '        return false;'
152         print '    }'
153         print
154
155         for camelcase_name, uppercase_name in self.arrays:
156             # in which profile is the array available?
157             profile_check = 'ctx->profile == gltrace::PROFILE_COMPAT'
158             if camelcase_name in self.arrays_es1:
159                 profile_check = '(' + profile_check + ' || ctx->profile == gltrace::PROFILE_ES1)';
160
161             function_name = 'gl%sPointer' % camelcase_name
162             enable_name = 'GL_%s_ARRAY' % uppercase_name
163             binding_name = 'GL_%s_ARRAY_BUFFER_BINDING' % uppercase_name
164             print '    // %s' % function_name
165             print '  if (%s) {' % profile_check
166             self.array_prolog(api, uppercase_name)
167             print '    if (_glIsEnabled(%s)) {' % enable_name
168             print '        GLint _binding = 0;'
169             print '        _glGetIntegerv(%s, &_binding);' % binding_name
170             print '        if (!_binding) {'
171             self.array_cleanup(api, uppercase_name)
172             print '            return true;'
173             print '        }'
174             print '    }'
175             self.array_epilog(api, uppercase_name)
176             print '  }'
177             print
178
179         print '    // ES1 does not support generic vertex attributes'
180         print '    if (ctx->profile == gltrace::PROFILE_ES1)'
181         print '        return false;'
182         print
183         print '    vertex_attrib _vertex_attrib = _get_vertex_attrib();'
184         print
185         print '    // glVertexAttribPointer'
186         print '    if (_vertex_attrib == VERTEX_ATTRIB) {'
187         print '        GLint _max_vertex_attribs = 0;'
188         print '        _glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &_max_vertex_attribs);'
189         print '        for (GLint index = 0; index < _max_vertex_attribs; ++index) {'
190         print '            GLint _enabled = 0;'
191         print '            _glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &_enabled);'
192         print '            if (_enabled) {'
193         print '                GLint _binding = 0;'
194         print '                _glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &_binding);'
195         print '                if (!_binding) {'
196         print '                    return true;'
197         print '                }'
198         print '            }'
199         print '        }'
200         print '    }'
201         print
202         print '    // glVertexAttribPointerARB'
203         print '    if (_vertex_attrib == VERTEX_ATTRIB_ARB) {'
204         print '        GLint _max_vertex_attribs = 0;'
205         print '        _glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &_max_vertex_attribs);'
206         print '        for (GLint index = 0; index < _max_vertex_attribs; ++index) {'
207         print '            GLint _enabled = 0;'
208         print '            _glGetVertexAttribivARB(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB, &_enabled);'
209         print '            if (_enabled) {'
210         print '                GLint _binding = 0;'
211         print '                _glGetVertexAttribivARB(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB, &_binding);'
212         print '                if (!_binding) {'
213         print '                    return true;'
214         print '                }'
215         print '            }'
216         print '        }'
217         print '    }'
218         print
219         print '    // glVertexAttribPointerNV'
220         print '    if (_vertex_attrib == VERTEX_ATTRIB_NV) {'
221         print '        for (GLint index = 0; index < 16; ++index) {'
222         print '            GLint _enabled = 0;'
223         print '            _glGetIntegerv(GL_VERTEX_ATTRIB_ARRAY0_NV + index, &_enabled);'
224         print '            if (_enabled) {'
225         print '                return true;'
226         print '            }'
227         print '        }'
228         print '    }'
229         print
230
231         print '    return false;'
232         print '}'
233         print
234
235         print 'static void _trace_user_arrays(GLuint count);'
236         print
237
238         # Buffer mappings
239         print '// whether glMapBufferRange(GL_MAP_WRITE_BIT) has ever been called'
240         print 'static bool _checkBufferMapRange = false;'
241         print
242         print '// whether glBufferParameteriAPPLE(GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE) has ever been called'
243         print 'static bool _checkBufferFlushingUnmapAPPLE = false;'
244         print
245         # Buffer mapping information, necessary for old Mesa 2.1 drivers which
246         # do not support glGetBufferParameteriv(GL_BUFFER_ACCESS_FLAGS/GL_BUFFER_MAP_LENGTH)
247         print 'struct buffer_mapping {'
248         print '    void *map;'
249         print '    GLint length;'
250         print '    bool write;'
251         print '    bool explicit_flush;'
252         print '};'
253         print
254         for target in self.buffer_targets:
255             print 'struct buffer_mapping _%s_mapping;' % target.lower();
256         print
257         print 'static inline struct buffer_mapping *'
258         print 'get_buffer_mapping(GLenum target) {'
259         print '    switch (target) {'
260         for target in self.buffer_targets:
261             print '    case GL_%s:' % target
262             print '        return & _%s_mapping;' % target.lower()
263         print '    default:'
264         print '        os::log("apitrace: warning: unknown buffer target 0x%04X\\n", target);'
265         print '        return NULL;'
266         print '    }'
267         print '}'
268         print
269
270         # Generate a helper function to determine whether a parameter name
271         # refers to a symbolic value or not
272         print 'static bool'
273         print 'is_symbolic_pname(GLenum pname) {'
274         print '    switch (pname) {'
275         for function, type, count, name in glparams.parameters:
276             if type is glapi.GLenum:
277                 print '    case %s:' % name
278         print '        return true;'
279         print '    default:'
280         print '        return false;'
281         print '    }'
282         print '}'
283         print
284         
285         # Generate a helper function to determine whether a parameter value is
286         # potentially symbolic or not; i.e., if the value can be represented in
287         # an enum or not
288         print 'template<class T>'
289         print 'static inline bool'
290         print 'is_symbolic_param(T param) {'
291         print '    return static_cast<T>(static_cast<GLenum>(param)) == param;'
292         print '}'
293         print
294
295         # Generate a helper function to know how many elements a parameter has
296         print 'static size_t'
297         print '_gl_param_size(GLenum pname) {'
298         print '    switch (pname) {'
299         for function, type, count, name in glparams.parameters:
300             if type is not None:
301                 print '    case %s: return %s;' % (name, count)
302         print '    default:'
303         print r'        os::log("apitrace: warning: %s: unknown GLenum 0x%04X\n", __FUNCTION__, pname);'
304         print '        return 1;'
305         print '    }'
306         print '}'
307         print
308
309         # states such as GL_UNPACK_ROW_LENGTH are not available in GLES
310         print 'static inline bool'
311         print 'can_unpack_subimage(void) {'
312         print '    gltrace::Context *ctx = gltrace::getContext();'
313         print '    return (ctx->profile == gltrace::PROFILE_COMPAT);'
314         print '}'
315         print
316
317     getProcAddressFunctionNames = []
318
319     def traceApi(self, api):
320         if self.getProcAddressFunctionNames:
321             # Generate a function to wrap proc addresses
322             getProcAddressFunction = api.getFunctionByName(self.getProcAddressFunctionNames[0])
323             argType = getProcAddressFunction.args[0].type
324             retType = getProcAddressFunction.type
325             
326             print 'static %s _wrapProcAddress(%s procName, %s procPtr);' % (retType, argType, retType)
327             print
328             
329             Tracer.traceApi(self, api)
330             
331             print 'static %s _wrapProcAddress(%s procName, %s procPtr) {' % (retType, argType, retType)
332
333             # Provide fallback functions to missing debug functions
334             print '    if (!procPtr) {'
335             else_ = ''
336             for function_name in self.debug_functions:
337                 if self.api.getFunctionByName(function_name):
338                     print '        %sif (strcmp("%s", (const char *)procName) == 0) {' % (else_, function_name)
339                     print '            return (%s)&%s;' % (retType, function_name)
340                     print '        }'
341                 else_ = 'else '
342             print '        %s{' % else_
343             print '            return NULL;'
344             print '        }'
345             print '    }'
346
347             for function in api.getAllFunctions():
348                 ptype = function_pointer_type(function)
349                 pvalue = function_pointer_value(function)
350                 print '    if (strcmp("%s", (const char *)procName) == 0) {' % function.name
351                 print '        %s = (%s)procPtr;' % (pvalue, ptype)
352                 print '        return (%s)&%s;' % (retType, function.name,)
353                 print '    }'
354             print '    os::log("apitrace: warning: unknown function \\"%s\\"\\n", (const char *)procName);'
355             print '    return procPtr;'
356             print '}'
357             print
358         else:
359             Tracer.traceApi(self, api)
360
361     def defineShadowBufferHelper(self):
362         print 'void _shadow_glGetBufferSubData(GLenum target, GLintptr offset,'
363         print '                                GLsizeiptr size, GLvoid *data)'
364         print '{'
365         print '    gltrace::Context *ctx = gltrace::getContext();'
366         print '    if (!ctx->needsShadowBuffers() || target != GL_ELEMENT_ARRAY_BUFFER) {'
367         print '        _glGetBufferSubData(target, offset, size, data);'
368         print '        return;'
369         print '    }'
370         print
371         print '    GLint buffer_binding = 0;'
372         print '    _glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &buffer_binding);'
373         print '    if (buffer_binding > 0) {'
374         print '        gltrace::Buffer & buf = ctx->buffers[buffer_binding];'
375         print '        buf.getSubData(offset, size, data);'
376         print '    }'
377         print '}'
378
379     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) {'
383         print '        GLint buffer_binding = 0;'
384         print '        _glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &buffer_binding);'
385         print '        if (buffer_binding > 0) {'
386         print '            gltrace::Buffer & buf = ctx->buffers[buffer_binding];'
387         print '            buf.' + method + ';'
388         print '        }'
389         print '    }'
390         print
391
392     def shadowBufferProlog(self, function):
393         if function.name == 'glBufferData':
394             self.shadowBufferMethod('bufferData(size, data)')
395
396         if function.name == 'glBufferSubData':
397             self.shadowBufferMethod('bufferSubData(offset, size, data)')
398
399         if function.name == 'glDeleteBuffers':
400             print '    gltrace::Context *ctx = gltrace::getContext();'
401             print '    if (ctx->needsShadowBuffers()) {'
402             print '        for (GLsizei i = 0; i < n; i++) {'
403             print '            ctx->buffers.erase(buffer[i]);'
404             print '        }'
405             print '    }'
406
407     array_pointer_function_names = set((
408         "glVertexPointer",
409         "glNormalPointer",
410         "glColorPointer",
411         "glIndexPointer",
412         "glTexCoordPointer",
413         "glEdgeFlagPointer",
414         "glFogCoordPointer",
415         "glSecondaryColorPointer",
416         
417         "glInterleavedArrays",
418
419         "glVertexPointerEXT",
420         "glNormalPointerEXT",
421         "glColorPointerEXT",
422         "glIndexPointerEXT",
423         "glTexCoordPointerEXT",
424         "glEdgeFlagPointerEXT",
425         "glFogCoordPointerEXT",
426         "glSecondaryColorPointerEXT",
427
428         "glVertexAttribPointer",
429         "glVertexAttribPointerARB",
430         "glVertexAttribPointerNV",
431         "glVertexAttribIPointer",
432         "glVertexAttribIPointerEXT",
433         "glVertexAttribLPointer",
434         "glVertexAttribLPointerEXT",
435         
436         #"glMatrixIndexPointerARB",
437     ))
438
439     draw_function_names = set((
440         'glDrawArrays',
441         'glDrawElements',
442         'glDrawRangeElements',
443         'glMultiDrawArrays',
444         'glMultiDrawElements',
445         'glDrawArraysInstanced',
446         "glDrawArraysInstancedBaseInstance",
447         'glDrawElementsInstanced',
448         'glDrawArraysInstancedARB',
449         'glDrawElementsInstancedARB',
450         'glDrawElementsBaseVertex',
451         'glDrawRangeElementsBaseVertex',
452         'glDrawElementsInstancedBaseVertex',
453         "glDrawElementsInstancedBaseInstance",
454         "glDrawElementsInstancedBaseVertexBaseInstance",
455         'glMultiDrawElementsBaseVertex',
456         'glDrawArraysIndirect',
457         'glDrawElementsIndirect',
458         'glMultiDrawArraysIndirect',
459         'glMultiDrawArraysIndirectAMD',
460         'glMultiDrawElementsIndirect',
461         'glMultiDrawElementsIndirectAMD',
462         'glDrawArraysEXT',
463         'glDrawRangeElementsEXT',
464         'glDrawRangeElementsEXT_size',
465         'glMultiDrawArraysEXT',
466         'glMultiDrawElementsEXT',
467         'glMultiModeDrawArraysIBM',
468         'glMultiModeDrawElementsIBM',
469         'glDrawArraysInstancedEXT',
470         'glDrawElementsInstancedEXT',
471     ))
472
473     interleaved_formats = [
474          'GL_V2F',
475          'GL_V3F',
476          'GL_C4UB_V2F',
477          'GL_C4UB_V3F',
478          'GL_C3F_V3F',
479          'GL_N3F_V3F',
480          'GL_C4F_N3F_V3F',
481          'GL_T2F_V3F',
482          'GL_T4F_V4F',
483          'GL_T2F_C4UB_V3F',
484          'GL_T2F_C3F_V3F',
485          'GL_T2F_N3F_V3F',
486          'GL_T2F_C4F_N3F_V3F',
487          'GL_T4F_C4F_N3F_V4F',
488     ]
489
490     def traceFunctionImplBody(self, function):
491         # Defer tracing of user array pointers...
492         if function.name in self.array_pointer_function_names:
493             print '    GLint _array_buffer = 0;'
494             print '    _glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &_array_buffer);'
495             print '    if (!_array_buffer) {'
496             print '        gltrace::Context *ctx = gltrace::getContext();'
497             print '        ctx->user_arrays = true;'
498             if function.name == "glVertexAttribPointerARB":
499                 print '        ctx->user_arrays_arb = true;'
500             if function.name == "glVertexAttribPointerNV":
501                 print '        ctx->user_arrays_nv = true;'
502             self.invokeFunction(function)
503
504             # And also break down glInterleavedArrays into the individual calls
505             if function.name == 'glInterleavedArrays':
506                 print
507
508                 # Initialize the enable flags
509                 for camelcase_name, uppercase_name in self.arrays:
510                     flag_name = '_' + uppercase_name.lower()
511                     print '        GLboolean %s = GL_FALSE;' % flag_name
512                 print
513
514                 # Switch for the interleaved formats
515                 print '        switch (format) {'
516                 for format in self.interleaved_formats:
517                     print '            case %s:' % format
518                     for camelcase_name, uppercase_name in self.arrays:
519                         flag_name = '_' + uppercase_name.lower()
520                         if format.find('_' + uppercase_name[0]) >= 0:
521                             print '                %s = GL_TRUE;' % flag_name
522                     print '                break;'
523                 print '            default:'
524                 print '               return;'
525                 print '        }'
526                 print
527
528                 # Emit fake glEnableClientState/glDisableClientState flags
529                 for camelcase_name, uppercase_name in self.arrays:
530                     flag_name = '_' + uppercase_name.lower()
531                     enable_name = 'GL_%s_ARRAY' % uppercase_name
532
533                     # Emit a fake function
534                     print '        {'
535                     print '            static const trace::FunctionSig &_sig = %s ? _glEnableClientState_sig : _glDisableClientState_sig;' % flag_name
536                     print '            unsigned _call = trace::localWriter.beginEnter(&_sig);'
537                     print '            trace::localWriter.beginArg(0);'
538                     self.serializeValue(glapi.GLenum, enable_name)
539                     print '            trace::localWriter.endArg();'
540                     print '            trace::localWriter.endEnter();'
541                     print '            trace::localWriter.beginLeave(_call);'
542                     print '            trace::localWriter.endLeave();'
543                     print '        }'
544
545             print '        return;'
546             print '    }'
547
548         # ... to the draw calls
549         if function.name in self.draw_function_names:
550             print '    if (_need_user_arrays()) {'
551             arg_names = ', '.join([arg.name for arg in function.args[1:]])
552             print '        GLuint _count = _%s_count(%s);' % (function.name, arg_names)
553             print '        _trace_user_arrays(_count);'
554             print '    }'
555         
556         # Emit a fake memcpy on buffer uploads
557         if function.name == 'glBufferParameteriAPPLE':
558             print '    if (pname == GL_BUFFER_FLUSHING_UNMAP_APPLE && param == GL_FALSE) {'
559             print '        _checkBufferFlushingUnmapAPPLE = true;'
560             print '    }'
561         if function.name in ('glUnmapBuffer', 'glUnmapBufferARB'):
562             if function.name.endswith('ARB'):
563                 suffix = 'ARB'
564             else:
565                 suffix = ''
566             print '    GLint access = 0;'
567             print '    _glGetBufferParameteriv%s(target, GL_BUFFER_ACCESS, &access);' % suffix
568             print '    if (access != GL_READ_ONLY) {'
569             print '        GLvoid *map = NULL;'
570             print '        _glGetBufferPointerv%s(target, GL_BUFFER_MAP_POINTER, &map);'  % suffix
571             print '        if (map) {'
572             print '            GLint length = -1;'
573             print '            bool flush = true;'
574             print '            if (_checkBufferMapRange) {'
575             print '                _glGetBufferParameteriv%s(target, GL_BUFFER_MAP_LENGTH, &length);' % suffix
576             print '                GLint access_flags = 0;'
577             print '                _glGetBufferParameteriv(target, GL_BUFFER_ACCESS_FLAGS, &access_flags);'
578             print '                flush = flush && !(access_flags & GL_MAP_FLUSH_EXPLICIT_BIT);'
579             print '                if (length == -1) {'
580             print '                    // Mesa drivers refuse GL_BUFFER_MAP_LENGTH without GL 3.0'
581             print '                    static bool warned = false;'
582             print '                    if (!warned) {'
583             print '                        os::log("apitrace: warning: glGetBufferParameteriv%s(GL_BUFFER_MAP_LENGTH) failed\\n");' % suffix
584             print '                        warned = true;'
585             print '                    }'
586             print '                    struct buffer_mapping *mapping = get_buffer_mapping(target);'
587             print '                    if (mapping) {'
588             print '                        length = mapping->length;'
589             print '                        flush = flush && !mapping->explicit_flush;'
590             print '                    } else {'
591             print '                        length = 0;'
592             print '                        flush = false;'
593             print '                    }'
594             print '                }'
595             print '            } else {'
596             print '                length = 0;'
597             print '                _glGetBufferParameteriv%s(target, GL_BUFFER_SIZE, &length);' % suffix
598             print '            }'
599             print '            if (_checkBufferFlushingUnmapAPPLE) {'
600             print '                GLint flushing_unmap = GL_TRUE;'
601             print '                _glGetBufferParameteriv%s(target, GL_BUFFER_FLUSHING_UNMAP_APPLE, &flushing_unmap);' % suffix
602             print '                flush = flush && flushing_unmap;'
603             print '            }'
604             print '            if (flush && length > 0) {'
605             self.emit_memcpy('map', 'map', 'length')
606             print '            }'
607             print '        }'
608             print '    }'
609         if function.name == 'glUnmapBufferOES':
610             print '    GLint access = 0;'
611             print '    _glGetBufferParameteriv(target, GL_BUFFER_ACCESS_OES, &access);'
612             print '    if (access == GL_WRITE_ONLY_OES) {'
613             print '        GLvoid *map = NULL;'
614             print '        _glGetBufferPointervOES(target, GL_BUFFER_MAP_POINTER_OES, &map);'
615             print '        GLint size = 0;'
616             print '        _glGetBufferParameteriv(target, GL_BUFFER_SIZE, &size);'
617             print '        if (map && size > 0) {'
618             self.emit_memcpy('map', 'map', 'size')
619             self.shadowBufferMethod('bufferSubData(0, size, map)')
620             print '        }'
621             print '    }'
622         if function.name == 'glUnmapNamedBufferEXT':
623             print '    GLint access_flags = 0;'
624             print '    _glGetNamedBufferParameterivEXT(buffer, GL_BUFFER_ACCESS_FLAGS, &access_flags);'
625             print '    if ((access_flags & GL_MAP_WRITE_BIT) && !(access_flags & GL_MAP_FLUSH_EXPLICIT_BIT)) {'
626             print '        GLvoid *map = NULL;'
627             print '        _glGetNamedBufferPointervEXT(buffer, GL_BUFFER_MAP_POINTER, &map);'
628             print '        GLint length = 0;'
629             print '        _glGetNamedBufferParameterivEXT(buffer, GL_BUFFER_MAP_LENGTH, &length);'
630             print '        if (map && length > 0) {'
631             self.emit_memcpy('map', 'map', 'length')
632             print '        }'
633             print '    }'
634         if function.name == 'glFlushMappedBufferRange':
635             print '    GLvoid *map = NULL;'
636             print '    _glGetBufferPointerv(target, GL_BUFFER_MAP_POINTER, &map);'
637             print '    if (map && length > 0) {'
638             self.emit_memcpy('(char *)map + offset', '(const char *)map + offset', 'length')
639             print '    }'
640         if function.name == 'glFlushMappedBufferRangeAPPLE':
641             print '    GLvoid *map = NULL;'
642             print '    _glGetBufferPointerv(target, GL_BUFFER_MAP_POINTER, &map);'
643             print '    if (map && size > 0) {'
644             self.emit_memcpy('(char *)map + offset', '(const char *)map + offset', 'size')
645             print '    }'
646         if function.name == 'glFlushMappedNamedBufferRangeEXT':
647             print '    GLvoid *map = NULL;'
648             print '    _glGetNamedBufferPointervEXT(buffer, GL_BUFFER_MAP_POINTER, &map);'
649             print '    if (map && length > 0) {'
650             self.emit_memcpy('(char *)map + offset', '(const char *)map + offset', 'length')
651             print '    }'
652
653         # Don't leave vertex attrib locations to chance.  Instead emit fake
654         # glBindAttribLocation calls to ensure that the same locations will be
655         # used when retracing.  Trying to remap locations after the fact would
656         # be an herculian task given that vertex attrib locations appear in
657         # many entry-points, including non-shader related ones.
658         if function.name == 'glLinkProgram':
659             Tracer.invokeFunction(self, function)
660             print '    GLint active_attributes = 0;'
661             print '    _glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &active_attributes);'
662             print '    for (GLint attrib = 0; attrib < active_attributes; ++attrib) {'
663             print '        GLint size = 0;'
664             print '        GLenum type = 0;'
665             print '        GLchar name[256];'
666             # TODO: Use ACTIVE_ATTRIBUTE_MAX_LENGTH instead of 256
667             print '        _glGetActiveAttrib(program, attrib, sizeof name, NULL, &size, &type, name);'
668             print "        if (name[0] != 'g' || name[1] != 'l' || name[2] != '_') {"
669             print '            GLint location = _glGetAttribLocation(program, name);'
670             print '            if (location >= 0) {'
671             bind_function = glapi.glapi.getFunctionByName('glBindAttribLocation')
672             self.fake_call(bind_function, ['program', 'location', 'name'])
673             print '            }'
674             print '        }'
675             print '    }'
676         if function.name == 'glLinkProgramARB':
677             Tracer.invokeFunction(self, function)
678             print '    GLint active_attributes = 0;'
679             print '    _glGetObjectParameterivARB(programObj, GL_OBJECT_ACTIVE_ATTRIBUTES_ARB, &active_attributes);'
680             print '    for (GLint attrib = 0; attrib < active_attributes; ++attrib) {'
681             print '        GLint size = 0;'
682             print '        GLenum type = 0;'
683             print '        GLcharARB name[256];'
684             # TODO: Use ACTIVE_ATTRIBUTE_MAX_LENGTH instead of 256
685             print '        _glGetActiveAttribARB(programObj, attrib, sizeof name, NULL, &size, &type, name);'
686             print "        if (name[0] != 'g' || name[1] != 'l' || name[2] != '_') {"
687             print '            GLint location = _glGetAttribLocationARB(programObj, name);'
688             print '            if (location >= 0) {'
689             bind_function = glapi.glapi.getFunctionByName('glBindAttribLocationARB')
690             self.fake_call(bind_function, ['programObj', 'location', 'name'])
691             print '            }'
692             print '        }'
693             print '    }'
694
695         self.shadowBufferProlog(function)
696
697         Tracer.traceFunctionImplBody(self, function)
698
699     # These entrypoints are only expected to be implemented by tools;
700     # drivers will probably not implement them.
701     marker_functions = [
702         # GL_GREMEDY_string_marker
703         'glStringMarkerGREMEDY',
704         # GL_GREMEDY_frame_terminator
705         'glFrameTerminatorGREMEDY',
706         # GL_EXT_debug_marker
707         'glInsertEventMarkerEXT',
708         'glPushGroupMarkerEXT',
709         'glPopGroupMarkerEXT',
710     ]
711
712     # These entrypoints may be implemented by drivers, but are also very useful
713     # for debugging / analysis tools.
714     debug_functions = [
715         # GL_KHR_debug
716         'glDebugMessageControl',
717         'glDebugMessageInsert',
718         'glDebugMessageCallback',
719         'glGetDebugMessageLog',
720         'glPushDebugGroup',
721         'glPopDebugGroup',
722         'glObjectLabel',
723         'glGetObjectLabel',
724         'glObjectPtrLabel',
725         'glGetObjectPtrLabel',
726         # GL_ARB_debug_output
727         'glDebugMessageControlARB',
728         'glDebugMessageInsertARB',
729         'glDebugMessageCallbackARB',
730         'glGetDebugMessageLogARB',
731         # GL_AMD_debug_output
732         'glDebugMessageEnableAMD',
733         'glDebugMessageInsertAMD',
734         'glDebugMessageCallbackAMD',
735         'glGetDebugMessageLogAMD',
736     ]
737
738     def invokeFunction(self, function):
739         if function.name in ('glLinkProgram', 'glLinkProgramARB'):
740             # These functions have been dispatched already
741             return
742
743         Tracer.invokeFunction(self, function)
744
745     def doInvokeFunction(self, function):
746         # Same as invokeFunction() but called both when trace is enabled or disabled.
747         #
748         # Used to modify the behavior of GL entry-points.
749
750         # Override GL extensions
751         if function.name in ('glGetString', 'glGetIntegerv', 'glGetStringi'):
752             Tracer.doInvokeFunction(self, function, prefix = 'gltrace::_', suffix = '_override')
753             return
754
755         # We implement GL_EXT_debug_marker, GL_GREMEDY_*, etc., and not the
756         # driver
757         if function.name in self.marker_functions:
758             return
759
760         if function.name in self.getProcAddressFunctionNames:
761             else_ = ''
762             for marker_function in self.marker_functions:
763                 if self.api.getFunctionByName(marker_function):
764                     print '    %sif (strcmp("%s", (const char *)%s) == 0) {' % (else_, marker_function, function.args[0].name)
765                     print '        _result = (%s)&%s;' % (function.type, marker_function)
766                     print '    }'
767                 else_ = 'else '
768             print '    %s{' % else_
769             Tracer.doInvokeFunction(self, function)
770
771             # Replace function addresses with ours
772             # XXX: Doing this here instead of wrapRet means that the trace will
773             # contain the addresses of the wrapper functions, and not the real
774             # functions, but in practice this should make no difference.
775             if function.name in self.getProcAddressFunctionNames:
776                 print '    _result = _wrapProcAddress(%s, _result);' % (function.args[0].name,)
777
778             print '    }'
779             return
780
781         Tracer.doInvokeFunction(self, function)
782
783     buffer_targets = [
784         'ARRAY_BUFFER',
785         'ELEMENT_ARRAY_BUFFER',
786         'PIXEL_PACK_BUFFER',
787         'PIXEL_UNPACK_BUFFER',
788         'UNIFORM_BUFFER',
789         'TEXTURE_BUFFER',
790         'TRANSFORM_FEEDBACK_BUFFER',
791         'COPY_READ_BUFFER',
792         'COPY_WRITE_BUFFER',
793         'DRAW_INDIRECT_BUFFER',
794         'ATOMIC_COUNTER_BUFFER',
795     ]
796
797     def wrapRet(self, function, instance):
798         Tracer.wrapRet(self, function, instance)
799
800         # Keep track of buffer mappings
801         if function.name in ('glMapBuffer', 'glMapBufferARB'):
802             print '    struct buffer_mapping *mapping = get_buffer_mapping(target);'
803             print '    if (mapping) {'
804             print '        mapping->map = %s;' % (instance)
805             print '        mapping->length = 0;'
806             print '        _glGetBufferParameteriv(target, GL_BUFFER_SIZE, &mapping->length);'
807             print '        mapping->write = (access != GL_READ_ONLY);'
808             print '        mapping->explicit_flush = false;'
809             print '    }'
810         if function.name == 'glMapBufferRange':
811             print '    if (access & GL_MAP_WRITE_BIT) {'
812             print '        _checkBufferMapRange = true;'
813             print '    }'
814             print '    struct buffer_mapping *mapping = get_buffer_mapping(target);'
815             print '    if (mapping) {'
816             print '        mapping->map = %s;' % (instance)
817             print '        mapping->length = length;'
818             print '        mapping->write = access & GL_MAP_WRITE_BIT;'
819             print '        mapping->explicit_flush = access & GL_MAP_FLUSH_EXPLICIT_BIT;'
820             print '    }'
821
822     boolean_names = [
823         'GL_FALSE',
824         'GL_TRUE',
825     ]
826
827     def gl_boolean(self, value):
828         return self.boolean_names[int(bool(value))]
829
830     # Names of the functions that unpack from a pixel buffer object.  See the
831     # ARB_pixel_buffer_object specification.
832     unpack_function_names = set([
833         'glBitmap',
834         'glColorSubTable',
835         'glColorTable',
836         'glCompressedMultiTexImage1DEXT',
837         'glCompressedMultiTexImage2DEXT',
838         'glCompressedMultiTexImage3DEXT',
839         'glCompressedMultiTexSubImage1DEXT',
840         'glCompressedMultiTexSubImage2DEXT',
841         'glCompressedMultiTexSubImage3DEXT',
842         'glCompressedTexImage1D',
843         'glCompressedTexImage2D',
844         'glCompressedTexImage3D',
845         'glCompressedTexSubImage1D',
846         'glCompressedTexSubImage2D',
847         'glCompressedTexSubImage3D',
848         'glCompressedTextureImage1DEXT',
849         'glCompressedTextureImage2DEXT',
850         'glCompressedTextureImage3DEXT',
851         'glCompressedTextureSubImage1DEXT',
852         'glCompressedTextureSubImage2DEXT',
853         'glCompressedTextureSubImage3DEXT',
854         'glConvolutionFilter1D',
855         'glConvolutionFilter2D',
856         'glDrawPixels',
857         'glMultiTexImage1DEXT',
858         'glMultiTexImage2DEXT',
859         'glMultiTexImage3DEXT',
860         'glMultiTexSubImage1DEXT',
861         'glMultiTexSubImage2DEXT',
862         'glMultiTexSubImage3DEXT',
863         'glPixelMapfv',
864         'glPixelMapuiv',
865         'glPixelMapusv',
866         'glPolygonStipple',
867         'glSeparableFilter2D',
868         'glTexImage1D',
869         'glTexImage1DEXT',
870         'glTexImage2D',
871         'glTexImage2DEXT',
872         'glTexImage3D',
873         'glTexImage3DEXT',
874         'glTexSubImage1D',
875         'glTexSubImage1DEXT',
876         'glTexSubImage2D',
877         'glTexSubImage2DEXT',
878         'glTexSubImage3D',
879         'glTexSubImage3DEXT',
880         'glTextureImage1DEXT',
881         'glTextureImage2DEXT',
882         'glTextureImage3DEXT',
883         'glTextureSubImage1DEXT',
884         'glTextureSubImage2DEXT',
885         'glTextureSubImage3DEXT',
886     ])
887
888     def serializeArgValue(self, function, arg):
889         # Recognize offsets instead of blobs when a PBO is bound
890         if function.name in self.unpack_function_names \
891            and (isinstance(arg.type, stdapi.Blob) \
892                 or (isinstance(arg.type, stdapi.Const) \
893                     and isinstance(arg.type.type, stdapi.Blob))):
894             print '    {'
895             print '        gltrace::Context *ctx = gltrace::getContext();'
896             print '        GLint _unpack_buffer = 0;'
897             print '        if (ctx->profile == gltrace::PROFILE_COMPAT)'
898             print '            _glGetIntegerv(GL_PIXEL_UNPACK_BUFFER_BINDING, &_unpack_buffer);'
899             print '        if (_unpack_buffer) {'
900             print '            trace::localWriter.writePointer((uintptr_t)%s);' % arg.name
901             print '        } else {'
902             Tracer.serializeArgValue(self, function, arg)
903             print '        }'
904             print '    }'
905             return
906
907         # Several GL state functions take GLenum symbolic names as
908         # integer/floats; so dump the symbolic name whenever possible
909         if function.name.startswith('gl') \
910            and arg.type in (glapi.GLint, glapi.GLfloat, glapi.GLdouble) \
911            and arg.name == 'param':
912             assert arg.index > 0
913             assert function.args[arg.index - 1].name == 'pname'
914             assert function.args[arg.index - 1].type == glapi.GLenum
915             print '    if (is_symbolic_pname(pname) && is_symbolic_param(%s)) {' % arg.name
916             self.serializeValue(glapi.GLenum, arg.name)
917             print '    } else {'
918             Tracer.serializeArgValue(self, function, arg)
919             print '    }'
920             return
921
922         Tracer.serializeArgValue(self, function, arg)
923
924     def footer(self, api):
925         Tracer.footer(self, api)
926
927         # A simple state tracker to track the pointer values
928         # update the state
929         print 'static void _trace_user_arrays(GLuint count)'
930         print '{'
931         print '    gltrace::Context *ctx = gltrace::getContext();'
932
933         for camelcase_name, uppercase_name in self.arrays:
934             # in which profile is the array available?
935             profile_check = 'ctx->profile == gltrace::PROFILE_COMPAT'
936             if camelcase_name in self.arrays_es1:
937                 profile_check = '(' + profile_check + ' || ctx->profile == gltrace::PROFILE_ES1)';
938
939             function_name = 'gl%sPointer' % camelcase_name
940             enable_name = 'GL_%s_ARRAY' % uppercase_name
941             binding_name = 'GL_%s_ARRAY_BUFFER_BINDING' % uppercase_name
942             function = api.getFunctionByName(function_name)
943
944             print '    // %s' % function.prototype()
945             print '  if (%s) {' % profile_check
946             self.array_trace_prolog(api, uppercase_name)
947             self.array_prolog(api, uppercase_name)
948             print '    if (_glIsEnabled(%s)) {' % enable_name
949             print '        GLint _binding = 0;'
950             print '        _glGetIntegerv(%s, &_binding);' % binding_name
951             print '        if (!_binding) {'
952
953             # Get the arguments via glGet*
954             for arg in function.args:
955                 arg_get_enum = 'GL_%s_ARRAY_%s' % (uppercase_name, arg.name.upper())
956                 arg_get_function, arg_type = TypeGetter().visit(arg.type)
957                 print '            %s %s = 0;' % (arg_type, arg.name)
958                 print '            _%s(%s, &%s);' % (arg_get_function, arg_get_enum, arg.name)
959             
960             arg_names = ', '.join([arg.name for arg in function.args[:-1]])
961             print '            size_t _size = _%s_size(%s, count);' % (function.name, arg_names)
962
963             # Emit a fake function
964             self.array_trace_intermezzo(api, uppercase_name)
965             print '            unsigned _call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,)
966             for arg in function.args:
967                 assert not arg.output
968                 print '            trace::localWriter.beginArg(%u);' % (arg.index,)
969                 if arg.name != 'pointer':
970                     self.serializeValue(arg.type, arg.name)
971                 else:
972                     print '            trace::localWriter.writeBlob((const void *)%s, _size);' % (arg.name)
973                 print '            trace::localWriter.endArg();'
974             
975             print '            trace::localWriter.endEnter();'
976             print '            trace::localWriter.beginLeave(_call);'
977             print '            trace::localWriter.endLeave();'
978             print '        }'
979             print '    }'
980             self.array_epilog(api, uppercase_name)
981             self.array_trace_epilog(api, uppercase_name)
982             print '  }'
983             print
984
985         # Samething, but for glVertexAttribPointer*
986         #
987         # Some variants of glVertexAttribPointer alias conventional and generic attributes:
988         # - glVertexAttribPointer: no
989         # - glVertexAttribPointerARB: implementation dependent
990         # - glVertexAttribPointerNV: yes
991         #
992         # This means that the implementations of these functions do not always
993         # alias, and they need to be considered independently.
994         #
995         print '    // ES1 does not support generic vertex attributes'
996         print '    if (ctx->profile == gltrace::PROFILE_ES1)'
997         print '        return;'
998         print
999         print '    vertex_attrib _vertex_attrib = _get_vertex_attrib();'
1000         print
1001         for suffix in ['', 'ARB', 'NV']:
1002             if suffix:
1003                 SUFFIX = '_' + suffix
1004             else:
1005                 SUFFIX = suffix
1006             function_name = 'glVertexAttribPointer' + suffix
1007             function = api.getFunctionByName(function_name)
1008
1009             print '    // %s' % function.prototype()
1010             print '    if (_vertex_attrib == VERTEX_ATTRIB%s) {' % SUFFIX
1011             if suffix == 'NV':
1012                 print '        GLint _max_vertex_attribs = 16;'
1013             else:
1014                 print '        GLint _max_vertex_attribs = 0;'
1015                 print '        _glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &_max_vertex_attribs);'
1016             print '        for (GLint index = 0; index < _max_vertex_attribs; ++index) {'
1017             print '            GLint _enabled = 0;'
1018             if suffix == 'NV':
1019                 print '            _glGetIntegerv(GL_VERTEX_ATTRIB_ARRAY0_NV + index, &_enabled);'
1020             else:
1021                 print '            _glGetVertexAttribiv%s(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED%s, &_enabled);' % (suffix, SUFFIX)
1022             print '            if (_enabled) {'
1023             print '                GLint _binding = 0;'
1024             if suffix != 'NV':
1025                 # It doesn't seem possible to use VBOs with NV_vertex_program.
1026                 print '                _glGetVertexAttribiv%s(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING%s, &_binding);' % (suffix, SUFFIX)
1027             print '                if (!_binding) {'
1028
1029             # Get the arguments via glGet*
1030             for arg in function.args[1:]:
1031                 if suffix == 'NV':
1032                     arg_get_enum = 'GL_ATTRIB_ARRAY_%s%s' % (arg.name.upper(), SUFFIX)
1033                 else:
1034                     arg_get_enum = 'GL_VERTEX_ATTRIB_ARRAY_%s%s' % (arg.name.upper(), SUFFIX)
1035                 arg_get_function, arg_type = TypeGetter('glGetVertexAttrib', False, suffix).visit(arg.type)
1036                 print '                    %s %s = 0;' % (arg_type, arg.name)
1037                 print '                    _%s(index, %s, &%s);' % (arg_get_function, arg_get_enum, arg.name)
1038             
1039             arg_names = ', '.join([arg.name for arg in function.args[1:-1]])
1040             print '                    size_t _size = _%s_size(%s, count);' % (function.name, arg_names)
1041
1042             # Emit a fake function
1043             print '                    unsigned _call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,)
1044             for arg in function.args:
1045                 assert not arg.output
1046                 print '                    trace::localWriter.beginArg(%u);' % (arg.index,)
1047                 if arg.name != 'pointer':
1048                     self.serializeValue(arg.type, arg.name)
1049                 else:
1050                     print '                    trace::localWriter.writeBlob((const void *)%s, _size);' % (arg.name)
1051                 print '                    trace::localWriter.endArg();'
1052             
1053             print '                    trace::localWriter.endEnter();'
1054             print '                    trace::localWriter.beginLeave(_call);'
1055             print '                    trace::localWriter.endLeave();'
1056             print '                }'
1057             print '            }'
1058             print '        }'
1059             print '    }'
1060             print
1061
1062         print '}'
1063         print
1064
1065     #
1066     # Hooks for glTexCoordPointer, which is identical to the other array
1067     # pointers except the fact that it is indexed by glClientActiveTexture.
1068     #
1069
1070     def array_prolog(self, api, uppercase_name):
1071         if uppercase_name == 'TEXTURE_COORD':
1072             print '    GLint client_active_texture = 0;'
1073             print '    _glGetIntegerv(GL_CLIENT_ACTIVE_TEXTURE, &client_active_texture);'
1074             print '    GLint max_texture_coords = 0;'
1075             print '    if (ctx->profile == gltrace::PROFILE_COMPAT)'
1076             print '        _glGetIntegerv(GL_MAX_TEXTURE_COORDS, &max_texture_coords);'
1077             print '    else'
1078             print '        _glGetIntegerv(GL_MAX_TEXTURE_UNITS, &max_texture_coords);'
1079             print '    for (GLint unit = 0; unit < max_texture_coords; ++unit) {'
1080             print '        GLint texture = GL_TEXTURE0 + unit;'
1081             print '        _glClientActiveTexture(texture);'
1082
1083     def array_trace_prolog(self, api, uppercase_name):
1084         if uppercase_name == 'TEXTURE_COORD':
1085             print '    bool client_active_texture_dirty = false;'
1086
1087     def array_epilog(self, api, uppercase_name):
1088         if uppercase_name == 'TEXTURE_COORD':
1089             print '    }'
1090         self.array_cleanup(api, uppercase_name)
1091
1092     def array_cleanup(self, api, uppercase_name):
1093         if uppercase_name == 'TEXTURE_COORD':
1094             print '    _glClientActiveTexture(client_active_texture);'
1095         
1096     def array_trace_intermezzo(self, api, uppercase_name):
1097         if uppercase_name == 'TEXTURE_COORD':
1098             print '    if (texture != client_active_texture || client_active_texture_dirty) {'
1099             print '        client_active_texture_dirty = true;'
1100             self.fake_glClientActiveTexture_call(api, "texture");
1101             print '    }'
1102
1103     def array_trace_epilog(self, api, uppercase_name):
1104         if uppercase_name == 'TEXTURE_COORD':
1105             print '    if (client_active_texture_dirty) {'
1106             self.fake_glClientActiveTexture_call(api, "client_active_texture");
1107             print '    }'
1108
1109     def fake_glClientActiveTexture_call(self, api, texture):
1110         function = api.getFunctionByName('glClientActiveTexture')
1111         self.fake_call(function, [texture])
1112
1113     def emitFakeTexture2D(self):
1114         function = glapi.glapi.getFunctionByName('glTexImage2D')
1115         instances = function.argNames()
1116         print '        unsigned _fake_call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,)
1117         for arg in function.args:
1118             assert not arg.output
1119             self.serializeArg(function, arg)
1120         print '        trace::localWriter.endEnter();'
1121         print '        trace::localWriter.beginLeave(_fake_call);'
1122         print '        trace::localWriter.endLeave();'
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133