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