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_RECTANGLE', 'GL_TEXTURE_BINDING_RECTANGLE'),
41 ('GL_TEXTURE_CUBE_MAP', 'GL_TEXTURE_BINDING_CUBE_MAP')
46 '''Objects that describes how to inflect.'''
54 def __init__(self, radical, inflections, suffix = ''):
55 self.radical = radical
56 self.inflections = inflections
59 def reduced_type(self, type):
60 if type in self.inflections:
62 if type in self.reduced_types:
63 return self.reduced_type(self.reduced_types[type])
64 raise NotImplementedError
66 def inflect(self, type):
67 return self.radical + self.inflection(type) + self.suffix
69 def inflection(self, type):
70 type = self.reduced_type(type)
71 assert type in self.inflections
72 return self.inflections[type]
75 return self.radical + self.suffix
78 class StateGetter(Visitor):
79 '''Type visitor that is able to extract the state via one of the glGet*
82 It will declare any temporary variable
85 def __init__(self, radical, inflections, suffix=''):
86 self.inflector = GetInflector(radical, inflections)
89 def __call__(self, *args):
92 for function, type, count, name in parameters:
97 type = Array(type, str(count))
99 return type, self.visit(type, args)
101 raise NotImplementedError
103 def temp_name(self, args):
104 '''Return the name of a temporary variable to hold the state.'''
107 return pname[3:].lower()
109 def visit_const(self, const, args):
110 return self.visit(const.type, args)
112 def visit_scalar(self, type, args):
113 temp_name = self.temp_name(args)
114 elem_type = self.inflector.reduced_type(type)
115 inflection = self.inflector.inflect(type)
116 if inflection.endswith('v'):
117 print ' %s %s = 0;' % (elem_type, temp_name)
118 print ' %s(%s, &%s);' % (inflection + self.suffix, ', '.join(args), temp_name)
120 print ' %s %s = %s(%s);' % (elem_type, temp_name, inflection + self.suffix, ', '.join(args))
123 def visit_string(self, string, args):
124 temp_name = self.temp_name(args)
125 inflection = self.inflector.inflect(string)
126 assert not inflection.endswith('v')
127 print ' %s %s = (%s)%s(%s);' % (string, temp_name, string, inflection + self.suffix, ', '.join(args))
130 def visit_alias(self, alias, args):
131 return self.visit_scalar(alias, args)
133 def visit_enum(self, enum, args):
134 return self.visit(GLint, args)
136 def visit_bitmask(self, bitmask, args):
137 return self.visit(GLint, args)
139 def visit_array(self, array, args):
140 temp_name = self.temp_name(args)
141 if array.length == '1':
142 return self.visit(array.type)
143 elem_type = self.inflector.reduced_type(array.type)
144 inflection = self.inflector.inflect(array.type)
145 assert inflection.endswith('v')
146 print ' %s %s[%s];' % (elem_type, temp_name, array.length)
147 print ' memset(%s, 0, %s * sizeof *%s);' % (temp_name, array.length, temp_name)
148 print ' %s(%s, %s);' % (inflection + self.suffix, ', '.join(args), temp_name)
151 def visit_opaque(self, pointer, args):
152 temp_name = self.temp_name(args)
153 inflection = self.inflector.inflect(pointer)
154 assert inflection.endswith('v')
155 print ' GLvoid *%s;' % temp_name
156 print ' %s(%s, &%s);' % (inflection + self.suffix, ', '.join(args), temp_name)
160 glGet = StateGetter('glGet', {
169 glGetMaterial = StateGetter('glGetMaterial', {I: 'iv', F: 'fv'})
170 glGetLight = StateGetter('glGetLight', {I: 'iv', F: 'fv'})
171 glGetVertexAttrib = StateGetter('glGetVertexAttrib', {I: 'iv', F: 'fv', D: 'dv', P: 'Pointerv'})
172 glGetTexParameter = StateGetter('glGetTexParameter', {I: 'iv', F: 'fv'})
173 glGetTexEnv = StateGetter('glGetTexEnv', {I: 'iv', F: 'fv'})
174 glGetTexLevelParameter = StateGetter('glGetTexLevelParameter', {I: 'iv', F: 'fv'})
175 glGetShader = StateGetter('glGetShaderiv', {I: 'iv'})
176 glGetProgram = StateGetter('glGetProgram', {I: 'iv'})
177 glGetProgramARB = StateGetter('glGetProgram', {I: 'iv', F: 'fv', S: 'Stringv'}, 'ARB')
180 class JsonWriter(Visitor):
181 '''Type visitor that will dump a value of the specified type through the
184 It expects a previously declared JSONWriter instance named "json".'''
186 def visit_literal(self, literal, instance):
187 if literal.format == 'Bool':
188 print ' json.writeBool(%s);' % instance
189 elif literal.format in ('SInt', 'Uint', 'Float', 'Double'):
190 print ' json.writeNumber(%s);' % instance
192 raise NotImplementedError
194 def visit_string(self, string, instance):
195 assert string.length is None
196 print ' json.writeString((const char *)%s);' % instance
198 def visit_enum(self, enum, instance):
199 if enum.expr == 'GLenum':
200 print ' writeEnum(json, %s);' % instance
202 print ' json.writeNumber(%s);' % instance
204 def visit_bitmask(self, bitmask, instance):
205 raise NotImplementedError
207 def visit_alias(self, alias, instance):
208 self.visit(alias.type, instance)
210 def visit_opaque(self, opaque, instance):
211 print ' json.writeNumber((size_t)%s);' % instance
215 def visit_array(self, array, instance):
216 index = '__i%u' % JsonWriter.__index
217 JsonWriter.__index += 1
218 print ' json.beginArray();'
219 print ' for (unsigned %s = 0; %s < %s; ++%s) {' % (index, index, array.length, index)
220 self.visit(array.type, '%s[%s]' % (instance, index))
222 print ' json.endArray();'
227 '''Class to generate code to dump all GL state in JSON format via
234 print '#include <string.h>'
235 print '#include <iostream>'
236 print '#include <algorithm>'
238 print '#include "image.hpp"'
239 print '#include "json.hpp"'
240 print '#include "glimports.hpp"'
241 print '#include "glproc.hpp"'
242 print '#include "glsize.hpp"'
243 print '#include "glstate.hpp"'
246 print 'static const char *'
247 print '_enum_string(GLenum pname)'
249 print ' switch(pname) {'
250 for name in GLenum.values:
251 print ' case %s:' % name
252 print ' return "%s";' % name
254 print ' return NULL;'
259 print 'static const char *'
260 print 'enum_string(GLenum pname)'
262 print ' const char *s = _enum_string(pname);'
266 print ' static char buf[16];'
267 print ' snprintf(buf, sizeof buf, "0x%04x", pname);'
273 print 'static inline void'
274 print 'writeEnum(JSONWriter &json, GLenum pname)'
276 print ' const char *s = _enum_string(pname);'
278 print ' json.writeString(s);'
280 print ' json.writeNumber(pname);'
288 writeShader(JSONWriter &json, GLuint shader)
294 GLint shader_type = 0;
295 glGetShaderiv(shader, GL_SHADER_TYPE, &shader_type);
300 GLint source_length = 0;
301 glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &source_length);
302 if (!source_length) {
306 GLchar *source = new GLchar[source_length];
309 glGetShaderSource(shader, source_length, &length, source);
311 json.beginMember(enum_string(shader_type));
312 json.writeString(source);
319 writeShaderObj(JSONWriter &json, GLhandleARB shaderObj)
325 GLint shader_type = 0;
326 glGetObjectParameterivARB(shaderObj, GL_OBJECT_TYPE_ARB, &shader_type);
331 GLint source_length = 0;
332 glGetObjectParameterivARB(shaderObj, GL_OBJECT_SHADER_SOURCE_LENGTH_ARB, &source_length);
333 if (!source_length) {
337 GLcharARB *source = new GLcharARB[source_length];
340 glGetShaderSource(shaderObj, source_length, &length, source);
342 json.beginMember(enum_string(shader_type));
343 json.writeString(source);
350 writeCurrentProgram(JSONWriter &json)
353 glGetIntegerv(GL_CURRENT_PROGRAM, &program);
358 GLint attached_shaders = 0;
359 glGetProgramiv(program, GL_ATTACHED_SHADERS, &attached_shaders);
360 if (!attached_shaders) {
364 GLuint *shaders = new GLuint[attached_shaders];
366 glGetAttachedShaders(program, attached_shaders, &count, shaders);
367 for (GLsizei i = 0; i < count; ++ i) {
368 writeShader(json, shaders[i]);
374 writeCurrentProgramObj(JSONWriter &json)
376 GLhandleARB programObj = glGetHandleARB(GL_PROGRAM_OBJECT_ARB);
381 GLint attached_shaders = 0;
382 glGetProgramivARB(programObj, GL_OBJECT_ATTACHED_OBJECTS_ARB, &attached_shaders);
383 if (!attached_shaders) {
387 GLhandleARB *shaderObjs = new GLhandleARB[attached_shaders];
389 glGetAttachedObjectsARB(programObj, attached_shaders, &count, shaderObjs);
390 for (GLsizei i = 0; i < count; ++ i) {
391 writeShaderObj(json, shaderObjs[i]);
393 delete [] shaderObjs;
397 writeArbProgram(JSONWriter &json, GLenum target)
399 if (!glIsEnabled(target)) {
403 GLint program_length = 0;
404 glGetProgramivARB(target, GL_PROGRAM_LENGTH_ARB, &program_length);
405 if (!program_length) {
409 GLchar *source = new GLchar[program_length + 1];
411 glGetProgramStringARB(target, GL_PROGRAM_STRING_ARB, source);
412 source[program_length] = 0;
414 json.beginMember(enum_string(target));
415 json.writeString(source);
425 writeTextureImage(JSONWriter &json, GLenum target, GLint level)
427 GLint width, height = 1, depth = 1;
430 glGetTexLevelParameteriv(target, level, GL_TEXTURE_WIDTH, &width);
432 if (target != GL_TEXTURE_1D) {
434 glGetTexLevelParameteriv(target, level, GL_TEXTURE_HEIGHT, &height);
435 if (target == GL_TEXTURE_3D) {
437 glGetTexLevelParameteriv(target, level, GL_TEXTURE_DEPTH, &depth);
441 if (width <= 0 || height <= 0 || depth <= 0) {
446 GLint active_texture = GL_TEXTURE0;
447 glGetIntegerv(GL_ACTIVE_TEXTURE, &active_texture);
448 snprintf(label, sizeof label, "%s, %s, level = %i", _enum_string(active_texture), _enum_string(target), level);
450 json.beginMember(label);
454 // Tell the GUI this is no ordinary object, but an image
455 json.writeStringMember("__class__", "image");
457 json.writeNumberMember("__width__", width);
458 json.writeNumberMember("__height__", height);
459 json.writeNumberMember("__depth__", depth);
461 // Hardcoded for now, but we could chose types more adequate to the
462 // texture internal format
463 json.writeStringMember("__type__", "uint8");
464 json.writeBoolMember("__normalized__", true);
465 json.writeNumberMember("__channels__", 4);
467 GLubyte *pixels = new GLubyte[depth*width*height*4];
469 glGetTexImage(target, level, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
471 json.beginMember("__data__");
474 Image::writePixelsToBuffer(pixels, width, height, 4, false, &pngBuffer, &pngBufferSize);
475 json.writeBase64(pngBuffer, pngBufferSize);
477 json.endMember(); // __data__
486 getDrawableBounds(GLint *width, GLint *height) {
489 HDC hDC = wglGetCurrentDC();
494 HWND hWnd = WindowFromDC(hDC);
497 if (!GetClientRect(hWnd, &rect)) {
501 *width = rect.right - rect.left;
502 *height = rect.bottom - rect.top;
504 #elif 0 /* __APPLE__ */
506 CGLError CGLGetSurface(CGLContextObj, CGSConnectionID*, CGSWindowID*, CGSSurfaceID*);
507 CGError CGSGetWindowBounds(CGSConnectionID, CGWindowID, CGRect *ret);
515 unsigned int w, h, bw, depth;
517 display = glXGetCurrentDisplay();
522 drawable = glXGetCurrentDrawable();
523 if (drawable == None) {
527 if (!XGetGeometry(display, drawable, &root, &x, &y, &w, &h, &bw, &depth)) {
541 writeDrawBufferImage(JSONWriter &json, GLenum format)
543 GLint channels = __gl_format_channels(format);
547 if (!getDrawableBounds(&width, &height)) {
552 // Tell the GUI this is no ordinary object, but an image
553 json.writeStringMember("__class__", "image");
555 json.writeNumberMember("__width__", width);
556 json.writeNumberMember("__height__", height);
557 json.writeNumberMember("__depth__", 1);
559 // Hardcoded for now, but we could chose types more adequate to the
560 // texture internal format
561 json.writeStringMember("__type__", "uint8");
562 json.writeBoolMember("__normalized__", true);
563 json.writeNumberMember("__channels__", channels);
565 GLubyte *pixels = new GLubyte[width*height*channels];
567 GLint drawbuffer = GL_NONE;
568 GLint readbuffer = GL_NONE;
569 glGetIntegerv(GL_DRAW_BUFFER, &drawbuffer);
570 glGetIntegerv(GL_READ_BUFFER, &readbuffer);
571 glReadBuffer(drawbuffer);
573 glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
574 glPixelStorei(GL_PACK_ALIGNMENT, 1);
576 glReadPixels(0, 0, width, height, format, GL_UNSIGNED_BYTE, pixels);
579 glReadBuffer(readbuffer);
581 json.beginMember("__data__");
584 Image::writePixelsToBuffer(pixels, width, height, channels, false, &pngBuffer, &pngBufferSize);
585 //std::cerr <<" Before = "<<(width * height * channels * sizeof *pixels)
586 // <<", after = "<<pngBufferSize << ", ratio = " << double(width * height * channels * sizeof *pixels)/pngBufferSize;
587 json.writeBase64(pngBuffer, pngBufferSize);
589 json.endMember(); // __data__
597 downsampledFramebuffer(GLuint oldFbo, GLint drawbuffer,
598 GLint colorRb, GLint depthRb, GLint stencilRb,
599 GLuint *rbs, GLint *numRbs)
607 glGenFramebuffers(1, &fbo);
608 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
610 glBindRenderbuffer(GL_RENDERBUFFER, colorRb);
611 glGetRenderbufferParameteriv(GL_RENDERBUFFER,
612 GL_RENDERBUFFER_WIDTH, &w);
613 glGetRenderbufferParameteriv(GL_RENDERBUFFER,
614 GL_RENDERBUFFER_HEIGHT, &h);
615 glGetRenderbufferParameteriv(GL_RENDERBUFFER,
616 GL_RENDERBUFFER_INTERNAL_FORMAT, &format);
618 glGenRenderbuffers(1, &rbs[*numRbs]);
619 glBindRenderbuffer(GL_RENDERBUFFER, rbs[*numRbs]);
620 glRenderbufferStorage(GL_RENDERBUFFER, format, w, h);
621 glFramebufferRenderbuffer(GL_FRAMEBUFFER, drawbuffer,
622 GL_RENDERBUFFER, rbs[*numRbs]);
624 glBindFramebuffer(GL_READ_FRAMEBUFFER, oldFbo);
625 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
626 glDrawBuffer(drawbuffer);
627 glReadBuffer(drawbuffer);
628 glBlitFramebuffer(0, 0, w, h, 0, 0, w, h,
629 GL_COLOR_BUFFER_BIT, GL_NEAREST);
630 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
633 if (stencilRb == depthRb && stencilRb) {
634 //combined depth and stencil buffer
635 glBindRenderbuffer(GL_RENDERBUFFER, depthRb);
636 glGetRenderbufferParameteriv(GL_RENDERBUFFER,
637 GL_RENDERBUFFER_WIDTH, &w);
638 glGetRenderbufferParameteriv(GL_RENDERBUFFER,
639 GL_RENDERBUFFER_HEIGHT, &h);
640 glGetRenderbufferParameteriv(GL_RENDERBUFFER,
641 GL_RENDERBUFFER_INTERNAL_FORMAT, &format);
643 glGenRenderbuffers(1, &rbs[*numRbs]);
644 glBindRenderbuffer(GL_RENDERBUFFER, rbs[*numRbs]);
645 glRenderbufferStorage(GL_RENDERBUFFER, format, w, h);
646 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
647 GL_RENDERBUFFER, rbs[*numRbs]);
648 glBindFramebuffer(GL_READ_FRAMEBUFFER, oldFbo);
649 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
650 glBlitFramebuffer(0, 0, w, h, 0, 0, w, h,
651 GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
652 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
656 glBindRenderbuffer(GL_RENDERBUFFER, depthRb);
657 glGetRenderbufferParameteriv(GL_RENDERBUFFER,
658 GL_RENDERBUFFER_WIDTH, &w);
659 glGetRenderbufferParameteriv(GL_RENDERBUFFER,
660 GL_RENDERBUFFER_HEIGHT, &h);
661 glGetRenderbufferParameteriv(GL_RENDERBUFFER,
662 GL_RENDERBUFFER_INTERNAL_FORMAT, &format);
664 glGenRenderbuffers(1, &rbs[*numRbs]);
665 glBindRenderbuffer(GL_RENDERBUFFER, rbs[*numRbs]);
666 glRenderbufferStorage(GL_RENDERBUFFER, format, w, h);
667 glFramebufferRenderbuffer(GL_FRAMEBUFFER,
669 GL_RENDERBUFFER, rbs[*numRbs]);
670 glBindFramebuffer(GL_READ_FRAMEBUFFER, oldFbo);
671 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
672 glDrawBuffer(GL_DEPTH_ATTACHMENT);
673 glReadBuffer(GL_DEPTH_ATTACHMENT);
674 glBlitFramebuffer(0, 0, w, h, 0, 0, w, h,
675 GL_DEPTH_BUFFER_BIT, GL_NEAREST);
679 glBindRenderbuffer(GL_RENDERBUFFER, stencilRb);
680 glGetRenderbufferParameteriv(GL_RENDERBUFFER,
681 GL_RENDERBUFFER_WIDTH, &w);
682 glGetRenderbufferParameteriv(GL_RENDERBUFFER,
683 GL_RENDERBUFFER_HEIGHT, &h);
684 glGetRenderbufferParameteriv(GL_RENDERBUFFER,
685 GL_RENDERBUFFER_INTERNAL_FORMAT, &format);
687 glGenRenderbuffers(1, &rbs[*numRbs]);
688 glBindRenderbuffer(GL_RENDERBUFFER, rbs[*numRbs]);
689 glRenderbufferStorage(GL_RENDERBUFFER, format, w, h);
690 glFramebufferRenderbuffer(GL_FRAMEBUFFER,
691 GL_STENCIL_ATTACHMENT,
692 GL_RENDERBUFFER, rbs[*numRbs]);
693 glBindFramebuffer(GL_READ_FRAMEBUFFER, oldFbo);
694 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
695 glDrawBuffer(GL_STENCIL_ATTACHMENT);
696 glReadBuffer(GL_STENCIL_ATTACHMENT);
697 glBlitFramebuffer(0, 0, w, h, 0, 0, w, h,
698 GL_STENCIL_BUFFER_BIT, GL_NEAREST);
707 writeDrawBuffers(JSONWriter &json, GLboolean writeDepth, GLboolean writeStencil)
709 json.beginMember("GL_RGBA");
710 writeDrawBufferImage(json, GL_RGBA);
714 json.beginMember("GL_DEPTH_COMPONENT");
715 writeDrawBufferImage(json, GL_DEPTH_COMPONENT);
720 json.beginMember("GL_STENCIL_INDEX");
721 writeDrawBufferImage(json, GL_STENCIL_INDEX);
729 print 'static inline void'
730 print 'writeTexture(JSONWriter &json, GLenum target, GLenum binding)'
732 print ' GLint texture_binding = 0;'
733 print ' glGetIntegerv(binding, &texture_binding);'
734 print ' if (!glIsEnabled(target) && !texture_binding) {'
738 print ' GLint level = 0;'
740 print ' GLint width = 0, height = 0;'
741 print ' glGetTexLevelParameteriv(target, level, GL_TEXTURE_WIDTH, &width);'
742 print ' glGetTexLevelParameteriv(target, level, GL_TEXTURE_HEIGHT, &height);'
743 print ' if (!width || !height) {'
747 print ' if (target == GL_TEXTURE_CUBE_MAP) {'
748 print ' for (int face = 0; face < 6; ++face) {'
749 print ' writeTextureImage(json, GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level);'
752 print ' writeTextureImage(json, target, level);'
756 print ' } while(true);'
760 print 'void glstate::state_dump(std::ostream &os)'
762 print ' JSONWriter json(os);'
763 self.dump_parameters()
764 self.dump_current_program()
766 self.dump_framebuffer()
770 def dump_parameters(self):
771 print ' json.beginMember("parameters");'
772 print ' json.beginObject();'
774 self.dump_atoms(glGet)
776 self.dump_material_params()
777 self.dump_light_params()
778 self.dump_vertex_attribs()
779 self.dump_texenv_params()
780 self.dump_program_params()
781 self.dump_texture_parameters()
783 print ' json.endObject();'
784 print ' json.endMember(); // parameters'
787 def dump_material_params(self):
788 for face in ['GL_FRONT', 'GL_BACK']:
789 print ' json.beginMember("%s");' % face
790 print ' json.beginObject();'
791 self.dump_atoms(glGetMaterial, face)
792 print ' json.endObject();'
795 def dump_light_params(self):
796 print ' GLint max_lights = 0;'
797 print ' __glGetIntegerv(GL_MAX_LIGHTS, &max_lights);'
798 print ' for (GLint index = 0; index < max_lights; ++index) {'
799 print ' GLenum light = GL_LIGHT0 + index;'
800 print ' if (glIsEnabled(light)) {'
801 print ' char name[32];'
802 print ' snprintf(name, sizeof name, "GL_LIGHT%i", index);'
803 print ' json.beginMember(name);'
804 print ' json.beginObject();'
805 self.dump_atoms(glGetLight, ' GL_LIGHT0 + index')
806 print ' json.endObject();'
807 print ' json.endMember(); // GL_LIGHTi'
812 def dump_texenv_params(self):
813 for target in ['GL_TEXTURE_ENV', 'GL_TEXTURE_FILTER_CONTROL', 'GL_POINT_SPRITE']:
814 if target != 'GL_TEXTURE_FILTER_CONTROL':
815 print ' if (glIsEnabled(%s)) {' % target
818 print ' json.beginMember("%s");' % target
819 print ' json.beginObject();'
820 self.dump_atoms(glGetTexEnv, target)
821 print ' json.endObject();'
824 def dump_vertex_attribs(self):
825 print ' GLint max_vertex_attribs = 0;'
826 print ' __glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &max_vertex_attribs);'
827 print ' for (GLint index = 0; index < max_vertex_attribs; ++index) {'
828 print ' char name[32];'
829 print ' snprintf(name, sizeof name, "GL_VERTEX_ATTRIB_ARRAY%i", index);'
830 print ' json.beginMember(name);'
831 print ' json.beginObject();'
832 self.dump_atoms(glGetVertexAttrib, 'index')
833 print ' json.endObject();'
834 print ' json.endMember(); // GL_VERTEX_ATTRIB_ARRAYi'
839 'GL_FRAGMENT_PROGRAM_ARB',
840 'GL_VERTEX_PROGRAM_ARB',
843 def dump_program_params(self):
844 for target in self.program_targets:
845 print ' if (glIsEnabled(%s)) {' % target
846 print ' json.beginMember("%s");' % target
847 print ' json.beginObject();'
848 self.dump_atoms(glGetProgramARB, target)
849 print ' json.endObject();'
852 def dump_texture_parameters(self):
854 print ' GLint active_texture = GL_TEXTURE0;'
855 print ' glGetIntegerv(GL_ACTIVE_TEXTURE, &active_texture);'
856 print ' GLint max_texture_coords = 0;'
857 print ' glGetIntegerv(GL_MAX_TEXTURE_COORDS, &max_texture_coords);'
858 print ' GLint max_combined_texture_image_units = 0;'
859 print ' glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_combined_texture_image_units);'
860 print ' GLint max_units = std::max(max_combined_texture_image_units, max_texture_coords);'
861 print ' for (GLint unit = 0; unit < max_units; ++unit) {'
862 print ' char name[32];'
863 print ' snprintf(name, sizeof name, "GL_TEXTURE%i", unit);'
864 print ' json.beginMember(name);'
865 print ' glActiveTexture(GL_TEXTURE0 + unit);'
866 print ' json.beginObject();'
867 print ' GLint texture;'
869 for target, binding in texture_targets:
870 print ' // %s' % target
871 print ' texture = 0;'
872 print ' glGetIntegerv(%s, &texture);' % binding
873 print ' if (glIsEnabled(%s) || texture) {' % target
874 print ' json.beginMember("%s");' % target
875 print ' json.beginObject();'
876 self.dump_atoms(glGetTexParameter, target)
877 # We only dump the first level parameters
878 self.dump_atoms(glGetTexLevelParameter, target, "0")
879 print ' json.endObject();'
880 print ' json.endMember(); // %s' % target
883 print ' json.endObject();'
884 print ' json.endMember(); // GL_TEXTUREi'
886 print ' glActiveTexture(active_texture);'
890 def dump_current_program(self):
891 print ' json.beginMember("shaders");'
892 print ' json.beginObject();'
893 print ' writeCurrentProgram(json);'
894 for target in self.program_targets:
895 print ' writeArbProgram(json, %s);' % target
896 print ' json.endObject();'
897 print ' json.endMember(); //shaders'
900 def dump_textures(self):
902 print ' json.beginMember("textures");'
903 print ' json.beginObject();'
904 print ' GLint active_texture = GL_TEXTURE0;'
905 print ' glGetIntegerv(GL_ACTIVE_TEXTURE, &active_texture);'
906 print ' GLint max_texture_coords = 0;'
907 print ' glGetIntegerv(GL_MAX_TEXTURE_COORDS, &max_texture_coords);'
908 print ' GLint max_combined_texture_image_units = 0;'
909 print ' glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_combined_texture_image_units);'
910 print ' GLint max_units = std::max(max_combined_texture_image_units, max_texture_coords);'
911 print ' for (GLint unit = 0; unit < max_units; ++unit) {'
912 print ' GLenum texture = GL_TEXTURE0 + unit;'
913 print ' glActiveTexture(texture);'
914 for target, binding in texture_targets:
915 print ' writeTexture(json, %s, %s);' % (target, binding)
917 print ' glActiveTexture(active_texture);'
918 print ' json.endObject();'
919 print ' json.endMember(); // textures'
923 def dump_framebuffer(self):
924 print ' json.beginMember("framebuffer");'
925 print ' json.beginObject();'
926 # TODO: Handle real FBOs
928 print ' GLint boundDrawFbo = 0, boundReadFbo = 0;'
929 print ' glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundDrawFbo);'
930 print ' glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &boundReadFbo);'
931 print ' if (!boundDrawFbo) {'
932 print ' GLint depth_bits = 0;'
933 print ' glGetIntegerv(GL_DEPTH_BITS, &depth_bits);'
934 print ' GLint stencil_bits = 0;'
935 print ' glGetIntegerv(GL_STENCIL_BITS, &stencil_bits);'
936 print ' writeDrawBuffers(json, depth_bits, stencil_bits);'
938 print ' GLint colorRb, stencilRb, depthRb;'
939 print ' GLint boundRb;'
940 print ' glGetIntegerv(GL_RENDERBUFFER_BINDING, &boundRb);'
941 print ' GLint drawbuffer = GL_NONE;'
942 print ' glGetIntegerv(GL_DRAW_BUFFER, &drawbuffer);'
944 print ' glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,'
946 print ' GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,'
948 print ' glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,'
949 print ' GL_DEPTH_ATTACHMENT,'
950 print ' GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,'
952 print ' glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,'
953 print ' GL_STENCIL_ATTACHMENT,'
954 print ' GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,'
955 print ' &stencilRb);'
957 print ' GLint colorSamples, depthSamples, stencilSamples;'
958 print ' GLuint rbs[3];'
959 print ' GLint numRbs = 0;'
960 print ' GLuint fboCopy = 0;'
961 print ' glBindRenderbuffer(GL_RENDERBUFFER, colorRb);'
962 print ' glGetRenderbufferParameteriv(GL_RENDERBUFFER,'
963 print ' GL_RENDERBUFFER_SAMPLES, &colorSamples);'
964 print ' glBindRenderbuffer(GL_RENDERBUFFER, depthRb);'
965 print ' glGetRenderbufferParameteriv(GL_RENDERBUFFER,'
966 print ' GL_RENDERBUFFER_SAMPLES, &depthSamples);'
967 print ' glBindRenderbuffer(GL_RENDERBUFFER, stencilRb);'
968 print ' glGetRenderbufferParameteriv(GL_RENDERBUFFER,'
969 print ' GL_RENDERBUFFER_SAMPLES, &stencilSamples);'
970 print ' glBindRenderbuffer(GL_RENDERBUFFER, boundRb);'
972 print ' if (colorSamples || depthSamples || stencilSamples) {'
973 print ' //glReadPixels doesnt support multisampled buffers so we need'
974 print ' // to blit the fbo to a temporary one'
975 print ' fboCopy = downsampledFramebuffer(boundDrawFbo, drawbuffer,'
976 print ' colorRb, depthRb, stencilRb,'
977 print ' rbs, &numRbs);'
979 print ' glDrawBuffer(drawbuffer);'
980 print ' glReadBuffer(drawbuffer);'
982 print ' writeDrawBuffers(json, depthRb, stencilRb);'
984 print ' if (fboCopy) {'
985 print ' glBindFramebuffer(GL_FRAMEBUFFER, boundDrawFbo);'
986 print ' glBindFramebuffer(GL_READ_FRAMEBUFFER, boundReadFbo);'
987 print ' glBindFramebuffer(GL_DRAW_FRAMEBUFFER, boundDrawFbo);'
988 print ' glBindRenderbuffer(GL_RENDERBUFFER_BINDING, boundRb);'
989 print ' glDeleteRenderbuffers(numRbs, rbs);'
990 print ' glDeleteFramebuffers(1, &fboCopy);'
994 print ' json.endObject();'
995 print ' json.endMember(); // framebuffer'
998 def dump_atoms(self, getter, *args):
999 for function, type, count, name in parameters:
1000 inflection = getter.inflector.radical + getter.suffix
1001 if inflection not in function.split(','):
1005 print ' // %s' % name
1007 type, value = getter(*(args + (name,)))
1008 print ' if (glGetError() != GL_NO_ERROR) {'
1009 #print ' std::cerr << "warning: %s(%s) failed\\n";' % (inflection, name)
1011 print ' json.beginMember("%s");' % name
1012 JsonWriter().visit(type, value)
1013 print ' json.endMember();'
1019 if __name__ == '__main__':
1020 StateDumper().dump()