OpenGL3: Sort out texture color format support

This commit is contained in:
numzero 2023-04-20 17:40:51 +03:00 committed by sfan5
parent 49b6ccde72
commit 1387370260
5 changed files with 107 additions and 228 deletions

@ -2111,226 +2111,17 @@ COpenGL3DriverBase::~COpenGL3DriverBase()
bool COpenGL3DriverBase::getColorFormatParameters(ECOLOR_FORMAT format, GLint& internalFormat, GLenum& pixelFormat, bool COpenGL3DriverBase::getColorFormatParameters(ECOLOR_FORMAT format, GLint& internalFormat, GLenum& pixelFormat,
GLenum& pixelType, void(**converter)(const void*, s32, void*)) const GLenum& pixelType, void(**converter)(const void*, s32, void*)) const
{ {
bool supported = false; auto &info = TextureFormats[format];
pixelFormat = GL_RGBA; internalFormat = info.InternalFormat;
pixelType = GL_UNSIGNED_BYTE; pixelFormat = info.PixelFormat;
*converter = 0; pixelType = info.PixelType;
*converter = info.Converter;
switch (format) return info.InternalFormat != 0;
{
case ECF_A1R5G5B5:
supported = true;
pixelFormat = GL_RGBA;
pixelType = GL_UNSIGNED_SHORT_5_5_5_1;
*converter = CColorConverter::convert_A1R5G5B5toR5G5B5A1;
break;
case ECF_R5G6B5:
supported = true;
pixelFormat = GL_RGB;
pixelType = GL_UNSIGNED_SHORT_5_6_5;
break;
case ECF_R8G8B8:
supported = true;
pixelFormat = GL_RGB;
pixelType = GL_UNSIGNED_BYTE;
break;
case ECF_A8R8G8B8:
supported = true;
if (queryGLESFeature(COGLESCoreExtensionHandler::IRR_GL_IMG_texture_format_BGRA8888) ||
queryGLESFeature(COGLESCoreExtensionHandler::IRR_GL_EXT_texture_format_BGRA8888) ||
queryGLESFeature(COGLESCoreExtensionHandler::IRR_GL_APPLE_texture_format_BGRA8888))
{
pixelFormat = GL_BGRA;
}
else
{
pixelFormat = GL_RGBA;
*converter = CColorConverter::convert_A8R8G8B8toA8B8G8R8;
}
pixelType = GL_UNSIGNED_BYTE;
break;
#ifdef GL_EXT_texture_compression_s3tc
case ECF_DXT1:
supported = true;
pixelFormat = GL_RGBA;
pixelType = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
break;
case ECF_DXT2:
case ECF_DXT3:
supported = true;
pixelFormat = GL_RGBA;
pixelType = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
break;
case ECF_DXT4:
case ECF_DXT5:
supported = true;
pixelFormat = GL_RGBA;
pixelType = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
break;
#endif
#ifdef GL_OES_compressed_ETC1_RGB8_texture
case ECF_ETC1:
supported = true;
pixelFormat = GL_RGB;
pixelType = GL_ETC1_RGB8_OES;
break;
#endif
#ifdef GL_ES_VERSION_3_0 // TO-DO - fix when extension name will be available
case ECF_ETC2_RGB:
supported = true;
pixelFormat = GL_RGB;
pixelType = GL_COMPRESSED_RGB8_ETC2;
break;
#endif
#ifdef GL_ES_VERSION_3_0 // TO-DO - fix when extension name will be available
case ECF_ETC2_ARGB:
supported = true;
pixelFormat = GL_RGBA;
pixelType = GL_COMPRESSED_RGBA8_ETC2_EAC;
break;
#endif
case ECF_D16:
supported = true;
pixelFormat = GL_DEPTH_COMPONENT;
pixelType = GL_UNSIGNED_SHORT;
break;
case ECF_D32:
#if defined(GL_OES_depth32)
if (queryGLESFeature(COGLESCoreExtensionHandler::IRR_GL_OES_depth32))
{
supported = true;
pixelFormat = GL_DEPTH_COMPONENT;
pixelType = GL_UNSIGNED_INT;
}
#endif
break;
case ECF_D24S8:
#ifdef GL_OES_packed_depth_stencil
if (queryGLESFeature(COGLESCoreExtensionHandler::IRR_GL_OES_packed_depth_stencil))
{
supported = true;
pixelFormat = GL_DEPTH_STENCIL_OES;
pixelType = GL_UNSIGNED_INT_24_8_OES;
}
#endif
break;
case ECF_R8:
#if defined(GL_EXT_texture_rg)
if (queryGLESFeature(COGLESCoreExtensionHandler::IRR_GL_EXT_texture_rg))
{
supported = true;
pixelFormat = GL_RED_EXT;
pixelType = GL_UNSIGNED_BYTE;
}
#endif
break;
case ECF_R8G8:
#if defined(GL_EXT_texture_rg)
if (queryGLESFeature(COGLESCoreExtensionHandler::IRR_GL_EXT_texture_rg))
{
supported = true;
pixelFormat = GL_RG_EXT;
pixelType = GL_UNSIGNED_BYTE;
}
#endif
break;
case ECF_R16:
break;
case ECF_R16G16:
break;
case ECF_R16F:
#if defined(GL_OES_texture_half_float) && defined(GL_EXT_texture_rg)
if (queryGLESFeature(COGLESCoreExtensionHandler::IRR_GL_EXT_texture_rg)
&& queryGLESFeature(COGLESCoreExtensionHandler::IRR_GL_OES_texture_half_float)
)
{
supported = true;
pixelFormat = GL_RED_EXT;
pixelType = GL_HALF_FLOAT_OES ;
}
#endif
break;
case ECF_G16R16F:
#if defined(GL_OES_texture_half_float) && defined(GL_EXT_texture_rg)
if (queryGLESFeature(COGLESCoreExtensionHandler::IRR_GL_EXT_texture_rg)
&& queryGLESFeature(COGLESCoreExtensionHandler::IRR_GL_OES_texture_half_float)
)
{
supported = true;
pixelFormat = GL_RG_EXT;
pixelType = GL_HALF_FLOAT_OES ;
}
#endif
break;
case ECF_A16B16G16R16F:
#if defined(GL_OES_texture_half_float)
if (queryGLESFeature(COGLESCoreExtensionHandler::IRR_GL_OES_texture_half_float))
{
supported = true;
pixelFormat = GL_RGBA;
pixelType = GL_HALF_FLOAT_OES ;
}
#endif
break;
case ECF_R32F:
#if defined(GL_OES_texture_float) && defined(GL_EXT_texture_rg)
if (queryGLESFeature(COGLESCoreExtensionHandler::IRR_GL_EXT_texture_rg)
&& queryGLESFeature(COGLESCoreExtensionHandler::IRR_GL_OES_texture_float)
)
{
supported = true;
pixelFormat = GL_RED_EXT;
pixelType = GL_FLOAT;
}
#endif
break;
case ECF_G32R32F:
#if defined(GL_OES_texture_float) && defined(GL_EXT_texture_rg)
if (queryGLESFeature(COGLESCoreExtensionHandler::IRR_GL_EXT_texture_rg)
&& queryGLESFeature(COGLESCoreExtensionHandler::IRR_GL_OES_texture_float)
)
{
supported = true;
pixelFormat = GL_RG_EXT;
pixelType = GL_FLOAT;
}
#endif
break;
case ECF_A32B32G32R32F:
#if defined(GL_OES_texture_float)
if (queryGLESFeature(COGLESCoreExtensionHandler::IRR_GL_OES_texture_half_float))
{
supported = true;
pixelFormat = GL_RGBA;
pixelType = GL_FLOAT ;
}
#endif
break;
default:
break;
}
// ES 2.0 says internalFormat must match pixelFormat (chapter 3.7.1 in Spec).
// Doesn't mention if "match" means "equal" or some other way of matching, but
// some bug on Emscripten and browsing discussions by others lead me to believe
// it means they have to be equal. Note that this was different in OpenGL.
internalFormat = pixelFormat;
#ifdef _IRR_IOS_PLATFORM_
if (internalFormat == GL_BGRA)
internalFormat = GL_RGBA;
#endif
return supported;
} }
bool COpenGL3DriverBase::queryTextureFormat(ECOLOR_FORMAT format) const bool COpenGL3DriverBase::queryTextureFormat(ECOLOR_FORMAT format) const
{ {
GLint dummyInternalFormat; return TextureFormats[format].InternalFormat != 0;
GLenum dummyPixelFormat;
GLenum dummyPixelType;
void (*dummyConverter)(const void*, s32, void*);
return getColorFormatParameters(format, dummyInternalFormat, dummyPixelFormat, dummyPixelType, &dummyConverter);
} }
bool COpenGL3DriverBase::needsTransparentRenderPass(const irr::video::SMaterial& material) const bool COpenGL3DriverBase::needsTransparentRenderPass(const irr::video::SMaterial& material) const

