#include <string.h>
-#include <iostream>
+
#include <algorithm>
+#include <iostream>
+#include <map>
+#include <sstream>
#include "image.hpp"
#include "json.hpp"
}
+// Mapping from shader type to shader source, used to accumulated the sources
+// of different shaders with same type.
+typedef std::map<std::string, std::string> ShaderMap;
+
+
static void
-dumpShader(JSONWriter &json, GLuint shader)
+getShaderSource(ShaderMap &shaderMap, GLuint shader)
{
if (!shader) {
return;
source[0] = 0;
glGetShaderSource(shader, source_length, &length, source);
- json.beginMember(enumToString(shader_type));
- json.writeString(source);
- json.endMember();
+ shaderMap[enumToString(shader_type)] += source;
delete [] source;
}
static void
-dumpShaderObj(JSONWriter &json, GLhandleARB shaderObj)
+getShaderObjSource(ShaderMap &shaderMap, GLhandleARB shaderObj)
{
if (!shaderObj) {
return;
}
+ GLint object_type = 0;
+ glGetObjectParameterivARB(shaderObj, GL_OBJECT_TYPE_ARB, &object_type);
+ if (object_type != GL_SHADER_OBJECT_ARB) {
+ return;
+ }
+
GLint shader_type = 0;
- glGetObjectParameterivARB(shaderObj, GL_OBJECT_TYPE_ARB, &shader_type);
+ glGetObjectParameterivARB(shaderObj, GL_OBJECT_SUBTYPE_ARB, &shader_type);
if (!shader_type) {
return;
}
source[0] = 0;
glGetShaderSource(shaderObj, source_length, &length, source);
- json.beginMember(enumToString(shader_type));
- json.writeString(source);
- json.endMember();
+ shaderMap[enumToString(shader_type)] += source;
delete [] source;
}
static inline void
-dumpCurrentProgram(JSONWriter &json)
+dumpProgram(JSONWriter &json, GLint program)
{
- 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;
}
+ ShaderMap shaderMap;
+
GLuint *shaders = new GLuint[attached_shaders];
GLsizei count = 0;
glGetAttachedShaders(program, attached_shaders, &count, shaders);
+ std::sort(shaders, shaders + count);
for (GLsizei i = 0; i < count; ++ i) {
- dumpShader(json, shaders[i]);
+ getShaderSource(shaderMap, shaders[i]);
}
delete [] shaders;
+
+ for (ShaderMap::const_iterator it = shaderMap.begin(); it != shaderMap.end(); ++it) {
+ json.beginMember(it->first);
+ json.writeString(it->second);
+ json.endMember();
+ }
}
static inline void
-dumpCurrentProgramObj(JSONWriter &json)
+dumpProgramObj(JSONWriter &json, GLhandleARB programObj)
{
- GLhandleARB programObj = glGetHandleARB(GL_PROGRAM_OBJECT_ARB);
- if (!programObj) {
- return;
- }
-
GLint attached_shaders = 0;
- glGetProgramivARB(programObj, GL_OBJECT_ATTACHED_OBJECTS_ARB, &attached_shaders);
+ glGetObjectParameterivARB(programObj, GL_OBJECT_ATTACHED_OBJECTS_ARB, &attached_shaders);
if (!attached_shaders) {
return;
}
+ ShaderMap shaderMap;
+
GLhandleARB *shaderObjs = new GLhandleARB[attached_shaders];
GLsizei count = 0;
glGetAttachedObjectsARB(programObj, attached_shaders, &count, shaderObjs);
+ std::sort(shaderObjs, shaderObjs + count);
for (GLsizei i = 0; i < count; ++ i) {
- dumpShaderObj(json, shaderObjs[i]);
+ getShaderObjSource(shaderMap, shaderObjs[i]);
}
delete [] shaderObjs;
+
+ for (ShaderMap::const_iterator it = shaderMap.begin(); it != shaderMap.end(); ++it) {
+ json.beginMember(it->first);
+ json.writeString(it->second);
+ json.endMember();
+ }
+}
+
+
+static void
+dumpUniform(JSONWriter &json, GLint program, GLint size, GLenum type, const GLchar *name) {
+
+ GLenum elemType;
+ GLint numElems;
+ __gl_uniform_size(type, elemType, numElems);
+ if (elemType == GL_NONE) {
+ return;
+ }
+
+ GLfloat fvalues[4*4];
+ GLdouble dvalues[4*4];
+ GLint ivalues[4*4];
+ GLuint uivalues[4*4];
+
+ GLint i, j;
+
+ for (i = 0; i < size; ++i) {
+ std::stringstream ss;
+ ss << name;
+
+ if (size > 1) {
+ ss << '[' << i << ']';
+ }
+
+ std::string elemName = ss.str();
+
+ json.beginMember(elemName);
+
+ GLint location = glGetUniformLocation(program, elemName.c_str());
+
+ if (numElems > 1) {
+ json.beginArray();
+ }
+
+ switch (elemType) {
+ case GL_FLOAT:
+ glGetUniformfv(program, location, fvalues);
+ for (j = 0; j < numElems; ++j) {
+ json.writeNumber(fvalues[j]);
+ }
+ break;
+ case GL_DOUBLE:
+ glGetUniformdv(program, location, dvalues);
+ for (j = 0; j < numElems; ++j) {
+ json.writeNumber(dvalues[j]);
+ }
+ break;
+ case GL_INT:
+ glGetUniformiv(program, location, ivalues);
+ for (j = 0; j < numElems; ++j) {
+ json.writeNumber(ivalues[j]);
+ }
+ break;
+ case GL_UNSIGNED_INT:
+ glGetUniformuiv(program, location, uivalues);
+ for (j = 0; j < numElems; ++j) {
+ json.writeNumber(uivalues[j]);
+ }
+ break;
+ case GL_BOOL:
+ glGetUniformiv(program, location, ivalues);
+ for (j = 0; j < numElems; ++j) {
+ json.writeBool(ivalues[j]);
+ }
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ if (numElems > 1) {
+ json.endArray();
+ }
+
+ json.endMember();
+ }
+}
+
+
+static void
+dumpUniformARB(JSONWriter &json, GLhandleARB programObj, GLint size, GLenum type, const GLchar *name) {
+
+ GLenum elemType;
+ GLint numElems;
+ __gl_uniform_size(type, elemType, numElems);
+ if (elemType == GL_NONE) {
+ return;
+ }
+
+ GLfloat fvalues[4*4];
+ GLint ivalues[4*4];
+
+ GLint i, j;
+
+ for (i = 0; i < size; ++i) {
+ std::stringstream ss;
+ ss << name;
+
+ if (size > 1) {
+ ss << '[' << i << ']';
+ }
+
+ std::string elemName = ss.str();
+
+ json.beginMember(elemName);
+
+ GLint location = glGetUniformLocationARB(programObj, elemName.c_str());
+
+ if (numElems > 1) {
+ json.beginArray();
+ }
+
+ switch (elemType) {
+ case GL_DOUBLE:
+ // glGetUniformdvARB does not exists
+ case GL_FLOAT:
+ glGetUniformfvARB(programObj, location, fvalues);
+ for (j = 0; j < numElems; ++j) {
+ json.writeNumber(fvalues[j]);
+ }
+ break;
+ case GL_UNSIGNED_INT:
+ // glGetUniformuivARB does not exists
+ case GL_INT:
+ glGetUniformivARB(programObj, location, ivalues);
+ for (j = 0; j < numElems; ++j) {
+ json.writeNumber(ivalues[j]);
+ }
+ break;
+ case GL_BOOL:
+ glGetUniformivARB(programObj, location, ivalues);
+ for (j = 0; j < numElems; ++j) {
+ json.writeBool(ivalues[j]);
+ }
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ if (numElems > 1) {
+ json.endArray();
+ }
+
+ json.endMember();
+ }
+}
+
+
+static inline void
+dumpProgramUniforms(JSONWriter &json, GLint program)
+{
+ GLint active_uniforms = 0;
+ glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &active_uniforms);
+ if (!active_uniforms) {
+ return;
+ }
+
+ GLint active_uniform_max_length = 0;
+ glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &active_uniform_max_length);
+ GLchar *name = new GLchar[active_uniform_max_length];
+ if (!name) {
+ return;
+ }
+
+ for (GLint index = 0; index < active_uniforms; ++index) {
+ GLsizei length = 0;
+ GLint size = 0;
+ GLenum type = GL_NONE;
+ glGetActiveUniform(program, index, active_uniform_max_length, &length, &size, &type, name);
+
+ dumpUniform(json, program, size, type, name);
+ }
+
+ delete [] name;
+}
+
+
+static inline void
+dumpProgramObjUniforms(JSONWriter &json, GLhandleARB programObj)
+{
+ GLint active_uniforms = 0;
+ glGetObjectParameterivARB(programObj, GL_OBJECT_ACTIVE_UNIFORMS_ARB, &active_uniforms);
+ if (!active_uniforms) {
+ return;
+ }
+
+ GLint active_uniform_max_length = 0;
+ glGetObjectParameterivARB(programObj, GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB, &active_uniform_max_length);
+ GLchar *name = new GLchar[active_uniform_max_length];
+ if (!name) {
+ return;
+ }
+
+ for (GLint index = 0; index < active_uniforms; ++index) {
+ GLsizei length = 0;
+ GLint size = 0;
+ GLenum type = GL_NONE;
+ glGetActiveUniformARB(programObj, index, active_uniform_max_length, &length, &size, &type, name);
+
+ dumpUniformARB(json, programObj, size, type, name);
+ }
+
+ delete [] name;
}
static inline void
-dumpShaders(JSONWriter &json)
+dumpArbProgramUniforms(JSONWriter &json, GLenum target, const char *prefix)
+{
+ if (!glIsEnabled(target)) {
+ return;
+ }
+
+ GLint program_parameters = 0;
+ glGetProgramivARB(target, GL_PROGRAM_PARAMETERS_ARB, &program_parameters);
+ if (!program_parameters) {
+ return;
+ }
+
+ GLint max_program_local_parameters = 0;
+ glGetProgramivARB(target, GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB, &max_program_local_parameters);
+ for (GLuint index = 0; index < max_program_local_parameters; ++index) {
+ GLdouble params[4] = {0, 0, 0, 0};
+ glGetProgramLocalParameterdvARB(target, index, params);
+
+ if (!params[0] && !params[1] && !params[2] && !params[3]) {
+ continue;
+ }
+
+ char name[256];
+ snprintf(name, sizeof name, "%sprogram.local[%u]", prefix, index);
+
+ json.beginMember(name);
+ json.beginArray();
+ json.writeNumber(params[0]);
+ json.writeNumber(params[1]);
+ json.writeNumber(params[2]);
+ json.writeNumber(params[3]);
+ json.endArray();
+ json.endMember();
+ }
+
+ GLint max_program_env_parameters = 0;
+ glGetProgramivARB(target, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &max_program_env_parameters);
+ for (GLuint index = 0; index < max_program_env_parameters; ++index) {
+ GLdouble params[4] = {0, 0, 0, 0};
+ glGetProgramEnvParameterdvARB(target, index, params);
+
+ if (!params[0] && !params[1] && !params[2] && !params[3]) {
+ continue;
+ }
+
+ char name[256];
+ snprintf(name, sizeof name, "%sprogram.env[%u]", prefix, index);
+
+ json.beginMember(name);
+ json.beginArray();
+ json.writeNumber(params[0]);
+ json.writeNumber(params[1]);
+ json.writeNumber(params[2]);
+ json.writeNumber(params[3]);
+ json.endArray();
+ json.endMember();
+ }
+}
+
+
+static inline void
+dumpShadersUniforms(JSONWriter &json)
{
+ GLint program = 0;
+ glGetIntegerv(GL_CURRENT_PROGRAM, &program);
+
+ GLhandleARB programObj = glGetHandleARB(GL_PROGRAM_OBJECT_ARB);
+
json.beginMember("shaders");
json.beginObject();
- dumpCurrentProgram(json);
- dumpArbProgram(json, GL_FRAGMENT_PROGRAM_ARB);
- dumpArbProgram(json, GL_VERTEX_PROGRAM_ARB);
+ if (program) {
+ dumpProgram(json, program);
+ } else if (programObj) {
+ dumpProgramObj(json, programObj);
+ } else {
+ dumpArbProgram(json, GL_FRAGMENT_PROGRAM_ARB);
+ dumpArbProgram(json, GL_VERTEX_PROGRAM_ARB);
+ }
+ json.endObject();
+ json.endMember(); // shaders
+
+ json.beginMember("uniforms");
+ json.beginObject();
+ if (program) {
+ dumpProgramUniforms(json, program);
+ } else if (programObj) {
+ dumpProgramObjUniforms(json, programObj);
+ } else {
+ dumpArbProgramUniforms(json, GL_FRAGMENT_PROGRAM_ARB, "fp.");
+ dumpArbProgramUniforms(json, GL_VERTEX_PROGRAM_ARB, "vp.");
+ }
json.endObject();
- json.endMember(); //shaders
+ json.endMember(); // uniforms
}
}
+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}
+};
+
+
+static bool
+bindTexture(GLint texture, GLenum &target, GLint &bound_texture)
+{
+
+ for (unsigned i = 0; i < sizeof(texture_bindings)/sizeof(texture_bindings[0]); ++i) {
+ target = texture_bindings[i][0];
+
+ GLenum binding = texture_bindings[i][1];
+
+ while (glGetError() != GL_NO_ERROR)
+ ;
+
+ glGetIntegerv(binding, &bound_texture);
+ glBindTexture(target, texture);
+
+ if (glGetError() == GL_NO_ERROR) {
+ return true;
+ }
+
+ glBindTexture(target, bound_texture);
+ }
+
+ target = GL_NONE;
+
+ return false;
+}
+
+
+static bool
+getTextureLevelSize(GLint texture, GLint level, GLint *width, GLint *height)
+{
+ *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 bool
+getRenderbufferSize(GLint renderbuffer, GLint *width, GLint *height)
+{
+ 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);
+
+ return *width > 0 && *height > 0;
+}
+
+
+static bool
+getFramebufferAttachmentSize(GLenum target, GLenum attachment, GLint *width, GLint *height)
+{
+ GLint object_type = GL_NONE;
+ glGetFramebufferAttachmentParameteriv(target, attachment,
+ GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE,
+ &object_type);
+ if (object_type == GL_NONE) {
+ return false;
+ }
+
+ GLint object_name = 0;
+ glGetFramebufferAttachmentParameteriv(target, attachment,
+ GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
+ &object_name);
+ if (object_name == 0) {
+ return false;
+ }
+
+ if (object_type == GL_RENDERBUFFER) {
+ return getRenderbufferSize(object_name, width, height);
+ } 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);
+ } else {
+ std::cerr << "warning: unexpected GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE = " << object_type << "\n";
+ return false;
+ }
+}
+
+
Image::Image *
getDrawBufferImage(GLenum format) {
GLint channels = __gl_format_channels(format);
return NULL;
}
+ GLint draw_framebuffer = 0;
+ glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &draw_framebuffer);
+
+ GLint draw_buffer = GL_NONE;
GLint width, height;
- if (!getDrawableBounds(&width, &height)) {
- return NULL;
+ if (draw_framebuffer) {
+ glGetIntegerv(GL_DRAW_BUFFER0, &draw_buffer);
+ if (draw_buffer == GL_NONE) {
+ return NULL;
+ }
+
+ if (!getFramebufferAttachmentSize(GL_DRAW_FRAMEBUFFER, draw_buffer, &width, &height)) {
+ return NULL;
+ }
+ } else {
+ glGetIntegerv(GL_DRAW_BUFFER, &draw_buffer);
+ if (draw_buffer == GL_NONE) {
+ return NULL;
+ }
+
+ if (!getDrawableBounds(&width, &height)) {
+ return NULL;
+ }
}
Image::Image *image = new Image::Image(width, height, channels, true);
return NULL;
}
- GLint draw_buffer = GL_NONE;
- GLint read_buffer = GL_NONE;
- glGetIntegerv(GL_DRAW_BUFFER, &draw_buffer);
+ while (glGetError() != GL_NO_ERROR) {}
+
+ GLint read_framebuffer = 0;
+ glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &read_framebuffer);
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, draw_framebuffer);
+
+ GLint read_buffer = 0;
glGetIntegerv(GL_READ_BUFFER, &read_buffer);
glReadBuffer(draw_buffer);
+ // TODO: reset imaging state too
resetPixelPackState();
glReadPixels(0, 0, width, height, format, GL_UNSIGNED_BYTE, image->pixels);
restorePixelPackState();
glReadBuffer(read_buffer);
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, read_framebuffer);
+ GLenum error = glGetError();
+ if (error != GL_NO_ERROR) {
+ do {
+ std::cerr << "warning: " << enumToString(error) << " while getting snapshot\n";
+ error = glGetError();
+ } while(error != GL_NO_ERROR);
+ delete image;
+ return NULL;
+ }
+
return image;
}
GLubyte *pixels = new GLubyte[width*height*channels];
+ // TODO: reset imaging state too
resetPixelPackState();
glReadPixels(0, 0, width, height, format, GL_UNSIGNED_BYTE, pixels);
json.endMember();
}
}
-
-
-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}
-};
-
-
-static bool
-bindTexture(GLint texture, GLenum &target, GLint &bound_texture)
-{
-
- for (unsigned i = 0; i < sizeof(texture_bindings)/sizeof(texture_bindings[0]); ++i) {
- target = texture_bindings[i][0];
-
- GLenum binding = texture_bindings[i][1];
-
- while (glGetError() != GL_NO_ERROR)
- ;
-
- glGetIntegerv(binding, &bound_texture);
- glBindTexture(target, texture);
-
- if (glGetError() == GL_NO_ERROR) {
- return true;
- }
-
- glBindTexture(target, bound_texture);
- }
-
- target = GL_NONE;
-
- return false;
-}
-
-
-static bool
-getTextureLevelSize(GLint texture, GLint level, GLint *width, GLint *height)
-{
- *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;
-}
-
-
/**
* Dump the specified framebuffer attachment.
*
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";
+ GLint width = 0, height = 0;
+ if (!getFramebufferAttachmentSize(target, attachment, &width, &height)) {
return;
}
}
+static const GLenum bindings[] = {
+ GL_DRAW_BUFFER,
+ GL_READ_BUFFER,
+ GL_PIXEL_PACK_BUFFER_BINDING,
+ GL_PIXEL_UNPACK_BUFFER_BINDING,
+ GL_TEXTURE_BINDING_1D,
+ GL_TEXTURE_BINDING_2D,
+ GL_TEXTURE_BINDING_3D,
+ GL_TEXTURE_BINDING_RECTANGLE,
+ GL_TEXTURE_BINDING_CUBE_MAP,
+ GL_DRAW_FRAMEBUFFER_BINDING,
+ GL_READ_FRAMEBUFFER_BINDING,
+ GL_RENDERBUFFER_BINDING,
+ GL_DRAW_BUFFER0,
+ GL_DRAW_BUFFER1,
+ GL_DRAW_BUFFER2,
+ GL_DRAW_BUFFER3,
+ GL_DRAW_BUFFER4,
+ GL_DRAW_BUFFER5,
+ GL_DRAW_BUFFER6,
+ GL_DRAW_BUFFER7,
+};
+
+
+#define NUM_BINDINGS sizeof(bindings)/sizeof(bindings[0])
+
+
void dumpCurrentContext(std::ostream &os)
{
JSONWriter json(os);
+
+#ifndef NDEBUG
+ GLint old_bindings[NUM_BINDINGS];
+ for (unsigned i = 0; i < NUM_BINDINGS; ++i) {
+ old_bindings[i] = 0;
+ glGetIntegerv(bindings[i], &old_bindings[i]);
+ }
+#endif
+
dumpParameters(json);
- dumpShaders(json);
+ dumpShadersUniforms(json);
dumpTextures(json);
dumpFramebuffer(json);
+
+#ifndef NDEBUG
+ for (unsigned i = 0; i < NUM_BINDINGS; ++i) {
+ GLint new_binding = 0;
+ glGetIntegerv(bindings[i], &new_binding);
+ if (new_binding != old_bindings[i]) {
+ std::cerr << "warning: " << enumToString(bindings[i]) << " was clobbered\n";
+ }
+ }
+#endif
+
}