0031082: Visualization - crash on display if there are no lights in the view
[occt.git] / src / OpenGl / OpenGl_View.cxx
index 85c996f..4179fa2 100644 (file)
-// File:      OpenGl_View.cxx
-// Created:   20 September 2011
-// Author:    Sergey ZERCHANINOV
-// Copyright: OPEN CASCADE 2011
-
-#include <OpenGl_GlCore11.hxx>
+// 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 <OpenGl_View.hxx>
 
-#include <OpenGl_Workspace.hxx>
-#include <OpenGl_Display.hxx>
-
-#include <OpenGl_Display.hxx>
-#include <OpenGl_Trihedron.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_FrameBuffer.hxx>
+#include <OpenGl_GlCore11.hxx>
 #include <OpenGl_GraduatedTrihedron.hxx>
-
-#include <OpenGl_transform_persistence.hxx>
-
-#include <GL/glu.h> // gluUnProject()
-
-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_EXTRA_REP myDefaultExtra =
-{
-  //vrp
-  { 0.F, 0.F, 0.F },
-  //vpn
-  { 0.F, 0.F, 1.F },
-  //vup
-  { 0.F, 1.F, 0.F },
-  //map
-  {
-    //window
-    { 0.F, 0.F, 1.F, 1.F },
-    //viewport
-    { 0.F, 0.F, 0.F, 1.F, 1.F, 1.F },
-    //proj
-    TelParallel,
-    //prp
-    { 0.F, 0.F, 0.F },
-    //vpd
-    0.F,
-    //fpd
-    0.F,
-    //bpd
-    -1.F
-  },
-  //scaleFactors
-  { 1.F, 1.F, 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 };
-
-/*----------------------------------------------------------------------*/
-
-OpenGl_View::OpenGl_View (const CALL_DEF_VIEWCONTEXT &AContext)
-: myTextureEnv(0),
-  mySurfaceDetail(Visual3d_TOD_NONE),
-  myBackfacing(0),
-  myBgTexture(myDefaultBgTexture),
-  myBgGradient(myDefaultBgGradient),
-  //myOrientationMatrix(myDefaultMatrix),
-  //myMappingMatrix(myDefaultMatrix),
-  //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),
-  myExtra(myDefaultExtra),
-  myFog(myDefaultFog),
-  myVisualization(AContext.Visualization),
-  myIntShadingMethod(TEL_SM_GOURAUD),
-  myAntiAliasing(Standard_False),
-  myAnimationListIndex(0),
-  myAnimationListReady(Standard_False),
-  myTransPers(&myDefaultTransPers),
-  myIsTransPers(Standard_False),
-  myResetFLIST(Standard_False)
+#include <OpenGl_GraphicDriver.hxx>
+#include <OpenGl_ShaderManager.hxx>
+#include <OpenGl_Texture.hxx>
+#include <OpenGl_Window.hxx>
+#include <OpenGl_Workspace.hxx>
+#include <OSD_Parallel.hxx>
+#include <Standard_CLocaleSentry.hxx>
+
+#include "../Graphic3d/Graphic3d_Structure.pxx"
+
+IMPLEMENT_STANDARD_RTTIEXT(OpenGl_View,Graphic3d_CView)
+
+// =======================================================================
+// 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),
+  myBackfacing     (Graphic3d_TOBM_AUTOMATIC),
+  myToShowGradTrihedron  (false),
+  myZLayers        (Structure_MAX_PRIORITY - Structure_MIN_PRIORITY + 1),
+  myStateCounter         (theCounter),
+  myCurrLightSourceState (theCounter->Increment()),
+  myLightsRevision       (0),
+  myLastLightSourceState (0, 0),
+  mySRgbState            (-1),
+  myFboColorFormat       (GL_SRGB8_ALPHA8), // note that GL_SRGB8 is not required to be renderable, unlike GL_RGB8, GL_RGBA8, GL_SRGB8_ALPHA8
+  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_Aspects()),
+  myCubeMapParams   (new OpenGl_Aspects()),
+  myBackgroundType  (Graphic3d_TOB_NONE),
+  // 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)
 {
-  // Initialize matrices
-  memcpy(myOrientationMatrix,myDefaultMatrix,sizeof(Tmatrix3));
-  memcpy(myMappingMatrix,myDefaultMatrix,sizeof(Tmatrix3));
-
-  // Shading method
-  switch (AContext.Model)
+  for (int i = 0; i < Graphic3d_TypeOfBackground_NB; ++i)
   {
-    case 1 : /* VISUAL3D_TOM_INTERP_COLOR */
-    case 3 : /* VISUAL3D_TOM_VERTEX */
-      myIntShadingMethod = TEL_SM_GOURAUD;
-      break;
-    default :
-      myIntShadingMethod = TEL_SM_FLAT;
-      break;
+    myBackgrounds[i] = new OpenGl_BackgroundArray(Graphic3d_TypeOfBackground(i));
   }
-}
 
-/*----------------------------------------------------------------------*/
+  myWorkspace = new OpenGl_Workspace (this, NULL);
+
+  Handle(Graphic3d_CLight) aLight = new Graphic3d_CLight (Graphic3d_TOLS_AMBIENT);
+  aLight->SetHeadlight (false);
+  aLight->SetColor (Quantity_NOC_WHITE);
+  myLights = new Graphic3d_LightSet();
+  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()
 {
-  if (myAnimationListIndex)
-    glDeleteLists((GLuint)myAnimationListIndex,1);
+  ReleaseGlResources (NULL); // ensure ReleaseGlResources() was called within valid context
+  for (int i = 0; i < Graphic3d_TypeOfBackground_NB; ++i)
+  {
+    OpenGl_Element::Destroy(NULL, myBackgrounds[i]);
+  }
 
-  if ( myBgTexture.TexId != 0 )
-    glDeleteTextures( 1, (GLuint*)&(myBgTexture.TexId) );
+  OpenGl_Element::Destroy (NULL, myTextureParams);
+  OpenGl_Element::Destroy (NULL, myCubeMapParams);
 }
 
