1 ##########################################################################
3 # Copyright 2011 Jose Fonseca
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:
13 # The above copyright notice and this permission notice shall be included in
14 # all copies or substantial portions of the Software.
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
24 ##########################################################################/
27 '''Generate code to dump most GL state into JSON.'''
33 from glparams import *
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')
45 '''Objects that describes how to inflect.'''
53 def __init__(self, radical, inflections, suffix = ''):
54 self.radical = radical
55 self.inflections = inflections
58 def reduced_type(self, type):
59 if type in self.inflections:
61 if type in self.reduced_types:
62 return self.reduced_type(self.reduced_types[type])
63 raise NotImplementedError
65 def inflect(self, type):
66 return self.radical + self.inflection(type) + self.suffix
68 def inflection(self, type):
69 type = self.reduced_type(type)
70 assert type in self.inflections
71 return self.inflections[type]
74 return self.radical + self.suffix
77 class StateGetter(Visitor):
78 '''Type visitor that is able to extract the state via one of the glGet*
81 It will declare any temporary variable
84 def __init__(self, radical, inflections, suffix=''):
85 self.inflector = GetInflector(radical, inflections)
88 def __call__(self, *args):
91 for function, type, count, name in parameters:
96 type = Array(type, str(count))
98 return type, self.visit(type, args)
100 raise NotImplementedError
102 def temp_name(self, args):
103 '''Return the name of a temporary variable to hold the state.'''
106 return pname[3:].lower()
108 def visit_const(self, const, args):
109 return self.visit(const.type, args)
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)
119 print ' %s %s = %s(%s);' % (elem_type, temp_name, inflection + self.suffix, ', '.join(args))
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))
129 def visit_alias(self, alias, args):
130 return self.visit_scalar(alias, args)
132 def visit_enum(self, enum, args):
133 return self.visit(GLint, args)
135 def visit_bitmask(self, bitmask, args):
136 return self.visit(GLint, args)
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)
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)
159 glGet = StateGetter('glGet', {
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')
177 class JsonWriter(Visitor):
178 '''Type visitor that will dump a value of the specified type through the
181 It expects a previously declared JSONWriter instance named "json".'''
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
189 raise NotImplementedError
191 def visit_string(self, string, instance):
192 assert string.length is None
193 print ' json.writeString((const char *)%s);' % instance
195 def visit_enum(self, enum, instance):
196 if enum.expr == 'GLenum':
197 print ' writeEnum(json, %s);' % instance
199 print ' json.writeNumber(%s);' % instance
201 def visit_bitmask(self, bitmask, instance):
202 raise NotImplementedError
204 def visit_alias(self, alias, instance):
205 self.visit(alias.type, instance)
207 def visit_opaque(self, opaque, instance):
208 print ' json.writeNumber((size_t)%s);' % instance
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))
219 print ' json.endArray();'
224 '''Class to generate code to dump all GL state in JSON format via
231 print '#include <string.h>'
232 print '#include <iostream>'
233 print '#include <algorithm>'
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"'
243 print 'static const char *'
244 print '_enum_string(GLenum pname)'
246 print ' switch(pname) {'
247 for name in GLenum.values:
248 print ' case %s:' % name
249 print ' return "%s";' % name
251 print ' return NULL;'
256 print 'static const char *'
257 print 'enum_string(GLenum pname)'
259 print ' const char *s = _enum_string(pname);'
263 print ' static char buf[16];'
264 print ' snprintf(buf, sizeof buf, "0x%04x", pname);'
270 print 'static inline void'
271 print 'writeEnum(JSONWriter &json, GLenum pname)'
273 print ' const char *s = _enum_string(pname);'
275 print ' json.writeString(s);'
277 print ' json.writeNumber(pname);'
285 writeShader(JSONWriter &json, GLuint shader)
291 GLint shader_type = 0;
292 glGetShaderiv(shader, GL_SHADER_TYPE, &shader_type);
297 GLint source_length = 0;
298 glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &source_length);
299 if (!source_length) {
303 GLchar *source = new GLchar[source_length];
306 glGetShaderSource(shader, source_length, &length, source);
308 json.beginMember(enum_string(shader_type));
309 json.writeString(source);
316 writeCurrentProgram(JSONWriter &json)
319 glGetIntegerv(GL_CURRENT_PROGRAM, &program);
324 GLint attached_shaders = 0;
325 glGetProgramiv(program, GL_ATTACHED_SHADERS, &attached_shaders);
326 if (!attached_shaders) {
330 GLuint *shaders = new GLuint[attached_shaders];
332 glGetAttachedShaders(program, attached_shaders, &count, shaders);
333 for (GLsizei i = 0; i < count; ++ i) {
334 writeShader(json, shaders[i]);
340 writeArbProgram(JSONWriter &json, GLenum target)
342 if (!glIsEnabled(target)) {
346 GLint program_length = 0;
347 glGetProgramivARB(target, GL_PROGRAM_LENGTH_ARB, &program_length);
348 if (!program_length) {
352 GLchar *source = new GLchar[program_length + 1];
354 glGetProgramStringARB(target, GL_PROGRAM_STRING_ARB, source);
355 source[program_length] = 0;
357 json.beginMember(enum_string(target));
358 json.writeString(source);
368 writeTextureImage(JSONWriter &json, GLenum target, GLint level)
370 GLint width, height = 1, depth = 1;
373 glGetTexLevelParameteriv(target, level, GL_TEXTURE_WIDTH, &width);
375 if (target != GL_TEXTURE_1D) {
377 glGetTexLevelParameteriv(target, level, GL_TEXTURE_HEIGHT, &height);
378 if (target == GL_TEXTURE_3D) {
380 glGetTexLevelParameteriv(target, level, GL_TEXTURE_DEPTH, &depth);
384 if (width <= 0 || height <= 0 || depth <= 0) {
389 // Tell the GUI this is no ordinary object, but an image
390 json.writeStringMember("__class__", "image");
392 json.writeNumberMember("__width__", width);
393 json.writeNumberMember("__height__", height);
394 json.writeNumberMember("__depth__", depth);
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);
402 GLubyte *pixels = new GLubyte[depth*width*height*4];
404 glGetTexImage(target, level, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
406 json.beginMember("__data__");
409 Image::writePixelsToBuffer(pixels, width, height, 4, false, &pngBuffer, &pngBufferSize);
410 json.writeBase64(pngBuffer, pngBufferSize);
412 json.endMember(); // __data__
420 writeDrawBufferImage(JSONWriter &json, GLenum format)
422 GLint channels = __gl_format_channels(format);
424 if (!glretrace::drawable) {
427 GLint width = glretrace::drawable->width;
428 GLint height = glretrace::drawable->height;
432 // Tell the GUI this is no ordinary object, but an image
433 json.writeStringMember("__class__", "image");
435 json.writeNumberMember("__width__", width);
436 json.writeNumberMember("__height__", height);
437 json.writeNumberMember("__depth__", 1);
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);
445 GLubyte *pixels = new GLubyte[width*height*channels];
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);
453 glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
454 glPixelStorei(GL_PACK_ALIGNMENT, 1);
456 glReadPixels(0, 0, width, height, format, GL_UNSIGNED_BYTE, pixels);
459 glReadBuffer(readbuffer);
461 json.beginMember("__data__");
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);
469 json.endMember(); // __data__
477 downsampledFramebuffer(GLuint oldFbo, GLint drawbuffer,
478 GLint colorRb, GLint depthRb, GLint stencilRb,
479 GLuint *rbs, GLint *numRbs)
487 glGenFramebuffers(1, &fbo);
488 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
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);
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]);
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);
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);
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);
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);
544 glGenRenderbuffers(1, &rbs[*numRbs]);
545 glBindRenderbuffer(GL_RENDERBUFFER, rbs[*numRbs]);
546 glRenderbufferStorage(GL_RENDERBUFFER, format, w, h);
547 glFramebufferRenderbuffer(GL_FRAMEBUFFER,
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);
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);
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);
587 writeDrawBuffers(JSONWriter &json, GLboolean writeDepth, GLboolean writeStencil)
589 json.beginMember("GL_RGBA");
590 writeDrawBufferImage(json, GL_RGBA);
594 json.beginMember("GL_DEPTH_COMPONENT");
595 writeDrawBufferImage(json, GL_DEPTH_COMPONENT);
600 json.beginMember("GL_STENCIL_INDEX");
601 writeDrawBufferImage(json, GL_STENCIL_INDEX);
609 print 'static inline void'
610 print 'writeTexture(JSONWriter &json, GLenum target, GLenum binding)'
612 print ' GLint texture = 0;'
613 print ' glGetIntegerv(binding, &texture);'
614 print ' if (!glIsEnabled(target) && !texture) {'
615 print ' json.writeNull();'
619 print ' json.beginObject();'
620 print ' json.beginMember("levels");'
621 print ' json.beginArray();'
622 print ' GLint level = 0;'
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) {'
630 print ' json.beginObject();'
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();'
638 print ' json.beginMember("image");'
639 print ' writeTextureImage(json, target, level);'
640 print ' json.endMember();'
642 print ' json.endObject();'
644 print ' } while(true);'
645 print ' json.endArray();'
646 print ' json.endMember(); // levels'
648 print ' json.endObject();'
652 print 'void glretrace::state_dump(std::ostream &os)'
654 print ' JSONWriter json(os);'
655 self.dump_parameters()
656 self.dump_current_program()
658 self.dump_framebuffer()
662 def dump_parameters(self):
663 print ' json.beginMember("parameters");'
664 print ' json.beginObject();'
666 self.dump_atoms(glGet)
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()
675 print ' json.endObject();'
676 print ' json.endMember(); // parameters'
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();'
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'
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
710 print ' json.beginMember("%s");' % target
711 print ' json.beginObject();'
712 self.dump_atoms(glGetTexEnv, target)
713 print ' json.endObject();'
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'
731 'GL_FRAGMENT_PROGRAM_ARB',
732 'GL_VERTEX_PROGRAM_ARB',
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();'
744 def dump_texture_parameters(self):
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;'
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
775 print ' json.endObject();'
776 print ' json.endMember(); // GL_TEXTUREi'
778 print ' glActiveTexture(active_texture);'
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'
792 def dump_textures(self):
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();'
812 print ' glActiveTexture(active_texture);'
813 print ' json.endArray();'
814 print ' json.endMember(); // texture'
818 def dump_framebuffer(self):
819 print ' json.beginMember("framebuffer");'
820 print ' json.beginObject();'
821 # TODO: Handle real FBOs
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);'
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);'
839 print ' glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,'
841 print ' GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,'
843 print ' glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,'
844 print ' GL_DEPTH_ATTACHMENT,'
845 print ' GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,'
847 print ' glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,'
848 print ' GL_STENCIL_ATTACHMENT,'
849 print ' GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,'
850 print ' &stencilRb);'
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);'
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);'
874 print ' glDrawBuffer(drawbuffer);'
875 print ' glReadBuffer(drawbuffer);'
877 print ' writeDrawBuffers(json, depthRb, stencilRb);'
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);'
889 print ' json.endObject();'
890 print ' json.endMember(); // framebuffer'
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(','):
900 print ' // %s' % name
902 type, value = getter(*(args + (name,)))
903 print ' if (glGetError() != GL_NO_ERROR) {'
904 #print ' std::cerr << "warning: %s(%s) failed\\n";' % (inflection, name)
906 print ' json.beginMember("%s");' % name
907 JsonWriter().visit(type, value)
908 print ' json.endMember();'
914 if __name__ == '__main__':