@ -365,6 +365,15 @@ namespace video
core::matrix4 TextureFlipMatrix; core::matrix4 TextureFlipMatrix;
using FColorConverter = void(*)(const void *source, s32 count, void *dest);
struct STextureFormatInfo {
GLenum InternalFormat;
GLenum PixelFormat;
GLenum PixelType;
FColorConverter Converter;
};
STextureFormatInfo TextureFormats[ECF_UNKNOWN] = {};
private: private:
COpenGL3Renderer2D* MaterialRenderer2DActive; COpenGL3Renderer2D* MaterialRenderer2DActive;

@ -70,16 +70,6 @@ namespace video
case EVDF_MRT_BLEND_FUNC: case EVDF_MRT_BLEND_FUNC:
case EVDF_OCCLUSION_QUERY: case EVDF_OCCLUSION_QUERY:
return false; return false;
case EVDF_TEXTURE_COMPRESSED_DXT:
return false; // NV Tegra need improvements here
case EVDF_TEXTURE_COMPRESSED_PVRTC:
return FeatureAvailable[IRR_GL_IMG_texture_compression_pvrtc];
case EVDF_TEXTURE_COMPRESSED_PVRTC2:
return FeatureAvailable[IRR_GL_IMG_texture_compression_pvrtc2];
case EVDF_TEXTURE_COMPRESSED_ETC1:
return FeatureAvailable[IRR_GL_OES_compressed_ETC1_RGB8_texture];
case EVDF_TEXTURE_COMPRESSED_ETC2:
return false;
case EVDF_STENCIL_BUFFER: case EVDF_STENCIL_BUFFER:
return StencilBuffer; return StencilBuffer;
default: default:
@ -101,13 +91,13 @@ namespace video
inline void irrGlCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, inline void irrGlCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border,
GLsizei imageSize, const void* data) GLsizei imageSize, const void* data)
{ {
glCompressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data); os::Printer::log("Compressed textures aren't supported", ELL_ERROR);
} }
inline void irrGlCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, inline void irrGlCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
GLenum format, GLsizei imageSize, const void* data) GLenum format, GLsizei imageSize, const void* data)
{ {
glCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data); os::Printer::log("Compressed textures aren't supported", ELL_ERROR);
} }
inline void irrGlUseProgram(GLuint prog) inline void irrGlUseProgram(GLuint prog)

