diff --git a/adm/templates/env.bat.in b/adm/templates/env.bat.in index 94e8db5cea..538ad7cc67 100644 --- a/adm/templates/env.bat.in +++ b/adm/templates/env.bat.in @@ -131,6 +131,10 @@ if exist "%CASROOT%\custom.bat" ( call "%CASROOT%\custom.bat" %VCVER% %ARCH% %CASDEB% ) +if not ["%QTDIR%"] == [""] ( + set "PATH=%QTDIR%/bin;%PATH%" + set "QT_PLUGIN_PATH=%QTDIR%/plugins" +) if not ["%TCL_DIR%"] == [""] set "PATH=%TCL_DIR%;%PATH%" if not ["%TK_DIR%"] == [""] set "PATH=%TK_DIR%;%PATH%" if not ["%FREETYPE_DIR%"] == [""] set "PATH=%FREETYPE_DIR%;%PATH%" @@ -141,10 +145,6 @@ if not ["%TBB_DIR%"] == [""] set "PATH=%TBB_DIR%;%PATH%" if not ["%VTK_DIR%"] == [""] set "PATH=%VTK_DIR%;%PATH%" if not ["%FFMPEG_DIR%"] == [""] set "PATH=%FFMPEG_DIR%;%PATH%" if not ["%OPENVR_DIR%"] == [""] set "PATH=%OPENVR_DIR%;%PATH%" -if not ["%QTDIR%"] == [""] ( - set "PATH=%QTDIR%/bin;%PATH%" - set "QT_PLUGIN_PATH=%QTDIR%/plugins" -) rem ----- Set path to 3rd party and OCCT libraries ----- if not "%CSF_OCCTBinPath%" == "" ( diff --git a/src/OpenGl/OpenGl_Context.cxx b/src/OpenGl/OpenGl_Context.cxx index 38c27c2015..da868a036c 100644 --- a/src/OpenGl/OpenGl_Context.cxx +++ b/src/OpenGl/OpenGl_Context.cxx @@ -184,6 +184,13 @@ OpenGl_Context::OpenGl_Context (const Handle(OpenGl_Caps)& theCaps) myClippingState (), myGlLibHandle (NULL), myFuncs (new OpenGl_GlFunctions()), + myGapi ( +#if defined(GL_ES_VERSION_2_0) + Aspect_GraphicsLibrary_OpenGLES +#else + Aspect_GraphicsLibrary_OpenGL +#endif + ), mySupportedFormats (new Image_SupportedFormats()), myAnisoMax (1), myTexClamp (GL_CLAMP_TO_EDGE), @@ -200,6 +207,7 @@ OpenGl_Context::OpenGl_Context (const Handle(OpenGl_Caps)& theCaps) myGlVerMinor (0), myIsInitialized (Standard_False), myIsStereoBuffers (Standard_False), + myHasMsaaTextures (Standard_False), myIsGlNormalizeEnabled (Standard_False), mySpriteTexUnit (Graphic3d_TextureUnit_PointSprite), myHasRayTracing (Standard_False), @@ -1386,6 +1394,7 @@ void OpenGl_Context::init (const Standard_Boolean theIsCoreProfile) // read version myGlVerMajor = 0; myGlVerMinor = 0; + myHasMsaaTextures = false; myMaxMsaaSamples = 0; myMaxDrawBuffers = 1; myMaxColorAttachments = 1; @@ -1573,25 +1582,26 @@ void OpenGl_Context::init (const Standard_Boolean theIsCoreProfile) myClippingState.Init(); #if defined(GL_ES_VERSION_2_0) - if (IsGlGreaterEqual (3, 1) - && myFuncs->glTexStorage2DMultisample != NULL) + if (IsGlGreaterEqual (3, 0)) { - // MSAA RenderBuffers have been defined in OpenGL ES 3.0, - // but MSAA Textures - only in OpenGL ES 3.1+ + // MSAA RenderBuffers have been defined in OpenGL ES 3.0, but MSAA Textures - only in OpenGL ES 3.1+ + myHasMsaaTextures = IsGlGreaterEqual (3, 1) + && myFuncs->glTexStorage2DMultisample != NULL; ::glGetIntegerv (GL_MAX_SAMPLES, &myMaxMsaaSamples); } #else if (core30 != NULL) { - // MSAA RenderBuffers have been defined in OpenGL 3.0, - // but MSAA Textures - only in OpenGL 3.2+ + // MSAA RenderBuffers have been defined in OpenGL 3.0, but MSAA Textures - only in OpenGL 3.2+ if (core32 != NULL) { + myHasMsaaTextures = true; ::glGetIntegerv (GL_MAX_SAMPLES, &myMaxMsaaSamples); } else if (CheckExtension ("GL_ARB_texture_multisample") && myFuncs->glTexImage2DMultisample != NULL) { + myHasMsaaTextures = true; GLint aNbColorSamples = 0, aNbDepthSamples = 0; ::glGetIntegerv (GL_MAX_COLOR_TEXTURE_SAMPLES, &aNbColorSamples); ::glGetIntegerv (GL_MAX_DEPTH_TEXTURE_SAMPLES, &aNbDepthSamples); @@ -1599,6 +1609,10 @@ void OpenGl_Context::init (const Standard_Boolean theIsCoreProfile) } } #endif + if (myMaxMsaaSamples <= 1) + { + myHasMsaaTextures = false; + } #if !defined(GL_ES_VERSION_2_0) if (core32 != NULL && isCoreProfile) @@ -2370,6 +2384,32 @@ Handle(OpenGl_FrameBuffer) OpenGl_Context::SetDefaultFrameBuffer (const Handle(O return aFbo; } +// ======================================================================= +// function : IsRender +// purpose : +// ======================================================================= +Standard_Boolean OpenGl_Context::IsRender() const +{ +#if !defined(GL_ES_VERSION_2_0) + return myRenderMode == GL_RENDER; +#else + return Standard_True; +#endif +} + +// ======================================================================= +// function : IsFeedback +// purpose : +// ======================================================================= +Standard_Boolean OpenGl_Context::IsFeedback() const +{ +#if !defined(GL_ES_VERSION_2_0) + return myRenderMode == GL_FEEDBACK; +#else + return Standard_False; +#endif +} + // ======================================================================= // function : SetShadingMaterial // purpose : diff --git a/src/OpenGl/OpenGl_Context.hxx b/src/OpenGl/OpenGl_Context.hxx index 27849d3169..e0cf8cdf1e 100644 --- a/src/OpenGl/OpenGl_Context.hxx +++ b/src/OpenGl/OpenGl_Context.hxx @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -330,6 +331,9 @@ public: return (theFuncPtr != NULL); } + //! Return active graphics library. + Aspect_GraphicsLibrary GraphicsLibrary() const { return myGapi; } + //! @return true if detected GL version is greater or equal to requested one. inline Standard_Boolean IsGlGreaterEqual (const Standard_Integer theVerMajor, const Standard_Integer theVerMinor) const @@ -367,24 +371,10 @@ public: Standard_EXPORT Standard_Boolean SetSwapInterval (const Standard_Integer theInterval); //! Return true if active mode is GL_RENDER (cached state) - Standard_Boolean IsRender() const - { - #if !defined(GL_ES_VERSION_2_0) - return myRenderMode == GL_RENDER; - #else - return Standard_True; - #endif - } + Standard_EXPORT Standard_Boolean IsRender() const; //! Return true if active mode is GL_FEEDBACK (cached state) - Standard_Boolean IsFeedback() const - { - #if !defined(GL_ES_VERSION_2_0) - return myRenderMode == GL_FEEDBACK; - #else - return Standard_False; - #endif - } + Standard_EXPORT Standard_Boolean IsFeedback() const; //! This function retrieves information from GL about free GPU memory that is: //! - OS-dependent. On some OS it is per-process and on others - for entire system. @@ -480,11 +470,9 @@ public: //! @return true if texture parameters GL_TEXTURE_BASE_LEVEL/GL_TEXTURE_MAX_LEVEL are supported. Standard_Boolean HasTextureBaseLevel() const { - #if !defined(GL_ES_VERSION_2_0) - return IsGlGreaterEqual (1, 2); - #else - return IsGlGreaterEqual (3, 0); - #endif + return myGapi == Aspect_GraphicsLibrary_OpenGLES + ? IsGlGreaterEqual (3, 0) + : IsGlGreaterEqual (1, 2); } //! Return map of supported texture formats. @@ -507,6 +495,9 @@ public: //! Return texture unit to be used for sprites (Graphic3d_TextureUnit_PointSprite by default). Graphic3d_TextureUnit SpriteTextureUnit() const { return mySpriteTexUnit; } + //! @return true if MSAA textures are supported. + Standard_Boolean HasTextureMultisampling() const { return myHasMsaaTextures; } + //! @return value for GL_MAX_SAMPLES Standard_Integer MaxMsaaSamples() const { return myMaxMsaaSamples; } @@ -721,16 +712,8 @@ public: Standard_EXPORT Standard_Boolean IncludeMessage (const unsigned int theSource, const unsigned int theId); - //! @return true if OpenGl context supports left and - //! right rendering buffers. - Standard_Boolean HasStereoBuffers() const - { - #if !defined(GL_ES_VERSION_2_0) - return myIsStereoBuffers; - #else - return Standard_False; - #endif - } + //! @return true if OpenGl context supports left and right rendering buffers. + Standard_Boolean HasStereoBuffers() const { return myIsStereoBuffers; } public: //! @name methods to alter or retrieve current state @@ -1110,6 +1093,7 @@ private: // context info void* myGlLibHandle; //!< optional handle to GL library NCollection_Handle myFuncs; //!< mega structure for all GL functions + Aspect_GraphicsLibrary myGapi; //!< GAPI name Handle(Image_SupportedFormats) mySupportedFormats; //!< map of supported texture formats Standard_Integer myAnisoMax; //!< maximum level of anisotropy texture filter @@ -1127,6 +1111,7 @@ private: // context info Standard_Integer myGlVerMinor; //!< cached GL version minor number Standard_Boolean myIsInitialized; //!< flag indicates initialization state Standard_Boolean myIsStereoBuffers; //!< context supports stereo buffering + Standard_Boolean myHasMsaaTextures; //!< context supports MSAA textures Standard_Boolean myIsGlNormalizeEnabled; //!< GL_NORMALIZE flag //!< Used to tell OpenGl that normals should be normalized Graphic3d_TextureUnit mySpriteTexUnit; //!< sampler2D occSamplerPointSprite, texture unit for point sprite texture diff --git a/src/OpenGl/OpenGl_FrameBuffer.cxx b/src/OpenGl/OpenGl_FrameBuffer.cxx index 1864da9a4f..6ee169946a 100644 --- a/src/OpenGl/OpenGl_FrameBuffer.cxx +++ b/src/OpenGl/OpenGl_FrameBuffer.cxx @@ -19,6 +19,7 @@ #include #include +#include #include IMPLEMENT_STANDARD_RTTIEXT(OpenGl_FrameBuffer,OpenGl_Resource) @@ -363,6 +364,13 @@ Standard_Boolean OpenGl_FrameBuffer::Init (const Handle(OpenGl_Context)& theGlCo return Standard_False; } + if (theNbSamples != 0 + && !theGlContext->HasTextureMultisampling() + && theGlContext->MaxMsaaSamples() > 1) + { + return InitRenderBuffer (theGlContext, theSize, theColorFormats, theDepthFormat, theNbSamples); + } + myIsOwnColor = true; myIsOwnBuffer = true; myIsOwnDepth = true; @@ -429,6 +437,16 @@ Standard_Boolean OpenGl_FrameBuffer::Init (const Handle(OpenGl_Context)& theGlCo theGlContext->arbFBO->glBindRenderbuffer (GL_RENDERBUFFER, myGlDepthRBufferId); theGlContext->arbFBO->glRenderbufferStorage (GL_RENDERBUFFER, aDepthStencilFormat, aSizeX, aSizeY); theGlContext->arbFBO->glBindRenderbuffer (GL_RENDERBUFFER, NO_RENDERBUFFER); + const GLenum aRendImgErr = theGlContext->core11fwd->glGetError(); + if (aRendImgErr != GL_NO_ERROR) + { + theGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, + TCollection_AsciiString ("Error: FBO depth render buffer ") + aSizeX + "x" + aSizeY + + " IF: " + OpenGl_TextureFormat::FormatFormat (aDepthStencilFormat) + + " can not be created with error " + OpenGl_Context::FormatGlError (aRendImgErr) + "."); + Release (theGlContext.get()); + return Standard_False; + } } } @@ -535,8 +553,26 @@ Standard_Boolean OpenGl_FrameBuffer::InitWithRB (const Handle(OpenGl_Context)& t const Standard_Integer theDepthFormat, const unsigned int theColorRBufferFromWindow) { - myColorFormats.Clear(); - myColorFormats.Append (theColorFormat); + OpenGl_ColorFormats aColorFormats; + if (theColorFormat != 0) + { + aColorFormats.Append (theColorFormat); + } + return initRenderBuffer (theGlCtx, theSize, aColorFormats, theDepthFormat, 0, theColorRBufferFromWindow); +} + +// ======================================================================= +// function : initRenderBuffer +// purpose : +// ======================================================================= +Standard_Boolean OpenGl_FrameBuffer::initRenderBuffer (const Handle(OpenGl_Context)& theGlCtx, + const Graphic3d_Vec2i& theSize, + const OpenGl_ColorFormats& theColorFormats, + const Standard_Integer theDepthFormat, + const Standard_Integer theNbSamples, + const unsigned int theColorRBufferFromWindow) +{ + myColorFormats = theColorFormats; if (!myColorTextures.IsEmpty()) { Handle(OpenGl_Texture) aTexutre = myColorTextures.First(); @@ -549,7 +585,7 @@ Standard_Boolean OpenGl_FrameBuffer::InitWithRB (const Handle(OpenGl_Context)& t } myDepthFormat = theDepthFormat; - myNbSamples = 0; + myNbSamples = theNbSamples; myInitVPSizeX = theSize.x(); myInitVPSizeY = theSize.y(); if (theGlCtx->arbFBO == NULL) @@ -559,6 +595,14 @@ Standard_Boolean OpenGl_FrameBuffer::InitWithRB (const Handle(OpenGl_Context)& t // clean up previous state Release (theGlCtx.operator->()); + if (theNbSamples > theGlCtx->MaxMsaaSamples() + || theNbSamples < 0) + { + theGlCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, + TCollection_AsciiString ("Error: FBO creation failed - MSAA") + theNbSamples + + " render buffer exceeds samples limit: " + theGlCtx->MaxMsaaSamples() + ")."); + return Standard_False; + } myIsOwnColor = true; myIsOwnBuffer = true; @@ -575,11 +619,43 @@ Standard_Boolean OpenGl_FrameBuffer::InitWithRB (const Handle(OpenGl_Context)& t { myGlColorRBufferId = theColorRBufferFromWindow; } - else if (theColorFormat != 0) + else if (!theColorFormats.IsEmpty()) { + if (theColorFormats.Size() != 1) + { + throw Standard_NotImplemented ("Multiple color attachments as FBO render buffers are not implemented"); + } + + const GLint aColorFormat = theColorFormats.First(); + const OpenGl_TextureFormat aFormat = OpenGl_TextureFormat::FindSizedFormat (theGlCtx, aColorFormat); + if (!aFormat.IsValid()) + { + Release (theGlCtx.operator->()); + return Standard_False; + } + theGlCtx->arbFBO->glGenRenderbuffers (1, &myGlColorRBufferId); theGlCtx->arbFBO->glBindRenderbuffer (GL_RENDERBUFFER, myGlColorRBufferId); - theGlCtx->arbFBO->glRenderbufferStorage (GL_RENDERBUFFER, theColorFormat, aSizeX, aSizeY); + if (theNbSamples != 0) + { + theGlCtx->Functions()->glRenderbufferStorageMultisample (GL_RENDERBUFFER, theNbSamples, aFormat.InternalFormat(), aSizeX, aSizeY); + } + else + { + theGlCtx->arbFBO->glRenderbufferStorage (GL_RENDERBUFFER, aFormat.InternalFormat(), aSizeX, aSizeY); + } + theGlCtx->arbFBO->glBindRenderbuffer (GL_RENDERBUFFER, NO_RENDERBUFFER); + + const GLenum aRendImgErr = theGlCtx->core11fwd->glGetError(); + if (aRendImgErr != GL_NO_ERROR) + { + theGlCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, + TCollection_AsciiString ("Error: FBO color render buffer ") + aSizeX + "x" + aSizeY + "@" + theNbSamples + + " IF: " + OpenGl_TextureFormat::FormatFormat (aFormat.InternalFormat()) + + " can not be created with error " + OpenGl_Context::FormatGlError (aRendImgErr) + "."); + Release (theGlCtx.get()); + return Standard_False; + } } bool hasStencilRB = false; @@ -590,15 +666,36 @@ Standard_Boolean OpenGl_FrameBuffer::InitWithRB (const Handle(OpenGl_Context)& t theGlCtx->arbFBO->glGenRenderbuffers (1, &myGlDepthRBufferId); theGlCtx->arbFBO->glBindRenderbuffer (GL_RENDERBUFFER, myGlDepthRBufferId); - theGlCtx->arbFBO->glRenderbufferStorage (GL_RENDERBUFFER, myDepthFormat, aSizeX, aSizeY); + if (theNbSamples != 0) + { + theGlCtx->Functions()->glRenderbufferStorageMultisample (GL_RENDERBUFFER, theNbSamples, myDepthFormat, aSizeX, aSizeY); + } + else + { + theGlCtx->arbFBO->glRenderbufferStorage (GL_RENDERBUFFER, myDepthFormat, aSizeX, aSizeY); + } theGlCtx->arbFBO->glBindRenderbuffer (GL_RENDERBUFFER, NO_RENDERBUFFER); + + const GLenum aRendImgErr = theGlCtx->core11fwd->glGetError(); + if (aRendImgErr != GL_NO_ERROR) + { + theGlCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, + TCollection_AsciiString ("Error: FBO depth render buffer ") + aSizeX + "x" + aSizeY + "@" + theNbSamples + + " IF: " + OpenGl_TextureFormat::FormatFormat (myDepthFormat) + + " can not be created with error " + OpenGl_Context::FormatGlError (aRendImgErr) + "."); + Release (theGlCtx.get()); + return Standard_False; + } } // create FBO theGlCtx->arbFBO->glGenFramebuffers (1, &myGlFBufferId); theGlCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, myGlFBufferId); - theGlCtx->arbFBO->glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_RENDERBUFFER, myGlColorRBufferId); + if (myGlColorRBufferId != NO_RENDERBUFFER) + { + theGlCtx->arbFBO->glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_RENDERBUFFER, myGlColorRBufferId); + } if (myGlDepthRBufferId != NO_RENDERBUFFER) { if (hasDepthStencilAttach (theGlCtx) && hasStencilRB) diff --git a/src/OpenGl/OpenGl_FrameBuffer.hxx b/src/OpenGl/OpenGl_FrameBuffer.hxx index ca34f1a7a6..3071c04cdc 100644 --- a/src/OpenGl/OpenGl_FrameBuffer.hxx +++ b/src/OpenGl/OpenGl_FrameBuffer.hxx @@ -165,9 +165,26 @@ public: //! (Re-)initialize FBO with properties taken from another FBO. Standard_Boolean InitLazy (const Handle(OpenGl_Context)& theGlCtx, - const OpenGl_FrameBuffer& theFbo) + const OpenGl_FrameBuffer& theFbo, + const Standard_Boolean theToKeepMsaa = true) { - return InitLazy (theGlCtx, Graphic3d_Vec2i (theFbo.myVPSizeX, theFbo.myVPSizeY), theFbo.myColorFormats, theFbo.myDepthFormat, theFbo.myNbSamples); + return InitLazy (theGlCtx, Graphic3d_Vec2i (theFbo.myVPSizeX, theFbo.myVPSizeY), theFbo.myColorFormats, theFbo.myDepthFormat, theToKeepMsaa ? theFbo.myNbSamples : 0); + } + + //! (Re-)initialize FBO with specified dimensions. + //! The Render Buffer Objects will be used for Color, Depth and Stencil attachments (as opposite to textures). + //! @param theGlCtx currently bound OpenGL context + //! @param theSize render buffer width x height + //! @param theColorFormats list of color render buffer sized format, e.g. GL_RGBA8; list should define only one element + //! @param theDepthFormat depth-stencil render buffer sized format, e.g. GL_DEPTH24_STENCIL8 + //! @param theNbSamples MSAA number of samples (0 means normal render buffer) + Standard_Boolean InitRenderBuffer (const Handle(OpenGl_Context)& theGlCtx, + const Graphic3d_Vec2i& theSize, + const OpenGl_ColorFormats& theColorFormats, + const Standard_Integer theDepthFormat, + const Standard_Integer theNbSamples = 0) + { + return initRenderBuffer (theGlCtx, theSize, theColorFormats, theDepthFormat, theNbSamples, 0); } //! (Re-)initialize FBO with specified dimensions. @@ -176,12 +193,12 @@ public: //! @param theSize render buffer width x height //! @param theColorFormat color render buffer sized format, e.g. GL_RGBA8 //! @param theDepthFormat depth-stencil render buffer sized format, e.g. GL_DEPTH24_STENCIL8 - //! @param theColorRBufferFromWindow when specified - should be ID of already initialized RB object, which will be released within this class + //! @param theColorRBufferFromWindow should be ID of already initialized RB object, which will be released within this class Standard_EXPORT Standard_Boolean InitWithRB (const Handle(OpenGl_Context)& theGlCtx, const Graphic3d_Vec2i& theSize, const Standard_Integer theColorFormat, const Standard_Integer theDepthFormat, - const unsigned int theColorRBufferFromWindow = 0); + const unsigned int theColorRBufferFromWindow); //! Initialize class from currently bound FBO. //! Retrieved OpenGL objects will not be destroyed on Release. @@ -220,9 +237,15 @@ public: //! Returns the depth-stencil texture. const Handle(OpenGl_Texture)& DepthStencilTexture() const { return myDepthStencilTexture; } + //! Returns TRUE if color Render Buffer is defined. + bool IsColorRenderBuffer() const { return myGlColorRBufferId != NO_RENDERBUFFER; } + //! Returns the color Render Buffer. unsigned int ColorRenderBuffer() const { return myGlColorRBufferId; } + //! Returns TRUE if depth Render Buffer is defined. + bool IsDepthStencilRenderBuffer() const { return myGlDepthRBufferId != NO_RENDERBUFFER; } + //! Returns the depth Render Buffer. unsigned int DepthStencilRenderBuffer() const { return myGlDepthRBufferId; } @@ -231,6 +254,21 @@ public: public: + //! (Re-)initialize FBO with specified dimensions. + //! The Render Buffer Objects will be used for Color, Depth and Stencil attachments (as opposite to textures). + //! @param theGlCtx currently bound OpenGL context + //! @param theSize render buffer width x height + //! @param theColorFormats list of color render buffer sized format, e.g. GL_RGBA8 + //! @param theDepthFormat depth-stencil render buffer sized format, e.g. GL_DEPTH24_STENCIL8 + //! @param theNbSamples MSAA number of samples (0 means normal render buffer) + //! @param theColorRBufferFromWindow when specified - should be ID of already initialized RB object, which will be released within this class + Standard_EXPORT Standard_Boolean initRenderBuffer (const Handle(OpenGl_Context)& theGlCtx, + const Graphic3d_Vec2i& theSize, + const OpenGl_ColorFormats& theColorFormats, + const Standard_Integer theDepthFormat, + const Standard_Integer theNbSamples, + const unsigned int theColorRBufferFromWindow); + //! Initialize FBO for rendering into single/multiple color buffer and depth textures. Standard_DEPRECATED("Obsolete method, use Init() taking Graphic3d_Vec2i") bool Init (const Handle(OpenGl_Context)& theGlCtx, diff --git a/src/OpenGl/OpenGl_Texture.cxx b/src/OpenGl/OpenGl_Texture.cxx index 759a12fe3f..1d1933ff23 100644 --- a/src/OpenGl/OpenGl_Texture.cxx +++ b/src/OpenGl/OpenGl_Texture.cxx @@ -712,9 +712,12 @@ bool OpenGl_Texture::Init2DMultisample (const Handle(OpenGl_Context)& theCtx, const Standard_Integer theSizeY) { if (!Create (theCtx) - || theNbSamples > theCtx->MaxMsaaSamples() - || theNbSamples < 1) + || theNbSamples > theCtx->MaxMsaaSamples() + || theNbSamples < 1) { + theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, + TCollection_AsciiString ("Error: MSAA texture ") + theSizeX + "x" + theSizeY + "@" + myNbSamples + + " exceeds samples limit: " + theCtx->MaxMsaaSamples() + "."); return false; } @@ -724,26 +727,42 @@ bool OpenGl_Texture::Init2DMultisample (const Handle(OpenGl_Context)& theCtx, if(theSizeX > theCtx->MaxTextureSize() || theSizeY > theCtx->MaxTextureSize()) { + theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, + TCollection_AsciiString ("Error: MSAA texture ") + theSizeX + "x" + theSizeY + "@" + myNbSamples + + " exceeds size limit: " + theCtx->MaxTextureSize() + "x" + theCtx->MaxTextureSize() + "."); return false; } Bind (theCtx); //myTextFormat = theTextFormat; mySizedFormat = theTextFormat; -#if !defined(GL_ES_VERSION_2_0) - if (theCtx->Functions()->glTexStorage2DMultisample != NULL) + if (theCtx->HasTextureMultisampling() + && theCtx->Functions()->glTexStorage2DMultisample != NULL) { theCtx->Functions()->glTexStorage2DMultisample (myTarget, myNbSamples, theTextFormat, theSizeX, theSizeY, GL_FALSE); } - else +#if !defined(GL_ES_VERSION_2_0) + else if (theCtx->HasTextureMultisampling() + && theCtx->Functions()->glTexImage2DMultisample != NULL) { theCtx->Functions()->glTexImage2DMultisample (myTarget, myNbSamples, theTextFormat, theSizeX, theSizeY, GL_FALSE); } -#else - theCtx->Functions() ->glTexStorage2DMultisample (myTarget, myNbSamples, theTextFormat, theSizeX, theSizeY, GL_FALSE); #endif - if (theCtx->core11fwd->glGetError() != GL_NO_ERROR) + else { + theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, + "Error: MSAA textures are not supported by hardware."); + Unbind (theCtx); + return false; + } + + const GLenum aTexImgErr = theCtx->core11fwd->glGetError(); + if (aTexImgErr != GL_NO_ERROR) + { + theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, + TCollection_AsciiString ("Error: MSAA texture ") + theSizeX + "x" + theSizeY + "@" + myNbSamples + + " IF: " + OpenGl_TextureFormat::FormatFormat (theTextFormat) + + " cannot be created with error " + OpenGl_Context::FormatGlError (aTexImgErr) + "."); Unbind (theCtx); return false; } diff --git a/src/OpenGl/OpenGl_View.cxx b/src/OpenGl/OpenGl_View.cxx index a2d17ad6a5..c636f9252b 100644 --- a/src/OpenGl/OpenGl_View.cxx +++ b/src/OpenGl/OpenGl_View.cxx @@ -1106,6 +1106,11 @@ bool OpenGl_View::prepareFrameBuffers (Graphic3d_Camera::Projection& theProj) { aNbSamples = OpenGl_Context::GetPowerOfTwo (aNbSamples, aCtx->MaxMsaaSamples()); } + // Only MSAA textures can be blit into MSAA target, + // while render buffers could be resolved only into non-MSAA targets. + // As result, within obsolete OpenGL ES 3.0 context, we may create only one MSAA render buffer for main scene content + // and blit it into non-MSAA immediate FBO. + const bool hasTextureMsaa = aCtx->HasTextureMultisampling(); bool toUseOit = myRenderParams.TransparencyMethod != Graphic3d_RTM_BLEND_UNORDERED && checkOitCompatibility (aCtx, aNbSamples > 0); @@ -1156,7 +1161,7 @@ bool OpenGl_View::prepareFrameBuffers (Graphic3d_Camera::Projection& theProj) if (myMainSceneFbos[0]->IsValid() && (toInitImmediateFbo || myImmediateSceneFbos[0]->IsValid())) { const bool wasFailedImm0 = checkWasFailedFbo (myImmediateSceneFbos[0], myMainSceneFbos[0]); - if (!myImmediateSceneFbos[0]->InitLazy (aCtx, *myMainSceneFbos[0]) + if (!myImmediateSceneFbos[0]->InitLazy (aCtx, *myMainSceneFbos[0], hasTextureMsaa) && !wasFailedImm0) { TCollection_ExtendedString aMsg = TCollection_ExtendedString() + "Error! Immediate FBO " @@ -1200,7 +1205,7 @@ bool OpenGl_View::prepareFrameBuffers (Graphic3d_Camera::Projection& theProj) && myMainSceneFbos[0]->IsValid()) { const bool wasFailedMain1 = checkWasFailedFbo (myMainSceneFbos[1], myMainSceneFbos[0]); - if (!myMainSceneFbos[1]->InitLazy (aCtx, *myMainSceneFbos[0]) + if (!myMainSceneFbos[1]->InitLazy (aCtx, *myMainSceneFbos[0], true) && !wasFailedMain1) { TCollection_ExtendedString aMsg = TCollection_ExtendedString() + "Error! Main FBO (second) " @@ -1221,14 +1226,14 @@ bool OpenGl_View::prepareFrameBuffers (Graphic3d_Camera::Projection& theProj) { const bool wasFailedImm0 = checkWasFailedFbo (myImmediateSceneFbos[0], myMainSceneFbos[0]); const bool wasFailedImm1 = checkWasFailedFbo (myImmediateSceneFbos[1], myMainSceneFbos[0]); - if (!myImmediateSceneFbos[0]->InitLazy (aCtx, *myMainSceneFbos[0]) + if (!myImmediateSceneFbos[0]->InitLazy (aCtx, *myMainSceneFbos[0], hasTextureMsaa) && !wasFailedImm0) { TCollection_ExtendedString aMsg = TCollection_ExtendedString() + "Error! Immediate FBO (first) " + printFboFormat (myImmediateSceneFbos[0]) + " initialization has failed"; aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aMsg); } - if (!myImmediateSceneFbos[1]->InitLazy (aCtx, *myMainSceneFbos[0]) + if (!myImmediateSceneFbos[1]->InitLazy (aCtx, *myMainSceneFbos[0], hasTextureMsaa) && !wasFailedImm1) { TCollection_ExtendedString aMsg = TCollection_ExtendedString() + "Error! Immediate FBO (first) " @@ -2649,9 +2654,22 @@ bool OpenGl_View::blitBuffers (OpenGl_FrameBuffer* theReadFbo, aCtx->SetColorMask (true); // restore default alpha component write state const bool toApplyGamma = aCtx->ToRenderSRGB() != aCtx->IsFrameBufferSRGB(); - if (aCtx->arbFBOBlit != NULL - && !toApplyGamma - && theReadFbo->NbSamples() != 0) + bool toDrawTexture = true; + if (aCtx->arbFBOBlit != NULL) + { + if (!toApplyGamma + && theReadFbo->NbSamples() != 0) + { + toDrawTexture = false; + } + if (theReadFbo->IsColorRenderBuffer()) + { + // render buffers could be resolved only via glBlitFramebuffer() + toDrawTexture = false; + } + } + + if (!toDrawTexture) { GLbitfield aCopyMask = 0; theReadFbo->BindReadBuffer (aCtx); diff --git a/src/OpenGl/OpenGl_Window.cxx b/src/OpenGl/OpenGl_Window.cxx index f722dfdc53..89140cdea7 100644 --- a/src/OpenGl/OpenGl_Window.cxx +++ b/src/OpenGl/OpenGl_Window.cxx @@ -785,7 +785,9 @@ void OpenGl_Window::Init() aDefFbo = new OpenGl_FrameBuffer(); } - if (!aDefFbo->InitWithRB (myGlContext, Graphic3d_Vec2i (myWidth, myHeight), GL_RGBA8, GL_DEPTH24_STENCIL8)) + OpenGl_ColorFormats aColorFormats; + aColorFormats.Append (GL_RGBA8); + if (!aDefFbo->InitRenderBuffer (myGlContext, Graphic3d_Vec2i (myWidth, myHeight), aColorFormats, GL_DEPTH24_STENCIL8)) { TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: default FBO creation failed"); throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString());