1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-04 18:06:22 +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;
}
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;
}
}

View File

@ -20,6 +20,55 @@
#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;
}
// =======================================================================

View 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; }

View 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;
}
}