0025091: Visualization - use FBO for layer with immediate objects
authorkgv <kgv@opencascade.com>
Thu, 29 Jan 2015 13:01:07 +0000 (16:01 +0300)
committerbugmaster <bugmaster@opencascade.com>
Thu, 19 Feb 2015 13:13:15 +0000 (16:13 +0300)
16 files changed:
src/Graphic3d/Graphic3d_ShaderProgram.hxx
src/OpenGl/OpenGl_ArbFBO.hxx
src/OpenGl/OpenGl_Context.cxx
src/OpenGl/OpenGl_Context.hxx
src/OpenGl/OpenGl_FrameBuffer.cxx
src/OpenGl/OpenGl_FrameBuffer.hxx
src/OpenGl/OpenGl_GlFunctions.hxx
src/OpenGl/OpenGl_ShaderManager.cxx
src/OpenGl/OpenGl_ShaderManager.hxx
src/OpenGl/OpenGl_ShaderProgram.cxx
src/OpenGl/OpenGl_View_2.cxx
src/OpenGl/OpenGl_Workspace.cxx
src/OpenGl/OpenGl_Workspace.hxx
src/Shaders/Declarations.glsl
tests/3rdparty/end
tests/mesh/end

index 112d1a0..44fc43e 100755 (executable)
@@ -61,6 +61,18 @@ public:
   //! Returns unique ID used to manage resource in graphic driver.
   const TCollection_AsciiString& GetId() const { return myID; }
 
+  //! Returns GLSL header (version code and extensions).
+  const TCollection_AsciiString& Header() const { return myHeader; }
+
+  //! Setup GLSL header containing language version code and used extensions.
+  //! Will be prepended to the very beginning of the source code.
+  //! Example:
+  //! @code
+  //!   #version 300 es
+  //!   #extension GL_ARB_bindless_texture : require
+  //! @endcode
+  void SetHeader (const TCollection_AsciiString& theHeader) { myHeader = theHeader; }
+
   //! Attaches shader object to the program object.
   Standard_EXPORT Standard_Boolean AttachShader (const Handle(Graphic3d_ShaderObject)& theShader);
 
@@ -96,6 +108,7 @@ private:
   TCollection_AsciiString      myID;            //!< The unique identifier of program object.
   Graphic3d_ShaderObjectList   myShaderObjects; //!< the list of attached shader objects.
   Graphic3d_ShaderVariableList myVariables;     //!< the list of custom uniform variables.
+  TCollection_AsciiString      myHeader;        //!< GLSL header with version code and used extensions
 
 };
 
index 8e67351..bfac84a 100644 (file)
@@ -48,4 +48,13 @@ struct OpenGl_ArbFBO : protected OpenGl_GlFunctions
 
 };
 
+//! FBO blit is available in OpenGL 3.0+.
+//! Moved out from OpenGl_ArbFBO since it is unavailable in OpenGL ES 2.0.
+struct OpenGl_ArbFBOBlit : protected OpenGl_GlFunctions
+{
+
+  using OpenGl_GlFunctions::glBlitFramebuffer;
+
+};
+
 #endif // _OpenGl_ArbFBO_H__
index 247c189..3f47492 100644 (file)
@@ -95,6 +95,7 @@ OpenGl_Context::OpenGl_Context (const Handle(OpenGl_Caps)& theCaps)
   arbIns (NULL),
   arbDbg (NULL),
   arbFBO (NULL),
+  arbFBOBlit (NULL),
   extGS  (NULL),
   extBgra(Standard_False),
   extAnis(Standard_False),
@@ -877,6 +878,7 @@ void OpenGl_Context::init()
   arbIns     = NULL;
   arbDbg     = NULL;
   arbFBO     = NULL;
+  arbFBOBlit = NULL;
   extGS      = NULL;
 
 #if defined(GL_ES_VERSION_2_0)
@@ -902,7 +904,12 @@ void OpenGl_Context::init()
     core20    = (OpenGl_GlCore20*    )(&(*myFuncs));
     core20fwd = (OpenGl_GlCore20Fwd* )(&(*myFuncs));
     core15fwd = (OpenGl_GlCore15Fwd* )(&(*myFuncs));
