From 1387370260330a4c8500634c8c24cc699639d039 Mon Sep 17 00:00:00 2001 From: numzero Date: Thu, 20 Apr 2023 17:40:51 +0300 Subject: [PATCH] OpenGL3: Sort out texture color format support --- source/Irrlicht/OpenGL/Driver.cpp | 223 +--------------------- source/Irrlicht/OpenGL/Driver.h | 9 + source/Irrlicht/OpenGL/ExtensionHandler.h | 14 +- source/Irrlicht/OpenGL3/Driver.cpp | 18 ++ source/Irrlicht/OpenGLES2/Driver.cpp | 71 +++++++ 5 files changed, 107 insertions(+), 228 deletions(-) diff --git a/source/Irrlicht/OpenGL/Driver.cpp b/source/Irrlicht/OpenGL/Driver.cpp index 8994be63..f49228ba 100644 --- a/source/Irrlicht/OpenGL/Driver.cpp +++ b/source/Irrlicht/OpenGL/Driver.cpp @@ -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 diff --git a/source/Irrlicht/OpenGL/Driver.h b/source/Irrlicht/OpenGL/Driver.h index 0b5a3854..862c79d5 100644 --- a/source/Irrlicht/OpenGL/Driver.h +++ b/source/Irrlicht/OpenGL/Driver.h @@ -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; diff --git a/source/Irrlicht/OpenGL/ExtensionHandler.h b/source/Irrlicht/OpenGL/ExtensionHandler.h index 57106f0c..84641dd4 100644 --- a/source/Irrlicht/OpenGL/ExtensionHandler.h +++ b/source/Irrlicht/OpenGL/ExtensionHandler.h @@ -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) diff --git a/source/Irrlicht/OpenGL3/Driver.cpp b/source/Irrlicht/OpenGL3/Driver.cpp index 66574793..70343a85 100644 --- a/source/Irrlicht/OpenGL3/Driver.cpp +++ b/source/Irrlicht/OpenGL3/Driver.cpp @@ -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; diff --git a/source/Irrlicht/OpenGLES2/Driver.cpp b/source/Irrlicht/OpenGLES2/Driver.cpp index 5766e8a5..2e80e1be 100644 --- a/source/Irrlicht/OpenGLES2/Driver.cpp +++ b/source/Irrlicht/OpenGLES2/Driver.cpp @@ -4,6 +4,7 @@ #include "Driver.h" #include +#include 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];