]> OCCT Git - occt.git/commitdiff
0032093: Visualization, TKOpenGl - loading texture in BGR format fails in OpenGL ES
authorkgv <kgv@opencascade.com>
Fri, 29 Jan 2021 00:34:16 +0000 (03:34 +0300)
committerbugmaster <bugmaster@opencascade.com>
Fri, 29 Jan 2021 16:51:17 +0000 (19:51 +0300)
Graphic3d_TextureRoot::convertToCompatible() - fixed handling of
Image_Format_BGR and Image_Format_BGRA formats.

OpenGl_Texture - added error message for unsupported pixel format;
error messages have been extended by resource id.
OpenGl_Texture::InitCubeMap() now does not release cubemap
on mipmaps generation failure.

Image_PixMap::ImageFormatToString() - added method returning name of pixel format.

src/Graphic3d/Graphic3d_TextureRoot.cxx
src/Image/Image_PixMap.cxx
src/Image/Image_PixMap.hxx
src/OpenGl/OpenGl_Texture.cxx

index 5911201b381a8ed1ffab38be034ff3e96b422396..a89f32dabe3a2e8f6b0d328af9baefbaadd7ea1e 100644 (file)
@@ -221,13 +221,20 @@ void Graphic3d_TextureRoot::convertToCompatible (const Handle(Image_SupportedFor
     return;
   }
 
-  if ((theImage->Format() == Image_Format_BGR32
-    || theImage->Format() == Image_Format_BGR32))
+  switch (theImage->Format())
   {
-    Image_PixMap::SwapRgbaBgra (*theImage);
-    theImage->SetFormat (theImage->Format() == Image_Format_BGR32
-                       ? Image_Format_RGB32
-                       : Image_Format_RGBA);
+    // BGR formats are unsupported in OpenGL ES, only RGB
+    case Image_Format_BGR:
+      Image_PixMap::SwapRgbaBgra (*theImage);
+      theImage->SetFormat (Image_Format_RGB);
+      break;
+    case Image_Format_BGRA:
+    case Image_Format_BGR32:
+      Image_PixMap::SwapRgbaBgra (*theImage);
+      theImage->SetFormat (theImage->Format() == Image_Format_BGR32 ? Image_Format_RGB32 : Image_Format_RGBA);
+      break;
+    default:
+      break;
   }
 }
 
index 8358edf261b4cde30bc5568bbfc1d9a2cf99b085..15d2fad63f6e9a76a1691c6cb9db599fb0bcdcf7 100644 (file)
 
 #include <algorithm>
 
