]> git.cworth.org Git - apitrace/blob - glstate.py
Unify glenum.py and glstate.py parameter table into a single one.
[apitrace] / glstate.py
1 ##########################################################################
2 #
3 # Copyright 2011 Jose Fonseca
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 '''Generate code to dump most GL state into JSON.'''
28
29
30 from stdapi import *
31
32 from gltypes import *
33 from glparams import *
34
35
36 texture_targets = [
37     ('GL_TEXTURE_1D', 'GL_TEXTURE_BINDING_1D'),
38     ('GL_TEXTURE_2D', 'GL_TEXTURE_BINDING_2D'),
39     ('GL_TEXTURE_3D', 'GL_TEXTURE_BINDING_3D'),
40     #(GL_TEXTURE_CUBE_MAP, 'GL_TEXTURE_BINDING_CUBE_MAP')
41 ]
42
43
44 class GetInflector:
45     '''Objects that describes how to inflect.'''
46
47     reduced_types = {
48         B: I,
49         E: I,
50         I: F,
51     }
52
53     def __init__(self, radical, inflections, suffix = ''):
54         self.radical = radical
55         self.inflections = inflections
56         self.suffix = suffix
57
58     def reduced_type(self, type):
59         if type in self.inflections:
60             return type
61         if type in self.reduced_types:
62             return self.reduced_type(self.reduced_types[type])
63         raise NotImplementedError
64
65     def inflect(self, type):
66         return self.radical + self.inflection(type) + self.suffix
67
68     def inflection(self, type):
69         type = self.reduced_type(type)
70         assert type in self.inflections
71         return self.inflections[type]
72
73     def __str__(self):
74         return self.radical + self.suffix
75
76
77 class StateGetter(Visitor):
78     '''Type visitor that is able to extract the state via one of the glGet*
79     functions.
80
81     It will declare any temporary variable
82     '''
83
84     def __init__(self, radical, inflections, suffix=''):
85         self.inflector = GetInflector(radical, inflections)
86         self.suffix = suffix
87
88     def __call__(self, *args):
89         pname = args[-1]
90
91         for function, type, count, name in parameters:
92             if type is X:
93                 continue
94             if name == pname:
95                 if count != 1:
96                     type = Array(type, str(count))
97
98                 return type, self.visit(type, args)
99
100         raise NotImplementedError
101
102     def temp_name(self, args):
103         '''Return the name of a temporary variable to hold the state.'''
104         pname = args[-1]
105
106         return pname[3:].lower()
107
108     def visit_const(self, const, args):
109         return self.visit(const.type, args)
110
111     def visit_scalar(self, type, args):
112         temp_name = self.temp_name(args)
113         elem_type = self.inflector.reduced_type(type)
114         inflection = self.inflector.inflect(type)
115         if inflection.endswith('v'):
116             print '    %s %s = 0;' % (elem_type, temp_name)
117             print '    %s(%s, &%s);' % (inflection + self.suffix, ', '.join(args), temp_name)
118         else:
119             print '    %s %s = %s(%s);' % (elem_type, temp_name, inflection + self.suffix, ', '.join(args))
120         return temp_name
121
122     def visit_string(self, string, args):
123         temp_name = self.temp_name(args)
124         inflection = self.inflector.inflect(string)
125         assert not inflection.endswith('v')
126         print '    %s %s = (%s)%s(%s);' % (string, temp_name, string, inflection + self.suffix, ', '.join(args))
127         return temp_name
128
129     def visit_alias(self, alias, args):
130         return self.visit_scalar(alias, args)
131
132     def visit_enum(self, enum, args):
133         return self.visit(GLint, args)
134
135     def visit_bitmask(self, bitmask, args):
136         return self.visit(GLint, args)
137
138     def visit_array(self, array, args):
139         temp_name = self.temp_name(args)
140         if array.length == '1':
141             return self.visit(array.type)
142         elem_type = self.inflector.reduced_type(array.type)
143         inflection = self.inflector.inflect(array.type)
144         assert inflection.endswith('v')
145         print '    %s %s[%s];' % (elem_type, temp_name, array.length)
146         print '    memset(%s, 0, %s * sizeof *%s);' % (temp_name, array.length, temp_name)
147         print '    %s(%s, %s);' % (inflection + self.suffix, ', '.join(args), temp_name)
148         return temp_name
149
150     def visit_opaque(self, pointer, args):
151         temp_name = self.temp_name(args)
152         inflection = self.inflector.inflect(pointer)
153         assert inflection.endswith('v')
154         print '    GLvoid *%s;' % temp_name
155         print '    %s(%s, &%s);' % (inflection + self.suffix, ', '.join(args), temp_name)
156         return temp_name
157
158
159 glGet = StateGetter('glGet', {
160     B: 'Booleanv',
161     I: 'Integerv',
162     F: 'Floatv',
163     D: 'Doublev',
164     S: 'String',
165     P: 'Pointerv',
166 })
167
168 glGetMaterial = StateGetter('glGetMaterial', {I: 'iv', F: 'fv'})
169 glGetLight = StateGetter('glGetLight', {I: 'iv', F: 'fv'})
170 glGetVertexAttrib = StateGetter('glGetVertexAttrib', {I: 'iv', F: 'fv', D: 'dv', P: 'Pointerv'})
171 glGetTexParameter = StateGetter('glGetTexParameter', {I: 'iv', F: 'fv'})
172 glGetTexEnv = StateGetter('glGetTexEnv', {I: 'iv', F: 'fv'})
173 glGetTexLevelParameter = StateGetter('glGetTexLevelParameter', {I: 'iv', F: 'fv'})
174 glGetProgramARB = StateGetter('glGetProgram', {I: 'iv', F: 'fv', S: 'Stringv'}, 'ARB')
175
176
177 class JsonWriter(Visitor):
178     '''Type visitor that will dump a value of the specified type through the
179     JSON writer.
180     
181     It expects a previously declared JSONWriter instance named "json".'''
182
183     def visit_literal(self, literal, instance):
184         if literal.format == 'Bool':
185             print '    json.writeBool(%s);' % instance
186         elif literal.format in ('SInt', 'Uint', 'Float', 'Double'):
187             print '    json.writeNumber(%s);' % instance
188         else:
189             raise NotImplementedError
190
191     def visit_string(self, string, instance):
192         assert string.length is None
193         print '    json.writeString((const char *)%s);' % instance
194
195     def visit_enum(self, enum, instance):
196         if enum.expr == 'GLenum':
197             print '    writeEnum(json, %s);' % instance
198         else:
199             print '    json.writeNumber(%s);' % instance
200
201     def visit_bitmask(self, bitmask, instance):
202         raise NotImplementedError
203
204     def visit_alias(self, alias, instance):
205         self.visit(alias.type, instance)
206
207     def visit_opaque(self, opaque, instance):
208         print '    json.writeNumber((size_t)%s);' % instance
209
210     __index = 0
211
212     def visit_array(self, array, instance):
213         index = '__i%u' % JsonWriter.__index
214         JsonWriter.__index += 1
215         print '    json.beginArray();'
216         print '    for (unsigned %s = 0; %s < %s; ++%s) {' % (index, index, array.length, index)
217         self.visit(array.type, '%s[%s]' % (instance, index))
218         print '    }'
219         print '    json.endArray();'
220
221
222
223 class StateDumper:
224     '''Class to generate code to dump all GL state in JSON format via
225     stdout.'''
226
227     def __init__(self):
228         self.level = 0
229
230     def dump(self):
231         print '#include <string.h>'
232         print '#include <iostream>'
233         print '#include <algorithm>'
234         print
235         print '#include "image.hpp"'
236         print '#include "json.hpp"'
237         print '#include "glimports.hpp"'
238         print '#include "glproc.hpp"'
239         print '#include "glsize.hpp"'
240         print '#include "glretrace.hpp"'
241         print
242
243         print 'static const char *'
244         print '_enum_string(GLenum pname)'
245         print '{'
246         print '    switch(pname) {'
247         for name in GLenum.values:
248             print '    case %s:' % name
249             print '        return "%s";' % name
250         print '    default:'
251         print '        return NULL;'
252         print '    }'
253         print '}'
254         print
255
256         print 'static const char *'
257         print 'enum_string(GLenum pname)'
258         print '{'
259         print '    const char *s = _enum_string(pname);'
260         print '    if (s) {'
261         print '        return s;'
262         print '    } else {'
263         print '        static char buf[16];'
264         print '        snprintf(buf, sizeof buf, "0x%04x", pname);'
265         print '        return buf;'
266         print '    }'
267         print '}'
268         print
269
270         print 'static inline void'
271         print 'writeEnum(JSONWriter &json, GLenum pname)'
272         print '{'
273         print '    const char *s = _enum_string(pname);'
274         print '    if (s) {'
275         print '        json.writeString(s);'
276         print '    } else {'
277         print '        json.writeNumber(pname);'
278         print '    }'
279         print '}'
280         print
281
282         # shaders
283         print '''
284 static void
285 writeShader(JSONWriter &json, GLuint shader)
286 {
287     if (!shader) {
288         return;
289     }
290
291     GLint shader_type = 0;
292     glGetShaderiv(shader, GL_SHADER_TYPE, &shader_type);
293     if (!shader_type) {
294         return;
295     }
296
297     GLint source_length = 0;
298     glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &source_length);
299     if (!source_length) {
300         return;
301     }
302
303     GLchar *source = new GLchar[source_length];
304     GLsizei length = 0;
305     source[0] = 0;
306     glGetShaderSource(shader, source_length, &length, source);
307
308     json.beginMember(enum_string(shader_type));
309     json.writeString(source);
310     json.endMember();
311
312     delete [] source;
313 }
314
315 static inline void
316 writeCurrentProgram(JSONWriter &json)
317 {
318     GLint program = 0;
319     glGetIntegerv(GL_CURRENT_PROGRAM, &program);
320     if (!program) {
321         return;
322     }
323
324     GLint attached_shaders = 0;
325     glGetProgramiv(program, GL_ATTACHED_SHADERS, &attached_shaders);
326     if (!attached_shaders) {
327         return;
328     }
329
330     GLuint *shaders = new GLuint[attached_shaders];
331     GLsizei count = 0;
332     glGetAttachedShaders(program, attached_shaders, &count, shaders);
333     for (GLsizei i = 0; i < count; ++ i) {
334        writeShader(json, shaders[i]);
335     }
336     delete [] shaders;
337 }
338
339 static inline void
340 writeArbProgram(JSONWriter &json, GLenum target)
341 {
342     if (!glIsEnabled(target)) {
343         return;
344     }
345
346     GLint program_length = 0;
347     glGetProgramivARB(target, GL_PROGRAM_LENGTH_ARB, &program_length);
348     if (!program_length) {
349         return;
350     }
351
352     GLchar *source = new GLchar[program_length + 1];
353     source[0] = 0;
354     glGetProgramStringARB(target, GL_PROGRAM_STRING_ARB, source);
355     source[program_length] = 0;
356
357     json.beginMember(enum_string(target));
358     json.writeString(source);
359     json.endMember();
360
361     delete [] source;
362 }
363 '''
364
365         # texture image
366         print '''
367 static inline void
368 writeTextureImage(JSONWriter &json, GLenum target, GLint level)
369 {
370     GLint width, height = 1, depth = 1;
371
372     width = 0;
373     glGetTexLevelParameteriv(target, level, GL_TEXTURE_WIDTH, &width);
374
375     if (target != GL_TEXTURE_1D) {
376         height = 0;
377         glGetTexLevelParameteriv(target, level, GL_TEXTURE_HEIGHT, &height);
378         if (target == GL_TEXTURE_3D) {
379             depth = 0;
380             glGetTexLevelParameteriv(target, level, GL_TEXTURE_DEPTH, &depth);
381         }
382     }
383
384     if (width <= 0 || height <= 0 || depth <= 0) {
385         json.writeNull();
386     } else {
387         json.beginObject();
388
389         // Tell the GUI this is no ordinary object, but an image
390         json.writeStringMember("__class__", "image");
391
392         json.writeNumberMember("__width__", width);
393         json.writeNumberMember("__height__", height);
394         json.writeNumberMember("__depth__", depth);
395
396         // Hardcoded for now, but we could chose types more adequate to the
397         // texture internal format
398         json.writeStringMember("__type__", "uint8");
399         json.writeBoolMember("__normalized__", true);
400         json.writeNumberMember("__channels__", 4);
401         
402         GLubyte *pixels = new GLubyte[depth*width*height*4];
403         
404         glGetTexImage(target, level, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
405
406         json.beginMember("__data__");
407         char *pngBuffer;
408         int pngBufferSize;
409         Image::writePixelsToBuffer(pixels, width, height, 4, false, &pngBuffer, &pngBufferSize);
410         json.writeBase64(pngBuffer, pngBufferSize);
411         free(pngBuffer);
412         json.endMember(); // __data__
413
414         delete [] pixels;
415         json.endObject();
416     }
417 }
418
419 static inline void
420 writeDrawBufferImage(JSONWriter &json, GLenum format)
421 {
422     GLint width  = glretrace::window_width;
423     GLint height = glretrace::window_height;
424
425     GLint channels = __gl_format_channels(format);
426
427     if (!width || !height) {
428         json.writeNull();
429     } else {
430         json.beginObject();
431
432         // Tell the GUI this is no ordinary object, but an image
433         json.writeStringMember("__class__", "image");
434
435         json.writeNumberMember("__width__", width);
436         json.writeNumberMember("__height__", height);
437         json.writeNumberMember("__depth__", 1);
438
439         // Hardcoded for now, but we could chose types more adequate to the
440         // texture internal format
441         json.writeStringMember("__type__", "uint8");
442         json.writeBoolMember("__normalized__", true);
443         json.writeNumberMember("__channels__", channels);
444
445         GLubyte *pixels = new GLubyte[width*height*channels];
446         
447         GLint drawbuffer = glretrace::double_buffer ? GL_BACK : GL_FRONT;
448         GLint readbuffer = glretrace::double_buffer ? GL_BACK : GL_FRONT;
449         glGetIntegerv(GL_DRAW_BUFFER, &drawbuffer);
450         glGetIntegerv(GL_READ_BUFFER, &readbuffer);
451         glReadBuffer(drawbuffer);
452
453         glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
454         glPixelStorei(GL_PACK_ALIGNMENT, 1);
455
456         glReadPixels(0, 0, width, height, format, GL_UNSIGNED_BYTE, pixels);
457
458         glPopClientAttrib();
459         glReadBuffer(readbuffer);
460
461         json.beginMember("__data__");
462         char *pngBuffer;
463         int pngBufferSize;
464         Image::writePixelsToBuffer(pixels, width, height, channels, false, &pngBuffer, &pngBufferSize);
465         //std::cerr <<" Before = "<<(width * height * channels * sizeof *pixels)
466         //          <<", after = "<<pngBufferSize << ", ratio = " << double(width * height * channels * sizeof *pixels)/pngBufferSize;
467         json.writeBase64(pngBuffer, pngBufferSize);
468         free(pngBuffer);
469         json.endMember(); // __data__
470
471         delete [] pixels;
472         json.endObject();
473     }
474 }
475
476 static inline GLuint
477 downsampledFramebuffer(GLuint oldFbo, GLint drawbuffer,
478                        GLint colorRb, GLint depthRb, GLint stencilRb,
479                        GLuint *rbs, GLint *numRbs)
480 {
481     GLuint fbo;
482     GLint format;
483     GLint w, h;
484
485     *numRbs = 0;
486
487     glGenFramebuffers(1, &fbo);
488     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
489
490     glBindRenderbuffer(GL_RENDERBUFFER, colorRb);
491     glGetRenderbufferParameteriv(GL_RENDERBUFFER,
492                                  GL_RENDERBUFFER_WIDTH, &w);
493     glGetRenderbufferParameteriv(GL_RENDERBUFFER,
494                                  GL_RENDERBUFFER_HEIGHT, &h);
495     glGetRenderbufferParameteriv(GL_RENDERBUFFER,
496                                  GL_RENDERBUFFER_INTERNAL_FORMAT, &format);
497
498     glGenRenderbuffers(1, &rbs[*numRbs]);
499     glBindRenderbuffer(GL_RENDERBUFFER, rbs[*numRbs]);
500     glRenderbufferStorage(GL_RENDERBUFFER, format, w, h);
501     glFramebufferRenderbuffer(GL_FRAMEBUFFER, drawbuffer,
502                               GL_RENDERBUFFER, rbs[*numRbs]);
503
504     glBindFramebuffer(GL_READ_FRAMEBUFFER, oldFbo);
505     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
506     glDrawBuffer(drawbuffer);
507     glReadBuffer(drawbuffer);
508     glBlitFramebuffer(0, 0, w, h, 0, 0, w, h,
509                       GL_COLOR_BUFFER_BIT, GL_NEAREST);
510     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
511     ++*numRbs;
512
513     if (stencilRb == depthRb && stencilRb) {
514         //combined depth and stencil buffer
515         glBindRenderbuffer(GL_RENDERBUFFER, depthRb);
516         glGetRenderbufferParameteriv(GL_RENDERBUFFER,
517                                      GL_RENDERBUFFER_WIDTH, &w);
518         glGetRenderbufferParameteriv(GL_RENDERBUFFER,
519                                      GL_RENDERBUFFER_HEIGHT, &h);
520         glGetRenderbufferParameteriv(GL_RENDERBUFFER,
521                                      GL_RENDERBUFFER_INTERNAL_FORMAT, &format);
522
523         glGenRenderbuffers(1, &rbs[*numRbs]);
524         glBindRenderbuffer(GL_RENDERBUFFER, rbs[*numRbs]);
525         glRenderbufferStorage(GL_RENDERBUFFER, format, w, h);
526         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
527                                   GL_RENDERBUFFER, rbs[*numRbs]);
528         glBindFramebuffer(GL_READ_FRAMEBUFFER, oldFbo);
529         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
530         glBlitFramebuffer(0, 0, w, h, 0, 0, w, h,
531                           GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
532         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
533         ++*numRbs;
534     } else {
535         if (depthRb) {
536             glBindRenderbuffer(GL_RENDERBUFFER, depthRb);
537             glGetRenderbufferParameteriv(GL_RENDERBUFFER,
538                                          GL_RENDERBUFFER_WIDTH, &w);
539             glGetRenderbufferParameteriv(GL_RENDERBUFFER,
540                                          GL_RENDERBUFFER_HEIGHT, &h);
541             glGetRenderbufferParameteriv(GL_RENDERBUFFER,
542                                          GL_RENDERBUFFER_INTERNAL_FORMAT, &format);
543
544             glGenRenderbuffers(1, &rbs[*numRbs]);
545             glBindRenderbuffer(GL_RENDERBUFFER, rbs[*numRbs]);
546             glRenderbufferStorage(GL_RENDERBUFFER, format, w, h);
547             glFramebufferRenderbuffer(GL_FRAMEBUFFER,
548                                       GL_DEPTH_ATTACHMENT,
549                                       GL_RENDERBUFFER, rbs[*numRbs]);
550             glBindFramebuffer(GL_READ_FRAMEBUFFER, oldFbo);
551             glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
552             glDrawBuffer(GL_DEPTH_ATTACHMENT);
553             glReadBuffer(GL_DEPTH_ATTACHMENT);
554             glBlitFramebuffer(0, 0, w, h, 0, 0, w, h,
555                               GL_DEPTH_BUFFER_BIT, GL_NEAREST);
556             ++*numRbs;
557         }
558         if (stencilRb) {
559             glBindRenderbuffer(GL_RENDERBUFFER, stencilRb);
560             glGetRenderbufferParameteriv(GL_RENDERBUFFER,
561                                          GL_RENDERBUFFER_WIDTH, &w);
562             glGetRenderbufferParameteriv(GL_RENDERBUFFER,
563                                          GL_RENDERBUFFER_HEIGHT, &h);
564             glGetRenderbufferParameteriv(GL_RENDERBUFFER,
565                                      GL_RENDERBUFFER_INTERNAL_FORMAT, &format);
566
567             glGenRenderbuffers(1, &rbs[*numRbs]);
568             glBindRenderbuffer(GL_RENDERBUFFER, rbs[*numRbs]);
569             glRenderbufferStorage(GL_RENDERBUFFER, format, w, h);
570             glFramebufferRenderbuffer(GL_FRAMEBUFFER,
571                                       GL_STENCIL_ATTACHMENT,
572                                       GL_RENDERBUFFER, rbs[*numRbs]);
573             glBindFramebuffer(GL_READ_FRAMEBUFFER, oldFbo);
574             glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
575             glDrawBuffer(GL_STENCIL_ATTACHMENT);
576             glReadBuffer(GL_STENCIL_ATTACHMENT);
577             glBlitFramebuffer(0, 0, w, h, 0, 0, w, h,
578                               GL_STENCIL_BUFFER_BIT, GL_NEAREST);
579             ++*numRbs;
580         }
581     }
582
583     return fbo;
584 }
585
586 static void
587 writeDrawBuffers(JSONWriter &json, GLboolean writeDepth, GLboolean writeStencil)
588 {
589     json.beginMember("GL_RGBA");
590     writeDrawBufferImage(json, GL_RGBA);
591     json.endMember();
592
593     if (writeDepth) {
594         json.beginMember("GL_DEPTH_COMPONENT");
595         writeDrawBufferImage(json, GL_DEPTH_COMPONENT);
596         json.endMember();
597     }
598
599     if (writeStencil) {
600         json.beginMember("GL_STENCIL_INDEX");
601         writeDrawBufferImage(json, GL_STENCIL_INDEX);
602         json.endMember();
603     }
604 }
605
606 '''
607
608         # textures
609         print 'static inline void'
610         print 'writeTexture(JSONWriter &json, GLenum target, GLenum binding)'
611         print '{'
612         print '    GLint texture = 0;'
613         print '    glGetIntegerv(binding, &texture);'
614         print '    if (!glIsEnabled(target) && !texture) {'
615         print '        json.writeNull();'
616         print '        return;'
617         print '    }'
618         print
619         print '    json.beginObject();'
620         print '    json.beginMember("levels");'
621         print '    json.beginArray();'
622         print '    GLint level = 0;'
623         print '    do {'
624         print '        GLint width = 0, height = 0;'
625         print '        glGetTexLevelParameteriv(target, level, GL_TEXTURE_WIDTH, &width);'
626         print '        glGetTexLevelParameteriv(target, level, GL_TEXTURE_HEIGHT, &height);'
627         print '        if (!width || !height) {'
628         print '            break;'
629         print '        }'
630         print '        json.beginObject();'
631         print
632         # FIXME: This is not the original texture name in the trace -- we need
633         # to do a reverse lookup of the texture mappings to find the original one
634         print '        json.beginMember("binding");'
635         print '        json.writeNumber(texture);'
636         print '        json.endMember();'
637         print
638         print '        json.beginMember("image");'
639         print '        writeTextureImage(json, target, level);'
640         print '        json.endMember();'
641         print
642         print '        json.endObject();'
643         print '        ++level;'
644         print '    } while(true);'
645         print '    json.endArray();'
646         print '    json.endMember(); // levels'
647         print
648         print '    json.endObject();'
649         print '}'
650         print
651
652         print 'void glretrace::state_dump(std::ostream &os)'
653         print '{'
654         print '    JSONWriter json(os);'
655         self.dump_parameters()
656         self.dump_current_program()
657         self.dump_textures()
658         self.dump_framebuffer()
659         print '}'
660         print
661
662     def dump_parameters(self):
663         print '    json.beginMember("parameters");'
664         print '    json.beginObject();'
665         
666         self.dump_atoms(glGet)
667         
668         self.dump_material_params()
669         self.dump_light_params()
670         self.dump_vertex_attribs()
671         self.dump_texenv_params()
672         self.dump_program_params()
673         self.dump_texture_parameters()
674
675         print '    json.endObject();'
676         print '    json.endMember(); // parameters'
677         print
678
679     def dump_material_params(self):
680         for face in ['GL_FRONT', 'GL_BACK']:
681             print '    json.beginMember("%s");' % face
682             print '    json.beginObject();'
683             self.dump_atoms(glGetMaterial, face)
684             print '    json.endObject();'
685         print
686
687     def dump_light_params(self):
688         print '    GLint max_lights = 0;'
689         print '    __glGetIntegerv(GL_MAX_LIGHTS, &max_lights);'
690         print '    for (GLint index = 0; index < max_lights; ++index) {'
691         print '        GLenum light = GL_LIGHT0 + index;'
692         print '        if (glIsEnabled(light)) {'
693         print '            char name[32];'
694         print '            snprintf(name, sizeof name, "GL_LIGHT%i", index);'
695         print '            json.beginMember(name);'
696         print '            json.beginObject();'
697         self.dump_atoms(glGetLight, '    GL_LIGHT0 + index')
698         print '            json.endObject();'
699         print '            json.endMember(); // GL_LIGHTi'
700         print '        }'
701         print '    }'
702         print
703
704     def dump_texenv_params(self):
705         for target in ['GL_TEXTURE_ENV', 'GL_TEXTURE_FILTER_CONTROL', 'GL_POINT_SPRITE']:
706             if target != 'GL_TEXTURE_FILTER_CONTROL':
707                 print '    if (glIsEnabled(%s)) {' % target
708             else:
709                 print '    {'
710             print '        json.beginMember("%s");' % target
711             print '        json.beginObject();'
712             self.dump_atoms(glGetTexEnv, target)
713             print '        json.endObject();'
714             print '    }'
715
716     def dump_vertex_attribs(self):
717         print '    GLint max_vertex_attribs = 0;'
718         print '    __glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &max_vertex_attribs);'
719         print '    for (GLint index = 0; index < max_vertex_attribs; ++index) {'
720         print '        char name[32];'
721         print '        snprintf(name, sizeof name, "GL_VERTEX_ATTRIB_ARRAY%i", index);'
722         print '        json.beginMember(name);'
723         print '        json.beginObject();'
724         self.dump_atoms(glGetVertexAttrib, 'index')
725         print '        json.endObject();'
726         print '        json.endMember(); // GL_VERTEX_ATTRIB_ARRAYi'
727         print '    }'
728         print
729
730     program_targets = [
731         'GL_FRAGMENT_PROGRAM_ARB',
732         'GL_VERTEX_PROGRAM_ARB',
733     ]
734
735     def dump_program_params(self):
736         for target in self.program_targets:
737             print '    if (glIsEnabled(%s)) {' % target
738             print '        json.beginMember("%s");' % target
739             print '        json.beginObject();'
740             self.dump_atoms(glGetProgramARB, target)
741             print '        json.endObject();'
742             print '    }'
743
744     def dump_texture_parameters(self):
745         print '    {'
746         print '        GLint active_texture = GL_TEXTURE0;'
747         print '        glGetIntegerv(GL_ACTIVE_TEXTURE, &active_texture);'
748         print '        GLint max_texture_coords = 0;'
749         print '        glGetIntegerv(GL_MAX_TEXTURE_COORDS, &max_texture_coords);'
750         print '        GLint max_combined_texture_image_units = 0;'
751         print '        glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_combined_texture_image_units);'
752         print '        GLint max_units = std::max(max_combined_texture_image_units, max_texture_coords);'
753         print '        for (GLint unit = 0; unit < max_units; ++unit) {'
754         print '            char name[32];'
755         print '            snprintf(name, sizeof name, "GL_TEXTURE%i", unit);'
756         print '            json.beginMember(name);'
757         print '            glActiveTexture(GL_TEXTURE0 + unit);'
758         print '            json.beginObject();'
759         print '            GLint texture;'
760         print
761         for target, binding in texture_targets:
762             print '            // %s' % target
763             print '            texture = 0;'
764             print '            glGetIntegerv(%s, &texture);' % binding
765             print '            if (glIsEnabled(%s) || texture) {' % target
766             print '                json.beginMember("%s");' % target
767             print '                json.beginObject();'
768             self.dump_atoms(glGetTexParameter, target)
769             # We only dump the first level parameters
770             self.dump_atoms(glGetTexLevelParameter, target, "0")
771             print '                json.endObject();'
772             print '                json.endMember(); // %s' % target
773             print '            }'
774             print
775         print '            json.endObject();'
776         print '            json.endMember(); // GL_TEXTUREi'
777         print '        }'
778         print '        glActiveTexture(active_texture);'
779         print '    }'
780         print
781
782     def dump_current_program(self):
783         print '    json.beginMember("shaders");'
784         print '    json.beginObject();'
785         print '    writeCurrentProgram(json);'
786         for target in self.program_targets:
787             print '    writeArbProgram(json, %s);' % target
788         print '    json.endObject();'
789         print '    json.endMember(); //shaders'
790         print
791
792     def dump_textures(self):
793         print '    {'
794         print '        json.beginMember("textures");'
795         print '        json.beginArray();'
796         print '        GLint active_texture = GL_TEXTURE0;'
797         print '        glGetIntegerv(GL_ACTIVE_TEXTURE, &active_texture);'
798         print '        GLint max_texture_coords = 0;'
799         print '        glGetIntegerv(GL_MAX_TEXTURE_COORDS, &max_texture_coords);'
800         print '        GLint max_combined_texture_image_units = 0;'
801         print '        glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_combined_texture_image_units);'
802         print '        GLint max_units = std::max(max_combined_texture_image_units, max_texture_coords);'
803         print '        for (GLint unit = 0; unit < max_units; ++unit) {'
804         print '            glActiveTexture(GL_TEXTURE0 + unit);'
805         print '            json.beginObject();'
806         for target, binding in texture_targets:
807             print '            json.beginMember("%s");' % target
808             print '            writeTexture(json, %s, %s);' % (target, binding)
809             print '            json.endMember();'
810         print '            json.endObject();'
811         print '        }'
812         print '        glActiveTexture(active_texture);'
813         print '        json.endArray();'
814         print '        json.endMember(); // texture'
815         print '    }'
816         print
817
818     def dump_framebuffer(self):
819         print '    json.beginMember("framebuffer");'
820         print '    json.beginObject();'
821         # TODO: Handle real FBOs
822         print
823         print '    GLint boundDrawFbo = 0, boundReadFbo = 0;'
824         print '    glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundDrawFbo);'
825         print '    glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &boundReadFbo);'
826         print '    if (!boundDrawFbo) {'
827         print '        GLint depth_bits = 0;'
828         print '        glGetIntegerv(GL_DEPTH_BITS, &depth_bits);'
829         print '        GLint stencil_bits = 0;'
830         print '        glGetIntegerv(GL_STENCIL_BITS, &stencil_bits);'
831         print '        writeDrawBuffers(json, depth_bits, stencil_bits);'
832         print '    } else {'
833         print '        GLint colorRb, stencilRb, depthRb;'
834         print '        GLint boundRb;'
835         print '        glGetIntegerv(GL_RENDERBUFFER_BINDING, &boundRb);'
836         print '        GLint drawbuffer = glretrace::double_buffer ? GL_BACK : GL_FRONT;'
837         print '        glGetIntegerv(GL_DRAW_BUFFER, &drawbuffer);'
838         print
839         print '        glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,'
840         print '                                              drawbuffer,'
841         print '                                              GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,'
842         print '                                              &colorRb);'
843         print '        glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,'
844         print '                                              GL_DEPTH_ATTACHMENT,'
845         print '                                              GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,'
846         print '                                              &depthRb);'
847         print '        glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,'
848         print '                                              GL_STENCIL_ATTACHMENT,'
849         print '                                              GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,'
850         print '                                              &stencilRb);'
851         print
852         print '        GLint colorSamples, depthSamples, stencilSamples;'
853         print '        GLuint rbs[3];'
854         print '        GLint numRbs = 0;'
855         print '        GLuint fboCopy = 0;'
856         print '        glBindRenderbuffer(GL_RENDERBUFFER, colorRb);'
857         print '        glGetRenderbufferParameteriv(GL_RENDERBUFFER,'
858         print '                                     GL_RENDERBUFFER_SAMPLES, &colorSamples);'
859         print '        glBindRenderbuffer(GL_RENDERBUFFER, depthRb);'
860         print '        glGetRenderbufferParameteriv(GL_RENDERBUFFER,'
861         print '                                     GL_RENDERBUFFER_SAMPLES, &depthSamples);'
862         print '        glBindRenderbuffer(GL_RENDERBUFFER, stencilRb);'
863         print '        glGetRenderbufferParameteriv(GL_RENDERBUFFER,'
864         print '                                     GL_RENDERBUFFER_SAMPLES, &stencilSamples);'
865         print '        glBindRenderbuffer(GL_RENDERBUFFER, boundRb);'
866         print
867         print '        if (colorSamples || depthSamples || stencilSamples) {'
868         print '            //glReadPixels doesnt support multisampled buffers so we need'
869         print '            // to blit the fbo to a temporary one'
870         print '            fboCopy = downsampledFramebuffer(boundDrawFbo, drawbuffer,'
871         print '                                             colorRb, depthRb, stencilRb,'
872         print '                                             rbs, &numRbs);'
873         print '        }'
874         print '        glDrawBuffer(drawbuffer);'
875         print '        glReadBuffer(drawbuffer);'
876         print
877         print '        writeDrawBuffers(json, depthRb, stencilRb);'
878         print
879         print '        if (fboCopy) {'
880         print '            glBindFramebuffer(GL_FRAMEBUFFER, boundDrawFbo);'
881         print '            glBindFramebuffer(GL_READ_FRAMEBUFFER, boundReadFbo);'
882         print '            glBindFramebuffer(GL_DRAW_FRAMEBUFFER, boundDrawFbo);'
883         print '            glBindRenderbuffer(GL_RENDERBUFFER_BINDING, boundRb);'
884         print '            glDeleteRenderbuffers(numRbs, rbs);'
885         print '            glDeleteFramebuffers(1, &fboCopy);'
886         print '        }'
887         print '    }'
888         print
889         print '    json.endObject();'
890         print '    json.endMember(); // framebuffer'
891         pass
892
893     def dump_atoms(self, getter, *args):
894         for function, type, count, name in parameters:
895             inflection = getter.inflector.radical + getter.suffix
896             if inflection not in function.split(','):
897                 continue
898             if type is X:
899                 continue
900             print '        // %s' % name
901             print '        {'
902             type, value = getter(*(args + (name,)))
903             print '            if (glGetError() != GL_NO_ERROR) {'
904             #print '                std::cerr << "warning: %s(%s) failed\\n";' % (inflection, name)
905             print '            } else {'
906             print '                json.beginMember("%s");' % name
907             JsonWriter().visit(type, value)
908             print '                json.endMember();'
909             print '            }'
910             print '        }'
911             print
912
913     def write_line(s):
914         self.write('  '*self.level + s + '\n')
915
916     def write(self, s):
917         sys.stdout.write(s)
918
919     def indent(self):
920         self.level += 1
921
922     def dedent(self):
923         self.level -= 1
924
925
926
927 if __name__ == '__main__':
928     StateDumper().dump()