From eee6a80a90d88091747de0bf8096a36d703f4df9 Mon Sep 17 00:00:00 2001 From: kgv Date: Thu, 16 Sep 2021 10:50:18 +0300 Subject: [PATCH] 0032089: Visualization, TKOpenGl - support GL_EXT_sRGB extension to OpenGL ES 2.0 --- src/OpenGl/OpenGl_Context.cxx | 11 ++++- src/OpenGl/OpenGl_Context.hxx | 2 +- src/OpenGl/OpenGl_GLESExtensions.hxx | 4 ++ src/OpenGl/OpenGl_GlFunctions.cxx | 7 +++ src/OpenGl/OpenGl_Texture.cxx | 25 +++++++++-- src/OpenGl/OpenGl_TextureFormat.cxx | 66 +++++++++++++++++++++++----- 6 files changed, 97 insertions(+), 18 deletions(-) diff --git a/src/OpenGl/OpenGl_Context.cxx b/src/OpenGl/OpenGl_Context.cxx index 9dd3afd573..38c27c2015 100644 --- a/src/OpenGl/OpenGl_Context.cxx +++ b/src/OpenGl/OpenGl_Context.cxx @@ -1650,8 +1650,15 @@ void OpenGl_Context::init (const Standard_Boolean theIsCoreProfile) GL_BACK; #endif GLint aWinColorEncoding = 0; // GL_LINEAR - arbFBO->glGetFramebufferAttachmentParameteriv (GL_FRAMEBUFFER, aDefWinBuffer, GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING, &aWinColorEncoding); - ResetErrors (true); + bool toSkipCheck = false; + #if defined(GL_ES_VERSION_2_0) + toSkipCheck = !IsGlGreaterEqual (3, 0); + #endif + if (!toSkipCheck) + { + arbFBO->glGetFramebufferAttachmentParameteriv (GL_FRAMEBUFFER, aDefWinBuffer, GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING, &aWinColorEncoding); + ResetErrors (true); + } myIsSRgbWindow = aWinColorEncoding == GL_SRGB; // On desktop OpenGL, pixel formats are almost always sRGB-ready, even when not requested; diff --git a/src/OpenGl/OpenGl_Context.hxx b/src/OpenGl/OpenGl_Context.hxx index 893047b0f6..f2a205fa31 100644 --- a/src/OpenGl/OpenGl_Context.hxx +++ b/src/OpenGl/OpenGl_Context.hxx @@ -1047,7 +1047,7 @@ public: //! @name extensions Standard_Boolean hasUintIndex; //!< GLuint for index buffer is supported (always available on desktop; on OpenGL ES - since 3.0 or as extension GL_OES_element_index_uint) Standard_Boolean hasTexRGBA8; //!< always available on desktop; on OpenGL ES - since 3.0 or as extension GL_OES_rgb8_rgba8 Standard_Boolean hasTexFloatLinear; //!< texture-filterable state for 32-bit floating texture formats (always on desktop, GL_OES_texture_float_linear within OpenGL ES) - Standard_Boolean hasTexSRGB; //!< sRGB texture formats (desktop OpenGL 2.1, OpenGL ES 3.0 or GL_EXT_texture_sRGB) + Standard_Boolean hasTexSRGB; //!< sRGB texture formats (desktop OpenGL 2.1, OpenGL ES 3.0 or OpenGL ES 2.0 + GL_EXT_sRGB) Standard_Boolean hasFboSRGB; //!< sRGB FBO render targets (desktop OpenGL 2.1, OpenGL ES 3.0) Standard_Boolean hasSRGBControl; //!< sRGB write control (any desktop OpenGL, OpenGL ES + GL_EXT_sRGB_write_control extension) Standard_Boolean hasFboRenderMipmap; //!< FBO render target could be non-zero mipmap level of texture diff --git a/src/OpenGl/OpenGl_GLESExtensions.hxx b/src/OpenGl/OpenGl_GLESExtensions.hxx index 03fb90b2ec..30d0181f50 100644 --- a/src/OpenGl/OpenGl_GLESExtensions.hxx +++ b/src/OpenGl/OpenGl_GLESExtensions.hxx @@ -33,6 +33,10 @@ typedef double GLclampd; // GL_EXT_texture_format_BGRA8888 #define GL_BGRA_EXT 0x80E1 // same as GL_BGRA on desktop +// GL_EXT_sRGB +#define GL_SRGB_EXT 0x8C40 // GL_SRGB_EXT +#define GL_SRGB_ALPHA_EXT 0x8C42 // GL_SRGB_ALPHA_EXT + #define GL_R16 0x822A #define GL_RGB4 0x804F #define GL_RGB5 0x8050 diff --git a/src/OpenGl/OpenGl_GlFunctions.cxx b/src/OpenGl/OpenGl_GlFunctions.cxx index 0ee1aef309..67688584bb 100644 --- a/src/OpenGl/OpenGl_GlFunctions.cxx +++ b/src/OpenGl/OpenGl_GlFunctions.cxx @@ -78,6 +78,13 @@ void OpenGl_GlFunctions::load (OpenGl_Context& theCtx, || checkExtensionShort ("GL_OES_rgb8_rgba8"); theCtx.hasTexSRGB = isGlGreaterEqualShort (3, 0); theCtx.hasFboSRGB = isGlGreaterEqualShort (3, 0); + if (!isGlGreaterEqualShort (3, 0) + && checkExtensionShort ("GL_EXT_sRGB")) + { + // limited support + theCtx.hasTexSRGB = true; + theCtx.hasFboSRGB = true; + } theCtx.hasFboRenderMipmap = isGlGreaterEqualShort (3, 0) || checkExtensionShort ("GL_OES_fbo_render_mipmap"); theCtx.hasSRGBControl = checkExtensionShort ("GL_EXT_sRGB_write_control"); diff --git a/src/OpenGl/OpenGl_Texture.cxx b/src/OpenGl/OpenGl_Texture.cxx index 16a4f20f48..759a12fe3f 100644 --- a/src/OpenGl/OpenGl_Texture.cxx +++ b/src/OpenGl/OpenGl_Texture.cxx @@ -336,10 +336,9 @@ bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx, || theSizeXY.y() != aHeightP2) { 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 ("Warning: Mipmap NPOT Textures (") + theSizeXY.x() + "x" + theSizeXY.y() + ")" " are not supported by OpenGL ES 2.0 [" + myResourceId +"]"); - Release (theCtx.get()); - return false; + myMaxMipLevel = 0; } } #endif @@ -1012,6 +1011,20 @@ bool OpenGl_Texture::InitCubeMap (const Handle(OpenGl_Context)& theCtx, return false; } +#if defined(GL_ES_VERSION_2_0) + if (theToGenMipmap + && !theCtx->IsGlGreaterEqual (3, 0) + && (aFormat.PixelFormat() == GL_SRGB_EXT + || aFormat.PixelFormat() == GL_SRGB_ALPHA_EXT)) + { + theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH, + TCollection_AsciiString ("Warning, GL_EXT_sRGB disallows generation of mipmaps - fallback using non-sRGB format") + + " [" + myResourceId +"]"); + aFormat.SetPixelFormat (aFormat.PixelFormat() == GL_SRGB_EXT ? GL_RGB : GL_RGBA); + aFormat.SetInternalFormat(aFormat.PixelFormat() == GL_SRGB_EXT ? GL_RGB8 : GL_RGBA8); + } +#endif + myTarget = GL_TEXTURE_CUBE_MAP; myNbSamples = 1; mySizeX = (GLsizei )theSize; @@ -1132,7 +1145,11 @@ 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 initialize side of cubemap. Error ") + OpenGl_Context::FormatGlError (anErr)); + TCollection_AsciiString ("Error: cubemap side ") + (int )theSize + "x" + (int )theSize + + " IF: " + OpenGl_TextureFormat::FormatFormat (anIntFormat) + + " PF: " + OpenGl_TextureFormat::FormatFormat (aFormat.PixelFormat()) + + " DT: " + OpenGl_TextureFormat::FormatDataType (aFormat.DataType()) + + " can not be created with error " + OpenGl_Context::FormatGlError (anErr) + "."); Unbind (theCtx); Release (theCtx.get()); return false; diff --git a/src/OpenGl/OpenGl_TextureFormat.cxx b/src/OpenGl/OpenGl_TextureFormat.cxx index 02b1d0a727..14a89723a4 100644 --- a/src/OpenGl/OpenGl_TextureFormat.cxx +++ b/src/OpenGl/OpenGl_TextureFormat.cxx @@ -46,6 +46,7 @@ TCollection_AsciiString OpenGl_TextureFormat::FormatFormat (GLint theInternalFor case 0x8050: return "GL_RGB5"; case GL_RGB8: return "GL_RGB8"; case GL_SRGB8: return "GL_SRGB8"; + case GL_SRGB_EXT: return "GL_SRGB_EXT"; case 0x8052: return "GL_RGB10"; case 0x8053: return "GL_RGB12"; case 0x8054: return "GL_RGB16"; @@ -55,7 +56,8 @@ TCollection_AsciiString OpenGl_TextureFormat::FormatFormat (GLint theInternalFor // RGBA variations case GL_RGBA: return "GL_RGBA"; case GL_RGBA8: return "GL_RGBA8"; - case GL_SRGB8_ALPHA8: return "GL_SRGB8_ALPHA8"; + case GL_SRGB8_ALPHA8: return "GL_SRGB8_ALPHA8"; + case GL_SRGB_ALPHA_EXT: return "GL_SRGB_ALPHA_EXT"; case GL_RGB10_A2: return "GL_RGB10_A2"; case 0x805A: return "GL_RGBA12"; case 0x805B: return "GL_RGBA16"; @@ -259,6 +261,12 @@ OpenGl_TextureFormat OpenGl_TextureFormat::FindFormat (const Handle(OpenGl_Conte if (theIsColorMap && theCtx->ToRenderSRGB()) { + #if defined(GL_ES_VERSION_2_0) + if (!theCtx->IsGlGreaterEqual (3, 0)) + { + aFormat.SetPixelFormat (GL_SRGB_ALPHA_EXT); + } + #endif aFormat.SetInternalFormat (GL_SRGB8_ALPHA8); } return aFormat; @@ -301,6 +309,8 @@ OpenGl_TextureFormat OpenGl_TextureFormat::FindFormat (const Handle(OpenGl_Conte // ask driver to convert data to RGB8 to save memory aFormat.SetNbComponents (3); aFormat.SetInternalFormat (GL_RGB8); + aFormat.SetPixelFormat (GL_RGBA); + aFormat.SetDataType (GL_UNSIGNED_BYTE); if (theIsColorMap && theCtx->ToRenderSRGB()) { @@ -310,14 +320,18 @@ OpenGl_TextureFormat OpenGl_TextureFormat::FindFormat (const Handle(OpenGl_Conte // conversion is not supported aFormat.SetNbComponents (4); aFormat.SetInternalFormat (GL_RGBA8); + aFormat.SetPixelFormat (GL_RGBA); + aFormat.SetDataType (GL_UNSIGNED_BYTE); if (theIsColorMap && theCtx->ToRenderSRGB()) { + if (!theCtx->IsGlGreaterEqual (3, 0)) + { + aFormat.SetPixelFormat (GL_SRGB_ALPHA_EXT); + } aFormat.SetInternalFormat (GL_SRGB8_ALPHA8); } #endif - aFormat.SetPixelFormat (GL_RGBA); - aFormat.SetDataType (GL_UNSIGNED_BYTE); return aFormat; } case Image_Format_BGR32: @@ -360,6 +374,12 @@ OpenGl_TextureFormat OpenGl_TextureFormat::FindFormat (const Handle(OpenGl_Conte if (theIsColorMap && theCtx->ToRenderSRGB()) { + #if defined(GL_ES_VERSION_2_0) + if (!theCtx->IsGlGreaterEqual (3, 0)) + { + aFormat.SetPixelFormat (GL_SRGB_EXT); + } + #endif aFormat.SetInternalFormat (GL_SRGB8); } return aFormat; @@ -374,13 +394,13 @@ OpenGl_TextureFormat OpenGl_TextureFormat::FindFormat (const Handle(OpenGl_Conte } aFormat.SetNbComponents (3); aFormat.SetInternalFormat (GL_RGB8); + aFormat.SetPixelFormat (GL_BGR); // equals to GL_BGR_EXT + aFormat.SetDataType (GL_UNSIGNED_BYTE); if (theIsColorMap && theCtx->ToRenderSRGB()) { aFormat.SetInternalFormat (GL_SRGB8); } - aFormat.SetPixelFormat (GL_BGR); // equals to GL_BGR_EXT - aFormat.SetDataType (GL_UNSIGNED_BYTE); #endif return aFormat; } @@ -521,6 +541,7 @@ OpenGl_TextureFormat OpenGl_TextureFormat::FindSizedFormat (const Handle(OpenGl_ return aFormat; } case GL_SRGB8_ALPHA8: + case GL_SRGB_ALPHA_EXT: case GL_RGBA8: case GL_RGBA: { @@ -529,14 +550,26 @@ OpenGl_TextureFormat OpenGl_TextureFormat::FindSizedFormat (const Handle(OpenGl_ aFormat.SetPixelFormat (GL_RGBA); aFormat.SetDataType (GL_UNSIGNED_BYTE); aFormat.SetImageFormat (Image_Format_RGBA); - if (theSizedFormat == GL_SRGB8_ALPHA8 - && !theCtx->ToRenderSRGB()) + if ((theSizedFormat == GL_SRGB8_ALPHA8 || theSizedFormat == GL_SRGB_ALPHA_EXT)) { - aFormat.SetInternalFormat (GL_RGBA8); // fallback format + if (theCtx->ToRenderSRGB()) + { + #if defined(GL_ES_VERSION_2_0) + if (!theCtx->IsGlGreaterEqual (3, 0)) + { + aFormat.SetPixelFormat (GL_SRGB_ALPHA_EXT); + } + #endif + } + else + { + aFormat.SetInternalFormat (GL_RGBA8); // fallback format + } } return aFormat; } case GL_SRGB8: + case GL_SRGB_EXT: case GL_RGB8: case GL_RGB: { @@ -545,10 +578,21 @@ OpenGl_TextureFormat OpenGl_TextureFormat::FindSizedFormat (const Handle(OpenGl_ aFormat.SetPixelFormat (GL_RGB); aFormat.SetDataType (GL_UNSIGNED_BYTE); aFormat.SetImageFormat (Image_Format_RGB); - if (theSizedFormat == GL_SRGB8 - && !theCtx->ToRenderSRGB()) + if ((theSizedFormat == GL_SRGB8 || theSizedFormat == GL_SRGB_EXT)) { - aFormat.SetInternalFormat (GL_RGB8); // fallback format + if (theCtx->ToRenderSRGB()) + { + #if defined(GL_ES_VERSION_2_0) + if (!theCtx->IsGlGreaterEqual (3, 0)) + { + aFormat.SetPixelFormat (GL_SRGB_EXT); + } + #endif + } + else + { + aFormat.SetInternalFormat (GL_RGB8); // fallback format + } } return aFormat; }