]> git.cworth.org Git - apitrace/blob - gltrace.py
Silence warnings due to unused variables.
[apitrace] / 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 import stdapi
31 import glapi
32 import glparams
33 from glxapi import glxapi
34 from trace import Tracer, dump_instance
35
36
37 class TypeGetter(stdapi.Visitor):
38     '''Determine which glGet*v function that matches the specified type.'''
39
40     def __init__(self, prefix = 'glGet', long_suffix = True):
41         self.prefix = prefix
42         self.long_suffix = long_suffix
43
44     def visit_const(self, const):
45         return self.visit(const.type)
46
47     def visit_alias(self, alias):
48         if alias.expr == 'GLboolean':
49             if self.long_suffix:
50                 return self.prefix + 'Booleanv', alias.expr
51             else:
52                 return self.prefix + 'iv', 'GLint'
53         elif alias.expr == 'GLdouble':
54             if self.long_suffix:
55                 return self.prefix + 'Doublev', alias.expr
56             else:
57                 return self.prefix + 'dv', alias.expr
58         elif alias.expr == 'GLfloat':
59             if self.long_suffix:
60                 return self.prefix + 'Floatv', alias.expr
61             else:
62                 return self.prefix + 'fv', alias.expr
63         elif alias.expr in ('GLint', 'GLuint', 'GLsizei'):
64             if self.long_suffix:
65                 return self.prefix + 'Integerv', 'GLint'
66             else:
67                 return self.prefix + 'iv', 'GLint'
68         else:
69             print alias.expr
70             assert False
71     
72     def visit_enum(self, enum):
73         return self.visit(glapi.GLint)
74
75     def visit_bitmask(self, bitmask):
76         return self.visit(glapi.GLint)
77
78     def visit_opaque(self, pointer):
79         return self.prefix + 'Pointerv', 'GLvoid *'
80
81
82 class GlTracer(Tracer):
83
84     arrays = [
85         ("Vertex", "VERTEX"),
86         ("Normal", "NORMAL"),
87         ("Color", "COLOR"),
88         ("Index", "INDEX"),
89         ("TexCoord", "TEXTURE_COORD"),
90         ("EdgeFlag", "EDGE_FLAG"),
91         ("FogCoord", "FOG_COORD"),
92         ("SecondaryColor", "SECONDARY_COLOR"),
93     ]
94     arrays.reverse()
95
96     def header(self, api):
97         Tracer.header(self, api)
98
99         print '// Whether user arrays were used'
100         print 'static bool __user_arrays = false;'
101         print
102         # Whether we need user arrays
103         print 'static inline bool __need_user_arrays(void)'
104         print '{'
105         print '    if (!__user_arrays) {'
106         print '        return false;'
107         print '    }'
108         print
109
110         for camelcase_name, uppercase_name in self.arrays:
111             function_name = 'gl%sPointer' % camelcase_name
112             enable_name = 'GL_%s_ARRAY' % uppercase_name
113             binding_name = 'GL_%s_ARRAY_BUFFER_BINDING' % uppercase_name
114             print '    // %s' % function_name
115             self.array_prolog(api, uppercase_name)
116             print '    if (__glIsEnabled(%s)) {' % enable_name
117             print '        GLint __binding = 0;'
118             print '        __glGetIntegerv(%s, &__binding);' % binding_name
119             print '        if (!__binding) {'
120             self.array_cleanup(api, uppercase_name)
121             print '            return true;'
122             print '        }'
123             print '    }'
124             self.array_epilog(api, uppercase_name)
125             print
126
127         print '    // glVertexAttribPointer'
128         print '    GLint __max_vertex_attribs = 0;'
129         print '    __glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &__max_vertex_attribs);'
130         print '    for (GLint index = 0; index < __max_vertex_attribs; ++index) {'
131         print '        GLint __enabled = 0;'
132         print '        __glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &__enabled);'
133         print '        if (__enabled) {'
134         print '            GLint __binding = 0;'
135         print '            __glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &__binding);'
136         print '            if (!__binding) {'
137         print '                return true;'
138         print '            }'
139         print '        }'
140         print '    }'
141         print
142
143         print '    return false;'
144         print '}'
145         print
146
147         print 'static void __trace_user_arrays(GLuint maxindex);'
148         print
149
150         print 'struct buffer_mapping {'
151         print '    void *map;'
152         print '    GLint length;'
153         print '    bool write;'
154         print '    bool explicit_flush;'
155         print '};'
156         print
157         for target in self.buffer_targets:
158             print 'struct buffer_mapping __%s_mapping;' % target.lower();
159         print
160         print 'static inline struct buffer_mapping *'
161         print 'get_buffer_mapping(GLenum target) {'
162         print '    switch(target) {'
163         for target in self.buffer_targets:
164             print '    case GL_%s:' % target
165             print '        return & __%s_mapping;' % target.lower()
166         print '    default:'
167         print '        OS::DebugMessage("warning: unknown buffer target 0x%04X\\n", target);'
168         print '        return NULL;'
169         print '    }'
170         print '}'
171         print
172
173         # Generate memcpy's signature
174         self.trace_function_decl(glapi.memcpy)
175
176         # Generate a helper function to determine whether a parameter name
177         # refers to a symbolic value or not
178         print 'static bool'
179         print 'is_symbolic_pname(GLenum pname) {'
180         print '    switch(pname) {'
181         for function, type, count, name in glparams.parameters:
182             if type is glapi.GLenum:
183                 print '    case %s:' % name
184         print '        return true;'
185         print '    default:'
186         print '        return false;'
187         print '    }'
188         print '}'
189         print
190         
191         # Generate a helper function to determine whether a parameter value is
192         # potentially symbolic or not; i.e., if the value can be represented in
193         # an enum or not
194         print 'template<class T>'
195         print 'static inline bool'
196         print 'is_symbolic_param(T param) {'
197         print '    return static_cast<T>(static_cast<GLenum>(param)) == param;'
198         print '}'
199         print
200
201         # Generate a helper function to know how many elements a parameter has
202         print 'static size_t'
203         print '__gl_param_size(GLenum pname) {'
204         print '    switch(pname) {'
205         for function, type, count, name in glparams.parameters:
206             if type is not None:
207                 print '    case %s: return %u;' % (name, count)
208         print '    case GL_COMPRESSED_TEXTURE_FORMATS: {'
209         print '            GLint num_compressed_texture_formats = 0;'
210         print '            __glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &num_compressed_texture_formats);'
211         print '            return num_compressed_texture_formats;'
212         print '        }'
213         print '    default:'
214         print r'        OS::DebugMessage("warning: %s: unknown GLenum 0x%04X\n", __FUNCTION__, pname);'
215         print '        return 1;'
216         print '    }'
217         print '}'
218         print
219
220     array_pointer_function_names = set((
221         "glVertexPointer",
222         "glNormalPointer",
223         "glColorPointer",
224         "glIndexPointer",
225         "glTexCoordPointer",
226         "glEdgeFlagPointer",
227         "glFogCoordPointer",
228         "glSecondaryColorPointer",
229         
230         "glInterleavedArrays",
231
232         "glVertexPointerEXT",
233         "glNormalPointerEXT",
234         "glColorPointerEXT",
235         "glIndexPointerEXT",
236         "glTexCoordPointerEXT",
237         "glEdgeFlagPointerEXT",
238         "glFogCoordPointerEXT",
239         "glSecondaryColorPointerEXT",
240
241         "glVertexAttribPointer",
242         "glVertexAttribPointerARB",
243         "glVertexAttribPointerNV",
244         "glVertexAttribIPointer",
245         "glVertexAttribIPointerEXT",
246         "glVertexAttribLPointer",
247         "glVertexAttribLPointerEXT",
248         
249         #"glMatrixIndexPointerARB",
250     ))
251
252     draw_function_names = set((
253         'glDrawArrays',
254         'glDrawElements',
255         'glDrawRangeElements',
256         'glMultiDrawArrays',
257         'glMultiDrawElements',
258         'glDrawArraysInstanced',
259         'glDrawElementsInstanced',
260         'glDrawArraysInstancedARB',
261         'glDrawElementsInstancedARB',
262         'glDrawElementsBaseVertex',
263         'glDrawRangeElementsBaseVertex',
264         'glDrawElementsInstancedBaseVertex',
265         'glMultiDrawElementsBaseVertex',
266         'glDrawArraysIndirect',
267         'glDrawElementsIndirect',
268         'glDrawArraysEXT',
269         'glDrawRangeElementsEXT',
270         'glDrawRangeElementsEXT_size',
271         'glMultiDrawArraysEXT',
272         'glMultiDrawElementsEXT',
273         'glMultiModeDrawArraysIBM',
274         'glMultiModeDrawElementsIBM',
275         'glDrawArraysInstancedEXT',
276         'glDrawElementsInstancedEXT',
277     ))
278
279     interleaved_formats = [
280          'GL_V2F',
281          'GL_V3F',
282          'GL_C4UB_V2F',
283          'GL_C4UB_V3F',
284          'GL_C3F_V3F',
285          'GL_N3F_V3F',
286          'GL_C4F_N3F_V3F',
287          'GL_T2F_V3F',
288          'GL_T4F_V4F',
289          'GL_T2F_C4UB_V3F',
290          'GL_T2F_C3F_V3F',
291          'GL_T2F_N3F_V3F',
292          'GL_T2F_C4F_N3F_V3F',
293          'GL_T4F_C4F_N3F_V4F',
294     ]
295
296     def trace_function_impl_body(self, function):
297         # Defer tracing of user array pointers...
298         if function.name in self.array_pointer_function_names:
299             print '    GLint __array_buffer = 0;'
300             print '    __glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &__array_buffer);'
301             print '    if (!__array_buffer) {'
302             print '        __user_arrays = true;'
303             self.dispatch_function(function)
304
305             # And also break down glInterleavedArrays into the individual calls
306             if function.name == 'glInterleavedArrays':
307                 print
308
309                 # Initialize the enable flags
310                 for camelcase_name, uppercase_name in self.arrays:
311                     flag_name = '__' + uppercase_name.lower()
312                     print '        GLboolean %s = GL_FALSE;' % flag_name
313                 print
314
315                 # Switch for the interleaved formats
316                 print '        switch (format) {'
317                 for format in self.interleaved_formats:
318                     print '            case %s:' % format
319                     for camelcase_name, uppercase_name in self.arrays:
320                         flag_name = '__' + uppercase_name.lower()
321                         if format.find('_' + uppercase_name[0]) >= 0:
322                             print '                %s = GL_TRUE;' % flag_name
323                     print '                break;'
324                 print '            default:'
325                 print '               return;'
326                 print '        }'
327                 print
328
329                 # Emit fake glEnableClientState/glDisableClientState flags
330                 for camelcase_name, uppercase_name in self.arrays:
331                     flag_name = '__' + uppercase_name.lower()
332                     enable_name = 'GL_%s_ARRAY' % uppercase_name
333
334                     # Emit a fake function
335                     print '        {'
336                     print '            static const Trace::FunctionSig &__sig = %s ? __glEnableClientState_sig : __glDisableClientState_sig;' % flag_name
337                     print '            unsigned __call = Trace::BeginEnter(__sig);'
338                     print '            Trace::BeginArg(0);'
339                     dump_instance(glapi.GLenum, enable_name)
340                     print '            Trace::EndArg();'
341                     print '            Trace::EndEnter();'
342                     print '            Trace::BeginLeave(__call);'
343                     print '            Trace::EndLeave();'
344                     print '        }'
345
346             print '        return;'
347             print '    }'
348
349         # ... to the draw calls
350         if function.name in self.draw_function_names:
351             print '    if (__need_user_arrays()) {'
352             arg_names = ', '.join([arg.name for arg in function.args[1:]])
353             print '        GLuint maxindex = __%s_maxindex(%s);' % (function.name, arg_names)
354             print '        __trace_user_arrays(maxindex);'
355             print '    }'
356         
357         # Emit a fake memcpy on buffer uploads
358         if function.name in ('glUnmapBuffer', 'glUnmapBufferARB', ):
359             print '    struct buffer_mapping *mapping = get_buffer_mapping(target);'
360             print '    if (mapping && mapping->write && !mapping->explicit_flush) {'
361             self.emit_memcpy('mapping->map', 'mapping->map', 'mapping->length')
362             print '    }'
363         if function.name in ('glFlushMappedBufferRange', 'glFlushMappedBufferRangeAPPLE'):
364             # TODO: avoid copying [0, offset] bytes
365             print '    struct buffer_mapping *mapping = get_buffer_mapping(target);'
366             print '    if (mapping) {'
367             if function.name.endswith('APPLE'):
368                  print '        GLsizeiptr length = size;'
369                  print '        mapping->explicit_flush = true;'
370             print '        //assert(offset + length <= mapping->length);'
371             self.emit_memcpy('mapping->map', 'mapping->map', 'offset + length')
372             print '    }'
373         # FIXME: glFlushMappedNamedBufferRangeEXT
374
375         Tracer.trace_function_impl_body(self, function)
376
377     def emit_memcpy(self, dest, src, length):
378         print '        unsigned __call = Trace::BeginEnter(__memcpy_sig);'
379         print '        Trace::BeginArg(0);'
380         print '        Trace::LiteralOpaque(%s);' % dest
381         print '        Trace::EndArg();'
382         print '        Trace::BeginArg(1);'
383         print '        Trace::LiteralBlob(%s, %s);' % (src, length)
384         print '        Trace::EndArg();'
385         print '        Trace::BeginArg(2);'
386         print '        Trace::LiteralUInt(%s);' % length
387         print '        Trace::EndArg();'
388         print '        Trace::EndEnter();'
389         print '        Trace::BeginLeave(__call);'
390         print '        Trace::EndLeave();'
391        
392     buffer_targets = [
393         'ARRAY_BUFFER',
394         'ELEMENT_ARRAY_BUFFER',
395         'PIXEL_PACK_BUFFER',
396         'PIXEL_UNPACK_BUFFER',
397     ]
398
399     def wrap_ret(self, function, instance):
400         Tracer.wrap_ret(self, function, instance)
401             
402         if function.name in ('glMapBuffer', 'glMapBufferARB'):
403             print '    struct buffer_mapping *mapping = get_buffer_mapping(target);'
404             print '    if (mapping) {'
405             print '        mapping->map = %s;' % (instance)
406             print '        mapping->length = 0;'
407             print '        __glGetBufferParameteriv(target, GL_BUFFER_SIZE, &mapping->length);'
408             print '        mapping->write = (access != GL_READ_ONLY);'
409             print '        mapping->explicit_flush = false;'
410             print '    }'
411
412         if function.name == 'glMapBufferRange':
413             print '    struct buffer_mapping *mapping = get_buffer_mapping(target);'
414             print '    if (mapping) {'
415             print '        mapping->map = %s;' % (instance)
416             print '        mapping->length = length;'
417             print '        mapping->write = access & GL_MAP_WRITE_BIT;'
418             print '        mapping->explicit_flush = access & GL_MAP_FLUSH_EXPLICIT_BIT;'
419             print '    }'
420
421     boolean_names = [
422         'GL_FALSE',
423         'GL_TRUE',
424     ]
425
426     def gl_boolean(self, value):
427         return self.boolean_names[int(bool(value))]
428
429     def dump_arg_instance(self, function, arg):
430         if function.name in self.draw_function_names and arg.name == 'indices':
431             print '    GLint __element_array_buffer = 0;'
432             print '    __glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &__element_array_buffer);'
433             print '    if (!__element_array_buffer) {'
434             if isinstance(arg.type, stdapi.Array):
435                 Tracer.dump_arg_instance(self, function, arg)
436                 print '        Trace::BeginArray(%s);' % arg.type.length
437                 print '        for(GLsizei i = 0; i < %s; ++i) {' % arg.type.length
438                 print '            Trace::BeginElement();'
439                 print '            Trace::LiteralBlob((const void *)%s, count[i]*__gl_type_size(type));' % (arg.name)
440                 print '            Trace::EndElement();'
441                 print '        }'
442                 print '        Trace::EndArray();'
443             else:
444                 print '        Trace::LiteralBlob((const void *)%s, count*__gl_type_size(type));' % (arg.name)
445             print '    } else {'
446             Tracer.dump_arg_instance(self, function, arg)
447             print '    }'
448             return
449
450         # Several GL state functions take GLenum symbolic names as
451         # integer/floats; so dump the symbolic name whenever possible
452         if arg.type in (glapi.GLint, glapi.GLfloat) and arg.name == 'param':
453             assert arg.index > 0
454             assert function.args[arg.index - 1].name == 'pname'
455             assert function.args[arg.index - 1].type == glapi.GLenum
456             print '    if (is_symbolic_pname(pname) && is_symbolic_param(%s)) {' % arg.name
457             dump_instance(glapi.GLenum, arg.name)
458             print '    } else {'
459             Tracer.dump_arg_instance(self, function, arg)
460             print '    }'
461             return
462
463         Tracer.dump_arg_instance(self, function, arg)
464
465     def footer(self, api):
466         Tracer.footer(self, api)
467
468         # A simple state tracker to track the pointer values
469         # update the state
470         print 'static void __trace_user_arrays(GLuint maxindex)'
471         print '{'
472
473         for camelcase_name, uppercase_name in self.arrays:
474             function_name = 'gl%sPointer' % camelcase_name
475             enable_name = 'GL_%s_ARRAY' % uppercase_name
476             binding_name = 'GL_%s_ARRAY_BUFFER_BINDING' % uppercase_name
477             function = api.get_function_by_name(function_name)
478
479             print '    // %s' % function.name
480             self.array_trace_prolog(api, uppercase_name)
481             self.array_prolog(api, uppercase_name)
482             print '    if (__glIsEnabled(%s)) {' % enable_name
483             print '        GLint __binding = 0;'
484             print '        __glGetIntegerv(%s, &__binding);' % binding_name
485             print '        if (!__binding) {'
486
487             # Get the arguments via glGet*
488             for arg in function.args:
489                 arg_get_enum = 'GL_%s_ARRAY_%s' % (uppercase_name, arg.name.upper())
490                 arg_get_function, arg_type = TypeGetter().visit(arg.type)
491                 print '            %s %s = 0;' % (arg_type, arg.name)
492                 print '            __%s(%s, &%s);' % (arg_get_function, arg_get_enum, arg.name)
493             
494             arg_names = ', '.join([arg.name for arg in function.args[:-1]])
495             print '            size_t __size = __%s_size(%s, maxindex);' % (function.name, arg_names)
496
497             # Emit a fake function
498             self.array_trace_intermezzo(api, uppercase_name)
499             print '            unsigned __call = Trace::BeginEnter(__%s_sig);' % (function.name,)
500             for arg in function.args:
501                 assert not arg.output
502                 print '            Trace::BeginArg(%u);' % (arg.index,)
503                 if arg.name != 'pointer':
504                     dump_instance(arg.type, arg.name)
505                 else:
506                     print '            Trace::LiteralBlob((const void *)%s, __size);' % (arg.name)
507                 print '            Trace::EndArg();'
508             
509             print '            Trace::EndEnter();'
510             print '            Trace::BeginLeave(__call);'
511             print '            Trace::EndLeave();'
512             print '        }'
513             print '    }'
514             self.array_epilog(api, uppercase_name)
515             self.array_trace_epilog(api, uppercase_name)
516             print
517
518         # Samething, but for glVertexAttribPointer
519         print '    // glVertexAttribPointer'
520         print '    GLint __max_vertex_attribs = 0;'
521         print '    __glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &__max_vertex_attribs);'
522         print '    for (GLint index = 0; index < __max_vertex_attribs; ++index) {'
523         print '        GLint __enabled = 0;'
524         print '        __glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &__enabled);'
525         print '        if (__enabled) {'
526         print '            GLint __binding = 0;'
527         print '            __glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &__binding);'
528         print '            if (!__binding) {'
529
530         function = api.get_function_by_name('glVertexAttribPointer')
531
532         # Get the arguments via glGet*
533         for arg in function.args[1:]:
534             arg_get_enum = 'GL_VERTEX_ATTRIB_ARRAY_%s' % (arg.name.upper(),)
535             arg_get_function, arg_type = TypeGetter('glGetVertexAttrib', False).visit(arg.type)
536             print '                %s %s = 0;' % (arg_type, arg.name)
537             print '                __%s(index, %s, &%s);' % (arg_get_function, arg_get_enum, arg.name)
538         
539         arg_names = ', '.join([arg.name for arg in function.args[1:-1]])
540         print '                size_t __size = __%s_size(%s, maxindex);' % (function.name, arg_names)
541
542         # Emit a fake function
543         print '                unsigned __call = Trace::BeginEnter(__%s_sig);' % (function.name,)
544         for arg in function.args:
545             assert not arg.output
546             print '                Trace::BeginArg(%u);' % (arg.index,)
547             if arg.name != 'pointer':
548                 dump_instance(arg.type, arg.name)
549             else:
550                 print '                Trace::LiteralBlob((const void *)%s, __size);' % (arg.name)
551             print '                Trace::EndArg();'
552         
553         print '                Trace::EndEnter();'
554         print '                Trace::BeginLeave(__call);'
555         print '                Trace::EndLeave();'
556         print '            }'
557         print '        }'
558         print '    }'
559         print
560
561         print '}'
562         print
563
564     #
565     # Hooks for glTexCoordPointer, which is identical to the other array
566     # pointers except the fact that it is indexed by glClientActiveTexture.
567     #
568
569     def array_prolog(self, api, uppercase_name):
570         if uppercase_name == 'TEXTURE_COORD':
571             print '    GLint client_active_texture = 0;'
572             print '    __glGetIntegerv(GL_CLIENT_ACTIVE_TEXTURE, &client_active_texture);'
573             print '    GLint max_texture_coords = 0;'
574             print '    __glGetIntegerv(GL_MAX_TEXTURE_COORDS, &max_texture_coords);'
575             print '    for (GLint unit = 0; unit < max_texture_coords; ++unit) {'
576             print '        GLenum texture = GL_TEXTURE0 + unit;'
577             print '        __glClientActiveTexture(texture);'
578
579     def array_trace_prolog(self, api, uppercase_name):
580         if uppercase_name == 'TEXTURE_COORD':
581             print '    bool client_active_texture_dirty = false;'
582
583     def array_epilog(self, api, uppercase_name):
584         if uppercase_name == 'TEXTURE_COORD':
585             print '    }'
586         self.array_cleanup(api, uppercase_name)
587
588     def array_cleanup(self, api, uppercase_name):
589         if uppercase_name == 'TEXTURE_COORD':
590             print '    __glClientActiveTexture(client_active_texture);'
591         
592     def array_trace_intermezzo(self, api, uppercase_name):
593         if uppercase_name == 'TEXTURE_COORD':
594             print '    if (texture != client_active_texture || client_active_texture_dirty) {'
595             print '        client_active_texture_dirty = true;'
596             self.fake_glClientActiveTexture_call(api, "texture");
597             print '    }'
598
599     def array_trace_epilog(self, api, uppercase_name):
600         if uppercase_name == 'TEXTURE_COORD':
601             print '    if (client_active_texture_dirty) {'
602             self.fake_glClientActiveTexture_call(api, "client_active_texture");
603             print '    }'
604
605     def fake_glClientActiveTexture_call(self, api, texture):
606         function = api.get_function_by_name('glClientActiveTexture')
607         self.fake_call(function, [texture])
608
609     def fake_call(self, function, args):
610         print '            unsigned __fake_call = Trace::BeginEnter(__%s_sig);' % (function.name,)
611         for arg, instance in zip(function.args, args):
612             assert not arg.output
613             print '            Trace::BeginArg(%u);' % (arg.index,)
614             dump_instance(arg.type, instance)
615             print '            Trace::EndArg();'
616         print '            Trace::EndEnter();'
617         print '            Trace::BeginLeave(__fake_call);'
618         print '            Trace::EndLeave();'
619
620
621
622
623
624
625
626
627
628
629