0032089: Visualization, TKOpenGl - support GL_EXT_sRGB extension to OpenGL ES 2.0
authorkgv <kgv@opencascade.com>
Thu, 16 Sep 2021 07:50:18 +0000 (10:50 +0300)
committersmoskvin <smoskvin@opencascade.com>
Fri, 17 Sep 2021 17:07:39 +0000 (20:07 +0300)
src/OpenGl/OpenGl_Context.cxx
src/OpenGl/OpenGl_Context.hxx
src/OpenGl/OpenGl_GLESExtensions.hxx
src/OpenGl/OpenGl_GlFunctions.cxx
src/OpenGl/OpenGl_Texture.cxx
src/OpenGl/OpenGl_TextureFormat.cxx

index 9dd3afd..38c27c2 100644 (file)
@@ -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;
index 893047b..f2a205f 100644 (file)
@@ -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
index 03fb90b..30d0181 100644 (file)
@@ -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
index 0ee1aef..6768858 100644 (file)
@@ -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");
index 16a4f20..759a12f 100644 (file)
@@ -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;
index 02b1d0a..14a8972 100644 (file)
@@ -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())
-      {
-        aFormat.SetInternalFormat (GL_RGB8); // fallback format
+      if ((theSizedFormat == GL_SRGB8 || theSizedFormat == GL_SRGB_EXT))
+      {
+        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;
     }