From b0a4a363e547f70063833b7975a97e09cf9e5f20 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jos=C3=A9=20Fonseca?= Date: Tue, 7 Jun 2011 15:50:49 +0100 Subject: [PATCH] Dump framebuffer images with their true size. --- glstate.cpp | 373 +++++++++++++++++++++++++++++++++++++++------------- glstate.py | 14 +- 2 files changed, 290 insertions(+), 97 deletions(-) diff --git a/glstate.cpp b/glstate.cpp index fbe3958..0aca210 100644 --- a/glstate.cpp +++ b/glstate.cpp @@ -459,59 +459,49 @@ getDrawBufferImage(GLenum format) { } +/** + * Dump the image of the currently bound read buffer. + */ static inline void -dumpDrawBufferImage(JSONWriter &json, GLenum format) +dumpReadBufferImage(JSONWriter &json, GLint width, GLint height, GLenum format) { GLint channels = __gl_format_channels(format); - GLint width, height; - - if (!getDrawableBounds(&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); + json.beginObject(); - // 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); + // Tell the GUI this is no ordinary object, but an image + json.writeStringMember("__class__", "image"); - GLubyte *pixels = new GLubyte[width*height*channels]; + json.writeNumberMember("__width__", width); + json.writeNumberMember("__height__", height); + json.writeNumberMember("__depth__", 1); - GLint draw_buffer = GL_NONE; - GLint read_buffer = GL_NONE; - glGetIntegerv(GL_DRAW_BUFFER, &draw_buffer); - glGetIntegerv(GL_READ_BUFFER, &read_buffer); - glReadBuffer(draw_buffer); + // 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); - resetPixelPackState(); + GLubyte *pixels = new GLubyte[width*height*channels]; - glReadPixels(0, 0, width, height, format, GL_UNSIGNED_BYTE, pixels); + resetPixelPackState(); - restorePixelPackState(); - glReadBuffer(read_buffer); + glReadPixels(0, 0, width, height, format, GL_UNSIGNED_BYTE, pixels); - 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 = "< 0 && *height > 0; +} + + +/** + * Dump the specified framebuffer attachment. + * + * In the case of a color attachment, it assumes it is already bound for read. + */ +static void +dumpFramebufferAttachment(JSONWriter &json, GLenum target, GLenum attachment, GLenum format) +{ + GLint width = 0; + GLint height = 0; + + GLint object_type = GL_NONE; + glGetFramebufferAttachmentParameteriv(target, attachment, + GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, + &object_type); + if (object_type == GL_NONE) { + return; + } + + GLint object_name = 0; + glGetFramebufferAttachmentParameteriv(target, attachment, + GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, + &object_name); + if (object_name == 0) { + return; + } + + if (object_type == GL_RENDERBUFFER) { + GLint bound_renderbuffer = 0; + glGetIntegerv(GL_RENDERBUFFER_BINDING, &bound_renderbuffer); + + glBindRenderbuffer(GL_RENDERBUFFER, object_name); + glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &width); + glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &height); + + if (width <= 0 || height <= 0) { + return; + } + + glBindRenderbuffer(GL_RENDERBUFFER, bound_renderbuffer); + + } else if (object_type == GL_TEXTURE) { + GLint texture_level = 0; + glGetFramebufferAttachmentParameteriv(target, attachment, + GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL, + &texture_level); + if (!getTextureLevelSize(object_name, texture_level, &width, &height)) { + return; + } + } else { + std::cerr << "warning: unexpected GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE = " << object_type << "\n"; + return; + } + + json.beginMember(enumToString(attachment)); + dumpReadBufferImage(json, width, height, format); + json.endMember(); +} + + +static void +dumpFramebufferAttachments(JSONWriter &json, GLenum target) +{ + GLint read_framebuffer = 0; + glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &read_framebuffer); + + GLint read_buffer = GL_NONE; + glGetIntegerv(GL_READ_BUFFER, &read_buffer); + + GLint max_draw_buffers = 1; + glGetIntegerv(GL_MAX_DRAW_BUFFERS, &max_draw_buffers); + GLint max_color_attachments = 0; + glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &max_color_attachments); + + for (GLint i = 0; i < max_draw_buffers; ++i) { + GLint draw_buffer = GL_NONE; + glGetIntegerv(GL_DRAW_BUFFER0 + i, &draw_buffer); + if (draw_buffer != GL_NONE) { + glReadBuffer(draw_buffer); + GLint attachment; + if (draw_buffer >= GL_COLOR_ATTACHMENT0 && draw_buffer < GL_COLOR_ATTACHMENT0 + max_color_attachments) { + attachment = draw_buffer; + } else { + std::cerr << "warning: unexpected GL_DRAW_BUFFER" << i << " = " << draw_buffer << "\n"; + attachment = GL_COLOR_ATTACHMENT0; + } + GLint alpha_size = 0; + glGetFramebufferAttachmentParameteriv(target, attachment, + GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE, + &alpha_size); + GLenum format = alpha_size ? GL_RGBA : GL_RGB; + dumpFramebufferAttachment(json, target, attachment, format); + } + } + + glReadBuffer(read_buffer); + + dumpFramebufferAttachment(json, target, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT); + dumpFramebufferAttachment(json, target, GL_STENCIL_ATTACHMENT, GL_STENCIL_INDEX); + + glBindFramebuffer(GL_READ_FRAMEBUFFER, read_framebuffer); +} + + static void dumpFramebuffer(JSONWriter &json) { @@ -657,66 +836,74 @@ dumpFramebuffer(JSONWriter &json) glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundDrawFbo); glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &boundReadFbo); if (!boundDrawFbo) { - GLint depth_bits = 0; - glGetIntegerv(GL_DEPTH_BITS, &depth_bits); - GLint stencil_bits = 0; - glGetIntegerv(GL_STENCIL_BITS, &stencil_bits); - dumpDrawBuffers(json, depth_bits, stencil_bits); + dumpDrawableImages(json); } else { - GLint colorRb, stencilRb, depthRb; - GLint boundRb; + GLint colorRb = 0, stencilRb = 0, depthRb = 0; + GLint draw_buffer0 = GL_NONE; + glGetIntegerv(GL_DRAW_BUFFER0, &draw_buffer0); + bool multisample = false; + + GLint boundRb = 0; glGetIntegerv(GL_RENDERBUFFER_BINDING, &boundRb); - GLint drawbuffer = GL_NONE; - glGetIntegerv(GL_DRAW_BUFFER, &drawbuffer); - - glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, - drawbuffer, - GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, - &colorRb); - glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, - GL_DEPTH_ATTACHMENT, - GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, - &depthRb); - glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, - GL_STENCIL_ATTACHMENT, - GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, - &stencilRb); - - GLint colorSamples, depthSamples, stencilSamples; + + GLint object_type; + glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, draw_buffer0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &object_type); + if (object_type == GL_RENDERBUFFER) { + glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, draw_buffer0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &colorRb); + glBindRenderbuffer(GL_RENDERBUFFER, colorRb); + GLint samples = 0; + glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES, &samples); + if (samples) { + multisample = true; + } + } + + glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &object_type); + if (object_type == GL_RENDERBUFFER) { + glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &depthRb); + glBindRenderbuffer(GL_RENDERBUFFER, depthRb); + GLint samples = 0; + glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES, &samples); + if (samples) { + multisample = true; + } + } + + glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &object_type); + if (object_type == GL_RENDERBUFFER) { + glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &stencilRb); + glBindRenderbuffer(GL_RENDERBUFFER, stencilRb); + GLint samples = 0; + glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES, &samples); + if (samples) { + multisample = true; + } + } + + glBindRenderbuffer(GL_RENDERBUFFER, boundRb); + GLuint rbs[3]; GLint numRbs = 0; GLuint fboCopy = 0; - glBindRenderbuffer(GL_RENDERBUFFER, colorRb); - glGetRenderbufferParameteriv(GL_RENDERBUFFER, - GL_RENDERBUFFER_SAMPLES, &colorSamples); - glBindRenderbuffer(GL_RENDERBUFFER, depthRb); - glGetRenderbufferParameteriv(GL_RENDERBUFFER, - GL_RENDERBUFFER_SAMPLES, &depthSamples); - glBindRenderbuffer(GL_RENDERBUFFER, stencilRb); - glGetRenderbufferParameteriv(GL_RENDERBUFFER, - GL_RENDERBUFFER_SAMPLES, &stencilSamples); - glBindRenderbuffer(GL_RENDERBUFFER, boundRb); - if (colorSamples || depthSamples || stencilSamples) { - //glReadPixels doesnt support multisampled buffers so we need + if (multisample) { + // glReadPixels doesnt support multisampled buffers so we need // to blit the fbo to a temporary one - fboCopy = downsampledFramebuffer(boundDrawFbo, drawbuffer, + fboCopy = downsampledFramebuffer(boundDrawFbo, draw_buffer0, colorRb, depthRb, stencilRb, rbs, &numRbs); } - glDrawBuffer(drawbuffer); - glReadBuffer(drawbuffer); - dumpDrawBuffers(json, depthRb, stencilRb); + dumpFramebufferAttachments(json, GL_DRAW_FRAMEBUFFER); - if (fboCopy) { - glBindFramebuffer(GL_FRAMEBUFFER, boundDrawFbo); - glBindFramebuffer(GL_READ_FRAMEBUFFER, boundReadFbo); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, boundDrawFbo); + if (multisample) { glBindRenderbuffer(GL_RENDERBUFFER_BINDING, boundRb); glDeleteRenderbuffers(numRbs, rbs); glDeleteFramebuffers(1, &fboCopy); } + + glBindFramebuffer(GL_READ_FRAMEBUFFER, boundReadFbo); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, boundDrawFbo); } json.endObject(); diff --git a/glstate.py b/glstate.py index c09e4fc..fb3e090 100644 --- a/glstate.py +++ b/glstate.py @@ -259,6 +259,13 @@ class StateDumper: print '}' print + print 'static void' + print 'dumpFramebufferAttachementParameters(JSONWriter &json, GLenum target, GLenum attachment)' + print '{' + self.dump_attachment_parameters('target', 'attachment') + print '}' + print + print 'void' print 'dumpEnum(JSONWriter &json, GLenum pname)' print '{' @@ -410,11 +417,10 @@ class StateDumper: print ' json.beginObject();' print ' for (GLint i = 0; i < max_color_attachments; ++i) {' print ' GLint color_attachment = GL_COLOR_ATTACHMENT0 + i;' - self.dump_attachment_parameters(target, 'color_attachment') + print ' dumpFramebufferAttachementParameters(json, %s, color_attachment);' % target print ' }' - self.dump_attachment_parameters(target, 'GL_DEPTH_ATTACHMENT') - self.dump_attachment_parameters(target, 'GL_STENCIL_ATTACHMENT') - #self.dump_attachment_parameters(target, 'GL_DEPTH_STENCIL_ATTACHMENT') + 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 ' }' -- 2.43.0