From 74706083605a15f3e223081fa3ed564dc2ac1994 Mon Sep 17 00:00:00 2001 From: kgv Date: Thu, 28 Nov 2013 13:55:52 +0400 Subject: [PATCH] 0023813: TKOpenGl, OpenGl_Texture ignores stride image property Added test case tests/bugs/vis/bug23813 --- src/OpenGl/OpenGl_GraphicDriver_7.cxx | 21 +++++++++------- src/OpenGl/OpenGl_Texture.cxx | 35 ++++++++++++++++++++++++++- tests/bugs/vis/bug23813 | 26 ++++++++++++++++++++ 3 files changed, 72 insertions(+), 10 deletions(-) create mode 100644 tests/bugs/vis/bug23813 diff --git a/src/OpenGl/OpenGl_GraphicDriver_7.cxx b/src/OpenGl/OpenGl_GraphicDriver_7.cxx index 0e40dfee1f..f4d7432d20 100755 --- a/src/OpenGl/OpenGl_GraphicDriver_7.cxx +++ b/src/OpenGl/OpenGl_GraphicDriver_7.cxx @@ -400,28 +400,31 @@ Standard_Boolean OpenGl_Workspace::BufferDump (OpenGl_FrameBuffer* theFB glReadBuffer (aDrawBufferPrev); } - GLint anAlignBack = 1; - glGetIntegerv (GL_PACK_ALIGNMENT, &anAlignBack); - GLint anExtraBytes = (GLint )theImage.RowExtraBytes(); - GLint anAligment = Min (GLint(theImage.MaxRowAligmentBytes()), 8); // limit to 8 bytes for OpenGL + // setup alignment + const GLint anExtraBytes = (GLint )theImage.RowExtraBytes(); + const GLint anAligment = Min (GLint(theImage.MaxRowAligmentBytes()), 8); // limit to 8 bytes for OpenGL glPixelStorei (GL_PACK_ALIGNMENT, anAligment); - if (anExtraBytes >= anAligment) + const GLint aPixelsWidth = GLint(theImage.SizeRowBytes() / theImage.SizePixelBytes()); + glPixelStorei (GL_PACK_ROW_LENGTH, (anExtraBytes >= anAligment) ? aPixelsWidth : 0); + + if (theImage.IsTopDown()) { // copy row by row for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow) { - glReadPixels (0, GLint(aRow), GLsizei (theImage.SizeX()), 1, aFormat, aType, theImage.ChangeRow (aRow)); + // Image_PixMap rows indexation always starts from the upper corner + // while order in memory depends on the flag and processed by ChangeRow() method + glReadPixels (0, GLint(theImage.SizeY() - aRow - 1), GLsizei (theImage.SizeX()), 1, aFormat, aType, theImage.ChangeRow (aRow)); } } else { - // read pixels glReadPixels (0, 0, GLsizei (theImage.SizeX()), GLsizei (theImage.SizeY()), aFormat, aType, theImage.ChangeData()); - theImage.SetTopDown (false); // image bottom-up in OpenGL } - glPixelStorei (GL_PACK_ALIGNMENT, anAlignBack); + glPixelStorei (GL_PACK_ALIGNMENT, 1); + glPixelStorei (GL_PACK_ROW_LENGTH, 0); if (theFBOPtr != NULL && theFBOPtr->IsValid()) { diff --git a/src/OpenGl/OpenGl_Texture.cxx b/src/OpenGl/OpenGl_Texture.cxx index 2e9552c8d6..39bd1abefd 100644 --- a/src/OpenGl/OpenGl_Texture.cxx +++ b/src/OpenGl/OpenGl_Texture.cxx @@ -27,6 +27,24 @@ IMPLEMENT_STANDARD_HANDLE (OpenGl_Texture, OpenGl_Resource) IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Texture, OpenGl_Resource) +//! Simple class to reset unpack alignment settings +struct OpenGl_UnpackAlignmentSentry +{ + + //! Reset unpack alignment settings to safe values + void Reset() + { + glPixelStorei (GL_UNPACK_ALIGNMENT, 1); + glPixelStorei (GL_UNPACK_ROW_LENGTH, 0); + } + + ~OpenGl_UnpackAlignmentSentry() + { + Reset(); + } + +}; + // ======================================================================= // function : OpenGl_Texture // purpose : @@ -287,7 +305,16 @@ bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx, GLint aTestWidth = 0; GLint aTestHeight = 0; - glPixelStorei (GL_UNPACK_ALIGNMENT, 1); // ensure alignment will not screw up the party + // setup the alignment + OpenGl_UnpackAlignmentSentry anUnpackSentry; + const GLint anAligment = Min ((GLint )theImage.MaxRowAligmentBytes(), 8); // OpenGL supports alignment upto 8 bytes + glPixelStorei (GL_UNPACK_ALIGNMENT, anAligment); + + // notice that GL_UNPACK_ROW_LENGTH is not available on OpenGL ES 2.0 without GL_EXT_unpack_subimage extension + const GLint anExtraBytes = GLint(theImage.RowExtraBytes()); + const GLint aPixelsWidth = GLint(theImage.SizeRowBytes() / theImage.SizePixelBytes()); + glPixelStorei (GL_UNPACK_ROW_LENGTH, (anExtraBytes >= anAligment) ? aPixelsWidth : 0); + switch (theType) { case Graphic3d_TOT_1D: @@ -301,6 +328,8 @@ bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx, GLvoid* aDataPtr = (GLvoid* )theImage.Data(); if (aWidth != aWidthOut) { + glPixelStorei (GL_PACK_ALIGNMENT, 1); + glPixelStorei (GL_PACK_ROW_LENGTH, 0); if (!aCopy.InitTrash (theImage.Format(), Standard_Size(aWidthOut), 1) || gluScaleImage (aPixelFormat, aWidth, 1, aDataType, theImage.Data(), @@ -311,6 +340,7 @@ bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx, } aDataPtr = (GLvoid* )aCopy.Data(); + anUnpackSentry.Reset(); } // use proxy to check texture could be created or not @@ -352,6 +382,8 @@ bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx, if (aWidth != aWidthOut || aHeight != aHeightOut) { // scale texture + glPixelStorei (GL_PACK_ALIGNMENT, 1); + glPixelStorei (GL_PACK_ROW_LENGTH, 0); if (!aCopy.InitTrash (theImage.Format(), Standard_Size(aWidthOut), Standard_Size(aHeightOut)) || gluScaleImage (aPixelFormat, aWidth, aHeight, aDataType, theImage.Data(), @@ -362,6 +394,7 @@ bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx, } aDataPtr = (GLvoid* )aCopy.Data(); + anUnpackSentry.Reset(); } // use proxy to check texture could be created or not diff --git a/tests/bugs/vis/bug23813 b/tests/bugs/vis/bug23813 new file mode 100644 index 0000000000..a4c6255713 --- /dev/null +++ b/tests/bugs/vis/bug23813 @@ -0,0 +1,26 @@ +puts "============" +puts "OCC23813" +puts "============" +puts "" +####################################################################### +# TKOpenGl, OpenGl_Texture ignores stride image property +####################################################################### + +file delete -force ${imagedir}/texture_412.png +file delete -force ${imagedir}/texture_409.png + +box b 1 2 3 +vinit +vsetdispmode 1 +vdisplay b +vfit +vdump ${imagedir}/texture_409.png rgb 409 409 +vdump ${imagedir}/texture_412.png rgb 412 412 + +# texture loaded correctly +vtexture b ${imagedir}/texture_412.png + +# texture is corrupted during uploading to OpenGL +vtexture b ${imagedir}/texture_409.png + +set only_screen 1 -- 2.20.1