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