Messenger()->Send (aMsg, aGrav);
}
+// =======================================================================
+// function : checkWrongVersion
+// purpose :
+// ======================================================================
+void OpenGl_Context::checkWrongVersion (const Standard_Integer theGlVerMajor,
+ const Standard_Integer theGlVerMinor)
+{
+ if (!IsGlGreaterEqual (theGlVerMajor, theGlVerMinor))
+ {
+ return;
+ }
+
+ TCollection_ExtendedString aMsg = TCollection_ExtendedString()
+ + "Error! OpenGL context reports version "
+ + myGlVerMajor + "." + myGlVerMinor
+ + " but does not export required functions for "
+ + theGlVerMajor + "." + theGlVerMinor;
+ PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
+ GL_DEBUG_TYPE_ERROR_ARB,
+ 0,
+ GL_DEBUG_SEVERITY_HIGH_ARB,
+ aMsg);
+}
+
// =======================================================================
// function : init
// purpose :
if (!has12)
{
+ checkWrongVersion (1, 2);
myGlVerMajor = 1;
myGlVerMinor = 1;
return;
}
else if (!has13)
{
+ checkWrongVersion (1, 3);
myGlVerMajor = 1;
myGlVerMinor = 2;
return;
}
else if (!has14)
{
+ checkWrongVersion (1, 4);
myGlVerMajor = 1;
myGlVerMinor = 3;
return;
}
else if (!has15)
{
+ checkWrongVersion (1, 5);
myGlVerMajor = 1;
myGlVerMinor = 4;
return;
if (!has20)
{
+ checkWrongVersion (2, 0);
+ myGlVerMajor = 1;
+ myGlVerMinor = 5;
+ return;
+ }
+
+ const char* aGlslVer = (const char* )::glGetString (GL_SHADING_LANGUAGE_VERSION);
+ if (aGlslVer == NULL
+ || *aGlslVer == '\0')
+ {
+ // broken context has been detected
+ TCollection_ExtendedString aMsg = TCollection_ExtendedString()
+ + "Error! OpenGL context reports version "
+ + myGlVerMajor + "." + myGlVerMinor
+ + " but reports wrong GLSL version";
+ PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
+ GL_DEBUG_TYPE_ERROR_ARB,
+ 0,
+ GL_DEBUG_SEVERITY_HIGH_ARB,
+ aMsg);
myGlVerMajor = 1;
myGlVerMinor = 5;
return;
if (!has21)
{
+ checkWrongVersion (2, 1);
myGlVerMajor = 2;
myGlVerMinor = 0;
return;
if (!has30)
{
+ checkWrongVersion (3, 0);
myGlVerMajor = 2;
myGlVerMinor = 1;
return;
if (!has31)
{
+ checkWrongVersion (3, 1);
myGlVerMajor = 3;
myGlVerMinor = 0;
return;
if (!has32)
{
+ checkWrongVersion (3, 2);
myGlVerMajor = 3;
myGlVerMinor = 1;
return;
if (!has33)
{
+ checkWrongVersion (3, 3);
myGlVerMajor = 3;
myGlVerMinor = 2;
return;
if (!has40)
{
+ checkWrongVersion (4, 0);
myGlVerMajor = 3;
myGlVerMinor = 3;
return;
if (!has41)
{
+ checkWrongVersion (4, 1);
myGlVerMajor = 4;
myGlVerMinor = 0;
return;
if(!has42)
{
+ checkWrongVersion (4, 2);
myGlVerMajor = 4;
myGlVerMinor = 1;
return;
if (!has43)
{
+ checkWrongVersion (4, 3);
myGlVerMajor = 4;
myGlVerMinor = 2;
return;
if (!has44)
{
+ checkWrongVersion (4, 4);
myGlVerMajor = 4;
myGlVerMinor = 3;
return;
myComputeInitStatus (OpenGl_RT_NONE),
myIsRaytraceDataValid (Standard_False),
myIsRaytraceWarnTextures (Standard_False),
+ myHasFboBlit (Standard_True),
myViewModificationStatus (0),
myLayersModificationStatus (0),
//
myIsCullingEnabled = theCView.IsCullingEnabled;
// release pending GL resources
- Handle(OpenGl_Context) aGlCtx = GetGlContext();
- aGlCtx->ReleaseDelayed();
+ myGlContext->ReleaseDelayed();
// fetch OpenGl context state
- aGlCtx->FetchState();
+ myGlContext->FetchState();
- Tint toSwap = (aGlCtx->IsRender() && !aGlCtx->caps->buffersNoSwap) ? 1 : 0; // swap buffers
OpenGl_FrameBuffer* aFrameBuffer = (OpenGl_FrameBuffer* )theCView.ptrFBO;
if (aFrameBuffer != NULL)
{
- aFrameBuffer->SetupViewport (aGlCtx);
- toSwap = 0; // no need to swap buffers
+ aFrameBuffer->SetupViewport (myGlContext);
}
else
{
- aGlCtx->core11fwd->glViewport (0, 0, myWidth, myHeight);
+ myGlContext->core11fwd->glViewport (0, 0, myWidth, myHeight);
}
+ 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 (myResultFBO->GetVPSizeX() != aSizeX
- || myResultFBO->GetVPSizeY() != aSizeY)
+ if (myHasFboBlit
+ && myTransientDrawToFront)
{
- // prepare FBOs containing main scene
- // for further blitting and rendering immediate presentations on top
- if (aGlCtx->core20fwd != NULL)
+ if (myResultFBO->GetVPSizeX() != aSizeX
+ || myResultFBO->GetVPSizeY() != aSizeY)
{
- myResultFBO->Init (aGlCtx, aSizeX, aSizeY);
+ // prepare FBOs containing main scene
+ // for further blitting and rendering immediate presentations on top
+ if (myGlContext->core20fwd != NULL)
+ {
+ myResultFBO->Init (myGlContext, aSizeX, aSizeY);
+ }
+ }
+
+ if (myResultFBO->IsValid())
+ {
+ myResultFBO->SetupViewport (myGlContext);
}
}
- if (myResultFBO->IsValid())
+ else
{
- myResultFBO->SetupViewport (aGlCtx);
+ myResultFBO->Release (myGlContext.operator->());
}
- const Standard_Boolean isImmediate = myView->HasImmediateStructures()
- || myResultFBO->IsValid();
-
myToRedrawGL = Standard_True;
if (theCView.RenderParams.Method == Graphic3d_RM_RAYTRACING
&& myComputeInitStatus != OpenGl_RT_FAIL)
if (myOpenGlFBO->GetVPSizeX() != aSizeX
|| myOpenGlFBO->GetVPSizeY() != aSizeY)
{
- myOpenGlFBO->Init (aGlCtx, aSizeX, aSizeY);
+ myOpenGlFBO->Init (myGlContext, aSizeX, aSizeY);
}
// OverLayer and UnderLayer shouldn't be drawn by OpenGL.
Aspect_CLayer2d anEmptyCLayer;
anEmptyCLayer.ptrLayer = NULL;
- myOpenGlFBO->BindBuffer (aGlCtx);
- redraw1 (theCView, anEmptyCLayer, anEmptyCLayer, 0);
- myOpenGlFBO->UnbindBuffer (aGlCtx);
+ myOpenGlFBO->BindBuffer (myGlContext);
+ redraw1 (theCView, anEmptyCLayer, anEmptyCLayer);
+ myOpenGlFBO->UnbindBuffer (myGlContext);
- Raytrace (theCView, aSizeX, aSizeY, isImmediate ? 0 : toSwap,
+ Raytrace (theCView, aSizeX, aSizeY,
theCOverLayer, theCUnderLayer,
myResultFBO->IsValid() ? myResultFBO.operator->() : aFrameBuffer);
-
- if (isImmediate)
+ myBackBufferRestored = Standard_True;
+ myIsImmediateDrawn = Standard_False;
+ if (!redrawImmediate (theCView, theCOverLayer, theCUnderLayer, aFrameBuffer))
{
- RedrawImmediate (theCView, theCUnderLayer, theCOverLayer, Standard_True, aFrameBuffer);
+ toSwap = false;
}
SetRenderFilter (aRenderFilter);
// draw entire frame using normal OpenGL pipeline
if (myResultFBO->IsValid())
{
- myResultFBO->BindBuffer (aGlCtx);
+ myResultFBO->BindBuffer (myGlContext);
}
else if (aFrameBuffer != NULL)
{
- aFrameBuffer->BindBuffer (aGlCtx);
+ aFrameBuffer->BindBuffer (myGlContext);
}
- redraw1 (theCView, theCUnderLayer, theCOverLayer, isImmediate ? 0 : toSwap);
- if (isImmediate)
+ redraw1 (theCView, theCUnderLayer, theCOverLayer);
+ myBackBufferRestored = Standard_True;
+ myIsImmediateDrawn = Standard_False;
+ if (!redrawImmediate (theCView, theCOverLayer, theCUnderLayer, aFrameBuffer))
{
- RedrawImmediate (theCView, theCUnderLayer, theCOverLayer, Standard_True, aFrameBuffer);
+ toSwap = false;
}
theCView.WasRedrawnGL = Standard_True;
if (aFrameBuffer != NULL)
{
- aFrameBuffer->UnbindBuffer (aGlCtx);
+ aFrameBuffer->UnbindBuffer (myGlContext);
// move back original viewport
- aGlCtx->core11fwd->glViewport (0, 0, myWidth, myHeight);
+ myGlContext->core11fwd->glViewport (0, 0, myWidth, myHeight);
}
#if defined(_WIN32) && defined(HAVE_VIDEOCAPTURE)
}
#endif
+ // Swap the buffers
+ if (toSwap)
+ {
+ GetGlContext()->SwapBuffers();
+ if (!myResultFBO->IsValid())
+ {
+ myBackBufferRestored = Standard_False;
+ }
+ }
+ else
+ {
+ myGlContext->core11fwd->glFlush();
+ }
+
// reset render mode state
- aGlCtx->FetchState();
+ myGlContext->FetchState();
}
// =======================================================================
// =======================================================================
void OpenGl_Workspace::redraw1 (const Graphic3d_CView& theCView,
const Aspect_CLayer2d& theCUnderLayer,
- const Aspect_CLayer2d& theCOverLayer,
- const int theToSwap)
+ const Aspect_CLayer2d& theCOverLayer)
{
if (myView.IsNull())
{
Handle(OpenGl_Workspace) aWS (this);
myView->Render (myPrintContext, aWS, theCView, theCUnderLayer, theCOverLayer, Standard_False);
-
- // swap the buffers
- if (theToSwap)
- {
- GetGlContext()->SwapBuffers();
- myBackBufferRestored = Standard_False;
- myIsImmediateDrawn = Standard_False;
- }
- else
- {
- glFlush(); //
- myBackBufferRestored = Standard_True;//
- myIsImmediateDrawn = Standard_False;//
- }
}
// =======================================================================
// =======================================================================
void OpenGl_Workspace::RedrawImmediate (const Graphic3d_CView& theCView,
const Aspect_CLayer2d& theCUnderLayer,
- const Aspect_CLayer2d& theCOverLayer,
- const Standard_Boolean theToForce,
- OpenGl_FrameBuffer* theTargetFBO)
+ const Aspect_CLayer2d& theCOverLayer)
{
- if (!Activate())
+ if (!myTransientDrawToFront
+ || !myBackBufferRestored
+ || (myGlContext->caps->buffersNoSwap && !myResultFBO->IsValid()))
{
+ Redraw (theCView, theCUnderLayer, theCOverLayer);
return;
}
-
- GLboolean isDoubleBuffer = GL_FALSE;
-#if !defined(GL_ES_VERSION_2_0)
- glGetBooleanv (GL_DOUBLEBUFFER, &isDoubleBuffer);
-#endif
- if (!myView->HasImmediateStructures()
- && !myResultFBO->IsValid())
+ else if (!Activate())
{
- if (theToForce
- || !myIsImmediateDrawn)
- {
- myIsImmediateDrawn = Standard_False;
- return;
- }
-
- if (myBackBufferRestored
- && isDoubleBuffer)
- {
- copyBackToFront();
- glFlush();
- }
- else
- {
- Redraw (theCView, theCUnderLayer, theCOverLayer);
- }
return;
}
- if (myResultFBO->IsValid()
- && myGlContext->IsRender())
+ if (redrawImmediate (theCView, theCUnderLayer, theCOverLayer, NULL, Standard_True))
{
- if (!myBackBufferRestored)
- {
- Redraw (theCView, theCUnderLayer, theCOverLayer);
- return;
- }
+ myGlContext->SwapBuffers();
+ }
+ else
+ {
+ myGlContext->core11fwd->glFlush();
+ MakeBackBufCurrent();
+ }
+}
+// =======================================================================
+// function : redrawImmediate
+// purpose :
+// =======================================================================
+bool OpenGl_Workspace::redrawImmediate (const Graphic3d_CView& theCView,
+ const Aspect_CLayer2d& theCUnderLayer,
+ const Aspect_CLayer2d& theCOverLayer,
+ OpenGl_FrameBuffer* theTargetFBO,
+ const Standard_Boolean theIsPartialUpdate)
+{
+ GLboolean toCopyBackToFront = GL_FALSE;
+ if (!myTransientDrawToFront)
+ {
+ myBackBufferRestored = Standard_False;
+ }
+ else if (myResultFBO->IsValid()
+ && myGlContext->IsRender())
+ {
// clear destination before blitting
if (theTargetFBO != NULL)
{
myResultFBO->DepthStencilTexture()->Unbind (myGlContext, GL_TEXTURE0 + 1);
myResultFBO->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;
+ myResultFBO->Release (myGlContext.operator->());
+ return true;
+ }
}
}
- else if (isDoubleBuffer && myTransientDrawToFront)
+ else if (theTargetFBO == NULL)
{
- if (!myBackBufferRestored)
+ #if !defined(GL_ES_VERSION_2_0)
+ myGlContext->core11fwd->glGetBooleanv (GL_DOUBLEBUFFER, &toCopyBackToFront);
+ #endif
+ if (toCopyBackToFront)
{
- Redraw (theCView, theCUnderLayer, theCOverLayer);
- return;
+ if (!myView->HasImmediateStructures()
+ && !theIsPartialUpdate)
+ {
+ // prefer Swap Buffers within Redraw in compatibility mode (without FBO)
+ return true;
+ }
+ copyBackToFront();
+ MakeFrontBufCurrent();
+ }
+ else
+ {
+ myBackBufferRestored = Standard_False;
}
- copyBackToFront();
- MakeFrontBufCurrent();
}
else
{
aStructure->Render (aWS);
}
- if (myResultFBO->IsValid())
- {
- if (theTargetFBO == NULL
- && myGlContext->IsRender()
- && !myGlContext->caps->buffersNoSwap)
- {
- myGlContext->SwapBuffers();
- }
- }
- else if (isDoubleBuffer && myTransientDrawToFront)
+ if (toCopyBackToFront)
{
- glFlush();
MakeBackBufCurrent();
+ return false;
}
+ return true;
}
Standard_Boolean SetImmediateModeDrawToFront (const Standard_Boolean theDrawToFrontBuffer);
void RedrawImmediate (const Graphic3d_CView& theCView,
const Aspect_CLayer2d& theCUnderLayer,
- const Aspect_CLayer2d& theCOverLayer,
- const Standard_Boolean theToForce = Standard_False,
- OpenGl_FrameBuffer* theTargetFBO = NULL);
+ const Aspect_CLayer2d& theCOverLayer);
void Invalidate (const Graphic3d_CView& /*theCView*/)
{
void redraw1 (const Graphic3d_CView& theCView,
const Aspect_CLayer2d& theCUnderLayer,
- const Aspect_CLayer2d& theCOverLayer,
- const int theToSwap);
+ const Aspect_CLayer2d& theCOverLayer);
+
+ //! Blit snapshot containing main scene (myResultFBO or BackBuffer)
+ //! into presentation buffer (myResultFBO->offscreen FBO or myResultFBO->BackBuffer or BackBuffer->FrontBuffer),
+ //! and redraw immediate structures on top.
+ //!
+ //! When scene caching is disabled (myTransientDrawToFront, no double buffer in window, etc.),
+ //! the first step (blitting) will be skipped.
+ //!
+ //! @return false if immediate structures has been rendered directly into FrontBuffer and Buffer Swap should not be called.
+ bool redrawImmediate (const Graphic3d_CView& theCView,
+ const Aspect_CLayer2d& theCUnderLayer,
+ const Aspect_CLayer2d& theCOverLayer,
+ OpenGl_FrameBuffer* theTargetFBO,
+ const Standard_Boolean theIsPartialUpdate = Standard_False);
void updateMaterial (const int theFlag);
Standard_Boolean Raytrace (const Graphic3d_CView& theCView,
const Standard_Integer theSizeX,
const Standard_Integer theSizeY,
- const Standard_Boolean theToSwap,
const Aspect_CLayer2d& theCOverLayer,
const Aspect_CLayer2d& theCUnderLayer,
OpenGl_FrameBuffer* theFrameBuffer);
//! Framebuffer stores cached main presentation of the view (without presentation of immediate layers).
Handle(OpenGl_FrameBuffer) myResultFBO;
+ //! Special flag which is invalidated when myResultFBO can not be blitted for some reason (e.g. driver bugs).
+ Standard_Boolean myHasFboBlit;
//! Vertices for full-screen quad rendering.
OpenGl_VertexBuffer myFullScreenQuad;