// Created on: 2011-09-20 // Created by: Sergey ZERCHANINOV // Copyright (c) 2011-2014 OPEN CASCADE SAS // // This file is part of Open CASCADE Technology software library. // // This library is free software; you can redistribute it and/or modify it under // the terms of the GNU Lesser General Public License version 2.1 as published // by the Free Software Foundation, with special exception defined in the file // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT // distribution for complete text of the license and disclaimer of any warranty. // // 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 #include #include #include #include #include #include #include #include #include #include #include #if defined(_WIN32) && defined(HAVE_VIDEOCAPTURE) #include #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_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 }, { 0.0F, 1.0F, 0.0F, 0.0F }, { 0.0F, 0.0F, 1.0F, 0.0F }, { 0.0F, 0.0F, 0.0F, 1.0F }} }; }; // ======================================================================= // function : Init // purpose : // ======================================================================= void OpenGl_Material::Init (const OPENGL_SURF_PROP& theProp) { // ambient component if (theProp.color_mask & OPENGL_AMBIENT_MASK) { 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); } else { Ambient = THE_BLACK_COLOR; } // diffusion component if (theProp.color_mask & OPENGL_DIFFUSE_MASK) { 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); } else { Diffuse = THE_BLACK_COLOR; } // specular component if (theProp.color_mask & OPENGL_SPECULAR_MASK) { 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); } else { Specular = THE_BLACK_COLOR; } // emission component if (theProp.color_mask & OPENGL_EMISSIVE_MASK) { 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); } else { Emission = THE_BLACK_COLOR; } ChangeShine() = theProp.shine; ChangeTransparency() = theProp.trans; } // ======================================================================= // 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), HighlightColor (&THE_WHITE_COLOR), // myHasFboBlit (Standard_True), myToFlipOutput (Standard_False), // myViewId (-1), myAntiAliasingMode (3), myTransientDrawToFront (Standard_True), myBackBufferRestored (Standard_False), myIsImmediateDrawn (Standard_False), 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), ViewMatrix_applied (&myDefaultMatrix), StructureMatrix_applied (&myDefaultMatrix), myCullingMode (TelCullUndefined), myModelViewMatrix (myDefaultMatrix), PolygonOffset_applied (THE_DEFAULT_POFFSET) { 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)) { // share and register for release once the resource is no longer used myLineAttribs = new OpenGl_LineAttributes(); myGlContext->ShareResource ("OpenGl_LineAttributes", myLineAttribs); myLineAttribs->Init (myGlContext); } // 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 : SetActiveView // purpose : // ======================================================================= void OpenGl_Workspace::SetActiveView (const Handle(OpenGl_View)& theView, const Standard_Integer theViewId) { myView = theView; myViewId = theViewId; } // ======================================================================= // function : SetImmediateModeDrawToFront // purpose : // ======================================================================= Standard_Boolean OpenGl_Workspace::SetImmediateModeDrawToFront (const Standard_Boolean theDrawToFrontBuffer) { const Standard_Boolean aPrevMode = myTransientDrawToFront; myTransientDrawToFront = theDrawToFrontBuffer; return aPrevMode; } inline void nullifyGlResource (Handle(OpenGl_Resource)& theResource, const Handle(OpenGl_Context)& theCtx) { if (!theResource.IsNull()) { theResource->Release (theCtx.operator->()); theResource.Nullify(); } } // ======================================================================= // function : ~OpenGl_Workspace // purpose : // ======================================================================= OpenGl_Workspace::~OpenGl_Workspace() { if (!myLineAttribs.IsNull()) { myLineAttribs.Nullify(); myGlContext->ReleaseResource ("OpenGl_LineAttributes", Standard_True); } nullifyGlResource (myMainSceneFbos[0], myGlContext); nullifyGlResource (myMainSceneFbos[1], myGlContext); nullifyGlResource (myImmediateSceneFbos[0], myGlContext); nullifyGlResource (myImmediateSceneFbos[1], myGlContext); myFullScreenQuad .Release (myGlContext.operator->()); myFullScreenQuadFlip.Release (myGlContext.operator->()); } // ======================================================================= // function : Activate // purpose : // ======================================================================= Standard_Boolean OpenGl_Workspace::Activate() { if (!OpenGl_Window::Activate()) return Standard_False; ViewMatrix_applied = &myDefaultMatrix; StructureMatrix_applied = &myDefaultMatrix; ResetAppliedAspect(); return Standard_True; } //======================================================================= //function : ResetAppliedAspect //purpose : Sets default values of GL parameters in accordance with default aspects //======================================================================= void OpenGl_Workspace::ResetAppliedAspect() { myGlContext->BindDefaultVao(); 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()); } // ======================================================================= // function : DisableTexture // purpose : // ======================================================================= Handle(OpenGl_Texture) OpenGl_Workspace::DisableTexture() { if (myTextureBound.IsNull()) { return myTextureBound; } const Handle(OpenGl_Sampler)& aSampler = myGlContext->TextureSampler(); if (!aSampler.IsNull()) { aSampler->Unbind (*myGlContext); } #if !defined(GL_ES_VERSION_2_0) // reset texture matrix because some code may expect it is identity if (myGlContext->core11 != NULL) { GLint aMatrixMode = GL_TEXTURE; glGetIntegerv (GL_MATRIX_MODE, &aMatrixMode); glMatrixMode (GL_TEXTURE); glLoadIdentity(); glMatrixMode (aMatrixMode); } #endif myTextureBound->Unbind (myGlContext); switch (myTextureBound->GetTarget()) { #if !defined(GL_ES_VERSION_2_0) case GL_TEXTURE_1D: { if (myGlContext->core11 != NULL) { if (myTextureBound->GetParams()->GenMode() != GL_NONE) { glDisable (GL_TEXTURE_GEN_S); } glDisable (GL_TEXTURE_1D); } break; } #endif case GL_TEXTURE_2D: { #if !defined(GL_ES_VERSION_2_0) if (myGlContext->core11 != NULL) { if (myTextureBound->GetParams()->GenMode() != GL_NONE) { glDisable (GL_TEXTURE_GEN_S); glDisable (GL_TEXTURE_GEN_T); if (myTextureBound->GetParams()->GenMode() == Graphic3d_TOTM_SPRITE) { glDisable (GL_POINT_SPRITE); } } glDisable (GL_TEXTURE_2D); } #endif break; } default: break; } Handle(OpenGl_Texture) aPrevTexture = myTextureBound; myTextureBound.Nullify(); return aPrevTexture; } // ======================================================================= // function : setTextureParams // purpose : // ======================================================================= void OpenGl_Workspace::setTextureParams (Handle(OpenGl_Texture)& theTexture, const Handle(Graphic3d_TextureParams)& theParams) { const Handle(Graphic3d_TextureParams)& aParams = theParams.IsNull() ? theTexture->GetParams() : theParams; if (aParams.IsNull()) { return; } #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(); Graphic3d_TransformUtils::Scale (aTextureMat, aScale.x(), aScale.y(), 1.0f); Graphic3d_TransformUtils::Translate (aTextureMat, -aTrans.x(), -aTrans.y(), 0.0f); Graphic3d_TransformUtils::Rotate (aTextureMat, -aParams->Rotation(), 0.0f, 0.0f, 1.0f); glLoadMatrixf (aTextureMat); GLint anEnvMode = GL_MODULATE; // lighting mode if (!aParams->IsModulate()) { anEnvMode = GL_DECAL; if (theTexture->GetFormat() == GL_ALPHA || theTexture->GetFormat() == GL_LUMINANCE) { anEnvMode = GL_REPLACE; } } // setup generation of texture coordinates switch (aParams->GenMode()) { case Graphic3d_TOTM_OBJECT: { glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); glTexGenfv (GL_S, GL_OBJECT_PLANE, aParams->GenPlaneS().GetData()); if (theTexture->GetTarget() != GL_TEXTURE_1D) { glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); glTexGenfv (GL_T, GL_OBJECT_PLANE, aParams->GenPlaneT().GetData()); } break; } case Graphic3d_TOTM_SPHERE: { glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); if (theTexture->GetTarget() != GL_TEXTURE_1D) { glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); } break; } case Graphic3d_TOTM_EYE: { myGlContext->WorldViewState.Push(); myGlContext->WorldViewState.SetIdentity(); myGlContext->ApplyWorldViewMatrix(); glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); glTexGenfv (GL_S, GL_EYE_PLANE, aParams->GenPlaneS().GetData()); if (theTexture->GetTarget() != GL_TEXTURE_1D) { glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); glTexGenfv (GL_T, GL_EYE_PLANE, aParams->GenPlaneT().GetData()); } myGlContext->WorldViewState.Pop(); break; } case Graphic3d_TOTM_SPRITE: { if (GetGlContext()->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; } case Graphic3d_TOTM_MANUAL: default: break; } // setup lighting glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, anEnvMode); } #endif // get active sampler object to override default texture parameters const Handle(OpenGl_Sampler)& aSampler = myGlContext->TextureSampler(); // setup texture filtering and wrapping //if (theTexture->GetParams() != theParams) const GLenum aFilter = (aParams->Filter() == Graphic3d_TOTF_NEAREST) ? GL_NEAREST : GL_LINEAR; const GLenum aWrapMode = aParams->IsRepeat() ? GL_REPEAT : myGlContext->TextureWrapClamp(); switch (theTexture->GetTarget()) { #if !defined(GL_ES_VERSION_2_0) case GL_TEXTURE_1D: { if (aSampler.IsNull() || !aSampler->IsValid()) { glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, aFilter); glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, aFilter); glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, aWrapMode); } else { aSampler->SetParameter (*myGlContext, GL_TEXTURE_MAG_FILTER, aFilter); aSampler->SetParameter (*myGlContext, GL_TEXTURE_MIN_FILTER, aFilter); aSampler->SetParameter (*myGlContext, GL_TEXTURE_WRAP_S, aWrapMode); } break; } #endif case GL_TEXTURE_2D: { GLenum aFilterMin = aFilter; if (theTexture->HasMipmaps()) { aFilterMin = GL_NEAREST_MIPMAP_NEAREST; if (aParams->Filter() == Graphic3d_TOTF_BILINEAR) { aFilterMin = GL_LINEAR_MIPMAP_NEAREST; } else if (aParams->Filter() == Graphic3d_TOTF_TRILINEAR) { aFilterMin = GL_LINEAR_MIPMAP_LINEAR; } if (myGlContext->extAnis) { // setup degree of anisotropy filter const GLint aMaxDegree = myGlContext->MaxDegreeOfAnisotropy(); GLint aDegree; switch (aParams->AnisoFilter()) { case Graphic3d_LOTA_QUALITY: { aDegree = aMaxDegree; break; } case Graphic3d_LOTA_MIDDLE: { aDegree = (aMaxDegree <= 4) ? 2 : (aMaxDegree / 2); break; } case Graphic3d_LOTA_FAST: { aDegree = 2; break; } case Graphic3d_LOTA_OFF: default: { aDegree = 1; break; } } if (aSampler.IsNull() || !aSampler->IsValid()) { glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, aDegree); } else { aSampler->SetParameter (*myGlContext, GL_TEXTURE_MAX_ANISOTROPY_EXT, aDegree); } } } if (aSampler.IsNull() || !aSampler->IsValid()) { glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, aFilterMin); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, aFilter); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, aWrapMode); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, aWrapMode); } else { aSampler->SetParameter (*myGlContext, GL_TEXTURE_MIN_FILTER, aFilterMin); aSampler->SetParameter (*myGlContext, GL_TEXTURE_MAG_FILTER, aFilter); aSampler->SetParameter (*myGlContext, GL_TEXTURE_WRAP_S, aWrapMode); aSampler->SetParameter (*myGlContext, GL_TEXTURE_WRAP_T, aWrapMode); } break; } default: break; } switch (theTexture->GetTarget()) { #if !defined(GL_ES_VERSION_2_0) case GL_TEXTURE_1D: { if (myGlContext->core11 != NULL) { if (aParams->GenMode() != Graphic3d_TOTM_MANUAL) { glEnable (GL_TEXTURE_GEN_S); } glEnable (GL_TEXTURE_1D); } break; } #endif case GL_TEXTURE_2D: { #if !defined(GL_ES_VERSION_2_0) if (myGlContext->core11 != NULL) { if (aParams->GenMode() != Graphic3d_TOTM_MANUAL) { glEnable (GL_TEXTURE_GEN_S); glEnable (GL_TEXTURE_GEN_T); } glEnable (GL_TEXTURE_2D); } #endif break; } default: break; } #if !defined(GL_ES_VERSION_2_0) if (myGlContext->core11 != NULL) { glMatrixMode (aMatrixMode); // turn back active matrix } #endif theTexture->SetParams (aParams); } // ======================================================================= // function : EnableTexture // purpose : // ======================================================================= Handle(OpenGl_Texture) OpenGl_Workspace::EnableTexture (const Handle(OpenGl_Texture)& theTexture, const Handle(Graphic3d_TextureParams)& theParams) { if (theTexture.IsNull() || !theTexture->IsValid()) { return DisableTexture(); } if (myTextureBound == theTexture && (theParams.IsNull() || theParams == theTexture->GetParams())) { // already bound return myTextureBound; } Handle(OpenGl_Texture) aPrevTexture = DisableTexture(); myTextureBound = theTexture; myTextureBound->Bind (myGlContext); setTextureParams (myTextureBound, theParams); // If custom sampler object is available it will be // used for overriding default texture parameters const Handle(OpenGl_Sampler)& aSampler = myGlContext->TextureSampler(); if (!aSampler.IsNull() && aSampler->IsValid()) { aSampler->Bind (*myGlContext); } return aPrevTexture; } // ======================================================================= // function : bindDefaultFbo // purpose : // ======================================================================= void OpenGl_Workspace::bindDefaultFbo (OpenGl_FrameBuffer* theCustomFbo) { 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 } myGlContext->core11fwd->glViewport (0, 0, myWidth, myHeight); } // ======================================================================= // function : initBlitQuad // purpose : // ======================================================================= OpenGl_VertexBuffer* OpenGl_Workspace::initBlitQuad (const Standard_Boolean theToFlip) { OpenGl_VertexBuffer* aVerts = NULL; if (!theToFlip) { aVerts = &myFullScreenQuad; if (!aVerts->IsValid()) { 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) }; aVerts->Init (myGlContext, 4, 4, aQuad[0].GetData()); } } else { aVerts = &myFullScreenQuadFlip; if (!aVerts->IsValid()) { OpenGl_Vec4 aQuad[4] = { OpenGl_Vec4( 1.0f, -1.0f, 1.0f, 1.0f), OpenGl_Vec4( 1.0f, 1.0f, 1.0f, 0.0f), OpenGl_Vec4(-1.0f, -1.0f, 0.0f, 1.0f), OpenGl_Vec4(-1.0f, 1.0f, 0.0f, 0.0f) }; aVerts->Init (myGlContext, 4, 4, aQuad[0].GetData()); } } return aVerts; } // ======================================================================= // function : blitBuffers // purpose : // ======================================================================= bool OpenGl_Workspace::blitBuffers (OpenGl_FrameBuffer* theReadFbo, OpenGl_FrameBuffer* theDrawFbo, const Standard_Boolean theToFlip) { if (theReadFbo == NULL || myGlContext->IsFeedback()) { return false; } else if (theReadFbo == theDrawFbo) { return true; } // clear destination before blitting if (theDrawFbo != NULL && theDrawFbo->IsValid()) { theDrawFbo->BindBuffer (myGlContext); } else { myGlContext->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER); } #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) { theReadFbo->BindReadBuffer (myGlContext); if (theDrawFbo != NULL && theDrawFbo->IsValid()) { theDrawFbo->BindDrawBuffer (myGlContext); } else { myGlContext->arbFBO->glBindFramebuffer (GL_DRAW_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER); } // 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()) { theDrawFbo->BindBuffer (myGlContext); } else { myGlContext->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER); } } else #endif*/ { myGlContext->core20fwd->glDepthFunc (GL_ALWAYS); myGlContext->core20fwd->glDepthMask (GL_TRUE); myGlContext->core20fwd->glEnable (GL_DEPTH_TEST); DisableTexture(); OpenGl_VertexBuffer* aVerts = initBlitQuad (theToFlip); const Handle(OpenGl_ShaderManager)& aManager = myGlContext->ShaderManager(); if (aVerts->IsValid() && aManager->BindFboBlitProgram()) { theReadFbo->ColorTexture() ->Bind (myGlContext, GL_TEXTURE0 + 0); theReadFbo->DepthStencilTexture()->Bind (myGlContext, GL_TEXTURE0 + 1); aVerts->BindVertexAttrib (myGlContext, Graphic3d_TOA_POS); myGlContext->core20fwd->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4); aVerts->UnbindVertexAttrib (myGlContext, Graphic3d_TOA_POS); theReadFbo->DepthStencilTexture()->Unbind (myGlContext, GL_TEXTURE0 + 1); theReadFbo->ColorTexture() ->Unbind (myGlContext, GL_TEXTURE0 + 0); } 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; } } 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) { 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(); OpenGl_VertexBuffer* aVerts = initBlitQuad (myToFlipOutput); const Handle(OpenGl_ShaderManager)& aManager = myGlContext->ShaderManager(); if (aVerts->IsValid() && aManager->BindStereoProgram (theCView.RenderParams.StereoMode)) { if (theCView.RenderParams.StereoMode == Graphic3d_StereoMode_Anaglyph) { 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); } aPair[0]->ColorTexture()->Bind (myGlContext, GL_TEXTURE0 + 0); aPair[1]->ColorTexture()->Bind (myGlContext, GL_TEXTURE0 + 1); aVerts->BindVertexAttrib (myGlContext, 0); myGlContext->core20fwd->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4); aVerts->UnbindVertexAttrib (myGlContext, 0); aPair[1]->ColorTexture()->Unbind (myGlContext, GL_TEXTURE0 + 1); aPair[0]->ColorTexture()->Unbind (myGlContext, GL_TEXTURE0 + 0); } else { 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); } } // ======================================================================= // function : Redraw // purpose : // ======================================================================= void OpenGl_Workspace::Redraw (const Graphic3d_CView& theCView) { 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(); OpenGl_FrameBuffer* aFrameBuffer = (OpenGl_FrameBuffer* )theCView.ptrFBO; bool toSwap = myGlContext->IsRender() && !myGlContext->caps->buffersNoSwap && aFrameBuffer == NULL; Standard_Integer aSizeX = aFrameBuffer != NULL ? aFrameBuffer->GetVPSizeX() : myWidth; Standard_Integer aSizeY = aFrameBuffer != NULL ? aFrameBuffer->GetVPSizeY() : myHeight; if ( aFrameBuffer == NULL && !myGlContext->DefaultFrameBuffer().IsNull() && myGlContext->DefaultFrameBuffer()->IsValid()) { aFrameBuffer = myGlContext->DefaultFrameBuffer().operator->(); } if (myHasFboBlit && (myTransientDrawToFront || aProjectType == Graphic3d_Camera::Projection_Stereo)) { if (myMainSceneFbos[0]->GetVPSizeX() != aSizeX || myMainSceneFbos[0]->GetVPSizeY() != aSizeY) { // prepare FBOs containing main scene // for further blitting and rendering immediate presentations on top if (myGlContext->core20fwd != NULL) { myMainSceneFbos[0]->Init (myGlContext, aSizeX, aSizeY); } if (!myGlContext->caps->useSystemBuffer && myMainSceneFbos[0]->IsValid()) { myImmediateSceneFbos[0]->InitLazy (myGlContext, aSizeX, aSizeY); } } } else { 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); } if (aProjectType == Graphic3d_Camera::Projection_Stereo && myMainSceneFbos[0]->IsValid()) { 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) { myImmediateSceneFbos[0]->InitLazy (myGlContext, aSizeX, aSizeY); myImmediateSceneFbos[1]->InitLazy (myGlContext, aSizeX, aSizeY); if (!myImmediateSceneFbos[0]->IsValid() || !myImmediateSceneFbos[1]->IsValid()) { aProjectType = Graphic3d_Camera::Projection_Perspective; } } } if (aProjectType == Graphic3d_Camera::Projection_Stereo) { 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; } #if !defined(GL_ES_VERSION_2_0) myGlContext->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_LEFT : GL_BACK); #endif redraw1 (theCView, 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, aMainFbos[0], aProjectType, anImmFbos[0])) { toSwap = false; } else if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip && toSwap) { myGlContext->SwapBuffers(); } #if !defined(GL_ES_VERSION_2_0) myGlContext->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_RIGHT : GL_BACK); #endif redraw1 (theCView, aMainFbos[1], Graphic3d_Camera::Projection_MonoRightEye); myBackBufferRestored = Standard_True; myIsImmediateDrawn = Standard_False; if (!redrawImmediate (theCView, aMainFbos[1], aProjectType, anImmFbos[1])) { toSwap = false; } if (anImmFbos[0] != NULL) { bindDefaultFbo (aFrameBuffer); drawStereoPair (theCView); } } else { OpenGl_FrameBuffer* aMainFbo = myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL; OpenGl_FrameBuffer* anImmFbo = aFrameBuffer; if (!myGlContext->caps->useSystemBuffer && myImmediateSceneFbos[0]->IsValid()) { anImmFbo = myImmediateSceneFbos[0].operator->(); } #if !defined(GL_ES_VERSION_2_0) if (aMainFbo == NULL && aFrameBuffer == NULL) { myGlContext->SetReadDrawBuffer (GL_BACK); } #endif redraw1 (theCView, aMainFbo != NULL ? aMainFbo : aFrameBuffer, aProjectType); myBackBufferRestored = Standard_True; myIsImmediateDrawn = Standard_False; if (!redrawImmediate (theCView, aMainFbo, aProjectType, anImmFbo)) { toSwap = false; } if (anImmFbo != NULL && anImmFbo != aFrameBuffer) { blitBuffers (anImmFbo, aFrameBuffer, myToFlipOutput); } } #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 // bind default FBO bindDefaultFbo(); // Swap the buffers if (toSwap) { GetGlContext()->SwapBuffers(); if (!myMainSceneFbos[0]->IsValid()) { myBackBufferRestored = Standard_False; } } else { myGlContext->core11fwd->glFlush(); } // reset render mode state myGlContext->FetchState(); } // ======================================================================= // function : redraw1 // purpose : // ======================================================================= void OpenGl_Workspace::redraw1 (const Graphic3d_CView& theCView, OpenGl_FrameBuffer* theReadDrawFbo, const Graphic3d_Camera::Projection theProjection) { if (myView.IsNull()) { return; } if (theReadDrawFbo != NULL) { theReadDrawFbo->BindBuffer (myGlContext); theReadDrawFbo->SetupViewport (myGlContext); } else { myGlContext->core11fwd->glViewport (0, 0, myWidth, myHeight); } // 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) { // set background to white glClearColor (1.0f, 1.0f, 1.0f, 1.0f); } else { glClearColor (myBgColor.rgb[0], myBgColor.rgb[1], myBgColor.rgb[2], 0.0f); } glClear (toClear); Handle(OpenGl_Workspace) aWS (this); myView->Render (myPrintContext, aWS, theReadDrawFbo, theProjection, theCView, Standard_False); } // ======================================================================= // function : copyBackToFront // purpose : // ======================================================================= void OpenGl_Workspace::copyBackToFront() { #if !defined(GL_ES_VERSION_2_0) OpenGl_Mat4 aProjectMat; Graphic3d_TransformUtils::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()) { case GL_BACK_LEFT: { 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; } } glRasterPos2i (0, 0); glCopyPixels (0, 0, myWidth + 1, myHeight + 1, GL_COLOR); //glCopyPixels (0, 0, myWidth + 1, myHeight + 1, GL_DEPTH); EnableFeatures(); myGlContext->WorldViewState.Pop(); myGlContext->ProjectionState.Pop(); myGlContext->ApplyProjectionMatrix(); // read/write from front buffer now myGlContext->SetReadBuffer (myGlContext->DrawBuffer()); #endif myIsImmediateDrawn = Standard_False; } // ======================================================================= // function : DisplayCallback // purpose : // ======================================================================= void OpenGl_Workspace::DisplayCallback (const Graphic3d_CView& theCView, Standard_Integer theReason) { if (theCView.GDisplayCB == NULL) { return; } 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); } // ======================================================================= // function : RedrawImmediate // purpose : // ======================================================================= void OpenGl_Workspace::RedrawImmediate (const Graphic3d_CView& theCView) { if (!myTransientDrawToFront || !myBackBufferRestored || (myGlContext->caps->buffersNoSwap && !myMainSceneFbos[0]->IsValid())) { Redraw (theCView); return; } else if (!Activate()) { return; } 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()) { aFrameBuffer = myGlContext->DefaultFrameBuffer().operator->(); } const Graphic3d_StereoMode aStereoMode = theCView.RenderParams.StereoMode; if (aProjectType == Graphic3d_Camera::Projection_Stereo) { if (myMainSceneFbos[0]->IsValid() && !myMainSceneFbos[1]->IsValid()) { aProjectType = Graphic3d_Camera::Projection_Perspective; } } bool toSwap = false; if (aProjectType == Graphic3d_Camera::Projection_Stereo) { 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, 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, aMainFbos[1], Graphic3d_Camera::Projection_MonoRightEye, anImmFbos[1], Standard_True) || toSwap; if (anImmFbos[0] != NULL) { bindDefaultFbo (aFrameBuffer); drawStereoPair (theCView); } } else { OpenGl_FrameBuffer* aMainFbo = myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL; OpenGl_FrameBuffer* anImmFbo = aFrameBuffer; if (!myGlContext->caps->useSystemBuffer && myImmediateSceneFbos[0]->IsValid()) { anImmFbo = myImmediateSceneFbos[0].operator->(); } #if !defined(GL_ES_VERSION_2_0) if (aMainFbo == NULL) { myGlContext->SetReadDrawBuffer (GL_BACK); } #endif toSwap = redrawImmediate (theCView, aMainFbo, aProjectType, anImmFbo, Standard_True) || toSwap; if (anImmFbo != NULL && anImmFbo != aFrameBuffer) { blitBuffers (anImmFbo, aFrameBuffer, myToFlipOutput); } } // bind default FBO bindDefaultFbo(); if (toSwap && !myGlContext->caps->buffersNoSwap) { myGlContext->SwapBuffers(); } else { myGlContext->core11fwd->glFlush(); } } // ======================================================================= // function : redrawImmediate // purpose : // ======================================================================= bool OpenGl_Workspace::redrawImmediate (const Graphic3d_CView& theCView, OpenGl_FrameBuffer* theReadFbo, const Graphic3d_Camera::Projection theProjection, OpenGl_FrameBuffer* theDrawFbo, const Standard_Boolean theIsPartialUpdate) { GLboolean toCopyBackToFront = GL_FALSE; if (!myTransientDrawToFront) { myBackBufferRestored = Standard_False; } else if (theReadFbo != NULL && theReadFbo->IsValid() && myGlContext->IsRender()) { if (!blitBuffers (theReadFbo, theDrawFbo)) { return true; } } else if (theDrawFbo == NULL) { #if !defined(GL_ES_VERSION_2_0) myGlContext->core11fwd->glGetBooleanv (GL_DOUBLEBUFFER, &toCopyBackToFront); #endif if (toCopyBackToFront) { if (!myView->HasImmediateStructures() && !theIsPartialUpdate) { // prefer Swap Buffers within Redraw in compatibility mode (without FBO) return true; } copyBackToFront(); } else { myBackBufferRestored = Standard_False; } } else { myBackBufferRestored = Standard_False; } myIsImmediateDrawn = Standard_True; Handle(OpenGl_Workspace) aWS (this); myUseZBuffer = Standard_True; myUseDepthWrite = Standard_True; 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 myView->Render (myPrintContext, aWS, theDrawFbo, theProjection, theCView, Standard_True); return !toCopyBackToFront; } // ======================================================================= // function : CanRender // purpose : // ======================================================================= Standard_Boolean OpenGl_RaytraceFilter::CanRender (const OpenGl_Element* theElement) { Standard_Boolean aPrevFilterResult = Standard_True; if (!myPrevRenderFilter.IsNull()) { aPrevFilterResult = myPrevRenderFilter->CanRender (theElement); } return aPrevFilterResult && !OpenGl_Raytrace::IsRaytracedElement (theElement); }