X-Git-Url: http://git.dev.opencascade.org/gitweb/?p=occt.git;a=blobdiff_plain;f=src%2FOpenGl%2FOpenGl_Workspace.cxx;h=a0e76563af24887329482627b437a5c33fc5eb7e;hp=d2619f9f6f24d57a4da3808e49560081cf2771da;hb=1be4179947116e54658924f0149d3f35743a899a;hpb=c04c30b3eeabbb8cdc8fbe00aee9fe5e31dc0c14 diff --git a/src/OpenGl/OpenGl_Workspace.cxx b/src/OpenGl/OpenGl_Workspace.cxx index d2619f9f6f..a0e76563af 100644 --- a/src/OpenGl/OpenGl_Workspace.cxx +++ b/src/OpenGl/OpenGl_Workspace.cxx @@ -13,11 +13,9 @@ // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. -#include -#include - -#include +#include +#include #include #include #include @@ -25,37 +23,39 @@ #include #include #include +#include +#include #include #include -#include #include -#include #include -#include +#include #include -#include +#include -#if defined(_WIN32) && defined(HAVE_VIDEOCAPTURE) - #include -#endif +IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Workspace,Standard_Transient) +IMPLEMENT_STANDARD_RTTIEXT(OpenGl_RaytraceFilter,OpenGl_RenderFilter) +#ifdef HAVE_GL2PS + #include + /* OCC22216 NOTE: linker dependency can be switched off by undefining macro. + Pragma comment for gl2ps.lib is defined only here. */ + #ifdef _MSC_VER + #pragma comment( lib, "gl2ps.lib" ) + #endif +#endif namespace { - static const TEL_COLOUR THE_WHITE_COLOR = { { 1.0f, 1.0f, 1.0f, 1.0f } }; - static const OpenGl_Vec4 THE_BLACK_COLOR (0.0f, 0.0f, 0.0f, 1.0f); + static const OpenGl_Vec4 THE_WHITE_COLOR (1.0f, 1.0f, 1.0f, 1.0f); + static const OpenGl_Vec4 THE_BLACK_COLOR (0.0f, 0.0f, 0.0f, 1.0f); static const OpenGl_AspectLine myDefaultAspectLine; static const OpenGl_AspectFace myDefaultAspectFace; static const OpenGl_AspectMarker myDefaultAspectMarker; static const OpenGl_AspectText myDefaultAspectText; - static const OpenGl_TextParam myDefaultTextParam = - { - 16, Graphic3d_HTA_LEFT, Graphic3d_VTA_BOTTOM - }; - static const OpenGl_Matrix myDefaultMatrix = { {{ 1.0F, 0.0F, 0.0F, 0.0F }, @@ -64,22 +64,22 @@ namespace { 0.0F, 0.0F, 0.0F, 1.0F }} }; -}; +} // ======================================================================= // function : Init // purpose : // ======================================================================= -void OpenGl_Material::Init (const OPENGL_SURF_PROP& theProp) +void OpenGl_Material::Init (const Graphic3d_MaterialAspect& theMat, + const Quantity_Color& theInteriorColor) { + const bool isPhysic = theMat.MaterialType (Graphic3d_MATERIAL_PHYSIC) == Standard_True; + // ambient component - if (theProp.color_mask & OPENGL_AMBIENT_MASK) + if (theMat.ReflectionMode (Graphic3d_TOR_AMBIENT)) { - const float* aSrcAmb = theProp.isphysic ? theProp.ambcol.rgb : theProp.matcol.rgb; - Ambient = OpenGl_Vec4 (aSrcAmb[0] * theProp.amb, - aSrcAmb[1] * theProp.amb, - aSrcAmb[2] * theProp.amb, - 1.0f); + const OpenGl_Vec3& aSrcAmb = isPhysic ? theMat.AmbientColor() : theInteriorColor; + Ambient = OpenGl_Vec4 (aSrcAmb * (float )theMat.Ambient(), 1.0f); } else { @@ -87,13 +87,10 @@ void OpenGl_Material::Init (const OPENGL_SURF_PROP& theProp) } // diffusion component - if (theProp.color_mask & OPENGL_DIFFUSE_MASK) + if (theMat.ReflectionMode (Graphic3d_TOR_DIFFUSE)) { - const float* aSrcDif = theProp.isphysic ? theProp.difcol.rgb : theProp.matcol.rgb; - Diffuse = OpenGl_Vec4 (aSrcDif[0] * theProp.diff, - aSrcDif[1] * theProp.diff, - aSrcDif[2] * theProp.diff, - 1.0f); + const OpenGl_Vec3& aSrcDif = isPhysic ? theMat.DiffuseColor() : theInteriorColor; + Diffuse = OpenGl_Vec4 (aSrcDif * (float )theMat.Diffuse(), 1.0f); } else { @@ -101,13 +98,10 @@ void OpenGl_Material::Init (const OPENGL_SURF_PROP& theProp) } // specular component - if (theProp.color_mask & OPENGL_SPECULAR_MASK) + if (theMat.ReflectionMode (Graphic3d_TOR_SPECULAR)) { - const float* aSrcSpe = theProp.isphysic ? theProp.speccol.rgb : THE_WHITE_COLOR.rgb; - Specular = OpenGl_Vec4 (aSrcSpe[0] * theProp.spec, - aSrcSpe[1] * theProp.spec, - aSrcSpe[2] * theProp.spec, - 1.0f); + const OpenGl_Vec3& aSrcSpe = isPhysic ? (const OpenGl_Vec3& )theMat.SpecularColor() : THE_WHITE_COLOR.rgb(); + Specular = OpenGl_Vec4 (aSrcSpe * (float )theMat.Specular(), 1.0f); } else { @@ -115,151 +109,74 @@ void OpenGl_Material::Init (const OPENGL_SURF_PROP& theProp) } // emission component - if (theProp.color_mask & OPENGL_EMISSIVE_MASK) + if (theMat.ReflectionMode (Graphic3d_TOR_EMISSION)) { - const float* aSrcEms = theProp.isphysic ? theProp.emscol.rgb : theProp.matcol.rgb; - Emission = OpenGl_Vec4 (aSrcEms[0] * theProp.emsv, - aSrcEms[1] * theProp.emsv, - aSrcEms[2] * theProp.emsv, - 1.0f); + const OpenGl_Vec3& aSrcEms = isPhysic ? theMat.EmissiveColor() : theInteriorColor; + Emission = OpenGl_Vec4 (aSrcEms * (float )theMat.Emissive(), 1.0f); } else { Emission = THE_BLACK_COLOR; } - ChangeShine() = theProp.shine; - ChangeTransparency() = theProp.trans; + ChangeShine() = 128.0f * float(theMat.Shininess()); + ChangeTransparency() = 1.0f - (float )theMat.Transparency(); } // ======================================================================= // function : OpenGl_Workspace // purpose : // ======================================================================= -OpenGl_Workspace::OpenGl_Workspace (const Handle(OpenGl_GraphicDriver)& theDriver, - const CALL_DEF_WINDOW& theCWindow, - Aspect_RenderingContext theGContext, - const Handle(OpenGl_Caps)& theCaps, - const Handle(OpenGl_Context)& theShareCtx) -: OpenGl_Window (theDriver, theCWindow, theGContext, theCaps, theShareCtx), - NamedStatus (0), +OpenGl_Workspace::OpenGl_Workspace (OpenGl_View* theView, const Handle(OpenGl_Window)& theWindow) +: NamedStatus (0), HighlightColor (&THE_WHITE_COLOR), - // - myHasFboBlit (Standard_True), - // - myViewId (-1), - myAntiAliasingMode (3), - myTransientDrawToFront (Standard_True), - myBackBufferRestored (Standard_False), - myIsImmediateDrawn (Standard_False), + myView (theView), + myWindow (theWindow), + myGlContext (!theWindow.IsNull() ? theWindow->GetGlContext() : NULL), myUseZBuffer (Standard_True), myUseDepthWrite (Standard_True), myUseGLLight (Standard_True), - myIsCullingEnabled (Standard_False), - myFrameCounter (0), // - AspectLine_set (&myDefaultAspectLine), - AspectLine_applied (NULL), - AspectFace_set (&myDefaultAspectFace), - AspectFace_applied (NULL), - AspectMarker_set (&myDefaultAspectMarker), - AspectMarker_applied (NULL), - AspectText_set (&myDefaultAspectText), - AspectText_applied (NULL), - TextParam_set (&myDefaultTextParam), - TextParam_applied (NULL), + myAspectLineSet (&myDefaultAspectLine), + myAspectFaceSet (&myDefaultAspectFace), + myAspectMarkerSet (&myDefaultAspectMarker), + myAspectTextSet (&myDefaultAspectText), + myAspectFaceAppliedWithHL (false), + // ViewMatrix_applied (&myDefaultMatrix), StructureMatrix_applied (&myDefaultMatrix), - myCullingMode (TelCullUndefined), - myModelViewMatrix (myDefaultMatrix), - PolygonOffset_applied (THE_DEFAULT_POFFSET) + myToAllowFaceCulling (false), + myToHighlight (false), + myModelViewMatrix (myDefaultMatrix) { - myGlContext->core11fwd->glPixelStorei (GL_UNPACK_ALIGNMENT, 1); - myMainSceneFbos[0] = new OpenGl_FrameBuffer(); - myMainSceneFbos[1] = new OpenGl_FrameBuffer(); - myImmediateSceneFbos[0] = new OpenGl_FrameBuffer(); - myImmediateSceneFbos[1] = new OpenGl_FrameBuffer(); - - if (!myGlContext->GetResource ("OpenGl_LineAttributes", myLineAttribs)) + if (!myGlContext.IsNull() && myGlContext->MakeCurrent()) { - // share and register for release once the resource is no longer used - myLineAttribs = new OpenGl_LineAttributes(); - myGlContext->ShareResource ("OpenGl_LineAttributes", myLineAttribs); - myLineAttribs->Init (myGlContext); - } + myGlContext->core11fwd->glPixelStorei (GL_UNPACK_ALIGNMENT, 1); - // General initialization of the context - -#if !defined(GL_ES_VERSION_2_0) - if (myGlContext->core11 != NULL) - { - // Eviter d'avoir les faces mal orientees en noir. - // Pourrait etre utiliser pour detecter les problemes d'orientation - glLightModeli ((GLenum )GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); - - // Optimisation pour le Fog et l'antialiasing - glHint (GL_FOG_HINT, GL_FASTEST); - glHint (GL_POINT_SMOOTH_HINT, GL_FASTEST); - } - - glHint (GL_LINE_SMOOTH_HINT, GL_FASTEST); - glHint (GL_POLYGON_SMOOTH_HINT, GL_FASTEST); -#endif - - // AA mode - const char* anAaEnv = ::getenv ("CALL_OPENGL_ANTIALIASING_MODE"); - if (anAaEnv != NULL) - { - int v; - if (sscanf (anAaEnv, "%d", &v) > 0) myAntiAliasingMode = v; - } - - myDefaultCappingAlgoFilter = new OpenGl_CappingAlgoFilter(); - myNoneCulling.ChangeCullingMode() = TelCullNone; - myNoneCulling.ChangeEdge() = 0; - myFrontCulling.ChangeCullingMode() = TelCullBack; - myFrontCulling.ChangeEdge() = 0; -} - -// ======================================================================= -// function : SetImmediateModeDrawToFront -// purpose : -// ======================================================================= -Standard_Boolean OpenGl_Workspace::SetImmediateModeDrawToFront (const Standard_Boolean theDrawToFrontBuffer) -{ - const Standard_Boolean aPrevMode = myTransientDrawToFront; - myTransientDrawToFront = theDrawToFrontBuffer; - return aPrevMode; -} + // General initialization of the context + #if !defined(GL_ES_VERSION_2_0) + if (myGlContext->core11 != NULL) + { + // Eviter d'avoir les faces mal orientees en noir. + // Pourrait etre utiliser pour detecter les problemes d'orientation + glLightModeli ((GLenum )GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); -inline void nullifyGlResource (Handle(OpenGl_Resource)& theResource, - const Handle(OpenGl_Context)& theCtx) -{ - if (!theResource.IsNull()) - { - theResource->Release (theCtx.operator->()); - theResource.Nullify(); - } -} + // Optimisation pour le Fog et l'antialiasing + glHint (GL_FOG_HINT, GL_FASTEST); + glHint (GL_POINT_SMOOTH_HINT, GL_FASTEST); + } -// ======================================================================= -// function : ~OpenGl_Workspace -// purpose : -// ======================================================================= -OpenGl_Workspace::~OpenGl_Workspace() -{ - if (!myLineAttribs.IsNull()) - { - myLineAttribs.Nullify(); - myGlContext->ReleaseResource ("OpenGl_LineAttributes", Standard_True); + glHint (GL_LINE_SMOOTH_HINT, GL_FASTEST); + glHint (GL_POLYGON_SMOOTH_HINT, GL_FASTEST); + #endif } - nullifyGlResource (myMainSceneFbos[0], myGlContext); - nullifyGlResource (myMainSceneFbos[1], myGlContext); - nullifyGlResource (myImmediateSceneFbos[0], myGlContext); - nullifyGlResource (myImmediateSceneFbos[1], myGlContext); + myDefaultCappingAlgoFilter = new OpenGl_CappingAlgoFilter(); - myFullScreenQuad.Release (myGlContext.operator->()); + myNoneCulling .Aspect()->SetSuppressBackFaces (false); + myNoneCulling .Aspect()->SetDrawEdges (false); + myFrontCulling.Aspect()->SetSuppressBackFaces (true); + myFrontCulling.Aspect()->SetDrawEdges (false); } // ======================================================================= @@ -268,8 +185,10 @@ OpenGl_Workspace::~OpenGl_Workspace() // ======================================================================= Standard_Boolean OpenGl_Workspace::Activate() { - if (!OpenGl_Window::Activate()) + if (myWindow.IsNull() || !myWindow->Activate()) + { return Standard_False; + } ViewMatrix_applied = &myDefaultMatrix; StructureMatrix_applied = &myDefaultMatrix; @@ -289,26 +208,22 @@ void OpenGl_Workspace::ResetAppliedAspect() NamedStatus = !myTextureBound.IsNull() ? OPENGL_NS_TEXTURE : 0; HighlightColor = &THE_WHITE_COLOR; - AspectLine_set = &myDefaultAspectLine; - AspectLine_applied = NULL; - AspectFace_set = &myDefaultAspectFace; - AspectFace_applied = NULL; - AspectMarker_set = &myDefaultAspectMarker; - AspectMarker_applied = NULL; - AspectText_set = &myDefaultAspectText; - AspectText_applied = NULL; - TextParam_set = &myDefaultTextParam; - TextParam_applied = NULL; - PolygonOffset_applied = THE_DEFAULT_POFFSET; - myCullingMode = TelCullUndefined; - - AspectLine(Standard_True); - AspectFace(Standard_True); - AspectMarker(Standard_True); - AspectText(Standard_True); - - myGlContext->SetTypeOfLine (myDefaultAspectLine.Type()); - myGlContext->SetLineWidth (myDefaultAspectLine.Width()); + myToAllowFaceCulling = false; + myAspectLineSet = &myDefaultAspectLine; + myAspectFaceSet = &myDefaultAspectFace; + myAspectFaceApplied.Nullify(); + myAspectMarkerSet = &myDefaultAspectMarker; + myAspectMarkerApplied.Nullify(); + myAspectTextSet = &myDefaultAspectText; + myPolygonOffsetApplied= Graphic3d_PolygonOffset(); + + ApplyAspectLine(); + ApplyAspectFace(); + ApplyAspectMarker(); + ApplyAspectText(); + + myGlContext->SetTypeOfLine (myDefaultAspectLine.Aspect()->Type()); + myGlContext->SetLineWidth (myDefaultAspectLine.Aspect()->Width()); } // ======================================================================= @@ -398,21 +313,8 @@ void OpenGl_Workspace::setTextureParams (Handle(OpenGl_Texture)& } #if !defined(GL_ES_VERSION_2_0) - GLint aMatrixMode = GL_TEXTURE; if (myGlContext->core11 != NULL) { - glGetIntegerv (GL_MATRIX_MODE, &aMatrixMode); - - // setup texture matrix - glMatrixMode (GL_TEXTURE); - OpenGl_Mat4 aTextureMat; - const Graphic3d_Vec2& aScale = aParams->Scale(); - const Graphic3d_Vec2& aTrans = aParams->Translation(); - OpenGl_Utils::Scale (aTextureMat, aScale.x(), aScale.y(), 1.0f); - OpenGl_Utils::Translate (aTextureMat, -aTrans.x(), -aTrans.y(), 0.0f); - OpenGl_Utils::Rotate (aTextureMat, -aParams->Rotation(), 0.0f, 0.0f, 1.0f); - glLoadMatrixf (aTextureMat); - GLint anEnvMode = GL_MODULATE; // lighting mode if (!aParams->IsModulate()) { @@ -469,12 +371,11 @@ void OpenGl_Workspace::setTextureParams (Handle(OpenGl_Texture)& } case Graphic3d_TOTM_SPRITE: { - if (GetGlContext()->core20fwd != NULL) + if (myGlContext->core20fwd != NULL) { glEnable (GL_POINT_SPRITE); glTexEnvi (GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE); anEnvMode = GL_REPLACE; - GetGlContext()->core15->glPointParameteri (GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT); } break; } @@ -625,12 +526,6 @@ void OpenGl_Workspace::setTextureParams (Handle(OpenGl_Texture)& default: break; } -#if !defined(GL_ES_VERSION_2_0) - if (myGlContext->core11 != NULL) - { - glMatrixMode (aMatrixMode); // turn back active matrix - } -#endif theTexture->SetParams (aParams); } @@ -671,883 +566,642 @@ Handle(OpenGl_Texture) OpenGl_Workspace::EnableTexture (const Handle(OpenGl_Text } // ======================================================================= -// function : bindDefaultFbo +// function : updateMaterial // purpose : // ======================================================================= -void OpenGl_Workspace::bindDefaultFbo (OpenGl_FrameBuffer* theCustomFbo) +void OpenGl_Workspace::updateMaterial (const int theFlag) { - OpenGl_FrameBuffer* anFbo = (theCustomFbo != NULL && theCustomFbo->IsValid()) - ? theCustomFbo - : (!myGlContext->DefaultFrameBuffer().IsNull() - && myGlContext->DefaultFrameBuffer()->IsValid() - ? myGlContext->DefaultFrameBuffer().operator->() - : NULL); - if (anFbo != NULL) - { - anFbo->BindBuffer (myGlContext); - } - else - { - #if !defined(GL_ES_VERSION_2_0) - myGlContext->SetReadDrawBuffer (GL_BACK); - #else - if (myGlContext->arbFBO != NULL) - { - myGlContext->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER); - } - #endif + // Case of hidden line + if (myAspectFaceSet->Aspect()->InteriorStyle() == Aspect_IS_HIDDENLINE) + { + // copy all values including line edge aspect + *myAspectFaceHl.Aspect().operator->() = *myAspectFaceSet->Aspect(); + myAspectFaceHl.SetAspectEdge (myAspectFaceSet->AspectEdge()); + myAspectFaceHl.Aspect()->SetInteriorColor (myView->BackgroundColor().GetRGB()); + myAspectFaceHl.SetNoLighting (true); + myAspectFaceSet = &myAspectFaceHl; + return; } - myGlContext->core11fwd->glViewport (0, 0, myWidth, myHeight); -} -// ======================================================================= -// function : blitBuffers -// purpose : -// ======================================================================= -bool OpenGl_Workspace::blitBuffers (OpenGl_FrameBuffer* theReadFbo, - OpenGl_FrameBuffer* theDrawFbo) -{ - if (theReadFbo == NULL) + const Graphic3d_MaterialAspect* aSrcMat = &myAspectFaceSet->Aspect()->FrontMaterial(); + const Quantity_Color* aSrcIntColor = &myAspectFaceSet->Aspect()->InteriorColor(); + GLenum aFace = GL_FRONT_AND_BACK; + if (theFlag == TEL_BACK_MATERIAL) { - return false; + aFace = GL_BACK; + aSrcMat = &myAspectFaceSet->Aspect()->BackMaterial(); + aSrcIntColor = &myAspectFaceSet->Aspect()->BackInteriorColor(); } - else if (theReadFbo == theDrawFbo) + else if (myAspectFaceSet->Aspect()->Distinguish() + && !(NamedStatus & OPENGL_NS_RESMAT)) { - return true; + aFace = GL_FRONT; } - // clear destination before blitting - if (theDrawFbo != NULL - && theDrawFbo->IsValid()) + myMatTmp.Init (*aSrcMat, *aSrcIntColor); + if (myToHighlight) { - theDrawFbo->BindBuffer (myGlContext); + myMatTmp.SetColor (*HighlightColor); } - else + + // handling transparency + if (NamedStatus & OPENGL_NS_2NDPASSDO) { - myGlContext->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER); + // second pass + myMatTmp.Diffuse.a() = aSrcMat->EnvReflexion(); } -#if !defined(GL_ES_VERSION_2_0) - myGlContext->core20fwd->glClearDepth (1.0); -#else - myGlContext->core20fwd->glClearDepthf (1.0f); -#endif - myGlContext->core20fwd->glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - -/*#if !defined(GL_ES_VERSION_2_0) - if (myGlContext->arbFBOBlit != NULL) + else { - theReadFbo->BindReadBuffer (myGlContext); - if (theDrawFbo != NULL - && theDrawFbo->IsValid()) - { - theDrawFbo->BindDrawBuffer (myGlContext); - } - else + if (aSrcMat->EnvReflexion() != 0.0f) { - myGlContext->arbFBO->glBindFramebuffer (GL_DRAW_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER); + // if the material reflects the environment scene, the second pass is needed + NamedStatus |= OPENGL_NS_2NDPASSNEED; } - // we don't copy stencil buffer here... does it matter for performance? - myGlContext->arbFBOBlit->glBlitFramebuffer (0, 0, theReadFbo->GetVPSizeX(), theReadFbo->GetVPSizeY(), - 0, 0, theReadFbo->GetVPSizeX(), theReadFbo->GetVPSizeY(), - GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST); - if (theDrawFbo != NULL - && theDrawFbo->IsValid()) + const float aTransp = (float )aSrcMat->Transparency(); + if (aTransp != 0.0f) { - theDrawFbo->BindBuffer (myGlContext); + // render transparent + myMatTmp.Diffuse.a() = 1.0f - aTransp; + glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable (GL_BLEND); + if (myUseDepthWrite) + { + glDepthMask (GL_FALSE); + } } else { - myGlContext->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER); + // render opaque + glBlendFunc (GL_ONE, GL_ZERO); + glDisable (GL_BLEND); + if (myUseDepthWrite) + { + glDepthMask (GL_TRUE); + } } } - else -#endif*/ + + // do not update material properties in case of zero reflection mode, + // because GL lighting will be disabled by OpenGl_PrimitiveArray::DrawArray() anyway. + if (myAspectFaceSet->IsNoLighting()) { - myGlContext->core20fwd->glDepthFunc (GL_ALWAYS); - myGlContext->core20fwd->glDepthMask (GL_TRUE); - myGlContext->core20fwd->glEnable (GL_DEPTH_TEST); + return; + } - DisableTexture(); - if (!myFullScreenQuad.IsValid()) + // reset material + if (NamedStatus & OPENGL_NS_RESMAT) + { + #if !defined(GL_ES_VERSION_2_0) + if (myGlContext->core11 != NULL) { - OpenGl_Vec4 aQuad[4] = - { - OpenGl_Vec4( 1.0f, -1.0f, 1.0f, 0.0f), - OpenGl_Vec4( 1.0f, 1.0f, 1.0f, 1.0f), - OpenGl_Vec4(-1.0f, -1.0f, 0.0f, 0.0f), - OpenGl_Vec4(-1.0f, 1.0f, 0.0f, 1.0f) - }; - myFullScreenQuad.Init (myGlContext, 4, 4, aQuad[0].GetData()); + myGlContext->core11->glMaterialfv (aFace, GL_AMBIENT, myMatTmp.Ambient.GetData()); + myGlContext->core11->glMaterialfv (aFace, GL_DIFFUSE, myMatTmp.Diffuse.GetData()); + myGlContext->core11->glMaterialfv (aFace, GL_SPECULAR, myMatTmp.Specular.GetData()); + myGlContext->core11->glMaterialfv (aFace, GL_EMISSION, myMatTmp.Emission.GetData()); + myGlContext->core11->glMaterialf (aFace, GL_SHININESS, myMatTmp.Shine()); } + #endif - const Handle(OpenGl_ShaderManager)& aManager = myGlContext->ShaderManager(); - if (myFullScreenQuad.IsValid() - && aManager->BindFboBlitProgram()) + if (theFlag == TEL_FRONT_MATERIAL) { - theReadFbo->ColorTexture() ->Bind (myGlContext, GL_TEXTURE0 + 0); - theReadFbo->DepthStencilTexture()->Bind (myGlContext, GL_TEXTURE0 + 1); - myFullScreenQuad.BindVertexAttrib (myGlContext, Graphic3d_TOA_POS); - - myGlContext->core20fwd->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4); - - myFullScreenQuad.UnbindVertexAttrib (myGlContext, Graphic3d_TOA_POS); - theReadFbo->DepthStencilTexture()->Unbind (myGlContext, GL_TEXTURE0 + 1); - theReadFbo->ColorTexture() ->Unbind (myGlContext, GL_TEXTURE0 + 0); + myMatFront = myMatTmp; + myMatBack = myMatTmp; } else { - TCollection_ExtendedString aMsg = TCollection_ExtendedString() - + "Error! FBO blitting has failed"; - myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB, - GL_DEBUG_TYPE_ERROR_ARB, - 0, - GL_DEBUG_SEVERITY_HIGH_ARB, - aMsg); - myHasFboBlit = Standard_False; - theReadFbo->Release (myGlContext.operator->()); - return true; + myMatBack = myMatTmp; } - } - return true; -} -// ======================================================================= -// function : drawStereoPair -// purpose : -// ======================================================================= -void OpenGl_Workspace::drawStereoPair (const Graphic3d_CView& theCView) -{ - OpenGl_FrameBuffer* aPair[2] = - { - myImmediateSceneFbos[0]->IsValid() ? myImmediateSceneFbos[0].operator->() : NULL, - myImmediateSceneFbos[1]->IsValid() ? myImmediateSceneFbos[1].operator->() : NULL - }; - if (aPair[0] == NULL - || aPair[1] == NULL - || !myTransientDrawToFront) - { - aPair[0] = myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL; - aPair[1] = myMainSceneFbos[1]->IsValid() ? myMainSceneFbos[1].operator->() : NULL; - } - - if (aPair[0] == NULL - || aPair[1] == NULL) - { + NamedStatus &= ~OPENGL_NS_RESMAT; return; } - Standard_Boolean toReverse = theCView.RenderParams.ToReverseStereo; - const Standard_Boolean isOddY = (theCView.DefWindow.top + theCView.DefWindow.dy) % 2 == 1; - const Standard_Boolean isOddX = theCView.DefWindow.left % 2 == 1; - if (isOddY - && (theCView.RenderParams.StereoMode == Graphic3d_StereoMode_RowInterlaced - || theCView.RenderParams.StereoMode == Graphic3d_StereoMode_ChessBoard)) - { - toReverse = !toReverse; - } - if (isOddX - && (theCView.RenderParams.StereoMode == Graphic3d_StereoMode_ColumnInterlaced - || theCView.RenderParams.StereoMode == Graphic3d_StereoMode_ChessBoard)) - { - toReverse = !toReverse; - } - - if (toReverse) - { - std::swap (aPair[0], aPair[1]); - } - - myGlContext->core20fwd->glDepthFunc (GL_ALWAYS); - myGlContext->core20fwd->glDepthMask (GL_TRUE); - myGlContext->core20fwd->glEnable (GL_DEPTH_TEST); - - DisableTexture(); - if (!myFullScreenQuad.IsValid()) + // reduce updates + OpenGl_Material& anOld = (theFlag == TEL_FRONT_MATERIAL) + ? myMatFront + : myMatBack; +#if !defined(GL_ES_VERSION_2_0) + if (myGlContext->core11 != NULL) { - OpenGl_Vec4 aQuad[4] = + if (myMatTmp.Ambient.r() != anOld.Ambient.r() + || myMatTmp.Ambient.g() != anOld.Ambient.g() + || myMatTmp.Ambient.b() != anOld.Ambient.b()) { - OpenGl_Vec4( 1.0f, -1.0f, 1.0f, 0.0f), - OpenGl_Vec4( 1.0f, 1.0f, 1.0f, 1.0f), - OpenGl_Vec4(-1.0f, -1.0f, 0.0f, 0.0f), - OpenGl_Vec4(-1.0f, 1.0f, 0.0f, 1.0f) - }; - myFullScreenQuad.Init (myGlContext, 4, 4, aQuad[0].GetData()); - } - - const Handle(OpenGl_ShaderManager)& aManager = myGlContext->ShaderManager(); - if (myFullScreenQuad.IsValid() - && aManager->BindStereoProgram (theCView.RenderParams.StereoMode)) - { - if (theCView.RenderParams.StereoMode == Graphic3d_StereoMode_Anaglyph) + myGlContext->core11->glMaterialfv (aFace, GL_AMBIENT, myMatTmp.Ambient.GetData()); + } + if (myMatTmp.Diffuse.r() != anOld.Diffuse.r() + || myMatTmp.Diffuse.g() != anOld.Diffuse.g() + || myMatTmp.Diffuse.b() != anOld.Diffuse.b() + || fabs (myMatTmp.Diffuse.a() - anOld.Diffuse.a()) > 0.01f) { - OpenGl_Mat4 aFilterL, aFilterR; - aFilterL.SetDiagonal (Graphic3d_Vec4 (0.0f, 0.0f, 0.0f, 0.0f)); - aFilterR.SetDiagonal (Graphic3d_Vec4 (0.0f, 0.0f, 0.0f, 0.0f)); - switch (theCView.RenderParams.AnaglyphFilter) - { - case Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple: - { - aFilterL.SetRow (0, Graphic3d_Vec4 (1.0f, 0.0f, 0.0f, 0.0f)); - aFilterR.SetRow (1, Graphic3d_Vec4 (0.0f, 1.0f, 0.0f, 0.0f)); - aFilterR.SetRow (2, Graphic3d_Vec4 (0.0f, 0.0f, 1.0f, 0.0f)); - break; - } - case Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized: - { - aFilterL.SetRow (0, Graphic3d_Vec4 ( 0.4154f, 0.4710f, 0.16666667f, 0.0f)); - aFilterL.SetRow (1, Graphic3d_Vec4 (-0.0458f, -0.0484f, -0.0257f, 0.0f)); - aFilterL.SetRow (2, Graphic3d_Vec4 (-0.0547f, -0.0615f, 0.0128f, 0.0f)); - aFilterL.SetRow (3, Graphic3d_Vec4 ( 0.0f, 0.0f, 0.0f, 0.0f)); - aFilterR.SetRow (0, Graphic3d_Vec4 (-0.01090909f, -0.03636364f, -0.00606061f, 0.0f)); - aFilterR.SetRow (1, Graphic3d_Vec4 ( 0.37560000f, 0.73333333f, 0.01111111f, 0.0f)); - aFilterR.SetRow (2, Graphic3d_Vec4 (-0.06510000f, -0.12870000f, 1.29710000f, 0.0f)); - aFilterR.SetRow (3, Graphic3d_Vec4 ( 0.0f, 0.0f, 0.0f, 0.0f)); - break; - } - case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple: - { - aFilterL.SetRow (0, Graphic3d_Vec4 (1.0f, 0.0f, 0.0f, 0.0f)); - aFilterL.SetRow (1, Graphic3d_Vec4 (0.0f, 1.0f, 0.0f, 0.0f)); - aFilterR.SetRow (2, Graphic3d_Vec4 (0.0f, 0.0f, 1.0f, 0.0f)); - break; - } - case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized: - { - aFilterL.SetRow (0, Graphic3d_Vec4 ( 1.062f, -0.205f, 0.299f, 0.0f)); - aFilterL.SetRow (1, Graphic3d_Vec4 (-0.026f, 0.908f, 0.068f, 0.0f)); - aFilterL.SetRow (2, Graphic3d_Vec4 (-0.038f, -0.173f, 0.022f, 0.0f)); - aFilterL.SetRow (3, Graphic3d_Vec4 ( 0.0f, 0.0f, 0.0f, 0.0f)); - aFilterR.SetRow (0, Graphic3d_Vec4 (-0.016f, -0.123f, -0.017f, 0.0f)); - aFilterR.SetRow (1, Graphic3d_Vec4 ( 0.006f, 0.062f, -0.017f, 0.0f)); - aFilterR.SetRow (2, Graphic3d_Vec4 ( 0.094f, 0.185f, 0.911f, 0.0f)); - aFilterR.SetRow (3, Graphic3d_Vec4 ( 0.0f, 0.0f, 0.0f, 0.0f)); - break; - } - case Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple: - { - aFilterR.SetRow (0, Graphic3d_Vec4 (1.0f, 0.0f, 0.0f, 0.0f)); - aFilterL.SetRow (1, Graphic3d_Vec4 (0.0f, 1.0f, 0.0f, 0.0f)); - aFilterR.SetRow (2, Graphic3d_Vec4 (0.0f, 0.0f, 1.0f, 0.0f)); - break; - } - case Graphic3d_RenderingParams::Anaglyph_UserDefined: - { - aFilterL = theCView.RenderParams.AnaglyphLeft; - aFilterR = theCView.RenderParams.AnaglyphRight; - break; - } - } - myGlContext->ActiveProgram()->SetUniform (myGlContext, "uMultL", aFilterL); - myGlContext->ActiveProgram()->SetUniform (myGlContext, "uMultR", aFilterR); + myGlContext->core11->glMaterialfv (aFace, GL_DIFFUSE, myMatTmp.Diffuse.GetData()); + } + if (myMatTmp.Specular.r() != anOld.Specular.r() + || myMatTmp.Specular.g() != anOld.Specular.g() + || myMatTmp.Specular.b() != anOld.Specular.b()) + { + myGlContext->core11->glMaterialfv (aFace, GL_SPECULAR, myMatTmp.Specular.GetData()); + } + if (myMatTmp.Emission.r() != anOld.Emission.r() + || myMatTmp.Emission.g() != anOld.Emission.g() + || myMatTmp.Emission.b() != anOld.Emission.b()) + { + myGlContext->core11->glMaterialfv (aFace, GL_EMISSION, myMatTmp.Emission.GetData()); + } + if (myMatTmp.Shine() != anOld.Shine()) + { + myGlContext->core11->glMaterialf (aFace, GL_SHININESS, myMatTmp.Shine()); } - - aPair[0]->ColorTexture()->Bind (myGlContext, GL_TEXTURE0 + 0); - aPair[1]->ColorTexture()->Bind (myGlContext, GL_TEXTURE0 + 1); - myFullScreenQuad.BindVertexAttrib (myGlContext, 0); - - myGlContext->core20fwd->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4); - - myFullScreenQuad.UnbindVertexAttrib (myGlContext, 0); - aPair[1]->ColorTexture()->Unbind (myGlContext, GL_TEXTURE0 + 1); - aPair[0]->ColorTexture()->Unbind (myGlContext, GL_TEXTURE0 + 0); } - else +#endif + anOld = myMatTmp; + if (aFace == GL_FRONT_AND_BACK) { - TCollection_ExtendedString aMsg = TCollection_ExtendedString() - + "Error! Anaglyph has failed"; - myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB, - GL_DEBUG_TYPE_ERROR_ARB, - 0, - GL_DEBUG_SEVERITY_HIGH_ARB, - aMsg); + myMatBack = myMatTmp; } } // ======================================================================= -// function : Redraw +// function : SetAspectLine // purpose : // ======================================================================= -void OpenGl_Workspace::Redraw (const Graphic3d_CView& theCView, - const Aspect_CLayer2d& theCUnderLayer, - const Aspect_CLayer2d& theCOverLayer) +const OpenGl_AspectLine* OpenGl_Workspace::SetAspectLine (const OpenGl_AspectLine* theAspect) { - if (!Activate()) - { - return; - } - - if (mySwapInterval != myGlContext->caps->swapInterval) - { - mySwapInterval = myGlContext->caps->swapInterval; - myGlContext->SetSwapInterval (mySwapInterval); - } - - ++myFrameCounter; - myIsCullingEnabled = theCView.IsCullingEnabled; - const Graphic3d_StereoMode aStereoMode = theCView.RenderParams.StereoMode; - const Handle(Graphic3d_Camera)& aCamera = myView->Camera(); - Graphic3d_Camera::Projection aProjectType = aCamera->ProjectionType(); - - // release pending GL resources - myGlContext->ReleaseDelayed(); - - // fetch OpenGl context state - myGlContext->FetchState(); + const OpenGl_AspectLine* aPrevAspectLine = myAspectLineSet; + myAspectLineSet = theAspect; + return aPrevAspectLine; +} - OpenGl_FrameBuffer* aFrameBuffer = (OpenGl_FrameBuffer* )theCView.ptrFBO; - bool toSwap = myGlContext->IsRender() - && !myGlContext->caps->buffersNoSwap - && aFrameBuffer == NULL; +// ======================================================================= +// function : SetAspectFace +// purpose : +// ======================================================================= +const OpenGl_AspectFace * OpenGl_Workspace::SetAspectFace (const OpenGl_AspectFace* theAspect) +{ + const OpenGl_AspectFace* aPrevAspectFace = myAspectFaceSet; + myAspectFaceSet = theAspect; + return aPrevAspectFace; +} - Standard_Integer aSizeX = aFrameBuffer != NULL ? aFrameBuffer->GetVPSizeX() : myWidth; - Standard_Integer aSizeY = aFrameBuffer != NULL ? aFrameBuffer->GetVPSizeY() : myHeight; +// ======================================================================= +// function : SetAspectMarker +// purpose : +// ======================================================================= +const OpenGl_AspectMarker* OpenGl_Workspace::SetAspectMarker (const OpenGl_AspectMarker* theAspect) +{ + const OpenGl_AspectMarker* aPrevAspectMarker = myAspectMarkerSet; + myAspectMarkerSet = theAspect; + return aPrevAspectMarker; +} - if ( aFrameBuffer == NULL - && !myGlContext->DefaultFrameBuffer().IsNull() - && myGlContext->DefaultFrameBuffer()->IsValid()) - { - aFrameBuffer = myGlContext->DefaultFrameBuffer().operator->(); - } +// ======================================================================= +// function : SetAspectText +// purpose : +// ======================================================================= +const OpenGl_AspectText * OpenGl_Workspace::SetAspectText (const OpenGl_AspectText* theAspect) +{ + const OpenGl_AspectText* aPrevAspectText = myAspectTextSet; + myAspectTextSet = theAspect; + return aPrevAspectText; +} - if (myHasFboBlit - && (myTransientDrawToFront || aProjectType == Graphic3d_Camera::Projection_Stereo)) +// ======================================================================= +// function : ApplyAspectFace +// purpose : +// ======================================================================= +const OpenGl_AspectFace* OpenGl_Workspace::ApplyAspectFace() +{ + if (myView->BackfacingModel() == Graphic3d_TOBM_AUTOMATIC) { - if (myMainSceneFbos[0]->GetVPSizeX() != aSizeX - || myMainSceneFbos[0]->GetVPSizeY() != aSizeY) + // manage back face culling mode, disable culling when clipping is enabled + bool toSuppressBackFaces = myToAllowFaceCulling + && myAspectFaceSet->Aspect()->ToSuppressBackFaces(); + if (toSuppressBackFaces) + { + if (myGlContext->Clipping().IsClippingOrCappingOn() + || myAspectFaceSet->Aspect()->InteriorStyle() == Aspect_IS_HATCH) + { + toSuppressBackFaces = false; + } + } + if (toSuppressBackFaces) { - // prepare FBOs containing main scene - // for further blitting and rendering immediate presentations on top - if (myGlContext->core20fwd != NULL) + if (!(NamedStatus & OPENGL_NS_2NDPASSDO) + && (float )myAspectFaceSet->Aspect()->FrontMaterial().Transparency() != 0.0f) { - myMainSceneFbos[0]->Init (myGlContext, aSizeX, aSizeY); + // disable culling in case of translucent shading aspect + toSuppressBackFaces = false; } } + myGlContext->SetCullBackFaces (toSuppressBackFaces); } - else + + if (myAspectFaceSet->Aspect() == myAspectFaceApplied + && myToHighlight == myAspectFaceAppliedWithHL) { - myMainSceneFbos [0]->Release (myGlContext.operator->()); - myMainSceneFbos [1]->Release (myGlContext.operator->()); - myImmediateSceneFbos[0]->Release (myGlContext.operator->()); - myImmediateSceneFbos[1]->Release (myGlContext.operator->()); - myMainSceneFbos [0]->ChangeViewport (0, 0); - myMainSceneFbos [1]->ChangeViewport (0, 0); - myImmediateSceneFbos[0]->ChangeViewport (0, 0); - myImmediateSceneFbos[1]->ChangeViewport (0, 0); + return myAspectFaceSet; } + myAspectFaceAppliedWithHL = myToHighlight; - if (aProjectType == Graphic3d_Camera::Projection_Stereo - && myMainSceneFbos[0]->IsValid()) +#if !defined(GL_ES_VERSION_2_0) + const Aspect_InteriorStyle anIntstyle = myAspectFaceSet->Aspect()->InteriorStyle(); + if (myAspectFaceApplied.IsNull() + || myAspectFaceApplied->InteriorStyle() != anIntstyle) { - myMainSceneFbos[1]->InitLazy (myGlContext, aSizeX, aSizeY); - if (!myMainSceneFbos[1]->IsValid()) - { - // no enough memory? - aProjectType = Graphic3d_Camera::Projection_Perspective; - } - else if (!myTransientDrawToFront) - { - // - } - else if (!myGlContext->HasStereoBuffers() - || aStereoMode != Graphic3d_StereoMode_QuadBuffer) + switch (anIntstyle) { - myImmediateSceneFbos[0]->InitLazy (myGlContext, aSizeX, aSizeY); - myImmediateSceneFbos[1]->InitLazy (myGlContext, aSizeX, aSizeY); - if (!myImmediateSceneFbos[0]->IsValid() - || !myImmediateSceneFbos[1]->IsValid()) + case Aspect_IS_EMPTY: + case Aspect_IS_HOLLOW: + { + myGlContext->SetPolygonMode (GL_LINE); + break; + } + case Aspect_IS_HATCH: + { + myGlContext->SetPolygonMode (GL_FILL); + myGlContext->SetPolygonHatchEnabled (true); + break; + } + case Aspect_IS_SOLID: + case Aspect_IS_HIDDENLINE: { - aProjectType = Graphic3d_Camera::Projection_Perspective; + myGlContext->SetPolygonMode (GL_FILL); + myGlContext->SetPolygonHatchEnabled (false); + break; + } + case Aspect_IS_POINT: + { + myGlContext->SetPolygonMode (GL_POINT); + break; } } } - if (aProjectType == Graphic3d_Camera::Projection_Stereo) + if (anIntstyle == Aspect_IS_HATCH) { - OpenGl_FrameBuffer* aMainFbos[2] = - { - myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL, - myMainSceneFbos[1]->IsValid() ? myMainSceneFbos[1].operator->() : NULL - }; - OpenGl_FrameBuffer* anImmFbos[2] = - { - myImmediateSceneFbos[0]->IsValid() ? myImmediateSceneFbos[0].operator->() : NULL, - myImmediateSceneFbos[1]->IsValid() ? myImmediateSceneFbos[1].operator->() : NULL - }; - - if (!myTransientDrawToFront) - { - anImmFbos[0] = aMainFbos[0]; - anImmFbos[1] = aMainFbos[1]; - } - else if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip - || aStereoMode == Graphic3d_StereoMode_QuadBuffer) - { - anImmFbos[0] = NULL; - anImmFbos[1] = NULL; - } + myGlContext->SetPolygonHatchStyle (myAspectFaceSet->Aspect()->HatchStyle()); + } +#endif - #if !defined(GL_ES_VERSION_2_0) - myGlContext->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_LEFT : GL_BACK); - #endif - redraw1 (theCView, theCUnderLayer, theCOverLayer, - aMainFbos[0], Graphic3d_Camera::Projection_MonoLeftEye); - myBackBufferRestored = Standard_True; - myIsImmediateDrawn = Standard_False; - #if !defined(GL_ES_VERSION_2_0) - myGlContext->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_LEFT : GL_BACK); - #endif - if (!redrawImmediate (theCView, theCOverLayer, theCUnderLayer, aMainFbos[0], aProjectType, anImmFbos[0])) - { - toSwap = false; - } - else if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip - && toSwap) + // Aspect_POM_None means: do not change current settings + if ((myAspectFaceSet->Aspect()->PolygonOffset().Mode & Aspect_POM_None) != Aspect_POM_None) + { + if (myPolygonOffsetApplied.Mode != myAspectFaceSet->Aspect()->PolygonOffset().Mode + || myPolygonOffsetApplied.Factor != myAspectFaceSet->Aspect()->PolygonOffset().Factor + || myPolygonOffsetApplied.Units != myAspectFaceSet->Aspect()->PolygonOffset().Units) { - myGlContext->SwapBuffers(); + SetPolygonOffset (myAspectFaceSet->Aspect()->PolygonOffset()); } + } - #if !defined(GL_ES_VERSION_2_0) - myGlContext->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_RIGHT : GL_BACK); - #endif - redraw1 (theCView, theCUnderLayer, theCOverLayer, - aMainFbos[1], Graphic3d_Camera::Projection_MonoRightEye); - myBackBufferRestored = Standard_True; - myIsImmediateDrawn = Standard_False; - if (!redrawImmediate (theCView, theCOverLayer, theCUnderLayer, aMainFbos[1], aProjectType, anImmFbos[1])) - { - toSwap = false; - } + updateMaterial (TEL_FRONT_MATERIAL); + if (myAspectFaceSet->Aspect()->Distinguish()) + { + updateMaterial (TEL_BACK_MATERIAL); + } - if (anImmFbos[0] != NULL) - { - bindDefaultFbo (aFrameBuffer); - drawStereoPair (theCView); - } + if (myAspectFaceSet->Aspect()->ToMapTexture()) + { + EnableTexture (myAspectFaceSet->TextureRes (myGlContext), + myAspectFaceSet->TextureParams()); } else { - OpenGl_FrameBuffer* aMainFbo = myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL; - #if !defined(GL_ES_VERSION_2_0) - if (aMainFbo == NULL - && aFrameBuffer == NULL) + if (!myEnvironmentTexture.IsNull()) { - myGlContext->SetReadDrawBuffer (GL_BACK); + EnableTexture (myEnvironmentTexture, + myEnvironmentTexture->GetParams()); } - #endif - redraw1 (theCView, theCUnderLayer, theCOverLayer, - aMainFbo != NULL ? aMainFbo : aFrameBuffer, aProjectType); - myBackBufferRestored = Standard_True; - myIsImmediateDrawn = Standard_False; - if (!redrawImmediate (theCView, theCOverLayer, theCUnderLayer, aMainFbo, aProjectType, aFrameBuffer)) + else { - toSwap = false; + DisableTexture(); } } -#if defined(_WIN32) && defined(HAVE_VIDEOCAPTURE) - if (OpenGl_AVIWriter_AllowWriting (theCView.DefWindow.XWindow)) - { - GLint params[4]; - glGetIntegerv (GL_VIEWPORT, params); - int nWidth = params[2] & ~0x7; - int nHeight = params[3] & ~0x7; - - const int nBitsPerPixel = 24; - GLubyte* aDumpData = new GLubyte[nWidth * nHeight * nBitsPerPixel / 8]; - - glPixelStorei (GL_PACK_ALIGNMENT, 1); - glReadPixels (0, 0, nWidth, nHeight, GL_BGR_EXT, GL_UNSIGNED_BYTE, aDumpData); - OpenGl_AVIWriter_AVIWriter (aDumpData, nWidth, nHeight, nBitsPerPixel); - delete[] aDumpData; - } -#endif + myAspectFaceApplied = myAspectFaceSet->Aspect(); + return myAspectFaceSet; +} - // bind default FBO - bindDefaultFbo(); +//======================================================================= +//function : SetPolygonOffset +//purpose : +//======================================================================= +void OpenGl_Workspace::SetPolygonOffset (const Graphic3d_PolygonOffset& theParams) +{ + myPolygonOffsetApplied = theParams; - // Swap the buffers - if (toSwap) + if ((theParams.Mode & Aspect_POM_Fill) == Aspect_POM_Fill) { - GetGlContext()->SwapBuffers(); - if (!myMainSceneFbos[0]->IsValid()) - { - myBackBufferRestored = Standard_False; - } + glEnable (GL_POLYGON_OFFSET_FILL); } else { - myGlContext->core11fwd->glFlush(); - } - - // reset render mode state - myGlContext->FetchState(); -} - -// ======================================================================= -// function : redraw1 -// purpose : -// ======================================================================= -void OpenGl_Workspace::redraw1 (const Graphic3d_CView& theCView, - const Aspect_CLayer2d& theCUnderLayer, - const Aspect_CLayer2d& theCOverLayer, - OpenGl_FrameBuffer* theReadDrawFbo, - const Graphic3d_Camera::Projection theProjection) -{ - if (myView.IsNull()) - { - return; + glDisable (GL_POLYGON_OFFSET_FILL); } - if (theReadDrawFbo != NULL) +#if !defined(GL_ES_VERSION_2_0) + if ((theParams.Mode & Aspect_POM_Line) == Aspect_POM_Line) { - theReadDrawFbo->BindBuffer (myGlContext); - theReadDrawFbo->SetupViewport (myGlContext); + glEnable (GL_POLYGON_OFFSET_LINE); } else { - myGlContext->core11fwd->glViewport (0, 0, myWidth, myHeight); + glDisable (GL_POLYGON_OFFSET_LINE); } - // request reset of material - NamedStatus |= OPENGL_NS_RESMAT; - - myUseZBuffer = Standard_True; - myUseDepthWrite = Standard_True; - GLbitfield toClear = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT; - glDepthFunc (GL_LEQUAL); - glDepthMask (GL_TRUE); - glEnable (GL_DEPTH_TEST); - -#if !defined(GL_ES_VERSION_2_0) - glClearDepth (1.0); -#else - glClearDepthf (1.0f); -#endif - - if (NamedStatus & OPENGL_NS_WHITEBACK) + if ((theParams.Mode & Aspect_POM_Point) == Aspect_POM_Point) { - // set background to white - glClearColor (1.0f, 1.0f, 1.0f, 1.0f); + glEnable (GL_POLYGON_OFFSET_POINT); } else { - glClearColor (myBgColor.rgb[0], myBgColor.rgb[1], myBgColor.rgb[2], 0.0f); + glDisable (GL_POLYGON_OFFSET_POINT); } - - glClear (toClear); - - Handle(OpenGl_Workspace) aWS (this); - myView->Render (myPrintContext, aWS, theReadDrawFbo, theProjection, theCView, theCUnderLayer, theCOverLayer, Standard_False); +#endif + glPolygonOffset (theParams.Factor, theParams.Units); } // ======================================================================= -// function : copyBackToFront +// function : ApplyAspectMarker // purpose : // ======================================================================= -void OpenGl_Workspace::copyBackToFront() +const OpenGl_AspectMarker* OpenGl_Workspace::ApplyAspectMarker() { -#if !defined(GL_ES_VERSION_2_0) - - OpenGl_Mat4 aProjectMat; - OpenGl_Utils::Ortho2D (aProjectMat, - 0.f, static_cast (myWidth), 0.f, static_cast (myHeight)); - - myGlContext->WorldViewState.Push(); - myGlContext->ProjectionState.Push(); - - myGlContext->WorldViewState.SetIdentity(); - myGlContext->ProjectionState.SetCurrent (aProjectMat); - - myGlContext->ApplyProjectionMatrix(); - myGlContext->ApplyWorldViewMatrix(); - - DisableFeatures(); - - switch (myGlContext->DrawBuffer()) + if (myAspectMarkerSet->Aspect() != myAspectMarkerApplied) { - case GL_BACK_LEFT: + if (myAspectMarkerApplied.IsNull() + || (myAspectMarkerSet->Aspect()->Scale() != myAspectMarkerApplied->Scale())) { - myGlContext->SetReadBuffer (GL_BACK_LEFT); - myGlContext->SetDrawBuffer (GL_FRONT_LEFT); - break; - } - case GL_BACK_RIGHT: - { - myGlContext->SetReadBuffer (GL_BACK_RIGHT); - myGlContext->SetDrawBuffer (GL_FRONT_RIGHT); - break; - } - default: - { - myGlContext->SetReadBuffer (GL_BACK); - myGlContext->SetDrawBuffer (GL_FRONT); - break; + #if !defined(GL_ES_VERSION_2_0) + glPointSize (myAspectMarkerSet->Aspect()->Scale()); + #ifdef HAVE_GL2PS + gl2psPointSize (myAspectMarkerSet->Aspect()->Scale()); + #endif + #endif } + myAspectMarkerApplied = myAspectMarkerSet->Aspect(); } + return myAspectMarkerSet; +} - glRasterPos2i (0, 0); - glCopyPixels (0, 0, myWidth + 1, myHeight + 1, GL_COLOR); - //glCopyPixels (0, 0, myWidth + 1, myHeight + 1, GL_DEPTH); +// ======================================================================= +// function : Width +// purpose : +// ======================================================================= +Standard_Integer OpenGl_Workspace::Width() const +{ + return !myView->GlWindow().IsNull() ? myView->GlWindow()->Width() : 0; +} - EnableFeatures(); +// ======================================================================= +// function : Height +// purpose : +// ======================================================================= +Standard_Integer OpenGl_Workspace::Height() const +{ + return !myView->GlWindow().IsNull() ? myView->GlWindow()->Height() : 0; +} - myGlContext->WorldViewState.Pop(); - myGlContext->ProjectionState.Pop(); - myGlContext->ApplyProjectionMatrix(); +// ======================================================================= +// function : UseGLLight +// purpose : +// ======================================================================= +Standard_Boolean OpenGl_Workspace::UseGLLight() const +{ + return myView->IsGLLightEnabled(); +} - // read/write from front buffer now - myGlContext->SetReadBuffer (myGlContext->DrawBuffer()); -#endif - myIsImmediateDrawn = Standard_False; +// ======================================================================= +// function : IsCullingEnabled +// purpose : +// ======================================================================= +Standard_Boolean OpenGl_Workspace::IsCullingEnabled() const +{ + return myView->IsCullingEnabled(); } // ======================================================================= -// function : DisplayCallback +// function : FBOCreate // purpose : // ======================================================================= -void OpenGl_Workspace::DisplayCallback (const Graphic3d_CView& theCView, - Standard_Integer theReason) +Handle(OpenGl_FrameBuffer) OpenGl_Workspace::FBOCreate (const Standard_Integer theWidth, + const Standard_Integer theHeight) { - if (theCView.GDisplayCB == NULL) + // activate OpenGL context + if (!Activate()) + return Handle(OpenGl_FrameBuffer)(); + + DisableTexture(); + + // create the FBO + const Handle(OpenGl_Context)& aCtx = GetGlContext(); + Handle(OpenGl_FrameBuffer) aFrameBuffer = new OpenGl_FrameBuffer(); + if (!aFrameBuffer->Init (aCtx, theWidth, theHeight, GL_RGBA8, GL_DEPTH24_STENCIL8, 0)) { - return; + aFrameBuffer->Release (aCtx.operator->()); + return Handle(OpenGl_FrameBuffer)(); } - - Aspect_GraphicCallbackStruct aCallData; - aCallData.reason = theReason; - aCallData.glContext = myGlContext; - aCallData.wsID = theCView.WsId; - aCallData.viewID = theCView.ViewId; - aCallData.IsCoreProfile = (myGlContext->core11 == NULL); - theCView.GDisplayCB (theCView.DefWindow.XWindow, theCView.GClientData, &aCallData); + return aFrameBuffer; } // ======================================================================= -// function : RedrawImmediate +// function : FBORelease // purpose : // ======================================================================= -void OpenGl_Workspace::RedrawImmediate (const Graphic3d_CView& theCView, - const Aspect_CLayer2d& theCUnderLayer, - const Aspect_CLayer2d& theCOverLayer) +void OpenGl_Workspace::FBORelease (Handle(OpenGl_FrameBuffer)& theFbo) { - const Handle(Graphic3d_Camera)& aCamera = myView->Camera(); - Graphic3d_Camera::Projection aProjectType = aCamera->ProjectionType(); - OpenGl_FrameBuffer* aFrameBuffer = (OpenGl_FrameBuffer* )theCView.ptrFBO; - if ( aFrameBuffer == NULL - && !myGlContext->DefaultFrameBuffer().IsNull() - && myGlContext->DefaultFrameBuffer()->IsValid()) + // activate OpenGL context + if (!Activate() + || theFbo.IsNull()) { - aFrameBuffer = myGlContext->DefaultFrameBuffer().operator->(); + return; } - const Graphic3d_StereoMode aStereoMode = theCView.RenderParams.StereoMode; - if (aProjectType == Graphic3d_Camera::Projection_Stereo) + theFbo->Release (GetGlContext().operator->()); + theFbo.Nullify(); +} + +inline bool getDataFormat (const Image_PixMap& theData, + GLenum& thePixelFormat, + GLenum& theDataType) +{ + thePixelFormat = GL_RGB; + theDataType = GL_UNSIGNED_BYTE; + switch (theData.Format()) { - if (aFrameBuffer != NULL) - { - // implicitly switch to mono camera for image dump - aProjectType = Graphic3d_Camera::Projection_Perspective; - } - else if (myMainSceneFbos[0]->IsValid() - && !myMainSceneFbos[1]->IsValid()) - { - aProjectType = Graphic3d_Camera::Projection_Perspective; - } + #if !defined(GL_ES_VERSION_2_0) + case Image_PixMap::ImgGray: + thePixelFormat = GL_DEPTH_COMPONENT; + theDataType = GL_UNSIGNED_BYTE; + return true; + case Image_PixMap::ImgGrayF: + thePixelFormat = GL_DEPTH_COMPONENT; + theDataType = GL_FLOAT; + return true; + case Image_PixMap::ImgBGR: + thePixelFormat = GL_BGR; + theDataType = GL_UNSIGNED_BYTE; + return true; + case Image_PixMap::ImgBGRA: + case Image_PixMap::ImgBGR32: + thePixelFormat = GL_BGRA; + theDataType = GL_UNSIGNED_BYTE; + return true; + case Image_PixMap::ImgBGRF: + thePixelFormat = GL_BGR; + theDataType = GL_FLOAT; + return true; + case Image_PixMap::ImgBGRAF: + thePixelFormat = GL_BGRA; + theDataType = GL_FLOAT; + return true; + #else + case Image_PixMap::ImgGray: + case Image_PixMap::ImgGrayF: + case Image_PixMap::ImgBGR: + case Image_PixMap::ImgBGRA: + case Image_PixMap::ImgBGR32: + case Image_PixMap::ImgBGRF: + case Image_PixMap::ImgBGRAF: + return false; + #endif + case Image_PixMap::ImgRGB: + thePixelFormat = GL_RGB; + theDataType = GL_UNSIGNED_BYTE; + return true; + case Image_PixMap::ImgRGBA: + case Image_PixMap::ImgRGB32: + thePixelFormat = GL_RGBA; + theDataType = GL_UNSIGNED_BYTE; + return true; + case Image_PixMap::ImgRGBF: + thePixelFormat = GL_RGB; + theDataType = GL_FLOAT; + return true; + case Image_PixMap::ImgRGBAF: + thePixelFormat = GL_RGBA; + theDataType = GL_FLOAT; + return true; + case Image_PixMap::ImgAlpha: + case Image_PixMap::ImgAlphaF: + return false; // GL_ALPHA is no more supported in core context + case Image_PixMap::ImgUNKNOWN: + return false; } + return false; +} + +// ======================================================================= +// function : getAligned +// purpose : +// ======================================================================= +inline Standard_Size getAligned (const Standard_Size theNumber, + const Standard_Size theAlignment) +{ + return theNumber + theAlignment - 1 - (theNumber - 1) % theAlignment; +} - if (!myTransientDrawToFront - || !myBackBufferRestored - || (myGlContext->caps->buffersNoSwap && !myMainSceneFbos[0]->IsValid())) +// ======================================================================= +// function : BufferDump +// purpose : +// ======================================================================= +Standard_Boolean OpenGl_Workspace::BufferDump (const Handle(OpenGl_FrameBuffer)& theFbo, + Image_PixMap& theImage, + const Graphic3d_BufferType& theBufferType) +{ + GLenum aFormat, aType; + if (theImage.IsEmpty() + || !getDataFormat (theImage, aFormat, aType) + || !Activate()) { - Redraw (theCView, theCUnderLayer, theCOverLayer); - return; + return Standard_False; } - else if (!Activate()) +#if !defined(GL_ES_VERSION_2_0) + GLint aReadBufferPrev = GL_BACK; + if (theBufferType == Graphic3d_BT_Depth + && aFormat != GL_DEPTH_COMPONENT) { - return; + return Standard_False; } +#else + (void )theBufferType; +#endif - bool toSwap = false; - if (aProjectType == Graphic3d_Camera::Projection_Stereo) + // bind FBO if used + if (!theFbo.IsNull() && theFbo->IsValid()) { - OpenGl_FrameBuffer* aMainFbos[2] = - { - myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL, - myMainSceneFbos[1]->IsValid() ? myMainSceneFbos[1].operator->() : NULL - }; - OpenGl_FrameBuffer* anImmFbos[2] = - { - myImmediateSceneFbos[0]->IsValid() ? myImmediateSceneFbos[0].operator->() : NULL, - myImmediateSceneFbos[1]->IsValid() ? myImmediateSceneFbos[1].operator->() : NULL - }; - if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip - || aStereoMode == Graphic3d_StereoMode_QuadBuffer) - { - anImmFbos[0] = NULL; - anImmFbos[1] = NULL; - } - - if (myGlContext->arbFBO != NULL) - { - myGlContext->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER); - } - #if !defined(GL_ES_VERSION_2_0) - if (anImmFbos[0] == NULL) - { - myGlContext->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_LEFT : GL_BACK); - } - #endif - toSwap = redrawImmediate (theCView, theCUnderLayer, theCOverLayer, - aMainFbos[0], - Graphic3d_Camera::Projection_MonoLeftEye, - anImmFbos[0], - Standard_True) || toSwap; - if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip - && toSwap - && !myGlContext->caps->buffersNoSwap) - { - myGlContext->SwapBuffers(); - } - - if (myGlContext->arbFBO != NULL) - { - myGlContext->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER); - } - #if !defined(GL_ES_VERSION_2_0) - if (anImmFbos[1] == NULL) - { - myGlContext->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_RIGHT : GL_BACK); - } - #endif - toSwap = redrawImmediate (theCView, theCUnderLayer, theCOverLayer, - aMainFbos[1], - Graphic3d_Camera::Projection_MonoRightEye, - anImmFbos[1], - Standard_True) || toSwap; - if (anImmFbos[0] != NULL) - { - bindDefaultFbo (aFrameBuffer); - drawStereoPair (theCView); - } + theFbo->BindBuffer (GetGlContext()); } else { - OpenGl_FrameBuffer* aMainFbo = myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL; #if !defined(GL_ES_VERSION_2_0) - if (aMainFbo == NULL) - { - myGlContext->SetReadDrawBuffer (GL_BACK); - } + glGetIntegerv (GL_READ_BUFFER, &aReadBufferPrev); + GLint aDrawBufferPrev = GL_BACK; + glGetIntegerv (GL_DRAW_BUFFER, &aDrawBufferPrev); + glReadBuffer (aDrawBufferPrev); #endif - toSwap = redrawImmediate (theCView, theCUnderLayer, theCOverLayer, - aMainFbo, - aProjectType, - aFrameBuffer, - Standard_True) || toSwap; } - // bind default FBO - bindDefaultFbo(); + // setup alignment + const GLint anAligment = Min (GLint(theImage.MaxRowAligmentBytes()), 8); // limit to 8 bytes for OpenGL + glPixelStorei (GL_PACK_ALIGNMENT, anAligment); + bool isBatchCopy = !theImage.IsTopDown(); - if (toSwap - && !myGlContext->caps->buffersNoSwap) - { - myGlContext->SwapBuffers(); - } - else + const GLint anExtraBytes = GLint(theImage.RowExtraBytes()); + GLint aPixelsWidth = GLint(theImage.SizeRowBytes() / theImage.SizePixelBytes()); + Standard_Size aSizeRowBytesEstim = getAligned (theImage.SizePixelBytes() * aPixelsWidth, anAligment); + if (anExtraBytes < anAligment) { - myGlContext->core11fwd->glFlush(); + aPixelsWidth = 0; } -} - -// ======================================================================= -// function : redrawImmediate -// purpose : -// ======================================================================= -bool OpenGl_Workspace::redrawImmediate (const Graphic3d_CView& theCView, - const Aspect_CLayer2d& theCUnderLayer, - const Aspect_CLayer2d& theCOverLayer, - OpenGl_FrameBuffer* theReadFbo, - const Graphic3d_Camera::Projection theProjection, - OpenGl_FrameBuffer* theDrawFbo, - const Standard_Boolean theIsPartialUpdate) -{ - GLboolean toCopyBackToFront = GL_FALSE; - if (!myTransientDrawToFront) + else if (aSizeRowBytesEstim != theImage.SizeRowBytes()) { - myBackBufferRestored = Standard_False; + aPixelsWidth = 0; + isBatchCopy = false; } - else if (theReadFbo != NULL - && theReadFbo->IsValid() - && myGlContext->IsRender()) +#if !defined(GL_ES_VERSION_2_0) + glPixelStorei (GL_PACK_ROW_LENGTH, aPixelsWidth); +#else + if (aPixelsWidth != 0) { - if (!blitBuffers (theReadFbo, theDrawFbo)) - { - return true; - } + isBatchCopy = false; } - else if (theDrawFbo == NULL) +#endif + + if (!isBatchCopy) { - #if !defined(GL_ES_VERSION_2_0) - myGlContext->core11fwd->glGetBooleanv (GL_DOUBLEBUFFER, &toCopyBackToFront); - #endif - if (toCopyBackToFront) + // copy row by row + for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow) { - if (!myView->HasImmediateStructures() - && !theIsPartialUpdate) - { - // prefer Swap Buffers within Redraw in compatibility mode (without FBO) - return true; - } - copyBackToFront(); - } - else - { - myBackBufferRestored = Standard_False; + // Image_PixMap rows indexation always starts from the upper corner + // while order in memory depends on the flag and processed by ChangeRow() method + glReadPixels (0, GLint(theImage.SizeY() - aRow - 1), GLsizei (theImage.SizeX()), 1, aFormat, aType, theImage.ChangeRow (aRow)); } } else { - myBackBufferRestored = Standard_False; + glReadPixels (0, 0, GLsizei (theImage.SizeX()), GLsizei (theImage.SizeY()), aFormat, aType, theImage.ChangeData()); } - myIsImmediateDrawn = Standard_True; - - Handle(OpenGl_Workspace) aWS (this); - myUseZBuffer = Standard_True; - myUseDepthWrite = Standard_True; - glDepthFunc (GL_LEQUAL); - glDepthMask (GL_TRUE); - glEnable (GL_DEPTH_TEST); + glPixelStorei (GL_PACK_ALIGNMENT, 1); #if !defined(GL_ES_VERSION_2_0) - glClearDepth (1.0); -#else - glClearDepthf (1.0f); + glPixelStorei (GL_PACK_ROW_LENGTH, 0); #endif - myView->Render (myPrintContext, aWS, theDrawFbo, theProjection, - theCView, theCUnderLayer, theCOverLayer, Standard_True); - if (!myView->ImmediateStructures().IsEmpty()) + if (!theFbo.IsNull() && theFbo->IsValid()) { - myUseZBuffer = Standard_False; - glDisable (GL_DEPTH_TEST); + theFbo->UnbindBuffer (GetGlContext()); } - for (OpenGl_IndexedMapOfStructure::Iterator anIter (myView->ImmediateStructures()); anIter.More(); anIter.Next()) + else { - const OpenGl_Structure* aStructure = anIter.Value(); - if (!aStructure->IsVisible()) - { - continue; - } - - aStructure->Render (aWS); + #if !defined(GL_ES_VERSION_2_0) + glReadBuffer (aReadBufferPrev); + #endif } - - return !toCopyBackToFront; + return Standard_True; } - // ======================================================================= // function : CanRender // purpose :