@ -33,6 +33,24 @@ namespace video {
assert (isVersionAtLeast(3, 2)); assert (isVersionAtLeast(3, 2));
initExtensionsNew(); initExtensionsNew();
TextureFormats[ECF_A1R5G5B5] = {GL_RGB5_A1, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV}; // WARNING: may not be renderable
TextureFormats[ECF_R5G6B5] = {GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5}; // GL_RGB565 is an extension until 4.1
TextureFormats[ECF_R8G8B8] = {GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE}; // WARNING: may not be renderable
TextureFormats[ECF_A8R8G8B8] = {GL_RGBA8, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV};
TextureFormats[ECF_R16F] = {GL_R16F, GL_RED, GL_HALF_FLOAT};
TextureFormats[ECF_G16R16F] = {GL_RG16F, GL_RG, GL_HALF_FLOAT};
TextureFormats[ECF_A16B16G16R16F] = {GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT};
TextureFormats[ECF_R32F] = {GL_R32F, GL_RED, GL_FLOAT};
TextureFormats[ECF_G32R32F] = {GL_RG32F, GL_RG, GL_FLOAT};
TextureFormats[ECF_A32B32G32R32F] = {GL_RGBA32F, GL_RGBA, GL_FLOAT};
TextureFormats[ECF_R8] = {GL_R8, GL_RED, GL_UNSIGNED_BYTE};
TextureFormats[ECF_R8G8] = {GL_RG8, GL_RG, GL_UNSIGNED_BYTE};
TextureFormats[ECF_R16] = {GL_R16, GL_RED, GL_UNSIGNED_SHORT};
TextureFormats[ECF_R16G16] = {GL_RG16, GL_RG, GL_UNSIGNED_SHORT};
TextureFormats[ECF_D16] = {GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT};
TextureFormats[ECF_D32] = {GL_DEPTH_COMPONENT32, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT}; // WARNING: may not be renderable (?!)
TextureFormats[ECF_D24S8] = {GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8};
AnisotropicFilterSupported = isVersionAtLeast(4, 6) || queryExtension("GL_ARB_texture_filter_anisotropic") || queryExtension("GL_EXT_texture_filter_anisotropic"); AnisotropicFilterSupported = isVersionAtLeast(4, 6) || queryExtension("GL_ARB_texture_filter_anisotropic") || queryExtension("GL_EXT_texture_filter_anisotropic");
BlendMinMaxSupported = true; BlendMinMaxSupported = true;

@ -4,6 +4,7 @@
#include "Driver.h" #include "Driver.h"
#include <cassert> #include <cassert>
#include <CColorConverter.h>
namespace irr { namespace irr {
namespace video { namespace video {
@ -30,6 +31,76 @@ namespace video {
else else
initExtensionsOld(); initExtensionsOld();
if (Version.Major >= 3) {
// NOTE floating-point formats may not be suitable for render targets.
TextureFormats[ECF_A1R5G5B5] = {GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, CColorConverter::convert_A1R5G5B5toR5G5B5A1};
TextureFormats[ECF_R5G6B5] = {GL_RGB565, GL_RGB, GL_UNSIGNED_SHORT_5_6_5};
TextureFormats[ECF_R8G8B8] = {GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE};
TextureFormats[ECF_A8R8G8B8] = {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, CColorConverter::convert_A8R8G8B8toA8B8G8R8};
TextureFormats[ECF_R16F] = {GL_R16F, GL_RED, GL_HALF_FLOAT};
TextureFormats[ECF_G16R16F] = {GL_RG16F, GL_RG, GL_HALF_FLOAT};
TextureFormats[ECF_A16B16G16R16F] = {GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT};
TextureFormats[ECF_R32F] = {GL_R32F, GL_RED, GL_FLOAT};
TextureFormats[ECF_G32R32F] = {GL_RG32F, GL_RG, GL_FLOAT};
TextureFormats[ECF_A32B32G32R32F] = {GL_RGBA32F, GL_RGBA, GL_FLOAT};
TextureFormats[ECF_R8] = {GL_R8, GL_RED, GL_UNSIGNED_BYTE};
TextureFormats[ECF_R8G8] = {GL_RG8, GL_RG, GL_UNSIGNED_BYTE};
TextureFormats[ECF_D16] = {GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT};
TextureFormats[ECF_D24S8] = {GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8};
if (FeatureAvailable[IRR_GL_EXT_texture_format_BGRA8888])
TextureFormats[ECF_A8R8G8B8] = {GL_RGBA, GL_BGRA, GL_UNSIGNED_BYTE};
else if (FeatureAvailable[IRR_GL_APPLE_texture_format_BGRA8888])
TextureFormats[ECF_A8R8G8B8] = {GL_BGRA, GL_BGRA, GL_UNSIGNED_BYTE};
if (FeatureAvailable[IRR_GL_OES_depth32])
TextureFormats[ECF_D32] = {GL_DEPTH_COMPONENT32, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT};
} else {
// NOTE These are *texture* formats. They may or may not be suitable
// for render targets. The specs only talks on *sized* formats for the
// latter but forbids creating textures with sized internal formats,
// reserving them for renderbuffers.
static const GLenum HALF_FLOAT_OES = 0x8D61; // not equal to GL_HALF_FLOAT
TextureFormats[ECF_A1R5G5B5] = {GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, CColorConverter::convert_A1R5G5B5toR5G5B5A1};
TextureFormats[ECF_R5G6B5] = {GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5};
TextureFormats[ECF_R8G8B8] = {GL_RGB, GL_RGB, GL_UNSIGNED_BYTE};
TextureFormats[ECF_A8R8G8B8] = {GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, CColorConverter::convert_A8R8G8B8toA8B8G8R8};
if (FeatureAvailable[IRR_GL_EXT_texture_format_BGRA8888])
TextureFormats[ECF_A8R8G8B8] = {GL_RGBA, GL_BGRA, GL_UNSIGNED_BYTE};
else if (FeatureAvailable[IRR_GL_APPLE_texture_format_BGRA8888])
TextureFormats[ECF_A8R8G8B8] = {GL_BGRA, GL_BGRA, GL_UNSIGNED_BYTE};
if (FeatureAvailable[IRR_GL_OES_texture_half_float]) {
TextureFormats[ECF_A16B16G16R16F] = {GL_RGBA, GL_RGBA, HALF_FLOAT_OES};
}
if (FeatureAvailable[IRR_GL_OES_texture_float]) {
TextureFormats[ECF_A32B32G32R32F] = {GL_RGBA, GL_RGBA, GL_FLOAT};
}
if (FeatureAvailable[IRR_GL_EXT_texture_rg]) {
TextureFormats[ECF_R8] = {GL_RED, GL_RED, GL_UNSIGNED_BYTE};
TextureFormats[ECF_R8G8] = {GL_RG, GL_RG, GL_UNSIGNED_BYTE};
if (FeatureAvailable[IRR_GL_OES_texture_half_float]) {
TextureFormats[ECF_R16F] = {GL_RED, GL_RED, HALF_FLOAT_OES};
TextureFormats[ECF_G16R16F] = {GL_RG, GL_RG, HALF_FLOAT_OES};
}
if (FeatureAvailable[IRR_GL_OES_texture_float]) {
TextureFormats[ECF_R32F] = {GL_RED, GL_RED, GL_FLOAT};
TextureFormats[ECF_G32R32F] = {GL_RG, GL_RG, GL_FLOAT};
}
}
if (FeatureAvailable[IRR_GL_OES_depth_texture]) {
TextureFormats[ECF_D16] = {GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT};
if (FeatureAvailable[IRR_GL_OES_depth32])
TextureFormats[ECF_D32] = {GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT};
if (FeatureAvailable[IRR_GL_OES_packed_depth_stencil])
TextureFormats[ECF_D24S8] = {GL_DEPTH_STENCIL, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8};
}
}
const bool MRTSupported = Version.Major >= 3 || queryExtension("GL_EXT_draw_buffers"); const bool MRTSupported = Version.Major >= 3 || queryExtension("GL_EXT_draw_buffers");
AnisotropicFilterSupported = queryExtension("GL_EXT_texture_filter_anisotropic"); AnisotropicFilterSupported = queryExtension("GL_EXT_texture_filter_anisotropic");
BlendMinMaxSupported = (Version.Major >= 3) || FeatureAvailable[IRR_GL_EXT_blend_minmax]; BlendMinMaxSupported = (Version.Major >= 3) || FeatureAvailable[IRR_GL_EXT_blend_minmax];