From 177781da922e123b9e04f1b3da223dfa8734f29d Mon Sep 17 00:00:00 2001 From: kgv Date: Thu, 8 Jun 2017 10:44:17 +0300 Subject: [PATCH] 0028826: Visualization, TKOpenGl - fix compatibility with strict OpenGL ES drivers OpenGl_ShaderProgram::Initialize() - precision declarations have been moved after the list of enabled extensions. Declarations.glsl - the fragment shader outputs have been re-declared as array for proper assignment of default locations (draw buffers). OpenGl_FrameBuffer - GL_HALF_FLOAT is now used instead of GL_HALF_FLOAT_OES on OpenGL ES 3.2+. OpenGl_Texture - fixed initialization of Image_Format_RGB32 image format on OpenGL ES 3.0+. --- src/OpenGl/OpenGl_FrameBuffer.cxx | 23 +++++++++++-- src/OpenGl/OpenGl_GlFunctions.hxx | 5 +-- src/OpenGl/OpenGl_GraphicDriver.cxx | 8 +++-- src/OpenGl/OpenGl_ShaderProgram.cxx | 4 +-- src/OpenGl/OpenGl_Texture.cxx | 40 ++++++++++++++++++++--- src/OpenGl/OpenGl_View_Redraw.cxx | 16 ++++----- src/Shaders/Declarations.glsl | 7 ++-- src/Shaders/Shaders_Declarations_glsl.pxx | 7 ++-- 8 files changed, 85 insertions(+), 25 deletions(-) diff --git a/src/OpenGl/OpenGl_FrameBuffer.cxx b/src/OpenGl/OpenGl_FrameBuffer.cxx index ef3cdf6acd..f58dd92276 100644 --- a/src/OpenGl/OpenGl_FrameBuffer.cxx +++ b/src/OpenGl/OpenGl_FrameBuffer.cxx @@ -65,7 +65,8 @@ namespace } //! Determine data type from texture sized format. - static bool getColorDataFormat (GLint theTextFormat, + static bool getColorDataFormat (const Handle(OpenGl_Context)& theGlContext, + GLint theTextFormat, GLenum& thePixelFormat, GLenum& theDataType) { @@ -87,12 +88,28 @@ namespace { thePixelFormat = GL_RGBA; theDataType = GL_HALF_FLOAT; + if (theGlContext->hasHalfFloatBuffer == OpenGl_FeatureInExtensions) + { + #if defined(GL_ES_VERSION_2_0) + theDataType = GL_HALF_FLOAT_OES; + #else + theDataType = GL_FLOAT; + #endif + } return true; } case GL_R16F: { thePixelFormat = GL_RED; theDataType = GL_HALF_FLOAT; + if (theGlContext->hasHalfFloatBuffer == OpenGl_FeatureInExtensions) + { + #if defined(GL_ES_VERSION_2_0) + theDataType = GL_HALF_FLOAT_OES; + #else + theDataType = GL_FLOAT; + #endif + } return true; } case GL_RGBA8: @@ -255,7 +272,7 @@ Standard_Boolean OpenGl_FrameBuffer::Init (const Handle(OpenGl_Context)& theGlCo const Handle(OpenGl_Texture)& aColorTexture = myColorTextures (aColorBufferIdx); const GLint aColorFormat = myColorFormats (aColorBufferIdx); if (aColorFormat != 0 - && getColorDataFormat (aColorFormat, aPixelFormat, aDataType) + && getColorDataFormat (theGlContext, aColorFormat, aPixelFormat, aDataType) && !aColorTexture->Init (theGlContext, aColorFormat, aPixelFormat, aDataType, aSizeX, aSizeY, Graphic3d_TOT_2D)) @@ -386,7 +403,7 @@ Standard_Boolean OpenGl_FrameBuffer::Init (const Handle(OpenGl_Context)& theGlCo const Handle(OpenGl_Texture)& aColorTexture = myColorTextures (aColorBufferIdx); const GLint aColorFormat = myColorFormats (aColorBufferIdx); if (aColorFormat != 0 - && getColorDataFormat (aColorFormat, aPixelFormat, aDataType) + && getColorDataFormat (theGlContext, aColorFormat, aPixelFormat, aDataType) && !aColorTexture->Init (theGlContext, aColorFormat, aPixelFormat, aDataType, aSizeX, aSizeY, Graphic3d_TOT_2D)) diff --git a/src/OpenGl/OpenGl_GlFunctions.hxx b/src/OpenGl/OpenGl_GlFunctions.hxx index daebf8ee79..fca42c5e2f 100644 --- a/src/OpenGl/OpenGl_GlFunctions.hxx +++ b/src/OpenGl/OpenGl_GlFunctions.hxx @@ -191,8 +191,9 @@ #define GL_MAX_COLOR_ATTACHMENTS 0x8CDF #define GL_MAX_DRAW_BUFFERS 0x8824 - // OES_texture_half_float - #define GL_HALF_FLOAT 0x8D61 + // OpenGL ES 3.0+ or OES_texture_half_float + #define GL_HALF_FLOAT 0x140B + #define GL_HALF_FLOAT_OES 0x8D61 #endif #if !defined(HAVE_EGL) && (defined(__ANDROID__) || defined(__QNX__) || defined(HAVE_GLES2) || defined(OCCT_UWP)) diff --git a/src/OpenGl/OpenGl_GraphicDriver.cxx b/src/OpenGl/OpenGl_GraphicDriver.cxx index d3c178a2fa..a409eb19c5 100644 --- a/src/OpenGl/OpenGl_GraphicDriver.cxx +++ b/src/OpenGl/OpenGl_GraphicDriver.cxx @@ -416,9 +416,13 @@ Standard_Integer OpenGl_GraphicDriver::InquireLimit (const Graphic3d_TypeOfLimit case Graphic3d_TypeOfLimit_HasRayTracingAdaptiveSampling: return (!aCtx.IsNull() && aCtx->HasRayTracingAdaptiveSampling()) ? 1 : 0; case Graphic3d_TypeOfLimit_HasBlendedOit: - return (!aCtx.IsNull() && aCtx->hasDrawBuffers && (aCtx->hasFloatBuffer || aCtx->hasHalfFloatBuffer)) ? 1 : 0; + return (!aCtx.IsNull() + && aCtx->hasDrawBuffers != OpenGl_FeatureNotAvailable + && (aCtx->hasFloatBuffer != OpenGl_FeatureNotAvailable || aCtx->hasHalfFloatBuffer != OpenGl_FeatureNotAvailable)) ? 1 : 0; case Graphic3d_TypeOfLimit_HasBlendedOitMsaa: - return (!aCtx.IsNull() && aCtx->hasSampleVariables && (InquireLimit (Graphic3d_TypeOfLimit_HasBlendedOit) == 1)) ? 1 : 0; + return (!aCtx.IsNull() + && aCtx->hasSampleVariables != OpenGl_FeatureNotAvailable + && (InquireLimit (Graphic3d_TypeOfLimit_HasBlendedOit) == 1)) ? 1 : 0; case Graphic3d_TypeOfLimit_NB: return 0; } diff --git a/src/OpenGl/OpenGl_ShaderProgram.cxx b/src/OpenGl/OpenGl_ShaderProgram.cxx index 7e3b8adac9..7d8fe6d77a 100755 --- a/src/OpenGl/OpenGl_ShaderProgram.cxx +++ b/src/OpenGl/OpenGl_ShaderProgram.cxx @@ -206,7 +206,7 @@ Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)& } TCollection_AsciiString aSource = aDeclarations + anIter.Value()->Source(); - TCollection_AsciiString anExtensions = "// This section enables extensions used in OCCT GLSL programs\n"; + TCollection_AsciiString anExtensions = "// Enable extensions used in OCCT GLSL programs\n"; if (theCtx->hasDrawBuffers) { anExtensions += "#define OCC_ENABLE_draw_buffers\n"; @@ -253,7 +253,7 @@ Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)& "precision highp int;\n" : "precision mediump float;\n" "precision mediump int;\n"); - aSource = aHeader + aPrefix + anExtensions + aSource; + aSource = aHeader + anExtensions + aPrefix + aSource; #else aSource = aHeader + anExtensions + aSource; #endif diff --git a/src/OpenGl/OpenGl_Texture.cxx b/src/OpenGl/OpenGl_Texture.cxx index 0603ce5d1d..04bad58076 100644 --- a/src/OpenGl/OpenGl_Texture.cxx +++ b/src/OpenGl/OpenGl_Texture.cxx @@ -266,29 +266,51 @@ bool OpenGl_Texture::GetDataFormat (const Handle(OpenGl_Context)& theCtx, } case Image_Format_BGRA: { + #if !defined(GL_ES_VERSION_2_0) if (!theCtx->IsGlGreaterEqual (1, 2) && !theCtx->extBgra) { return false; } theTextFormat = GL_RGBA8; + #else + if (!theCtx->extBgra) + { + return false; + } + theTextFormat = GL_BGRA_EXT; + #endif thePixelFormat = GL_BGRA_EXT; // equals to GL_BGRA theDataType = GL_UNSIGNED_BYTE; return true; } case Image_Format_RGB32: { - theTextFormat = GL_RGB8; + #if !defined(GL_ES_VERSION_2_0) + // ask driver to convert data to RGB8 to save memory + theTextFormat = GL_RGB8; + #else + // conversion is not supported + theTextFormat = GL_RGBA8; + #endif thePixelFormat = GL_RGBA; theDataType = GL_UNSIGNED_BYTE; return true; } case Image_Format_BGR32: { - if (!theCtx->IsGlGreaterEqual (1, 2) && !theCtx->extBgra) + #if !defined(GL_ES_VERSION_2_0) + if (!theCtx->IsGlGreaterEqual(1, 2) && !theCtx->extBgra) { return false; } theTextFormat = GL_RGB8; + #else + if (!theCtx->extBgra) + { + return false; + } + theTextFormat = GL_BGRA_EXT; + #endif thePixelFormat = GL_BGRA_EXT; // equals to GL_BGRA theDataType = GL_UNSIGNED_BYTE; return true; @@ -590,8 +612,13 @@ bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx, glTexImage2D (GL_TEXTURE_2D, 0, anIntFormat, theSizeX, theSizeY, 0, thePixelFormat, theDataType, aDataPtr); - if (glGetError() != GL_NO_ERROR) + const GLenum anErr = glGetError(); + if (anErr != GL_NO_ERROR) { + theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, + TCollection_AsciiString ("Error: 2D texture ") + theSizeX + "x" + theSizeY + + " IF: " + int(anIntFormat) + " PF: " + int(thePixelFormat) + " DT: " + int(theDataType) + + " can not be created with error " + int(anErr) + "."); Unbind (theCtx); Release (theCtx.operator->()); return false; @@ -663,8 +690,13 @@ bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx, glTexImage2D (GL_TEXTURE_2D, 0, anIntFormat, theSizeX, theSizeY, 0, thePixelFormat, theDataType, theImage->Data()); - if (glGetError() != GL_NO_ERROR) + const GLenum aTexImgErr = glGetError(); + if (aTexImgErr != GL_NO_ERROR) { + theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, + TCollection_AsciiString ("Error: 2D texture ") + theSizeX + "x" + theSizeY + + " IF: " + int(anIntFormat) + " PF: " + int(thePixelFormat) + " DT: " + int(theDataType) + + " can not be created with error " + int(aTexImgErr) + "."); Unbind (theCtx); Release (theCtx.operator->()); return false; diff --git a/src/OpenGl/OpenGl_View_Redraw.cxx b/src/OpenGl/OpenGl_View_Redraw.cxx index 0c4aa802dc..1491a7cd4f 100644 --- a/src/OpenGl/OpenGl_View_Redraw.cxx +++ b/src/OpenGl/OpenGl_View_Redraw.cxx @@ -1699,16 +1699,16 @@ Standard_Boolean OpenGl_View::checkOitCompatibility (const Handle(OpenGl_Context } TCollection_ExtendedString aCompatibilityMsg; - if (!theGlContext->hasFloatBuffer - && !theGlContext->hasHalfFloatBuffer) + if (theGlContext->hasFloatBuffer == OpenGl_FeatureNotAvailable + && theGlContext->hasHalfFloatBuffer == OpenGl_FeatureNotAvailable) { aCompatibilityMsg += "OpenGL context does not support floating-point RGBA color buffer format.\n"; } - if (theMSAA && !theGlContext->hasSampleVariables) + if (theMSAA && theGlContext->hasSampleVariables == OpenGl_FeatureNotAvailable) { aCompatibilityMsg += "Current version of GLSL does not support built-in sample variables.\n"; } - if (!theGlContext->hasDrawBuffers) + if (theGlContext->hasDrawBuffers == OpenGl_FeatureNotAvailable) { aCompatibilityMsg += "OpenGL context does not support multiple draw buffers.\n"; } @@ -1741,14 +1741,14 @@ bool OpenGl_View::chooseOitColorConfiguration (const Handle(OpenGl_Context)& the { case 0: // choose best applicable color format combination { - theFormats.Append (theGlContext->hasHalfFloatBuffer ? GL_RGBA16F : GL_RGBA32F); - theFormats.Append (theGlContext->hasHalfFloatBuffer ? GL_R16F : GL_R32F); + theFormats.Append (theGlContext->hasHalfFloatBuffer != OpenGl_FeatureNotAvailable ? GL_RGBA16F : GL_RGBA32F); + theFormats.Append (theGlContext->hasHalfFloatBuffer != OpenGl_FeatureNotAvailable ? GL_R16F : GL_R32F); return true; } case 1: // choose non-optimal applicable color format combination { - theFormats.Append (theGlContext->hasHalfFloatBuffer ? GL_RGBA16F : GL_RGBA32F); - theFormats.Append (theGlContext->hasHalfFloatBuffer ? GL_RGBA16F : GL_RGBA32F); + theFormats.Append (theGlContext->hasHalfFloatBuffer != OpenGl_FeatureNotAvailable ? GL_RGBA16F : GL_RGBA32F); + theFormats.Append (theGlContext->hasHalfFloatBuffer != OpenGl_FeatureNotAvailable ? GL_RGBA16F : GL_RGBA32F); return true; } } diff --git a/src/Shaders/Declarations.glsl b/src/Shaders/Declarations.glsl index 001565ef6a..be565d0e60 100644 --- a/src/Shaders/Declarations.glsl +++ b/src/Shaders/Declarations.glsl @@ -50,9 +50,12 @@ THE_ATTRIBUTE vec4 occTexCoord; THE_ATTRIBUTE vec4 occVertColor; #elif (__VERSION__ >= 130) - out vec4 occFragColor; #ifdef OCC_ENABLE_draw_buffers - out vec4 occFragCoverage; + out vec4 occFragColorArray[2]; + #define occFragColor occFragColorArray[0] + #define occFragCoverage occFragColorArray[1] + #else + out vec4 occFragColor; #endif #else #ifdef OCC_ENABLE_draw_buffers diff --git a/src/Shaders/Shaders_Declarations_glsl.pxx b/src/Shaders/Shaders_Declarations_glsl.pxx index 7476af2974..ea1a087554 100644 --- a/src/Shaders/Shaders_Declarations_glsl.pxx +++ b/src/Shaders/Shaders_Declarations_glsl.pxx @@ -53,9 +53,12 @@ static const char Shaders_Declarations_glsl[] = " THE_ATTRIBUTE vec4 occTexCoord;\n" " THE_ATTRIBUTE vec4 occVertColor;\n" "#elif (__VERSION__ >= 130)\n" - " out vec4 occFragColor;\n" " #ifdef OCC_ENABLE_draw_buffers\n" - " out vec4 occFragCoverage;\n" + " out vec4 occFragColorArray[2];\n" + " #define occFragColor occFragColorArray[0]\n" + " #define occFragCoverage occFragColorArray[1]\n" + " #else\n" + " out vec4 occFragColor;\n" " #endif\n" "#else\n" " #ifdef OCC_ENABLE_draw_buffers\n" -- 2.20.1