X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=retrace%2Fglstate_images.cpp;h=0fcc9d82d89696e5ff8c350c461fc9240b700c26;hb=b79fe3d2e482c492248d96da992f8fabcd9fe8cd;hp=7b0a42473fdf97cbc8c04ad4910247d078d4b2cf;hpb=6083cfc0885f162b532825b23639f0ec2fe285c2;p=apitrace diff --git a/retrace/glstate_images.cpp b/retrace/glstate_images.cpp index 7b0a424..0fcc9d8 100644 --- a/retrace/glstate_images.cpp +++ b/retrace/glstate_images.cpp @@ -72,6 +72,7 @@ struct ImageDesc GLint width; GLint height; GLint depth; + GLint samples; GLint internalFormat; inline @@ -79,9 +80,19 @@ struct ImageDesc width(0), height(0), depth(0), + samples(0), internalFormat(GL_NONE) {} + inline bool + operator == (const ImageDesc &other) const { + return width == other.width && + height == other.height && + depth == other.depth && + samples == other.samples && + internalFormat == other.internalFormat; + } + inline bool valid(void) const { return width > 0 && height > 0 && depth > 0; @@ -283,35 +294,58 @@ getActiveTextureLevelDesc(Context &context, GLenum target, GLint level, ImageDes } } + glGetTexLevelParameteriv(target, level, GL_TEXTURE_SAMPLES, &desc.samples); + return desc.valid(); } -/** - * OpenGL ES does not support glGetTexImage. Obtain the pixels by attaching the - * texture to a framebuffer. - */ -static inline void -getTexImageOES(GLenum target, GLint level, ImageDesc &desc, GLubyte *pixels) +static GLenum +getTextureBinding(GLenum target) { - memset(pixels, 0x80, desc.height * desc.width * 4); - - GLenum texture_binding = GL_NONE; switch (target) { + case GL_TEXTURE_1D: + return GL_TEXTURE_BINDING_1D; + case GL_TEXTURE_1D_ARRAY: + return GL_TEXTURE_BINDING_1D_ARRAY; case GL_TEXTURE_2D: - texture_binding = GL_TEXTURE_BINDING_2D; - break; + return GL_TEXTURE_BINDING_2D; + case GL_TEXTURE_2D_MULTISAMPLE: + return GL_TEXTURE_BINDING_2D_MULTISAMPLE; + case GL_TEXTURE_2D_ARRAY: + return GL_TEXTURE_BINDING_2D_ARRAY; + case GL_TEXTURE_RECTANGLE: + return GL_TEXTURE_BINDING_RECTANGLE; + case GL_TEXTURE_CUBE_MAP: case GL_TEXTURE_CUBE_MAP_POSITIVE_X: case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - texture_binding = GL_TEXTURE_BINDING_CUBE_MAP; - break; - case GL_TEXTURE_3D_OES: - texture_binding = GL_TEXTURE_BINDING_3D_OES; + return GL_TEXTURE_BINDING_CUBE_MAP; + case GL_TEXTURE_CUBE_MAP_ARRAY: + return GL_TEXTURE_BINDING_CUBE_MAP_ARRAY; + case GL_TEXTURE_3D: + return GL_TEXTURE_BINDING_3D; default: + assert(false); + return GL_NONE; + } +} + + +/** + * OpenGL ES does not support glGetTexImage. Obtain the pixels by attaching the + * texture to a framebuffer. + */ +static inline void +getTexImageOES(GLenum target, GLint level, ImageDesc &desc, GLubyte *pixels) +{ + memset(pixels, 0x80, desc.height * desc.width * 4); + + GLenum texture_binding = getTextureBinding(target); + if (texture_binding == GL_NONE) { return; } @@ -378,6 +412,78 @@ isDepthFormat(GLenum internalFormat) } +static inline GLboolean +isIntegerFormat(GLenum internalFormat) +{ + switch (internalFormat) { + + case GL_RG_INTEGER: + case GL_RED_INTEGER: + case GL_GREEN_INTEGER: + case GL_BLUE_INTEGER: + case GL_ALPHA_INTEGER: + case GL_RGB_INTEGER: + case GL_RGBA_INTEGER: + case GL_BGR_INTEGER: + case GL_BGRA_INTEGER: + case GL_LUMINANCE_INTEGER_EXT: + case GL_LUMINANCE_ALPHA_INTEGER_EXT: + + case GL_R8I: + case GL_R8UI: + case GL_R16I: + case GL_R16UI: + case GL_R32I: + case GL_R32UI: + case GL_RG8I: + case GL_RG8UI: + case GL_RG16I: + case GL_RG16UI: + case GL_RG32I: + case GL_RG32UI: + case GL_RGB8I: + case GL_RGB8UI: + case GL_RGB16I: + case GL_RGB16UI: + case GL_RGB32I: + case GL_RGB32UI: + case GL_RGBA8I: + case GL_RGBA8UI: + case GL_RGBA16I: + case GL_RGBA16UI: + case GL_RGBA32I: + case GL_RGBA32UI: + case GL_RGB10_A2UI: + case GL_LUMINANCE8I_EXT: + case GL_LUMINANCE8UI_EXT: + case GL_LUMINANCE16I_EXT: + case GL_LUMINANCE16UI_EXT: + case GL_LUMINANCE32I_EXT: + case GL_LUMINANCE32UI_EXT: + case GL_ALPHA8I_EXT: + case GL_ALPHA8UI_EXT: + case GL_ALPHA16I_EXT: + case GL_ALPHA16UI_EXT: + case GL_ALPHA32I_EXT: + case GL_ALPHA32UI_EXT: + case GL_LUMINANCE_ALPHA8I_EXT: + case GL_LUMINANCE_ALPHA8UI_EXT: + case GL_LUMINANCE_ALPHA16I_EXT: + case GL_LUMINANCE_ALPHA16UI_EXT: + case GL_LUMINANCE_ALPHA32I_EXT: + case GL_LUMINANCE_ALPHA32UI_EXT: + case GL_INTENSITY8I_EXT: + case GL_INTENSITY8UI_EXT: + case GL_INTENSITY16I_EXT: + case GL_INTENSITY16UI_EXT: + case GL_INTENSITY32I_EXT: + case GL_INTENSITY32UI_EXT: + return GL_TRUE; + } + return GL_FALSE; +} + + static inline void dumpActiveTextureLevel(JSONWriter &json, Context &context, GLenum target, GLint level) { @@ -397,11 +503,15 @@ dumpActiveTextureLevel(JSONWriter &json, Context &context, GLenum target, GLint GLuint channels; GLenum format; if (!context.ES && isDepthFormat(desc.internalFormat)) { - format = GL_DEPTH_COMPONENT; - channels = 1; + format = GL_DEPTH_COMPONENT; + channels = 1; } else { - format = GL_RGBA; - channels = 4; + if (isIntegerFormat(desc.internalFormat)) { + format = GL_RGBA_INTEGER; + } else { + format = GL_RGBA; + } + channels = 4; } image::Image *image = new image::Image(desc.width, desc.height*desc.depth, channels, true); @@ -497,26 +607,24 @@ getDrawableBounds(GLint *width, GLint *height) { #if defined(__linux__) if (dlsym(RTLD_DEFAULT, "eglGetCurrentContext")) { EGLContext currentContext = eglGetCurrentContext(); - if (currentContext == EGL_NO_CONTEXT) { - return false; - } + if (currentContext != EGL_NO_CONTEXT) { + EGLSurface currentSurface = eglGetCurrentSurface(EGL_DRAW); + if (currentSurface == EGL_NO_SURFACE) { + return false; + } - EGLSurface currentSurface = eglGetCurrentSurface(EGL_DRAW); - if (currentSurface == EGL_NO_SURFACE) { - return false; - } + EGLDisplay currentDisplay = eglGetCurrentDisplay(); + if (currentDisplay == EGL_NO_DISPLAY) { + return false; + } - EGLDisplay currentDisplay = eglGetCurrentDisplay(); - if (currentDisplay == EGL_NO_DISPLAY) { - return false; - } + if (!eglQuerySurface(currentDisplay, currentSurface, EGL_WIDTH, width) || + !eglQuerySurface(currentDisplay, currentSurface, EGL_HEIGHT, height)) { + return false; + } - if (!eglQuerySurface(currentDisplay, currentSurface, EGL_WIDTH, width) || - !eglQuerySurface(currentDisplay, currentSurface, EGL_HEIGHT, height)) { - return false; + return true; } - - return true; } #endif @@ -597,57 +705,55 @@ getDrawableBounds(GLint *width, GLint *height) { } -static const GLenum texture_bindings[][2] = { - {GL_TEXTURE_1D, GL_TEXTURE_BINDING_1D}, - {GL_TEXTURE_2D, GL_TEXTURE_BINDING_2D}, - {GL_TEXTURE_3D, GL_TEXTURE_BINDING_3D}, - {GL_TEXTURE_RECTANGLE, GL_TEXTURE_BINDING_RECTANGLE}, - {GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BINDING_CUBE_MAP} +struct TextureTargetBinding +{ + GLenum target; + GLenum binding; }; -static bool -bindTexture(GLint texture, GLenum &target, GLint &bound_texture) -{ +static const GLenum +textureTargets[] = { + GL_TEXTURE_1D, + GL_TEXTURE_2D, + GL_TEXTURE_RECTANGLE, + GL_TEXTURE_CUBE_MAP, + GL_TEXTURE_3D, + GL_TEXTURE_2D_MULTISAMPLE, + GL_TEXTURE_1D_ARRAY, + GL_TEXTURE_2D_ARRAY, + GL_TEXTURE_CUBE_MAP_ARRAY, +}; - for (unsigned i = 0; i < sizeof(texture_bindings)/sizeof(texture_bindings[0]); ++i) { - target = texture_bindings[i][0]; - GLenum binding = texture_bindings[i][1]; +static GLenum +getTextureTarget(GLint texture) +{ + if (!glIsTexture(texture)) { + return GL_NONE; + } + + for (unsigned i = 0; i < sizeof(textureTargets)/sizeof(textureTargets[0]); ++i) { + GLenum target = textureTargets[i]; + GLenum binding = getTextureBinding(target); while (glGetError() != GL_NO_ERROR) ; + GLint bound_texture = 0; glGetIntegerv(binding, &bound_texture); glBindTexture(target, texture); - if (glGetError() == GL_NO_ERROR) { - return true; - } + bool succeeded = glGetError() == GL_NO_ERROR; glBindTexture(target, bound_texture); - } - - target = GL_NONE; - - return false; -} - -static bool -getTextureLevelDesc(Context &context, GLint texture, GLint level, ImageDesc &desc) -{ - GLenum target; - GLint bound_texture = 0; - if (!bindTexture(texture, target, bound_texture)) { - return false; + if (succeeded) { + return target; + } } - getActiveTextureLevelDesc(context, target, level, desc); - - glBindTexture(target, bound_texture); - - return desc.valid(); + return GL_NONE; } @@ -658,6 +764,8 @@ getBoundRenderbufferDesc(Context &context, ImageDesc &desc) glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &desc.height); desc.depth = 1; + glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES, &desc.samples); + glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_INTERNAL_FORMAT, &desc.internalFormat); return desc.valid(); @@ -701,11 +809,32 @@ getFramebufferAttachmentDesc(Context &context, GLenum target, GLenum attachment, if (object_type == GL_RENDERBUFFER) { return getRenderbufferDesc(context, object_name, desc); } else if (object_type == GL_TEXTURE) { + GLint texture_face = 0; + glGetFramebufferAttachmentParameteriv(target, attachment, + GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE, + &texture_face); + GLint texture_level = 0; glGetFramebufferAttachmentParameteriv(target, attachment, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL, &texture_level); - return getTextureLevelDesc(context, object_name, texture_level, desc); + + GLint bound_texture = 0; + if (texture_face != 0) { + glGetIntegerv(GL_TEXTURE_BINDING_CUBE_MAP, &bound_texture); + glBindTexture(GL_TEXTURE_CUBE_MAP, object_name); + getActiveTextureLevelDesc(context, texture_face, texture_level, desc); + glBindTexture(GL_TEXTURE_CUBE_MAP, bound_texture); + } else { + GLenum texture_target = getTextureTarget(object_name); + GLenum texture_binding = getTextureBinding(texture_target); + glGetIntegerv(texture_binding, &bound_texture); + glBindTexture(texture_target, object_name); + getActiveTextureLevelDesc(context, texture_target, texture_level, desc); + glBindTexture(texture_target, bound_texture); + } + + return desc.valid(); } else { std::cerr << "warning: unexpected GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE = " << object_type << "\n"; return false; @@ -745,13 +874,22 @@ getDrawBufferImage() { if (draw_buffer == GL_NONE) { return NULL; } + } else { + // GL_COLOR_ATTACHMENT0 is implied + draw_buffer = GL_COLOR_ATTACHMENT0; } if (!getFramebufferAttachmentDesc(context, framebuffer_target, draw_buffer, desc)) { return NULL; } } else { - if (!context.ES) { + if (context.ES) { + // XXX: Draw buffer is always FRONT for single buffer context, BACK + // for double buffered contexts. There is no way to know which (as + // GL_DOUBLEBUFFER state is also unavailable), so always assume + // double-buffering. + draw_buffer = GL_BACK; + } else { glGetIntegerv(GL_DRAW_BUFFER, &draw_buffer); if (draw_buffer == GL_NONE) { return NULL; @@ -843,6 +981,8 @@ dumpReadBufferImage(JSONWriter &json, GLint width, GLint height, GLenum format, image::Image *image = new image::Image(width, height, channels, true); + while (glGetError() != GL_NO_ERROR) {} + // TODO: reset imaging state too context.resetPixelPackState(); @@ -850,7 +990,16 @@ dumpReadBufferImage(JSONWriter &json, GLint width, GLint height, GLenum format, context.restorePixelPackState(); - json.writeImage(image, formatToString(internalFormat)); + GLenum error = glGetError(); + if (error != GL_NO_ERROR) { + do { + std::cerr << "warning: " << enumToString(error) << " while reading framebuffer\n"; + error = glGetError(); + } while(error != GL_NO_ERROR); + json.writeNull(); + } else { + json.writeImage(image, formatToString(internalFormat)); + } delete image; } @@ -859,7 +1008,9 @@ dumpReadBufferImage(JSONWriter &json, GLint width, GLint height, GLenum format, static inline GLuint downsampledFramebuffer(Context &context, GLuint oldFbo, GLint drawbuffer, - GLint colorRb, GLint depthRb, GLint stencilRb, + const ImageDesc &colorDesc, + const ImageDesc &depthDesc, + const ImageDesc &stencilDesc, GLuint *rbs, GLint *numRbs) { GLuint fbo; @@ -872,13 +1023,9 @@ downsampledFramebuffer(Context &context, { // color buffer - ImageDesc desc; - glBindRenderbuffer(GL_RENDERBUFFER, colorRb); - getBoundRenderbufferDesc(context, desc); - glGenRenderbuffers(1, &rbs[*numRbs]); glBindRenderbuffer(GL_RENDERBUFFER, rbs[*numRbs]); - glRenderbufferStorage(GL_RENDERBUFFER, desc.internalFormat, desc.width, desc.height); + glRenderbufferStorage(GL_RENDERBUFFER, colorDesc.internalFormat, colorDesc.width, colorDesc.height); glFramebufferRenderbuffer(GL_FRAMEBUFFER, drawbuffer, GL_RENDERBUFFER, rbs[*numRbs]); @@ -886,38 +1033,31 @@ downsampledFramebuffer(Context &context, glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo); glDrawBuffer(drawbuffer); glReadBuffer(drawbuffer); - glBlitFramebuffer(0, 0, desc.width, desc.height, 0, 0, desc.width, desc.height, + glBlitFramebuffer(0, 0, colorDesc.width, colorDesc.height, 0, 0, colorDesc.width, colorDesc.height, GL_COLOR_BUFFER_BIT, GL_NEAREST); glBindFramebuffer(GL_FRAMEBUFFER, fbo); ++*numRbs; } - if (stencilRb == depthRb && stencilRb) { + if (stencilDesc == depthDesc && + depthDesc.valid()) { //combined depth and stencil buffer - ImageDesc desc; - glBindRenderbuffer(GL_RENDERBUFFER, depthRb); - getBoundRenderbufferDesc(context, desc); - glGenRenderbuffers(1, &rbs[*numRbs]); glBindRenderbuffer(GL_RENDERBUFFER, rbs[*numRbs]); - glRenderbufferStorage(GL_RENDERBUFFER, desc.internalFormat, desc.width, desc.height); + glRenderbufferStorage(GL_RENDERBUFFER, depthDesc.internalFormat, depthDesc.width, depthDesc.height); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbs[*numRbs]); glBindFramebuffer(GL_READ_FRAMEBUFFER, oldFbo); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo); - glBlitFramebuffer(0, 0, desc.width, desc.height, 0, 0, desc.width, desc.height, + glBlitFramebuffer(0, 0, depthDesc.width, depthDesc.height, 0, 0, depthDesc.width, depthDesc.height, GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST); glBindFramebuffer(GL_FRAMEBUFFER, fbo); ++*numRbs; } else { - if (depthRb) { - ImageDesc desc; - glBindRenderbuffer(GL_RENDERBUFFER, depthRb); - getBoundRenderbufferDesc(context, desc); - + if (depthDesc.valid()) { glGenRenderbuffers(1, &rbs[*numRbs]); glBindRenderbuffer(GL_RENDERBUFFER, rbs[*numRbs]); - glRenderbufferStorage(GL_RENDERBUFFER, desc.internalFormat, desc.width, desc.height); + glRenderbufferStorage(GL_RENDERBUFFER, depthDesc.internalFormat, depthDesc.width, depthDesc.height); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbs[*numRbs]); @@ -925,18 +1065,14 @@ downsampledFramebuffer(Context &context, glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo); glDrawBuffer(GL_DEPTH_ATTACHMENT); glReadBuffer(GL_DEPTH_ATTACHMENT); - glBlitFramebuffer(0, 0, desc.width, desc.height, 0, 0, desc.width, desc.height, + glBlitFramebuffer(0, 0, depthDesc.width, depthDesc.height, 0, 0, depthDesc.width, depthDesc.height, GL_DEPTH_BUFFER_BIT, GL_NEAREST); ++*numRbs; } - if (stencilRb) { - ImageDesc desc; - glBindRenderbuffer(GL_RENDERBUFFER, stencilRb); - getBoundRenderbufferDesc(context, desc); - + if (stencilDesc.valid()) { glGenRenderbuffers(1, &rbs[*numRbs]); glBindRenderbuffer(GL_RENDERBUFFER, rbs[*numRbs]); - glRenderbufferStorage(GL_RENDERBUFFER, desc.internalFormat, desc.width, desc.height); + glRenderbufferStorage(GL_RENDERBUFFER, stencilDesc.internalFormat, stencilDesc.width, stencilDesc.height); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbs[*numRbs]); @@ -944,7 +1080,7 @@ downsampledFramebuffer(Context &context, glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo); glDrawBuffer(GL_STENCIL_ATTACHMENT); glReadBuffer(GL_STENCIL_ATTACHMENT); - glBlitFramebuffer(0, 0, desc.width, desc.height, 0, 0, desc.width, desc.height, + glBlitFramebuffer(0, 0, stencilDesc.width, stencilDesc.height, 0, 0, stencilDesc.width, stencilDesc.height, GL_STENCIL_BUFFER_BIT, GL_NEAREST); ++*numRbs; } @@ -968,16 +1104,21 @@ dumpDrawableImages(JSONWriter &json, Context &context) GLint draw_buffer = GL_NONE; if (context.ES) { + // XXX: Draw buffer is always FRONT for single buffer context, BACK for + // double buffered contexts. There is no way to know which (as + // GL_DOUBLEBUFFER state is also unavailable), so always assume + // double-buffering. draw_buffer = GL_BACK; } else { glGetIntegerv(GL_DRAW_BUFFER, &draw_buffer); - glReadBuffer(draw_buffer); } if (draw_buffer != GL_NONE) { + // Read from current draw buffer GLint read_buffer = GL_NONE; if (!context.ES) { glGetIntegerv(GL_READ_BUFFER, &read_buffer); + glReadBuffer(draw_buffer); } GLint alpha_bits = 0; @@ -990,6 +1131,7 @@ dumpDrawableImages(JSONWriter &json, Context &context) dumpReadBufferImage(json, width, height, format); json.endMember(); + // Restore original read buffer if (!context.ES) { glReadBuffer(read_buffer); } @@ -1028,6 +1170,8 @@ dumpFramebufferAttachment(JSONWriter &json, Context &context, GLenum target, GLe return; } + assert(desc.samples == 0); + json.beginMember(enumToString(attachment)); dumpReadBufferImage(json, desc.width, desc.height, format, desc.internalFormat); json.endMember(); @@ -1094,7 +1238,6 @@ dumpFramebuffer(JSONWriter &json, Context &context) } else if (context.ES) { dumpFramebufferAttachments(json, context, GL_FRAMEBUFFER); } else { - GLint colorRb = 0, stencilRb = 0, depthRb = 0; GLint draw_buffer0 = GL_NONE; glGetIntegerv(GL_DRAW_BUFFER0, &draw_buffer0); bool multisample = false; @@ -1102,42 +1245,27 @@ dumpFramebuffer(JSONWriter &json, Context &context) GLint boundRb = 0; glGetIntegerv(GL_RENDERBUFFER_BINDING, &boundRb); - 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) { + ImageDesc colorDesc; + if (getFramebufferAttachmentDesc(context, GL_DRAW_FRAMEBUFFER, draw_buffer0, colorDesc)) { + if (colorDesc.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) { + ImageDesc depthDesc; + if (getFramebufferAttachmentDesc(context, GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthDesc)) { + if (depthDesc.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) { + ImageDesc stencilDesc; + if (getFramebufferAttachmentDesc(context, GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, stencilDesc)) { + if (stencilDesc.samples) { multisample = true; } } - glBindRenderbuffer(GL_RENDERBUFFER, boundRb); - GLuint rbs[3]; GLint numRbs = 0; GLuint fboCopy = 0; @@ -1147,14 +1275,16 @@ dumpFramebuffer(JSONWriter &json, Context &context) // to blit the fbo to a temporary one fboCopy = downsampledFramebuffer(context, boundDrawFbo, draw_buffer0, - colorRb, depthRb, stencilRb, + colorDesc, depthDesc, stencilDesc, rbs, &numRbs); + } else { + glBindFramebuffer(GL_READ_FRAMEBUFFER, boundDrawFbo); } - dumpFramebufferAttachments(json, context, GL_DRAW_FRAMEBUFFER); + dumpFramebufferAttachments(json, context, GL_READ_FRAMEBUFFER); if (multisample) { - glBindRenderbuffer(GL_RENDERBUFFER_BINDING, boundRb); + glBindRenderbuffer(GL_RENDERBUFFER, boundRb); glDeleteRenderbuffers(numRbs, rbs); glDeleteFramebuffers(1, &fboCopy); }