-/*----------------------------------------------------------------------*/
-
-void OpenGl_View::SetBackfacing (const Standard_Integer AMode)
-{
-  myBackfacing = AMode;
-  myResetFLIST = Standard_True;
-}
-
-/*----------------------------------------------------------------------*/
-
-//call_togl_setlight
-void OpenGl_View::SetLights (const CALL_DEF_VIEWCONTEXT &AContext)
-{
-  myLights.Clear();
-
-  const int nb_lights = AContext.NbActiveLight;
-
-  int i = 0;
-  const CALL_DEF_LIGHT *alight = &(AContext.ActiveLight[0]);
-  for ( ; i < nb_lights; i++, alight++ )
-  {
-    OpenGl_Light rep;
+// =======================================================================
+// function : releaseSrgbResources
+// purpose  :
+// =======================================================================
+void OpenGl_View::releaseSrgbResources (const Handle(OpenGl_Context)& theCtx)
+{
+  myRenderParams.RebuildRayTracingShaders = true;
 
-       switch( alight->LightType )
+  if (!myTextureEnv.IsNull())
+  {
+    if (!theCtx.IsNull())
     {
-      case 0 : /* TOLS_AMBIENT */
-        rep.type = TLightAmbient;
-        rep.col.rgb[0] = alight->Color.r;
-        rep.col.rgb[1] = alight->Color.g;
-        rep.col.rgb[2] = alight->Color.b;
-        break;
-
-      case 1 : /* TOLS_DIRECTIONAL */
-        rep.type = TLightDirectional;
-        rep.col.rgb[0] = alight->Color.r;
-        rep.col.rgb[1] = alight->Color.g;
-        rep.col.rgb[2] = alight->Color.b;
-        rep.dir[0] = alight->Direction.x;
-        rep.dir[1] = alight->Direction.y;
-        rep.dir[2] = alight->Direction.z;
-        break;
-
-      case 2 : /* TOLS_POSITIONAL */
-        rep.type = TLightPositional;
-        rep.col.rgb[0] = alight->Color.r;
-        rep.col.rgb[1] = alight->Color.g;
-        rep.col.rgb[2] = alight->Color.b;
-        rep.pos[0] = alight->Position.x;
-        rep.pos[1] = alight->Position.y;
-        rep.pos[2] = alight->Position.z;
-        rep.atten[0] = alight->Attenuation[0];
-        rep.atten[1] = alight->Attenuation[1];
-        break;
-
-      case 3 : /* TOLS_SPOT */
-        rep.type = TLightSpot;
-        rep.col.rgb[0] = alight->Color.r;
-        rep.col.rgb[1] = alight->Color.g;
-        rep.col.rgb[2] = alight->Color.b;
-        rep.pos[0] = alight->Position.x;
-        rep.pos[1] = alight->Position.y;
-        rep.pos[2] = alight->Position.z;
-        rep.dir[0] = alight->Direction.x;
-        rep.dir[1] = alight->Direction.y;
-        rep.dir[2] = alight->Direction.z;
-        rep.shine = alight->Concentration;
-        rep.atten[0] = alight->Attenuation[0];
-        rep.atten[1] = alight->Attenuation[1];
-        rep.angle = alight->Angle;
-        break;
+      for (OpenGl_TextureSet::Iterator aTextureIter (myTextureEnv); aTextureIter.More(); aTextureIter.Next())
+      {
+        theCtx->DelayedRelease (aTextureIter.ChangeValue());
+        aTextureIter.ChangeValue().Nullify();
+      }
     }
+    myTextureEnv.Nullify();
+  }
 
-    rep.HeadLight = alight->Headlight;
-
-    myLights.Append(rep);
+  if (myTextureParams != NULL)
+  {
+    myTextureParams->Release (theCtx.get());
   }
-}
 
-/*----------------------------------------------------------------------*/
+  if (myCubeMapParams != NULL)
+  {
+    myCubeMapParams->Release (theCtx.get());
+  }
 
-//call_togl_setplane
-void OpenGl_View::SetClippingPlanes (const CALL_DEF_VIEWCONTEXT &AContext)
-{
-  // clear clipping planes information
-  myClippingPlanes.Clear();
-  // update information 
-  int i = 0;
-  for (; i < AContext.NbActivePlane; i++)
+  for (int i = 0; i < Graphic3d_TypeOfBackground_NB; ++i)
   {
-    const CALL_DEF_PLANE &aCPlane = AContext.ActivePlane[i];
-    if ( aCPlane.Active && aCPlane.PlaneId > 0 )
+    if (myBackgrounds[i] != NULL)
     {
-      OPENGL_CLIP_REP aPlane;
-      aPlane.equation[0] = aCPlane.CoefA;
-      aPlane.equation[1] = aCPlane.CoefB;
-      aPlane.equation[2] = aCPlane.CoefC;
-      aPlane.equation[3] = aCPlane.CoefD;
-      myClippingPlanes.Append( aPlane );
+      myBackgrounds[i]->Release (theCtx.get());
     }
   }
+
+  myMainSceneFbos[0]        ->Release (theCtx.get());
+  myMainSceneFbos[1]        ->Release (theCtx.get());
+  myMainSceneFbosOit[0]     ->Release (theCtx.get());
+  myMainSceneFbosOit[1]     ->Release (theCtx.get());
+  myImmediateSceneFbos[0]   ->Release (theCtx.get());
+  myImmediateSceneFbos[1]   ->Release (theCtx.get());
+  myImmediateSceneFbosOit[0]->Release (theCtx.get());
+  myImmediateSceneFbosOit[1]->Release (theCtx.get());
+  myOpenGlFBO               ->Release (theCtx.get());
+  myOpenGlFBO2              ->Release (theCtx.get());
+  myFullScreenQuad           .Release (theCtx.get());
+  myFullScreenQuadFlip       .Release (theCtx.get());
+
+  // Technically we should also re-initialize all sRGB/RGB8 color textures.
+  // But for now consider this sRGB disabling/enabling to be done at application start-up
+  // and re-create dynamically only frame buffers.
 }
 
-/*----------------------------------------------------------------------*/
+// =======================================================================
+// function : ReleaseGlResources
+// purpose  :
+// =======================================================================
+void OpenGl_View::ReleaseGlResources (const Handle(OpenGl_Context)& theCtx)
+{
+  myGraduatedTrihedron.Release (theCtx.get());
+  myFrameStatsPrs.Release (theCtx.get());
 
-//call_togl_setvisualisation
-void OpenGl_View::SetVisualisation (const CALL_DEF_VIEWCONTEXT &AContext)
+  releaseSrgbResources (theCtx);
+
+  releaseRaytraceResources (theCtx);
+}
+
+// =======================================================================
+// function : Remove
+// purpose  :
+// =======================================================================
+void OpenGl_View::Remove()
 {
-  myVisualization = AContext.Visualization;
-  // Shading method
-  switch (AContext.Model)
+  if (IsRemoved())
   {
-    case 1 : /* VISUAL3D_TOM_INTERP_COLOR */
-    case 3 : /* VISUAL3D_TOM_VERTEX */
-      myIntShadingMethod = TEL_SM_GOURAUD;
-      break;
-    default :
-      myIntShadingMethod = TEL_SM_FLAT;
-      break;
+    return;
   }
-}
 
-/*----------------------------------------------------------------------*/
+  myDriver->RemoveView (this);
+  myWindow.Nullify();
+
+  Graphic3d_CView::Remove();
+}
 
-//call_togl_cliplimit
-void OpenGl_View::SetClipLimit (const CALL_DEF_VIEW &ACView)
+// =======================================================================
+// function : SetLocalOrigin
+// purpose  :
+// =======================================================================
+void OpenGl_View::SetLocalOrigin (const gp_XYZ& theOrigin)
 {
-  myZClip.Back.Limit =
-    ( ACView.Context.ZClipBackPlane - ACView.Mapping.BackPlaneDistance ) /
-    ( ACView.Mapping.FrontPlaneDistance - ACView.Mapping.BackPlaneDistance );
-  myZClip.Front.Limit =
-    ( ACView.Context.ZClipFrontPlane - ACView.Mapping.BackPlaneDistance ) /
-    ( ACView.Mapping.FrontPlaneDistance - ACView.Mapping.BackPlaneDistance );
-  if ( myZClip.Back.Limit < 0.F )
-    myZClip.Back.Limit = 0.F;
-  if ( myZClip.Front.Limit > 1.F )
-    myZClip.Front.Limit = 1.F;
-  if ( myZClip.Back.Limit > myZClip.Front.Limit )
+  myLocalOrigin = theOrigin;
+  const Handle(OpenGl_Context)& aCtx = myWorkspace->GetGlContext();
+  if (!aCtx.IsNull())
   {
-    myZClip.Back.Limit = 0.F;
-    myZClip.Front.Limit = 1.F;
+    aCtx->ShaderManager()->SetLocalOrigin (theOrigin);
   }
-
-  myZClip.Back.IsOn = (ACView.Context.BackZClipping != 0);
-  myZClip.Front.IsOn = (ACView.Context.FrontZClipping != 0);
 }
 
-/*----------------------------------------------------------------------*/
-
-//call_togl_viewmapping
-void OpenGl_View::SetMapping (const CALL_DEF_VIEW &ACView)
+// =======================================================================
+// function : SetTextureEnv
+// purpose  :
+// =======================================================================
+void OpenGl_View::SetTextureEnv (const Handle(Graphic3d_TextureEnv)& theTextureEnv)
 {
-  const float ratio = ACView.DefWindow.dy / ACView.DefWindow.dx;
-  const float r_ratio = ACView.DefWindow.dx / ACView.DefWindow.dy;
-
-  TEL_VIEW_MAPPING Map;
+  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();
+    }
+  }
 
-  Map.window.xmin = ACView.Mapping.WindowLimit.um;
-  Map.window.ymin = ACView.Mapping.WindowLimit.vm;
-  Map.window.xmax = ACView.Mapping.WindowLimit.uM;
-  Map.window.ymax = ACView.Mapping.WindowLimit.vM;
+  myToUpdateEnvironmentMap = Standard_True;
+  myTextureEnvData = theTextureEnv;
+  myTextureEnv.Nullify();
+  initTextureEnv (aCtx);
+}
 
-  Map.viewport.xmin = 0.F;
-  Map.viewport.xmax = ( 1.F < r_ratio ? 1.F : r_ratio );
-  Map.viewport.ymin = 0.F;
-  Map.viewport.ymax = ( 1.F < ratio ? 1.F : ratio );
-  Map.viewport.zmin = 0.F;
-  Map.viewport.zmax = 1.F;
+// =======================================================================
+// function : initTextureEnv
+// purpose  :
+// =======================================================================
+void OpenGl_View::initTextureEnv (const Handle(OpenGl_Context)& theContext)
+{
+  if (myTextureEnvData.IsNull()
+    ||  theContext.IsNull()
+    || !theContext->MakeCurrent())
+  {
+    return;
+  }
 
-  /* projection type */
-  switch( ACView.Mapping.Projection )
+  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())
   {
-    case 0 :
-      Map.proj = TelPerspective;
-      break;
-    case 1 :
-      Map.proj = TelParallel;
-      break;
+    aTextureEnv->Init (theContext, *anImage, myTextureEnvData->Type(), true);
   }
+}
 
-  /* projection reference point */
-  Map.prp[0] = ACView.Mapping.ProjectionReferencePoint.x;
-  Map.prp[1] = ACView.Mapping.ProjectionReferencePoint.y;
-  Map.prp[2] = ACView.Mapping.ProjectionReferencePoint.z;
-  if (!openglDisplay.IsNull() && !openglDisplay->Walkthrough())
-    Map.prp[2] += ACView.Mapping.FrontPlaneDistance;
+// =======================================================================
+// function : SetImmediateModeDrawToFront
+// purpose  :
+// =======================================================================
+Standard_Boolean OpenGl_View::SetImmediateModeDrawToFront (const Standard_Boolean theDrawToFrontBuffer)
+{
+  const Standard_Boolean aPrevMode = myTransientDrawToFront;
+  myTransientDrawToFront = theDrawToFrontBuffer;
+  return aPrevMode;
+}
 
-  /* view plane distance */
-  Map.vpd = ACView.Mapping.ViewPlaneDistance;
+// =======================================================================
+// 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());
+}
 
-  /* back plane distance */
-  Map.bpd = ACView.Mapping.BackPlaneDistance;
+// =======================================================================
+// function : Resized
+// purpose  :
+// =======================================================================
+void OpenGl_View::Resized()
+{
+  if (myWindow.IsNull())
+    return;
 
-  /* front plane distance */
-  Map.fpd = ACView.Mapping.FrontPlaneDistance;
+  myWindow->Resize();
+}
 
-  Tint err_ind = 0;
+// =======================================================================
+// function : SetMinMaxValuesCallback
+// purpose  :
+// =======================================================================
+static void SetMinMaxValuesCallback (Graphic3d_CView* theView)
+{
+  OpenGl_View* aView = dynamic_cast<OpenGl_View*>(theView);
+  if (aView == NULL)
+    return;
 
-  /* use user-defined matrix */
-  if ( ACView.Mapping.IsCustomMatrix )
+  Bnd_Box aBox = theView->MinMaxValues();
+  if (!aBox.IsVoid())
   {
-    int i, j;
-    for( i = 0; i < 4; i++ )
-      for( j = 0; j < 4; j++ )
-        myMappingMatrix[i][j] = ACView.Mapping.ProjectionMatrix[i][j];
-  }
-  else 
-    TelEvalViewMappingMatrix( &Map, &err_ind, myMappingMatrix );
+    gp_Pnt aMin = aBox.CornerMin();
+    gp_Pnt aMax = aBox.CornerMax();
 
-  if ( !err_ind )
-    myExtra.map = Map;
+    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_vieworientation
-void OpenGl_View::SetOrientation (const CALL_DEF_VIEW &ACView)
+// =======================================================================
+// function : GraduatedTrihedronDisplay
+// purpose  :
+// =======================================================================
+void OpenGl_View::GraduatedTrihedronDisplay (const Graphic3d_GraduatedTrihedron& theTrihedronData)
 {
-  Tfloat Vrp[3];
-  Tfloat Vpn[3];
-  Tfloat Vup[3];
-  Tfloat ScaleFactors[3];
+  myGTrihedronData = theTrihedronData;
+  myGTrihedronData.PtrView = this;
+  myGTrihedronData.CubicAxesCallback = SetMinMaxValuesCallback;
+  myGraduatedTrihedron.SetValues (myGTrihedronData);
+  myToShowGradTrihedron = true;
+}
 
-  Vrp[0] = ACView.Orientation.ViewReferencePoint.x;
-  Vrp[1] = ACView.Orientation.ViewReferencePoint.y;
-  Vrp[2] = ACView.Orientation.ViewReferencePoint.z;
+// =======================================================================
+// function : GraduatedTrihedronErase
+// purpose  :
+// =======================================================================
+void OpenGl_View::GraduatedTrihedronErase()
+{
+  myGTrihedronData.PtrView = NULL;
+  myGraduatedTrihedron.Release (myWorkspace->GetGlContext().operator->());
+  myToShowGradTrihedron = false;
+}
 
-  Vpn[0] = ACView.Orientation.ViewReferencePlane.x;
-  Vpn[1] = ACView.Orientation.ViewReferencePlane.y;
-  Vpn[2] = ACView.Orientation.ViewReferencePlane.z;
+// =======================================================================
+// function : GraduatedTrihedronMinMaxValues
+// purpose  :
+// =======================================================================
+void OpenGl_View::GraduatedTrihedronMinMaxValues (const Graphic3d_Vec3 theMin, const Graphic3d_Vec3 theMax)
+{
+  myGraduatedTrihedron.SetMinMax (theMin, theMax);
+}
 
-  Vup[0] = ACView.Orientation.ViewReferenceUp.x;
-  Vup[1] = ACView.Orientation.ViewReferenceUp.y;
-  Vup[2] = ACView.Orientation.ViewReferenceUp.z;
+// =======================================================================
+// function : BufferDump
+// purpose  :
+// =======================================================================
+Standard_Boolean OpenGl_View::BufferDump (Image_PixMap& theImage, const Graphic3d_BufferType& theBufferType)
+{
+  if (theBufferType != Graphic3d_BT_RGB_RayTraceHdrLeft)
+  {
+    return myWorkspace->BufferDump(myFBO, theImage, theBufferType);
+  }
 
-  ScaleFactors[0] = ACView.Orientation.ViewScaleX;
-  ScaleFactors[1] = ACView.Orientation.ViewScaleY;
-  ScaleFactors[2] = ACView.Orientation.ViewScaleZ;
+  if (!myRaytraceParameters.AdaptiveScreenSampling)
+  {
+    return myWorkspace->BufferDump(myAccumFrames % 2 ? myRaytraceFBO2[0] : myRaytraceFBO1[0], theImage, theBufferType);
+  }
 
-  Tint err_ind = 0;
+#if defined(GL_ES_VERSION_2_0)
+  return false;
+#else
+  if (theImage.Format() != Image_Format_RGBF)
+  {
+    return false;
+  }
 
-  // use user-defined matrix
-  if ( ACView.Orientation.IsCustomMatrix )
+  const GLuint aW = myRaytraceOutputTexture[0]->SizeX();
+  const GLuint aH = myRaytraceOutputTexture[0]->SizeY();
+  if (aW / 3 != theImage.SizeX() || aH / 2 != theImage.SizeY())
   {
-    int i, j;
-    for( i = 0; i < 4; i++ )
-      for( j = 0; j < 4; j++ )
-        myOrientationMatrix[i][j] = ACView.Orientation.ModelViewMatrix[i][j];
+    return false;
   }
-  else
-    TelEvalViewOrientationMatrix( Vrp, Vpn, Vup, ScaleFactors, &err_ind, myOrientationMatrix );
 
-  if ( !err_ind )
+  std::vector<GLfloat> aValues;
+  try
   {
-    myExtra.vrp[0] = Vrp[0];
-    myExtra.vrp[1] = Vrp[1];
-    myExtra.vrp[2] = Vrp[2];
+    aValues.resize (aW * aH);
+  }
+  catch (const std::bad_alloc&)
+  {
+    return false;
+  }
 
-    myExtra.vpn[0] = Vpn[0];
-    myExtra.vpn[1] = Vpn[1];
-    myExtra.vpn[2] = Vpn[2];
+  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;
+    }
+  }
 
-    myExtra.vup[0] = Vup[0];
-    myExtra.vup[1] = Vup[1];
-    myExtra.vup[2] = Vup[2];
+  return true;
+#endif
+}
 
-    myExtra.scaleFactors[0] = ScaleFactors[0],
-    myExtra.scaleFactors[1] = ScaleFactors[1],
-    myExtra.scaleFactors[2] = ScaleFactors[2];
-  }
+// =======================================================================
+// function : GradientBackground
+// purpose  :
+// =======================================================================
+Aspect_GradientBackground OpenGl_View::GradientBackground() const
+{
+  Quantity_Color aColor1, aColor2;
+  aColor1.SetValues (myBackgrounds[Graphic3d_TOB_GRADIENT]->GradientColor (0).r(),
+                     myBackgrounds[Graphic3d_TOB_GRADIENT]->GradientColor (0).g(),
+                     myBackgrounds[Graphic3d_TOB_GRADIENT]->GradientColor (0).b(), Quantity_TOC_RGB);
+  aColor2.SetValues (myBackgrounds[Graphic3d_TOB_GRADIENT]->GradientColor (1).r(),
+                     myBackgrounds[Graphic3d_TOB_GRADIENT]->GradientColor (1).g(),
+                     myBackgrounds[Graphic3d_TOB_GRADIENT]->GradientColor (1).b(), Quantity_TOC_RGB);
+  return Aspect_GradientBackground (aColor1, aColor2, myBackgrounds[Graphic3d_TOB_GRADIENT]->GradientFillMethod());
 }
 
-/*----------------------------------------------------------------------*/
+// =======================================================================
+// function : SetGradientBackground
+// purpose  :
+// =======================================================================
+void OpenGl_View::SetGradientBackground (const Aspect_GradientBackground& theBackground)
+{
+  Quantity_Color aColor1, aColor2;
+  theBackground.Colors (aColor1, aColor2);
+  myBackgrounds[Graphic3d_TOB_GRADIENT]->SetGradientParameters (aColor1, aColor2, theBackground.BgGradientFillMethod());
+
+  myBackgroundType = Graphic3d_TOB_GRADIENT;
+}
 
-void OpenGl_View::SetFog (const CALL_DEF_VIEW &ACView, const Standard_Boolean AFlag)
+// =======================================================================
+// function : SetBackgroundImage
+// purpose  :
+// =======================================================================
+void OpenGl_View::SetBackgroundImage (const TCollection_AsciiString& theFilePath)
 {
-  if( !AFlag )
+  // 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())
   {
-    myFog.IsOn = Standard_False;
+    anAspect->SetTextureMapOn();
   }
   else
   {
-    myFog.IsOn = Standard_True;
+    anAspect->SetTextureMapOff();
+    return;
+  }
+
+  // Set texture parameters
+  myTextureParams->SetAspect (anAspect);
 
-    myFog.Front =
-      (ACView.Context.DepthFrontPlane - ACView.Mapping.BackPlaneDistance) /
-      (ACView.Mapping.FrontPlaneDistance - ACView.Mapping.BackPlaneDistance);
+  myBackgroundType = Graphic3d_TOB_TEXTURE;
+}
+
+// =======================================================================
+// function : BackgroundImageStyle
+// purpose  :
+// =======================================================================
+Aspect_FillMethod OpenGl_View::BackgroundImageStyle() const
+{
+  return myBackgrounds[Graphic3d_TOB_TEXTURE]->TextureFillMethod();
+}
 
-    myFog.Back =
-      (ACView.Context.DepthBackPlane - ACView.Mapping.BackPlaneDistance) /
-      (ACView.Mapping.FrontPlaneDistance - ACView.Mapping.BackPlaneDistance);
+// =======================================================================
+// function : SetBackgroundImageStyle
+// purpose  :
+// =======================================================================
+void OpenGl_View::SetBackgroundImageStyle (const Aspect_FillMethod theFillStyle)
+{
+  myBackgrounds[Graphic3d_TOB_TEXTURE]->SetTextureFillMethod (theFillStyle);
+}
 
-    if (myFog.Front < 0.F)
-      myFog.Front = 0.F;
-    else if (myFog.Front > 1.F)
-      myFog.Front = 1.F;
+// =======================================================================
+// function : BackgroundCubeMap
+// purpose  :
+// =======================================================================
+Handle(Graphic3d_CubeMap) OpenGl_View::BackgroundCubeMap() const
+{
+  return myBackgroundCubeMap;
+}
+// =======================================================================
+// function : SetBackgroundCubeMap
+// purpose  :
+// =======================================================================
+void OpenGl_View::SetBackgroundCubeMap (const Handle(Graphic3d_CubeMap)& theCubeMap)
+{
+  myBackgroundCubeMap = theCubeMap;
+  Handle(Graphic3d_AspectFillArea3d) anAspect = new Graphic3d_AspectFillArea3d;
+  Handle(Graphic3d_TextureSet) aTextureSet = new Graphic3d_TextureSet (myBackgroundCubeMap);
 
-    if (myFog.Back < 0.F)
-      myFog.Back = 0.F;
-    else if (myFog.Back > 1.F)
-      myFog.Back = 1.F;
+  anAspect->SetInteriorStyle(Aspect_IS_SOLID);
+  anAspect->SetSuppressBackFaces(false);
+  anAspect->SetTextureSet(aTextureSet);
 
-    if (myFog.Back > myFog.Front)
-    {
-      myFog.Front = 1.F;
-      myFog.Back = 0.F;
-    }
+  const Handle(OpenGl_Context)& aCtx = myWorkspace->GetGlContext();
+  if (!aCtx.IsNull())
+  {
+    anAspect->SetShaderProgram (aCtx->ShaderManager()->GetBgCubeMapProgram());
+  }
 
-    myFog.Color.rgb[0] = ACView.DefWindow.Background.r;
-    myFog.Color.rgb[1] = ACView.DefWindow.Background.g;
-    myFog.Color.rgb[2] = ACView.DefWindow.Background.b;
-    myFog.Color.rgb[3] = 1.F;
+  if (theCubeMap->IsDone())
+  {
+    anAspect->SetTextureMapOn();
+  }
+  else
+  {
+    anAspect->SetTextureMapOff();
   }
-}
 
-/*----------------------------------------------------------------------*/
+  myCubeMapParams->SetAspect(anAspect);
+  const OpenGl_Aspects* anAspectsBackup = myWorkspace->SetAspects (myCubeMapParams);
+  myWorkspace->ApplyAspects();
+  myWorkspace->SetAspects (anAspectsBackup);
+  myWorkspace->ApplyAspects();
 
-void OpenGl_View::TriedronDisplay (const Aspect_TypeOfTriedronPosition APosition, const Quantity_NameOfColor AColor,
-                                  const Standard_Real AScale, const Standard_Boolean AsWireframe)
-{
-  myTrihedron = new OpenGl_Trihedron (APosition, AColor, AScale, AsWireframe);
+  myBackgroundType = Graphic3d_TOB_CUBEMAP;
 }
 
-/*----------------------------------------------------------------------*/
-
-void OpenGl_View::TriedronErase ()
+//=======================================================================
+//function : InsertLayerBefore
+//purpose  :
+//=======================================================================
+void OpenGl_View::InsertLayerBefore (const Graphic3d_ZLayerId theLayerId,
+  const Graphic3d_ZLayerSettings& theSettings,
+  const Graphic3d_ZLayerId theLayerAfter)
 {
-  myTrihedron.Nullify();
+  myZLayers.InsertLayerBefore (theLayerId, theSettings, theLayerAfter);
 }
 
-/*----------------------------------------------------------------------*/
-
-void OpenGl_View::GraduatedTrihedronDisplay (const Graphic3d_CGraduatedTrihedron &data)
+//=======================================================================
+//function : InsertLayerAfter
+//purpose  :
+//=======================================================================
+void OpenGl_View::InsertLayerAfter (const Graphic3d_ZLayerId theLayerId,
+  const Graphic3d_ZLayerSettings& theSettings,
+  const Graphic3d_ZLayerId theLayerBefore)
 {
-  myGraduatedTrihedron = new OpenGl_GraduatedTrihedron(data);
+  myZLayers.InsertLayerAfter (theLayerId, theSettings, theLayerBefore);
 }
 
-/*----------------------------------------------------------------------*/
-
-void OpenGl_View::GraduatedTrihedronErase ()
+//=======================================================================
+//function : RemoveZLayer
+//purpose  :
+//=======================================================================
+void OpenGl_View::RemoveZLayer (const Graphic3d_ZLayerId theLayerId)
 {
-  myGraduatedTrihedron.Nullify();
+  myZLayers.RemoveLayer (theLayerId);
 }
 
-/*----------------------------------------------------------------------*/
+//=======================================================================
+//function : SetZLayerSettings
+//purpose  :
+//=======================================================================
+void OpenGl_View::SetZLayerSettings (const Graphic3d_ZLayerId        theLayerId,
+                                     const Graphic3d_ZLayerSettings& theSettings)
+{
+  myZLayers.SetLayerSettings (theLayerId, theSettings);
+}
 
-//transform_persistence_end
-void OpenGl_View::EndTransformPersistence ()
+//=======================================================================
+//function : ZLayerMax
+//purpose  :
+//=======================================================================
+Standard_Integer OpenGl_View::ZLayerMax() const
 {
-  if ( myIsTransPers )
+  Standard_Integer aLayerMax = Graphic3d_ZLayerId_Default;
+  for (NCollection_List<Handle(Graphic3d_Layer)>::Iterator aLayerIter (myZLayers.Layers()); aLayerIter.More(); aLayerIter.Next())
   {
-    /* restore matrix */
-    glMatrixMode (GL_PROJECTION);
-    glPopMatrix ();
-    glMatrixMode (GL_MODELVIEW);
-    glPopMatrix ();
-    myIsTransPers = Standard_False;
+    aLayerMax = Max (aLayerMax, aLayerIter.Value()->LayerId());
   }
-} 
-
-/*----------------------------------------------------------------------*/
+  return aLayerMax;
+}
 
-//transform_persistence_begin
-const TEL_TRANSFORM_PERSISTENCE * OpenGl_View::BeginTransformPersistence (const TEL_TRANSFORM_PERSISTENCE *ATransPers)
+//=======================================================================
+//function : Layers
+//purpose  :
+//=======================================================================
+const NCollection_List<Handle(Graphic3d_Layer)>& OpenGl_View::Layers() const
 {
-  const TEL_TRANSFORM_PERSISTENCE *TransPers_old = myTransPers;
+  return myZLayers.Layers();
+}
 
-  if ( ATransPers->mode == 0 )
+//=======================================================================
+//function : Layer
+//purpose  :
+//=======================================================================
+Handle(Graphic3d_Layer) OpenGl_View::Layer (const Graphic3d_ZLayerId theLayerId) const
+{
+  Handle(Graphic3d_Layer) aLayer;
+  if (theLayerId != Graphic3d_ZLayerId_UNKNOWN)
   {
-    EndTransformPersistence();
-    return TransPers_old;
+    myZLayers.LayerIDs().Find (theLayerId, aLayer);
   }
+  return aLayer;
+}
 
-  myTransPers = ATransPers;
-
-  GLint viewport[4];
-  glGetIntegerv (GL_VIEWPORT, viewport);
-  GLdouble modelMatrix[4][4];
-  glGetDoublev( GL_MODELVIEW_MATRIX,  (GLdouble *) modelMatrix );
-  GLdouble projMatrix[4][4];
-  glGetDoublev( GL_PROJECTION_MATRIX, (GLdouble *) projMatrix );
-
-  double W = viewport[2];
-  double H = viewport[3];
-
-  if ( myIsTransPers )
+//=======================================================================
+//function : MinMaxValues
+//purpose  :
+//=======================================================================
+Bnd_Box OpenGl_View::MinMaxValues (const Standard_Boolean theToIncludeAuxiliary) const
+{
+  if (!IsDefined())
   {
-    /* restore matrix */
-    glMatrixMode (GL_PROJECTION);
-    glPopMatrix ();
-    glMatrixMode (GL_MODELVIEW);
-    glPopMatrix ();
+    return Bnd_Box();
   }
-  else
-    myIsTransPers = Standard_True;
 
-  glMatrixMode( GL_MODELVIEW );
-  glPushMatrix();
-  glLoadIdentity();
+  Bnd_Box aBox = base_type::MinMaxValues (theToIncludeAuxiliary);
 
-  glMatrixMode( GL_PROJECTION );
-  glPushMatrix();
-  glLoadIdentity();
-
-  /*pre loading matrix*/
-  if( ATransPers->mode & TPF_PAN )
-    /* Annulate translate matrix */
+  // add bounding box of gradient/texture background for proper Z-fit
+  if (theToIncludeAuxiliary
+    && (myBackgrounds[Graphic3d_TOB_TEXTURE]->IsDefined()
+     || myBackgrounds[Graphic3d_TOB_GRADIENT]->IsDefined()))
   {
-    modelMatrix[3][0] = 0.;
-    modelMatrix[3][1] = 0.;
-    modelMatrix[3][2] = 0.;
-    projMatrix[3][0] = 0.;
-    projMatrix[3][1] = 0.;
-    projMatrix[3][2] = 0.;
+    const Handle(Graphic3d_Camera)& aCamera = Camera();
+    Graphic3d_Vec2i aWinSize;
+    Window()->Size (aWinSize.x(), aWinSize.y());
+
+    // 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 = aCamera->ProjectionMatrix();
+    const Graphic3d_Mat4d& aWorldViewMat  = aCamera->OrientationMatrix();
+    Graphic3d_BndBox3d aBox2d (Graphic3d_Vec3d (0.0, 0.0, 0.0),
+                               Graphic3d_Vec3d (double(aWinSize.x()), double(aWinSize.y()), 0.0));
+
+    Graphic3d_TransformPers aTrsfPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_LOWER);
+    aTrsfPers.Apply (aCamera,
+                     aProjectionMat,
+                     aWorldViewMat,
+                     aWinSize.x(),
+                     aWinSize.y(),
+                     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()));
   }
 
-  if( ATransPers->mode & TPF_ZOOM )
-    /* Annulate zoom matrix */
-  {
-    const double scaleX = myExtra.scaleFactors[0];
-    const double scaleY = myExtra.scaleFactors[1];
-    const double scaleZ = myExtra.scaleFactors[2];
+  return aBox;
+}
 
-    for (int i = 0; i < 3; ++i)
-    {
-      modelMatrix[0][i] /= scaleX;
-      modelMatrix[1][i] /= scaleY;
-      modelMatrix[2][i] /= scaleZ;
-    }
+//=======================================================================
+//function : FBO
+//purpose  :
+//=======================================================================
+Handle(Standard_Transient) OpenGl_View::FBO() const
+{
+  return Handle(Standard_Transient)(myFBO);
+}
 
-    const double det2 = 0.002 / ( W > H ? projMatrix[1][1] : projMatrix[0][0]);
-    projMatrix[0][0] *= det2;
-    projMatrix[1][1] *= det2;
-  }
+//=======================================================================
+//function : SetFBO
+//purpose  :
+//=======================================================================
+void OpenGl_View::SetFBO (const Handle(Standard_Transient)& theFbo)
+{
+  myFBO = Handle(OpenGl_FrameBuffer)::DownCast (theFbo);
+}
 
-  if( ATransPers->mode & TPF_ROTATE )
-    /* Annulate rotate matrix */
-  {
-    modelMatrix[0][0] = 1.;
-    modelMatrix[1][1] = 1.;
-    modelMatrix[2][2] = 1.;
+//=======================================================================
+//function : FBOCreate
+//purpose  :
+//=======================================================================
+Handle(Standard_Transient) OpenGl_View::FBOCreate (const Standard_Integer theWidth,
+                                                   const Standard_Integer theHeight)
+{
+  return myWorkspace->FBOCreate (theWidth, theHeight);
+}
 
-    modelMatrix[1][0] = 0.;
-    modelMatrix[2][0] = 0.;
-    modelMatrix[0][1] = 0.;
-    modelMatrix[2][1] = 0.;
-    modelMatrix[0][2] = 0.;
-    modelMatrix[1][2] = 0.;
-  }
-  else if( ATransPers->mode & TPF_RELATIVE_ROTATE )
-    /* Initialize relative rotate matrix*/
+//=======================================================================
+//function : FBORelease
+//purpose  :
+//=======================================================================
+void OpenGl_View::FBORelease (Handle(Standard_Transient)& theFbo)
+{
+  Handle(OpenGl_FrameBuffer) aFrameBuffer = Handle(OpenGl_FrameBuffer)::DownCast (theFbo);
+  if (aFrameBuffer.IsNull())
   {
-    modelMatrix[3][0] = 0.;
-    modelMatrix[3][1] = 0.;
-    modelMatrix[3][2] = 0.;
-
-    glMatrixMode( GL_MODELVIEW );
-    glLoadIdentity();
-    glTranslated( ATransPers->pointX, ATransPers->pointY, ATransPers->pointZ );        
+    return;
   }
 
-  if( ATransPers->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())
   {
-    /* Annulate translation matrix */
-    modelMatrix[3][0] = 0.;
-    modelMatrix[3][1] = 0.;
-    modelMatrix[3][2] = 0.;
+    return;
+  }
 
-    projMatrix[3][0] = 0.;
-    projMatrix[3][1] = 0.;
-    projMatrix[3][2] = 0.;
+  theWidth     = aFrameBuffer->GetVPSizeX(); // current viewport size
+  theHeight    = aFrameBuffer->GetVPSizeY();
+  theWidthMax  = aFrameBuffer->GetSizeX(); // texture size
+  theHeightMax = aFrameBuffer->GetSizeY();
+}
 
-    const double det2 = 0.002 / ( W > H ? projMatrix[1][1] : projMatrix[0][0]);
-    projMatrix[0][0] *= det2;
-    projMatrix[1][1] *= det2;
+//=======================================================================
+//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())
+  {
+    return;
   }
 
-  /* load matrix */
-  glMatrixMode (GL_MODELVIEW);
-  glMultMatrixd ((GLdouble *) modelMatrix);
+  aFrameBuffer->ChangeViewport (theWidth, theHeight);
+}
 
-  glMatrixMode (GL_PROJECTION);
-  glMultMatrixd ((GLdouble *) projMatrix);
+//=======================================================================
+//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);
+}
 
-  /*post loading matrix*/
-  if( ATransPers->mode == TPF_TRIEDRON )
-  {
-    glMatrixMode( GL_PROJECTION );
+//=======================================================================
+//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);
+}
 
-       double winx, winy, winz;
-    const GLdouble idenMatrix[4][4] = { {1.,0.,0.,0.}, {0.,1.,0.,0.}, {0.,0.,1.,0.}, {0.,0.,0.,1.} };
+//=======================================================================
+//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);
+}
 
-    gluUnProject( W/2., H/2., 0., (GLdouble*)idenMatrix, (GLdouble*)projMatrix, (GLint*)viewport, &winx, &winy, &winz);
-    double W1, H1;
-    W1 = winx;
-    H1 = winy;
-    gluUnProject( -W/2., -H/2., 0., (GLdouble*)idenMatrix, (GLdouble*)projMatrix, (GLint*)viewport, &winx, &winy, &winz);
-    double W2, H2;
-    W2 = winx;
-    H2 = winy;
+//=======================================================================
+//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);
+}
 
-    if( ATransPers->pointX == 0. && ATransPers->pointY == 0. )
-    {
-      /*center*/
-    }
-    else if( ATransPers->pointX > 0. && ATransPers->pointY > 0. )
-    {
-      /*right upper*/
-      glTranslated( 0.5*(W1 - W2 - ATransPers->pointZ), 0.5*(H1 - H2 - ATransPers->pointZ), 0. );
-    }
-    else if( ATransPers->pointX > 0. && ATransPers->pointY < 0. )
-    {
-      /*right lower*/
-      glTranslated( 0.5*(W1 - W2 - ATransPers->pointZ), 0.5*(H2 - H1 + ATransPers->pointZ), 0. );
-    }
-    else if( ATransPers->pointX < 0. && ATransPers->pointY > 0. )
-    {
-      /*left upper*/
-      glTranslated( 0.5*(W2 - W1 + ATransPers->pointZ), 0.5*(H1 - H2 - ATransPers->pointZ), 0. );
-    }
-    else if( ATransPers->pointX < 0 && ATransPers->pointY < 0 )
-    {
-      /*left lower*/
-      glTranslated( -(W1 - W2)/2. + ATransPers->pointZ/2., -(H1-H2)/2. + ATransPers->pointZ/2., 0. );
-    }
+//=======================================================================
+//function : DiagnosticInformation
+//purpose  :
+//=======================================================================
+void OpenGl_View::DiagnosticInformation (TColStd_IndexedDataMapOfStringString& theDict,
+                                         Graphic3d_DiagnosticInfo theFlags) const
+{
+  Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext();
+  if (!myWorkspace->Activate()
+   || aCtx.IsNull())
+  {
+    return;
   }
 
-  return TransPers_old;
+  aCtx->DiagnosticInformation (theDict, theFlags);
+  if ((theFlags & Graphic3d_DiagnosticInfo_FrameBuffer) != 0)
+  {
+    TCollection_AsciiString aResRatio (myRenderParams.ResolutionRatio());
+    theDict.ChangeFromIndex (theDict.Add ("ResolutionRatio", aResRatio)) = aResRatio;
+  }
+}
+
+//=======================================================================
+//function : StatisticInformation
+//purpose  :
+//=======================================================================
+void OpenGl_View::StatisticInformation (TColStd_IndexedDataMapOfStringString& theDict) const
+{
+  if (const Handle(OpenGl_Context)& aCtx = myWorkspace->GetGlContext())
+  {
+    const Handle(OpenGl_FrameStats)& aStats = aCtx->FrameStats();
+    const Graphic3d_RenderingParams& aRendParams = myWorkspace->View()->RenderingParams();
+    aStats->FormatStats (theDict, aRendParams.CollectedStats);
+  }
 }
 
-/*----------------------------------------------------------------------*/
+//=======================================================================
+//function : StatisticInformation
+//purpose  :
+//=======================================================================
+TCollection_AsciiString OpenGl_View::StatisticInformation() const
+{
+  if (const Handle(OpenGl_Context)& aCtx = myWorkspace->GetGlContext())
+  {
+    const Handle(OpenGl_FrameStats)& aStats = aCtx->FrameStats();
+    const Graphic3d_RenderingParams& aRendParams = myWorkspace->View()->RenderingParams();
+    return aStats->FormatStats (aRendParams.CollectedStats);
+  }
+  return TCollection_AsciiString();
+}