#include "glstate_internal.hpp"
+#ifdef __linux__
+#include <dlfcn.h>
+#endif
+
#ifdef __APPLE__
#include <Carbon/Carbon.h>
namespace glstate {
+struct ImageDesc
+{
+ GLint width;
+ GLint height;
+ GLint depth;
+ GLint internalFormat;
+
+ inline
+ ImageDesc() :
+ width(0),
+ height(0),
+ depth(0),
+ internalFormat(GL_NONE)
+ {}
+
+ inline bool
+ valid(void) const {
+ return width > 0 && height > 0 && depth > 0;
+ }
+};
+
+
+/**
+ * OpenGL ES does not support glGetTexLevelParameteriv, but it is possible to
+ * probe whether a texture has a given size by crafting a dummy glTexSubImage()
+ * call.
+ */
+static bool
+probeTextureLevelSizeOES(GLenum target, GLint level, const GLint size[3]) {
+ while (glGetError() != GL_NO_ERROR)
+ ;
+
+ GLenum internalFormat = GL_RGBA;
+ GLenum type = GL_UNSIGNED_BYTE;
+ GLint dummy = 0;
+
+ switch (target) {
+ case GL_TEXTURE_2D:
+ 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:
+ glTexSubImage2D(target, level, size[0], size[1], 0, 0, internalFormat, type, &dummy);
+ break;
+ case GL_TEXTURE_3D_OES:
+ glTexSubImage3DOES(target, level, size[0], size[1], size[2], 0, 0, 0, internalFormat, type, &dummy);
+ default:
+ assert(0);
+ return false;
+ }
+
+ GLenum error = glGetError();
+
+ if (0) {
+ std::cerr << "(" << size[0] << ", " << size[1] << ", " << size[2] << ") = " << enumToString(error) << "\n";
+ }
+
+ if (error == GL_NO_ERROR) {
+ return true;
+ }
+
+ while (glGetError() != GL_NO_ERROR)
+ ;
+
+ return false;
+}
+
+
+/**
+ * Bisect the texture size along an axis.
+ *
+ * It is assumed that the texture exists.
+ */
+static GLint
+bisectTextureLevelSizeOES(GLenum target, GLint level, GLint axis, GLint max) {
+ GLint size[3] = {0, 0, 0};
+
+ assert(axis < 3);
+ assert(max >= 0);
+
+ GLint min = 0;
+ while (true) {
+ GLint test = (min + max) / 2;
+ if (test == min) {
+ return min;
+ }
+
+ size[axis] = test;
+
+ if (probeTextureLevelSizeOES(target, level, size)) {
+ min = test;
+ } else {
+ max = test;
+ }
+ }
+}
+
+
+/**
+ * Special path to obtain texture size on OpenGL ES, that does not rely on
+ * glGetTexLevelParameteriv
+ */
+static bool
+getActiveTextureLevelDescOES(Context &context, GLenum target, GLint level, ImageDesc &desc)
+{
+ if (target == GL_TEXTURE_1D) {
+ // OpenGL ES does not support 1D textures
+ return false;
+ }
+
+ const GLint size[3] = {1, 1, 1};
+ if (!probeTextureLevelSizeOES(target, level, size)) {
+ return false;
+ }
+
+ // XXX: mere guess
+ desc.internalFormat = GL_RGBA;
+
+ GLint maxSize = 0;
+ switch (target) {
+ case GL_TEXTURE_2D:
+ glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxSize);
+ desc.width = bisectTextureLevelSizeOES(target, level, 0, maxSize);
+ desc.height = bisectTextureLevelSizeOES(target, level, 1, maxSize);
+ desc.depth = 1;
+ break;
+ 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:
+ glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &maxSize);
+ desc.width = bisectTextureLevelSizeOES(target, level, 0, maxSize);
+ desc.height = desc.width;
+ desc.depth = 1;
+ break;
+ case GL_TEXTURE_3D_OES:
+ glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_OES, &maxSize);
+ desc.width = bisectTextureLevelSizeOES(target, level, 0, maxSize);
+ desc.width = bisectTextureLevelSizeOES(target, level, 1, maxSize);
+ desc.depth = bisectTextureLevelSizeOES(target, level, 2, maxSize);
+ break;
+ default:
+ return false;
+ }
+
+ if (0) {
+ std::cerr
+ << enumToString(target) << " "
+ << level << " "
+ << desc.width << "x" << desc.height << "x" << desc.depth
+ << "\n";
+ }
+
+ return desc.valid();
+}
+
+
+static inline bool
+getActiveTextureLevelDesc(Context &context, GLenum target, GLint level, ImageDesc &desc)
+{
+ if (context.ES) {
+ return getActiveTextureLevelDescOES(context, target, level, desc);
+ }
+
+ glGetTexLevelParameteriv(target, level, GL_TEXTURE_INTERNAL_FORMAT, &desc.internalFormat);
+
+ desc.width = 0;
+ glGetTexLevelParameteriv(target, level, GL_TEXTURE_WIDTH, &desc.width);
+
+ if (target == GL_TEXTURE_1D) {
+ desc.height = 1;
+ desc.depth = 1;
+ } else {
+ desc.height = 0;
+ glGetTexLevelParameteriv(target, level, GL_TEXTURE_HEIGHT, &desc.height);
+ if (target != GL_TEXTURE_3D) {
+ desc.depth = 1;
+ } else {
+ desc.depth = 0;
+ glGetTexLevelParameteriv(target, level, GL_TEXTURE_DEPTH, &desc.depth);
+ }
+ }
+
+ return desc.valid();
+}
+
+
+/**
+ * OpenGL ES does not support glGetTexImage. Obtain the pixels by attaching the
+ * texture to a framebuffer.
+ */
static inline void
-dumpTextureImage(JSONWriter &json, Context &context, GLenum target, GLint level)
+getTexImageOES(GLenum target, GLint level, ImageDesc &desc, GLubyte *pixels)
{
- GLint width, height = 1, depth = 1;
- GLint format;
+ memset(pixels, 0x80, desc.height * desc.width * 4);
+
+ GLenum texture_binding = GL_NONE;
+ switch (target) {
+ case GL_TEXTURE_2D:
+ texture_binding = GL_TEXTURE_BINDING_2D;
+ break;
+ 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;
+ default:
+ return;
+ }
- glGetTexLevelParameteriv(target, level, GL_TEXTURE_INTERNAL_FORMAT, &format);
+ GLint texture = 0;
+ glGetIntegerv(texture_binding, &texture);
+ if (!texture) {
+ return;
+ }
- width = 0;
- glGetTexLevelParameteriv(target, level, GL_TEXTURE_WIDTH, &width);
+ GLint prev_fbo = 0;
+ GLuint fbo = 0;
+ glGetIntegerv(GL_FRAMEBUFFER_BINDING, &prev_fbo);
+ glGenFramebuffers(1, &fbo);
+ glBindFramebuffer(GL_FRAMEBUFFER, fbo);
- 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);
+ GLenum status;
+
+ switch (target) {
+ case GL_TEXTURE_2D:
+ 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:
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, level);
+ status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
+ std::cerr << __FUNCTION__ << ": " << enumToString(status) << "\n";
+ }
+ glReadPixels(0, 0, desc.width, desc.height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
+ break;
+ case GL_TEXTURE_3D_OES:
+ for (int i = 0; i < desc.depth; i++) {
+ glFramebufferTexture3D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_3D, texture, level, i);
+ glReadPixels(0, 0, desc.width, desc.height, GL_RGBA, GL_UNSIGNED_BYTE, pixels + 4 * i * desc.width * desc.height);
}
+ break;
}
- if (width <= 0 || height <= 0 || depth <= 0) {
+ glBindFramebuffer(GL_FRAMEBUFFER, prev_fbo);
+
+ glDeleteFramebuffers(1, &fbo);
+}
+
+
+static inline void
+dumpActiveTextureLevel(JSONWriter &json, Context &context, GLenum target, GLint level)
+{
+ ImageDesc desc;
+ if (!getActiveTextureLevelDesc(context, target, level, desc)) {
return;
- } else {
- char label[512];
+ }
+
+ char label[512];
- GLint active_texture = GL_TEXTURE0;
- glGetIntegerv(GL_ACTIVE_TEXTURE, &active_texture);
- snprintf(label, sizeof label, "%s, %s, level = %d",
- enumToString(active_texture), enumToString(target), level);
+ GLint active_texture = GL_TEXTURE0;
+ glGetIntegerv(GL_ACTIVE_TEXTURE, &active_texture);
+ snprintf(label, sizeof label, "%s, %s, level = %d",
+ enumToString(active_texture), enumToString(target), level);
- json.beginMember(label);
+ json.beginMember(label);
- json.beginObject();
+ json.beginObject();
- // Tell the GUI this is no ordinary object, but an image
- json.writeStringMember("__class__", "image");
+ // 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);
+ json.writeNumberMember("__width__", desc.width);
+ json.writeNumberMember("__height__", desc.height);
+ json.writeNumberMember("__depth__", desc.depth);
- json.writeStringMember("__format__", enumToString(format));
+ json.writeStringMember("__format__", enumToString(desc.internalFormat));
- // 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);
+ // 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];
+ GLubyte *pixels = new GLubyte[desc.depth*desc.width*desc.height*4];
- context.resetPixelPackState();
+ context.resetPixelPackState();
+ if (context.ES) {
+ getTexImageOES(target, level, desc, pixels);
+ } else {
glGetTexImage(target, level, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
+ }
- context.restorePixelPackState();
+ context.restorePixelPackState();
- json.beginMember("__data__");
- char *pngBuffer;
- int pngBufferSize;
- image::writePixelsToBuffer(pixels, width, height, 4, true, &pngBuffer, &pngBufferSize);
- json.writeBase64(pngBuffer, pngBufferSize);
- free(pngBuffer);
- json.endMember(); // __data__
+ json.beginMember("__data__");
+ char *pngBuffer;
+ int pngBufferSize;
+ image::writePixelsToBuffer(pixels, desc.width, desc.height, 4, true, &pngBuffer, &pngBufferSize);
+ json.writeBase64(pngBuffer, pngBufferSize);
+ free(pngBuffer);
+ json.endMember(); // __data__
- delete [] pixels;
- json.endObject();
- }
+ delete [] pixels;
+ json.endObject();
}
GLint level = 0;
do {
- GLint width = 0, height = 0;
- glGetTexLevelParameteriv(target, level, GL_TEXTURE_WIDTH, &width);
- glGetTexLevelParameteriv(target, level, GL_TEXTURE_HEIGHT, &height);
- if (!width || !height) {
+ ImageDesc desc;
+ if (!getActiveTextureLevelDesc(context, target, level, desc)) {
break;
}
if (target == GL_TEXTURE_CUBE_MAP) {
for (int face = 0; face < 6; ++face) {
- dumpTextureImage(json, context, GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level);
+ dumpActiveTextureLevel(json, context, GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level);
}
} else {
- dumpTextureImage(json, context, target, level);
+ dumpActiveTextureLevel(json, context, target, level);
}
++level;
static bool
getDrawableBounds(GLint *width, GLint *height) {
-#if defined(TRACE_EGL)
+#if defined(__linux__)
+ if (dlsym(RTLD_DEFAULT, "eglGetCurrentContext")) {
+ EGLContext currentContext = eglGetCurrentContext();
+ if (currentContext == EGL_NO_CONTEXT) {
+ return false;
+ }
- EGLContext currentContext = eglGetCurrentContext();
- if (currentContext == EGL_NO_CONTEXT) {
- return false;
- }
+ 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;
}
+#endif
- return true;
-
-#elif defined(_WIN32)
+#if defined(_WIN32)
HDC hDC = wglGetCurrentDC();
if (!hDC) {
static bool
-getTextureLevelSize(GLint texture, GLint level, GLint *width, GLint *height)
+getTextureLevelDesc(Context &context, GLint texture, GLint level, ImageDesc &desc)
{
- *width = 0;
- *height = 0;
-
GLenum target;
GLint bound_texture = 0;
if (!bindTexture(texture, target, bound_texture)) {
return false;
}
- glGetTexLevelParameteriv(target, level, GL_TEXTURE_WIDTH, width);
- glGetTexLevelParameteriv(target, level, GL_TEXTURE_HEIGHT, height);
-
- glBindTexture(target, bound_texture);
-
- return *width > 0 && *height > 0;
-}
-
-
-static GLenum
-getTextureLevelFormat(GLint texture, GLint level)
-{
- GLenum target;
- GLint bound_texture = 0;
- if (!bindTexture(texture, target, bound_texture)) {
- return GL_NONE;
- }
-
- GLint format = GL_NONE;
- glGetTexLevelParameteriv(target, level, GL_TEXTURE_INTERNAL_FORMAT, &format);
+ getActiveTextureLevelDesc(context, target, level, desc);
glBindTexture(target, bound_texture);
- return format;
+ return desc.valid();
}
-
static bool
-getRenderbufferSize(GLint renderbuffer, GLint *width, GLint *height)
+getBoundRenderbufferDesc(Context &context, ImageDesc &desc)
{
- GLint bound_renderbuffer = 0;
- glGetIntegerv(GL_RENDERBUFFER_BINDING, &bound_renderbuffer);
- glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
-
- *width = 0;
- *height = 0;
- glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, width);
- glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, height);
-
- glBindRenderbuffer(GL_RENDERBUFFER, bound_renderbuffer);
+ glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &desc.width);
+ glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &desc.height);
+ desc.depth = 1;
+
+ glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_INTERNAL_FORMAT, &desc.internalFormat);
- return *width > 0 && *height > 0;
+ return desc.valid();
}
-static GLenum
-getRenderbufferFormat(GLint renderbuffer)
+static bool
+getRenderbufferDesc(Context &context, GLint renderbuffer, ImageDesc &desc)
{
GLint bound_renderbuffer = 0;
glGetIntegerv(GL_RENDERBUFFER_BINDING, &bound_renderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
- GLint format = GL_NONE;
- glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_INTERNAL_FORMAT, &format);
+ getBoundRenderbufferDesc(context, desc);
glBindRenderbuffer(GL_RENDERBUFFER, bound_renderbuffer);
- return format;
+ return desc.valid();
}
static bool
-getFramebufferAttachmentSize(GLenum target, GLenum attachment, GLint *width, GLint *height)
+getFramebufferAttachmentDesc(Context &context, GLenum target, GLenum attachment, ImageDesc &desc)
{
GLint object_type = GL_NONE;
glGetFramebufferAttachmentParameteriv(target, attachment,
}
if (object_type == GL_RENDERBUFFER) {
- return getRenderbufferSize(object_name, width, height);
+ return getRenderbufferDesc(context, object_name, desc);
} else if (object_type == GL_TEXTURE) {
GLint texture_level = 0;
glGetFramebufferAttachmentParameteriv(target, attachment,
GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL,
&texture_level);
- return getTextureLevelSize(object_name, texture_level, width, height);
+ return getTextureLevelDesc(context, object_name, texture_level, desc);
} else {
std::cerr << "warning: unexpected GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE = " << object_type << "\n";
return false;
-static GLint
-getFramebufferAttachmentFormat(GLenum target, GLenum attachment)
-{
- GLint object_type = GL_NONE;
- glGetFramebufferAttachmentParameteriv(target, attachment,
- GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE,
- &object_type);
- if (object_type == GL_NONE) {
- return GL_NONE;
- }
-
- GLint object_name = 0;
- glGetFramebufferAttachmentParameteriv(target, attachment,
- GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
- &object_name);
- if (object_name == 0) {
- return GL_NONE;
- }
-
- if (object_type == GL_RENDERBUFFER) {
- return getRenderbufferFormat(object_name);
- } else if (object_type == GL_TEXTURE) {
- GLint texture_level = 0;
- glGetFramebufferAttachmentParameteriv(target, attachment,
- GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL,
- &texture_level);
- return getTextureLevelFormat(object_name, texture_level);
- } else {
- std::cerr << "warning: unexpected GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE = " << object_type << "\n";
- return GL_NONE;
- }
-}
-
-
-
image::Image *
getDrawBufferImage() {
GLenum format = GL_RGB;
glGetIntegerv(framebuffer_binding, &draw_framebuffer);
GLint draw_buffer = GL_NONE;
- GLint width, height;
+ ImageDesc desc;
if (draw_framebuffer) {
if (context.ARB_draw_buffers) {
glGetIntegerv(GL_DRAW_BUFFER0, &draw_buffer);
}
}
- if (!getFramebufferAttachmentSize(framebuffer_target, draw_buffer, &width, &height)) {
+ if (!getFramebufferAttachmentDesc(context, framebuffer_target, draw_buffer, desc)) {
return NULL;
}
} else {
}
}
- if (!getDrawableBounds(&width, &height)) {
+ if (!getDrawableBounds(&desc.width, &desc.height)) {
return NULL;
}
+
+ desc.depth = 1;
}
GLenum type = GL_UNSIGNED_BYTE;
}
#endif
- image::Image *image = new image::Image(width, height, channels, true);
+ image::Image *image = new image::Image(desc.width, desc.height, channels, true);
if (!image) {
return NULL;
}
// TODO: reset imaging state too
context.resetPixelPackState();
- glReadPixels(0, 0, width, height, format, type, image->pixels);
+ glReadPixels(0, 0, desc.width, desc.height, format, type, image->pixels);
context.restorePixelPackState();
static inline GLuint
-downsampledFramebuffer(GLuint oldFbo, GLint drawbuffer,
+downsampledFramebuffer(Context &context,
+ 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;
+ {
+ // 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);
+ 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, desc.width, desc.height, 0, 0, desc.width, desc.height,
+ GL_COLOR_BUFFER_BIT, GL_NEAREST);
+ glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+ ++*numRbs;
+ }
if (stencilRb == depthRb && stencilRb) {
//combined depth and stencil buffer
+ ImageDesc desc;
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);
+ getBoundRenderbufferDesc(context, desc);
glGenRenderbuffers(1, &rbs[*numRbs]);
glBindRenderbuffer(GL_RENDERBUFFER, rbs[*numRbs]);
- glRenderbufferStorage(GL_RENDERBUFFER, format, w, h);
+ glRenderbufferStorage(GL_RENDERBUFFER, desc.internalFormat, desc.width, desc.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, w, h, 0, 0, w, h,
+ glBlitFramebuffer(0, 0, desc.width, desc.height, 0, 0, desc.width, desc.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);
- glGetRenderbufferParameteriv(GL_RENDERBUFFER,
- GL_RENDERBUFFER_WIDTH, &w);
- glGetRenderbufferParameteriv(GL_RENDERBUFFER,
- GL_RENDERBUFFER_HEIGHT, &h);
- glGetRenderbufferParameteriv(GL_RENDERBUFFER,
- GL_RENDERBUFFER_INTERNAL_FORMAT, &format);
+ getBoundRenderbufferDesc(context, desc);
glGenRenderbuffers(1, &rbs[*numRbs]);
glBindRenderbuffer(GL_RENDERBUFFER, rbs[*numRbs]);
- glRenderbufferStorage(GL_RENDERBUFFER, format, w, h);
+ glRenderbufferStorage(GL_RENDERBUFFER, desc.internalFormat, desc.width, desc.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, w, h, 0, 0, w, h,
+ glBlitFramebuffer(0, 0, desc.width, desc.height, 0, 0, desc.width, desc.height,
GL_DEPTH_BUFFER_BIT, GL_NEAREST);
++*numRbs;
}
if (stencilRb) {
+ ImageDesc desc;
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);
+ getBoundRenderbufferDesc(context, desc);
glGenRenderbuffers(1, &rbs[*numRbs]);
glBindRenderbuffer(GL_RENDERBUFFER, rbs[*numRbs]);
- glRenderbufferStorage(GL_RENDERBUFFER, format, w, h);
+ glRenderbufferStorage(GL_RENDERBUFFER, desc.internalFormat, desc.width, desc.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, w, h, 0, 0, w, h,
+ glBlitFramebuffer(0, 0, desc.width, desc.height, 0, 0, desc.width, desc.height,
GL_STENCIL_BUFFER_BIT, GL_NEAREST);
++*numRbs;
}
* 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)
+dumpFramebufferAttachment(JSONWriter &json, Context &context, GLenum target, GLenum attachment, GLenum format)
{
- GLint width = 0, height = 0;
- if (!getFramebufferAttachmentSize(target, attachment, &width, &height)) {
+ ImageDesc desc;
+ if (!getFramebufferAttachmentDesc(context, target, attachment, desc)) {
return;
}
- GLint internalFormat = getFramebufferAttachmentFormat(target, attachment);
-
json.beginMember(enumToString(attachment));
- dumpReadBufferImage(json, width, height, format, internalFormat);
+ dumpReadBufferImage(json, desc.width, desc.height, format, desc.internalFormat);
json.endMember();
}
GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE,
&alpha_size);
GLenum format = alpha_size ? GL_RGBA : GL_RGB;
- dumpFramebufferAttachment(json, target, attachment, format);
+ dumpFramebufferAttachment(json, context, target, attachment, format);
}
}
glReadBuffer(read_buffer);
if (!context.ES) {
- dumpFramebufferAttachment(json, target, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT);
- dumpFramebufferAttachment(json, target, GL_STENCIL_ATTACHMENT, GL_STENCIL_INDEX);
+ dumpFramebufferAttachment(json, context, target, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT);
+ dumpFramebufferAttachment(json, context, target, GL_STENCIL_ATTACHMENT, GL_STENCIL_INDEX);
}
glBindFramebuffer(GL_READ_FRAMEBUFFER, read_framebuffer);
if (multisample) {
// glReadPixels doesnt support multisampled buffers so we need
// to blit the fbo to a temporary one
- fboCopy = downsampledFramebuffer(boundDrawFbo, draw_buffer0,
+ fboCopy = downsampledFramebuffer(context,
+ boundDrawFbo, draw_buffer0,
colorRb, depthRb, stencilRb,
rbs, &numRbs);
}