+namespace
+{
+  //! Structure defining image pixel format description.
+  struct Image_FormatInfo
+  {
+    const char*  Name;         //!< string representation
+    int          Format;       //!< enumeration name
+    unsigned int NbComponents; //!< number of components
+    unsigned int PixelSize;    //!< bytes per pixel
+
+    Image_FormatInfo (Image_Format theFormat, const char* theName, unsigned int theNbComponents, Standard_Size thePixelSize)
+    : Name (theName), Format (theFormat), NbComponents (theNbComponents), PixelSize ((unsigned int )thePixelSize) {}
+
+    Image_FormatInfo (Image_CompressedFormat theFormat, const char* theName, unsigned int theNbComponents, Standard_Size thePixelSize)
+    : Name (theName), Format (theFormat), NbComponents (theNbComponents), PixelSize ((unsigned int )thePixelSize) {}
+  };
+
+  #define ImageFormatInfo(theName, theNbComponents, thePixelSize) \
+    Image_FormatInfo(Image_Format_##theName, #theName, theNbComponents, thePixelSize)
+
+  #define CompressedImageFormatInfo(theName, theNbComponents, thePixelSize) \
+    Image_FormatInfo(Image_CompressedFormat_##theName, #theName, theNbComponents, thePixelSize)
+
+  //! Table of image pixel formats.
+  static const Image_FormatInfo Image_Table_ImageFormats[Image_CompressedFormat_NB] =
+  {
+    ImageFormatInfo(UNKNOWN, 0, 1),
+    ImageFormatInfo(Gray,    1, 1),
+    ImageFormatInfo(Alpha,   1, 1),
+    ImageFormatInfo(RGB,     3, 3),
+    ImageFormatInfo(BGR,     3, 3),
+    ImageFormatInfo(RGB32,   3, 4),
+    ImageFormatInfo(BGR32,   3, 4),
+    ImageFormatInfo(RGBA,    4, 4),
+    ImageFormatInfo(BGRA,    4, 4),
+    ImageFormatInfo(GrayF,   1, sizeof(float)),
+    ImageFormatInfo(AlphaF,  1, sizeof(float)),
+    ImageFormatInfo(RGF,     2, sizeof(float) * 2),
+    ImageFormatInfo(RGBF,    3, sizeof(float) * 3),
+    ImageFormatInfo(BGRF,    3, sizeof(float) * 3),
+    ImageFormatInfo(RGBAF,   4, sizeof(float) * 4),
+    ImageFormatInfo(BGRAF,   4, sizeof(float) * 4),
+    CompressedImageFormatInfo(RGB_S3TC_DXT1,  3, 1), // DXT1 uses circa half a byte per pixel (64 bits per 4x4 block)
+    CompressedImageFormatInfo(RGBA_S3TC_DXT1, 4, 1),
+    CompressedImageFormatInfo(RGBA_S3TC_DXT3, 4, 1), // DXT3/5 uses circa 1 byte per pixel (128 bits per 4x4 block)
+    CompressedImageFormatInfo(RGBA_S3TC_DXT5, 4, 1)
+  };
+}
+
 IMPLEMENT_STANDARD_RTTIEXT(Image_PixMap,Standard_Transient)
 
 // =======================================================================
@@ -32,6 +81,24 @@ const Handle(NCollection_BaseAllocator)& Image_PixMap::DefaultAllocator()
   return THE_ALLOC;
 }
 
+// =======================================================================
+// function : ImageFormatToString
+// purpose  :
+// =======================================================================
+Standard_CString Image_PixMap::ImageFormatToString (Image_Format theFormat)
+{
+  return Image_Table_ImageFormats[theFormat].Name;
+}
+
+// =======================================================================
+// function : ImageFormatToString
+// purpose  :
+// =======================================================================
+Standard_CString Image_PixMap::ImageFormatToString (Image_CompressedFormat theFormat)
+{
+  return Image_Table_ImageFormats[theFormat].Name;
+}
+
 // =======================================================================
 // function : Image_PixMap
 // purpose  :
@@ -57,35 +124,7 @@ Image_PixMap::~Image_PixMap()
 // =======================================================================
 Standard_Size Image_PixMap::SizePixelBytes (const Image_Format thePixelFormat)
 {
-  switch (thePixelFormat)
-  {
-    case Image_Format_GrayF:
-    case Image_Format_AlphaF:
-      return sizeof(float);
-    case Image_Format_RGF:
-      return sizeof(float) * 2;
-    case Image_Format_RGBAF:
-    case Image_Format_BGRAF:
-      return sizeof(float) * 4;
-    case Image_Format_RGBF:
-    case Image_Format_BGRF:
-      return sizeof(float) * 3;
-    case Image_Format_RGBA:
-    case Image_Format_BGRA:
-      return 4;
-    case Image_Format_RGB32:
-    case Image_Format_BGR32:
-      return 4;
-    case Image_Format_RGB:
-    case Image_Format_BGR:
-      return 3;
-    case Image_Format_Gray:
-    case Image_Format_Alpha:
-      return 1;
-    case Image_Format_UNKNOWN:
-      return 1;
-  }
-  return 1;
+  return Image_Table_ImageFormats[thePixelFormat].PixelSize;
 }
 
 // =======================================================================
index 4f696e65ef7ffb2a8798a87fdad7696e7bf20a64..a043f8894a7c87f0e276a3d7107045375fe111c1 100644 (file)
@@ -16,7 +16,7 @@
 #ifndef _Image_PixMap_H__
 #define _Image_PixMap_H__
 
-#include <Image_Format.hxx>
+#include <Image_CompressedFormat.hxx>
 #include <Image_PixMapData.hxx>
 #include <Standard_Transient.hxx>
 #include <Quantity_ColorRGBA.hxx>
@@ -54,6 +54,12 @@ public:
   //! Return default image data allocator.
   Standard_EXPORT static const Handle(NCollection_BaseAllocator)& DefaultAllocator();
 
+  //! Return string representation of pixel format.
+  Standard_EXPORT static Standard_CString ImageFormatToString (Image_Format theFormat);
+
+  //! Return string representation of compressed pixel format.
+  Standard_EXPORT static Standard_CString ImageFormatToString (Image_CompressedFormat theFormat);
+
 public: // high-level API
 
   Image_Format Format() const { return myImgFormat; }
index 050aa5edbcadae284f66ec53116bf0925af4a9e6..2bf73d553f5398d61dc14f76f10de80848a644b9 100644 (file)
@@ -234,7 +234,7 @@ bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx,
    || theSizeXY.y() < 1)
   {
     theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
-                         "Error: texture of 0 size cannot be created.");
+                         TCollection_AsciiString ("Error: texture of 0 size cannot be created [") + myResourceId +"]");
     Release (theCtx.get());
     return false;
   }
@@ -286,7 +286,7 @@ bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx,
   && !theCtx->arbTexFloat)
   {
     theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
-                         "Error: floating-point textures are not supported by hardware.");
+                         TCollection_AsciiString ("Error: floating-point textures are not supported by hardware [") + myResourceId +"]");
     Release (theCtx.get());
     return false;
   }
@@ -297,7 +297,8 @@ bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx,
   {
     theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
                          TCollection_AsciiString ("Error: Texture dimension - ") + theSizeXY.x() + "x" + theSizeXY.y()
-                       + " exceeds hardware limits (" + aMaxSize + "x" + aMaxSize + ")");
+                       + " exceeds hardware limits (" + aMaxSize + "x" + aMaxSize + ")"
+                       + " [" + myResourceId +"]");
     Release (theCtx.get());
     return false;
   }
@@ -315,7 +316,7 @@ bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx,
     {
       theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH,
                            TCollection_AsciiString ("Error: NPOT Textures (") + theSizeXY.x() + "x" + theSizeXY.y() + ")"
-                           " are not supported by hardware.");
+                           " are not supported by hardware [" + myResourceId +"]");
       Release (theCtx.get());
       return false;
     }
@@ -331,7 +332,7 @@ bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx,
     {
       theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH,
                            TCollection_AsciiString ("Error: Mipmap NPOT Textures (") + theSizeXY.x() + "x" + theSizeXY.y() + ")"
-                           " are not supported by OpenGL ES 2.0");
+                           " are not supported by OpenGL ES 2.0 [" + myResourceId +"]");
       Release (theCtx.get());
       return false;
     }
@@ -407,7 +408,7 @@ bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx,
       return true;
     #else
       theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
-                           "Error: 1D textures are not supported by hardware.");
+                           TCollection_AsciiString ( "Error: 1D textures are not supported by hardware [") + myResourceId +"]");
       Release (theCtx.get());
       return false;
     #endif
@@ -466,7 +467,8 @@ bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx,
                                                    + " IF: " + OpenGl_TextureFormat::FormatFormat (anIntFormat)
                                                    + " PF: " + OpenGl_TextureFormat::FormatFormat (theFormat.PixelFormat())
                                                    + " DT: " + OpenGl_TextureFormat::FormatDataType (theFormat.DataType())
-                                                   + " can not be created with error " + OpenGl_Context::FormatGlError (anErr) + ".");
+                                                   + " can not be created with error " + OpenGl_Context::FormatGlError (anErr)
+                                                   + " [" + myResourceId +"]");
         Unbind (theCtx);
         Release (theCtx.get());
         return false;
@@ -484,8 +486,20 @@ bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx,
         if (anErr != GL_NO_ERROR)
         {
           myMaxMipLevel = 0;
-          theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH,
-                               "Warning: generating mipmaps requires GL_ARB_framebuffer_object extension which is missing.");
+        #if defined(GL_ES_VERSION_2_0)
+          if (theFormat.InternalFormat() == GL_RGB8
+           || theFormat.InternalFormat() == GL_SRGB8)
+          {
+            theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH,
+                                 TCollection_AsciiString ("Warning: generating mipmaps requires color-renderable format, while giving ")
+                                 + OpenGl_TextureFormat::FormatFormat (anIntFormat) + " [" + myResourceId +"]");
+          }
+          else
+        #endif
+          {
+            theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH,
+                                 TCollection_AsciiString ("Warning: generating mipmaps has failed [") + myResourceId +"]");
+          }
         }
       }
 
@@ -522,6 +536,9 @@ bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx,
   const OpenGl_TextureFormat aFormat = OpenGl_TextureFormat::FindFormat (theCtx, theImage.Format(), theIsColorMap);
   if (!aFormat.IsValid())
   {
+    theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
+                         TCollection_AsciiString ("Error: No suitable texture format for ") + Image_PixMap::ImageFormatToString (theImage.Format()) + " image format"
+                         + " [" + myResourceId +"]");
     Release (theCtx.get());
     return false;
   }
@@ -600,6 +617,9 @@ bool OpenGl_Texture::InitCompressed (const Handle(OpenGl_Context)& theCtx,
   const OpenGl_TextureFormat aFormat = OpenGl_TextureFormat::FindCompressedFormat (theCtx, theImage.CompressedFormat(), theIsColorMap);
   if (!aFormat.IsValid())
   {
+    theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
+                         TCollection_AsciiString ("Error: No suitable texture format for ") + Image_PixMap::ImageFormatToString (theImage.CompressedFormat()) + " image format "
+                         + " [" + myResourceId +"]");
     Release (theCtx.get());
     return false;
   }
@@ -978,6 +998,9 @@ bool OpenGl_Texture::InitCubeMap (const Handle(OpenGl_Context)&    theCtx,
   }
   if (!aFormat.IsValid())
   {
+    theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
+                         TCollection_AsciiString ("Error: No suitable texture format for ") + Image_PixMap::ImageFormatToString (theFormat) + " image format"
+                         + " [" + myResourceId +"]");
     Unbind(theCtx);
     Release(theCtx.get());
     return false;
@@ -1115,10 +1138,10 @@ bool OpenGl_Texture::InitCubeMap (const Handle(OpenGl_Context)&    theCtx,
     if (anErr != GL_NO_ERROR)
     {
       theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
-                           TCollection_AsciiString ("Unable to generate mipmap of cubemap. Error ") + OpenGl_Context::FormatGlError (anErr));
-      Unbind (theCtx);
-      Release (theCtx.get());
-      return false;
+                           TCollection_AsciiString ("Unable to generate mipmap of cubemap with format ")
+                           + OpenGl_TextureFormat::FormatFormat (anIntFormat)
+                           + ", error " + OpenGl_Context::FormatGlError (anErr));
+      myMaxMipLevel = 0;
     }
   }