-    arbFBO    = (OpenGl_ArbFBO* )(&(*myFuncs));
+    arbFBO    = (OpenGl_ArbFBO*      )(&(*myFuncs));
+  }
+  if (IsGlGreaterEqual (3, 0)
+   && FindProc ("glBlitFramebuffer", myFuncs->glBlitFramebuffer))
+  {
+    arbFBOBlit = (OpenGl_ArbFBOBlit* )(&(*myFuncs));
   }
 
   hasHighp = CheckExtension ("OES_fragment_precision_high");
@@ -1762,7 +1769,8 @@ void OpenGl_Context::init()
   // initialize FBO extension (ARB)
   if (hasFBO)
   {
-    arbFBO = (OpenGl_ArbFBO* )(&(*myFuncs));
+    arbFBO     = (OpenGl_ArbFBO*     )(&(*myFuncs));
+    arbFBOBlit = (OpenGl_ArbFBOBlit* )(&(*myFuncs));
     extPDS = Standard_True; // extension for EXT, but part of ARB
   }
 
index 1510e5b..187a918 100644 (file)
@@ -45,6 +45,7 @@ struct OpenGl_ArbTBO;
 struct OpenGl_ArbIns;
 struct OpenGl_ArbDbg;
 struct OpenGl_ArbFBO;
+struct OpenGl_ArbFBOBlit;
 struct OpenGl_ExtGS;
 struct OpenGl_ArbTexBindless;
 
@@ -522,6 +523,7 @@ public: //! @name extensions
   OpenGl_ArbIns*         arbIns;         //!< GL_ARB_draw_instanced
   OpenGl_ArbDbg*         arbDbg;         //!< GL_ARB_debug_output
   OpenGl_ArbFBO*         arbFBO;         //!< GL_ARB_framebuffer_object
+  OpenGl_ArbFBOBlit*     arbFBOBlit;     //!< glBlitFramebuffer function, moved out from OpenGl_ArbFBO structure for compatibility with OpenGL ES 2.0
   OpenGl_ExtGS*          extGS;          //!< GL_EXT_geometry_shader4
   Standard_Boolean       extBgra;        //!< GL_EXT_bgra or GL_EXT_texture_format_BGRA8888 on OpenGL ES
   Standard_Boolean       extAnis;        //!< GL_EXT_texture_filter_anisotropic
index 4d45461..6304afd 100644 (file)
 IMPLEMENT_STANDARD_HANDLE (OpenGl_FrameBuffer, OpenGl_Resource)
 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_FrameBuffer, OpenGl_Resource)
 
-static inline bool isOddNumber (const GLsizei theNumber)
-{
-  return theNumber & 0x01;
-}
-
-static inline GLsizei getEvenNumber (const GLsizei theNumber)
-{
-  return isOddNumber (theNumber) ? (theNumber + 1) : theNumber;
-}
-
-//! Notice - 0 is not power of two here
-static inline bool isPowerOfTwo (const GLsizei theNumber)
-{
-  return !(theNumber & (theNumber - 1));
-}
-
 // =======================================================================
 // function : OpenGl_FrameBuffer
 // purpose  :
@@ -177,6 +161,24 @@ void OpenGl_FrameBuffer::BindBuffer (const Handle(OpenGl_Context)& theGlCtx)
 }
 
 // =======================================================================
+// function : BindDrawBuffer
+// purpose  :
+// =======================================================================
+void OpenGl_FrameBuffer::BindDrawBuffer (const Handle(OpenGl_Context)& theGlCtx)
+{
+  theGlCtx->arbFBO->glBindFramebuffer (GL_DRAW_FRAMEBUFFER, myGlFBufferId);
+}
+
+// =======================================================================
+// function : BindReadBuffer
+// purpose  :
+// =======================================================================
+void OpenGl_FrameBuffer::BindReadBuffer (const Handle(OpenGl_Context)& theGlCtx)
+{
+  theGlCtx->arbFBO->glBindFramebuffer (GL_READ_FRAMEBUFFER, myGlFBufferId);
+}
+
+// =======================================================================
 // function : UnbindBuffer
 // purpose  :
 // =======================================================================
index 3a4eeb4..b091e50 100644 (file)
@@ -92,9 +92,15 @@ public:
   Standard_EXPORT void ChangeViewport (const GLsizei theVPSizeX,
                                        const GLsizei theVPSizeY);
 
