diff options
author | José Fonseca <jose.r.fonseca@gmail.com> | 2011-05-19 10:45:04 +0100 |
---|---|---|
committer | José Fonseca <jose.r.fonseca@gmail.com> | 2011-05-19 10:45:04 +0100 |
commit | 2e3fff6025fac330cbf00c8b81766dcbcf6298b5 (patch) | |
tree | d36d056a1143eb24b01cd45319ae59a394422525 | |
parent | a4d77a9074af5290b0dbbb7fddd99b981f59bc8a (diff) |
Reorganize glstate code.
-rw-r--r-- | .gitignore | 2 | ||||
-rwxr-xr-x | CMakeLists.txt | 5 | ||||
-rw-r--r-- | glretrace_main.cpp | 2 | ||||
-rw-r--r-- | glstate.cpp | 643 | ||||
-rw-r--r-- | glstate.hpp | 15 | ||||
-rw-r--r-- | glstate.py | 629 |
6 files changed, 673 insertions, 623 deletions
@@ -35,7 +35,7 @@ dxsdk glproc.hpp glretrace glretrace_gl.cpp -glstate.cpp +glstate_params.cpp glxtrace.cpp install_manifest.txt qapitrace diff --git a/CMakeLists.txt b/CMakeLists.txt index 41bbd6d9..44b4c84a 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -306,8 +306,8 @@ add_custom_command ( ) add_custom_command ( - OUTPUT glstate.cpp - COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/glstate.py > ${CMAKE_CURRENT_BINARY_DIR}/glstate.cpp + OUTPUT glstate_params.cpp + COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/glstate.py > ${CMAKE_CURRENT_BINARY_DIR}/glstate_params.cpp DEPENDS glstate.py glparams.py gltypes.py stdapi.py ) @@ -323,6 +323,7 @@ add_executable (glretrace glretrace_wgl.cpp glretrace_main.cpp glstate.cpp + glstate_params.cpp retrace.cpp ${glws} image.cpp diff --git a/glretrace_main.cpp b/glretrace_main.cpp index bfab151f..56113efc 100644 --- a/glretrace_main.cpp +++ b/glretrace_main.cpp @@ -203,7 +203,7 @@ static void display(void) { if (!insideGlBeginEnd && drawable && context && call->no >= dump_state) { - glstate::state_dump(std::cout); + glstate::dumpCurrentContext(std::cout); exit(0); } diff --git a/glstate.cpp b/glstate.cpp new file mode 100644 index 00000000..a60c6876 --- /dev/null +++ b/glstate.cpp @@ -0,0 +1,643 @@ +/************************************************************************** + * + * Copyright 2011 Jose Fonseca + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + **************************************************************************/ + + +#include <string.h> +#include <iostream> +#include <algorithm> + +#include "image.hpp" +#include "json.hpp" +#include "glproc.hpp" +#include "glsize.hpp" +#include "glstate.hpp" + + +namespace glstate { + + +static void +dumpShader(JSONWriter &json, GLuint shader) +{ + if (!shader) { + return; + } + + GLint shader_type = 0; + glGetShaderiv(shader, GL_SHADER_TYPE, &shader_type); + if (!shader_type) { + return; + } + + GLint source_length = 0; + glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &source_length); + if (!source_length) { + return; + } + + GLchar *source = new GLchar[source_length]; + GLsizei length = 0; + source[0] = 0; + glGetShaderSource(shader, source_length, &length, source); + + json.beginMember(enumToString(shader_type)); + json.writeString(source); + json.endMember(); + + delete [] source; +} + + +static void +dumpShaderObj(JSONWriter &json, GLhandleARB shaderObj) +{ + if (!shaderObj) { + return; + } + + GLint shader_type = 0; + glGetObjectParameterivARB(shaderObj, GL_OBJECT_TYPE_ARB, &shader_type); + if (!shader_type) { + return; + } + + GLint source_length = 0; + glGetObjectParameterivARB(shaderObj, GL_OBJECT_SHADER_SOURCE_LENGTH_ARB, &source_length); + if (!source_length) { + return; + } + + GLcharARB *source = new GLcharARB[source_length]; + GLsizei length = 0; + source[0] = 0; + glGetShaderSource(shaderObj, source_length, &length, source); + + json.beginMember(enumToString(shader_type)); + json.writeString(source); + json.endMember(); + + delete [] source; +} + + +static inline void +dumpCurrentProgram(JSONWriter &json) +{ + 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; + } + + GLuint *shaders = new GLuint[attached_shaders]; + GLsizei count = 0; + glGetAttachedShaders(program, attached_shaders, &count, shaders); + for (GLsizei i = 0; i < count; ++ i) { + dumpShader(json, shaders[i]); + } + delete [] shaders; +} + + +static inline void +dumpCurrentProgramObj(JSONWriter &json) +{ + GLhandleARB programObj = glGetHandleARB(GL_PROGRAM_OBJECT_ARB); + if (!programObj) { + return; + } + + GLint attached_shaders = 0; + glGetProgramivARB(programObj, GL_OBJECT_ATTACHED_OBJECTS_ARB, &attached_shaders); + if (!attached_shaders) { + return; + } + + GLhandleARB *shaderObjs = new GLhandleARB[attached_shaders]; + GLsizei count = 0; + glGetAttachedObjectsARB(programObj, attached_shaders, &count, shaderObjs); + for (GLsizei i = 0; i < count; ++ i) { + dumpShaderObj(json, shaderObjs[i]); + } + delete [] shaderObjs; +} + + +static inline void +dumpArbProgram(JSONWriter &json, GLenum target) +{ + if (!glIsEnabled(target)) { + return; + } + + GLint program_length = 0; + glGetProgramivARB(target, GL_PROGRAM_LENGTH_ARB, &program_length); + if (!program_length) { + return; + } + + GLchar *source = new GLchar[program_length + 1]; + source[0] = 0; + glGetProgramStringARB(target, GL_PROGRAM_STRING_ARB, source); + source[program_length] = 0; + + json.beginMember(enumToString(target)); + json.writeString(source); + json.endMember(); + + delete [] source; +} + + +static inline void +dumpShaders(JSONWriter &json) +{ + json.beginMember("shaders"); + json.beginObject(); + dumpCurrentProgram(json); + dumpArbProgram(json, GL_FRAGMENT_PROGRAM_ARB); + dumpArbProgram(json, GL_VERTEX_PROGRAM_ARB); + json.endObject(); + json.endMember(); //shaders +} + + +static inline void +dumpTextureImage(JSONWriter &json, GLenum target, GLint level) +{ + GLint width, height = 1, depth = 1; + + width = 0; + glGetTexLevelParameteriv(target, level, GL_TEXTURE_WIDTH, &width); + + 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); + } + } + + if (width <= 0 || height <= 0 || depth <= 0) { + return; + } else { + char label[512]; + + GLint active_texture = GL_TEXTURE0; + glGetIntegerv(GL_ACTIVE_TEXTURE, &active_texture); + snprintf(label, sizeof label, "%s, %s, level = %i", enumToString(active_texture), enumToString(target), level); + + json.beginMember(label); + + json.beginObject(); + + // 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); + + // 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]; + + glGetTexImage(target, level, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + json.beginMember("__data__"); + char *pngBuffer; + int pngBufferSize; + Image::writePixelsToBuffer(pixels, width, height, 4, false, &pngBuffer, &pngBufferSize); + json.writeBase64(pngBuffer, pngBufferSize); + free(pngBuffer); + json.endMember(); // __data__ + + delete [] pixels; + json.endObject(); + } +} + + +static inline void +dumpTexture(JSONWriter &json, GLenum target, GLenum binding) +{ + GLint texture_binding = 0; + glGetIntegerv(binding, &texture_binding); + if (!glIsEnabled(target) && !texture_binding) { + return; + } + + 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) { + break; + } + + if (target == GL_TEXTURE_CUBE_MAP) { + for (int face = 0; face < 6; ++face) { + dumpTextureImage(json, GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level); + } + } else { + dumpTextureImage(json, target, level); + } + + ++level; + } while(true); +} + + +static inline void +dumpTextures(JSONWriter &json) +{ + json.beginMember("textures"); + json.beginObject(); + GLint active_texture = GL_TEXTURE0; + glGetIntegerv(GL_ACTIVE_TEXTURE, &active_texture); + GLint max_texture_coords = 0; + glGetIntegerv(GL_MAX_TEXTURE_COORDS, &max_texture_coords); + GLint max_combined_texture_image_units = 0; + glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_combined_texture_image_units); + GLint max_units = std::max(max_combined_texture_image_units, max_texture_coords); + for (GLint unit = 0; unit < max_units; ++unit) { + GLenum texture = GL_TEXTURE0 + unit; + glActiveTexture(texture); + dumpTexture(json, GL_TEXTURE_1D, GL_TEXTURE_BINDING_1D); + dumpTexture(json, GL_TEXTURE_2D, GL_TEXTURE_BINDING_2D); + dumpTexture(json, GL_TEXTURE_3D, GL_TEXTURE_BINDING_3D); + dumpTexture(json, GL_TEXTURE_RECTANGLE, GL_TEXTURE_BINDING_RECTANGLE); + dumpTexture(json, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BINDING_CUBE_MAP); + } + glActiveTexture(active_texture); + json.endObject(); + json.endMember(); // textures +} + + +static bool +getDrawableBounds(GLint *width, GLint *height) { +#if defined(_WIN32) + + HDC hDC = wglGetCurrentDC(); + if (!hDC) { + return false; + } + + HWND hWnd = WindowFromDC(hDC); + RECT rect; + + if (!GetClientRect(hWnd, &rect)) { + return false; + } + + *width = rect.right - rect.left; + *height = rect.bottom - rect.top; + +#elif 0 /* __APPLE__ */ + + CGLError CGLGetSurface(CGLContextObj, CGSConnectionID*, CGSWindowID*, CGSSurfaceID*); + CGError CGSGetWindowBounds(CGSConnectionID, CGWindowID, CGRect *ret); + +#else + + Display *display; + Drawable drawable; + Window root; + int x, y; + unsigned int w, h, bw, depth; + + display = glXGetCurrentDisplay(); + if (!display) { + return false; + } + + drawable = glXGetCurrentDrawable(); + if (drawable == None) { + return false; + } + + if (!XGetGeometry(display, drawable, &root, &x, &y, &w, &h, &bw, &depth)) { + return false; + } + + *width = w; + *height = h; + +#endif + + return true; +} + + +static inline void +dumpDrawBufferImage(JSONWriter &json, GLenum format) +{ + GLint channels = __gl_format_channels(format); + + GLint width, height; + + if (!getDrawableBounds(&width, &height)) { + json.writeNull(); + } else { + json.beginObject(); + + // 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__", 1); + + // 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__", channels); + + GLubyte *pixels = new GLubyte[width*height*channels]; + + GLint drawbuffer = GL_NONE; + GLint readbuffer = GL_NONE; + glGetIntegerv(GL_DRAW_BUFFER, &drawbuffer); + glGetIntegerv(GL_READ_BUFFER, &readbuffer); + glReadBuffer(drawbuffer); + + glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT); + glPixelStorei(GL_PACK_ALIGNMENT, 1); + + glReadPixels(0, 0, width, height, format, GL_UNSIGNED_BYTE, pixels); + + glPopClientAttrib(); + glReadBuffer(readbuffer); + + json.beginMember("__data__"); + char *pngBuffer; + int pngBufferSize; + Image::writePixelsToBuffer(pixels, width, height, channels, false, &pngBuffer, &pngBufferSize); + //std::cerr <<" Before = "<<(width * height * channels * sizeof *pixels) + // <<", after = "<<pngBufferSize << ", ratio = " << double(width * height * channels * sizeof *pixels)/pngBufferSize; + json.writeBase64(pngBuffer, pngBufferSize); + free(pngBuffer); + json.endMember(); // __data__ + + delete [] pixels; + json.endObject(); + } +} + + +static inline GLuint +downsampledFramebuffer(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; + + if (stencilRb == depthRb && stencilRb) { + //combined depth and stencil buffer + 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); + + glGenRenderbuffers(1, &rbs[*numRbs]); + glBindRenderbuffer(GL_RENDERBUFFER, rbs[*numRbs]); + glRenderbufferStorage(GL_RENDERBUFFER, format, w, h); + 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, + GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + ++*numRbs; + } else { + if (depthRb) { + 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); + + glGenRenderbuffers(1, &rbs[*numRbs]); + glBindRenderbuffer(GL_RENDERBUFFER, rbs[*numRbs]); + glRenderbufferStorage(GL_RENDERBUFFER, format, w, h); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, + GL_DEPTH_ATTACHMENT, + GL_RENDERBUFFER, rbs[*numRbs]); + glBindFramebuffer(GL_READ_FRAMEBUFFER, oldFbo); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo); + glDrawBuffer(GL_DEPTH_ATTACHMENT); + glReadBuffer(GL_DEPTH_ATTACHMENT); + glBlitFramebuffer(0, 0, w, h, 0, 0, w, h, + GL_DEPTH_BUFFER_BIT, GL_NEAREST); + ++*numRbs; + } + if (stencilRb) { + 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); + + glGenRenderbuffers(1, &rbs[*numRbs]); + glBindRenderbuffer(GL_RENDERBUFFER, rbs[*numRbs]); + glRenderbufferStorage(GL_RENDERBUFFER, format, w, h); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, + GL_STENCIL_ATTACHMENT, + GL_RENDERBUFFER, rbs[*numRbs]); + glBindFramebuffer(GL_READ_FRAMEBUFFER, oldFbo); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo); + glDrawBuffer(GL_STENCIL_ATTACHMENT); + glReadBuffer(GL_STENCIL_ATTACHMENT); + glBlitFramebuffer(0, 0, w, h, 0, 0, w, h, + GL_STENCIL_BUFFER_BIT, GL_NEAREST); + ++*numRbs; + } + } + + return fbo; +} + + +static void +dumpDrawBuffers(JSONWriter &json, GLboolean dumpDepth, GLboolean dumpStencil) +{ + json.beginMember("GL_RGBA"); + dumpDrawBufferImage(json, GL_RGBA); + json.endMember(); + + if (dumpDepth) { + json.beginMember("GL_DEPTH_COMPONENT"); + dumpDrawBufferImage(json, GL_DEPTH_COMPONENT); + json.endMember(); + } + + if (dumpStencil) { + json.beginMember("GL_STENCIL_INDEX"); + dumpDrawBufferImage(json, GL_STENCIL_INDEX); + json.endMember(); + } +} + + +static void +dumpFramebuffer(JSONWriter &json) +{ + json.beginMember("framebuffer"); + json.beginObject(); + + GLint boundDrawFbo = 0, boundReadFbo = 0; + glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundDrawFbo); + glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &boundReadFbo); + if (!boundDrawFbo) { + GLint depth_bits = 0; + glGetIntegerv(GL_DEPTH_BITS, &depth_bits); + GLint stencil_bits = 0; + glGetIntegerv(GL_STENCIL_BITS, &stencil_bits); + dumpDrawBuffers(json, depth_bits, stencil_bits); + } else { + GLint colorRb, stencilRb, depthRb; + GLint boundRb; + glGetIntegerv(GL_RENDERBUFFER_BINDING, &boundRb); + GLint drawbuffer = GL_NONE; + glGetIntegerv(GL_DRAW_BUFFER, &drawbuffer); + + glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, + drawbuffer, + GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, + &colorRb); + glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, + GL_DEPTH_ATTACHMENT, + GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, + &depthRb); + glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, + GL_STENCIL_ATTACHMENT, + GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, + &stencilRb); + + GLint colorSamples, depthSamples, stencilSamples; + GLuint rbs[3]; + GLint numRbs = 0; + GLuint fboCopy = 0; + glBindRenderbuffer(GL_RENDERBUFFER, colorRb); + glGetRenderbufferParameteriv(GL_RENDERBUFFER, + GL_RENDERBUFFER_SAMPLES, &colorSamples); + glBindRenderbuffer(GL_RENDERBUFFER, depthRb); + glGetRenderbufferParameteriv(GL_RENDERBUFFER, + GL_RENDERBUFFER_SAMPLES, &depthSamples); + glBindRenderbuffer(GL_RENDERBUFFER, stencilRb); + glGetRenderbufferParameteriv(GL_RENDERBUFFER, + GL_RENDERBUFFER_SAMPLES, &stencilSamples); + glBindRenderbuffer(GL_RENDERBUFFER, boundRb); + + if (colorSamples || depthSamples || stencilSamples) { + //glReadPixels doesnt support multisampled buffers so we need + // to blit the fbo to a temporary one + fboCopy = downsampledFramebuffer(boundDrawFbo, drawbuffer, + colorRb, depthRb, stencilRb, + rbs, &numRbs); + } + glDrawBuffer(drawbuffer); + glReadBuffer(drawbuffer); + + dumpDrawBuffers(json, depthRb, stencilRb); + + if (fboCopy) { + glBindFramebuffer(GL_FRAMEBUFFER, boundDrawFbo); + glBindFramebuffer(GL_READ_FRAMEBUFFER, boundReadFbo); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, boundDrawFbo); + glBindRenderbuffer(GL_RENDERBUFFER_BINDING, boundRb); + glDeleteRenderbuffers(numRbs, rbs); + glDeleteFramebuffers(1, &fboCopy); + } + } + + json.endObject(); + json.endMember(); // framebuffer +} + + +void dumpCurrentContext(std::ostream &os) +{ + JSONWriter json(os); + dumpParameters(json); + dumpShaders(json); + dumpTextures(json); + dumpFramebuffer(json); +} + + +} /* namespace glstate */ diff --git a/glstate.hpp b/glstate.hpp index 13426290..abbfad00 100644 --- a/glstate.hpp +++ b/glstate.hpp @@ -29,14 +29,25 @@ #include <ostream> +#include "glimports.hpp" + + +class JSONWriter; + namespace glstate { -void state_dump(std::ostream &os); +const char *enumToString(GLenum pname); + +void dumpEnum(JSONWriter &json, GLenum pname); + +void dumpParameters(JSONWriter &json); + +void dumpCurrentContext(std::ostream &os); -} /* namespace glretrace */ +} /* namespace glstate */ #endif /* _GLSTATE_HPP_ */ @@ -197,7 +197,7 @@ class JsonWriter(Visitor): def visit_enum(self, enum, instance): if enum.expr == 'GLenum': - print ' writeEnum(json, %s);' % instance + print ' dumpEnum(json, %s);' % instance else: print ' json.writeNumber(%s);' % instance @@ -232,19 +232,17 @@ class StateDumper: def dump(self): print '#include <string.h>' - print '#include <iostream>' - print '#include <algorithm>' print - print '#include "image.hpp"' print '#include "json.hpp"' - print '#include "glimports.hpp"' print '#include "glproc.hpp"' print '#include "glsize.hpp"' print '#include "glstate.hpp"' print + print 'namespace glstate {' + print - print 'static const char *' - print '_enum_string(GLenum pname)' + print 'const char *' + print 'enumToString(GLenum pname)' print '{' print ' switch(pname) {' for name in GLenum.values: @@ -256,24 +254,10 @@ class StateDumper: print '}' print - print 'static const char *' - print 'enum_string(GLenum pname)' + print 'void' + print 'dumpEnum(JSONWriter &json, GLenum pname)' print '{' - print ' const char *s = _enum_string(pname);' - print ' if (s) {' - print ' return s;' - print ' } else {' - print ' static char buf[16];' - print ' snprintf(buf, sizeof buf, "0x%04x", pname);' - print ' return buf;' - print ' }' - print '}' - print - - print 'static inline void' - print 'writeEnum(JSONWriter &json, GLenum pname)' - print '{' - print ' const char *s = _enum_string(pname);' + print ' const char *s = enumToString(pname);' print ' if (s) {' print ' json.writeString(s);' print ' } else {' @@ -282,492 +266,8 @@ class StateDumper: print '}' print - # shaders - print ''' -static void -writeShader(JSONWriter &json, GLuint shader) -{ - if (!shader) { - return; - } - - GLint shader_type = 0; - glGetShaderiv(shader, GL_SHADER_TYPE, &shader_type); - if (!shader_type) { - return; - } - - GLint source_length = 0; - glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &source_length); - if (!source_length) { - return; - } - - GLchar *source = new GLchar[source_length]; - GLsizei length = 0; - source[0] = 0; - glGetShaderSource(shader, source_length, &length, source); - - json.beginMember(enum_string(shader_type)); - json.writeString(source); - json.endMember(); - - delete [] source; -} - -static void -writeShaderObj(JSONWriter &json, GLhandleARB shaderObj) -{ - if (!shaderObj) { - return; - } - - GLint shader_type = 0; - glGetObjectParameterivARB(shaderObj, GL_OBJECT_TYPE_ARB, &shader_type); - if (!shader_type) { - return; - } - - GLint source_length = 0; - glGetObjectParameterivARB(shaderObj, GL_OBJECT_SHADER_SOURCE_LENGTH_ARB, &source_length); - if (!source_length) { - return; - } - - GLcharARB *source = new GLcharARB[source_length]; - GLsizei length = 0; - source[0] = 0; - glGetShaderSource(shaderObj, source_length, &length, source); - - json.beginMember(enum_string(shader_type)); - json.writeString(source); - json.endMember(); - - delete [] source; -} - -static inline void -writeCurrentProgram(JSONWriter &json) -{ - 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; - } - - GLuint *shaders = new GLuint[attached_shaders]; - GLsizei count = 0; - glGetAttachedShaders(program, attached_shaders, &count, shaders); - for (GLsizei i = 0; i < count; ++ i) { - writeShader(json, shaders[i]); - } - delete [] shaders; -} - -static inline void -writeCurrentProgramObj(JSONWriter &json) -{ - GLhandleARB programObj = glGetHandleARB(GL_PROGRAM_OBJECT_ARB); - if (!programObj) { - return; - } - - GLint attached_shaders = 0; - glGetProgramivARB(programObj, GL_OBJECT_ATTACHED_OBJECTS_ARB, &attached_shaders); - if (!attached_shaders) { - return; - } - - GLhandleARB *shaderObjs = new GLhandleARB[attached_shaders]; - GLsizei count = 0; - glGetAttachedObjectsARB(programObj, attached_shaders, &count, shaderObjs); - for (GLsizei i = 0; i < count; ++ i) { - writeShaderObj(json, shaderObjs[i]); - } - delete [] shaderObjs; -} - -static inline void -writeArbProgram(JSONWriter &json, GLenum target) -{ - if (!glIsEnabled(target)) { - return; - } - - GLint program_length = 0; - glGetProgramivARB(target, GL_PROGRAM_LENGTH_ARB, &program_length); - if (!program_length) { - return; - } - - GLchar *source = new GLchar[program_length + 1]; - source[0] = 0; - glGetProgramStringARB(target, GL_PROGRAM_STRING_ARB, source); - source[program_length] = 0; - - json.beginMember(enum_string(target)); - json.writeString(source); - json.endMember(); - - delete [] source; -} -''' - - # texture image - print ''' -static inline void -writeTextureImage(JSONWriter &json, GLenum target, GLint level) -{ - GLint width, height = 1, depth = 1; - - width = 0; - glGetTexLevelParameteriv(target, level, GL_TEXTURE_WIDTH, &width); - - 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); - } - } - - if (width <= 0 || height <= 0 || depth <= 0) { - return; - } else { - char label[512]; - - GLint active_texture = GL_TEXTURE0; - glGetIntegerv(GL_ACTIVE_TEXTURE, &active_texture); - snprintf(label, sizeof label, "%s, %s, level = %i", _enum_string(active_texture), _enum_string(target), level); - - json.beginMember(label); - - json.beginObject(); - - // 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); - - // 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]; - - glGetTexImage(target, level, GL_RGBA, GL_UNSIGNED_BYTE, pixels); - - json.beginMember("__data__"); - char *pngBuffer; - int pngBufferSize; - Image::writePixelsToBuffer(pixels, width, height, 4, false, &pngBuffer, &pngBufferSize); - json.writeBase64(pngBuffer, pngBufferSize); - free(pngBuffer); - json.endMember(); // __data__ - - delete [] pixels; - json.endObject(); - } -} - - -static bool -getDrawableBounds(GLint *width, GLint *height) { -#if defined(_WIN32) - - HDC hDC = wglGetCurrentDC(); - if (!hDC) { - return false; - } - - HWND hWnd = WindowFromDC(hDC); - RECT rect; - - if (!GetClientRect(hWnd, &rect)) { - return false; - } - - *width = rect.right - rect.left; - *height = rect.bottom - rect.top; - -#elif 0 /* __APPLE__ */ - - CGLError CGLGetSurface(CGLContextObj, CGSConnectionID*, CGSWindowID*, CGSSurfaceID*); - CGError CGSGetWindowBounds(CGSConnectionID, CGWindowID, CGRect *ret); - -#else - - Display *display; - Drawable drawable; - Window root; - int x, y; - unsigned int w, h, bw, depth; - - display = glXGetCurrentDisplay(); - if (!display) { - return false; - } - - drawable = glXGetCurrentDrawable(); - if (drawable == None) { - return false; - } - - if (!XGetGeometry(display, drawable, &root, &x, &y, &w, &h, &bw, &depth)) { - return false; - } - - *width = w; - *height = h; - -#endif - - return true; -} - - -static inline void -writeDrawBufferImage(JSONWriter &json, GLenum format) -{ - GLint channels = __gl_format_channels(format); - - GLint width, height; - - if (!getDrawableBounds(&width, &height)) { - json.writeNull(); - } else { - json.beginObject(); - - // 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__", 1); - - // 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__", channels); - - GLubyte *pixels = new GLubyte[width*height*channels]; - - GLint drawbuffer = GL_NONE; - GLint readbuffer = GL_NONE; - glGetIntegerv(GL_DRAW_BUFFER, &drawbuffer); - glGetIntegerv(GL_READ_BUFFER, &readbuffer); - glReadBuffer(drawbuffer); - - glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT); - glPixelStorei(GL_PACK_ALIGNMENT, 1); - - glReadPixels(0, 0, width, height, format, GL_UNSIGNED_BYTE, pixels); - - glPopClientAttrib(); - glReadBuffer(readbuffer); - - json.beginMember("__data__"); - char *pngBuffer; - int pngBufferSize; - Image::writePixelsToBuffer(pixels, width, height, channels, false, &pngBuffer, &pngBufferSize); - //std::cerr <<" Before = "<<(width * height * channels * sizeof *pixels) - // <<", after = "<<pngBufferSize << ", ratio = " << double(width * height * channels * sizeof *pixels)/pngBufferSize; - json.writeBase64(pngBuffer, pngBufferSize); - free(pngBuffer); - json.endMember(); // __data__ - - delete [] pixels; - json.endObject(); - } -} - -static inline GLuint -downsampledFramebuffer(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; - - if (stencilRb == depthRb && stencilRb) { - //combined depth and stencil buffer - 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); - - glGenRenderbuffers(1, &rbs[*numRbs]); - glBindRenderbuffer(GL_RENDERBUFFER, rbs[*numRbs]); - glRenderbufferStorage(GL_RENDERBUFFER, format, w, h); - 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, - GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST); - glBindFramebuffer(GL_FRAMEBUFFER, fbo); - ++*numRbs; - } else { - if (depthRb) { - 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); - - glGenRenderbuffers(1, &rbs[*numRbs]); - glBindRenderbuffer(GL_RENDERBUFFER, rbs[*numRbs]); - glRenderbufferStorage(GL_RENDERBUFFER, format, w, h); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, - GL_DEPTH_ATTACHMENT, - GL_RENDERBUFFER, rbs[*numRbs]); - glBindFramebuffer(GL_READ_FRAMEBUFFER, oldFbo); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo); - glDrawBuffer(GL_DEPTH_ATTACHMENT); - glReadBuffer(GL_DEPTH_ATTACHMENT); - glBlitFramebuffer(0, 0, w, h, 0, 0, w, h, - GL_DEPTH_BUFFER_BIT, GL_NEAREST); - ++*numRbs; - } - if (stencilRb) { - 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); - - glGenRenderbuffers(1, &rbs[*numRbs]); - glBindRenderbuffer(GL_RENDERBUFFER, rbs[*numRbs]); - glRenderbufferStorage(GL_RENDERBUFFER, format, w, h); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, - GL_STENCIL_ATTACHMENT, - GL_RENDERBUFFER, rbs[*numRbs]); - glBindFramebuffer(GL_READ_FRAMEBUFFER, oldFbo); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo); - glDrawBuffer(GL_STENCIL_ATTACHMENT); - glReadBuffer(GL_STENCIL_ATTACHMENT); - glBlitFramebuffer(0, 0, w, h, 0, 0, w, h, - GL_STENCIL_BUFFER_BIT, GL_NEAREST); - ++*numRbs; - } - } - - return fbo; -} - -static void -writeDrawBuffers(JSONWriter &json, GLboolean writeDepth, GLboolean writeStencil) -{ - json.beginMember("GL_RGBA"); - writeDrawBufferImage(json, GL_RGBA); - json.endMember(); - - if (writeDepth) { - json.beginMember("GL_DEPTH_COMPONENT"); - writeDrawBufferImage(json, GL_DEPTH_COMPONENT); - json.endMember(); - } - - if (writeStencil) { - json.beginMember("GL_STENCIL_INDEX"); - writeDrawBufferImage(json, GL_STENCIL_INDEX); - json.endMember(); - } -} - -''' - - # textures - print 'static inline void' - print 'writeTexture(JSONWriter &json, GLenum target, GLenum binding)' - print '{' - print ' GLint texture_binding = 0;' - print ' glGetIntegerv(binding, &texture_binding);' - print ' if (!glIsEnabled(target) && !texture_binding) {' - print ' return;' - print ' }' - print - print ' GLint level = 0;' - print ' do {' - print ' GLint width = 0, height = 0;' - print ' glGetTexLevelParameteriv(target, level, GL_TEXTURE_WIDTH, &width);' - print ' glGetTexLevelParameteriv(target, level, GL_TEXTURE_HEIGHT, &height);' - print ' if (!width || !height) {' - print ' break;' - print ' }' - print - print ' if (target == GL_TEXTURE_CUBE_MAP) {' - print ' for (int face = 0; face < 6; ++face) {' - print ' writeTextureImage(json, GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level);' - print ' }' - print ' } else {' - print ' writeTextureImage(json, target, level);' - print ' }' - print - print ' ++level;' - print ' } while(true);' - print '}' - print - - print 'void glstate::state_dump(std::ostream &os)' + print 'void dumpParameters(JSONWriter &json)' print '{' - print ' JSONWriter json(os);' - self.dump_parameters() - self.dump_current_program() - self.dump_textures() - self.dump_framebuffer() - print '}' - print - - def dump_parameters(self): print ' json.beginMember("parameters");' print ' json.beginObject();' @@ -782,7 +282,10 @@ writeDrawBuffers(JSONWriter &json, GLboolean writeDepth, GLboolean writeStencil) print ' json.endObject();' print ' json.endMember(); // parameters' + print '}' print + + print '} /*namespace glstate */' def dump_material_params(self): for face in ['GL_FRONT', 'GL_BACK']: @@ -887,114 +390,6 @@ writeDrawBuffers(JSONWriter &json, GLboolean writeDepth, GLboolean writeStencil) print ' }' print - def dump_current_program(self): - print ' json.beginMember("shaders");' - print ' json.beginObject();' - print ' writeCurrentProgram(json);' - for target in self.program_targets: - print ' writeArbProgram(json, %s);' % target - print ' json.endObject();' - print ' json.endMember(); //shaders' - print - - def dump_textures(self): - print ' {' - print ' json.beginMember("textures");' - print ' json.beginObject();' - print ' GLint active_texture = GL_TEXTURE0;' - print ' glGetIntegerv(GL_ACTIVE_TEXTURE, &active_texture);' - print ' GLint max_texture_coords = 0;' - print ' glGetIntegerv(GL_MAX_TEXTURE_COORDS, &max_texture_coords);' - print ' GLint max_combined_texture_image_units = 0;' - print ' glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_combined_texture_image_units);' - print ' GLint max_units = std::max(max_combined_texture_image_units, max_texture_coords);' - print ' for (GLint unit = 0; unit < max_units; ++unit) {' - print ' GLenum texture = GL_TEXTURE0 + unit;' - print ' glActiveTexture(texture);' - for target, binding in texture_targets: - print ' writeTexture(json, %s, %s);' % (target, binding) - print ' }' - print ' glActiveTexture(active_texture);' - print ' json.endObject();' - print ' json.endMember(); // textures' - print ' }' - print - - def dump_framebuffer(self): - print ' json.beginMember("framebuffer");' - print ' json.beginObject();' - # TODO: Handle real FBOs - print - print ' GLint boundDrawFbo = 0, boundReadFbo = 0;' - print ' glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundDrawFbo);' - print ' glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &boundReadFbo);' - print ' if (!boundDrawFbo) {' - print ' GLint depth_bits = 0;' - print ' glGetIntegerv(GL_DEPTH_BITS, &depth_bits);' - print ' GLint stencil_bits = 0;' - print ' glGetIntegerv(GL_STENCIL_BITS, &stencil_bits);' - print ' writeDrawBuffers(json, depth_bits, stencil_bits);' - print ' } else {' - print ' GLint colorRb, stencilRb, depthRb;' - print ' GLint boundRb;' - print ' glGetIntegerv(GL_RENDERBUFFER_BINDING, &boundRb);' - print ' GLint drawbuffer = GL_NONE;' - print ' glGetIntegerv(GL_DRAW_BUFFER, &drawbuffer);' - print - print ' glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,' - print ' drawbuffer,' - print ' GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,' - print ' &colorRb);' - print ' glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,' - print ' GL_DEPTH_ATTACHMENT,' - print ' GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,' - print ' &depthRb);' - print ' glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,' - print ' GL_STENCIL_ATTACHMENT,' - print ' GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,' - print ' &stencilRb);' - print - print ' GLint colorSamples, depthSamples, stencilSamples;' - print ' GLuint rbs[3];' - print ' GLint numRbs = 0;' - print ' GLuint fboCopy = 0;' - print ' glBindRenderbuffer(GL_RENDERBUFFER, colorRb);' - print ' glGetRenderbufferParameteriv(GL_RENDERBUFFER,' - print ' GL_RENDERBUFFER_SAMPLES, &colorSamples);' - print ' glBindRenderbuffer(GL_RENDERBUFFER, depthRb);' - print ' glGetRenderbufferParameteriv(GL_RENDERBUFFER,' - print ' GL_RENDERBUFFER_SAMPLES, &depthSamples);' - print ' glBindRenderbuffer(GL_RENDERBUFFER, stencilRb);' - print ' glGetRenderbufferParameteriv(GL_RENDERBUFFER,' - print ' GL_RENDERBUFFER_SAMPLES, &stencilSamples);' - print ' glBindRenderbuffer(GL_RENDERBUFFER, boundRb);' - print - print ' if (colorSamples || depthSamples || stencilSamples) {' - print ' //glReadPixels doesnt support multisampled buffers so we need' - print ' // to blit the fbo to a temporary one' - print ' fboCopy = downsampledFramebuffer(boundDrawFbo, drawbuffer,' - print ' colorRb, depthRb, stencilRb,' - print ' rbs, &numRbs);' - print ' }' - print ' glDrawBuffer(drawbuffer);' - print ' glReadBuffer(drawbuffer);' - print - print ' writeDrawBuffers(json, depthRb, stencilRb);' - print - print ' if (fboCopy) {' - print ' glBindFramebuffer(GL_FRAMEBUFFER, boundDrawFbo);' - print ' glBindFramebuffer(GL_READ_FRAMEBUFFER, boundReadFbo);' - print ' glBindFramebuffer(GL_DRAW_FRAMEBUFFER, boundDrawFbo);' - print ' glBindRenderbuffer(GL_RENDERBUFFER_BINDING, boundRb);' - print ' glDeleteRenderbuffers(numRbs, rbs);' - print ' glDeleteFramebuffers(1, &fboCopy);' - print ' }' - print ' }' - print - print ' json.endObject();' - print ' json.endMember(); // framebuffer' - pass - def dump_atoms(self, getter, *args): for function, type, count, name in parameters: inflection = getter.inflector.radical + getter.suffix |