1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-06-30 12:14:08 +03:00

0032093: Visualization, TKOpenGl - loading texture in BGR format fails in OpenGL ES

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.
This commit is contained in:
kgv 2021-01-29 03:34:16 +03:00 committed by bugmaster
parent 961c002c46
commit 776302d46b
4 changed files with 124 additions and 49 deletions

View File

@ -221,13 +221,20 @@ void Graphic3d_TextureRoot::convertToCompatible (const Handle(Image_SupportedFor
return; return;
} }
if ((theImage->Format() == Image_Format_BGR32 switch (theImage->Format())
|| theImage->Format() == Image_Format_BGR32))
{ {
Image_PixMap::SwapRgbaBgra (*theImage); // BGR formats are unsupported in OpenGL ES, only RGB
theImage->SetFormat (theImage->Format() == Image_Format_BGR32 case Image_Format_BGR:
? Image_Format_RGB32 Image_PixMap::SwapRgbaBgra (*theImage);
: Image_Format_RGBA); 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;
} }
} }

View File

@ -20,6 +20,55 @@
#include <algorithm> #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) IMPLEMENT_STANDARD_RTTIEXT(Image_PixMap,Standard_Transient)
// ======================================================================= // =======================================================================
@ -32,6 +81,24 @@ const Handle(NCollection_BaseAllocator)& Image_PixMap::DefaultAllocator()
return THE_ALLOC; 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 // function : Image_PixMap
// purpose : // purpose :
@ -57,35 +124,7 @@ Image_PixMap::~Image_PixMap()
// ======================================================================= // =======================================================================
Standard_Size Image_PixMap::SizePixelBytes (const Image_Format thePixelFormat) Standard_Size Image_PixMap::SizePixelBytes (const Image_Format thePixelFormat)
{ {
switch (thePixelFormat) return Image_Table_ImageFormats[thePixelFormat].PixelSize;
{
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;
} }
// ======================================================================= // =======================================================================

View File

@ -16,7 +16,7 @@
#ifndef _Image_PixMap_H__ #ifndef _Image_PixMap_H__
#define _Image_PixMap_H__ #define _Image_PixMap_H__
#include <Image_Format.hxx> #include <Image_CompressedFormat.hxx>
#include <Image_PixMapData.hxx> #include <Image_PixMapData.hxx>
#include <Standard_Transient.hxx> #include <Standard_Transient.hxx>
#include <Quantity_ColorRGBA.hxx> #include <Quantity_ColorRGBA.hxx>
@ -54,6 +54,12 @@ public:
//! Return default image data allocator. //! Return default image data allocator.
Standard_EXPORT static const Handle(NCollection_BaseAllocator)& DefaultAllocator(); 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 public: // high-level API
Image_Format Format() const { return myImgFormat; } Image_Format Format() const { return myImgFormat; }

View File

@ -234,7 +234,7 @@ bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx,
|| theSizeXY.y() < 1) || theSizeXY.y() < 1)
{ {
theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, 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()); Release (theCtx.get());
return false; return false;
} }
@ -286,7 +286,7 @@ bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx,
&& !theCtx->arbTexFloat) && !theCtx->arbTexFloat)
{ {
theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, 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()); Release (theCtx.get());
return false; 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, 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() 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()); Release (theCtx.get());
return false; 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, 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() + ")" TCollection_AsciiString ("Error: NPOT Textures (") + theSizeXY.x() + "x" + theSizeXY.y() + ")"
" are not supported by hardware."); " are not supported by hardware [" + myResourceId +"]");
Release (theCtx.get()); Release (theCtx.get());
return false; 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, 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() + ")" 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()); Release (theCtx.get());
return false; return false;
} }
@ -407,7 +408,7 @@ bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx,
return true; return true;
#else #else
theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, 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()); Release (theCtx.get());
return false; return false;
#endif #endif
@ -466,7 +467,8 @@ bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx,
+ " IF: " + OpenGl_TextureFormat::FormatFormat (anIntFormat) + " IF: " + OpenGl_TextureFormat::FormatFormat (anIntFormat)
+ " PF: " + OpenGl_TextureFormat::FormatFormat (theFormat.PixelFormat()) + " PF: " + OpenGl_TextureFormat::FormatFormat (theFormat.PixelFormat())
+ " DT: " + OpenGl_TextureFormat::FormatDataType (theFormat.DataType()) + " 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); Unbind (theCtx);
Release (theCtx.get()); Release (theCtx.get());
return false; return false;
@ -484,8 +486,20 @@ bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx,
if (anErr != GL_NO_ERROR) if (anErr != GL_NO_ERROR)
{ {
myMaxMipLevel = 0; myMaxMipLevel = 0;
theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH, #if defined(GL_ES_VERSION_2_0)
"Warning: generating mipmaps requires GL_ARB_framebuffer_object extension which is missing."); 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); const OpenGl_TextureFormat aFormat = OpenGl_TextureFormat::FindFormat (theCtx, theImage.Format(), theIsColorMap);
if (!aFormat.IsValid()) 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()); Release (theCtx.get());
return false; 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); const OpenGl_TextureFormat aFormat = OpenGl_TextureFormat::FindCompressedFormat (theCtx, theImage.CompressedFormat(), theIsColorMap);
if (!aFormat.IsValid()) 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()); Release (theCtx.get());
return false; return false;
} }
@ -978,6 +998,9 @@ bool OpenGl_Texture::InitCubeMap (const Handle(OpenGl_Context)& theCtx,
} }
if (!aFormat.IsValid()) 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); Unbind(theCtx);
Release(theCtx.get()); Release(theCtx.get());
return false; return false;
@ -1115,10 +1138,10 @@ bool OpenGl_Texture::InitCubeMap (const Handle(OpenGl_Context)& theCtx,
if (anErr != GL_NO_ERROR) if (anErr != GL_NO_ERROR)
{ {
theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, 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)); TCollection_AsciiString ("Unable to generate mipmap of cubemap with format ")
Unbind (theCtx); + OpenGl_TextureFormat::FormatFormat (anIntFormat)
Release (theCtx.get()); + ", error " + OpenGl_Context::FormatGlError (anErr));
return false; myMaxMipLevel = 0;
} }
} }