-  //! Bind frame buffer (to render into the texture).
+  //! Bind frame buffer for drawing and reading (to render into the texture).
   Standard_EXPORT virtual void BindBuffer (const Handle(OpenGl_Context)& theGlCtx);
 
+  //! Bind frame buffer for drawing GL_DRAW_FRAMEBUFFER (to render into the texture).
+  Standard_EXPORT virtual void BindDrawBuffer (const Handle(OpenGl_Context)& theGlCtx);
+
+  //! Bind frame buffer for reading GL_READ_FRAMEBUFFER
+  Standard_EXPORT virtual void BindReadBuffer (const Handle(OpenGl_Context)& theGlCtx);
+
   //! Unbind frame buffer.
   Standard_EXPORT virtual void UnbindBuffer (const Handle(OpenGl_Context)& theGlCtx);
 
index 79d2b2f..1cc3f03 100644 (file)
@@ -95,6 +95,9 @@
   #define GL_UNSIGNED_INT_24_8              0x84FA
   #define GL_DEPTH24_STENCIL8               0x88F0
 
+  #define GL_READ_FRAMEBUFFER               0x8CA8
+  #define GL_DRAW_FRAMEBUFFER               0x8CA9
+
   // GL_EXT_texture_filter_anisotropic
   #define GL_TEXTURE_MAX_ANISOTROPY_EXT     0x84FE
   #define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
@@ -688,6 +691,11 @@ public: //! @name OpenGL ES 2.0
     ::glVertexAttribPointer (index, size, type, normalized, stride, pointer);
   }
 
+public: //! @name OpenGL ES 3.0
+
+  typedef void (*glBlitFramebuffer_t)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+  glBlitFramebuffer_t glBlitFramebuffer;
+
 #else // OpenGL ES vs. desktop
 
 public: //! @name OpenGL 1.2
index e00d2e4..b63be61 100644 (file)
@@ -234,6 +234,7 @@ void OpenGl_ShaderManager::clear()
   myFlatPrograms = OpenGl_SetOfShaderPrograms();
   myMapOfLightPrograms.Clear();
   myFontProgram.Nullify();
+  myBlitProgram.Nullify();
   switchLightPrograms();
 }
 
@@ -1031,6 +1032,69 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFont()
 }
 
 // =======================================================================
+// function : prepareStdProgramFboBlit
+// purpose  :
+// =======================================================================
+Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFboBlit()
+{
+  Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
+  TCollection_AsciiString aSrcVert =
+      EOL"THE_SHADER_OUT vec2 TexCoord;"
+      EOL"void main()"
+      EOL"{"
+      EOL"  TexCoord    = occVertex.zw;"
+      EOL"  gl_Position = vec4(occVertex.x, occVertex.y, 0.0, 1.0);"
+      EOL"}";
+
+  TCollection_AsciiString aSrcFrag =
+      EOL"uniform sampler2D uColorSampler;"
+      EOL"uniform sampler2D uDepthSampler;"
+      EOL
+      EOL"THE_SHADER_IN vec2 TexCoord;"
+      EOL
+      EOL"void main()"
+      EOL"{"
+      EOL"  gl_FragDepth = occTexture2D (uDepthSampler, TexCoord).r;"
+      EOL"  occFragColor = occTexture2D (uColorSampler, TexCoord);"
+      EOL"}";
+
+#if defined(GL_ES_VERSION_2_0)
+  if (myContext->IsGlGreaterEqual (3, 0))
+  {
+    aProgramSrc->SetHeader ("#version 300 es");
+  }
+  else
+  {
+    // there is no way to draw into depth buffer
+    aSrcFrag =
+      EOL"uniform sampler2D uColorSampler;"
+      EOL
+      EOL"THE_SHADER_IN vec2 TexCoord;"
+      EOL
+      EOL"void main()"
+      EOL"{"
+      EOL"  occFragColor = occTexture2D (uColorSampler, TexCoord);"
+      EOL"}";
+  }
+#endif
+
+  aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX,   aSrcVert));
+  aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
+  TCollection_AsciiString aKey;
+  if (!Create (aProgramSrc, aKey, myBlitProgram))
+  {
+    myBlitProgram = new OpenGl_ShaderProgram(); // just mark as invalid
+    return Standard_False;
+  }
+
+  myContext->BindProgram (myBlitProgram);
+  myBlitProgram->SetSampler (myContext, "uColorSampler", 0);
+  myBlitProgram->SetSampler (myContext, "uDepthSampler", 1);
+  myContext->BindProgram (NULL);
+  return Standard_True;
+}
+
+// =======================================================================
 // function : prepareStdProgramFlat
 // purpose  :
 // =======================================================================
