0023813: TKOpenGl, OpenGl_Texture ignores stride image property
authorkgv <kgv@opencascade.com>
Thu, 28 Nov 2013 09:55:52 +0000 (13:55 +0400)
committerbugmaster <bugmaster@opencascade.com>
Thu, 28 Nov 2013 10:55:51 +0000 (14:55 +0400)
Added test case tests/bugs/vis/bug23813

src/OpenGl/OpenGl_GraphicDriver_7.cxx
src/OpenGl/OpenGl_Texture.cxx
tests/bugs/vis/bug23813 [new file with mode: 0644]

index 0e40dfe..f4d7432 100755 (executable)
@@ -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())
   {
index 2e9552c..39bd1ab 100644 (file)
 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 (file)
index 0000000..a4c6255
--- /dev/null
@@ -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