]> git.cworth.org Git - apitrace/blob - gltrace.py
Update glext headers.
[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, ext_suffix = ''):
41         self.prefix = prefix
42         self.long_suffix = long_suffix
43         self.ext_suffix = ext_suffix
44
45     def visit_const(self, const):
46         return self.visit(const.type)
47
48     def visit_alias(self, alias):
49         if alias.expr == 'GLboolean':
50             if self.long_suffix:
51                 suffix = 'Booleanv'
52                 arg_type = alias.expr
53             else:
54                 suffix = 'iv'
55                 arg_type = 'GLint'
56         elif alias.expr == 'GLdouble':
57             if self.long_suffix:
58                 suffix = 'Doublev'
59                 arg_type = alias.expr
60             else:
61                 suffix = 'dv'
62                 arg_type = alias.expr
63         elif alias.expr == 'GLfloat':
64             if self.long_suffix:
65                 suffix = 'Floatv'
66                 arg_type = alias.expr
67             else:
68                 suffix = 'fv'
69                 arg_type = alias.expr
70         elif alias.expr in ('GLint', 'GLuint', 'GLsizei'):
71             if self.long_suffix:
72                 suffix = 'Integerv'
73                 arg_type = 'GLint'
74             else:
75                 suffix = 'iv'
76                 arg_type = 'GLint'
77         else:
78             print alias.expr
79             assert False
80         function_name = self.prefix + suffix + self.ext_suffix
81         return function_name, arg_type
82     
83     def visit_enum(self, enum):
84         return self.visit(glapi.GLint)
85
86     def visit_bitmask(self, bitmask):
87         return self.visit(glapi.GLint)
88
89     def visit_opaque(self, pointer):
90         return self.prefix + 'Pointerv' + self.ext_suffix, 'GLvoid *'
91
92
93 class GlTracer(Tracer):
94
95     arrays = [
96         ("Vertex", "VERTEX"),
97         ("Normal", "NORMAL"),
98         ("Color", "COLOR"),
99         ("Index", "INDEX"),
100         ("TexCoord", "TEXTURE_COORD"),
101         ("EdgeFlag", "EDGE_FLAG"),
102         ("FogCoord", "FOG_COORD"),
103         ("SecondaryColor", "SECONDARY_COLOR"),
104     ]
105     arrays.reverse()
106
107     def header(self, api):
108         Tracer.header(self, api)
109
110         print '// Whether user arrays were used'
111         print 'static bool __user_arrays = false;'
112         print 'static bool __user_arrays_arb = false;'
113         print 'static bool __user_arrays_nv = false;'
114         print
115         
116         # Which glVertexAttrib* variant to use
117         print 'enum vertex_attrib {'
118         print '    VERTEX_ATTRIB,'
119         print '    VERTEX_ATTRIB_ARB,'
120         print '    VERTEX_ATTRIB_NV,'
121         print '};'
122         print
123         print 'static vertex_attrib __get_vertex_attrib(void) {'
124         print '    if (__user_arrays_arb || __user_arrays_nv) {'
125         print '        GLboolean __vertex_program = GL_FALSE;'
126         print '        __glGetBooleanv(GL_VERTEX_PROGRAM_ARB, &__vertex_program);'
127         print '        if (__vertex_program) {'
128         print '            if (__user_arrays_nv) {'
129         print '                GLint __vertex_program_binding_nv = 0;'
130         print '                __glGetIntegerv(GL_VERTEX_PROGRAM_BINDING_NV, &__vertex_program_binding_nv);'
131         print '                if (__vertex_program_binding_nv) {'
132         print '                    return VERTEX_ATTRIB_NV;'
133         print '                }'
134         print '            }'
135         print '            return VERTEX_ATTRIB_ARB;'
136         print '        }'
137         print '    }'
138         print '    return VERTEX_ATTRIB;'
139         print '}'
140         print
141
142         # Whether we need user arrays
143         print 'static inline bool __need_user_arrays(void)'
144         print '{'
145         print '    if (!__user_arrays) {'
146         print '        return false;'
147         print '    }'
148         print
149
150         for camelcase_name, uppercase_name in self.arrays:
151             function_name = 'gl%sPointer' % camelcase_name
152             enable_name = 'GL_%s_ARRAY' % uppercase_name
153             binding_name = 'GL_%s_ARRAY_BUFFER_BINDING' % uppercase_name
154             print '    // %s' % function_name
155             self.array_prolog(api, uppercase_name)
156             print '    if (__glIsEnabled(%s)) {' % enable_name
157             print '        GLint __binding = 0;'
158             print '        __glGetIntegerv(%s, &__binding);' % binding_name
159             print '        if (!__binding) {'
160             self.array_cleanup(api, uppercase_name)
161             print '            return true;'
162             print '        }'
163             print '    }'
164             self.array_epilog(api, uppercase_name)
165             print
166
167         print '    vertex_attrib __vertex_attrib = __get_vertex_attrib();'
168         print
169         print '    // glVertexAttribPointer'
170         print '    if (__vertex_attrib == VERTEX_ATTRIB) {'
171         print '        GLint __max_vertex_attribs = 0;'
172         print '        __glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &__max_vertex_attribs);'
173         print '        for (GLint index = 0; index < __max_vertex_attribs; ++index) {'
174         print '            GLint __enabled = 0;'
175         print '            __glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &__enabled);'
176         print '            if (__enabled) {'
177         print '                GLint __binding = 0;'
178         print '                __glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &__binding);'
179         print '                if (!__binding) {'
180         print '                    return true;'
181         print '                }'
182         print '            }'
183         print '        }'
184         print '    }'
185         print
186         print '    // glVertexAttribPointerARB'
187         print '    if (__vertex_attrib == VERTEX_ATTRIB_ARB) {'
188         print '        GLint __max_vertex_attribs = 0;'
189         print '        __glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &__max_vertex_attribs);'
190         print '        for (GLint index = 0; index < __max_vertex_attribs; ++index) {'
191         print '            GLint __enabled = 0;'
192         print '            __glGetVertexAttribivARB(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB, &__enabled);'
193         print '            if (__enabled) {'
194         print '                GLint __binding = 0;'
195         print '                __glGetVertexAttribivARB(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB, &__binding);'
196         print '                if (!__binding) {'
197         print '                    return true;'
198         print '                }'
199         print '            }'
200         print '        }'
201         print '    }'
202         print
203         print '    // glVertexAttribPointerNV'
204         print '    if (__vertex_attrib == VERTEX_ATTRIB_NV) {'
205         print '        for (GLint index = 0; index < 16; ++index) {'
206         print '            GLint __enabled = 0;'
207         print '            __glGetIntegerv(GL_VERTEX_ATTRIB_ARRAY0_NV + index, &__enabled);'
208         print '            if (__enabled) {'
209         print '                return true;'
210         print '            }'
211         print '        }'
212         print '    }'
213         print
214
215         print '    return false;'
216         print '}'
217         print
218
219         print 'static void __trace_user_arrays(GLuint maxindex);'
220         print
221
222         print 'struct buffer_mapping {'
223         print '    void *map;'
224         print '    GLint length;'
225         print '    bool write;'
226         print '    bool explicit_flush;'
227         print '};'
228         print
229         for target in self.buffer_targets:
230             print 'struct buffer_mapping __%s_mapping;' % target.lower();
231         print
232         print 'static inline struct buffer_mapping *'
233         print 'get_buffer_mapping(GLenum target) {'
234         print '    switch(target) {'
235         for target in self.buffer_targets:
236             print '    case GL_%s:' % target
237             print '        return & __%s_mapping;' % target.lower()
238         print '    default:'
239         print '        OS::DebugMessage("apitrace: warning: unknown buffer target 0x%04X\\n", target);'
240         print '        return NULL;'
241         print '    }'
242         print '}'
243         print
244
245         # Generate memcpy's signature
246         self.trace_function_decl(glapi.memcpy)
247
248         # Generate a helper function to determine whether a parameter name
249         # refers to a symbolic value or not
250         print 'static bool'
251         print 'is_symbolic_pname(GLenum pname) {'
252         print '    switch(pname) {'
253         for function, type, count, name in glparams.parameters:
254             if type is glapi.GLenum:
255                 print '    case %s:' % name
256         print '        return true;'
257         print '    default:'
258         print '        return false;'
259         print '    }'
260         print '}'
261         print
262         
263         # Generate a helper function to determine whether a parameter value is
264         # potentially symbolic or not; i.e., if the value can be represented in
265         # an enum or not
266         print 'template<class T>'
267         print 'static inline bool'
268         print 'is_symbolic_param(T param) {'
269         print '    return static_cast<T>(static_cast<GLenum>(param)) == param;'
270         print '}'
271         print
272
273         # Generate a helper function to know how many elements a parameter has
274         print 'static size_t'
275         print '__gl_param_size(GLenum pname) {'
276         print '    switch(pname) {'
277         for function, type, count, name in glparams.parameters:
278             if type is not None:
279                 print '    case %s: return %u;' % (name, count)
280         print '    case GL_COMPRESSED_TEXTURE_FORMATS: {'
281         print '            GLint num_compressed_texture_formats = 0;'
282         print '            __glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &num_compressed_texture_formats);'
283         print '            return num_compressed_texture_formats;'
284         print '        }'
285         print '    default:'
286         print r'        OS::DebugMessage("apitrace: warning: %s: unknown GLenum 0x%04X\n", __FUNCTION__, pname);'
287         print '        return 1;'
288         print '    }'
289         print '}'
290         print
291
292     array_pointer_function_names = set((
293         "glVertexPointer",
294         "glNormalPointer",
295         "glColorPointer",
296         "glIndexPointer",
297         "glTexCoordPointer",
298         "glEdgeFlagPointer",
299         "glFogCoordPointer",
300         "glSecondaryColorPointer",
301         
302         "glInterleavedArrays",
303
304         "glVertexPointerEXT",
305         "glNormalPointerEXT",
306         "glColorPointerEXT",
307         "glIndexPointerEXT",
308         "glTexCoordPointerEXT",
309         "glEdgeFlagPointerEXT",
310         "glFogCoordPointerEXT",
311         "glSecondaryColorPointerEXT",
312
313         "glVertexAttribPointer",
314         "glVertexAttribPointerARB",
315         "glVertexAttribPointerNV",
316         "glVertexAttribIPointer",
317         "glVertexAttribIPointerEXT",
318         "glVertexAttribLPointer",
319         "glVertexAttribLPointerEXT",
320         
321         #"glMatrixIndexPointerARB",
322     ))
323
324     draw_function_names = set((
325         'glDrawArrays',
326         'glDrawElements',
327         'glDrawRangeElements',
328         'glMultiDrawArrays',
329         'glMultiDrawElements',
330         'glDrawArraysInstanced',
331         'glDrawElementsInstanced',
332         'glDrawArraysInstancedARB',
333         'glDrawElementsInstancedARB',
334         'glDrawElementsBaseVertex',
335         'glDrawRangeElementsBaseVertex',
336         'glDrawElementsInstancedBaseVertex',
337         'glMultiDrawElementsBaseVertex',
338         'glDrawArraysIndirect',
339         'glDrawElementsIndirect',
340         'glDrawArraysEXT',
341         'glDrawRangeElementsEXT',
342         'glDrawRangeElementsEXT_size',
343         'glMultiDrawArraysEXT',
344         'glMultiDrawElementsEXT',
345         'glMultiModeDrawArraysIBM',
346         'glMultiModeDrawElementsIBM',
347         'glDrawArraysInstancedEXT',
348         'glDrawElementsInstancedEXT',
349     ))
350
351     interleaved_formats = [
352          'GL_V2F',
353          'GL_V3F',
354          'GL_C4UB_V2F',
355          'GL_C4UB_V3F',
356          'GL_C3F_V3F',
357          'GL_N3F_V3F',
358          'GL_C4F_N3F_V3F',
359          'GL_T2F_V3F',
360          'GL_T4F_V4F',
361          'GL_T2F_C4UB_V3F',
362          'GL_T2F_C3F_V3F',
363          'GL_T2F_N3F_V3F',
364          'GL_T2F_C4F_N3F_V3F',
365          'GL_T4F_C4F_N3F_V4F',
366     ]
367
368     def trace_function_impl_body(self, function):
369         # Defer tracing of user array pointers...
370         if function.name in self.array_pointer_function_names:
371             print '    GLint __array_buffer = 0;'
372             print '    __glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &__array_buffer);'
373             print '    if (!__array_buffer) {'
374             print '        __user_arrays = true;'
375             if function.name == "glVertexAttribPointerARB":
376                 print '        __user_arrays_arb = true;'
377             if function.name == "glVertexAttribPointerNV":
378                 print '        __user_arrays_nv = true;'
379             self.dispatch_function(function)
380
381             # And also break down glInterleavedArrays into the individual calls
382             if function.name == 'glInterleavedArrays':
383                 print
384
385                 # Initialize the enable flags
386                 for camelcase_name, uppercase_name in self.arrays:
387                     flag_name = '__' + uppercase_name.lower()
388                     print '        GLboolean %s = GL_FALSE;' % flag_name
389                 print
390
391                 # Switch for the interleaved formats
392                 print '        switch (format) {'
393                 for format in self.interleaved_formats:
394                     print '            case %s:' % format
395                     for camelcase_name, uppercase_name in self.arrays:
396                         flag_name = '__' + uppercase_name.lower()
397                         if format.find('_' + uppercase_name[0]) >= 0:
398                             print '                %s = GL_TRUE;' % flag_name
399                     print '                break;'
400                 print '            default:'
401                 print '               return;'
402                 print '        }'
403                 print
404
405                 # Emit fake glEnableClientState/glDisableClientState flags
406                 for camelcase_name, uppercase_name in self.arrays:
407                     flag_name = '__' + uppercase_name.lower()
408                     enable_name = 'GL_%s_ARRAY' % uppercase_name
409
410                     # Emit a fake function
411                     print '        {'
412                     print '            static const Trace::FunctionSig &__sig = %s ? __glEnableClientState_sig : __glDisableClientState_sig;' % flag_name
413                     print '            unsigned __call = __writer.beginEnter(&__sig);'
414                     print '            __writer.beginArg(0);'
415                     dump_instance(glapi.GLenum, enable_name)
416                     print '            __writer.endArg();'
417                     print '            __writer.endEnter();'
418                     print '            __writer.beginLeave(__call);'
419                     print '            __writer.endLeave();'
420                     print '        }'
421
422             print '        return;'
423             print '    }'
424
425         # ... to the draw calls
426         if function.name in self.draw_function_names:
427             print '    if (__need_user_arrays()) {'
428             arg_names = ', '.join([arg.name for arg in function.args[1:]])
429             print '        GLuint maxindex = __%s_maxindex(%s);' % (function.name, arg_names)
430             print '        __trace_user_arrays(maxindex);'
431             print '    }'
432         
433         # Emit a fake memcpy on buffer uploads
434         if function.name in ('glUnmapBuffer', 'glUnmapBufferARB', ):
435             print '    struct buffer_mapping *mapping = get_buffer_mapping(target);'
436             print '    if (mapping && mapping->write && !mapping->explicit_flush) {'
437             self.emit_memcpy('mapping->map', 'mapping->map', 'mapping->length')
438             print '    }'
439         if function.name in ('glFlushMappedBufferRange', 'glFlushMappedBufferRangeAPPLE'):
440             # TODO: avoid copying [0, offset] bytes
441             print '    struct buffer_mapping *mapping = get_buffer_mapping(target);'
442             print '    if (mapping) {'
443             if function.name.endswith('APPLE'):
444                  print '        GLsizeiptr length = size;'
445                  print '        mapping->explicit_flush = true;'
446             print '        //assert(offset + length <= mapping->length);'
447             self.emit_memcpy('mapping->map', 'mapping->map', 'offset + length')
448             print '    }'
449         # FIXME: glFlushMappedNamedBufferRangeEXT
450
451         # Don't leave vertex attrib locations to chance.  Instead emit fake
452         # glBindAttribLocation calls to ensure that the same locations will be
453         # used when retracing.  Trying to remap locations after the fact would
454         # be an herculian task given that vertex attrib locations appear in
455         # many entry-points, including non-shader related ones.
456         if function.name == 'glLinkProgram':
457             Tracer.dispatch_function(self, function)
458             print '    GLint active_attributes = 0;'
459             print '    __glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &active_attributes);'
460             print '    for (GLuint attrib = 0; attrib < active_attributes; ++attrib) {'
461             print '        GLint size = 0;'
462             print '        GLenum type = 0;'
463             print '        GLchar name[256];'
464             # TODO: Use ACTIVE_ATTRIBUTE_MAX_LENGTH instead of 256
465             print '        __glGetActiveAttrib(program, attrib, sizeof name, NULL, &size, &type, name);'
466             print "        if (name[0] != 'g' || name[1] != 'l' || name[2] != '_') {"
467             print '            GLint location = __glGetAttribLocation(program, name);'
468             print '            if (location >= 0) {'
469             bind_function = glapi.glapi.get_function_by_name('glBindAttribLocation')
470             self.fake_call(bind_function, ['program', 'location', 'name'])
471             print '            }'
472             print '        }'
473             print '    }'
474         if function.name == 'glLinkProgramARB':
475             Tracer.dispatch_function(self, function)
476             print '    GLint active_attributes = 0;'
477             print '    __glGetObjectParameterivARB(programObj, GL_OBJECT_ACTIVE_ATTRIBUTES_ARB, &active_attributes);'
478             print '    for (GLuint attrib = 0; attrib < active_attributes; ++attrib) {'
479             print '        GLint size = 0;'
480             print '        GLenum type = 0;'
481             print '        GLcharARB name[256];'
482             # TODO: Use ACTIVE_ATTRIBUTE_MAX_LENGTH instead of 256
483             print '        __glGetActiveAttribARB(programObj, attrib, sizeof name, NULL, &size, &type, name);'
484             print "        if (name[0] != 'g' || name[1] != 'l' || name[2] != '_') {"
485             print '            GLint location = __glGetAttribLocationARB(programObj, name);'
486             print '            if (location >= 0) {'
487             bind_function = glapi.glapi.get_function_by_name('glBindAttribLocationARB')
488             self.fake_call(bind_function, ['programObj', 'location', 'name'])
489             print '            }'
490             print '        }'
491             print '    }'
492
493         Tracer.trace_function_impl_body(self, function)
494
495     def dispatch_function(self, function):
496         if function.name in ('glLinkProgram', 'glLinkProgramARB'):
497             # These functions have been dispatched already
498             return
499
500         Tracer.dispatch_function(self, function)
501
502     def emit_memcpy(self, dest, src, length):
503         print '        unsigned __call = __writer.beginEnter(&__memcpy_sig);'
504         print '        __writer.beginArg(0);'
505         print '        __writer.writeOpaque(%s);' % dest
506         print '        __writer.endArg();'
507         print '        __writer.beginArg(1);'
508         print '        __writer.writeBlob(%s, %s);' % (src, length)
509         print '        __writer.endArg();'
510         print '        __writer.beginArg(2);'
511         print '        __writer.writeUInt(%s);' % length
512         print '        __writer.endArg();'
513         print '        __writer.endEnter();'
514         print '        __writer.beginLeave(__call);'
515         print '        __writer.endLeave();'
516        
517     buffer_targets = [
518         'ARRAY_BUFFER',
519         'ELEMENT_ARRAY_BUFFER',
520         'PIXEL_PACK_BUFFER',
521         'PIXEL_UNPACK_BUFFER',
522     ]
523
524     def wrap_ret(self, function, instance):
525         Tracer.wrap_ret(self, function, instance)
526             
527         if function.name in ('glMapBuffer', 'glMapBufferARB'):
528             print '    struct buffer_mapping *mapping = get_buffer_mapping(target);'
529             print '    if (mapping) {'
530             print '        mapping->map = %s;' % (instance)
531             print '        mapping->length = 0;'
532             print '        __glGetBufferParameteriv(target, GL_BUFFER_SIZE, &mapping->length);'
533             print '        mapping->write = (access != GL_READ_ONLY);'
534             print '        mapping->explicit_flush = false;'
535             print '    }'
536
537         if function.name == 'glMapBufferRange':
538             print '    struct buffer_mapping *mapping = get_buffer_mapping(target);'
539             print '    if (mapping) {'
540             print '        mapping->map = %s;' % (instance)
541             print '        mapping->length = length;'
542             print '        mapping->write = access & GL_MAP_WRITE_BIT;'
543             print '        mapping->explicit_flush = access & GL_MAP_FLUSH_EXPLICIT_BIT;'
544             print '    }'
545
546     boolean_names = [
547         'GL_FALSE',
548         'GL_TRUE',
549     ]
550
551     def gl_boolean(self, value):
552         return self.boolean_names[int(bool(value))]
553
554     # Names of the functions that unpack from a pixel buffer object.  See the
555     # ARB_pixel_buffer_object specification.
556     unpack_function_names = set([
557         'glBitmap',
558         'glColorSubTable',
559         'glColorTable',
560         'glCompressedTexImage1D',
561         'glCompressedTexImage2D',
562         'glCompressedTexImage3D',
563         'glCompressedTexSubImage1D',
564         'glCompressedTexSubImage2D',
565         'glCompressedTexSubImage3D',
566         'glConvolutionFilter1D',
567         'glConvolutionFilter2D',
568         'glDrawPixels',
569         'glMultiTexImage1DEXT',
570         'glMultiTexImage2DEXT',
571         'glMultiTexImage3DEXT',
572         'glMultiTexSubImage1DEXT',
573         'glMultiTexSubImage2DEXT',
574         'glMultiTexSubImage3DEXT',
575         'glPixelMapfv',
576         'glPixelMapuiv',
577         'glPixelMapusv',
578         'glPolygonStipple',
579         'glSeparableFilter2D',
580         'glTexImage1D',
581         'glTexImage1DEXT',
582         'glTexImage2D',
583         'glTexImage2DEXT',
584         'glTexImage3D',
585         'glTexImage3DEXT',
586         'glTexSubImage1D',
587         'glTexSubImage1DEXT',
588         'glTexSubImage2D',
589         'glTexSubImage2DEXT',
590         'glTexSubImage3D',
591         'glTexSubImage3DEXT',
592         'glTextureImage1DEXT',
593         'glTextureImage2DEXT',
594         'glTextureImage3DEXT',
595         'glTextureSubImage1DEXT',
596         'glTextureSubImage2DEXT',
597         'glTextureSubImage3DEXT',
598     ])
599
600     def dump_arg_instance(self, function, arg):
601         if function.name in self.draw_function_names and arg.name == 'indices':
602             print '    GLint __element_array_buffer = 0;'
603             print '    __glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &__element_array_buffer);'
604             print '    if (!__element_array_buffer) {'
605             if isinstance(arg.type, stdapi.Array):
606                 print '        __writer.beginArray(%s);' % arg.type.length
607                 print '        for(GLsizei i = 0; i < %s; ++i) {' % arg.type.length
608                 print '            __writer.beginElement();'
609                 print '            __writer.writeBlob(%s[i], count[i]*__gl_type_size(type));' % (arg.name)
610                 print '            __writer.endElement();'
611                 print '        }'
612                 print '        __writer.endArray();'
613             else:
614                 print '        __writer.writeBlob(%s, count*__gl_type_size(type));' % (arg.name)
615             print '    } else {'
616             Tracer.dump_arg_instance(self, function, arg)
617             print '    }'
618             return
619
620         # Recognize offsets instead of blobs when a PBO is bound
621         if function.name in self.unpack_function_names \
622            and (isinstance(arg.type, stdapi.Blob) \
623                 or (isinstance(arg.type, stdapi.Const) \
624                     and isinstance(arg.type.type, stdapi.Blob))):
625             print '    {'
626             print '        GLint __unpack_buffer = 0;'
627             print '        __glGetIntegerv(GL_PIXEL_UNPACK_BUFFER_BINDING, &__unpack_buffer);'
628             print '        if (__unpack_buffer) {'
629             print '            __writer.writeOpaque(%s);' % arg.name
630             print '        } else {'
631             Tracer.dump_arg_instance(self, function, arg)
632             print '        }'
633             print '    }'
634             return
635
636         # Several GL state functions take GLenum symbolic names as
637         # integer/floats; so dump the symbolic name whenever possible
638         if function.name.startswith('gl') \
639            and arg.type in (glapi.GLint, glapi.GLfloat) \
640            and arg.name == 'param':
641             assert arg.index > 0
642             assert function.args[arg.index - 1].name == 'pname'
643             assert function.args[arg.index - 1].type == glapi.GLenum
644             print '    if (is_symbolic_pname(pname) && is_symbolic_param(%s)) {' % arg.name
645             dump_instance(glapi.GLenum, arg.name)
646             print '    } else {'
647             Tracer.dump_arg_instance(self, function, arg)
648             print '    }'
649             return
650
651         Tracer.dump_arg_instance(self, function, arg)
652
653     def footer(self, api):
654         Tracer.footer(self, api)
655
656         # A simple state tracker to track the pointer values
657         # update the state
658         print 'static void __trace_user_arrays(GLuint maxindex)'
659         print '{'
660
661         for camelcase_name, uppercase_name in self.arrays:
662             function_name = 'gl%sPointer' % camelcase_name
663             enable_name = 'GL_%s_ARRAY' % uppercase_name
664             binding_name = 'GL_%s_ARRAY_BUFFER_BINDING' % uppercase_name
665             function = api.get_function_by_name(function_name)
666
667             print '    // %s' % function.name
668             self.array_trace_prolog(api, uppercase_name)
669             self.array_prolog(api, uppercase_name)
670             print '    if (__glIsEnabled(%s)) {' % enable_name
671             print '        GLint __binding = 0;'
672             print '        __glGetIntegerv(%s, &__binding);' % binding_name
673             print '        if (!__binding) {'
674
675             # Get the arguments via glGet*
676             for arg in function.args:
677                 arg_get_enum = 'GL_%s_ARRAY_%s' % (uppercase_name, arg.name.upper())
678                 arg_get_function, arg_type = TypeGetter().visit(arg.type)
679                 print '            %s %s = 0;' % (arg_type, arg.name)
680                 print '            __%s(%s, &%s);' % (arg_get_function, arg_get_enum, arg.name)
681             
682             arg_names = ', '.join([arg.name for arg in function.args[:-1]])
683             print '            size_t __size = __%s_size(%s, maxindex);' % (function.name, arg_names)
684
685             # Emit a fake function
686             self.array_trace_intermezzo(api, uppercase_name)
687             print '            unsigned __call = __writer.beginEnter(&__%s_sig);' % (function.name,)
688             for arg in function.args:
689                 assert not arg.output
690                 print '            __writer.beginArg(%u);' % (arg.index,)
691                 if arg.name != 'pointer':
692                     dump_instance(arg.type, arg.name)
693                 else:
694                     print '            __writer.writeBlob((const void *)%s, __size);' % (arg.name)
695                 print '            __writer.endArg();'
696             
697             print '            __writer.endEnter();'
698             print '            __writer.beginLeave(__call);'
699             print '            __writer.endLeave();'
700             print '        }'
701             print '    }'
702             self.array_epilog(api, uppercase_name)
703             self.array_trace_epilog(api, uppercase_name)
704             print
705
706         # Samething, but for glVertexAttribPointer*
707         #
708         # Some variants of glVertexAttribPointer alias conventional and generic attributes:
709         # - glVertexAttribPointer: no
710         # - glVertexAttribPointerARB: implementation dependent
711         # - glVertexAttribPointerNV: yes
712         #
713         # This means that the implementations of these functions do not always
714         # alias, and they need to be considered independently.
715         #
716         print '    vertex_attrib __vertex_attrib = __get_vertex_attrib();'
717         print
718         for suffix in ['', 'ARB', 'NV']:
719             if suffix:
720                 SUFFIX = '_' + suffix
721             else:
722                 SUFFIX = suffix
723             function_name = 'glVertexAttribPointer' + suffix
724             print '    // %s' % function_name
725             print '    if (__vertex_attrib == VERTEX_ATTRIB%s) {' % SUFFIX
726             if suffix == 'NV':
727                 print '        GLint __max_vertex_attribs = 16;'
728             else:
729                 print '        GLint __max_vertex_attribs = 0;'
730                 print '        __glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &__max_vertex_attribs);'
731             print '        for (GLint index = 0; index < __max_vertex_attribs; ++index) {'
732             print '            GLint __enabled = 0;'
733             if suffix == 'NV':
734                 print '            __glGetIntegerv(GL_VERTEX_ATTRIB_ARRAY0_NV + index, &__enabled);'
735             else:
736                 print '            __glGetVertexAttribiv%s(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED%s, &__enabled);' % (suffix, SUFFIX)
737             print '            if (__enabled) {'
738             print '                GLint __binding = 0;'
739             if suffix != 'NV':
740                 # It doesn't seem possible to use VBOs with NV_vertex_program.
741                 print '                __glGetVertexAttribiv%s(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING%s, &__binding);' % (suffix, SUFFIX)
742             print '                if (!__binding) {'
743
744             function = api.get_function_by_name(function_name)
745
746             # Get the arguments via glGet*
747             for arg in function.args[1:]:
748                 if suffix == 'NV':
749                     arg_get_enum = 'GL_ATTRIB_ARRAY_%s%s' % (arg.name.upper(), SUFFIX)
750                 else:
751                     arg_get_enum = 'GL_VERTEX_ATTRIB_ARRAY_%s%s' % (arg.name.upper(), SUFFIX)
752                 arg_get_function, arg_type = TypeGetter('glGetVertexAttrib', False, suffix).visit(arg.type)
753                 print '                    %s %s = 0;' % (arg_type, arg.name)
754                 print '                    __%s(index, %s, &%s);' % (arg_get_function, arg_get_enum, arg.name)
755             
756             arg_names = ', '.join([arg.name for arg in function.args[1:-1]])
757             print '                    size_t __size = __%s_size(%s, maxindex);' % (function.name, arg_names)
758
759             # Emit a fake function
760             print '                    unsigned __call = __writer.beginEnter(&__%s_sig);' % (function.name,)
761             for arg in function.args:
762                 assert not arg.output
763                 print '                    __writer.beginArg(%u);' % (arg.index,)
764                 if arg.name != 'pointer':
765                     dump_instance(arg.type, arg.name)
766                 else:
767                     print '                    __writer.writeBlob((const void *)%s, __size);' % (arg.name)
768                 print '                    __writer.endArg();'
769             
770             print '                    __writer.endEnter();'
771             print '                    __writer.beginLeave(__call);'
772             print '                    __writer.endLeave();'
773             print '                }'
774             print '            }'
775             print '        }'
776             print '    }'
777             print
778
779         print '}'
780         print
781
782     #
783     # Hooks for glTexCoordPointer, which is identical to the other array
784     # pointers except the fact that it is indexed by glClientActiveTexture.
785     #
786
787     def array_prolog(self, api, uppercase_name):
788         if uppercase_name == 'TEXTURE_COORD':
789             print '    GLint client_active_texture = 0;'
790             print '    __glGetIntegerv(GL_CLIENT_ACTIVE_TEXTURE, &client_active_texture);'
791             print '    GLint max_texture_coords = 0;'
792             print '    __glGetIntegerv(GL_MAX_TEXTURE_COORDS, &max_texture_coords);'
793             print '    for (GLint unit = 0; unit < max_texture_coords; ++unit) {'
794             print '        GLenum texture = GL_TEXTURE0 + unit;'
795             print '        __glClientActiveTexture(texture);'
796
797     def array_trace_prolog(self, api, uppercase_name):
798         if uppercase_name == 'TEXTURE_COORD':
799             print '    bool client_active_texture_dirty = false;'
800
801     def array_epilog(self, api, uppercase_name):
802         if uppercase_name == 'TEXTURE_COORD':
803             print '    }'
804         self.array_cleanup(api, uppercase_name)
805
806     def array_cleanup(self, api, uppercase_name):
807         if uppercase_name == 'TEXTURE_COORD':
808             print '    __glClientActiveTexture(client_active_texture);'
809         
810     def array_trace_intermezzo(self, api, uppercase_name):
811         if uppercase_name == 'TEXTURE_COORD':
812             print '    if (texture != client_active_texture || client_active_texture_dirty) {'
813             print '        client_active_texture_dirty = true;'
814             self.fake_glClientActiveTexture_call(api, "texture");
815             print '    }'
816
817     def array_trace_epilog(self, api, uppercase_name):
818         if uppercase_name == 'TEXTURE_COORD':
819             print '    if (client_active_texture_dirty) {'
820             self.fake_glClientActiveTexture_call(api, "client_active_texture");
821             print '    }'
822
823     def fake_glClientActiveTexture_call(self, api, texture):
824         function = api.get_function_by_name('glClientActiveTexture')
825         self.fake_call(function, [texture])
826
827     def fake_call(self, function, args):
828         print '            unsigned __fake_call = __writer.beginEnter(&__%s_sig);' % (function.name,)
829         for arg, instance in zip(function.args, args):
830             assert not arg.output
831             print '            __writer.beginArg(%u);' % (arg.index,)
832             dump_instance(arg.type, instance)
833             print '            __writer.endArg();'
834         print '            __writer.endEnter();'
835         print '            __writer.beginLeave(__fake_call);'
836         print '            __writer.endLeave();'
837
838
839
840
841
842
843
844
845
846
847