1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-05-21 10:55:33 +03:00

0030744: Visualization, TKOpenGl - stipple line does not work on OpenGL ES 2.0

OpenGl_ShaderManager now provides fallback stipple lines GLSL code for obsolete OpenGL ES 2.0 devices.
OpenGl_Caps has been extended by flags disallowing OpenGL extensions usage
and restricting upper OpenGL version to be used by OCCT for testing purposes.
This commit is contained in:
kgv 2019-07-19 16:35:23 +03:00 committed by bugmaster
parent fa1710b567
commit 59515ca600
9 changed files with 179 additions and 23 deletions

View File

@ -51,6 +51,9 @@ OpenGl_Caps::OpenGl_Caps()
#else
contextCompatible (Standard_False),
#endif
contextNoExtensions (Standard_False),
contextMajorVersionUpper (-1),
contextMinorVersionUpper (-1),
glslWarnings (Standard_False),
suppressExtraMsg (Standard_True),
glslDumpLevel (OpenGl_ShaderProgramDumpLevel_Off)
@ -76,6 +79,9 @@ OpenGl_Caps& OpenGl_Caps::operator= (const OpenGl_Caps& theCopy)
contextSyncDebug = theCopy.contextSyncDebug;
contextNoAccel = theCopy.contextNoAccel;
contextCompatible = theCopy.contextCompatible;
contextNoExtensions = theCopy.contextNoExtensions;
contextMajorVersionUpper = theCopy.contextMajorVersionUpper;
contextMinorVersionUpper = theCopy.contextMinorVersionUpper;
glslWarnings = theCopy.glslWarnings;
suppressExtraMsg = theCopy.suppressExtraMsg;
glslDumpLevel = theCopy.glslDumpLevel;

View File

@ -107,6 +107,23 @@ public: //! @name context creation parameters
*/
Standard_Boolean contextCompatible;
/**
* Disallow using OpenGL extensions.
* Should be used for debugging purposes only!
*
* OFF by default.
*/
Standard_Boolean contextNoExtensions;
/**
* Synthetically restrict upper version of OpenGL functionality to be used.
* Should be used for debugging purposes only!
*
* (-1, -1) by default, which means no restriction.
*/
Standard_Integer contextMajorVersionUpper;
Standard_Integer contextMinorVersionUpper;
public: //! @name flags to activate verbose output
//! Print GLSL program compilation/linkage warnings, if any. OFF by default.

View File

