]> git.cworth.org Git - apitrace/blobdiff - glstate.py
List GL_TEXTURE_xxx and GL_TEXTURE_BINDING_xxx params per texture unit.
[apitrace] / glstate.py
index 89d92badf3c9500f4b38fc54f716b1e4890f1aeb..c348d2b99b69dd2273ca30067f6a5c1fe237f7c6 100644 (file)
@@ -41,6 +41,10 @@ texture_targets = [
     ('GL_TEXTURE_CUBE_MAP', 'GL_TEXTURE_BINDING_CUBE_MAP')
 ]
 
+framebuffer_targets = [
+    ('GL_DRAW_FRAMEBUFFER', 'GL_DRAW_FRAMEBUFFER_BINDING'),
+    ('GL_READ_FRAMEBUFFER', 'GL_READ_FRAMEBUFFER_BINDING'),
+]
 
 class GetInflector:
     '''Objects that describes how to inflect.'''
@@ -172,7 +176,10 @@ glGetVertexAttrib = StateGetter('glGetVertexAttrib', {I: 'iv', F: 'fv', D: 'dv',
 glGetTexParameter = StateGetter('glGetTexParameter', {I: 'iv', F: 'fv'})
 glGetTexEnv = StateGetter('glGetTexEnv', {I: 'iv', F: 'fv'})
 glGetTexLevelParameter = StateGetter('glGetTexLevelParameter', {I: 'iv', F: 'fv'})
+glGetShader = StateGetter('glGetShaderiv', {I: 'iv'})
+glGetProgram = StateGetter('glGetProgram', {I: 'iv'})
 glGetProgramARB = StateGetter('glGetProgram', {I: 'iv', F: 'fv', S: 'Stringv'}, 'ARB')
+glGetFramebufferAttachmentParameter = StateGetter('glGetFramebufferAttachmentParameter', {I: 'iv'})
 
 
 class JsonWriter(Visitor):
@@ -195,7 +202,7 @@ class JsonWriter(Visitor):
 
     def visit_enum(self, enum, instance):
         if enum.expr == 'GLenum':
-            print '    writeEnum(json, %s);' % instance
+            print '    dumpEnum(json, %s);' % instance
         else:
             print '    json.writeNumber(%s);' % instance
 
@@ -230,19 +237,17 @@ class StateDumper:
 
     def dump(self):
         print '#include <string.h>'
-        print '#include <iostream>'
-        print '#include <algorithm>'
         print
-        print '#include "image.hpp"'
         print '#include "json.hpp"'
-        print '#include "glimports.hpp"'
         print '#include "glproc.hpp"'
         print '#include "glsize.hpp"'
-        print '#include "glretrace.hpp"'
+        print '#include "glstate.hpp"'
+        print
+        print 'namespace glstate {'
         print
 
-        print 'static const char *'
-        print '_enum_string(GLenum pname)'
+        print 'const char *'
+        print 'enumToString(GLenum pname)'
         print '{'
         print '    switch(pname) {'
         for name in GLenum.values:
@@ -254,24 +259,17 @@ class StateDumper:
         print '}'
         print
 
-        print 'static const char *'
-        print 'enum_string(GLenum pname)'
+        print 'static void'
+        print 'dumpFramebufferAttachementParameters(JSONWriter &json, GLenum target, GLenum attachment)'
         print '{'
-        print '    const char *s = _enum_string(pname);'
-        print '    if (s) {'
-        print '        return s;'
-        print '    } else {'
-        print '        static char buf[16];'
-        print '        snprintf(buf, sizeof buf, "0x%04x", pname);'
-        print '        return buf;'
-        print '    }'
+        self.dump_attachment_parameters('target', 'attachment')
         print '}'
         print
 
-        print 'static inline void'
-        print 'writeEnum(JSONWriter &json, GLenum pname)'
+        print 'void'
+        print 'dumpEnum(JSONWriter &json, GLenum pname)'
         print '{'
-        print '    const char *s = _enum_string(pname);'
+        print '    const char *s = enumToString(pname);'
         print '    if (s) {'
         print '        json.writeString(s);'
         print '    } else {'
@@ -280,383 +278,8 @@ class StateDumper:
         print '}'
         print
 
-        # shaders
-        print '''
-static void
-writeShader(JSONWriter &json, GLuint shader)
-{
-    if (!shader) {
-        return;
-    }
-
-    GLint shader_type = 0;
-    glGetShaderiv(shader, GL_SHADER_TYPE, &shader_type);
-    if (!shader_type) {
-        return;
-    }
-
-    GLint source_length = 0;
-    glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &source_length);
-    if (!source_length) {
-        return;
-    }
-
-    GLchar *source = new GLchar[source_length];
-    GLsizei length = 0;
-    source[0] = 0;
-    glGetShaderSource(shader, source_length, &length, source);
-
-    json.beginMember(enum_string(shader_type));
-    json.writeString(source);
-    json.endMember();
-
-    delete [] source;
-}
-
-static inline void
-writeCurrentProgram(JSONWriter &json)
-{
-    GLint program = 0;
-    glGetIntegerv(GL_CURRENT_PROGRAM, &program);
-    if (!program) {
-        return;
-    }
-
-    GLint attached_shaders = 0;
-    glGetProgramiv(program, GL_ATTACHED_SHADERS, &attached_shaders);
-    if (!attached_shaders) {
-        return;
-    }
-
-    GLuint *shaders = new GLuint[attached_shaders];
-    GLsizei count = 0;
-    glGetAttachedShaders(program, attached_shaders, &count, shaders);
-    for (GLsizei i = 0; i < count; ++ i) {
-       writeShader(json, shaders[i]);
-    }
-    delete [] shaders;
-}
-
-static inline void
-writeArbProgram(JSONWriter &json, GLenum target)
-{
-    if (!glIsEnabled(target)) {
-        return;
-    }
-
-    GLint program_length = 0;
-    glGetProgramivARB(target, GL_PROGRAM_LENGTH_ARB, &program_length);
-    if (!program_length) {
-        return;
-    }
-
-    GLchar *source = new GLchar[program_length + 1];
-    source[0] = 0;
-    glGetProgramStringARB(target, GL_PROGRAM_STRING_ARB, source);
-    source[program_length] = 0;
-
-    json.beginMember(enum_string(target));
-    json.writeString(source);
-    json.endMember();
-
-    delete [] source;
-}
-'''
-
-        # texture image
-        print '''
-static inline void
-writeTextureImage(JSONWriter &json, GLenum target, GLint level)
-{
-    GLint width, height = 1, depth = 1;
-
-    width = 0;
-    glGetTexLevelParameteriv(target, level, GL_TEXTURE_WIDTH, &width);
-
-    if (target != GL_TEXTURE_1D) {
-        height = 0;
-        glGetTexLevelParameteriv(target, level, GL_TEXTURE_HEIGHT, &height);
-        if (target == GL_TEXTURE_3D) {
-            depth = 0;
-            glGetTexLevelParameteriv(target, level, GL_TEXTURE_DEPTH, &depth);
-        }
-    }
-
-    if (width <= 0 || height <= 0 || depth <= 0) {
-        return;
-    } else {
-        char label[512];
-
-        GLint active_texture = GL_TEXTURE0;
-        glGetIntegerv(GL_ACTIVE_TEXTURE, &active_texture);
-        snprintf(label, sizeof label, "%s, %s, level = %i", _enum_string(active_texture), _enum_string(target), level);
-
-        json.beginMember(label);
-
-        json.beginObject();
-
-        // Tell the GUI this is no ordinary object, but an image
-        json.writeStringMember("__class__", "image");
-
-        json.writeNumberMember("__width__", width);
-        json.writeNumberMember("__height__", height);
-        json.writeNumberMember("__depth__", depth);
-
-        // Hardcoded for now, but we could chose types more adequate to the
-        // texture internal format
-        json.writeStringMember("__type__", "uint8");
-        json.writeBoolMember("__normalized__", true);
-        json.writeNumberMember("__channels__", 4);
-        
-        GLubyte *pixels = new GLubyte[depth*width*height*4];
-
-        glGetTexImage(target, level, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
-
-        json.beginMember("__data__");
-        char *pngBuffer;
-        int pngBufferSize;
-        Image::writePixelsToBuffer(pixels, width, height, 4, false, &pngBuffer, &pngBufferSize);
-        json.writeBase64(pngBuffer, pngBufferSize);
-        free(pngBuffer);
-        json.endMember(); // __data__
-
-        delete [] pixels;
-        json.endObject();
-    }
-}
-
-static inline void
-writeDrawBufferImage(JSONWriter &json, GLenum format)
-{
-    GLint width  = glretrace::window_width;
-    GLint height = glretrace::window_height;
-
-    GLint channels = __gl_format_channels(format);
-
-    if (!width || !height) {
-        json.writeNull();
-    } else {
-        json.beginObject();
-
-        // Tell the GUI this is no ordinary object, but an image
-        json.writeStringMember("__class__", "image");
-
-        json.writeNumberMember("__width__", width);
-        json.writeNumberMember("__height__", height);
-        json.writeNumberMember("__depth__", 1);
-
-        // Hardcoded for now, but we could chose types more adequate to the
-        // texture internal format
-        json.writeStringMember("__type__", "uint8");
-        json.writeBoolMember("__normalized__", true);
-        json.writeNumberMember("__channels__", channels);
-
-        GLubyte *pixels = new GLubyte[width*height*channels];
-        
-        GLint drawbuffer = glretrace::double_buffer ? GL_BACK : GL_FRONT;
-        GLint readbuffer = glretrace::double_buffer ? GL_BACK : GL_FRONT;
-        glGetIntegerv(GL_DRAW_BUFFER, &drawbuffer);
-        glGetIntegerv(GL_READ_BUFFER, &readbuffer);
-        glReadBuffer(drawbuffer);
-
-        glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
-        glPixelStorei(GL_PACK_ALIGNMENT, 1);
-
-        glReadPixels(0, 0, width, height, format, GL_UNSIGNED_BYTE, pixels);
-
-        glPopClientAttrib();
-        glReadBuffer(readbuffer);
-
-        json.beginMember("__data__");
-        char *pngBuffer;
-        int pngBufferSize;
-        Image::writePixelsToBuffer(pixels, width, height, channels, false, &pngBuffer, &pngBufferSize);
-        //std::cerr <<" Before = "<<(width * height * channels * sizeof *pixels)
-        //          <<", after = "<<pngBufferSize << ", ratio = " << double(width * height * channels * sizeof *pixels)/pngBufferSize;
-        json.writeBase64(pngBuffer, pngBufferSize);
-        free(pngBuffer);
-        json.endMember(); // __data__
-
-        delete [] pixels;
-        json.endObject();
-    }
-}
-
-static inline GLuint
-downsampledFramebuffer(GLuint oldFbo, GLint drawbuffer,
-                       GLint colorRb, GLint depthRb, GLint stencilRb,
-                       GLuint *rbs, GLint *numRbs)
-{
-    GLuint fbo;
-    GLint format;
-    GLint w, h;
-
-    *numRbs = 0;
-
-    glGenFramebuffers(1, &fbo);
-    glBindFramebuffer(GL_FRAMEBUFFER, fbo);
-
-    glBindRenderbuffer(GL_RENDERBUFFER, colorRb);
-    glGetRenderbufferParameteriv(GL_RENDERBUFFER,
-                                 GL_RENDERBUFFER_WIDTH, &w);
-    glGetRenderbufferParameteriv(GL_RENDERBUFFER,
-                                 GL_RENDERBUFFER_HEIGHT, &h);
-    glGetRenderbufferParameteriv(GL_RENDERBUFFER,
-                                 GL_RENDERBUFFER_INTERNAL_FORMAT, &format);
-
-    glGenRenderbuffers(1, &rbs[*numRbs]);
-    glBindRenderbuffer(GL_RENDERBUFFER, rbs[*numRbs]);
-    glRenderbufferStorage(GL_RENDERBUFFER, format, w, h);
-    glFramebufferRenderbuffer(GL_FRAMEBUFFER, drawbuffer,
-                              GL_RENDERBUFFER, rbs[*numRbs]);
-
-    glBindFramebuffer(GL_READ_FRAMEBUFFER, oldFbo);
-    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
-    glDrawBuffer(drawbuffer);
-    glReadBuffer(drawbuffer);
-    glBlitFramebuffer(0, 0, w, h, 0, 0, w, h,
-                      GL_COLOR_BUFFER_BIT, GL_NEAREST);
-    glBindFramebuffer(GL_FRAMEBUFFER, fbo);
-    ++*numRbs;
-
-    if (stencilRb == depthRb && stencilRb) {
-        //combined depth and stencil buffer
-        glBindRenderbuffer(GL_RENDERBUFFER, depthRb);
-        glGetRenderbufferParameteriv(GL_RENDERBUFFER,
-                                     GL_RENDERBUFFER_WIDTH, &w);
-        glGetRenderbufferParameteriv(GL_RENDERBUFFER,
-                                     GL_RENDERBUFFER_HEIGHT, &h);
-        glGetRenderbufferParameteriv(GL_RENDERBUFFER,
-                                     GL_RENDERBUFFER_INTERNAL_FORMAT, &format);
-
-        glGenRenderbuffers(1, &rbs[*numRbs]);
-        glBindRenderbuffer(GL_RENDERBUFFER, rbs[*numRbs]);
-        glRenderbufferStorage(GL_RENDERBUFFER, format, w, h);
-        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
-                                  GL_RENDERBUFFER, rbs[*numRbs]);
-        glBindFramebuffer(GL_READ_FRAMEBUFFER, oldFbo);
-        glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
-        glBlitFramebuffer(0, 0, w, h, 0, 0, w, h,
-                          GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
-        glBindFramebuffer(GL_FRAMEBUFFER, fbo);
-        ++*numRbs;
-    } else {
-        if (depthRb) {
-            glBindRenderbuffer(GL_RENDERBUFFER, depthRb);
-            glGetRenderbufferParameteriv(GL_RENDERBUFFER,
-                                         GL_RENDERBUFFER_WIDTH, &w);
-            glGetRenderbufferParameteriv(GL_RENDERBUFFER,
-                                         GL_RENDERBUFFER_HEIGHT, &h);
-            glGetRenderbufferParameteriv(GL_RENDERBUFFER,
-                                         GL_RENDERBUFFER_INTERNAL_FORMAT, &format);
-
-            glGenRenderbuffers(1, &rbs[*numRbs]);
-            glBindRenderbuffer(GL_RENDERBUFFER, rbs[*numRbs]);
-            glRenderbufferStorage(GL_RENDERBUFFER, format, w, h);
-            glFramebufferRenderbuffer(GL_FRAMEBUFFER,
-                                      GL_DEPTH_ATTACHMENT,
-                                      GL_RENDERBUFFER, rbs[*numRbs]);
-            glBindFramebuffer(GL_READ_FRAMEBUFFER, oldFbo);
-            glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
-            glDrawBuffer(GL_DEPTH_ATTACHMENT);
-            glReadBuffer(GL_DEPTH_ATTACHMENT);
-            glBlitFramebuffer(0, 0, w, h, 0, 0, w, h,
-                              GL_DEPTH_BUFFER_BIT, GL_NEAREST);
-            ++*numRbs;
-        }
-        if (stencilRb) {
-            glBindRenderbuffer(GL_RENDERBUFFER, stencilRb);
-            glGetRenderbufferParameteriv(GL_RENDERBUFFER,
-                                         GL_RENDERBUFFER_WIDTH, &w);
-            glGetRenderbufferParameteriv(GL_RENDERBUFFER,
-                                         GL_RENDERBUFFER_HEIGHT, &h);
-            glGetRenderbufferParameteriv(GL_RENDERBUFFER,
-                                     GL_RENDERBUFFER_INTERNAL_FORMAT, &format);
-
-            glGenRenderbuffers(1, &rbs[*numRbs]);
-            glBindRenderbuffer(GL_RENDERBUFFER, rbs[*numRbs]);
-            glRenderbufferStorage(GL_RENDERBUFFER, format, w, h);
-            glFramebufferRenderbuffer(GL_FRAMEBUFFER,
-                                      GL_STENCIL_ATTACHMENT,
-                                      GL_RENDERBUFFER, rbs[*numRbs]);
-            glBindFramebuffer(GL_READ_FRAMEBUFFER, oldFbo);
-            glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
-            glDrawBuffer(GL_STENCIL_ATTACHMENT);
-            glReadBuffer(GL_STENCIL_ATTACHMENT);
-            glBlitFramebuffer(0, 0, w, h, 0, 0, w, h,
-                              GL_STENCIL_BUFFER_BIT, GL_NEAREST);
-            ++*numRbs;
-        }
-    }
-
-    return fbo;
-}
-
-static void
-writeDrawBuffers(JSONWriter &json, GLboolean writeDepth, GLboolean writeStencil)
-{
-    json.beginMember("GL_RGBA");
-    writeDrawBufferImage(json, GL_RGBA);
-    json.endMember();
-
-    if (writeDepth) {
-        json.beginMember("GL_DEPTH_COMPONENT");
-        writeDrawBufferImage(json, GL_DEPTH_COMPONENT);
-        json.endMember();
-    }
-
-    if (writeStencil) {
-        json.beginMember("GL_STENCIL_INDEX");
-        writeDrawBufferImage(json, GL_STENCIL_INDEX);
-        json.endMember();
-    }
-}
-
-'''
-
-        # textures
-        print 'static inline void'
-        print 'writeTexture(JSONWriter &json, GLenum target, GLenum binding)'
+        print 'void dumpParameters(JSONWriter &json)'
         print '{'
-        print '    GLint texture_binding = 0;'
-        print '    glGetIntegerv(binding, &texture_binding);'
-        print '    if (!glIsEnabled(target) && !texture_binding) {'
-        print '        return;'
-        print '    }'
-        print
-        print '    GLint level = 0;'
-        print '    do {'
-        print '        GLint width = 0, height = 0;'
-        print '        glGetTexLevelParameteriv(target, level, GL_TEXTURE_WIDTH, &width);'
-        print '        glGetTexLevelParameteriv(target, level, GL_TEXTURE_HEIGHT, &height);'
-        print '        if (!width || !height) {'
-        print '            break;'
-        print '        }'
-        print
-        print '        if (target == GL_TEXTURE_CUBE_MAP) {'
-        print '            for (int face = 0; face < 6; ++face) {'
-        print '                writeTextureImage(json, GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level);'
-        print '            }'
-        print '        } else {'
-        print '            writeTextureImage(json, target, level);'
-        print '        }'
-        print
-        print '        ++level;'
-        print '    } while(true);'
-        print '}'
-        print
-
-        print 'void glretrace::state_dump(std::ostream &os)'
-        print '{'
-        print '    JSONWriter json(os);'
-        self.dump_parameters()
-        self.dump_current_program()
-        self.dump_textures()
-        self.dump_framebuffer()
-        print '}'
-        print
-
-    def dump_parameters(self):
         print '    json.beginMember("parameters");'
         print '    json.beginObject();'
         
@@ -668,10 +291,14 @@ writeDrawBuffers(JSONWriter &json, GLboolean writeDepth, GLboolean writeStencil)
         self.dump_texenv_params()
         self.dump_program_params()
         self.dump_texture_parameters()
+        self.dump_framebuffer_parameters()
 
         print '    json.endObject();'
         print '    json.endMember(); // parameters'
+        print '}'
         print
+        
+        print '} /*namespace glstate */'
 
     def dump_material_params(self):
         for face in ['GL_FRONT', 'GL_BACK']:
@@ -753,13 +380,18 @@ writeDrawBuffers(JSONWriter &json, GLboolean writeDepth, GLboolean writeStencil)
         print '            json.beginMember(name);'
         print '            glActiveTexture(GL_TEXTURE0 + unit);'
         print '            json.beginObject();'
-        print '            GLint texture;'
+        print '            GLboolean enabled;'
+        print '            GLint binding;'
         print
         for target, binding in texture_targets:
             print '            // %s' % target
-            print '            texture = 0;'
-            print '            glGetIntegerv(%s, &texture);' % binding
-            print '            if (glIsEnabled(%s) || texture) {' % target
+            print '            enabled = GL_FALSE;'
+            print '            glGetBooleanv(%s, &enabled);' % target
+            print '            json.writeBoolMember("%s", enabled);' % target
+            print '            binding = 0;'
+            print '            glGetIntegerv(%s, &binding);' % binding
+            print '            json.writeNumberMember("%s", binding);' % binding
+            print '            if (enabled || binding) {'
             print '                json.beginMember("%s");' % target
             print '                json.beginObject();'
             self.dump_atoms(glGetTexParameter, target)
@@ -776,113 +408,43 @@ writeDrawBuffers(JSONWriter &json, GLboolean writeDepth, GLboolean writeStencil)
         print '    }'
         print
 
-    def dump_current_program(self):
-        print '    json.beginMember("shaders");'
-        print '    json.beginObject();'
-        print '    writeCurrentProgram(json);'
-        for target in self.program_targets:
-            print '    writeArbProgram(json, %s);' % target
-        print '    json.endObject();'
-        print '    json.endMember(); //shaders'
-        print
-
-    def dump_textures(self):
+    def dump_framebuffer_parameters(self):
         print '    {'
-        print '        json.beginMember("textures");'
-        print '        json.beginObject();'
-        print '        GLint active_texture = GL_TEXTURE0;'
-        print '        glGetIntegerv(GL_ACTIVE_TEXTURE, &active_texture);'
-        print '        GLint max_texture_coords = 0;'
-        print '        glGetIntegerv(GL_MAX_TEXTURE_COORDS, &max_texture_coords);'
-        print '        GLint max_combined_texture_image_units = 0;'
-        print '        glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_combined_texture_image_units);'
-        print '        GLint max_units = std::max(max_combined_texture_image_units, max_texture_coords);'
-        print '        for (GLint unit = 0; unit < max_units; ++unit) {'
-        print '            GLenum texture = GL_TEXTURE0 + unit;'
-        print '            glActiveTexture(texture);'
-        for target, binding in texture_targets:
-            print '            writeTexture(json, %s, %s);' % (target, binding)
-        print '        }'
-        print '        glActiveTexture(active_texture);'
-        print '        json.endObject();'
-        print '        json.endMember(); // textures'
+        print '        GLint max_color_attachments = 0;'
+        print '        glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &max_color_attachments);'
+        print '        GLint framebuffer;'
+        for target, binding in framebuffer_targets:
+            print '            // %s' % target
+            print '            framebuffer = 0;'
+            print '            glGetIntegerv(%s, &framebuffer);' % binding
+            print '            if (framebuffer) {'
+            print '                json.beginMember("%s");' % target
+            print '                json.beginObject();'
+            print '                for (GLint i = 0; i < max_color_attachments; ++i) {'
+            print '                    GLint color_attachment = GL_COLOR_ATTACHMENT0 + i;'
+            print '                    dumpFramebufferAttachementParameters(json, %s, color_attachment);' % target
+            print '                }'
+            print '                dumpFramebufferAttachementParameters(json, %s, GL_DEPTH_ATTACHMENT);' % target
+            print '                dumpFramebufferAttachementParameters(json, %s, GL_STENCIL_ATTACHMENT);' % target
+            print '                json.endObject();'
+            print '                json.endMember(); // %s' % target
+            print '            }'
+            print
         print '    }'
         print
 
-    def dump_framebuffer(self):
-        print '    json.beginMember("framebuffer");'
-        print '    json.beginObject();'
-        # TODO: Handle real FBOs
-        print
-        print '    GLint boundDrawFbo = 0, boundReadFbo = 0;'
-        print '    glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundDrawFbo);'
-        print '    glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &boundReadFbo);'
-        print '    if (!boundDrawFbo) {'
-        print '        GLint depth_bits = 0;'
-        print '        glGetIntegerv(GL_DEPTH_BITS, &depth_bits);'
-        print '        GLint stencil_bits = 0;'
-        print '        glGetIntegerv(GL_STENCIL_BITS, &stencil_bits);'
-        print '        writeDrawBuffers(json, depth_bits, stencil_bits);'
-        print '    } else {'
-        print '        GLint colorRb, stencilRb, depthRb;'
-        print '        GLint boundRb;'
-        print '        glGetIntegerv(GL_RENDERBUFFER_BINDING, &boundRb);'
-        print '        GLint drawbuffer = glretrace::double_buffer ? GL_BACK : GL_FRONT;'
-        print '        glGetIntegerv(GL_DRAW_BUFFER, &drawbuffer);'
-        print
-        print '        glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,'
-        print '                                              drawbuffer,'
-        print '                                              GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,'
-        print '                                              &colorRb);'
-        print '        glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,'
-        print '                                              GL_DEPTH_ATTACHMENT,'
-        print '                                              GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,'
-        print '                                              &depthRb);'
-        print '        glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,'
-        print '                                              GL_STENCIL_ATTACHMENT,'
-        print '                                              GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,'
-        print '                                              &stencilRb);'
-        print
-        print '        GLint colorSamples, depthSamples, stencilSamples;'
-        print '        GLuint rbs[3];'
-        print '        GLint numRbs = 0;'
-        print '        GLuint fboCopy = 0;'
-        print '        glBindRenderbuffer(GL_RENDERBUFFER, colorRb);'
-        print '        glGetRenderbufferParameteriv(GL_RENDERBUFFER,'
-        print '                                     GL_RENDERBUFFER_SAMPLES, &colorSamples);'
-        print '        glBindRenderbuffer(GL_RENDERBUFFER, depthRb);'
-        print '        glGetRenderbufferParameteriv(GL_RENDERBUFFER,'
-        print '                                     GL_RENDERBUFFER_SAMPLES, &depthSamples);'
-        print '        glBindRenderbuffer(GL_RENDERBUFFER, stencilRb);'
-        print '        glGetRenderbufferParameteriv(GL_RENDERBUFFER,'
-        print '                                     GL_RENDERBUFFER_SAMPLES, &stencilSamples);'
-        print '        glBindRenderbuffer(GL_RENDERBUFFER, boundRb);'
-        print
-        print '        if (colorSamples || depthSamples || stencilSamples) {'
-        print '            //glReadPixels doesnt support multisampled buffers so we need'
-        print '            // to blit the fbo to a temporary one'
-        print '            fboCopy = downsampledFramebuffer(boundDrawFbo, drawbuffer,'
-        print '                                             colorRb, depthRb, stencilRb,'
-        print '                                             rbs, &numRbs);'
-        print '        }'
-        print '        glDrawBuffer(drawbuffer);'
-        print '        glReadBuffer(drawbuffer);'
-        print
-        print '        writeDrawBuffers(json, depthRb, stencilRb);'
-        print
-        print '        if (fboCopy) {'
-        print '            glBindFramebuffer(GL_FRAMEBUFFER, boundDrawFbo);'
-        print '            glBindFramebuffer(GL_READ_FRAMEBUFFER, boundReadFbo);'
-        print '            glBindFramebuffer(GL_DRAW_FRAMEBUFFER, boundDrawFbo);'
-        print '            glBindRenderbuffer(GL_RENDERBUFFER_BINDING, boundRb);'
-        print '            glDeleteRenderbuffers(numRbs, rbs);'
-        print '            glDeleteFramebuffers(1, &fboCopy);'
-        print '        }'
-        print '    }'
-        print
-        print '    json.endObject();'
-        print '    json.endMember(); // framebuffer'
-        pass
+    def dump_attachment_parameters(self, target, attachment):
+        print '            {'
+        print '                GLint object_type = GL_NONE;'
+        print '                glGetFramebufferAttachmentParameteriv(%s, %s, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &object_type);' % (target, attachment)
+        print '                if (object_type != GL_NONE) {'
+        print '                    json.beginMember(enumToString(%s));' % attachment
+        print '                    json.beginObject();'
+        self.dump_atoms(glGetFramebufferAttachmentParameter, target, attachment)
+        print '                    json.endObject();'
+        print '                    json.endMember(); // GL_x_ATTACHMENT'
+        print '                }'
+        print '            }'
 
     def dump_atoms(self, getter, *args):
         for function, type, count, name in parameters: