0029477: Visualization, TKOpenGl - MSAA FBO initialization failure on OpenGL ES 3...
[occt.git] / src / OpenGl / OpenGl_View.cxx
index 0291ea4..8f68818 100644 (file)
@@ -4,8 +4,8 @@
 //
 // 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 version 2.1 as published
+// 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.
 
-#ifdef HAVE_CONFIG_H
-  #include <config.h>
-#endif
+#include <OpenGl_View.hxx>
 
+#include <Aspect_RenderingContext.hxx>
+#include <Aspect_Window.hxx>
+#include <Graphic3d_AspectFillArea3d.hxx>
+#include <Graphic3d_Texture2Dmanual.hxx>
+#include <Graphic3d_TextureEnv.hxx>
+#include <Graphic3d_Mat4d.hxx>
 #include <NCollection_Mat4.hxx>
-
 #include <OpenGl_Context.hxx>
-#include <OpenGl_Display.hxx>
+#include <OpenGl_FrameBuffer.hxx>
 #include <OpenGl_GlCore11.hxx>
 #include <OpenGl_GraduatedTrihedron.hxx>
 #include <OpenGl_GraphicDriver.hxx>
 #include <OpenGl_ShaderManager.hxx>
 #include <OpenGl_Texture.hxx>
-#include <OpenGl_Trihedron.hxx>
-#include <OpenGl_transform_persistence.hxx>
-#include <OpenGl_View.hxx>
+#include <OpenGl_Window.hxx>
 #include <OpenGl_Workspace.hxx>
+#include <OSD_Parallel.hxx>
+#include <Standard_CLocaleSentry.hxx>
 
-#include <Graphic3d_TextureEnv.hxx>
-
-IMPLEMENT_STANDARD_HANDLE(OpenGl_View,MMgt_TShared)
-IMPLEMENT_STANDARD_RTTIEXT(OpenGl_View,MMgt_TShared)
-
-/*----------------------------------------------------------------------*/
-
-static const OPENGL_BG_TEXTURE myDefaultBgTexture = { 0, 0, 0, Aspect_FM_CENTERED };
-static const OPENGL_BG_GRADIENT myDefaultBgGradient = { {{ 0.F, 0.F, 0.F, 1.F }}, {{ 0.F, 0.F, 0.F, 1.F }}, Aspect_GFM_NONE };
-static const Tmatrix3 myDefaultMatrix = { { 1.F, 0.F, 0.F, 0.F }, { 0.F, 1.F, 0.F, 0.F }, { 0.F, 0.F, 1.F, 0.F }, { 0.F, 0.F, 0.F, 1.F } };
-static const OPENGL_ZCLIP myDefaultZClip = { { Standard_True, 0.F }, { Standard_True, 1.F } };
-
-static const OPENGL_FOG myDefaultFog = { Standard_False, 0.F, 1.F, { { 0.F, 0.F, 0.F, 1.F } } };
-static const TEL_TRANSFORM_PERSISTENCE myDefaultTransPers = { 0, 0.F, 0.F, 0.F };
-static const GLdouble THE_IDENTITY_MATRIX[4][4] =
-{
-  {1.0, 0.0, 0.0, 0.0},
-  {0.0, 1.0, 0.0, 0.0},
-  {0.0, 0.0, 1.0, 0.0},
-  {0.0, 0.0, 0.0, 1.0}
-};
-
-/*----------------------------------------------------------------------*/
-
-OpenGl_View::OpenGl_View (const CALL_DEF_VIEWCONTEXT &AContext,
-                          OpenGl_StateCounter*       theCounter)
-: mySurfaceDetail(Visual3d_TOD_NONE),
-  myBackfacing(0),
-  myBgTexture(myDefaultBgTexture),
-  myBgGradient(myDefaultBgGradient),
-  //shield_indicator = TOn,
-  //shield_colour = { { 0.F, 0.F, 0.F, 1.F } },
-  //border_indicator = TOff,
-  //border_colour = { { 0.F, 0.F, 0.F, 1.F } },
-  //active_status = TOn,
-  myZClip(myDefaultZClip),
-  myCamera(AContext.Camera),
-  myFog(myDefaultFog),
-  myTrihedron(NULL),
-  myGraduatedTrihedron(NULL),
-  myVisualization(AContext.Visualization),
-  myIntShadingMethod(TEL_SM_GOURAUD),
-  myAntiAliasing(Standard_False),
-  myTransPers(&myDefaultTransPers),
-  myIsTransPers(Standard_False),
-  myProjectionState (0),
-  myModelViewState (0),
-  myStateCounter (theCounter),
-  myLastLightSourceState (0, 0)
-{
-
-  // Shading method
-  switch (AContext.Model)
-  {
-    case 1 : /* VISUAL3D_TOM_INTERP_COLOR */
-    case 3 : /* VISUAL3D_TOM_VERTEX */
-      myIntShadingMethod = TEL_SM_GOURAUD;
-      break;
-    default :
-      myIntShadingMethod = TEL_SM_FLAT;
-      break;
-  }
+#include "../Graphic3d/Graphic3d_Structure.pxx"
 
-  myCurrLightSourceState = myStateCounter->Increment();
+IMPLEMENT_STANDARD_RTTIEXT(OpenGl_View,Graphic3d_CView)
 
-#ifdef HAVE_OPENCL
-  myModificationState = 1; // initial state
+#ifdef HAVE_GL2PS
+#include <gl2ps.h>
 #endif
-}
 
-/*----------------------------------------------------------------------*/
+// =======================================================================
+// function : Constructor
+// purpose  :
+// =======================================================================
+OpenGl_View::OpenGl_View (const Handle(Graphic3d_StructureManager)& theMgr,
+                          const Handle(OpenGl_GraphicDriver)& theDriver,
+                          const Handle(OpenGl_Caps)& theCaps,
+                          OpenGl_StateCounter* theCounter)
+: Graphic3d_CView  (theMgr),
+  myDriver         (theDriver.operator->()),
+  myCaps           (theCaps),
+  myWasRedrawnGL   (Standard_False),
+  myCulling        (Standard_True),
+  myShadingModel   (Graphic3d_TOSM_FACET),
+  myBackfacing     (Graphic3d_TOBM_AUTOMATIC),
+  myBgColor        (Quantity_NOC_BLACK),
+  myCamera         (new Graphic3d_Camera()),
+  myToShowGradTrihedron  (false),
+  myZLayers        (Structure_MAX_PRIORITY - Structure_MIN_PRIORITY + 1),
+  myStateCounter         (theCounter),
+  myCurrLightSourceState (theCounter->Increment()),
+  myLightsRevision       (0),
+  myLastLightSourceState (0, 0),
+  myFboColorFormat       (GL_RGBA8),
+  myFboDepthFormat       (GL_DEPTH24_STENCIL8),
+  myToFlipOutput         (Standard_False),
+  myFrameCounter         (0),
+  myHasFboBlit           (Standard_True),
+  myToDisableOIT         (Standard_False),
+  myToDisableOITMSAA     (Standard_False),
+  myToDisableMSAA        (Standard_False),
+  myTransientDrawToFront (Standard_True),
+  myBackBufferRestored   (Standard_False),
+  myIsImmediateDrawn     (Standard_False),
+  myTextureParams   (new OpenGl_AspectFace()),
+  myBgGradientArray (new OpenGl_BackgroundArray (Graphic3d_TOB_GRADIENT)),
+  myBgTextureArray  (new OpenGl_BackgroundArray (Graphic3d_TOB_TEXTURE)),
+  // ray-tracing fields initialization
+  myRaytraceInitStatus     (OpenGl_RT_NONE),
+  myIsRaytraceDataValid    (Standard_False),
+  myIsRaytraceWarnTextures (Standard_False),
+  myRaytraceBVHBuilder (new BVH_BinnedBuilder<Standard_ShortReal, 3, BVH_Constants_NbBinsBest> (BVH_Constants_LeafNodeSizeAverage,
+                                                                                                BVH_Constants_MaxTreeDepth,
+                                                                                                Standard_False,
+                                                                                                OSD_Parallel::NbLogicalProcessors() + 1)),
+  myRaytraceSceneRadius  (0.0f),
+  myRaytraceSceneEpsilon (1.0e-6f),
+  myToUpdateEnvironmentMap (Standard_False),
+  myRaytraceLayerListState (0),
+  myPrevCameraApertureRadius(0.f),
+  myPrevCameraFocalPlaneDist(0.f)
+{
+  myWorkspace = new OpenGl_Workspace (this, NULL);
+
+  Handle(Graphic3d_CLight) aLight = new Graphic3d_CLight (Graphic3d_TOLS_AMBIENT);
+  aLight->SetHeadlight (false);
+  aLight->SetColor (Quantity_NOC_WHITE);
+  myNoShadingLight = new Graphic3d_LightSet();
+  myNoShadingLight->Add (aLight);
+
+  myMainSceneFbos[0]         = new OpenGl_FrameBuffer();
+  myMainSceneFbos[1]         = new OpenGl_FrameBuffer();
+  myMainSceneFbosOit[0]      = new OpenGl_FrameBuffer();
+  myMainSceneFbosOit[1]      = new OpenGl_FrameBuffer();
+  myImmediateSceneFbos[0]    = new OpenGl_FrameBuffer();
+  myImmediateSceneFbos[1]    = new OpenGl_FrameBuffer();
+  myImmediateSceneFbosOit[0] = new OpenGl_FrameBuffer();
+  myImmediateSceneFbosOit[1] = new OpenGl_FrameBuffer();
+  myOpenGlFBO                = new OpenGl_FrameBuffer();
+  myOpenGlFBO2               = new OpenGl_FrameBuffer();
+  myRaytraceFBO1[0]          = new OpenGl_FrameBuffer();
+  myRaytraceFBO1[1]          = new OpenGl_FrameBuffer();
+  myRaytraceFBO2[0]          = new OpenGl_FrameBuffer();
+  myRaytraceFBO2[1]          = new OpenGl_FrameBuffer();
+}
 
-OpenGl_View::~OpenGl_View ()
+// =======================================================================
+// function : Destructor
+// purpose  :
+// =======================================================================
+OpenGl_View::~OpenGl_View()
 {
   ReleaseGlResources (NULL); // ensure ReleaseGlResources() was called within valid context
+  OpenGl_Element::Destroy (NULL, myBgGradientArray);
+  OpenGl_Element::Destroy (NULL, myBgTextureArray);
+  OpenGl_Element::Destroy (NULL, myTextureParams);
 }
 
+// =======================================================================
+// function : ReleaseGlResources
+// purpose  :
+// =======================================================================
 void OpenGl_View::ReleaseGlResources (const Handle(OpenGl_Context)& theCtx)
 {
-  OpenGl_Element::Destroy (theCtx, myTrihedron);
-  OpenGl_Element::Destroy (theCtx, myGraduatedTrihedron);
+  myGraduatedTrihedron.Release (theCtx.operator->());
+  myFrameStatsPrs.Release (theCtx.operator->());
 
   if (!myTextureEnv.IsNull())
   {
-    theCtx->DelayedRelease (myTextureEnv);
+    for (OpenGl_TextureSet::Iterator aTextureIter (myTextureEnv); aTextureIter.More(); aTextureIter.Next())
+    {
+      theCtx->DelayedRelease (aTextureIter.ChangeValue());
+      aTextureIter.ChangeValue().Nullify();
+    }
     myTextureEnv.Nullify();
   }
-  if (myBgTexture.TexId != 0)
+
+  if (myTextureParams != NULL)
   {
-    glDeleteTextures (1, (GLuint*)&(myBgTexture.TexId));
-    myBgTexture.TexId = 0;
+    myTextureParams->Release (theCtx.operator->());
   }
-}
-
-void OpenGl_View::SetTextureEnv (const Handle(OpenGl_Context)&       theCtx,
-                                 const Handle(Graphic3d_TextureEnv)& theTexture)
-{
-  if (!myTextureEnv.IsNull())
+  if (myBgGradientArray != NULL)
   {
-    theCtx->DelayedRelease (myTextureEnv);
-    myTextureEnv.Nullify();
+    myBgGradientArray->Release (theCtx.operator->());
   }
+  if (myBgTextureArray != NULL)
+  {
+    myBgTextureArray->Release (theCtx.operator->());
+  }
+
+  myMainSceneFbos[0]        ->Release (theCtx.operator->());
+  myMainSceneFbos[1]        ->Release (theCtx.operator->());
+  myMainSceneFbosOit[0]     ->Release (theCtx.operator->());
+  myMainSceneFbosOit[1]     ->Release (theCtx.operator->());
+  myImmediateSceneFbos[0]   ->Release (theCtx.operator->());
+  myImmediateSceneFbos[1]   ->Release (theCtx.operator->());
+  myImmediateSceneFbosOit[0]->Release (theCtx.operator->());
+  myImmediateSceneFbosOit[1]->Release (theCtx.operator->());
+  myOpenGlFBO               ->Release (theCtx.operator->());
+  myOpenGlFBO2              ->Release (theCtx.operator->());
+  myFullScreenQuad           .Release (theCtx.operator->());
+  myFullScreenQuadFlip       .Release (theCtx.operator->());
+
+  releaseRaytraceResources (theCtx);
+}
 
-  if (theTexture.IsNull())
+// =======================================================================
+// function : Remove
+// purpose  :
+// =======================================================================
+void OpenGl_View::Remove()
+{
+  if (IsRemoved())
   {
     return;
   }
 
-  myTextureEnv = new OpenGl_Texture (theTexture->GetParams());
-  Handle(Image_PixMap) anImage = theTexture->GetImage();
-  if (!anImage.IsNull())
-    myTextureEnv->Init (theCtx, *anImage.operator->(), theTexture->Type());
+  myDriver->RemoveView (this);
+  myWindow.Nullify();
 
-#ifdef HAVE_OPENCL
-  myModificationState++;
-#endif
+  Graphic3d_CView::Remove();
 }
 
-void OpenGl_View::SetSurfaceDetail (const Visual3d_TypeOfSurfaceDetail theMode)
+// =======================================================================
+// function : SetTextureEnv
+// purpose  :
+// =======================================================================
+void OpenGl_View::SetCamera(const Handle(Graphic3d_Camera)& theCamera)
 {
-  mySurfaceDetail = theMode;
+  myCamera = theCamera;
+}
 
-#ifdef HAVE_OPENCL
-  myModificationState++;
-#endif
+// =======================================================================
+// function : SetLocalOrigin
+// purpose  :
+// =======================================================================
+void OpenGl_View::SetLocalOrigin (const gp_XYZ& theOrigin)
+{
+  myLocalOrigin = theOrigin;
+  const Handle(OpenGl_Context)& aCtx = myWorkspace->GetGlContext();
+  if (!aCtx.IsNull())
+  {
+    aCtx->ShaderManager()->SetLocalOrigin (theOrigin);
+  }
 }
 
 // =======================================================================
-// function : SetBackfacing
+// function : SetTextureEnv
 // purpose  :
 // =======================================================================
-void OpenGl_View::SetBackfacing (const Standard_Integer theMode)
+void OpenGl_View::SetTextureEnv (const Handle(Graphic3d_TextureEnv)& theTextureEnv)
 {
-  myBackfacing = theMode;
+  Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext();
+  if (!aCtx.IsNull() && !myTextureEnv.IsNull())
+  {
+    for (OpenGl_TextureSet::Iterator aTextureIter (myTextureEnv); aTextureIter.More(); aTextureIter.Next())
+    {
+      aCtx->DelayedRelease (aTextureIter.ChangeValue());
+      aTextureIter.ChangeValue().Nullify();
+    }
+  }
+
+  myToUpdateEnvironmentMap = Standard_True;
+  myTextureEnvData = theTextureEnv;
+  myTextureEnv.Nullify();
+  initTextureEnv (aCtx);
 }
 
 // =======================================================================
-// function : SetLights
+// function : initTextureEnv
 // purpose  :
 // =======================================================================
-void OpenGl_View::SetLights (const CALL_DEF_VIEWCONTEXT& theViewCtx)
+void OpenGl_View::initTextureEnv (const Handle(OpenGl_Context)& theContext)
 {
-  myLights.Clear();
-  for (Standard_Integer aLightIt = 0; aLightIt < theViewCtx.NbActiveLight; ++aLightIt)
+  if (myTextureEnvData.IsNull()
+    ||  theContext.IsNull()
+    || !theContext->MakeCurrent())
+  {
+    return;
+  }
+
+  myTextureEnv = new OpenGl_TextureSet (1);
+  Handle(OpenGl_Texture)& aTextureEnv = myTextureEnv->ChangeFirst();
+  aTextureEnv = new OpenGl_Texture (myTextureEnvData->GetId(), myTextureEnvData->GetParams());
+  Handle(Image_PixMap) anImage = myTextureEnvData->GetImage();
+  if (!anImage.IsNull())
   {
-    myLights.Append (theViewCtx.ActiveLight[aLightIt]);
+    aTextureEnv->Init (theContext, *anImage.operator->(), myTextureEnvData->Type());
   }
-  myCurrLightSourceState = myStateCounter->Increment();
 }
 
-/*----------------------------------------------------------------------*/
+// =======================================================================
+// function : SetImmediateModeDrawToFront
+// purpose  :
+// =======================================================================
+Standard_Boolean OpenGl_View::SetImmediateModeDrawToFront (const Standard_Boolean theDrawToFrontBuffer)
+{
+  const Standard_Boolean aPrevMode = myTransientDrawToFront;
+  myTransientDrawToFront = theDrawToFrontBuffer;
+  return aPrevMode;
+}
+
+// =======================================================================
+// function : SetWindow
+// purpose  :
+// =======================================================================
+void OpenGl_View::SetWindow (const Handle(Aspect_Window)& theWindow,
+                             const Aspect_RenderingContext theContext)
+{
+  myWindow = myDriver->CreateRenderWindow (theWindow, theContext);
+  Standard_ASSERT_RAISE (!myWindow.IsNull(),
+                         "OpenGl_View::SetWindow, "
+                         "Failed to create OpenGl window.");
+
+  myWorkspace = new OpenGl_Workspace (this, myWindow);
+  myWorldViewProjState.Reset();
+  myToUpdateEnvironmentMap = Standard_True;
+  myHasFboBlit = Standard_True;
+  Invalidate();
+
+  // Environment texture resource does not support lazy initialization.
+  initTextureEnv (myWorkspace->GetGlContext());
+}
 
-//call_togl_setvisualisation
-void OpenGl_View::SetVisualisation (const CALL_DEF_VIEWCONTEXT &AContext)
+// =======================================================================
+// function : Resized
+// purpose  :
+// =======================================================================
+void OpenGl_View::Resized()
 {
-  myVisualization = AContext.Visualization;
-  // Shading method
-  switch (AContext.Model)
+  if (myWindow.IsNull())
+    return;
+
+  myWindow->Resize();
+}
+
+// =======================================================================
+// function : SetMinMaxValuesCallback
+// purpose  :
+// =======================================================================
+static void SetMinMaxValuesCallback (Graphic3d_CView* theView)
+{
+  OpenGl_View* aView = dynamic_cast<OpenGl_View*>(theView);
+  if (aView == NULL)
+    return;
+
+  Bnd_Box aBox = theView->MinMaxValues();
+  if (!aBox.IsVoid())
   {
-    case 1 : /* VISUAL3D_TOM_INTERP_COLOR */
-    case 3 : /* VISUAL3D_TOM_VERTEX */
-      myIntShadingMethod = TEL_SM_GOURAUD;
-      break;
-    default :
-      myIntShadingMethod = TEL_SM_FLAT;
-      break;
+    gp_Pnt aMin = aBox.CornerMin();
+    gp_Pnt aMax = aBox.CornerMax();
+
+    Graphic3d_Vec3 aMinVec ((Standard_ShortReal )aMin.X(), (Standard_ShortReal )aMin.Y(), (Standard_ShortReal )aMin.Z());
+    Graphic3d_Vec3 aMaxVec ((Standard_ShortReal )aMax.X(), (Standard_ShortReal )aMax.Y(), (Standard_ShortReal )aMax.Z());
+    aView->GraduatedTrihedronMinMaxValues (aMinVec, aMaxVec);
   }
 }
 
-/*----------------------------------------------------------------------*/
-
-//call_togl_cliplimit
-void OpenGl_View::SetClipLimit (const Graphic3d_CView& theCView)
+// =======================================================================
+// function : GraduatedTrihedronDisplay
+// purpose  :
+// =======================================================================
+void OpenGl_View::GraduatedTrihedronDisplay (const Graphic3d_GraduatedTrihedron& theTrihedronData)
 {
-  myZClip.Back.Limit = theCView.Context.ZClipBackPlane;
-  myZClip.Front.Limit = theCView.Context.ZClipFrontPlane;
+  myGTrihedronData = theTrihedronData;
+  myGTrihedronData.PtrView = this;
+  myGTrihedronData.CubicAxesCallback = SetMinMaxValuesCallback;
+  myGraduatedTrihedron.SetValues (myGTrihedronData);
+  myToShowGradTrihedron = true;
+}
 
-  myZClip.Back.IsOn  = (theCView.Context.BackZClipping  != 0);
-  myZClip.Front.IsOn = (theCView.Context.FrontZClipping != 0);
+// =======================================================================
+// function : GraduatedTrihedronErase
+// purpose  :
+// =======================================================================
+void OpenGl_View::GraduatedTrihedronErase()
+{
+  myGTrihedronData.PtrView = NULL;
+  myGraduatedTrihedron.Release (myWorkspace->GetGlContext().operator->());
+  myToShowGradTrihedron = false;
 }
 
-/*----------------------------------------------------------------------*/
+// =======================================================================
+// function : GraduatedTrihedronMinMaxValues
+// purpose  :
+// =======================================================================
+void OpenGl_View::GraduatedTrihedronMinMaxValues (const Graphic3d_Vec3 theMin, const Graphic3d_Vec3 theMax)
+{
+  myGraduatedTrihedron.SetMinMax (theMin, theMax);
+}
 
-void OpenGl_View::SetFog (const Graphic3d_CView& theCView,
-                          const Standard_Boolean theFlag)
+// =======================================================================
+// function : BufferDump
+// purpose  :
+// =======================================================================
+Standard_Boolean OpenGl_View::BufferDump (Image_PixMap& theImage, const Graphic3d_BufferType& theBufferType)
 {
-  if (!theFlag)
+  if (theBufferType != Graphic3d_BT_RGB_RayTraceHdrLeft)
   {
-    myFog.IsOn = Standard_False;
+    return myWorkspace->BufferDump(myFBO, theImage, theBufferType);
   }
-  else
+
+  if (!myRaytraceParameters.AdaptiveScreenSampling)
   {
-    myFog.IsOn = Standard_True;
+    return myWorkspace->BufferDump(myAccumFrames % 2 ? myRaytraceFBO2[0] : myRaytraceFBO1[0], theImage, theBufferType);
+  }
+
+#if defined(GL_ES_VERSION_2_0)
+  return false;
+#else
+  if (theImage.Format() != Image_Format_RGBF)
+  {
+    return false;
+  }
 
-    myFog.Front = theCView.Context.DepthFrontPlane;
-    myFog.Back = theCView.Context.DepthBackPlane;
+  const GLuint aW = myRaytraceOutputTexture[0]->SizeX();
+  const GLuint aH = myRaytraceOutputTexture[0]->SizeY();
+  if (aW / 3 != theImage.SizeX() || aH / 2 != theImage.SizeY())
+  {
+    return false;
+  }
 
-    myFog.Color.rgb[0] = theCView.DefWindow.Background.r;
-    myFog.Color.rgb[1] = theCView.DefWindow.Background.g;
-    myFog.Color.rgb[2] = theCView.DefWindow.Background.b;
-    myFog.Color.rgb[3] = 1.0f;
+  std::vector<GLfloat> aValues;
+  try
+  {
+    aValues.resize (aW * aH);
   }
+  catch (const std::bad_alloc&)
+  {
+    return false;
+  }
+
+  glBindTexture (GL_TEXTURE_RECTANGLE, myRaytraceOutputTexture[0]->TextureId());
+  glGetTexImage (GL_TEXTURE_RECTANGLE, 0, OpenGl_TextureFormat::Create<GLfloat, 1>().Format(), GL_FLOAT, &aValues[0]);
+  glBindTexture (GL_TEXTURE_RECTANGLE, 0);
+  for (unsigned int aRow = 0; aRow < aH; aRow += 2)
+  {
+    for (unsigned int aCol = 0; aCol < aW; aCol += 3)
+    {
+      float* anImageValue = theImage.ChangeValue<float[3]> ((aH - aRow) / 2 - 1, aCol / 3);
+      float aInvNbSamples = 1.f / aValues[aRow * aW + aCol + aW];
+      anImageValue[0] = aValues[aRow * aW + aCol] * aInvNbSamples;
+      anImageValue[1] = aValues[aRow * aW + aCol + 1] * aInvNbSamples;
+      anImageValue[2] = aValues[aRow * aW + aCol + 1 + aW] * aInvNbSamples;
+    }
+  }
+
+  return true;
+#endif
 }
 
-/*----------------------------------------------------------------------*/
+// =======================================================================
+// function : Background
+// purpose  :
+// =======================================================================
+Aspect_Background OpenGl_View::Background() const
+{
+  return Aspect_Background (myBgColor.GetRGB());
+}
 
-void OpenGl_View::TriedronDisplay (const Handle(OpenGl_Context)&       theCtx,
-                                   const Aspect_TypeOfTriedronPosition thePosition,
-                                   const Quantity_NameOfColor          theColor,
-                                   const Standard_Real                 theScale,
-                                   const Standard_Boolean              theAsWireframe)
+// =======================================================================
+// function : SetBackground
+// purpose  :
+// =======================================================================
+void OpenGl_View::SetBackground (const Aspect_Background& theBackground)
 {
-  OpenGl_Element::Destroy (theCtx, myTrihedron);
-  myTrihedron = new OpenGl_Trihedron (thePosition, theColor, theScale, theAsWireframe);
+  myBgColor.SetRGB (theBackground.Color());
 }
 
-/*----------------------------------------------------------------------*/
+// =======================================================================
+// function : GradientBackground
+// purpose  :
+// =======================================================================
+Aspect_GradientBackground OpenGl_View::GradientBackground() const
+{
+  Quantity_Color aColor1, aColor2;
+  aColor1.SetValues (myBgGradientArray->GradientColor (0).r(),
+                     myBgGradientArray->GradientColor (0).g(),
+                     myBgGradientArray->GradientColor (0).b(), Quantity_TOC_RGB);
+  aColor2.SetValues (myBgGradientArray->GradientColor (1).r(),
+                     myBgGradientArray->GradientColor (1).g(),
+                     myBgGradientArray->GradientColor (1).b(), Quantity_TOC_RGB);
+  return Aspect_GradientBackground (aColor1, aColor2, myBgGradientArray->GradientFillMethod());
+}
 
-void OpenGl_View::TriedronErase (const Handle(OpenGl_Context)& theCtx)
+// =======================================================================
+// function : SetGradientBackground
+// purpose  :
+// =======================================================================
+void OpenGl_View::SetGradientBackground (const Aspect_GradientBackground& theBackground)
 {
-  OpenGl_Element::Destroy (theCtx, myTrihedron);
+  Quantity_Color aColor1, aColor2;
+  theBackground.Colors (aColor1, aColor2);
+  myBgGradientArray->SetGradientParameters (aColor1, aColor2, theBackground.BgGradientFillMethod());
 }
 
-/*----------------------------------------------------------------------*/
+// =======================================================================
+// function : SetBackgroundImage
+// purpose  :
+// =======================================================================
+void OpenGl_View::SetBackgroundImage (const TCollection_AsciiString& theFilePath)
+{
+  // Prepare aspect for texture storage
+  myBackgroundImagePath = theFilePath;
+  Handle(Graphic3d_AspectFillArea3d) anAspect = new Graphic3d_AspectFillArea3d();
+  Handle(Graphic3d_Texture2Dmanual) aTextureMap = new Graphic3d_Texture2Dmanual (TCollection_AsciiString (theFilePath));
+  aTextureMap->EnableRepeat();
+  aTextureMap->DisableModulate();
+  aTextureMap->GetParams()->SetGenMode (Graphic3d_TOTM_MANUAL,
+                                        Graphic3d_Vec4 (0.0f, 0.0f, 0.0f, 0.0f),
+                                        Graphic3d_Vec4 (0.0f, 0.0f, 0.0f, 0.0f));
+  anAspect->SetTextureMap (aTextureMap);
+  anAspect->SetInteriorStyle (Aspect_IS_SOLID);
+  anAspect->SetSuppressBackFaces (false);
+  // Enable texture mapping
+  if (aTextureMap->IsDone())
+  {
+    anAspect->SetTextureMapOn();
+  }
+  else
+  {
+    anAspect->SetTextureMapOff();
+    return;
+  }
 
-void OpenGl_View::GraduatedTrihedronDisplay (const Handle(OpenGl_Context)&        theCtx,
-                                             const Graphic3d_CGraduatedTrihedron& theData)
+  // Set texture parameters
+  myTextureParams->SetAspect (anAspect);
+}
+
+// =======================================================================
+// function : BackgroundImageStyle
+// purpose  :
+// =======================================================================
+Aspect_FillMethod OpenGl_View::BackgroundImageStyle() const
 {
-  OpenGl_Element::Destroy (theCtx, myGraduatedTrihedron);
-  myGraduatedTrihedron = new OpenGl_GraduatedTrihedron (theData);
+  return myBgTextureArray->TextureFillMethod();
 }
 
-/*----------------------------------------------------------------------*/
+// =======================================================================
+// function : SetBackgroundImageStyle
+// purpose  :
+// =======================================================================
+void OpenGl_View::SetBackgroundImageStyle (const Aspect_FillMethod theFillStyle)
+{
+  myBgTextureArray->SetTextureFillMethod (theFillStyle);
+}
 
-void OpenGl_View::GraduatedTrihedronErase (const Handle(OpenGl_Context)& theCtx)
+//=======================================================================
+//function : AddZLayer
+//purpose  :
+//=======================================================================
+void OpenGl_View::AddZLayer (const Graphic3d_ZLayerId theLayerId)
 {
-  OpenGl_Element::Destroy (theCtx, myGraduatedTrihedron);
+  myZLayers.AddLayer (theLayerId);
 }
 
-/*----------------------------------------------------------------------*/
+//=======================================================================
+//function : RemoveZLayer
+//purpose  :
+//=======================================================================
+void OpenGl_View::RemoveZLayer (const Graphic3d_ZLayerId theLayerId)
+{
+  myZLayers.RemoveLayer (theLayerId);
+}
 
-//transform_persistence_end
-void OpenGl_View::EndTransformPersistence(const Handle(OpenGl_Context)& theCtx)
+//=======================================================================
+//function : SetZLayerSettings
+//purpose  :
+//=======================================================================
+void OpenGl_View::SetZLayerSettings (const Graphic3d_ZLayerId        theLayerId,
+                                     const Graphic3d_ZLayerSettings& theSettings)
 {
-  if (myIsTransPers)
-  {
-    // restore matrix
-    glMatrixMode (GL_PROJECTION);
-    glPopMatrix();
-    glMatrixMode (GL_MODELVIEW);
-    glPopMatrix();
-    myIsTransPers = Standard_False;
+  myZLayers.SetLayerSettings (theLayerId, theSettings);
+}
 
-    // Note: the approach of accessing OpenGl matrices is used now since the matrix
-    // manipulation are made with help of OpenGl methods. This might be replaced by
-    // direct computation of matrices by OCC subroutines.
-    Tmatrix3 aResultWorldView;
-    glGetFloatv (GL_MODELVIEW_MATRIX, *aResultWorldView);
+//=======================================================================
+//function : ZLayerMax
+//purpose  :
+//=======================================================================
+Standard_Integer OpenGl_View::ZLayerMax() const
+{
+  Standard_Integer aLayerMax = Graphic3d_ZLayerId_Default;
+  for (OpenGl_LayerSeqIds::Iterator aMapIt(myZLayers.LayerIDs()); aMapIt.More(); aMapIt.Next())
+  {
+    aLayerMax = Max (aLayerMax, aMapIt.Value());
+  }
 
-    Tmatrix3 aResultProjection;
-    glGetFloatv (GL_PROJECTION_MATRIX, *aResultProjection);
+  return aLayerMax;
+}
 
-    // Set OCCT state uniform variables
-    theCtx->ShaderManager()->RevertWorldViewStateTo (&aResultWorldView);
-    theCtx->ShaderManager()->RevertProjectionStateTo (&aResultProjection);
+//=======================================================================
+//function : InvalidateZLayerBoundingBox
+//purpose  :
+//=======================================================================
+void OpenGl_View::InvalidateZLayerBoundingBox (const Graphic3d_ZLayerId theLayerId) const
+{
+  if (myZLayers.LayerIDs().IsBound (theLayerId))
+  {
+    myZLayers.Layer (theLayerId).InvalidateBoundingBox();
+  }
+  else
+  {
+    const Standard_Integer aLayerMax = ZLayerMax();
+    for (Standard_Integer aLayerId = Graphic3d_ZLayerId_Default; aLayerId < aLayerMax; ++aLayerId)
+    {
+      if (myZLayers.LayerIDs().IsBound (aLayerId))
+      {
+        const OpenGl_Layer& aLayer = myZLayers.Layer (aLayerId);
+        if (aLayer.NbOfTransformPersistenceObjects() > 0)
+        {
+          aLayer.InvalidateBoundingBox();
+        }
+      }
+    }
   }
 }
 
-/*----------------------------------------------------------------------*/
-
-//transform_persistence_begin
-const TEL_TRANSFORM_PERSISTENCE* OpenGl_View::BeginTransformPersistence (const Handle(OpenGl_Context)& theCtx,
-                                                                         const TEL_TRANSFORM_PERSISTENCE* theTransPers)
+//=======================================================================
+//function : ZLayerBoundingBox
+//purpose  :
+//=======================================================================
+Bnd_Box OpenGl_View::ZLayerBoundingBox (const Graphic3d_ZLayerId        theLayerId,
+                                        const Handle(Graphic3d_Camera)& theCamera,
+                                        const Standard_Integer          theWindowWidth,
+                                        const Standard_Integer          theWindowHeight,
+                                        const Standard_Boolean          theToIncludeAuxiliary) const
 {
-  const TEL_TRANSFORM_PERSISTENCE* aTransPersPrev = myTransPers;
-  myTransPers = theTransPers;
-  if (theTransPers->mode == 0)
+  Bnd_Box aBox;
+  if (myZLayers.LayerIDs().IsBound (theLayerId))
   {
-    EndTransformPersistence (theCtx);
-    return aTransPersPrev;
+    aBox = myZLayers.Layer (theLayerId).BoundingBox (Identification(),
+                                                     theCamera,
+                                                     theWindowWidth,
+                                                     theWindowHeight,
+                                                     theToIncludeAuxiliary);
   }
 
-  GLint aViewport[4];
-  GLdouble aModelMatrix[4][4];
-  GLdouble aProjMatrix[4][4];
-  glGetIntegerv (GL_VIEWPORT,          aViewport);
-  glGetDoublev  (GL_MODELVIEW_MATRIX,  (GLdouble* )aModelMatrix);
-  glGetDoublev  (GL_PROJECTION_MATRIX, (GLdouble *)aProjMatrix);
-  const GLdouble aViewportW = (GLdouble )aViewport[2];
-  const GLdouble aViewportH = (GLdouble )aViewport[3];
-
-  if (myIsTransPers)
-  {
-    // pop matrix stack - it will be overridden later
-    glMatrixMode (GL_PROJECTION);
-    glPopMatrix();
-    glMatrixMode (GL_MODELVIEW);
-    glPopMatrix();
+  // add bounding box of gradient/texture background for proper Z-fit
+  if (theToIncludeAuxiliary
+   && theLayerId == Graphic3d_ZLayerId_BotOSD
+   && (myBgTextureArray->IsDefined()
+    || myBgGradientArray->IsDefined()))
+  {
+    // Background is drawn using 2D transformation persistence
+    // (e.g. it is actually placed in 3D coordinates within active camera position).
+    // We add here full-screen plane with 2D transformation persistence
+    // for simplicity (myBgTextureArray might define a little bit different options
+    // but it is updated within ::Render())
+    const Graphic3d_Mat4d& aProjectionMat = theCamera->ProjectionMatrix();
+    const Graphic3d_Mat4d& aWorldViewMat  = theCamera->OrientationMatrix();
+    Graphic3d_BndBox3d aBox2d (Graphic3d_Vec3d (0.0, 0.0, 0.0),
+                               Graphic3d_Vec3d (double(theWindowWidth), double(theWindowHeight), 0.0));
+
+    Graphic3d_TransformPers aTrsfPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_LOWER);
+    aTrsfPers.Apply (theCamera,
+                     aProjectionMat,
+                     aWorldViewMat,
+                     theWindowWidth,
+                     theWindowHeight,
+                     aBox2d);
+    aBox.Add (gp_Pnt (aBox2d.CornerMin().x(), aBox2d.CornerMin().y(), aBox2d.CornerMin().z()));
+    aBox.Add (gp_Pnt (aBox2d.CornerMax().x(), aBox2d.CornerMax().y(), aBox2d.CornerMax().z()));
   }
-  else
+
+  return aBox;
+}
+
+//=======================================================================
+//function : considerZoomPersistenceObjects
+//purpose  :
+//=======================================================================
+Standard_Real OpenGl_View::considerZoomPersistenceObjects (const Graphic3d_ZLayerId        theLayerId,
+                                                           const Handle(Graphic3d_Camera)& theCamera,
+                                                           const Standard_Integer          theWindowWidth,
+                                                           const Standard_Integer          theWindowHeight) const
+{
+  if (myZLayers.LayerIDs().IsBound (theLayerId))
   {
-    myIsTransPers = Standard_True;
+    return myZLayers.Layer (theLayerId).considerZoomPersistenceObjects (Identification(),
+                                                                        theCamera,
+                                                                        theWindowWidth,
+                                                                        theWindowHeight);
   }
 
-  // push matrices into stack and reset them
-  glMatrixMode (GL_MODELVIEW);
-  glPushMatrix();
-  glLoadIdentity();
+  return 1.0;
+}
+
+//=======================================================================
+//function : FBO
+//purpose  :
+//=======================================================================
+Handle(Standard_Transient) OpenGl_View::FBO() const
+{
+  return Handle(Standard_Transient)(myFBO);
+}
+
+//=======================================================================
+//function : SetFBO
+//purpose  :
+//=======================================================================
+void OpenGl_View::SetFBO (const Handle(Standard_Transient)& theFbo)
+{
+  myFBO = Handle(OpenGl_FrameBuffer)::DownCast (theFbo);
+}
 
-  glMatrixMode (GL_PROJECTION);
-  glPushMatrix();
-  glLoadIdentity();
+//=======================================================================
+//function : FBOCreate
+//purpose  :
+//=======================================================================
+Handle(Standard_Transient) OpenGl_View::FBOCreate (const Standard_Integer theWidth,
+                                                   const Standard_Integer theHeight)
+{
+  return myWorkspace->FBOCreate (theWidth, theHeight);
+}
 
-  // get the window's (fixed) coordinates for theTransPers->point before matrixes modifications
-  GLdouble aWinX = 0.0, aWinY = 0.0, aWinZ = 0.0;
-  if ((theTransPers->mode & TPF_PAN) != TPF_PAN)
+//=======================================================================
+//function : FBORelease
+//purpose  :
+//=======================================================================
+void OpenGl_View::FBORelease (Handle(Standard_Transient)& theFbo)
+{
+  Handle(OpenGl_FrameBuffer) aFrameBuffer = Handle(OpenGl_FrameBuffer)::DownCast (theFbo);
+  if (aFrameBuffer.IsNull())
   {
-    gluProject (theTransPers->pointX, theTransPers->pointY, theTransPers->pointZ,
-                (GLdouble* )aModelMatrix, (GLdouble* )aProjMatrix, aViewport,
-                &aWinX, &aWinY, &aWinZ);
+    return;
   }
 
-  // prevent zooming
-  if ((theTransPers->mode & TPF_ZOOM)
-   || (theTransPers->mode == TPF_TRIEDRON))
+  myWorkspace->FBORelease (aFrameBuffer);
+  theFbo.Nullify();
+}
+
+//=======================================================================
+//function : FBOGetDimensions
+//purpose  :
+//=======================================================================
+void OpenGl_View::FBOGetDimensions (const Handle(Standard_Transient)& theFbo,
+                                    Standard_Integer& theWidth,
+                                    Standard_Integer& theHeight,
+                                    Standard_Integer& theWidthMax,
+                                    Standard_Integer& theHeightMax)
+{
+  const Handle(OpenGl_FrameBuffer) aFrameBuffer = Handle(OpenGl_FrameBuffer)::DownCast (theFbo);
+  if (aFrameBuffer.IsNull())
   {
-    // compute fixed-zoom multiplier
-    // actually function works ugly with TelPerspective!
-    const GLdouble aDet2 = 0.002 / (aViewportW > aViewportH ? aProjMatrix[1][1] : aProjMatrix[0][0]);
-    aProjMatrix[0][0] *= aDet2;
-    aProjMatrix[1][1] *= aDet2;
-    aProjMatrix[2][2] *= aDet2;
+    return;
   }
 
-  // prevent translation - annulate translate matrix
-  if ((theTransPers->mode & TPF_PAN)
-   || (theTransPers->mode == TPF_TRIEDRON))
+  theWidth     = aFrameBuffer->GetVPSizeX(); // current viewport size
+  theHeight    = aFrameBuffer->GetVPSizeY();
+  theWidthMax  = aFrameBuffer->GetSizeX(); // texture size
+  theHeightMax = aFrameBuffer->GetSizeY();
+}
+
+//=======================================================================
+//function : FBOChangeViewport
+//purpose  :
+//=======================================================================
+void OpenGl_View::FBOChangeViewport (const Handle(Standard_Transient)& theFbo,
+                                     const Standard_Integer theWidth,
+                                     const Standard_Integer theHeight)
+{
+  const Handle(OpenGl_FrameBuffer) aFrameBuffer = Handle(OpenGl_FrameBuffer)::DownCast (theFbo);
+  if (aFrameBuffer.IsNull())
   {
-    aModelMatrix[3][0] = 0.0;
-    aModelMatrix[3][1] = 0.0;
-    aModelMatrix[3][2] = 0.0;
-    aProjMatrix [3][0] = 0.0;
-    aProjMatrix [3][1] = 0.0;
-    aProjMatrix [3][2] = 0.0;
+    return;
   }
 
-  // prevent scaling-on-axis
-  if (theTransPers->mode & TPF_ZOOM)
+  aFrameBuffer->ChangeViewport (theWidth, theHeight);
+}
+
+// =======================================================================
+// function : Export
+// purpose  :
+// =======================================================================
+#ifdef HAVE_GL2PS
+Standard_Boolean OpenGl_View::Export (const Standard_CString theFileName,
+                                      const Graphic3d_ExportFormat theFormat,
+                                      const Graphic3d_SortType theSortType)
+{
+  // gl2psBeginPage() will call OpenGL functions
+  // so we should activate correct GL context before redraw scene call
+  if (!myWorkspace->Activate())
   {
-    const gp_Pnt anAxialScale = myCamera->AxialScale();
-    const double aScaleX = anAxialScale.X();
-    const double aScaleY = anAxialScale.Y();
-    const double aScaleZ = anAxialScale.Z();
-    for (int i = 0; i < 3; ++i)
-    {
-      aModelMatrix[0][i] /= aScaleX;
-      aModelMatrix[1][i] /= aScaleY;
-      aModelMatrix[2][i] /= aScaleZ;
-    }
+    return Standard_False;
   }
 
-  // prevent rotating - annulate rotate matrix
-  if (theTransPers->mode & TPF_ROTATE)
+  Standard_Integer aFormat = -1;
+  Standard_Integer aSortType = Graphic3d_ST_BSP_Tree;
+  switch (theFormat)
   {
-    aModelMatrix[0][0] = 1.0;
-    aModelMatrix[1][1] = 1.0;
-    aModelMatrix[2][2] = 1.0;
+    case Graphic3d_EF_PostScript:
+      aFormat = GL2PS_PS;
+      break;
+    case Graphic3d_EF_EnhPostScript:
+      aFormat = GL2PS_EPS;
+      break;
+    case Graphic3d_EF_TEX:
+      aFormat = GL2PS_TEX;
+      break;
+    case Graphic3d_EF_PDF:
+      aFormat = GL2PS_PDF;
+      break;
+    case Graphic3d_EF_SVG:
+      aFormat = GL2PS_SVG;
+      break;
+    case Graphic3d_EF_PGF:
+      aFormat = GL2PS_PGF;
+      break;
+    case Graphic3d_EF_EMF:
+      //aFormat = GL2PS_EMF;
+      aFormat = GL2PS_PGF + 1; // 6
+      break;
+    default:
+      // unsupported format
+      return Standard_False;
+  }
 
-    aModelMatrix[1][0] = 0.0;
-    aModelMatrix[2][0] = 0.0;
-    aModelMatrix[0][1] = 0.0;
-    aModelMatrix[2][1] = 0.0;
-    aModelMatrix[0][2] = 0.0;
-    aModelMatrix[1][2] = 0.0;
+  switch (theSortType)
+  {
+    case Graphic3d_ST_Simple:
+      aSortType = GL2PS_SIMPLE_SORT;
+      break;
+    case Graphic3d_ST_BSP_Tree:
+      aSortType = GL2PS_BSP_SORT;
+      break;
   }
 
-  // load computed matrices
-  glMatrixMode (GL_MODELVIEW);
-  glMultMatrixd ((GLdouble* )aModelMatrix);
+  GLint aViewport[4];
+  aViewport[0] = 0;
+  aViewport[1] = 0;
+  aViewport[2] = myWindow->Width();
+  aViewport[3] = myWindow->Height();
+
+  GLint aBufferSize = 1024 * 1024;
+  GLint anErrCode = GL2PS_SUCCESS;
 
-  glMatrixMode (GL_PROJECTION);
-  glMultMatrixd ((GLdouble* )aProjMatrix);
+  // gl2ps uses standard write functions and do not check locale
+  Standard_CLocaleSentry aLocaleSentry;
 
-  if (theTransPers->mode == TPF_TRIEDRON)
+  while (aBufferSize > 0)
   {
-    // move to the window corner
-    if (theTransPers->pointX != 0.0
-     && theTransPers->pointY != 0.0)
+    // current patch for EMF support in gl2ps uses WinAPI functions to create file
+    FILE* aFileH = (theFormat != Graphic3d_EF_EMF) ? fopen (theFileName, "wb") : NULL;
+    anErrCode = gl2psBeginPage ("", "", aViewport, aFormat, aSortType,
+                    GL2PS_DRAW_BACKGROUND | GL2PS_OCCLUSION_CULL | GL2PS_BEST_ROOT/* | GL2PS_SIMPLE_LINE_OFFSET*/,
+                    GL_RGBA, 0, NULL,
+                    0, 0, 0, aBufferSize, aFileH, theFileName);
+    if (anErrCode != GL2PS_SUCCESS)
     {
-      GLdouble aW1, aH1, aW2, aH2, aDummy;
-      glMatrixMode (GL_PROJECTION);
-      gluUnProject ( 0.5 * aViewportW,  0.5 * aViewportH, 0.0,
-                    (GLdouble* )THE_IDENTITY_MATRIX, (GLdouble* )aProjMatrix, aViewport,
-                    &aW1, &aH1, &aDummy);
-      gluUnProject (-0.5 * aViewportW, -0.5 * aViewportH, 0.0,
-                    (GLdouble* )THE_IDENTITY_MATRIX, (GLdouble* )aProjMatrix, aViewport,
-                    &aW2, &aH2, &aDummy);
-      GLdouble aMoveX = 0.5 * (aW1 - aW2 - theTransPers->pointZ);
-      GLdouble aMoveY = 0.5 * (aH1 - aH2 - theTransPers->pointZ);
-      aMoveX = (theTransPers->pointX > 0.0) ? aMoveX : -aMoveX;
-      aMoveY = (theTransPers->pointY > 0.0) ? aMoveY : -aMoveY;
-      glTranslated (aMoveX, aMoveY, 0.0);
+      // initialization failed
+      if (aFileH != NULL)
+        fclose (aFileH);
+      break;
     }
-  }
-  else if ((theTransPers->mode & TPF_PAN) != TPF_PAN)
-  {
-    // move to thePoint using saved win-coordinates ('marker-behaviour')
-    GLdouble aMoveX, aMoveY, aMoveZ;
-    glGetDoublev (GL_MODELVIEW_MATRIX,  (GLdouble* )aModelMatrix);
-    glGetDoublev (GL_PROJECTION_MATRIX, (GLdouble* )aProjMatrix);
-    gluUnProject (aWinX, aWinY, aWinZ,
-                  (GLdouble* )aModelMatrix, (GLdouble* )aProjMatrix, aViewport,
-                  &aMoveX, &aMoveY, &aMoveZ);
+    Redraw();
 
-    glMatrixMode (GL_MODELVIEW);
-    glTranslated (aMoveX, aMoveY, aMoveZ);
-  }
+    anErrCode = gl2psEndPage();
+    if (aFileH != NULL)
+      fclose (aFileH);
 
-  // Note: the approach of accessing OpenGl matrices is used now since the matrix
-  // manipulation are made with help of OpenGl methods. This might be replaced by
-  // direct computation of matrices by OCC subroutines.
-  Tmatrix3 aResultWorldView;
-  glGetFloatv (GL_MODELVIEW_MATRIX, *aResultWorldView);
+    if (anErrCode == GL2PS_OVERFLOW)
+      aBufferSize *= 2;
+    else
+      break;
+  }
+  return anErrCode == GL2PS_SUCCESS;
+}
+#else
+Standard_Boolean OpenGl_View::Export (const Standard_CString /*theFileName*/,
+                                      const Graphic3d_ExportFormat /*theFormat*/,
+                                      const Graphic3d_SortType /*theSortType*/)
+{
+    return Standard_False;
+}
+#endif
 
-  Tmatrix3 aResultProjection;
-  glGetFloatv (GL_PROJECTION_MATRIX, *aResultProjection);
+//=======================================================================
+//function : displayStructure
+//purpose  :
+//=======================================================================
+void OpenGl_View::displayStructure (const Handle(Graphic3d_CStructure)& theStructure,
+                                    const Standard_Integer              thePriority)
+{
+  const OpenGl_Structure*  aStruct = reinterpret_cast<const OpenGl_Structure*> (theStructure.operator->());
+  const Graphic3d_ZLayerId aZLayer = aStruct->ZLayer();
+  myZLayers.AddStructure (aStruct, aZLayer, thePriority);
+}
 
-  // Set OCCT state uniform variables
-  theCtx->ShaderManager()->UpdateWorldViewStateTo (&aResultWorldView);
-  theCtx->ShaderManager()->UpdateProjectionStateTo (&aResultProjection);
+//=======================================================================
+//function : eraseStructure
+//purpose  :
+//=======================================================================
+void OpenGl_View::eraseStructure (const Handle(Graphic3d_CStructure)& theStructure)
+{
+  const OpenGl_Structure*  aStruct = reinterpret_cast<const OpenGl_Structure*> (theStructure.operator->());
+  myZLayers.RemoveStructure (aStruct);
+}
 
-  return aTransPersPrev;
+//=======================================================================
+//function : changeZLayer
+//purpose  :
+//=======================================================================
+void OpenGl_View::changeZLayer (const Handle(Graphic3d_CStructure)& theStructure,
+                                const Graphic3d_ZLayerId theNewLayerId)
+{
+  const Graphic3d_ZLayerId anOldLayer = theStructure->ZLayer();
+  const OpenGl_Structure* aStruct = reinterpret_cast<const OpenGl_Structure*> (theStructure.operator->());
+  myZLayers.ChangeLayer (aStruct, anOldLayer, theNewLayerId);
+  Update (anOldLayer);
+  Update (theNewLayerId);
 }
 
-/*----------------------------------------------------------------------*/
+//=======================================================================
+//function : changePriority
+//purpose  :
+//=======================================================================
+void OpenGl_View::changePriority (const Handle(Graphic3d_CStructure)& theStructure,
+                                  const Standard_Integer theNewPriority)
+{
+  const Graphic3d_ZLayerId aLayerId = theStructure->ZLayer();
+  const OpenGl_Structure* aStruct = reinterpret_cast<const OpenGl_Structure*> (theStructure.operator->());
+  myZLayers.ChangePriority (aStruct, aLayerId, theNewPriority);
+}
 
-void OpenGl_View::GetMatrices (TColStd_Array2OfReal&  theMatOrient,
-                               TColStd_Array2OfReal&  theMatMapping) const
+//=======================================================================
+//function : DiagnosticInformation
+//purpose  :
+//=======================================================================
+void OpenGl_View::DiagnosticInformation (TColStd_IndexedDataMapOfStringString& theDict,
+                                         Graphic3d_DiagnosticInfo theFlags) const
 {
-  const OpenGl_Matrix* aProj =   (const OpenGl_Matrix*) &myCamera->ProjectionMatrix();
-  const OpenGl_Matrix* aOrient = (const OpenGl_Matrix*) &myCamera->OrientationMatrix();
+  Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext();
+  if (!myWorkspace->Activate()
+   || aCtx.IsNull())
+  {
+    return;
+  }
 
-  int i, j;
-  for (i = 0; i < 4; ++i)
+  aCtx->DiagnosticInformation (theDict, theFlags);
+  if ((theFlags & Graphic3d_DiagnosticInfo_FrameBuffer) != 0)
   {
-    for (j = 0; j < 4; ++j)
-    {
-      theMatOrient  (i, j) = aOrient->mat[j][i];
-      theMatMapping (i, j) = aProj->  mat[j][i];
-    }
+    TCollection_AsciiString aResRatio (myRenderParams.ResolutionRatio());
+    theDict.ChangeFromIndex (theDict.Add ("ResolutionRatio", aResRatio)) = aResRatio;
   }
 }
-/*----------------------------------------------------------------------*/