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 **************************************************************************/
37 #include "glstate.hpp"
42 #include <Carbon/Carbon.h>
48 OSStatus CGSGetSurfaceBounds(CGSConnectionID, CGWindowID, CGSSurfaceID, CGRect *);
54 #endif /* __APPLE__ */
61 resetPixelPackState(void) {
62 glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
63 glPixelStorei(GL_PACK_SWAP_BYTES, GL_FALSE);
64 glPixelStorei(GL_PACK_LSB_FIRST, GL_FALSE);
65 glPixelStorei(GL_PACK_ROW_LENGTH, 0);
66 glPixelStorei(GL_PACK_IMAGE_HEIGHT, 0);
67 glPixelStorei(GL_PACK_SKIP_ROWS, 0);
68 glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
69 glPixelStorei(GL_PACK_SKIP_IMAGES, 0);
70 glPixelStorei(GL_PACK_ALIGNMENT, 1);
71 glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
76 restorePixelPackState(void) {
81 // Mapping from shader type to shader source, used to accumulated the sources
82 // of different shaders with same type.
83 typedef std::map<std::string, std::string> ShaderMap;
87 getShaderSource(ShaderMap &shaderMap, GLuint shader)
93 GLint shader_type = 0;
94 glGetShaderiv(shader, GL_SHADER_TYPE, &shader_type);
99 GLint source_length = 0;
100 glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &source_length);
101 if (!source_length) {
105 GLchar *source = new GLchar[source_length];
108 glGetShaderSource(shader, source_length, &length, source);
110 shaderMap[enumToString(shader_type)] += source;
117 getShaderObjSource(ShaderMap &shaderMap, GLhandleARB shaderObj)
123 GLint shader_type = 0;
124 glGetObjectParameterivARB(shaderObj, GL_OBJECT_TYPE_ARB, &shader_type);
129 GLint source_length = 0;
130 glGetObjectParameterivARB(shaderObj, GL_OBJECT_SHADER_SOURCE_LENGTH_ARB, &source_length);
131 if (!source_length) {
135 GLcharARB *source = new GLcharARB[source_length];
138 glGetShaderSource(shaderObj, source_length, &length, source);
140 shaderMap[enumToString(shader_type)] += source;
147 dumpCurrentProgram(JSONWriter &json)
150 glGetIntegerv(GL_CURRENT_PROGRAM, &program);
155 GLint attached_shaders = 0;
156 glGetProgramiv(program, GL_ATTACHED_SHADERS, &attached_shaders);
157 if (!attached_shaders) {
163 GLuint *shaders = new GLuint[attached_shaders];
165 glGetAttachedShaders(program, attached_shaders, &count, shaders);
166 std::sort(shaders, shaders + count);
167 for (GLsizei i = 0; i < count; ++ i) {
168 getShaderSource(shaderMap, shaders[i]);
172 for (ShaderMap::const_iterator it = shaderMap.begin(); it != shaderMap.end(); ++it) {
173 json.beginMember(it->first);
174 json.writeString(it->second);
181 dumpCurrentProgramObj(JSONWriter &json)
183 GLhandleARB programObj = glGetHandleARB(GL_PROGRAM_OBJECT_ARB);
188 GLint attached_shaders = 0;
189 glGetProgramivARB(programObj, GL_OBJECT_ATTACHED_OBJECTS_ARB, &attached_shaders);
190 if (!attached_shaders) {
196 GLhandleARB *shaderObjs = new GLhandleARB[attached_shaders];
198 glGetAttachedObjectsARB(programObj, attached_shaders, &count, shaderObjs);
199 std::sort(shaderObjs, shaderObjs + count);
200 for (GLsizei i = 0; i < count; ++ i) {
201 getShaderObjSource(shaderMap, shaderObjs[i]);
203 delete [] shaderObjs;
205 for (ShaderMap::const_iterator it = shaderMap.begin(); it != shaderMap.end(); ++it) {
206 json.beginMember(it->first);
207 json.writeString(it->second);
213 dumpUniform(JSONWriter &json, GLint program, GLenum type, const GLchar *name) {
220 basicType = GL_FLOAT;
224 basicType = GL_FLOAT;
232 GLint location = glGetUniformLocation(program, name);
234 GLfloat fvalues[4*4];
239 glGetUniformfv(program, location, fvalues);
240 for (GLint index = 0; index < length; ++index) {
241 json.writeNumber(fvalues[index]);
249 dumpCurrentProgramUniforms(JSONWriter &json)
252 glGetIntegerv(GL_CURRENT_PROGRAM, &program);
257 GLint active_uniforms = 0;
258 glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &active_uniforms);
259 if (!active_uniforms) {
263 GLint active_uniform_max_length = 0;
264 glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &active_uniform_max_length);
265 GLchar *name = new GLchar[active_uniform_max_length];
270 for (GLint index = 0; index < active_uniforms; ++index) {
273 GLenum type = GL_NONE;
274 glGetActiveUniform(program, index, active_uniform_max_length, &length, &size, &type, name);
277 json.beginMember(name);
279 json.writeNumberMember("size", size);
280 json.writeStringMember("type", enumToString(type));
282 json.beginMember("value");
283 dumpUniform(json, program, type, name);
295 dumpArbProgram(JSONWriter &json, GLenum target)
297 if (!glIsEnabled(target)) {
301 GLint program_length = 0;
302 glGetProgramivARB(target, GL_PROGRAM_LENGTH_ARB, &program_length);
303 if (!program_length) {
307 GLchar *source = new GLchar[program_length + 1];
309 glGetProgramStringARB(target, GL_PROGRAM_STRING_ARB, source);
310 source[program_length] = 0;
312 json.beginMember(enumToString(target));
313 json.writeString(source);
321 dumpShaders(JSONWriter &json)
323 json.beginMember("shaders");
325 dumpCurrentProgram(json);
326 dumpCurrentProgramObj(json);
327 dumpArbProgram(json, GL_FRAGMENT_PROGRAM_ARB);
328 dumpArbProgram(json, GL_VERTEX_PROGRAM_ARB);
330 json.endMember(); // shaders
335 dumpUniforms(JSONWriter &json)
337 json.beginMember("uniforms");
339 dumpCurrentProgramUniforms(json);
341 json.endMember(); // uniforms
346 dumpTextureImage(JSONWriter &json, GLenum target, GLint level)
348 GLint width, height = 1, depth = 1;
351 glGetTexLevelParameteriv(target, level, GL_TEXTURE_WIDTH, &width);
353 if (target != GL_TEXTURE_1D) {
355 glGetTexLevelParameteriv(target, level, GL_TEXTURE_HEIGHT, &height);
356 if (target == GL_TEXTURE_3D) {
358 glGetTexLevelParameteriv(target, level, GL_TEXTURE_DEPTH, &depth);
362 if (width <= 0 || height <= 0 || depth <= 0) {
367 GLint active_texture = GL_TEXTURE0;
368 glGetIntegerv(GL_ACTIVE_TEXTURE, &active_texture);
369 snprintf(label, sizeof label, "%s, %s, level = %i", enumToString(active_texture), enumToString(target), level);
371 json.beginMember(label);
375 // Tell the GUI this is no ordinary object, but an image
376 json.writeStringMember("__class__", "image");
378 json.writeNumberMember("__width__", width);
379 json.writeNumberMember("__height__", height);
380 json.writeNumberMember("__depth__", depth);
382 // Hardcoded for now, but we could chose types more adequate to the
383 // texture internal format
384 json.writeStringMember("__type__", "uint8");
385 json.writeBoolMember("__normalized__", true);
386 json.writeNumberMember("__channels__", 4);
388 GLubyte *pixels = new GLubyte[depth*width*height*4];
390 resetPixelPackState();
392 glGetTexImage(target, level, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
394 restorePixelPackState();
396 json.beginMember("__data__");
399 Image::writePixelsToBuffer(pixels, width, height, 4, false, &pngBuffer, &pngBufferSize);
400 json.writeBase64(pngBuffer, pngBufferSize);
402 json.endMember(); // __data__
411 dumpTexture(JSONWriter &json, GLenum target, GLenum binding)
413 GLint texture_binding = 0;
414 glGetIntegerv(binding, &texture_binding);
415 if (!glIsEnabled(target) && !texture_binding) {
421 GLint width = 0, height = 0;
422 glGetTexLevelParameteriv(target, level, GL_TEXTURE_WIDTH, &width);
423 glGetTexLevelParameteriv(target, level, GL_TEXTURE_HEIGHT, &height);
424 if (!width || !height) {
428 if (target == GL_TEXTURE_CUBE_MAP) {
429 for (int face = 0; face < 6; ++face) {
430 dumpTextureImage(json, GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level);
433 dumpTextureImage(json, target, level);
442 dumpTextures(JSONWriter &json)
444 json.beginMember("textures");
446 GLint active_texture = GL_TEXTURE0;
447 glGetIntegerv(GL_ACTIVE_TEXTURE, &active_texture);
448 GLint max_texture_coords = 0;
449 glGetIntegerv(GL_MAX_TEXTURE_COORDS, &max_texture_coords);
450 GLint max_combined_texture_image_units = 0;
451 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_combined_texture_image_units);
452 GLint max_units = std::max(max_combined_texture_image_units, max_texture_coords);
453 for (GLint unit = 0; unit < max_units; ++unit) {
454 GLenum texture = GL_TEXTURE0 + unit;
455 glActiveTexture(texture);
456 dumpTexture(json, GL_TEXTURE_1D, GL_TEXTURE_BINDING_1D);
457 dumpTexture(json, GL_TEXTURE_2D, GL_TEXTURE_BINDING_2D);
458 dumpTexture(json, GL_TEXTURE_3D, GL_TEXTURE_BINDING_3D);
459 dumpTexture(json, GL_TEXTURE_RECTANGLE, GL_TEXTURE_BINDING_RECTANGLE);
460 dumpTexture(json, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BINDING_CUBE_MAP);
462 glActiveTexture(active_texture);
464 json.endMember(); // textures
469 getDrawableBounds(GLint *width, GLint *height) {
472 HDC hDC = wglGetCurrentDC();
477 HWND hWnd = WindowFromDC(hDC);
480 if (!GetClientRect(hWnd, &rect)) {
484 *width = rect.right - rect.left;
485 *height = rect.bottom - rect.top;
487 #elif defined(__APPLE__)
489 CGLContextObj ctx = CGLGetCurrentContext();
498 if (CGLGetSurface(ctx, &cid, &wid, &sid) != kCGLNoError) {
504 if (CGSGetSurfaceBounds(cid, wid, sid, &rect) != 0) {
508 *width = rect.size.width;
509 *height = rect.size.height;
517 unsigned int w, h, bw, depth;
519 display = glXGetCurrentDisplay();
524 drawable = glXGetCurrentDrawable();
525 if (drawable == None) {
529 if (!XGetGeometry(display, drawable, &root, &x, &y, &w, &h, &bw, &depth)) {
542 static const GLenum texture_bindings[][2] = {
543 {GL_TEXTURE_1D, GL_TEXTURE_BINDING_1D},
544 {GL_TEXTURE_2D, GL_TEXTURE_BINDING_2D},
545 {GL_TEXTURE_3D, GL_TEXTURE_BINDING_3D},
546 {GL_TEXTURE_RECTANGLE, GL_TEXTURE_BINDING_RECTANGLE},
547 {GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BINDING_CUBE_MAP}
552 bindTexture(GLint texture, GLenum &target, GLint &bound_texture)
555 for (unsigned i = 0; i < sizeof(texture_bindings)/sizeof(texture_bindings[0]); ++i) {
556 target = texture_bindings[i][0];
558 GLenum binding = texture_bindings[i][1];
560 while (glGetError() != GL_NO_ERROR)
563 glGetIntegerv(binding, &bound_texture);
564 glBindTexture(target, texture);
566 if (glGetError() == GL_NO_ERROR) {
570 glBindTexture(target, bound_texture);
580 getTextureLevelSize(GLint texture, GLint level, GLint *width, GLint *height)
586 GLint bound_texture = 0;
587 if (!bindTexture(texture, target, bound_texture)) {
591 glGetTexLevelParameteriv(target, level, GL_TEXTURE_WIDTH, width);
592 glGetTexLevelParameteriv(target, level, GL_TEXTURE_HEIGHT, height);
594 glBindTexture(target, bound_texture);
596 return *width > 0 && *height > 0;
601 getRenderbufferSize(GLint renderbuffer, GLint *width, GLint *height)
603 GLint bound_renderbuffer = 0;
604 glGetIntegerv(GL_RENDERBUFFER_BINDING, &bound_renderbuffer);
605 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
609 glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, width);
610 glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, height);
612 glBindRenderbuffer(GL_RENDERBUFFER, bound_renderbuffer);
614 return *width > 0 && *height > 0;
619 getFramebufferAttachmentSize(GLenum target, GLenum attachment, GLint *width, GLint *height)
621 GLint object_type = GL_NONE;
622 glGetFramebufferAttachmentParameteriv(target, attachment,
623 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE,
625 if (object_type == GL_NONE) {
629 GLint object_name = 0;
630 glGetFramebufferAttachmentParameteriv(target, attachment,
631 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
633 if (object_name == 0) {
637 if (object_type == GL_RENDERBUFFER) {
638 return getRenderbufferSize(object_name, width, height);
639 } else if (object_type == GL_TEXTURE) {
640 GLint texture_level = 0;
641 glGetFramebufferAttachmentParameteriv(target, attachment,
642 GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL,
644 return getTextureLevelSize(object_name, texture_level, width, height);
646 std::cerr << "warning: unexpected GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE = " << object_type << "\n";
653 getDrawBufferImage(GLenum format) {
654 GLint channels = __gl_format_channels(format);
659 GLint draw_framebuffer = 0;
660 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &draw_framebuffer);
662 GLint draw_buffer = GL_NONE;
664 if (draw_framebuffer) {
665 glGetIntegerv(GL_DRAW_BUFFER0, &draw_buffer);
666 if (draw_buffer == GL_NONE) {
670 if (!getFramebufferAttachmentSize(GL_DRAW_FRAMEBUFFER, draw_buffer, &width, &height)) {
674 glGetIntegerv(GL_DRAW_BUFFER, &draw_buffer);
675 if (draw_buffer == GL_NONE) {
679 if (!getDrawableBounds(&width, &height)) {
684 Image::Image *image = new Image::Image(width, height, channels, true);
689 while (glGetError() != GL_NO_ERROR) {}
691 GLint read_framebuffer = 0;
692 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &read_framebuffer);
693 glBindFramebuffer(GL_READ_FRAMEBUFFER, draw_framebuffer);
695 GLint read_buffer = 0;
696 glGetIntegerv(GL_READ_BUFFER, &read_buffer);
697 glReadBuffer(draw_buffer);
699 // TODO: reset imaging state too
700 resetPixelPackState();
702 glReadPixels(0, 0, width, height, format, GL_UNSIGNED_BYTE, image->pixels);
704 restorePixelPackState();
705 glReadBuffer(read_buffer);
706 glBindFramebuffer(GL_READ_FRAMEBUFFER, read_framebuffer);
708 GLenum error = glGetError();
709 if (error != GL_NO_ERROR) {
711 std::cerr << "warning: " << enumToString(error) << " while getting snapshot\n";
712 error = glGetError();
713 } while(error != GL_NO_ERROR);
723 * Dump the image of the currently bound read buffer.
726 dumpReadBufferImage(JSONWriter &json, GLint width, GLint height, GLenum format)
728 GLint channels = __gl_format_channels(format);
732 // Tell the GUI this is no ordinary object, but an image
733 json.writeStringMember("__class__", "image");
735 json.writeNumberMember("__width__", width);
736 json.writeNumberMember("__height__", height);
737 json.writeNumberMember("__depth__", 1);
739 // Hardcoded for now, but we could chose types more adequate to the
740 // texture internal format
741 json.writeStringMember("__type__", "uint8");
742 json.writeBoolMember("__normalized__", true);
743 json.writeNumberMember("__channels__", channels);
745 GLubyte *pixels = new GLubyte[width*height*channels];
747 // TODO: reset imaging state too
748 resetPixelPackState();
750 glReadPixels(0, 0, width, height, format, GL_UNSIGNED_BYTE, pixels);
752 restorePixelPackState();
754 json.beginMember("__data__");
757 Image::writePixelsToBuffer(pixels, width, height, channels, false, &pngBuffer, &pngBufferSize);
758 //std::cerr <<" Before = "<<(width * height * channels * sizeof *pixels)
759 // <<", after = "<<pngBufferSize << ", ratio = " << double(width * height * channels * sizeof *pixels)/pngBufferSize;
760 json.writeBase64(pngBuffer, pngBufferSize);
762 json.endMember(); // __data__
770 downsampledFramebuffer(GLuint oldFbo, GLint drawbuffer,
771 GLint colorRb, GLint depthRb, GLint stencilRb,
772 GLuint *rbs, GLint *numRbs)
780 glGenFramebuffers(1, &fbo);
781 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
783 glBindRenderbuffer(GL_RENDERBUFFER, colorRb);
784 glGetRenderbufferParameteriv(GL_RENDERBUFFER,
785 GL_RENDERBUFFER_WIDTH, &w);
786 glGetRenderbufferParameteriv(GL_RENDERBUFFER,
787 GL_RENDERBUFFER_HEIGHT, &h);
788 glGetRenderbufferParameteriv(GL_RENDERBUFFER,
789 GL_RENDERBUFFER_INTERNAL_FORMAT, &format);
791 glGenRenderbuffers(1, &rbs[*numRbs]);
792 glBindRenderbuffer(GL_RENDERBUFFER, rbs[*numRbs]);
793 glRenderbufferStorage(GL_RENDERBUFFER, format, w, h);
794 glFramebufferRenderbuffer(GL_FRAMEBUFFER, drawbuffer,
795 GL_RENDERBUFFER, rbs[*numRbs]);
797 glBindFramebuffer(GL_READ_FRAMEBUFFER, oldFbo);
798 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
799 glDrawBuffer(drawbuffer);
800 glReadBuffer(drawbuffer);
801 glBlitFramebuffer(0, 0, w, h, 0, 0, w, h,
802 GL_COLOR_BUFFER_BIT, GL_NEAREST);
803 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
806 if (stencilRb == depthRb && stencilRb) {
807 //combined depth and stencil buffer
808 glBindRenderbuffer(GL_RENDERBUFFER, depthRb);
809 glGetRenderbufferParameteriv(GL_RENDERBUFFER,
810 GL_RENDERBUFFER_WIDTH, &w);
811 glGetRenderbufferParameteriv(GL_RENDERBUFFER,
812 GL_RENDERBUFFER_HEIGHT, &h);
813 glGetRenderbufferParameteriv(GL_RENDERBUFFER,
814 GL_RENDERBUFFER_INTERNAL_FORMAT, &format);
816 glGenRenderbuffers(1, &rbs[*numRbs]);
817 glBindRenderbuffer(GL_RENDERBUFFER, rbs[*numRbs]);
818 glRenderbufferStorage(GL_RENDERBUFFER, format, w, h);
819 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
820 GL_RENDERBUFFER, rbs[*numRbs]);
821 glBindFramebuffer(GL_READ_FRAMEBUFFER, oldFbo);
822 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
823 glBlitFramebuffer(0, 0, w, h, 0, 0, w, h,
824 GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
825 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
829 glBindRenderbuffer(GL_RENDERBUFFER, depthRb);
830 glGetRenderbufferParameteriv(GL_RENDERBUFFER,
831 GL_RENDERBUFFER_WIDTH, &w);
832 glGetRenderbufferParameteriv(GL_RENDERBUFFER,
833 GL_RENDERBUFFER_HEIGHT, &h);
834 glGetRenderbufferParameteriv(GL_RENDERBUFFER,
835 GL_RENDERBUFFER_INTERNAL_FORMAT, &format);
837 glGenRenderbuffers(1, &rbs[*numRbs]);
838 glBindRenderbuffer(GL_RENDERBUFFER, rbs[*numRbs]);
839 glRenderbufferStorage(GL_RENDERBUFFER, format, w, h);
840 glFramebufferRenderbuffer(GL_FRAMEBUFFER,
842 GL_RENDERBUFFER, rbs[*numRbs]);
843 glBindFramebuffer(GL_READ_FRAMEBUFFER, oldFbo);
844 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
845 glDrawBuffer(GL_DEPTH_ATTACHMENT);
846 glReadBuffer(GL_DEPTH_ATTACHMENT);
847 glBlitFramebuffer(0, 0, w, h, 0, 0, w, h,
848 GL_DEPTH_BUFFER_BIT, GL_NEAREST);
852 glBindRenderbuffer(GL_RENDERBUFFER, stencilRb);
853 glGetRenderbufferParameteriv(GL_RENDERBUFFER,
854 GL_RENDERBUFFER_WIDTH, &w);
855 glGetRenderbufferParameteriv(GL_RENDERBUFFER,
856 GL_RENDERBUFFER_HEIGHT, &h);
857 glGetRenderbufferParameteriv(GL_RENDERBUFFER,
858 GL_RENDERBUFFER_INTERNAL_FORMAT, &format);
860 glGenRenderbuffers(1, &rbs[*numRbs]);
861 glBindRenderbuffer(GL_RENDERBUFFER, rbs[*numRbs]);
862 glRenderbufferStorage(GL_RENDERBUFFER, format, w, h);
863 glFramebufferRenderbuffer(GL_FRAMEBUFFER,
864 GL_STENCIL_ATTACHMENT,
865 GL_RENDERBUFFER, rbs[*numRbs]);
866 glBindFramebuffer(GL_READ_FRAMEBUFFER, oldFbo);
867 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
868 glDrawBuffer(GL_STENCIL_ATTACHMENT);
869 glReadBuffer(GL_STENCIL_ATTACHMENT);
870 glBlitFramebuffer(0, 0, w, h, 0, 0, w, h,
871 GL_STENCIL_BUFFER_BIT, GL_NEAREST);
881 * Dump images of current draw drawable/window.
884 dumpDrawableImages(JSONWriter &json)
888 if (!getDrawableBounds(&width, &height)) {
892 GLint draw_buffer = GL_NONE;
893 glGetIntegerv(GL_DRAW_BUFFER, &draw_buffer);
894 glReadBuffer(draw_buffer);
896 if (draw_buffer != GL_NONE) {
897 GLint read_buffer = GL_NONE;
898 glGetIntegerv(GL_READ_BUFFER, &read_buffer);
900 GLint alpha_bits = 0;
901 glGetIntegerv(GL_ALPHA_BITS, &alpha_bits);
902 GLenum format = alpha_bits ? GL_RGBA : GL_RGB;
903 json.beginMember(enumToString(draw_buffer));
904 dumpReadBufferImage(json, width, height, format);
907 glReadBuffer(read_buffer);
910 GLint depth_bits = 0;
911 glGetIntegerv(GL_DEPTH_BITS, &depth_bits);
913 json.beginMember("GL_DEPTH_COMPONENT");
914 dumpReadBufferImage(json, width, height, GL_DEPTH_COMPONENT);
918 GLint stencil_bits = 0;
919 glGetIntegerv(GL_STENCIL_BITS, &stencil_bits);
921 json.beginMember("GL_STENCIL_INDEX");
922 dumpReadBufferImage(json, width, height, GL_STENCIL_INDEX);
927 * Dump the specified framebuffer attachment.
929 * In the case of a color attachment, it assumes it is already bound for read.
932 dumpFramebufferAttachment(JSONWriter &json, GLenum target, GLenum attachment, GLenum format)
934 GLint width = 0, height = 0;
935 if (!getFramebufferAttachmentSize(target, attachment, &width, &height)) {
939 json.beginMember(enumToString(attachment));
940 dumpReadBufferImage(json, width, height, format);
946 dumpFramebufferAttachments(JSONWriter &json, GLenum target)
948 GLint read_framebuffer = 0;
949 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &read_framebuffer);
951 GLint read_buffer = GL_NONE;
952 glGetIntegerv(GL_READ_BUFFER, &read_buffer);
954 GLint max_draw_buffers = 1;
955 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &max_draw_buffers);
956 GLint max_color_attachments = 0;
957 glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &max_color_attachments);
959 for (GLint i = 0; i < max_draw_buffers; ++i) {
960 GLint draw_buffer = GL_NONE;
961 glGetIntegerv(GL_DRAW_BUFFER0 + i, &draw_buffer);
962 if (draw_buffer != GL_NONE) {
963 glReadBuffer(draw_buffer);
965 if (draw_buffer >= GL_COLOR_ATTACHMENT0 && draw_buffer < GL_COLOR_ATTACHMENT0 + max_color_attachments) {
966 attachment = draw_buffer;
968 std::cerr << "warning: unexpected GL_DRAW_BUFFER" << i << " = " << draw_buffer << "\n";
969 attachment = GL_COLOR_ATTACHMENT0;
971 GLint alpha_size = 0;
972 glGetFramebufferAttachmentParameteriv(target, attachment,
973 GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE,
975 GLenum format = alpha_size ? GL_RGBA : GL_RGB;
976 dumpFramebufferAttachment(json, target, attachment, format);
980 glReadBuffer(read_buffer);
982 dumpFramebufferAttachment(json, target, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT);
983 dumpFramebufferAttachment(json, target, GL_STENCIL_ATTACHMENT, GL_STENCIL_INDEX);
985 glBindFramebuffer(GL_READ_FRAMEBUFFER, read_framebuffer);
990 dumpFramebuffer(JSONWriter &json)
992 json.beginMember("framebuffer");
995 GLint boundDrawFbo = 0, boundReadFbo = 0;
996 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundDrawFbo);
997 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &boundReadFbo);
999 dumpDrawableImages(json);
1001 GLint colorRb = 0, stencilRb = 0, depthRb = 0;
1002 GLint draw_buffer0 = GL_NONE;
1003 glGetIntegerv(GL_DRAW_BUFFER0, &draw_buffer0);
1004 bool multisample = false;
1007 glGetIntegerv(GL_RENDERBUFFER_BINDING, &boundRb);
1010 glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, draw_buffer0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &object_type);
1011 if (object_type == GL_RENDERBUFFER) {
1012 glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, draw_buffer0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &colorRb);
1013 glBindRenderbuffer(GL_RENDERBUFFER, colorRb);
1015 glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES, &samples);
1021 glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &object_type);
1022 if (object_type == GL_RENDERBUFFER) {
1023 glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &depthRb);
1024 glBindRenderbuffer(GL_RENDERBUFFER, depthRb);
1026 glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES, &samples);
1032 glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &object_type);
1033 if (object_type == GL_RENDERBUFFER) {
1034 glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &stencilRb);
1035 glBindRenderbuffer(GL_RENDERBUFFER, stencilRb);
1037 glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES, &samples);
1043 glBindRenderbuffer(GL_RENDERBUFFER, boundRb);
1050 // glReadPixels doesnt support multisampled buffers so we need
1051 // to blit the fbo to a temporary one
1052 fboCopy = downsampledFramebuffer(boundDrawFbo, draw_buffer0,
1053 colorRb, depthRb, stencilRb,
1057 dumpFramebufferAttachments(json, GL_DRAW_FRAMEBUFFER);
1060 glBindRenderbuffer(GL_RENDERBUFFER_BINDING, boundRb);
1061 glDeleteRenderbuffers(numRbs, rbs);
1062 glDeleteFramebuffers(1, &fboCopy);
1065 glBindFramebuffer(GL_READ_FRAMEBUFFER, boundReadFbo);
1066 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, boundDrawFbo);
1070 json.endMember(); // framebuffer
1074 static const GLenum bindings[] = {
1077 GL_PIXEL_PACK_BUFFER_BINDING,
1078 GL_PIXEL_UNPACK_BUFFER_BINDING,
1079 GL_TEXTURE_BINDING_1D,
1080 GL_TEXTURE_BINDING_2D,
1081 GL_TEXTURE_BINDING_3D,
1082 GL_TEXTURE_BINDING_RECTANGLE,
1083 GL_TEXTURE_BINDING_CUBE_MAP,
1084 GL_DRAW_FRAMEBUFFER_BINDING,
1085 GL_READ_FRAMEBUFFER_BINDING,
1086 GL_RENDERBUFFER_BINDING,
1098 #define NUM_BINDINGS sizeof(bindings)/sizeof(bindings[0])
1101 void dumpCurrentContext(std::ostream &os)
1103 JSONWriter json(os);
1106 GLint old_bindings[NUM_BINDINGS];
1107 for (unsigned i = 0; i < NUM_BINDINGS; ++i) {
1108 old_bindings[i] = 0;
1109 glGetIntegerv(bindings[i], &old_bindings[i]);
1113 dumpParameters(json);
1117 dumpFramebuffer(json);
1120 for (unsigned i = 0; i < NUM_BINDINGS; ++i) {
1121 GLint new_binding = 0;
1122 glGetIntegerv(bindings[i], &new_binding);
1123 if (new_binding != old_bindings[i]) {
1124 std::cerr << "warning: " << enumToString(bindings[i]) << " was clobbered\n";
1132 } /* namespace glstate */