From: José Fonseca Date: Thu, 19 May 2011 09:45:04 +0000 (+0100) Subject: Reorganize glstate code. X-Git-Url: https://git.cworth.org/git?a=commitdiff_plain;h=2e3fff6025fac330cbf00c8b81766dcbcf6298b5;p=apitrace Reorganize glstate code. --- diff --git a/.gitignore b/.gitignore index 5680977..5b14114 100644 --- a/.gitignore +++ b/.gitignore @@ -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 41bbd6d..44b4c84 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 bfab151..56113ef 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 0000000..a60c687 --- /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 +#include +#include + +#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 = "< +#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_ */ diff --git a/glstate.py b/glstate.py index 859b3df..3808415 100644 --- a/glstate.py +++ b/glstate.py @@ -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 ' - print '#include ' - print '#include ' 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 = "<