GLint width;
GLint height;
GLint depth;
+ GLint samples;
GLint internalFormat;
inline
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;
}
}
+ 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;
}
}
-static inline GLboolean
-isDepthFormat(GLenum internalFormat)
+struct InternalFormatDesc
{
- switch (internalFormat) {
- case GL_DEPTH_COMPONENT:
- case GL_DEPTH_COMPONENT16:
- case GL_DEPTH_COMPONENT24:
- case GL_DEPTH_COMPONENT32:
- case GL_DEPTH_COMPONENT32F:
- case GL_DEPTH_COMPONENT32F_NV:
- case GL_DEPTH_STENCIL:
- case GL_DEPTH24_STENCIL8:
- case GL_DEPTH32F_STENCIL8:
- case GL_DEPTH32F_STENCIL8_NV:
- return GL_TRUE;
- }
- return GL_FALSE;
+ GLenum internalFormat;
+ GLenum format;
+};
+
+
+static const InternalFormatDesc
+internalFormatDescs[] = {
+
+ {1, GL_RED},
+ {2, GL_RG},
+ {3, GL_RGB},
+ {4, GL_RGBA},
+
+ {GL_RED, GL_RED},
+ {GL_GREEN, GL_GREEN},
+ {GL_BLUE, GL_BLUE},
+ {GL_ALPHA, GL_ALPHA},
+ {GL_RG, GL_RG},
+ {GL_RGB, GL_RGB},
+ {GL_BGR, GL_RGB},
+ {GL_RGBA, GL_RGBA},
+ {GL_BGRA, GL_RGBA},
+ {GL_LUMINANCE, GL_LUMINANCE},
+ {GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA},
+ {GL_INTENSITY, GL_INTENSITY},
+
+ {GL_RG8, GL_RG},
+ {GL_RG16, GL_RG},
+ {GL_RGB8, GL_RGB},
+ {GL_RGB16, GL_RGB},
+ {GL_RGBA8, GL_RGBA},
+ {GL_RGBA16, GL_RGBA},
+ {GL_RGB10_A2, GL_RGBA},
+ {GL_LUMINANCE8, GL_LUMINANCE},
+ {GL_LUMINANCE16, GL_LUMINANCE},
+ {GL_ALPHA8, GL_ALPHA},
+ {GL_ALPHA16, GL_ALPHA},
+ {GL_LUMINANCE8_ALPHA8, GL_LUMINANCE_ALPHA},
+ {GL_LUMINANCE16_ALPHA16, GL_LUMINANCE_ALPHA},
+ {GL_INTENSITY8, GL_INTENSITY},
+ {GL_INTENSITY16, GL_INTENSITY},
+
+ {GL_RED_INTEGER, GL_RED_INTEGER},
+ {GL_GREEN_INTEGER, GL_GREEN_INTEGER},
+ {GL_BLUE_INTEGER, GL_BLUE_INTEGER},
+ {GL_ALPHA_INTEGER, GL_ALPHA_INTEGER},
+ {GL_RG_INTEGER, GL_RG_INTEGER},
+ {GL_RGB_INTEGER, GL_RGB_INTEGER},
+ {GL_BGR_INTEGER, GL_RGB_INTEGER},
+ {GL_RGBA_INTEGER, GL_RGBA_INTEGER},
+ {GL_BGRA_INTEGER, GL_RGBA_INTEGER},
+ {GL_LUMINANCE_INTEGER_EXT, GL_LUMINANCE_INTEGER_EXT},
+ {GL_LUMINANCE_ALPHA_INTEGER_EXT, GL_LUMINANCE_ALPHA_INTEGER_EXT},
+
+ {GL_R8I, GL_RED_INTEGER},
+ {GL_R8UI, GL_RED_INTEGER},
+ {GL_R16I, GL_RED_INTEGER},
+ {GL_R16UI, GL_RED_INTEGER},
+ {GL_R32I, GL_RED_INTEGER},
+ {GL_R32UI, GL_RED_INTEGER},
+ {GL_RG8I, GL_RG_INTEGER},
+ {GL_RG8UI, GL_RG_INTEGER},
+ {GL_RG16I, GL_RG_INTEGER},
+ {GL_RG16UI, GL_RG_INTEGER},
+ {GL_RG32I, GL_RG_INTEGER},
+ {GL_RG32UI, GL_RG_INTEGER},
+ {GL_RGB8I, GL_RGB_INTEGER},
+ {GL_RGB8UI, GL_RGB_INTEGER},
+ {GL_RGB16I, GL_RGB_INTEGER},
+ {GL_RGB16UI, GL_RGB_INTEGER},
+ {GL_RGB32I, GL_RGB_INTEGER},
+ {GL_RGB32UI, GL_RGB_INTEGER},
+ {GL_RGBA8I, GL_RGBA_INTEGER},
+ {GL_RGBA8UI, GL_RGBA_INTEGER},
+ {GL_RGBA16I, GL_RGBA_INTEGER},
+ {GL_RGBA16UI, GL_RGBA_INTEGER},
+ {GL_RGBA32I, GL_RGBA_INTEGER},
+ {GL_RGBA32UI, GL_RGBA_INTEGER},
+ {GL_RGB10_A2UI, GL_RGBA_INTEGER},
+ {GL_LUMINANCE8I_EXT, GL_LUMINANCE_INTEGER_EXT},
+ {GL_LUMINANCE8UI_EXT, GL_LUMINANCE_INTEGER_EXT},
+ {GL_LUMINANCE16I_EXT, GL_LUMINANCE_INTEGER_EXT},
+ {GL_LUMINANCE16UI_EXT, GL_LUMINANCE_INTEGER_EXT},
+ {GL_LUMINANCE32I_EXT, GL_LUMINANCE_INTEGER_EXT},
+ {GL_LUMINANCE32UI_EXT, GL_LUMINANCE_INTEGER_EXT},
+ {GL_ALPHA8I_EXT, GL_ALPHA_INTEGER_EXT},
+ {GL_ALPHA8UI_EXT, GL_ALPHA_INTEGER_EXT},
+ {GL_ALPHA16I_EXT, GL_ALPHA_INTEGER_EXT},
+ {GL_ALPHA16UI_EXT, GL_ALPHA_INTEGER_EXT},
+ {GL_ALPHA32I_EXT, GL_ALPHA_INTEGER_EXT},
+ {GL_ALPHA32UI_EXT, GL_ALPHA_INTEGER_EXT},
+ {GL_LUMINANCE_ALPHA8I_EXT, GL_LUMINANCE_ALPHA_INTEGER_EXT},
+ {GL_LUMINANCE_ALPHA8UI_EXT, GL_LUMINANCE_ALPHA_INTEGER_EXT},
+ {GL_LUMINANCE_ALPHA16I_EXT, GL_LUMINANCE_ALPHA_INTEGER_EXT},
+ {GL_LUMINANCE_ALPHA16UI_EXT, GL_LUMINANCE_ALPHA_INTEGER_EXT},
+ {GL_LUMINANCE_ALPHA32I_EXT, GL_LUMINANCE_ALPHA_INTEGER_EXT},
+ {GL_LUMINANCE_ALPHA32UI_EXT, GL_LUMINANCE_ALPHA_INTEGER_EXT},
+ {GL_INTENSITY8I_EXT, GL_RED_INTEGER},
+ {GL_INTENSITY8UI_EXT, GL_RED_INTEGER},
+ {GL_INTENSITY16I_EXT, GL_RED_INTEGER},
+ {GL_INTENSITY16UI_EXT, GL_RED_INTEGER},
+ {GL_INTENSITY32I_EXT, GL_RED_INTEGER},
+ {GL_INTENSITY32UI_EXT, GL_RED_INTEGER},
+
+ {GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT},
+ {GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT},
+ {GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT},
+ {GL_DEPTH_COMPONENT32, GL_DEPTH_COMPONENT},
+ {GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT},
+ {GL_DEPTH_COMPONENT32F_NV, GL_DEPTH_COMPONENT},
+ {GL_DEPTH_STENCIL, GL_DEPTH_COMPONENT},
+ {GL_DEPTH24_STENCIL8, GL_DEPTH_COMPONENT},
+ {GL_DEPTH32F_STENCIL8, GL_DEPTH_COMPONENT},
+ {GL_DEPTH32F_STENCIL8_NV, GL_DEPTH_COMPONENT},
+};
+
+
+static GLenum
+getFormat(GLenum internalFormat)
+{
+ for (unsigned i = 0; i < sizeof internalFormatDescs / sizeof internalFormatDescs[0]; ++i) {
+ if (internalFormatDescs[i].internalFormat == internalFormat) {
+ return internalFormatDescs[i].format;
+ }
+ }
+ return GL_RGBA;
}
json.beginMember(label);
- GLuint channels;
- GLenum format;
- if (!context.ES && isDepthFormat(desc.internalFormat)) {
- format = GL_DEPTH_COMPONENT;
- channels = 1;
- } else {
- format = GL_RGBA;
- channels = 4;
+ GLenum format = getFormat(desc.internalFormat);;
+ if (context.ES && format == GL_DEPTH_COMPONENT) {
+ format = GL_RED;
}
+ GLuint channels = _gl_format_channels(format);;
image::Image *image = new image::Image(desc.width, desc.height*desc.depth, channels, true);
#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
}
-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 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,
};
-static bool
-bindTexture(GLint texture, GLenum &target, GLint &bound_texture)
+static GLenum
+getTextureTarget(GLint texture)
{
+ if (!glIsTexture(texture)) {
+ return GL_NONE;
+ }
- for (unsigned i = 0; i < sizeof(texture_bindings)/sizeof(texture_bindings[0]); ++i) {
- target = texture_bindings[i][0];
-
- GLenum binding = texture_bindings[i][1];
+ 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;
}
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();
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;
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;
image::Image *image = new image::Image(width, height, channels, true);
+ while (glGetError() != GL_NO_ERROR) {}
+
// TODO: reset imaging state too
context.resetPixelPackState();
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;
}
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;
{
// 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]);
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]);
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]);
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;
}
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;
dumpReadBufferImage(json, width, height, format);
json.endMember();
+ // Restore original read buffer
if (!context.ES) {
glReadBuffer(read_buffer);
}
return;
}
+ assert(desc.samples == 0);
+
json.beginMember(enumToString(attachment));
dumpReadBufferImage(json, desc.width, desc.height, format, desc.internalFormat);
json.endMember();
} 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;
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;
// 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);
}