0029528: Visualization, TKOpenGl - allow defining sRGB textures
[occt.git] / src / OpenGl / OpenGl_View.cxx
1 // Created on: 2011-09-20
2 // Created by: Sergey ZERCHANINOV
3 // Copyright (c) 2011-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <OpenGl_View.hxx>
17
18 #include <Aspect_RenderingContext.hxx>
19 #include <Aspect_Window.hxx>
20 #include <Graphic3d_AspectFillArea3d.hxx>
21 #include <Graphic3d_Texture2Dmanual.hxx>
22 #include <Graphic3d_TextureEnv.hxx>
23 #include <Graphic3d_Mat4d.hxx>
24 #include <NCollection_Mat4.hxx>
25 #include <OpenGl_Context.hxx>
26 #include <OpenGl_FrameBuffer.hxx>
27 #include <OpenGl_GlCore11.hxx>
28 #include <OpenGl_GraduatedTrihedron.hxx>
29 #include <OpenGl_GraphicDriver.hxx>
30 #include <OpenGl_ShaderManager.hxx>
31 #include <OpenGl_Texture.hxx>
32 #include <OpenGl_Window.hxx>
33 #include <OpenGl_Workspace.hxx>
34 #include <OSD_Parallel.hxx>
35 #include <Standard_CLocaleSentry.hxx>
36
37 #include "../Graphic3d/Graphic3d_Structure.pxx"
38
39 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_View,Graphic3d_CView)
40
41 // =======================================================================
42 // function : Constructor
43 // purpose  :
44 // =======================================================================
45 OpenGl_View::OpenGl_View (const Handle(Graphic3d_StructureManager)& theMgr,
46                           const Handle(OpenGl_GraphicDriver)& theDriver,
47                           const Handle(OpenGl_Caps)& theCaps,
48                           OpenGl_StateCounter* theCounter)
49 : Graphic3d_CView  (theMgr),
50   myDriver         (theDriver.operator->()),
51   myCaps           (theCaps),
52   myWasRedrawnGL   (Standard_False),
53   myBackfacing     (Graphic3d_TOBM_AUTOMATIC),
54   myToShowGradTrihedron  (false),
55   myZLayers        (Structure_MAX_PRIORITY - Structure_MIN_PRIORITY + 1),
56   myStateCounter         (theCounter),
57   myCurrLightSourceState (theCounter->Increment()),
58   myLightsRevision       (0),
59   myLastLightSourceState (0, 0),
60   mySRgbState            (-1),
61   myFboColorFormat       (GL_SRGB8_ALPHA8), // note that GL_SRGB8 is not required to be renderable, unlike GL_RGB8, GL_RGBA8, GL_SRGB8_ALPHA8
62   myFboDepthFormat       (GL_DEPTH24_STENCIL8),
63   myToFlipOutput         (Standard_False),
64   myFrameCounter         (0),
65   myHasFboBlit           (Standard_True),
66   myToDisableOIT         (Standard_False),
67   myToDisableOITMSAA     (Standard_False),
68   myToDisableMSAA        (Standard_False),
69   myTransientDrawToFront (Standard_True),
70   myBackBufferRestored   (Standard_False),
71   myIsImmediateDrawn     (Standard_False),
72   myTextureParams   (new OpenGl_Aspects()),
73   myCubeMapParams   (new OpenGl_Aspects()),
74   myBackgroundType  (Graphic3d_TOB_NONE),
75   // ray-tracing fields initialization
76   myRaytraceInitStatus     (OpenGl_RT_NONE),
77   myIsRaytraceDataValid    (Standard_False),
78   myIsRaytraceWarnTextures (Standard_False),
79   myRaytraceBVHBuilder (new BVH_BinnedBuilder<Standard_ShortReal, 3, BVH_Constants_NbBinsBest> (BVH_Constants_LeafNodeSizeAverage,
80                                                                                                 BVH_Constants_MaxTreeDepth,
81                                                                                                 Standard_False,
82                                                                                                 OSD_Parallel::NbLogicalProcessors() + 1)),
83   myRaytraceSceneRadius  (0.0f),
84   myRaytraceSceneEpsilon (1.0e-6f),
85   myToUpdateEnvironmentMap (Standard_False),
86   myRaytraceLayerListState (0),
87   myPrevCameraApertureRadius(0.f),
88   myPrevCameraFocalPlaneDist(0.f)
89 {
90   for (int i = 0; i < Graphic3d_TypeOfBackground_NB; ++i)
91   {
92     myBackgrounds[i] = new OpenGl_BackgroundArray(Graphic3d_TypeOfBackground(i));
93   }
94
95   myWorkspace = new OpenGl_Workspace (this, NULL);
96
97   Handle(Graphic3d_CLight) aLight = new Graphic3d_CLight (Graphic3d_TOLS_AMBIENT);
98   aLight->SetHeadlight (false);
99   aLight->SetColor (Quantity_NOC_WHITE);
100   myNoShadingLight = new Graphic3d_LightSet();
101   myNoShadingLight->Add (aLight);
102
103   myMainSceneFbos[0]         = new OpenGl_FrameBuffer();
104   myMainSceneFbos[1]         = new OpenGl_FrameBuffer();
105   myMainSceneFbosOit[0]      = new OpenGl_FrameBuffer();
106   myMainSceneFbosOit[1]      = new OpenGl_FrameBuffer();
107   myImmediateSceneFbos[0]    = new OpenGl_FrameBuffer();
108   myImmediateSceneFbos[1]    = new OpenGl_FrameBuffer();
109   myImmediateSceneFbosOit[0] = new OpenGl_FrameBuffer();
110   myImmediateSceneFbosOit[1] = new OpenGl_FrameBuffer();
111   myOpenGlFBO                = new OpenGl_FrameBuffer();
112   myOpenGlFBO2               = new OpenGl_FrameBuffer();
113   myRaytraceFBO1[0]          = new OpenGl_FrameBuffer();
114   myRaytraceFBO1[1]          = new OpenGl_FrameBuffer();
115   myRaytraceFBO2[0]          = new OpenGl_FrameBuffer();
116   myRaytraceFBO2[1]          = new OpenGl_FrameBuffer();
117 }
118
119 // =======================================================================
120 // function : Destructor
121 // purpose  :
122 // =======================================================================
123 OpenGl_View::~OpenGl_View()
124 {
125   ReleaseGlResources (NULL); // ensure ReleaseGlResources() was called within valid context
126   for (int i = 0; i < Graphic3d_TypeOfBackground_NB; ++i)
127   {
128     OpenGl_Element::Destroy(NULL, myBackgrounds[i]);
129   }
130
131   OpenGl_Element::Destroy (NULL, myTextureParams);
132   OpenGl_Element::Destroy (NULL, myCubeMapParams);
133 }
134
135 // =======================================================================
136 // function : releaseSrgbResources
137 // purpose  :
138 // =======================================================================
139 void OpenGl_View::releaseSrgbResources (const Handle(OpenGl_Context)& theCtx)
140 {
141   myRenderParams.RebuildRayTracingShaders = true;
142
143   if (!myTextureEnv.IsNull())
144   {
145     if (!theCtx.IsNull())
146     {
147       for (OpenGl_TextureSet::Iterator aTextureIter (myTextureEnv); aTextureIter.More(); aTextureIter.Next())
148       {
149         theCtx->DelayedRelease (aTextureIter.ChangeValue());
150         aTextureIter.ChangeValue().Nullify();
151       }
152     }
153     myTextureEnv.Nullify();
154   }
155
156   if (myTextureParams != NULL)
157   {
158     myTextureParams->Release (theCtx.get());
159   }
160
161   if (myCubeMapParams != NULL)
162   {
163     myCubeMapParams->Release (theCtx.get());
164   }
165
166   for (int i = 0; i < Graphic3d_TypeOfBackground_NB; ++i)
167   {
168     if (myBackgrounds[i] != NULL)
169     {
170       myBackgrounds[i]->Release (theCtx.get());
171     }
172   }
173
174   myMainSceneFbos[0]        ->Release (theCtx.get());
175   myMainSceneFbos[1]        ->Release (theCtx.get());
176   myMainSceneFbosOit[0]     ->Release (theCtx.get());
177   myMainSceneFbosOit[1]     ->Release (theCtx.get());
178   myImmediateSceneFbos[0]   ->Release (theCtx.get());
179   myImmediateSceneFbos[1]   ->Release (theCtx.get());
180   myImmediateSceneFbosOit[0]->Release (theCtx.get());
181   myImmediateSceneFbosOit[1]->Release (theCtx.get());
182   myOpenGlFBO               ->Release (theCtx.get());
183   myOpenGlFBO2              ->Release (theCtx.get());
184   myFullScreenQuad           .Release (theCtx.get());
185   myFullScreenQuadFlip       .Release (theCtx.get());
186
187   // Technically we should also re-initialize all sRGB/RGB8 color textures.
188   // But for now consider this sRGB disabling/enabling to be done at application start-up
189   // and re-create dynamically only frame buffers.
190 }
191
192 // =======================================================================
193 // function : ReleaseGlResources
194 // purpose  :
195 // =======================================================================
196 void OpenGl_View::ReleaseGlResources (const Handle(OpenGl_Context)& theCtx)
197 {
198   myGraduatedTrihedron.Release (theCtx.get());
199   myFrameStatsPrs.Release (theCtx.get());
200
201   releaseSrgbResources (theCtx);
202
203   releaseRaytraceResources (theCtx);
204 }
205
206 // =======================================================================
207 // function : Remove
208 // purpose  :
209 // =======================================================================
210 void OpenGl_View::Remove()
211 {
212   if (IsRemoved())
213   {
214     return;
215   }
216
217   myDriver->RemoveView (this);
218   myWindow.Nullify();
219
220   Graphic3d_CView::Remove();
221 }
222
223 // =======================================================================
224 // function : SetLocalOrigin
225 // purpose  :
226 // =======================================================================
227 void OpenGl_View::SetLocalOrigin (const gp_XYZ& theOrigin)
228 {
229   myLocalOrigin = theOrigin;
230   const Handle(OpenGl_Context)& aCtx = myWorkspace->GetGlContext();
231   if (!aCtx.IsNull())
232   {
233     aCtx->ShaderManager()->SetLocalOrigin (theOrigin);
234   }
235 }
236
237 // =======================================================================
238 // function : SetTextureEnv
239 // purpose  :
240 // =======================================================================
241 void OpenGl_View::SetTextureEnv (const Handle(Graphic3d_TextureEnv)& theTextureEnv)
242 {
243   Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext();
244   if (!aCtx.IsNull() && !myTextureEnv.IsNull())
245   {
246     for (OpenGl_TextureSet::Iterator aTextureIter (myTextureEnv); aTextureIter.More(); aTextureIter.Next())
247     {
248       aCtx->DelayedRelease (aTextureIter.ChangeValue());
249       aTextureIter.ChangeValue().Nullify();
250     }
251   }
252
253   myToUpdateEnvironmentMap = Standard_True;
254   myTextureEnvData = theTextureEnv;
255   myTextureEnv.Nullify();
256   initTextureEnv (aCtx);
257 }
258
259 // =======================================================================
260 // function : initTextureEnv
261 // purpose  :
262 // =======================================================================
263 void OpenGl_View::initTextureEnv (const Handle(OpenGl_Context)& theContext)
264 {
265   if (myTextureEnvData.IsNull()
266     ||  theContext.IsNull()
267     || !theContext->MakeCurrent())
268   {
269     return;
270   }
271
272   myTextureEnv = new OpenGl_TextureSet (1);
273   Handle(OpenGl_Texture)& aTextureEnv = myTextureEnv->ChangeFirst();
274   aTextureEnv = new OpenGl_Texture (myTextureEnvData->GetId(), myTextureEnvData->GetParams());
275   Handle(Image_PixMap) anImage = myTextureEnvData->GetImage();
276   if (!anImage.IsNull())
277   {
278     aTextureEnv->Init (theContext, *anImage, myTextureEnvData->Type(), true);
279   }
280 }
281
282 // =======================================================================
283 // function : SetImmediateModeDrawToFront
284 // purpose  :
285 // =======================================================================
286 Standard_Boolean OpenGl_View::SetImmediateModeDrawToFront (const Standard_Boolean theDrawToFrontBuffer)
287 {
288   const Standard_Boolean aPrevMode = myTransientDrawToFront;
289   myTransientDrawToFront = theDrawToFrontBuffer;
290   return aPrevMode;
291 }
292
293 // =======================================================================
294 // function : SetWindow
295 // purpose  :
296 // =======================================================================
297 void OpenGl_View::SetWindow (const Handle(Aspect_Window)& theWindow,
298                              const Aspect_RenderingContext theContext)
299 {
300   myWindow = myDriver->CreateRenderWindow (theWindow, theContext);
301   Standard_ASSERT_RAISE (!myWindow.IsNull(),
302                          "OpenGl_View::SetWindow, "
303                          "Failed to create OpenGl window.");
304
305   myWorkspace = new OpenGl_Workspace (this, myWindow);
306   myWorldViewProjState.Reset();
307   myToUpdateEnvironmentMap = Standard_True;
308   myHasFboBlit = Standard_True;
309   Invalidate();
310
311   // Environment texture resource does not support lazy initialization.
312   initTextureEnv (myWorkspace->GetGlContext());
313 }
314
315 // =======================================================================
316 // function : Resized
317 // purpose  :
318 // =======================================================================
319 void OpenGl_View::Resized()
320 {
321   if (myWindow.IsNull())
322     return;
323
324   myWindow->Resize();
325 }
326
327 // =======================================================================
328 // function : SetMinMaxValuesCallback
329 // purpose  :
330 // =======================================================================
331 static void SetMinMaxValuesCallback (Graphic3d_CView* theView)
332 {
333   OpenGl_View* aView = dynamic_cast<OpenGl_View*>(theView);
334   if (aView == NULL)
335     return;
336
337   Bnd_Box aBox = theView->MinMaxValues();
338   if (!aBox.IsVoid())
339   {
340     gp_Pnt aMin = aBox.CornerMin();
341     gp_Pnt aMax = aBox.CornerMax();
342
343     Graphic3d_Vec3 aMinVec ((Standard_ShortReal )aMin.X(), (Standard_ShortReal )aMin.Y(), (Standard_ShortReal )aMin.Z());
344     Graphic3d_Vec3 aMaxVec ((Standard_ShortReal )aMax.X(), (Standard_ShortReal )aMax.Y(), (Standard_ShortReal )aMax.Z());
345     aView->GraduatedTrihedronMinMaxValues (aMinVec, aMaxVec);
346   }
347 }
348
349 // =======================================================================
350 // function : GraduatedTrihedronDisplay
351 // purpose  :
352 // =======================================================================
353 void OpenGl_View::GraduatedTrihedronDisplay (const Graphic3d_GraduatedTrihedron& theTrihedronData)
354 {
355   myGTrihedronData = theTrihedronData;
356   myGTrihedronData.PtrView = this;
357   myGTrihedronData.CubicAxesCallback = SetMinMaxValuesCallback;
358   myGraduatedTrihedron.SetValues (myGTrihedronData);
359   myToShowGradTrihedron = true;
360 }
361
362 // =======================================================================
363 // function : GraduatedTrihedronErase
364 // purpose  :
365 // =======================================================================
366 void OpenGl_View::GraduatedTrihedronErase()
367 {
368   myGTrihedronData.PtrView = NULL;
369   myGraduatedTrihedron.Release (myWorkspace->GetGlContext().operator->());
370   myToShowGradTrihedron = false;
371 }
372
373 // =======================================================================
374 // function : GraduatedTrihedronMinMaxValues
375 // purpose  :
376 // =======================================================================
377 void OpenGl_View::GraduatedTrihedronMinMaxValues (const Graphic3d_Vec3 theMin, const Graphic3d_Vec3 theMax)
378 {
379   myGraduatedTrihedron.SetMinMax (theMin, theMax);
380 }
381
382 // =======================================================================
383 // function : BufferDump
384 // purpose  :
385 // =======================================================================
386 Standard_Boolean OpenGl_View::BufferDump (Image_PixMap& theImage, const Graphic3d_BufferType& theBufferType)
387 {
388   if (theBufferType != Graphic3d_BT_RGB_RayTraceHdrLeft)
389   {
390     return myWorkspace->BufferDump(myFBO, theImage, theBufferType);
391   }
392
393   if (!myRaytraceParameters.AdaptiveScreenSampling)
394   {
395     return myWorkspace->BufferDump(myAccumFrames % 2 ? myRaytraceFBO2[0] : myRaytraceFBO1[0], theImage, theBufferType);
396   }
397
398 #if defined(GL_ES_VERSION_2_0)
399   return false;
400 #else
401   if (theImage.Format() != Image_Format_RGBF)
402   {
403     return false;
404   }
405
406   const GLuint aW = myRaytraceOutputTexture[0]->SizeX();
407   const GLuint aH = myRaytraceOutputTexture[0]->SizeY();
408   if (aW / 3 != theImage.SizeX() || aH / 2 != theImage.SizeY())
409   {
410     return false;
411   }
412
413   std::vector<GLfloat> aValues;
414   try
415   {
416     aValues.resize (aW * aH);
417   }
418   catch (const std::bad_alloc&)
419   {
420     return false;
421   }
422
423   glBindTexture (GL_TEXTURE_RECTANGLE, myRaytraceOutputTexture[0]->TextureId());
424   glGetTexImage (GL_TEXTURE_RECTANGLE, 0, OpenGl_TextureFormat::Create<GLfloat, 1>().Format(), GL_FLOAT, &aValues[0]);
425   glBindTexture (GL_TEXTURE_RECTANGLE, 0);
426   for (unsigned int aRow = 0; aRow < aH; aRow += 2)
427   {
428     for (unsigned int aCol = 0; aCol < aW; aCol += 3)
429     {
430       float* anImageValue = theImage.ChangeValue<float[3]> ((aH - aRow) / 2 - 1, aCol / 3);
431       float aInvNbSamples = 1.f / aValues[aRow * aW + aCol + aW];
432       anImageValue[0] = aValues[aRow * aW + aCol] * aInvNbSamples;
433       anImageValue[1] = aValues[aRow * aW + aCol + 1] * aInvNbSamples;
434       anImageValue[2] = aValues[aRow * aW + aCol + 1 + aW] * aInvNbSamples;
435     }
436   }
437
438   return true;
439 #endif
440 }
441
442 // =======================================================================
443 // function : GradientBackground
444 // purpose  :
445 // =======================================================================
446 Aspect_GradientBackground OpenGl_View::GradientBackground() const
447 {
448   Quantity_Color aColor1, aColor2;
449   aColor1.SetValues (myBackgrounds[Graphic3d_TOB_GRADIENT]->GradientColor (0).r(),
450                      myBackgrounds[Graphic3d_TOB_GRADIENT]->GradientColor (0).g(),
451                      myBackgrounds[Graphic3d_TOB_GRADIENT]->GradientColor (0).b(), Quantity_TOC_RGB);
452   aColor2.SetValues (myBackgrounds[Graphic3d_TOB_GRADIENT]->GradientColor (1).r(),
453                      myBackgrounds[Graphic3d_TOB_GRADIENT]->GradientColor (1).g(),
454                      myBackgrounds[Graphic3d_TOB_GRADIENT]->GradientColor (1).b(), Quantity_TOC_RGB);
455   return Aspect_GradientBackground (aColor1, aColor2, myBackgrounds[Graphic3d_TOB_GRADIENT]->GradientFillMethod());
456 }
457
458 // =======================================================================
459 // function : SetGradientBackground
460 // purpose  :
461 // =======================================================================
462 void OpenGl_View::SetGradientBackground (const Aspect_GradientBackground& theBackground)
463 {
464   Quantity_Color aColor1, aColor2;
465   theBackground.Colors (aColor1, aColor2);
466   myBackgrounds[Graphic3d_TOB_GRADIENT]->SetGradientParameters (aColor1, aColor2, theBackground.BgGradientFillMethod());
467
468   myBackgroundType = Graphic3d_TOB_GRADIENT;
469 }
470
471 // =======================================================================
472 // function : SetBackgroundImage
473 // purpose  :
474 // =======================================================================
475 void OpenGl_View::SetBackgroundImage (const TCollection_AsciiString& theFilePath)
476 {
477   // Prepare aspect for texture storage
478   myBackgroundImagePath = theFilePath;
479   Handle(Graphic3d_AspectFillArea3d) anAspect = new Graphic3d_AspectFillArea3d();
480   Handle(Graphic3d_Texture2Dmanual) aTextureMap = new Graphic3d_Texture2Dmanual (TCollection_AsciiString (theFilePath));
481   aTextureMap->EnableRepeat();
482   aTextureMap->DisableModulate();
483   aTextureMap->GetParams()->SetGenMode (Graphic3d_TOTM_MANUAL,
484                                         Graphic3d_Vec4 (0.0f, 0.0f, 0.0f, 0.0f),
485                                         Graphic3d_Vec4 (0.0f, 0.0f, 0.0f, 0.0f));
486   anAspect->SetTextureMap (aTextureMap);
487   anAspect->SetInteriorStyle (Aspect_IS_SOLID);
488   anAspect->SetSuppressBackFaces (false);
489   // Enable texture mapping
490   if (aTextureMap->IsDone())
491   {
492     anAspect->SetTextureMapOn();
493   }
494   else
495   {
496     anAspect->SetTextureMapOff();
497     return;
498   }
499
500   // Set texture parameters
501   myTextureParams->SetAspect (anAspect);
502
503   myBackgroundType = Graphic3d_TOB_TEXTURE;
504 }
505
506 // =======================================================================
507 // function : BackgroundImageStyle
508 // purpose  :
509 // =======================================================================
510 Aspect_FillMethod OpenGl_View::BackgroundImageStyle() const
511 {
512   return myBackgrounds[Graphic3d_TOB_TEXTURE]->TextureFillMethod();
513 }
514
515 // =======================================================================
516 // function : SetBackgroundImageStyle
517 // purpose  :
518 // =======================================================================
519 void OpenGl_View::SetBackgroundImageStyle (const Aspect_FillMethod theFillStyle)
520 {
521   myBackgrounds[Graphic3d_TOB_TEXTURE]->SetTextureFillMethod (theFillStyle);
522 }
523
524 // =======================================================================
525 // function : BackgroundCubeMap
526 // purpose  :
527 // =======================================================================
528 Handle(Graphic3d_CubeMap) OpenGl_View::BackgroundCubeMap() const
529 {
530   return myBackgroundCubeMap;
531 }
532  
533 // =======================================================================
534 // function : SetBackgroundCubeMap
535 // purpose  :
536 // =======================================================================
537 void OpenGl_View::SetBackgroundCubeMap (const Handle(Graphic3d_CubeMap)& theCubeMap)
538 {
539   myBackgroundCubeMap = theCubeMap;
540   Handle(Graphic3d_AspectFillArea3d) anAspect = new Graphic3d_AspectFillArea3d;
541   Handle(Graphic3d_TextureSet) aTextureSet = new Graphic3d_TextureSet (myBackgroundCubeMap);
542
543   anAspect->SetInteriorStyle(Aspect_IS_SOLID);
544   anAspect->SetSuppressBackFaces(false);
545   anAspect->SetTextureSet(aTextureSet);
546
547   const Handle(OpenGl_Context)& aCtx = myWorkspace->GetGlContext();
548   if (!aCtx.IsNull())
549   {
550     anAspect->SetShaderProgram (aCtx->ShaderManager()->GetBgCubeMapProgram());
551   }
552
553   if (theCubeMap->IsDone())
554   {
555     anAspect->SetTextureMapOn();
556   }
557   else
558   {
559     anAspect->SetTextureMapOff();
560   }
561
562   myCubeMapParams->SetAspect(anAspect);
563   const OpenGl_Aspects* anAspectsBackup = myWorkspace->SetAspects (myCubeMapParams);
564   myWorkspace->ApplyAspects();
565   myWorkspace->SetAspects (anAspectsBackup);
566   myWorkspace->ApplyAspects();
567
568   myBackgroundType = Graphic3d_TOB_CUBEMAP;
569 }
570
571 //=======================================================================
572 //function : InsertLayerBefore
573 //purpose  :
574 //=======================================================================
575 void OpenGl_View::InsertLayerBefore (const Graphic3d_ZLayerId theLayerId,
576   const Graphic3d_ZLayerSettings& theSettings,
577   const Graphic3d_ZLayerId theLayerAfter)
578 {
579   myZLayers.InsertLayerBefore (theLayerId, theSettings, theLayerAfter);
580 }
581
582 //=======================================================================
583 //function : InsertLayerAfter
584 //purpose  :
585 //=======================================================================
586 void OpenGl_View::InsertLayerAfter (const Graphic3d_ZLayerId theLayerId,
587   const Graphic3d_ZLayerSettings& theSettings,
588   const Graphic3d_ZLayerId theLayerBefore)
589 {
590   myZLayers.InsertLayerAfter (theLayerId, theSettings, theLayerBefore);
591 }
592
593 //=======================================================================
594 //function : RemoveZLayer
595 //purpose  :
596 //=======================================================================
597 void OpenGl_View::RemoveZLayer (const Graphic3d_ZLayerId theLayerId)
598 {
599   myZLayers.RemoveLayer (theLayerId);
600 }
601
602 //=======================================================================
603 //function : SetZLayerSettings
604 //purpose  :
605 //=======================================================================
606 void OpenGl_View::SetZLayerSettings (const Graphic3d_ZLayerId        theLayerId,
607                                      const Graphic3d_ZLayerSettings& theSettings)
608 {
609   myZLayers.SetLayerSettings (theLayerId, theSettings);
610 }
611
612 //=======================================================================
613 //function : ZLayerMax
614 //purpose  :
615 //=======================================================================
616 Standard_Integer OpenGl_View::ZLayerMax() const
617 {
618   Standard_Integer aLayerMax = Graphic3d_ZLayerId_Default;
619   for (NCollection_List<Handle(Graphic3d_Layer)>::Iterator aLayerIter (myZLayers.Layers()); aLayerIter.More(); aLayerIter.Next())
620   {
621     aLayerMax = Max (aLayerMax, aLayerIter.Value()->LayerId());
622   }
623   return aLayerMax;
624 }
625
626 //=======================================================================
627 //function : Layers
628 //purpose  :
629 //=======================================================================
630 const NCollection_List<Handle(Graphic3d_Layer)>& OpenGl_View::Layers() const
631 {
632   return myZLayers.Layers();
633 }
634
635 //=======================================================================
636 //function : Layer
637 //purpose  :
638 //=======================================================================
639 Handle(Graphic3d_Layer) OpenGl_View::Layer (const Graphic3d_ZLayerId theLayerId) const
640 {
641   Handle(Graphic3d_Layer) aLayer;
642   if (theLayerId != Graphic3d_ZLayerId_UNKNOWN)
643   {
644     myZLayers.LayerIDs().Find (theLayerId, aLayer);
645   }
646   return aLayer;
647 }
648
649 //=======================================================================
650 //function : MinMaxValues
651 //purpose  :
652 //=======================================================================
653 Bnd_Box OpenGl_View::MinMaxValues (const Standard_Boolean theToIncludeAuxiliary) const
654 {
655   if (!IsDefined())
656   {
657     return Bnd_Box();
658   }
659
660   Bnd_Box aBox = base_type::MinMaxValues (theToIncludeAuxiliary);
661
662   // add bounding box of gradient/texture background for proper Z-fit
663   if (theToIncludeAuxiliary
664     && (myBackgrounds[Graphic3d_TOB_TEXTURE]->IsDefined()
665      || myBackgrounds[Graphic3d_TOB_GRADIENT]->IsDefined()))
666   {
667     const Handle(Graphic3d_Camera)& aCamera = Camera();
668     Graphic3d_Vec2i aWinSize;
669     Window()->Size (aWinSize.x(), aWinSize.y());
670
671     // Background is drawn using 2D transformation persistence
672     // (e.g. it is actually placed in 3D coordinates within active camera position).
673     // We add here full-screen plane with 2D transformation persistence
674     // for simplicity (myBgTextureArray might define a little bit different options
675     // but it is updated within ::Render())
676     const Graphic3d_Mat4d& aProjectionMat = aCamera->ProjectionMatrix();
677     const Graphic3d_Mat4d& aWorldViewMat  = aCamera->OrientationMatrix();
678     Graphic3d_BndBox3d aBox2d (Graphic3d_Vec3d (0.0, 0.0, 0.0),
679                                Graphic3d_Vec3d (double(aWinSize.x()), double(aWinSize.y()), 0.0));
680
681     Graphic3d_TransformPers aTrsfPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_LOWER);
682     aTrsfPers.Apply (aCamera,
683                      aProjectionMat,
684                      aWorldViewMat,
685                      aWinSize.x(),
686                      aWinSize.y(),
687                      aBox2d);
688     aBox.Add (gp_Pnt (aBox2d.CornerMin().x(), aBox2d.CornerMin().y(), aBox2d.CornerMin().z()));
689     aBox.Add (gp_Pnt (aBox2d.CornerMax().x(), aBox2d.CornerMax().y(), aBox2d.CornerMax().z()));
690   }
691
692   return aBox;
693 }
694
695 //=======================================================================
696 //function : FBO
697 //purpose  :
698 //=======================================================================
699 Handle(Standard_Transient) OpenGl_View::FBO() const
700 {
701   return Handle(Standard_Transient)(myFBO);
702 }
703
704 //=======================================================================
705 //function : SetFBO
706 //purpose  :
707 //=======================================================================
708 void OpenGl_View::SetFBO (const Handle(Standard_Transient)& theFbo)
709 {
710   myFBO = Handle(OpenGl_FrameBuffer)::DownCast (theFbo);
711 }
712
713 //=======================================================================
714 //function : FBOCreate
715 //purpose  :
716 //=======================================================================
717 Handle(Standard_Transient) OpenGl_View::FBOCreate (const Standard_Integer theWidth,
718                                                    const Standard_Integer theHeight)
719 {
720   return myWorkspace->FBOCreate (theWidth, theHeight);
721 }
722
723 //=======================================================================
724 //function : FBORelease
725 //purpose  :
726 //=======================================================================
727 void OpenGl_View::FBORelease (Handle(Standard_Transient)& theFbo)
728 {
729   Handle(OpenGl_FrameBuffer) aFrameBuffer = Handle(OpenGl_FrameBuffer)::DownCast (theFbo);
730   if (aFrameBuffer.IsNull())
731   {
732     return;
733   }
734
735   myWorkspace->FBORelease (aFrameBuffer);
736   theFbo.Nullify();
737 }
738
739 //=======================================================================
740 //function : FBOGetDimensions
741 //purpose  :
742 //=======================================================================
743 void OpenGl_View::FBOGetDimensions (const Handle(Standard_Transient)& theFbo,
744                                     Standard_Integer& theWidth,
745                                     Standard_Integer& theHeight,
746                                     Standard_Integer& theWidthMax,
747                                     Standard_Integer& theHeightMax)
748 {
749   const Handle(OpenGl_FrameBuffer) aFrameBuffer = Handle(OpenGl_FrameBuffer)::DownCast (theFbo);
750   if (aFrameBuffer.IsNull())
751   {
752     return;
753   }
754
755   theWidth     = aFrameBuffer->GetVPSizeX(); // current viewport size
756   theHeight    = aFrameBuffer->GetVPSizeY();
757   theWidthMax  = aFrameBuffer->GetSizeX(); // texture size
758   theHeightMax = aFrameBuffer->GetSizeY();
759 }
760
761 //=======================================================================
762 //function : FBOChangeViewport
763 //purpose  :
764 //=======================================================================
765 void OpenGl_View::FBOChangeViewport (const Handle(Standard_Transient)& theFbo,
766                                      const Standard_Integer theWidth,
767                                      const Standard_Integer theHeight)
768 {
769   const Handle(OpenGl_FrameBuffer) aFrameBuffer = Handle(OpenGl_FrameBuffer)::DownCast (theFbo);
770   if (aFrameBuffer.IsNull())
771   {
772     return;
773   }
774
775   aFrameBuffer->ChangeViewport (theWidth, theHeight);
776 }
777
778 //=======================================================================
779 //function : displayStructure
780 //purpose  :
781 //=======================================================================
782 void OpenGl_View::displayStructure (const Handle(Graphic3d_CStructure)& theStructure,
783                                     const Standard_Integer              thePriority)
784 {
785   const OpenGl_Structure*  aStruct = reinterpret_cast<const OpenGl_Structure*> (theStructure.operator->());
786   const Graphic3d_ZLayerId aZLayer = aStruct->ZLayer();
787   myZLayers.AddStructure (aStruct, aZLayer, thePriority);
788 }
789
790 //=======================================================================
791 //function : eraseStructure
792 //purpose  :
793 //=======================================================================
794 void OpenGl_View::eraseStructure (const Handle(Graphic3d_CStructure)& theStructure)
795 {
796   const OpenGl_Structure*  aStruct = reinterpret_cast<const OpenGl_Structure*> (theStructure.operator->());
797   myZLayers.RemoveStructure (aStruct);
798 }
799
800 //=======================================================================
801 //function : changeZLayer
802 //purpose  :
803 //=======================================================================
804 void OpenGl_View::changeZLayer (const Handle(Graphic3d_CStructure)& theStructure,
805                                 const Graphic3d_ZLayerId theNewLayerId)
806 {
807   const Graphic3d_ZLayerId anOldLayer = theStructure->ZLayer();
808   const OpenGl_Structure* aStruct = reinterpret_cast<const OpenGl_Structure*> (theStructure.operator->());
809   myZLayers.ChangeLayer (aStruct, anOldLayer, theNewLayerId);
810   Update (anOldLayer);
811   Update (theNewLayerId);
812 }
813
814 //=======================================================================
815 //function : changePriority
816 //purpose  :
817 //=======================================================================
818 void OpenGl_View::changePriority (const Handle(Graphic3d_CStructure)& theStructure,
819                                   const Standard_Integer theNewPriority)
820 {
821   const Graphic3d_ZLayerId aLayerId = theStructure->ZLayer();
822   const OpenGl_Structure* aStruct = reinterpret_cast<const OpenGl_Structure*> (theStructure.operator->());
823   myZLayers.ChangePriority (aStruct, aLayerId, theNewPriority);
824 }
825
826 //=======================================================================
827 //function : DiagnosticInformation
828 //purpose  :
829 //=======================================================================
830 void OpenGl_View::DiagnosticInformation (TColStd_IndexedDataMapOfStringString& theDict,
831                                          Graphic3d_DiagnosticInfo theFlags) const
832 {
833   Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext();
834   if (!myWorkspace->Activate()
835    || aCtx.IsNull())
836   {
837     return;
838   }
839
840   aCtx->DiagnosticInformation (theDict, theFlags);
841   if ((theFlags & Graphic3d_DiagnosticInfo_FrameBuffer) != 0)
842   {
843     TCollection_AsciiString aResRatio (myRenderParams.ResolutionRatio());
844     theDict.ChangeFromIndex (theDict.Add ("ResolutionRatio", aResRatio)) = aResRatio;
845   }
846 }
847
848 //=======================================================================
849 //function : StatisticInformation
850 //purpose  :
851 //=======================================================================
852 void OpenGl_View::StatisticInformation (TColStd_IndexedDataMapOfStringString& theDict) const
853 {
854   if (const Handle(OpenGl_Context)& aCtx = myWorkspace->GetGlContext())
855   {
856     const Handle(OpenGl_FrameStats)& aStats = aCtx->FrameStats();
857     const Graphic3d_RenderingParams& aRendParams = myWorkspace->View()->RenderingParams();
858     aStats->FormatStats (theDict, aRendParams.CollectedStats);
859   }
860 }
861
862 //=======================================================================
863 //function : StatisticInformation
864 //purpose  :
865 //=======================================================================
866 TCollection_AsciiString OpenGl_View::StatisticInformation() const
867 {
868   if (const Handle(OpenGl_Context)& aCtx = myWorkspace->GetGlContext())
869   {
870     const Handle(OpenGl_FrameStats)& aStats = aCtx->FrameStats();
871     const Graphic3d_RenderingParams& aRendParams = myWorkspace->View()->RenderingParams();
872     return aStats->FormatStats (aRendParams.CollectedStats);
873   }
874   return TCollection_AsciiString();
875 }