index d4ab02c..adab135 100644 (file)
@@ -145,6 +145,17 @@ public:
     return bindProgramWithState (myFontProgram, theAspect);
   }
 
+  //! Bind program for FBO blit operation.
+  Standard_Boolean BindFboBlitProgram()
+  {
+    if (myBlitProgram.IsNull())
+    {
+      prepareStdProgramFboBlit();
+    }
+    return !myBlitProgram.IsNull()
+         && myContext->BindProgram (myBlitProgram);
+  }
+
 public:
 
   //! Returns current state of OCCT light sources.
@@ -292,6 +303,9 @@ protected:
   //! Prepare standard GLSL program for textured font.
   Standard_EXPORT Standard_Boolean prepareStdProgramFont();
 
+  //! Prepare standard GLSL program for FBO blit operation.
+  Standard_EXPORT Standard_Boolean prepareStdProgramFboBlit();
+
   //! Prepare standard GLSL program without lighting.
   Standard_EXPORT Standard_Boolean prepareStdProgramFlat (Handle(OpenGl_ShaderProgram)& theProgram,
                                                           const Standard_Integer        theBits);
@@ -331,6 +345,7 @@ protected:
   Handle(OpenGl_SetOfShaderPrograms) myLightPrograms;      //!< pointer to active lighting programs matrix
   OpenGl_SetOfShaderPrograms         myFlatPrograms;       //!< programs matrix without  lighting
   Handle(OpenGl_ShaderProgram)       myFontProgram;        //!< standard program for textured text
+  Handle(OpenGl_ShaderProgram)       myBlitProgram;        //!< standard program for FBO blit emulation
   OpenGl_MapOfShaderPrograms         myMapOfLightPrograms; //!< map of lighting programs depending on shading model and lights configuration
 
   OpenGl_Context*                    myContext;            //!< OpenGL context
index a539ac7..d88dc09 100755 (executable)
@@ -155,6 +155,10 @@ Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)&
     return Standard_False;
   }
 
+  TCollection_AsciiString aHeader = !myProxy.IsNull() && !myProxy->Header().IsEmpty()
+                                  ? (myProxy->Header() + "\n")
+                                  : TCollection_AsciiString();
+
   TCollection_AsciiString aDeclarations;
   aDeclFile.Open (OSD_ReadOnly, OSD_Protection());
   aDeclFile.Read (aDeclarations, (int)aDeclFile.Size());
@@ -216,7 +220,7 @@ Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)&
     {
       case Graphic3d_TOS_VERTEX:
       {
-        aSource = TCollection_AsciiString ("#define VERTEX_SHADER\n") + aSource;
+        aSource = aHeader + TCollection_AsciiString ("#define VERTEX_SHADER\n") + aSource;
         break;
       }
       case Graphic3d_TOS_FRAGMENT:
@@ -225,7 +229,7 @@ Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)&
         TCollection_AsciiString aPrefix (theCtx->hasHighp
                                        ? "precision highp float;\n"
                                        : "precision mediump float;\n");
-        aSource = aPrefix + aSource;
+        aSource = aHeader + aPrefix + aSource;
       #endif
         break;
       }
