1 /**************************************************************************
3 * Copyright 2011 Jose Fonseca
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 **************************************************************************/
38 #include "glstate.hpp"
43 #include <Carbon/Carbon.h>
49 OSStatus CGSGetSurfaceBounds(CGSConnectionID, CGWindowID, CGSSurfaceID, CGRect *);
55 #endif /* __APPLE__ */
62 resetPixelPackState(void) {
63 glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
64 glPixelStorei(GL_PACK_SWAP_BYTES, GL_FALSE);
65 glPixelStorei(GL_PACK_LSB_FIRST, GL_FALSE);
66 glPixelStorei(GL_PACK_ROW_LENGTH, 0);
67 glPixelStorei(GL_PACK_IMAGE_HEIGHT, 0);
68 glPixelStorei(GL_PACK_SKIP_ROWS, 0);
69 glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
70 glPixelStorei(GL_PACK_SKIP_IMAGES, 0);
71 glPixelStorei(GL_PACK_ALIGNMENT, 1);
72 glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
77 restorePixelPackState(void) {
82 // Mapping from shader type to shader source, used to accumulated the sources
83 // of different shaders with same type.
84 typedef std::map<std::string, std::string> ShaderMap;
88 getShaderSource(ShaderMap &shaderMap, GLuint shader)
94 GLint shader_type = 0;
95 glGetShaderiv(shader, GL_SHADER_TYPE, &shader_type);
100 GLint source_length = 0;
101 glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &source_length);
102 if (!source_length) {
106 GLchar *source = new GLchar[source_length];
109 glGetShaderSource(shader, source_length, &length, source);
111 shaderMap[enumToString(shader_type)] += source;
118 getShaderObjSource(ShaderMap &shaderMap, GLhandleARB shaderObj)
124 GLint object_type = 0;
125 glGetObjectParameterivARB(shaderObj, GL_OBJECT_TYPE_ARB, &object_type);
126 if (object_type != GL_SHADER_OBJECT_ARB) {
130 GLint shader_type = 0;
131 glGetObjectParameterivARB(shaderObj, GL_OBJECT_SUBTYPE_ARB, &shader_type);
136 GLint source_length = 0;
137 glGetObjectParameterivARB(shaderObj, GL_OBJECT_SHADER_SOURCE_LENGTH_ARB, &source_length);
138 if (!source_length) {
142 GLcharARB *source = new GLcharARB[source_length];
145 glGetShaderSource(shaderObj, source_length, &length, source);
147 shaderMap[enumToString(shader_type)] += source;
154 dumpCurrentProgram(JSONWriter &json)
157 glGetIntegerv(GL_CURRENT_PROGRAM, &program);
162 GLint attached_shaders = 0;
163 glGetProgramiv(program, GL_ATTACHED_SHADERS, &attached_shaders);
164 if (!attached_shaders) {
170 GLuint *shaders = new GLuint[attached_shaders];
172 glGetAttachedShaders(program, attached_shaders, &count, shaders);
173 std::sort(shaders, shaders + count);
174 for (GLsizei i = 0; i < count; ++ i) {
175 getShaderSource(shaderMap, shaders[i]);
179 for (ShaderMap::const_iterator it = shaderMap.begin(); it != shaderMap.end(); ++it) {
180 json.beginMember(it->first);
181 json.writeString(it->second);
188 dumpCurrentProgramObj(JSONWriter &json)
190 GLhandleARB programObj = glGetHandleARB(GL_PROGRAM_OBJECT_ARB);
195 GLint attached_shaders = 0;
196 glGetObjectParameterivARB(programObj, GL_OBJECT_ATTACHED_OBJECTS_ARB, &attached_shaders);
197 if (!attached_shaders) {
203 GLhandleARB *shaderObjs = new GLhandleARB[attached_shaders];
205 glGetAttachedObjectsARB(programObj, attached_shaders, &count, shaderObjs);
206 std::sort(shaderObjs, shaderObjs + count);
207 for (GLsizei i = 0; i < count; ++ i) {
208 getShaderObjSource(shaderMap, shaderObjs[i]);
210 delete [] shaderObjs;
212 for (ShaderMap::const_iterator it = shaderMap.begin(); it != shaderMap.end(); ++it) {
213 json.beginMember(it->first);
214 json.writeString(it->second);
221 dumpUniform(JSONWriter &json, GLint program, GLint size, GLenum type, const GLchar *name) {
225 __gl_uniform_size(type, elemType, numElems);
226 if (elemType == GL_NONE) {
230 GLfloat fvalues[4*4];
231 GLdouble dvalues[4*4];
233 GLuint uivalues[4*4];
237 for (i = 0; i < size; ++i) {
238 std::stringstream ss;
242 ss << '[' << i << ']';
245 std::string elemName = ss.str();
247 json.beginMember(elemName);
249 GLint location = glGetUniformLocation(program, elemName.c_str());
257 glGetUniformfv(program, location, fvalues);
258 for (j = 0; j < numElems; ++j) {
259 json.writeNumber(fvalues[j]);
263 glGetUniformdv(program, location, dvalues);
264 for (j = 0; j < numElems; ++j) {
265 json.writeNumber(dvalues[j]);
269 glGetUniformiv(program, location, ivalues);
270 for (j = 0; j < numElems; ++j) {
271 json.writeNumber(ivalues[j]);
274 case GL_UNSIGNED_INT:
275 glGetUniformuiv(program, location, uivalues);
276 for (j = 0; j < numElems; ++j) {
277 json.writeNumber(uivalues[j]);
281 glGetUniformiv(program, location, ivalues);
282 for (j = 0; j < numElems; ++j) {
283 json.writeBool(ivalues[j]);
301 dumpUniformARB(JSONWriter &json, GLhandleARB programObj, GLint size, GLenum type, const GLchar *name) {
305 __gl_uniform_size(type, elemType, numElems);
306 if (elemType == GL_NONE) {
310 GLfloat fvalues[4*4];
315 for (i = 0; i < size; ++i) {
316 std::stringstream ss;
320 ss << '[' << i << ']';
323 std::string elemName = ss.str();
325 json.beginMember(elemName);
327 GLint location = glGetUniformLocationARB(programObj, elemName.c_str());
335 // glGetUniformdvARB does not exists
337 glGetUniformfvARB(programObj, location, fvalues);
338 for (j = 0; j < numElems; ++j) {
339 json.writeNumber(fvalues[j]);
342 case GL_UNSIGNED_INT:
343 // glGetUniformuivARB does not exists
345 glGetUniformivARB(programObj, location, ivalues);
346 for (j = 0; j < numElems; ++j) {
347 json.writeNumber(ivalues[j]);
351 glGetUniformivARB(programObj, location, ivalues);
352 for (j = 0; j < numElems; ++j) {
353 json.writeBool(ivalues[j]);
371 dumpCurrentProgramUniforms(JSONWriter &json)
374 glGetIntegerv(GL_CURRENT_PROGRAM, &program);
379 GLint active_uniforms = 0;
380 glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &active_uniforms);
381 if (!active_uniforms) {
385 GLint active_uniform_max_length = 0;
386 glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &active_uniform_max_length);
387 GLchar *name = new GLchar[active_uniform_max_length];
392 for (GLint index = 0; index < active_uniforms; ++index) {
395 GLenum type = GL_NONE;
396 glGetActiveUniform(program, index, active_uniform_max_length, &length, &size, &type, name);
398 dumpUniform(json, program, size, type, name);
406 dumpCurrentProgramUniformsARB(JSONWriter &json)
408 GLhandleARB programObj = glGetHandleARB(GL_PROGRAM_OBJECT_ARB);
413 GLint active_uniforms = 0;
414 glGetObjectParameterivARB(programObj, GL_OBJECT_ACTIVE_UNIFORMS_ARB, &active_uniforms);
415 if (!active_uniforms) {
419 GLint active_uniform_max_length = 0;
420 glGetObjectParameterivARB(programObj, GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB, &active_uniform_max_length);
421 GLchar *name = new GLchar[active_uniform_max_length];
426 for (GLint index = 0; index < active_uniforms; ++index) {
429 GLenum type = GL_NONE;
430 glGetActiveUniformARB(programObj, index, active_uniform_max_length, &length, &size, &type, name);
432 dumpUniformARB(json, programObj, size, type, name);
440 dumpArbProgram(JSONWriter &json, GLenum target)
442 if (!glIsEnabled(target)) {
446 GLint program_length = 0;
447 glGetProgramivARB(target, GL_PROGRAM_LENGTH_ARB, &program_length);
448 if (!program_length) {
452 GLchar *source = new GLchar[program_length + 1];
454 glGetProgramStringARB(target, GL_PROGRAM_STRING_ARB, source);
455 source[program_length] = 0;
457 json.beginMember(enumToString(target));
458 json.writeString(source);
466 dumpProgramUniformsARB(JSONWriter &json, GLenum target, const char *prefix)
468 if (!glIsEnabled(target)) {
472 GLint program_parameters = 0;
473 glGetProgramivARB(target, GL_PROGRAM_PARAMETERS_ARB, &program_parameters);
474 if (!program_parameters) {
478 GLint max_program_local_parameters = 0;
479 glGetProgramivARB(target, GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB, &max_program_local_parameters);
480 for (GLuint index = 0; index < max_program_local_parameters; ++index) {
481 GLdouble params[4] = {0, 0, 0, 0};
482 glGetProgramLocalParameterdvARB(target, index, params);
484 if (!params[0] && !params[1] && !params[2] && !params[3]) {
489 snprintf(name, sizeof name, "%sprogram.local[%u]", prefix, index);
491 json.beginMember(name);
493 json.writeNumber(params[0]);
494 json.writeNumber(params[1]);
495 json.writeNumber(params[2]);
496 json.writeNumber(params[3]);
501 GLint max_program_env_parameters = 0;
502 glGetProgramivARB(target, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &max_program_env_parameters);
503 for (GLuint index = 0; index < max_program_env_parameters; ++index) {
504 GLdouble params[4] = {0, 0, 0, 0};
505 glGetProgramEnvParameterdvARB(target, index, params);
507 if (!params[0] && !params[1] && !params[2] && !params[3]) {
512 snprintf(name, sizeof name, "%sprogram.env[%u]", prefix, index);
514 json.beginMember(name);
516 json.writeNumber(params[0]);
517 json.writeNumber(params[1]);
518 json.writeNumber(params[2]);
519 json.writeNumber(params[3]);
527 dumpShaders(JSONWriter &json)
529 json.beginMember("shaders");
531 dumpCurrentProgram(json);
532 dumpCurrentProgramObj(json);
533 dumpArbProgram(json, GL_FRAGMENT_PROGRAM_ARB);
534 dumpArbProgram(json, GL_VERTEX_PROGRAM_ARB);
536 json.endMember(); // shaders
541 dumpUniforms(JSONWriter &json)
543 json.beginMember("uniforms");
545 dumpCurrentProgramUniforms(json);
546 dumpCurrentProgramUniformsARB(json);
547 dumpProgramUniformsARB(json, GL_FRAGMENT_PROGRAM_ARB, "fp.");
548 dumpProgramUniformsARB(json, GL_VERTEX_PROGRAM_ARB, "vp.");
550 json.endMember(); // uniforms
555 dumpTextureImage(JSONWriter &json, GLenum target, GLint level)
557 GLint width, height = 1, depth = 1;
560 glGetTexLevelParameteriv(target, level, GL_TEXTURE_WIDTH, &width);
562 if (target != GL_TEXTURE_1D) {
564 glGetTexLevelParameteriv(target, level, GL_TEXTURE_HEIGHT, &height);
565 if (target == GL_TEXTURE_3D) {
567 glGetTexLevelParameteriv(target, level, GL_TEXTURE_DEPTH, &depth);
571 if (width <= 0 || height <= 0 || depth <= 0) {
576 GLint active_texture = GL_TEXTURE0;
577 glGetIntegerv(GL_ACTIVE_TEXTURE, &active_texture);
578 snprintf(label, sizeof label, "%s, %s, level = %i", enumToString(active_texture), enumToString(target), level);
580 json.beginMember(label);
584 // Tell the GUI this is no ordinary object, but an image
585 json.writeStringMember("__class__", "image");
587 json.writeNumberMember("__width__", width);
588 json.writeNumberMember("__height__", height);
589 json.writeNumberMember("__depth__", depth);
591 // Hardcoded for now, but we could chose types more adequate to the
592 // texture internal format
593 json.writeStringMember("__type__", "uint8");
594 json.writeBoolMember("__normalized__", true);
595 json.writeNumberMember("__channels__", 4);
597 GLubyte *pixels = new GLubyte[depth*width*height*4];
599 resetPixelPackState();
601 glGetTexImage(target, level, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
603 restorePixelPackState();
605 json.beginMember("__data__");
608 Image::writePixelsToBuffer(pixels, width, height, 4, false, &pngBuffer, &pngBufferSize);
609 json.writeBase64(pngBuffer, pngBufferSize);
611 json.endMember(); // __data__
620 dumpTexture(JSONWriter &json, GLenum target, GLenum binding)
622 GLint texture_binding = 0;
623 glGetIntegerv(binding, &texture_binding);
624 if (!glIsEnabled(target) && !texture_binding) {
630 GLint width = 0, height = 0;
631 glGetTexLevelParameteriv(target, level, GL_TEXTURE_WIDTH, &width);
632 glGetTexLevelParameteriv(target, level, GL_TEXTURE_HEIGHT, &height);
633 if (!width || !height) {
637 if (target == GL_TEXTURE_CUBE_MAP) {
638 for (int face = 0; face < 6; ++face) {
639 dumpTextureImage(json, GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level);
642 dumpTextureImage(json, target, level);
651 dumpTextures(JSONWriter &json)
653 json.beginMember("textures");
655 GLint active_texture = GL_TEXTURE0;
656 glGetIntegerv(GL_ACTIVE_TEXTURE, &active_texture);
657 GLint max_texture_coords = 0;
658 glGetIntegerv(GL_MAX_TEXTURE_COORDS, &max_texture_coords);
659 GLint max_combined_texture_image_units = 0;
660 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_combined_texture_image_units);
661 GLint max_units = std::max(max_combined_texture_image_units, max_texture_coords);
662 for (GLint unit = 0; unit < max_units; ++unit) {
663 GLenum texture = GL_TEXTURE0 + unit;
664 glActiveTexture(texture);
665 dumpTexture(json, GL_TEXTURE_1D, GL_TEXTURE_BINDING_1D);
666 dumpTexture(json, GL_TEXTURE_2D, GL_TEXTURE_BINDING_2D);
667 dumpTexture(json, GL_TEXTURE_3D, GL_TEXTURE_BINDING_3D);
668 dumpTexture(json, GL_TEXTURE_RECTANGLE, GL_TEXTURE_BINDING_RECTANGLE);
669 dumpTexture(json, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BINDING_CUBE_MAP);
671 glActiveTexture(active_texture);
673 json.endMember(); // textures
678 getDrawableBounds(GLint *width, GLint *height) {
681 HDC hDC = wglGetCurrentDC();
686 HWND hWnd = WindowFromDC(hDC);
689 if (!GetClientRect(hWnd, &rect)) {
693 *width = rect.right - rect.left;
694 *height = rect.bottom - rect.top;
696 #elif defined(__APPLE__)
698 CGLContextObj ctx = CGLGetCurrentContext();
707 if (CGLGetSurface(ctx, &cid, &wid, &sid) != kCGLNoError) {
713 if (CGSGetSurfaceBounds(cid, wid, sid, &rect) != 0) {
717 *width = rect.size.width;
718 *height = rect.size.height;
726 unsigned int w, h, bw, depth;
728 display = glXGetCurrentDisplay();
733 drawable = glXGetCurrentDrawable();
734 if (drawable == None) {
738 if (!XGetGeometry(display, drawable, &root, &x, &y, &w, &h, &bw, &depth)) {
751 static const GLenum texture_bindings[][2] = {
752 {GL_TEXTURE_1D, GL_TEXTURE_BINDING_1D},
753 {GL_TEXTURE_2D, GL_TEXTURE_BINDING_2D},
754 {GL_TEXTURE_3D, GL_TEXTURE_BINDING_3D},
755 {GL_TEXTURE_RECTANGLE, GL_TEXTURE_BINDING_RECTANGLE},
756 {GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BINDING_CUBE_MAP}
761 bindTexture(GLint texture, GLenum &target, GLint &bound_texture)
764 for (unsigned i = 0; i < sizeof(texture_bindings)/sizeof(texture_bindings[0]); ++i) {
765 target = texture_bindings[i][0];
767 GLenum binding = texture_bindings[i][1];
769 while (glGetError() != GL_NO_ERROR)
772 glGetIntegerv(binding, &bound_texture);
773 glBindTexture(target, texture);
775 if (glGetError() == GL_NO_ERROR) {
779 glBindTexture(target, bound_texture);
789 getTextureLevelSize(GLint texture, GLint level, GLint *width, GLint *height)
795 GLint bound_texture = 0;
796 if (!bindTexture(texture, target, bound_texture)) {
800 glGetTexLevelParameteriv(target, level, GL_TEXTURE_WIDTH, width);
801 glGetTexLevelParameteriv(target, level, GL_TEXTURE_HEIGHT, height);
803 glBindTexture(target, bound_texture);
805 return *width > 0 && *height > 0;
810 getRenderbufferSize(GLint renderbuffer, GLint *width, GLint *height)
812 GLint bound_renderbuffer = 0;
813 glGetIntegerv(GL_RENDERBUFFER_BINDING, &bound_renderbuffer);
814 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
818 glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, width);
819 glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, height);
821 glBindRenderbuffer(GL_RENDERBUFFER, bound_renderbuffer);
823 return *width > 0 && *height > 0;
828 getFramebufferAttachmentSize(GLenum target, GLenum attachment, GLint *width, GLint *height)
830 GLint object_type = GL_NONE;
831 glGetFramebufferAttachmentParameteriv(target, attachment,
832 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE,
834 if (object_type == GL_NONE) {
838 GLint object_name = 0;
839 glGetFramebufferAttachmentParameteriv(target, attachment,
840 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
842 if (object_name == 0) {
846 if (object_type == GL_RENDERBUFFER) {
847 return getRenderbufferSize(object_name, width, height);
848 } else if (object_type == GL_TEXTURE) {
849 GLint texture_level = 0;
850 glGetFramebufferAttachmentParameteriv(target, attachment,
851 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL,
853 return getTextureLevelSize(object_name, texture_level, width, height);
855 std::cerr << "warning: unexpected GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE = " << object_type << "\n";
862 getDrawBufferImage(GLenum format) {
863 GLint channels = __gl_format_channels(format);
868 GLint draw_framebuffer = 0;
869 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &draw_framebuffer);
871 GLint draw_buffer = GL_NONE;
873 if (draw_framebuffer) {
874 glGetIntegerv(GL_DRAW_BUFFER0, &draw_buffer);
875 if (draw_buffer == GL_NONE) {
879 if (!getFramebufferAttachmentSize(GL_DRAW_FRAMEBUFFER, draw_buffer, &width, &height)) {
883 glGetIntegerv(GL_DRAW_BUFFER, &draw_buffer);
884 if (draw_buffer == GL_NONE) {
888 if (!getDrawableBounds(&width, &height)) {
893 Image::Image *image = new Image::Image(width, height, channels, true);
898 while (glGetError() != GL_NO_ERROR) {}
900 GLint read_framebuffer = 0;
901 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &read_framebuffer);
902 glBindFramebuffer(GL_READ_FRAMEBUFFER, draw_framebuffer);
904 GLint read_buffer = 0;
905 glGetIntegerv(GL_READ_BUFFER, &read_buffer);
906 glReadBuffer(draw_buffer);
908 // TODO: reset imaging state too
909 resetPixelPackState();
911 glReadPixels(0, 0, width, height, format, GL_UNSIGNED_BYTE, image->pixels);
913 restorePixelPackState();
914 glReadBuffer(read_buffer);
915 glBindFramebuffer(GL_READ_FRAMEBUFFER, read_framebuffer);
917 GLenum error = glGetError();
918 if (error != GL_NO_ERROR) {
920 std::cerr << "warning: " << enumToString(error) << " while getting snapshot\n";
921 error = glGetError();
922 } while(error != GL_NO_ERROR);
932 * Dump the image of the currently bound read buffer.
935 dumpReadBufferImage(JSONWriter &json, GLint width, GLint height, GLenum format)
937 GLint channels = __gl_format_channels(format);
941 // Tell the GUI this is no ordinary object, but an image
942 json.writeStringMember("__class__", "image");
944 json.writeNumberMember("__width__", width);
945 json.writeNumberMember("__height__", height);
946 json.writeNumberMember("__depth__", 1);
948 // Hardcoded for now, but we could chose types more adequate to the
949 // texture internal format
950 json.writeStringMember("__type__", "uint8");
951 json.writeBoolMember("__normalized__", true);
952 json.writeNumberMember("__channels__", channels);
954 GLubyte *pixels = new GLubyte[width*height*channels];
956 // TODO: reset imaging state too
957 resetPixelPackState();
959 glReadPixels(0, 0, width, height, format, GL_UNSIGNED_BYTE, pixels);
961 restorePixelPackState();
963 json.beginMember("__data__");
966 Image::writePixelsToBuffer(pixels, width, height, channels, false, &pngBuffer, &pngBufferSize);
967 //std::cerr <<" Before = "<<(width * height * channels * sizeof *pixels)
968 // <<", after = "<<pngBufferSize << ", ratio = " << double(width * height * channels * sizeof *pixels)/pngBufferSize;
969 json.writeBase64(pngBuffer, pngBufferSize);
971 json.endMember(); // __data__
979 downsampledFramebuffer(GLuint oldFbo, GLint drawbuffer,
980 GLint colorRb, GLint depthRb, GLint stencilRb,
981 GLuint *rbs, GLint *numRbs)
989 glGenFramebuffers(1, &fbo);
990 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
992 glBindRenderbuffer(GL_RENDERBUFFER, colorRb);
993 glGetRenderbufferParameteriv(GL_RENDERBUFFER,
994 GL_RENDERBUFFER_WIDTH, &w);
995 glGetRenderbufferParameteriv(GL_RENDERBUFFER,
996 GL_RENDERBUFFER_HEIGHT, &h);
997 glGetRenderbufferParameteriv(GL_RENDERBUFFER,
998 GL_RENDERBUFFER_INTERNAL_FORMAT, &format);
1000 glGenRenderbuffers(1, &rbs[*numRbs]);
1001 glBindRenderbuffer(GL_RENDERBUFFER, rbs[*numRbs]);
1002 glRenderbufferStorage(GL_RENDERBUFFER, format, w, h);
1003 glFramebufferRenderbuffer(GL_FRAMEBUFFER, drawbuffer,
1004 GL_RENDERBUFFER, rbs[*numRbs]);
1006 glBindFramebuffer(GL_READ_FRAMEBUFFER, oldFbo);
1007 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
1008 glDrawBuffer(drawbuffer);
1009 glReadBuffer(drawbuffer);
1010 glBlitFramebuffer(0, 0, w, h, 0, 0, w, h,
1011 GL_COLOR_BUFFER_BIT, GL_NEAREST);
1012 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1015 if (stencilRb == depthRb && stencilRb) {
1016 //combined depth and stencil buffer
1017 glBindRenderbuffer(GL_RENDERBUFFER, depthRb);
1018 glGetRenderbufferParameteriv(GL_RENDERBUFFER,
1019 GL_RENDERBUFFER_WIDTH, &w);
1020 glGetRenderbufferParameteriv(GL_RENDERBUFFER,
1021 GL_RENDERBUFFER_HEIGHT, &h);
1022 glGetRenderbufferParameteriv(GL_RENDERBUFFER,
1023 GL_RENDERBUFFER_INTERNAL_FORMAT, &format);
1025 glGenRenderbuffers(1, &rbs[*numRbs]);
1026 glBindRenderbuffer(GL_RENDERBUFFER, rbs[*numRbs]);
1027 glRenderbufferStorage(GL_RENDERBUFFER, format, w, h);
1028 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
1029 GL_RENDERBUFFER, rbs[*numRbs]);
1030 glBindFramebuffer(GL_READ_FRAMEBUFFER, oldFbo);
1031 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
1032 glBlitFramebuffer(0, 0, w, h, 0, 0, w, h,
1033 GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
1034 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1038 glBindRenderbuffer(GL_RENDERBUFFER, depthRb);
1039 glGetRenderbufferParameteriv(GL_RENDERBUFFER,
1040 GL_RENDERBUFFER_WIDTH, &w);
1041 glGetRenderbufferParameteriv(GL_RENDERBUFFER,
1042 GL_RENDERBUFFER_HEIGHT, &h);
1043 glGetRenderbufferParameteriv(GL_RENDERBUFFER,
1044 GL_RENDERBUFFER_INTERNAL_FORMAT, &format);
1046 glGenRenderbuffers(1, &rbs[*numRbs]);
1047 glBindRenderbuffer(GL_RENDERBUFFER, rbs[*numRbs]);
1048 glRenderbufferStorage(GL_RENDERBUFFER, format, w, h);
1049 glFramebufferRenderbuffer(GL_FRAMEBUFFER,
1050 GL_DEPTH_ATTACHMENT,
1051 GL_RENDERBUFFER, rbs[*numRbs]);
1052 glBindFramebuffer(GL_READ_FRAMEBUFFER, oldFbo);
1053 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
1054 glDrawBuffer(GL_DEPTH_ATTACHMENT);
1055 glReadBuffer(GL_DEPTH_ATTACHMENT);
1056 glBlitFramebuffer(0, 0, w, h, 0, 0, w, h,
1057 GL_DEPTH_BUFFER_BIT, GL_NEAREST);
1061 glBindRenderbuffer(GL_RENDERBUFFER, stencilRb);
1062 glGetRenderbufferParameteriv(GL_RENDERBUFFER,
1063 GL_RENDERBUFFER_WIDTH, &w);
1064 glGetRenderbufferParameteriv(GL_RENDERBUFFER,
1065 GL_RENDERBUFFER_HEIGHT, &h);
1066 glGetRenderbufferParameteriv(GL_RENDERBUFFER,
1067 GL_RENDERBUFFER_INTERNAL_FORMAT, &format);
1069 glGenRenderbuffers(1, &rbs[*numRbs]);
1070 glBindRenderbuffer(GL_RENDERBUFFER, rbs[*numRbs]);
1071 glRenderbufferStorage(GL_RENDERBUFFER, format, w, h);
1072 glFramebufferRenderbuffer(GL_FRAMEBUFFER,
1073 GL_STENCIL_ATTACHMENT,
1074 GL_RENDERBUFFER, rbs[*numRbs]);
1075 glBindFramebuffer(GL_READ_FRAMEBUFFER, oldFbo);
1076 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
1077 glDrawBuffer(GL_STENCIL_ATTACHMENT);
1078 glReadBuffer(GL_STENCIL_ATTACHMENT);
1079 glBlitFramebuffer(0, 0, w, h, 0, 0, w, h,
1080 GL_STENCIL_BUFFER_BIT, GL_NEAREST);
1090 * Dump images of current draw drawable/window.
1093 dumpDrawableImages(JSONWriter &json)
1095 GLint width, height;
1097 if (!getDrawableBounds(&width, &height)) {
1101 GLint draw_buffer = GL_NONE;
1102 glGetIntegerv(GL_DRAW_BUFFER, &draw_buffer);
1103 glReadBuffer(draw_buffer);
1105 if (draw_buffer != GL_NONE) {
1106 GLint read_buffer = GL_NONE;
1107 glGetIntegerv(GL_READ_BUFFER, &read_buffer);
1109 GLint alpha_bits = 0;
1110 glGetIntegerv(GL_ALPHA_BITS, &alpha_bits);
1111 GLenum format = alpha_bits ? GL_RGBA : GL_RGB;
1112 json.beginMember(enumToString(draw_buffer));
1113 dumpReadBufferImage(json, width, height, format);
1116 glReadBuffer(read_buffer);
1119 GLint depth_bits = 0;
1120 glGetIntegerv(GL_DEPTH_BITS, &depth_bits);
1122 json.beginMember("GL_DEPTH_COMPONENT");
1123 dumpReadBufferImage(json, width, height, GL_DEPTH_COMPONENT);
1127 GLint stencil_bits = 0;
1128 glGetIntegerv(GL_STENCIL_BITS, &stencil_bits);
1130 json.beginMember("GL_STENCIL_INDEX");
1131 dumpReadBufferImage(json, width, height, GL_STENCIL_INDEX);
1136 * Dump the specified framebuffer attachment.
1138 * In the case of a color attachment, it assumes it is already bound for read.
1141 dumpFramebufferAttachment(JSONWriter &json, GLenum target, GLenum attachment, GLenum format)
1143 GLint width = 0, height = 0;
1144 if (!getFramebufferAttachmentSize(target, attachment, &width, &height)) {
1148 json.beginMember(enumToString(attachment));
1149 dumpReadBufferImage(json, width, height, format);
1155 dumpFramebufferAttachments(JSONWriter &json, GLenum target)
1157 GLint read_framebuffer = 0;
1158 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &read_framebuffer);
1160 GLint read_buffer = GL_NONE;
1161 glGetIntegerv(GL_READ_BUFFER, &read_buffer);
1163 GLint max_draw_buffers = 1;
1164 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &max_draw_buffers);
1165 GLint max_color_attachments = 0;
1166 glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &max_color_attachments);
1168 for (GLint i = 0; i < max_draw_buffers; ++i) {
1169 GLint draw_buffer = GL_NONE;
1170 glGetIntegerv(GL_DRAW_BUFFER0 + i, &draw_buffer);
1171 if (draw_buffer != GL_NONE) {
1172 glReadBuffer(draw_buffer);
1174 if (draw_buffer >= GL_COLOR_ATTACHMENT0 && draw_buffer < GL_COLOR_ATTACHMENT0 + max_color_attachments) {
1175 attachment = draw_buffer;
1177 std::cerr << "warning: unexpected GL_DRAW_BUFFER" << i << " = " << draw_buffer << "\n";
1178 attachment = GL_COLOR_ATTACHMENT0;
1180 GLint alpha_size = 0;
1181 glGetFramebufferAttachmentParameteriv(target, attachment,
1182 GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE,
1184 GLenum format = alpha_size ? GL_RGBA : GL_RGB;
1185 dumpFramebufferAttachment(json, target, attachment, format);
1189 glReadBuffer(read_buffer);
1191 dumpFramebufferAttachment(json, target, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT);
1192 dumpFramebufferAttachment(json, target, GL_STENCIL_ATTACHMENT, GL_STENCIL_INDEX);
1194 glBindFramebuffer(GL_READ_FRAMEBUFFER, read_framebuffer);
1199 dumpFramebuffer(JSONWriter &json)
1201 json.beginMember("framebuffer");
1204 GLint boundDrawFbo = 0, boundReadFbo = 0;
1205 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundDrawFbo);
1206 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &boundReadFbo);
1207 if (!boundDrawFbo) {
1208 dumpDrawableImages(json);
1210 GLint colorRb = 0, stencilRb = 0, depthRb = 0;
1211 GLint draw_buffer0 = GL_NONE;
1212 glGetIntegerv(GL_DRAW_BUFFER0, &draw_buffer0);
1213 bool multisample = false;
1216 glGetIntegerv(GL_RENDERBUFFER_BINDING, &boundRb);
1219 glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, draw_buffer0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &object_type);
1220 if (object_type == GL_RENDERBUFFER) {
1221 glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, draw_buffer0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &colorRb);
1222 glBindRenderbuffer(GL_RENDERBUFFER, colorRb);
1224 glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES, &samples);
1230 glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &object_type);
1231 if (object_type == GL_RENDERBUFFER) {
1232 glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &depthRb);
1233 glBindRenderbuffer(GL_RENDERBUFFER, depthRb);
1235 glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES, &samples);
1241 glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &object_type);
1242 if (object_type == GL_RENDERBUFFER) {
1243 glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &stencilRb);
1244 glBindRenderbuffer(GL_RENDERBUFFER, stencilRb);
1246 glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES, &samples);
1252 glBindRenderbuffer(GL_RENDERBUFFER, boundRb);
1259 // glReadPixels doesnt support multisampled buffers so we need
1260 // to blit the fbo to a temporary one
1261 fboCopy = downsampledFramebuffer(boundDrawFbo, draw_buffer0,
1262 colorRb, depthRb, stencilRb,
1266 dumpFramebufferAttachments(json, GL_DRAW_FRAMEBUFFER);
1269 glBindRenderbuffer(GL_RENDERBUFFER_BINDING, boundRb);
1270 glDeleteRenderbuffers(numRbs, rbs);
1271 glDeleteFramebuffers(1, &fboCopy);
1274 glBindFramebuffer(GL_READ_FRAMEBUFFER, boundReadFbo);
1275 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, boundDrawFbo);
1279 json.endMember(); // framebuffer
1283 static const GLenum bindings[] = {
1286 GL_PIXEL_PACK_BUFFER_BINDING,
1287 GL_PIXEL_UNPACK_BUFFER_BINDING,
1288 GL_TEXTURE_BINDING_1D,
1289 GL_TEXTURE_BINDING_2D,
1290 GL_TEXTURE_BINDING_3D,
1291 GL_TEXTURE_BINDING_RECTANGLE,
1292 GL_TEXTURE_BINDING_CUBE_MAP,
1293 GL_DRAW_FRAMEBUFFER_BINDING,
1294 GL_READ_FRAMEBUFFER_BINDING,
1295 GL_RENDERBUFFER_BINDING,
1307 #define NUM_BINDINGS sizeof(bindings)/sizeof(bindings[0])
1310 void dumpCurrentContext(std::ostream &os)
1312 JSONWriter json(os);
1315 GLint old_bindings[NUM_BINDINGS];
1316 for (unsigned i = 0; i < NUM_BINDINGS; ++i) {
1317 old_bindings[i] = 0;
1318 glGetIntegerv(bindings[i], &old_bindings[i]);
1322 dumpParameters(json);
1326 dumpFramebuffer(json);
1329 for (unsigned i = 0; i < NUM_BINDINGS; ++i) {
1330 GLint new_binding = 0;
1331 glGetIntegerv(bindings[i], &new_binding);
1332 if (new_binding != old_bindings[i]) {
1333 std::cerr << "warning: " << enumToString(bindings[i]) << " was clobbered\n";
1341 } /* namespace glstate */