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,
GLenum& pixelType, void(**converter)(const void*, s32, void*)) const
{
bool supported = false;
pixelFormat = GL_RGBA;
pixelType = GL_UNSIGNED_BYTE;
*converter = 0;
switch (format)
{
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;
auto &info = TextureFormats[format];
internalFormat = info.InternalFormat;
pixelFormat = info.PixelFormat;
pixelType = info.PixelType;
*converter = info.Converter;
return info.InternalFormat != 0;
}
bool COpenGL3DriverBase::queryTextureFormat(ECOLOR_FORMAT format) const
{
GLint dummyInternalFormat;
GLenum dummyPixelFormat;
GLenum dummyPixelType;
void (*dummyConverter)(const void*, s32, void*);
return getColorFormatParameters(format, dummyInternalFormat, dummyPixelFormat, dummyPixelType, &dummyConverter);
return TextureFormats[format].InternalFormat != 0;
}
bool COpenGL3DriverBase::needsTransparentRenderPass(const irr::video::SMaterial& material) const

@ -365,6 +365,15 @@ namespace video
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:
COpenGL3Renderer2D* MaterialRenderer2DActive;

@ -70,16 +70,6 @@ namespace video
case EVDF_MRT_BLEND_FUNC:
case EVDF_OCCLUSION_QUERY:
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:
return StencilBuffer;
default:
@ -101,13 +91,13 @@ namespace video
inline void irrGlCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border,
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,
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)

@ -33,6 +33,24 @@ namespace video {
assert (isVersionAtLeast(3, 2));
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");
BlendMinMaxSupported = true;

@ -4,6 +4,7 @@
#include "Driver.h"
#include <cassert>
#include <CColorConverter.h>
namespace irr {
namespace video {
@ -30,6 +31,76 @@ namespace video {
else
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");
AnisotropicFilterSupported = queryExtension("GL_EXT_texture_filter_anisotropic");
BlendMinMaxSupported = (Version.Major >= 3) || FeatureAvailable[IRR_GL_EXT_blend_minmax];