@@ -644,7 +648,7 @@ Standard_Boolean OpenGl_ShaderProgram::SetAttributeName (const Handle(OpenGl_Con
   theCtx->core20fwd->glBindAttribLocation (myProgramID, theIndex, theName);
   return Standard_True;
 }
-  
+
 // =======================================================================
 // function : SetAttribute
 // purpose  :
index 7980367..9fe7f64 100644 (file)
@@ -306,8 +306,8 @@ void OpenGl_View::Render (const Handle(OpenGl_PrinterContext)& thePrintContext,
     myBVHSelector.SetViewVolume (myCamera);
   }
 
-  const Handle(OpenGl_ShaderManager) aManager   = aContext->ShaderManager();
-  const Standard_Boolean             isSameView = aManager->IsSameView (this); // force camera state update when needed
+  const Handle(OpenGl_ShaderManager)& aManager   = aContext->ShaderManager();
+  const Standard_Boolean              isSameView = aManager->IsSameView (this); // force camera state update when needed
   if (StateInfo (myCurrLightSourceState, aManager->LightSourceState().Index()) != myLastLightSourceState)
   {
     aManager->UpdateLightSourceStateTo (&myLights);
index c0e1d1a..80e6ff1 100644 (file)
@@ -14,6 +14,7 @@
 // commercial license or contractual agreement.
 
 #include <OpenGl_GlCore15.hxx>
+#include <OpenGl_ArbFBO.hxx>
 
 #include <InterfaceGraphic.hxx>
 
@@ -26,6 +27,7 @@
 #include <OpenGl_FrameBuffer.hxx>
 #include <OpenGl_Structure.hxx>
 #include <OpenGl_Sampler.hxx>
+#include <OpenGl_ShaderManager.hxx>
 #include <OpenGl_Texture.hxx>
 #include <OpenGl_Utils.hxx>
 #include <OpenGl_View.hxx>
@@ -179,6 +181,7 @@ OpenGl_Workspace::OpenGl_Workspace (const Handle(OpenGl_GraphicDriver)& theDrive
   PolygonOffset_applied (THE_DEFAULT_POFFSET)
 {
   myGlContext->core11fwd->glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
+  myResultFBO = new OpenGl_FrameBuffer();
 
   if (!myGlContext->GetResource ("OpenGl_LineAttributes", myLineAttribs))
   {
@@ -234,6 +237,16 @@ OpenGl_Workspace::~OpenGl_Workspace()
     myGlContext->ReleaseResource ("OpenGl_LineAttributes", Standard_True);
   }
 
+  if (!myResultFBO.IsNull())
+  {
+    myResultFBO->Release (myGlContext.operator->());
+    myResultFBO.Nullify();
+  }
+  if (myFullScreenQuad.IsValid())
+  {
+    myFullScreenQuad.Release (myGlContext.operator->());
+  }
+
   ReleaseRaytraceResources();
 }
 
@@ -655,6 +668,22 @@ void OpenGl_Workspace::Redraw (const Graphic3d_CView& theCView,
     aGlCtx->core11fwd->glViewport (0, 0, myWidth, myHeight);
   }
 
+  Standard_Integer aSizeX = aFrameBuffer != NULL ? aFrameBuffer->GetVPSizeX() : myWidth;
+  Standard_Integer aSizeY = aFrameBuffer != NULL ? aFrameBuffer->GetVPSizeY() : myHeight;
+
+  if (myResultFBO->GetVPSizeX() != aSizeX
+   || myResultFBO->GetVPSizeY() != aSizeY)
+  {
+    myResultFBO->Init (aGlCtx, aSizeX, aSizeY);
+  }
+  if (myResultFBO->IsValid())
+  {
+    myResultFBO->SetupViewport (aGlCtx);
+  }
+
+  const Standard_Boolean isImmediate = myView->HasImmediateStructures()
+                                    || myResultFBO->IsValid();
+
   myToRedrawGL = Standard_True;
   if (theCView.RenderParams.Method == Graphic3d_RM_RAYTRACING
    && myComputeInitStatus != OpenGl_RT_FAIL)
@@ -668,9 +697,6 @@ void OpenGl_Workspace::Redraw (const Graphic3d_CView& theCView,
       myRaytraceFilter->SetPrevRenderFilter (aRenderFilter);
       SetRenderFilter (myRaytraceFilter);
 
-      Standard_Integer aSizeX = aFrameBuffer != NULL ? aFrameBuffer->GetVPSizeX() : myWidth;
-      Standard_Integer aSizeY = aFrameBuffer != NULL ? aFrameBuffer->GetVPSizeY() : myHeight;
-
       if (myOpenGlFBO.IsNull())
       {
         myOpenGlFBO = new OpenGl_FrameBuffer();
@@ -690,13 +716,13 @@ void OpenGl_Workspace::Redraw (const Graphic3d_CView& theCView,
       redraw1 (theCView, anEmptyCLayer, anEmptyCLayer, 0);
       myOpenGlFBO->UnbindBuffer (aGlCtx);
 
-      const Standard_Boolean isImmediate = myView->HasImmediateStructures();
       Raytrace (theCView, aSizeX, aSizeY, isImmediate ? 0 : toSwap,
-                theCOverLayer, theCUnderLayer, aFrameBuffer);
+                theCOverLayer, theCUnderLayer,
+                myResultFBO->IsValid() ? myResultFBO.operator->() : aFrameBuffer);
 
       if (isImmediate)
       {
-        RedrawImmediate (theCView, theCUnderLayer, theCOverLayer, Standard_True);
+        RedrawImmediate (theCView, theCUnderLayer, theCOverLayer, Standard_True, aFrameBuffer);
       }
 
       SetRenderFilter (aRenderFilter);
@@ -708,16 +734,19 @@ void OpenGl_Workspace::Redraw (const Graphic3d_CView& theCView,
   if (myToRedrawGL)
   {
     // draw entire frame using normal OpenGL pipeline
-    if (aFrameBuffer != NULL)
+    if (myResultFBO->IsValid())
+    {
+      myResultFBO->BindBuffer (aGlCtx);
+    }
+    else if (aFrameBuffer != NULL)
     {
       aFrameBuffer->BindBuffer (aGlCtx);
     }
 
-    const Standard_Boolean isImmediate = myView->HasImmediateStructures();
     redraw1 (theCView, theCUnderLayer, theCOverLayer, isImmediate ? 0 : toSwap);
     if (isImmediate)
     {
-      RedrawImmediate (theCView, theCUnderLayer, theCOverLayer, Standard_True);
+      RedrawImmediate (theCView, theCUnderLayer, theCOverLayer, Standard_True, aFrameBuffer);
     }
 
     theCView.WasRedrawnGL = Standard_True;
@@ -902,7 +931,8 @@ void OpenGl_Workspace::DisplayCallback (const Graphic3d_CView& theCView,
 void OpenGl_Workspace::RedrawImmediate (const Graphic3d_CView& theCView,
                                         const Aspect_CLayer2d& theCUnderLayer,
                                         const Aspect_CLayer2d& theCOverLayer,
-                                        const Standard_Boolean theToForce)
+                                        const Standard_Boolean theToForce,
+                                        OpenGl_FrameBuffer*    theTargetFBO)
 {
   if (!Activate())
   {
@@ -913,7 +943,8 @@ void OpenGl_Workspace::RedrawImmediate (const Graphic3d_CView& theCView,
 #if !defined(GL_ES_VERSION_2_0)
   glGetBooleanv (GL_DOUBLEBUFFER, &isDoubleBuffer);
 #endif
-  if (!myView->HasImmediateStructures())
+  if (!myView->HasImmediateStructures()
+   && !myResultFBO->IsValid())
   {
     if (theToForce
      || !myIsImmediateDrawn)
@@ -935,7 +966,94 @@ void OpenGl_Workspace::RedrawImmediate (const Graphic3d_CView& theCView,
     return;
   }
 
-  if (isDoubleBuffer && myTransientDrawToFront)
+  if (myResultFBO->IsValid()
+   && myGlContext->IsRender())
+  {
+    if (!myBackBufferRestored)
+    {
+      Redraw (theCView, theCUnderLayer, theCOverLayer);
+      return;
+    }
+
+    // clear destination before blitting
+    if (theTargetFBO != NULL)
+    {
+      theTargetFBO->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)
+    {
+      myResultFBO->BindReadBuffer (myGlContext);
+      if (theTargetFBO != NULL)
+      {
+        theTargetFBO->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, myResultFBO->GetVPSizeX(), myResultFBO->GetVPSizeY(),
+                                                  0, 0, myResultFBO->GetVPSizeX(), myResultFBO->GetVPSizeY(),
+                                                  GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST);
+
+      if (theTargetFBO != NULL)
+      {
+        theTargetFBO->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();
+      if (!myFullScreenQuad.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)
+        };
+        myFullScreenQuad.Init (myGlContext, 4, 4, aQuad[0].GetData());
+      }
+
+      const Handle(OpenGl_ShaderManager)& aManager = myGlContext->ShaderManager();
+      if (myFullScreenQuad.IsValid()
+       && aManager->BindFboBlitProgram())
+      {
+        myResultFBO->ColorTexture()       ->Bind   (myGlContext, GL_TEXTURE0 + 0);
+        myResultFBO->DepthStencilTexture()->Bind   (myGlContext, GL_TEXTURE0 + 1);
+        myFullScreenQuad.BindVertexAttrib (myGlContext, 0);
+
+        myGlContext->core20fwd->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
+
+        myFullScreenQuad.UnbindVertexAttrib (myGlContext, 0);
+        myResultFBO->DepthStencilTexture()->Unbind (myGlContext, GL_TEXTURE0 + 1);
+        myResultFBO->ColorTexture()       ->Unbind (myGlContext, GL_TEXTURE0 + 0);
+      }
+    }
+  }
+  else if (isDoubleBuffer && myTransientDrawToFront)
   {
     if (!myBackBufferRestored)
     {
@@ -994,7 +1112,16 @@ void OpenGl_Workspace::RedrawImmediate (const Graphic3d_CView& theCView,
     aStructure->Render (aWS);
   }
 
-  if (isDoubleBuffer && myTransientDrawToFront)
+  if (myResultFBO->IsValid())
+  {
+    if (theTargetFBO == NULL
+    &&  myGlContext->IsRender()
+    && !myGlContext->caps->buffersNoSwap)
+    {
+      myGlContext->SwapBuffers();
+    }
+  }
+  else if (isDoubleBuffer && myTransientDrawToFront)
   {
     glFlush();
     MakeBackBufCurrent();
index 5450975..2c8523f 100644 (file)
@@ -152,7 +152,8 @@ public:
   void RedrawImmediate (const Graphic3d_CView& theCView,
                         const Aspect_CLayer2d& theCUnderLayer,
                         const Aspect_CLayer2d& theCOverLayer,
-                        const Standard_Boolean theToForce = Standard_False);
+                        const Standard_Boolean theToForce = Standard_False,
+                        OpenGl_FrameBuffer*    theTargetFBO = NULL);
 
   void Invalidate (const Graphic3d_CView& /*theCView*/)
   {
@@ -626,6 +627,12 @@ protected: //! @name fields related to ray-tracing
   //! Framebuffer (FBO) for pre-raytrace rendering by OpenGL.
   Handle(OpenGl_FrameBuffer) myOpenGlFBO;
 
+  //! Framebuffer stores cached main presentation of the view (without presentation of immediate layers).
+  Handle(OpenGl_FrameBuffer) myResultFBO;
+
+  //! Vertices for full-screen quad rendering.
+  OpenGl_VertexBuffer        myFullScreenQuad;
+
   //! State of OpenGL view.
   Standard_Size myViewModificationStatus;
   //! State of OpenGL layer list.
index 15f8837..8b6ec4b 100644 (file)
 #define THE_MAX_LIGHTS      8
 #define THE_MAX_CLIP_PLANES 8
 
+// compatibility macros
+#if (__VERSION__ >= 130)
+  #define THE_ATTRIBUTE  in
+  #define THE_SHADER_IN  in
+  #define THE_SHADER_OUT out
+  #define THE_OUT        out
+  #define occTexture2D   texture
+#else
+  #define THE_ATTRIBUTE  attribute
+  #define THE_SHADER_IN  varying
+  #define THE_SHADER_OUT varying
+  #define THE_OUT
+  #define occTexture2D   texture2D
+#endif
+
 // Vertex attributes
 #ifdef VERTEX_SHADER
-  attribute vec4 occVertex;
-  attribute vec3 occNormal;
-  attribute vec4 occTexCoord;
-  attribute vec4 occVertColor;
+  THE_ATTRIBUTE vec4 occVertex;
+  THE_ATTRIBUTE vec3 occNormal;
+  THE_ATTRIBUTE vec4 occTexCoord;
+  THE_ATTRIBUTE vec4 occVertColor;
+#elif (__VERSION__ >= 130)
+  out vec4 occFragColor;
+#else
+  #define occFragColor gl_FragColor
 #endif
 
 // Matrix state
index a818ecc..c816e7e 100755 (executable)
@@ -1,3 +1,4 @@
+vglinfo
 vdump $imagedir/${test_image}.png
 
 puts ""
index 0f8acd8..b9ed015 100644 (file)
@@ -190,6 +190,7 @@ if { [info exists test_image ] == 0 } {
 }
 
 if { [string compare $command "shading"] == 0 } {
+    vglinfo
     vdump $imagedir/${test_image}.png
 } else {
     isos 0