@ -123,6 +123,7 @@ OpenGl_Context::OpenGl_Context (const Handle(OpenGl_Caps)& theCaps)
hasTexRGBA8(Standard_True),
hasFlatShading (OpenGl_FeatureInCore),
#endif
hasGlslBitwiseOps (OpenGl_FeatureNotAvailable),
hasDrawBuffers (OpenGl_FeatureNotAvailable),
hasFloatBuffer (OpenGl_FeatureNotAvailable),
hasHalfFloatBuffer (OpenGl_FeatureNotAvailable),
@ -749,6 +750,10 @@ Standard_Boolean OpenGl_Context::CheckExtension (const char* theExtName) const
#endif
return Standard_False;
}
else if (caps->contextNoExtensions)
{
return Standard_False;
}
#if !defined(GL_ES_VERSION_2_0)
// available since OpenGL 3.0
@ -1217,6 +1222,44 @@ void OpenGl_Context::init (const Standard_Boolean theIsCoreProfile)
ReadGlVersion (myGlVerMajor, myGlVerMinor);
myVendor = (const char* )::glGetString (GL_VENDOR);
myVendor.LowerCase();
if (caps->contextMajorVersionUpper != -1)
{
// synthetically restrict OpenGL version for testing
Standard_Integer aCtxVer[2] = { myGlVerMajor, myGlVerMinor };
bool isLowered = false;
if (myGlVerMajor > caps->contextMajorVersionUpper)
{
isLowered = true;
myGlVerMajor = caps->contextMajorVersionUpper;
#if defined(GL_ES_VERSION_2_0)
switch (myGlVerMajor)
{
case 2: myGlVerMinor = 0; break;
}
#else
switch (myGlVerMajor)
{
case 1: myGlVerMinor = 5; break;
case 2: myGlVerMinor = 1; break;
case 3: myGlVerMinor = 3; break;
}
#endif
}
if (caps->contextMinorVersionUpper != -1
&& myGlVerMinor > caps->contextMinorVersionUpper)
{
isLowered = true;
myGlVerMinor = caps->contextMinorVersionUpper;
}
if (isLowered)
{
PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_MEDIUM,
TCollection_AsciiString ("OpenGL version ") + aCtxVer[0] + "." + aCtxVer[1]
+ " has been lowered to " + myGlVerMajor + "." + myGlVerMinor);
}
}
if (!caps->ffpEnable
&& !IsGlGreaterEqual (2, 0))
{
@ -1436,6 +1479,9 @@ void OpenGl_Context::init (const Standard_Boolean theIsCoreProfile)
hasSampleVariables = IsGlGreaterEqual (3, 2) ? OpenGl_FeatureInCore :
oesSampleVariables ? OpenGl_FeatureInExtensions
: OpenGl_FeatureNotAvailable;
hasGlslBitwiseOps = IsGlGreaterEqual (3, 0)
? OpenGl_FeatureInCore
: OpenGl_FeatureNotAvailable;
// without hasHighp, dFdx/dFdy precision is considered too low for flat shading (visual artifacts)
hasFlatShading = IsGlGreaterEqual (3, 0)
? OpenGl_FeatureInCore
@ -1474,6 +1520,12 @@ void OpenGl_Context::init (const Standard_Boolean theIsCoreProfile)
arbDrawBuffers ? OpenGl_FeatureInExtensions
: OpenGl_FeatureNotAvailable;
hasGlslBitwiseOps = IsGlGreaterEqual (3, 0)
? OpenGl_FeatureInCore
: CheckExtension ("GL_EXT_gpu_shader4")
? OpenGl_FeatureInExtensions
: OpenGl_FeatureNotAvailable;
hasFloatBuffer = hasHalfFloatBuffer = IsGlGreaterEqual (3, 0) ? OpenGl_FeatureInCore :
CheckExtension ("GL_ARB_color_buffer_float") ? OpenGl_FeatureInExtensions
: OpenGl_FeatureNotAvailable;
@ -2989,9 +3041,16 @@ void OpenGl_Context::DiagnosticInformation (TColStd_IndexedDataMapOfStringString
if ((theFlags & Graphic3d_DiagnosticInfo_Device) != 0)
{
Standard_Integer aDriverVer[2] = {};
ReadGlVersion (aDriverVer[0], aDriverVer[1]);
addInfo (theDict, "GLvendor", (const char*)::glGetString (GL_VENDOR));
addInfo (theDict, "GLdevice", (const char*)::glGetString (GL_RENDERER));
addInfo (theDict, "GLversion", (const char*)::glGetString (GL_VERSION));
if (myGlVerMajor != aDriverVer[0]
|| myGlVerMinor != aDriverVer[1])
{
addInfo (theDict, "GLversionOcct", TCollection_AsciiString (myGlVerMajor) + "." + TCollection_AsciiString (myGlVerMinor));
}
if (IsGlGreaterEqual (2, 0))
{
addInfo (theDict, "GLSLversion", (const char*)::glGetString (GL_SHADING_LANGUAGE_VERSION));
@ -3496,8 +3555,23 @@ void OpenGl_Context::SetTypeOfLine (const Aspect_TypeOfLine theType,
if (!myActiveProgram.IsNull())
{
myActiveProgram->SetUniform (this, "uPattern", aPattern);
myActiveProgram->SetUniform (this, "uFactor", theFactor);
if (const OpenGl_ShaderUniformLocation aPatternLoc = myActiveProgram->GetStateLocation (OpenGl_OCCT_LINE_STIPPLE_PATTERN))
{
if (hasGlslBitwiseOps != OpenGl_FeatureNotAvailable)
{
myActiveProgram->SetUniform (this, aPatternLoc, aPattern);
}
else
{
Standard_Integer aPatArr[16] = {};
for (unsigned int aBit = 0; aBit < 16; ++aBit)
{
aPatArr[aBit] = ((unsigned int)(aPattern) & (1U << aBit)) != 0 ? 1 : 0;
}
myActiveProgram->SetUniform (this, aPatternLoc, 16, aPatArr);
}
myActiveProgram->SetUniform (this, myActiveProgram->GetStateLocation (OpenGl_OCCT_LINE_STIPPLE_FACTOR), theFactor);
}
return;
}

View File

@ -889,6 +889,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
OpenGl_FeatureFlag hasFlatShading; //!< Complex flag indicating support of Flat shading (Graphic3d_TOSM_FACET) (always available on desktop; on OpenGL ES - since 3.0 or as extension GL_OES_standard_derivatives)
OpenGl_FeatureFlag hasGlslBitwiseOps; //!< GLSL supports bitwise operations; OpenGL 3.0 / OpenGL ES 3.0 (GLSL 130 / GLSL ES 300) or OpenGL 2.1 + GL_EXT_gpu_shader4
OpenGl_FeatureFlag hasDrawBuffers; //!< Complex flag indicating support of multiple draw buffers (desktop OpenGL 2.0, OpenGL ES 3.0, GL_ARB_draw_buffers, GL_EXT_draw_buffers)
OpenGl_FeatureFlag hasFloatBuffer; //!< Complex flag indicating support of float color buffer format (desktop OpenGL 3.0, GL_ARB_color_buffer_float, GL_EXT_color_buffer_float)
OpenGl_FeatureFlag hasHalfFloatBuffer; //!< Complex flag indicating support of half-float color buffer format (desktop OpenGL 3.0, GL_ARB_color_buffer_float, GL_EXT_color_buffer_half_float)

View File

@ -303,7 +303,10 @@ Standard_Boolean OpenGl_GraphicDriver::InitContext()
::Message::DefaultMessenger()->Send ("Error: EGL does not provide OpenGL ES client!", Message_Fail);
return Standard_False;
}
myEglContext = (Aspect_RenderingContext )eglCreateContext ((EGLDisplay )myEglDisplay, myEglConfig, EGL_NO_CONTEXT, anEglCtxAttribs3);
if (myCaps->contextMajorVersionUpper != 2)
{
myEglContext = (Aspect_RenderingContext )eglCreateContext ((EGLDisplay )myEglDisplay, myEglConfig, EGL_NO_CONTEXT, anEglCtxAttribs3);
}
if ((EGLContext )myEglContext == EGL_NO_CONTEXT)
{
myEglContext = (Aspect_RenderingContext )eglCreateContext ((EGLDisplay )myEglDisplay, myEglConfig, EGL_NO_CONTEXT, anEglCtxAttribs2);

View File

@ -1505,6 +1505,8 @@ int OpenGl_ShaderManager::defaultGlslVersion (const Handle(Graphic3d_ShaderProgr
bool theUsesDerivates) const
{
int aBits = theBits;
const bool toUseDerivates = theUsesDerivates
|| (theBits & OpenGl_PO_StippleLine) != 0;
#if !defined(GL_ES_VERSION_2_0)
if (myContext->core32 != NULL)
{
@ -1518,19 +1520,15 @@ int OpenGl_ShaderManager::defaultGlslVersion (const Handle(Graphic3d_ShaderProgr
{
theProgram->SetHeader ("#version 130");
}
else if (myContext->CheckExtension ("GL_EXT_gpu_shader4"))
else if (myContext->CheckExtension ("GL_EXT_gpu_shader4")) // myContext->hasGlslBitwiseOps == OpenGl_FeatureInExtensions
{
// GL_EXT_gpu_shader4 defines GLSL type "unsigned int", while core GLSL specs define type "uint"
theProgram->SetHeader ("#extension GL_EXT_gpu_shader4 : enable\n"
"#define uint unsigned int");
}
else
{
aBits = aBits & ~OpenGl_PO_StippleLine;
}
}
}
(void )theUsesDerivates;
(void )toUseDerivates;
#else
// prefer "100 es" on OpenGL ES 3.0- devices (save the features unavailable before "300 es")
// and "300 es" on OpenGL ES 3.1+ devices
@ -1557,10 +1555,13 @@ int OpenGl_ShaderManager::defaultGlslVersion (const Handle(Graphic3d_ShaderProgr
else
{
aBits = aBits & ~OpenGl_PO_WriteOit;
aBits = aBits & ~OpenGl_PO_StippleLine;
if (!myContext->oesStdDerivatives)
{
aBits = aBits & ~OpenGl_PO_StippleLine;
}
}
}
if (theUsesDerivates)
if (toUseDerivates)
{
if (myContext->IsGlGreaterEqual (3, 0))
{
@ -1819,28 +1820,34 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramUnlit (Handle(OpenGl_Sha
const Standard_Integer aBits = defaultGlslVersion (aProgramSrc, "unlit", theBits);
if ((aBits & OpenGl_PO_StippleLine) != 0)
{
aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("int uPattern", Graphic3d_TOS_FRAGMENT));
aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("float uFactor", Graphic3d_TOS_FRAGMENT));
if (myContext->hasGlslBitwiseOps != OpenGl_FeatureNotAvailable)
{
aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("int occStipplePattern", Graphic3d_TOS_FRAGMENT));
}
else
{
aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("bool occStipplePattern[16]", Graphic3d_TOS_FRAGMENT));
}
aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("float occStippleFactor", Graphic3d_TOS_FRAGMENT));
aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 occViewport", Graphic3d_TOS_VERTEX));
aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec2 ScreenSpaceCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
aSrcVertEndMain =
EOL" vec2 aPosition = gl_Position.xy / gl_Position.w;"
EOL" aPosition = aPosition * 0.5 + 0.5;"
EOL" ScreenSpaceCoord = aPosition.xy * occViewport.zw + occViewport.xy;";
aSrcFragMainGetColor =
EOL" vec2 anAxis = vec2 (0.0);"
aSrcFragMainGetColor = TCollection_AsciiString()
+ EOL" vec2 anAxis = vec2 (0.0, 1.0);"
EOL" if (abs (dFdx (ScreenSpaceCoord.x)) - abs (dFdy (ScreenSpaceCoord.y)) > 0.001)"
EOL" {"
EOL" anAxis = vec2 (1.0, 0.0);"
EOL" }"
EOL" else"
EOL" {"
EOL" anAxis = vec2 (0.0, 1.0);"
EOL" }"
EOL" float aRotatePoint = dot (gl_FragCoord.xy, anAxis);"
EOL" uint aBit = uint (floor (aRotatePoint / uFactor + 0.5)) & 15U;"
EOL" if ((uint (uPattern) & (1U << aBit)) == 0U) discard;"
EOL" vec4 aColor = getFinalColor();"
+ (myContext->hasGlslBitwiseOps != OpenGl_FeatureNotAvailable
? EOL" uint aBit = uint (floor (aRotatePoint / occStippleFactor + 0.5)) & 15U;"
EOL" if ((uint (occStipplePattern) & (1U << aBit)) == 0U) discard;"
: EOL" int aBit = int (mod (floor (aRotatePoint / occStippleFactor + 0.5), 16.0));"
EOL" if (!occStipplePattern[aBit]) discard;")
+ EOL" vec4 aColor = getFinalColor();"
EOL" if (aColor.a <= 0.1) discard;"
EOL" occSetFragColor (aColor);";
}

View File

@ -81,6 +81,8 @@ Standard_CString OpenGl_ShaderProgram::PredefinedKeywords[] =
"occViewport", // OpenGl_OCCT_VIEWPORT
"occLineWidth", // OpenGl_OCCT_LINE_WIDTH
"occLineFeather", // OpenGl_OCCT_LINE_FEATHER
"occStipplePattern", // OpenGl_OCCT_LINE_STIPPLE_PATTERN
"occStippleFactor", // OpenGl_OCCT_LINE_STIPPLE_FACTOR
"occWireframeColor", // OpenGl_OCCT_WIREFRAME_COLOR
"occIsQuadMode", // OpenGl_OCCT_QUAD_MODE_STATE

View File

@ -79,6 +79,8 @@ enum OpenGl_StateVariable
OpenGl_OCCT_VIEWPORT,
OpenGl_OCCT_LINE_WIDTH,
OpenGl_OCCT_LINE_FEATHER,
OpenGl_OCCT_LINE_STIPPLE_PATTERN, // occStipplePattern
OpenGl_OCCT_LINE_STIPPLE_FACTOR, // occStippleFactor
OpenGl_OCCT_WIREFRAME_COLOR,
OpenGl_OCCT_QUAD_MODE_STATE,

View File

@ -1658,8 +1658,9 @@ TCollection_AsciiString ViewerTest::ViewerInit (const Standard_Integer thePxLeft
// alternatively we can disable buffer swap at all, but this might be inappropriate for testing
//ViewerTest_myDefaultCaps.buffersNoSwap = true;
}
aGraphicDriver = new OpenGl_GraphicDriver (GetDisplayConnection());
aGraphicDriver = new OpenGl_GraphicDriver (GetDisplayConnection(), false);
aGraphicDriver->ChangeOptions() = ViewerTest_myDefaultCaps;
aGraphicDriver->InitContext();
ViewerTest_myDrivers.Bind (aViewNames.GetDriverName(), aGraphicDriver);
toCreateViewer = Standard_True;
@ -6626,6 +6627,8 @@ static int VCaps (Draw_Interpretor& theDI,
theDI << "Compatible:" << (aCaps->contextCompatible ? "1" : "0") << "\n";
theDI << "Stereo: " << (aCaps->contextStereo ? "1" : "0") << "\n";
theDI << "WinBuffer: " << (aCaps->useSystemBuffer ? "1" : "0") << "\n";
theDI << "NoExt:" << (aCaps->contextNoExtensions ? "1" : "0") << "\n";
theDI << "MaxVersion:" << aCaps->contextMajorVersionUpper << "." << aCaps->contextMinorVersionUpper << "\n";
return 0;
}
@ -6769,6 +6772,44 @@ static int VCaps (Draw_Interpretor& theDI,
}
aCaps->contextStereo = toEnable;
}
else if (anArgCase == "-noext"
|| anArgCase == "-noextensions"
|| anArgCase == "-noextension")
{
Standard_Boolean toDisable = Standard_True;
if (++anArgIter < theArgNb
&& !ViewerTest::ParseOnOff (theArgVec[anArgIter], toDisable))
{
--anArgIter;
}
aCaps->contextNoExtensions = toDisable;
}
else if (anArgCase == "-maxversion"
|| anArgCase == "-upperversion"
|| anArgCase == "-limitversion")
{
Standard_Integer aVer[2] = { -2, -1 };
for (Standard_Integer aValIter = 0; aValIter < 2; ++aValIter)
{
if (anArgIter + 1 < theArgNb)
{
const TCollection_AsciiString aStr (theArgVec[anArgIter + 1]);
if (aStr.IsIntegerValue())
{
aVer[aValIter] = aStr.IntegerValue();
++anArgIter;
}
}
}
if (aVer[0] < -1
|| aVer[1] < -1)
{
std::cout << "Syntax error at '" << anArgCase << "'\n";
return 1;
}
aCaps->contextMajorVersionUpper = aVer[0];
aCaps->contextMinorVersionUpper = aVer[1];
}
else
{
std::cout << "Error: unknown argument '" << anArg << "'\n";
@ -13713,6 +13754,7 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
"\n\t\t: [-vsync {0|1}] [-useWinBuffer {0|1}]"
"\n\t\t: [-quadBuffer {0|1}] [-stereo {0|1}]"
"\n\t\t: [-softMode {0|1}] [-noupdate|-update]"
"\n\t\t: [-noExtensions {0|1}] [-maxVersion Major Minor]"
"\n\t\t: Modify particular graphic driver options:"
"\n\t\t: FFP - use fixed-function pipeline instead of"
"\n\t\t: built-in GLSL programs"
@ -13727,6 +13769,8 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
"\n\t\t: softMode - software OpenGL implementation"
"\n\t\t: compatibleProfile - backward-compatible profile"
"\n\t\t: quadbuffer - QuadBuffer"
"\n\t\t: noExtensions - disallow usage of extensions"
"\n\t\t: maxVersion - force upper OpenGL version to be used"
"\n\t\t: Unlike vrenderparams, these parameters control alternative"
"\n\t\t: rendering paths producing the same visual result when"
"\n\t\t: possible."