d11d483c41ec7c3c2caa1ab30a1c60bdbfec736c
[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 <Standard_CLocaleSentry.hxx>
35
36 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_View,Graphic3d_CView)
37
38 #ifdef HAVE_GL2PS
39 #include <gl2ps.h>
40 #endif
41
42 // =======================================================================
43 // function : Constructor
44 // purpose  :
45 // =======================================================================
46 OpenGl_View::OpenGl_View (const Handle(Graphic3d_StructureManager)& theMgr,
47                           const Handle(OpenGl_GraphicDriver)& theDriver,
48                           const Handle(OpenGl_Caps)& theCaps,
49                           Standard_Boolean& theDeviceLostFlag,
50                           OpenGl_StateCounter* theCounter)
51 : Graphic3d_CView  (theMgr),
52   myDriver         (theDriver.operator->()),
53   myCaps           (theCaps),
54   myDeviceLostFlag (theDeviceLostFlag),
55   myWasRedrawnGL   (Standard_False),
56   myCulling        (Standard_True),
57   myShadingModel   (Graphic3d_TOSM_FACET),
58   myBackfacing     (Graphic3d_TOBM_AUTOMATIC),
59   myBgColor        (Quantity_NOC_BLACK),
60   myCamera         (new Graphic3d_Camera()),
61   myUseGLLight     (Standard_True),
62   myToShowGradTrihedron  (false),
63   myStateCounter         (theCounter),
64   myLastLightSourceState (0, 0),
65   myFboColorFormat       (GL_RGBA8),
66   myFboDepthFormat       (GL_DEPTH24_STENCIL8),
67   myToFlipOutput         (Standard_False),
68   myFrameCounter         (0),
69   myHasFboBlit           (Standard_True),
70   myToDisableMSAA        (Standard_False),
71   myTransientDrawToFront (Standard_True),
72   myBackBufferRestored   (Standard_False),
73   myIsImmediateDrawn     (Standard_False),
74   myTextureParams   (new OpenGl_AspectFace()),
75   myBgGradientArray (new OpenGl_BackgroundArray (Graphic3d_TOB_GRADIENT)),
76   myBgTextureArray  (new OpenGl_BackgroundArray (Graphic3d_TOB_TEXTURE)),
77   // ray-tracing fields initialization
78   myRaytraceInitStatus     (OpenGl_RT_NONE),
79   myIsRaytraceDataValid    (Standard_False),
80   myIsRaytraceWarnTextures (Standard_False),
81   myToUpdateEnvironmentMap (Standard_False),
82   myRaytraceLayerListState (0)
83 {
84   myWorkspace = new OpenGl_Workspace (this, NULL);
85
86   OpenGl_Light       aLight;
87   aLight.Type        = Graphic3d_TOLS_AMBIENT;
88   aLight.IsHeadlight = Standard_False;
89   aLight.Color.r()   = 1.;
90   aLight.Color.g()   = 1.;
91   aLight.Color.b()   = 1.;
92   myNoShadingLight.Append (aLight);
93
94   myCurrLightSourceState  = myStateCounter->Increment();
95   myMainSceneFbos[0]      = new OpenGl_FrameBuffer();
96   myMainSceneFbos[1]      = new OpenGl_FrameBuffer();
97   myImmediateSceneFbos[0] = new OpenGl_FrameBuffer();
98   myImmediateSceneFbos[1] = new OpenGl_FrameBuffer();
99   myOpenGlFBO             = new OpenGl_FrameBuffer();
100   myOpenGlFBO2            = new OpenGl_FrameBuffer();
101   myRaytraceFBO1[0]       = new OpenGl_FrameBuffer();
102   myRaytraceFBO1[1]       = new OpenGl_FrameBuffer();
103   myRaytraceFBO2[0]       = new OpenGl_FrameBuffer();
104   myRaytraceFBO2[1]       = new OpenGl_FrameBuffer();
105 }
106
107 // =======================================================================
108 // function : Destructor
109 // purpose  :
110 // =======================================================================
111 OpenGl_View::~OpenGl_View()
112 {
113   ReleaseGlResources (NULL); // ensure ReleaseGlResources() was called within valid context
114   OpenGl_Element::Destroy (NULL, myBgGradientArray);
115   OpenGl_Element::Destroy (NULL, myBgTextureArray);
116   OpenGl_Element::Destroy (NULL, myTextureParams);
117 }
118
119 // =======================================================================
120 // function : ReleaseGlResources
121 // purpose  :
122 // =======================================================================
123 void OpenGl_View::ReleaseGlResources (const Handle(OpenGl_Context)& theCtx)
124 {
125   myGraduatedTrihedron.Release (theCtx.operator->());
126
127   if (!myTextureEnv.IsNull())
128   {
129     theCtx->DelayedRelease (myTextureEnv);
130     myTextureEnv.Nullify();
131   }
132
133   if (myTextureParams != NULL)
134   {
135     myTextureParams->Release (theCtx.operator->());
136   }
137   if (myBgGradientArray != NULL)
138   {
139     myBgGradientArray->Release (theCtx.operator->());
140   }
141   if (myBgTextureArray != NULL)
142   {
143     myBgTextureArray->Release (theCtx.operator->());
144   }
145
146   myMainSceneFbos[0]     ->Release (theCtx.operator->());
147   myMainSceneFbos[1]     ->Release (theCtx.operator->());
148   myImmediateSceneFbos[0]->Release (theCtx.operator->());
149   myImmediateSceneFbos[1]->Release (theCtx.operator->());
150   myOpenGlFBO            ->Release (theCtx.operator->());
151   myOpenGlFBO2           ->Release (theCtx.operator->());
152   myFullScreenQuad        .Release (theCtx.operator->());
153   myFullScreenQuadFlip    .Release (theCtx.operator->());
154
155   releaseRaytraceResources (theCtx);
156 }
157
158 // =======================================================================
159 // function : Remove
160 // purpose  :
161 // =======================================================================
162 void OpenGl_View::Remove()
163 {
164   if (IsRemoved())
165   {
166     return;
167   }
168
169   myDriver->RemoveView (this);
170   myWindow.Nullify();
171
172   Graphic3d_CView::Remove();
173 }
174
175 // =======================================================================
176 // function : SetTextureEnv
177 // purpose  :
178 // =======================================================================
179 void OpenGl_View::SetTextureEnv (const Handle(Graphic3d_TextureEnv)& theTextureEnv)
180 {
181   Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext();
182   if (!aCtx.IsNull() && !myTextureEnv.IsNull())
183   {
184     aCtx->DelayedRelease (myTextureEnv);
185   }
186
187   myToUpdateEnvironmentMap = Standard_True;
188   myTextureEnvData = theTextureEnv;
189   myTextureEnv.Nullify();
190   initTextureEnv (aCtx);
191 }
192
193 // =======================================================================
194 // function : initTextureEnv
195 // purpose  :
196 // =======================================================================
197 void OpenGl_View::initTextureEnv (const Handle(OpenGl_Context)& theContext)
198 {
199   if (myTextureEnvData.IsNull()
200     ||  theContext.IsNull()
201     || !theContext->MakeCurrent())
202   {
203     return;
204   }
205
206   myTextureEnv = new OpenGl_Texture (myTextureEnvData->GetParams());
207   Handle(Image_PixMap) anImage = myTextureEnvData->GetImage();
208   if (!anImage.IsNull())
209   {
210     myTextureEnv->Init (theContext, *anImage.operator->(), myTextureEnvData->Type());
211   }
212 }
213
214 // =======================================================================
215 // function : SetImmediateModeDrawToFront
216 // purpose  :
217 // =======================================================================
218 Standard_Boolean OpenGl_View::SetImmediateModeDrawToFront (const Standard_Boolean theDrawToFrontBuffer)
219 {
220   const Standard_Boolean aPrevMode = myTransientDrawToFront;
221   myTransientDrawToFront = theDrawToFrontBuffer;
222   return aPrevMode;
223 }
224
225 // =======================================================================
226 // function : SetWindow
227 // purpose  :
228 // =======================================================================
229 void OpenGl_View::SetWindow (const Handle(Aspect_Window)& theWindow,
230                              const Aspect_RenderingContext theContext)
231 {
232   myWindow = myDriver->CreateRenderWindow (theWindow, theContext);
233   Standard_ASSERT_RAISE (!myWindow.IsNull(),
234                          "OpenGl_View::SetWindow, "
235                          "Failed to create OpenGl window.");
236
237   myWorkspace = new OpenGl_Workspace (this, myWindow);
238   myWorldViewProjState.Reset();
239   myToUpdateEnvironmentMap = Standard_True;
240   myHasFboBlit = Standard_True;
241   Invalidate();
242
243   // Environment texture resource does not support lazy initialization.
244   initTextureEnv (myWorkspace->GetGlContext());
245 }
246
247 // =======================================================================
248 // function : Resized
249 // purpose  :
250 // =======================================================================
251 void OpenGl_View::Resized()
252 {
253   if (myWindow.IsNull())
254     return;
255
256   myWindow->Resize();
257 }
258
259 // =======================================================================
260 // function : SetMinMaxValuesCallback
261 // purpose  :
262 // =======================================================================
263 static void SetMinMaxValuesCallback (Graphic3d_CView* theView)
264 {
265   OpenGl_View* aView = dynamic_cast<OpenGl_View*>(theView);
266   if (aView == NULL)
267     return;
268
269   Bnd_Box aBox = theView->MinMaxValues();
270   if (!aBox.IsVoid())
271   {
272     gp_Pnt aMin = aBox.CornerMin();
273     gp_Pnt aMax = aBox.CornerMax();
274
275     Graphic3d_Vec3 aMinVec ((Standard_ShortReal )aMin.X(), (Standard_ShortReal )aMin.Y(), (Standard_ShortReal )aMin.Z());
276     Graphic3d_Vec3 aMaxVec ((Standard_ShortReal )aMax.X(), (Standard_ShortReal )aMax.Y(), (Standard_ShortReal )aMax.Z());
277     aView->GraduatedTrihedronMinMaxValues (aMinVec, aMaxVec);
278   }
279 }
280
281 // =======================================================================
282 // function : GraduatedTrihedronDisplay
283 // purpose  :
284 // =======================================================================
285 void OpenGl_View::GraduatedTrihedronDisplay (const Graphic3d_GraduatedTrihedron& theTrihedronData)
286 {
287   myGTrihedronData = theTrihedronData;
288   myGTrihedronData.PtrView = this;
289   myGTrihedronData.CubicAxesCallback = SetMinMaxValuesCallback;
290   myGraduatedTrihedron.SetValues (myGTrihedronData);
291   myToShowGradTrihedron = true;
292 }
293
294 // =======================================================================
295 // function : GraduatedTrihedronErase
296 // purpose  :
297 // =======================================================================
298 void OpenGl_View::GraduatedTrihedronErase()
299 {
300   myGTrihedronData.PtrView = NULL;
301   myGraduatedTrihedron.Release (myWorkspace->GetGlContext().operator->());
302   myToShowGradTrihedron = false;
303 }
304
305 // =======================================================================
306 // function : GraduatedTrihedronMinMaxValues
307 // purpose  :
308 // =======================================================================
309 void OpenGl_View::GraduatedTrihedronMinMaxValues (const Graphic3d_Vec3 theMin, const Graphic3d_Vec3 theMax)
310 {
311   myGraduatedTrihedron.SetMinMax (theMin, theMax);
312 }
313
314 // =======================================================================
315 // function : BufferDump
316 // purpose  :
317 // =======================================================================
318 Standard_Boolean OpenGl_View::BufferDump (Image_PixMap& theImage, const Graphic3d_BufferType& theBufferType)
319 {
320   return myWorkspace->BufferDump (myFBO, theImage, theBufferType);
321 }
322
323 // =======================================================================
324 // function : Background
325 // purpose  :
326 // =======================================================================
327 Aspect_Background OpenGl_View::Background() const
328 {
329   return Aspect_Background (myBgColor.GetRGB());
330 }
331
332 // =======================================================================
333 // function : SetBackground
334 // purpose  :
335 // =======================================================================
336 void OpenGl_View::SetBackground (const Aspect_Background& theBackground)
337 {
338   myBgColor.SetRGB (theBackground.Color());
339 }
340
341 // =======================================================================
342 // function : GradientBackground
343 // purpose  :
344 // =======================================================================
345 Aspect_GradientBackground OpenGl_View::GradientBackground() const
346 {
347   Quantity_Color aColor1, aColor2;
348   aColor1.SetValues (myBgGradientArray->GradientColor (0).r(),
349                      myBgGradientArray->GradientColor (0).g(),
350                      myBgGradientArray->GradientColor (0).b(), Quantity_TOC_RGB);
351   aColor2.SetValues (myBgGradientArray->GradientColor (1).r(),
352                      myBgGradientArray->GradientColor (1).g(),
353                      myBgGradientArray->GradientColor (1).b(), Quantity_TOC_RGB);
354   return Aspect_GradientBackground (aColor1, aColor2, myBgGradientArray->GradientFillMethod());
355 }
356
357 // =======================================================================
358 // function : SetGradientBackground
359 // purpose  :
360 // =======================================================================
361 void OpenGl_View::SetGradientBackground (const Aspect_GradientBackground& theBackground)
362 {
363   Quantity_Color aColor1, aColor2;
364   theBackground.Colors (aColor1, aColor2);
365   myBgGradientArray->SetGradientParameters (aColor1, aColor2, theBackground.BgGradientFillMethod());
366 }
367
368 // =======================================================================
369 // function : SetBackgroundImage
370 // purpose  :
371 // =======================================================================
372 void OpenGl_View::SetBackgroundImage (const TCollection_AsciiString& theFilePath)
373 {
374   // Prepare aspect for texture storage
375   myBackgroundImagePath = theFilePath;
376   Handle(Graphic3d_AspectFillArea3d) anAspect = new Graphic3d_AspectFillArea3d();
377   Handle(Graphic3d_Texture2Dmanual) aTextureMap = new Graphic3d_Texture2Dmanual (TCollection_AsciiString (theFilePath));
378   aTextureMap->EnableRepeat();
379   aTextureMap->DisableModulate();
380   aTextureMap->GetParams()->SetGenMode (Graphic3d_TOTM_MANUAL,
381                                         Graphic3d_Vec4 (0.0f, 0.0f, 0.0f, 0.0f),
382                                         Graphic3d_Vec4 (0.0f, 0.0f, 0.0f, 0.0f));
383   anAspect->SetTextureMap (aTextureMap);
384   anAspect->SetInteriorStyle (Aspect_IS_SOLID);
385   anAspect->SetSuppressBackFaces (false);
386   // Enable texture mapping
387   if (aTextureMap->IsDone())
388   {
389     anAspect->SetTextureMapOn();
390   }
391   else
392   {
393     anAspect->SetTextureMapOff();
394     return;
395   }
396
397   // Set texture parameters
398   myTextureParams->SetAspect (anAspect);
399 }
400
401 // =======================================================================
402 // function : BackgroundImageStyle
403 // purpose  :
404 // =======================================================================
405 Aspect_FillMethod OpenGl_View::BackgroundImageStyle() const
406 {
407   return myBgTextureArray->TextureFillMethod();
408 }
409
410 // =======================================================================
411 // function : SetBackgroundImageStyle
412 // purpose  :
413 // =======================================================================
414 void OpenGl_View::SetBackgroundImageStyle (const Aspect_FillMethod theFillStyle)
415 {
416   myBgTextureArray->SetTextureFillMethod (theFillStyle);
417 }
418
419 //=======================================================================
420 //function : AddZLayer
421 //purpose  :
422 //=======================================================================
423 void OpenGl_View::AddZLayer (const Graphic3d_ZLayerId theLayerId)
424 {
425   myZLayers.AddLayer (theLayerId);
426 }
427
428 //=======================================================================
429 //function : RemoveZLayer
430 //purpose  :
431 //=======================================================================
432 void OpenGl_View::RemoveZLayer (const Graphic3d_ZLayerId theLayerId)
433 {
434   myZLayers.RemoveLayer (theLayerId);
435 }
436
437 //=======================================================================
438 //function : SetZLayerSettings
439 //purpose  :
440 //=======================================================================
441 void OpenGl_View::SetZLayerSettings (const Graphic3d_ZLayerId        theLayerId,
442                                      const Graphic3d_ZLayerSettings& theSettings)
443 {
444   myZLayers.SetLayerSettings (theLayerId, theSettings);
445 }
446
447 //=======================================================================
448 //function : ZLayerMax
449 //purpose  :
450 //=======================================================================
451 Standard_Integer OpenGl_View::ZLayerMax() const
452 {
453   Standard_Integer aLayerMax = Graphic3d_ZLayerId_Default;
454   for (OpenGl_LayerSeqIds::Iterator aMapIt(myZLayers.LayerIDs()); aMapIt.More(); aMapIt.Next())
455   {
456     aLayerMax = Max (aLayerMax, aMapIt.Value());
457   }
458
459   return aLayerMax;
460 }
461
462 //=======================================================================
463 //function : InvalidateZLayerBoundingBox
464 //purpose  :
465 //=======================================================================
466 void OpenGl_View::InvalidateZLayerBoundingBox (const Graphic3d_ZLayerId theLayerId) const
467 {
468   if (myZLayers.LayerIDs().IsBound (theLayerId))
469   {
470     myZLayers.Layer (theLayerId).InvalidateBoundingBox();
471   }
472   else
473   {
474     for (Standard_Integer aLayerId = Graphic3d_ZLayerId_Default; aLayerId < ZLayerMax(); ++aLayerId)
475     {
476       if (myZLayers.LayerIDs().IsBound (aLayerId))
477       {
478         const OpenGl_Layer& aLayer = myZLayers.Layer (aLayerId);
479         if (aLayer.NbOfTransformPersistenceObjects() > 0)
480         {
481           aLayer.InvalidateBoundingBox();
482         }
483       }
484     }
485   }
486 }
487
488 //=======================================================================
489 //function : ZLayerBoundingBox
490 //purpose  :
491 //=======================================================================
492 Graphic3d_BndBox4f OpenGl_View::ZLayerBoundingBox (const Graphic3d_ZLayerId        theLayerId,
493                                                    const Handle(Graphic3d_Camera)& theCamera,
494                                                    const Standard_Integer          theWindowWidth,
495                                                    const Standard_Integer          theWindowHeight,
496                                                    const Standard_Boolean          theToIncludeAuxiliary) const
497 {
498   Graphic3d_BndBox4f aBox;
499   if (myZLayers.LayerIDs().IsBound (theLayerId))
500   {
501     aBox = myZLayers.Layer (theLayerId).BoundingBox (Identification(),
502                                                      theCamera,
503                                                      theWindowWidth,
504                                                      theWindowHeight,
505                                                      theToIncludeAuxiliary);
506   }
507
508   // add bounding box of gradient/texture background for proper Z-fit
509   if (theToIncludeAuxiliary
510    && theLayerId == Graphic3d_ZLayerId_BotOSD
511    && (myBgTextureArray->IsDefined()
512     || myBgGradientArray->IsDefined()))
513   {
514     // Background is drawn using 2D transformation persistence
515     // (e.g. it is actually placed in 3D coordinates within active camera position).
516     // We add here full-screen plane with 2D transformation persistence
517     // for simplicity (myBgTextureArray might define a little bit different options
518     // but it is updated within ::Render())
519     const Graphic3d_Mat4& aProjectionMat = theCamera->ProjectionMatrixF();
520     const Graphic3d_Mat4& aWorldViewMat  = theCamera->OrientationMatrixF();
521     Graphic3d_BndBox4f aBox2d (Graphic3d_Vec4 (0.0f, 0.0f, 0.0f, 0.0f),
522                                Graphic3d_Vec4 (float(theWindowWidth), float(theWindowHeight), 0.0f, 0.0f));
523
524     Graphic3d_TransformPers aTrsfPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_LOWER);
525     aTrsfPers.Apply (theCamera,
526                      aProjectionMat,
527                      aWorldViewMat,
528                      theWindowWidth,
529                      theWindowHeight,
530                      aBox2d);
531     aBox.Combine (aBox2d);
532   }
533
534   return aBox;
535 }
536
537 //=======================================================================
538 //function : considerZoomPersistenceObjects
539 //purpose  :
540 //=======================================================================
541 Standard_Real OpenGl_View::considerZoomPersistenceObjects (const Graphic3d_ZLayerId        theLayerId,
542                                                            const Handle(Graphic3d_Camera)& theCamera,
543                                                            const Standard_Integer          theWindowWidth,
544                                                            const Standard_Integer          theWindowHeight) const
545 {
546   if (myZLayers.LayerIDs().IsBound (theLayerId))
547   {
548     return myZLayers.Layer (theLayerId).considerZoomPersistenceObjects (Identification(),
549                                                                         theCamera,
550                                                                         theWindowWidth,
551                                                                         theWindowHeight);
552   }
553
554   return 1.0;
555 }
556
557 //=======================================================================
558 //function : FBO
559 //purpose  :
560 //=======================================================================
561 Handle(Standard_Transient) OpenGl_View::FBO() const
562 {
563   return Handle(Standard_Transient)(myFBO);
564 }
565
566 //=======================================================================
567 //function : SetFBO
568 //purpose  :
569 //=======================================================================
570 void OpenGl_View::SetFBO (const Handle(Standard_Transient)& theFbo)
571 {
572   myFBO = Handle(OpenGl_FrameBuffer)::DownCast (theFbo);
573 }
574
575 //=======================================================================
576 //function : FBOCreate
577 //purpose  :
578 //=======================================================================
579 Handle(Standard_Transient) OpenGl_View::FBOCreate (const Standard_Integer theWidth,
580                                                    const Standard_Integer theHeight)
581 {
582   return myWorkspace->FBOCreate (theWidth, theHeight);
583 }
584
585 //=======================================================================
586 //function : FBORelease
587 //purpose  :
588 //=======================================================================
589 void OpenGl_View::FBORelease (Handle(Standard_Transient)& theFbo)
590 {
591   Handle(OpenGl_FrameBuffer) aFrameBuffer = Handle(OpenGl_FrameBuffer)::DownCast (theFbo);
592   if (aFrameBuffer.IsNull())
593   {
594     return;
595   }
596
597   myWorkspace->FBORelease (aFrameBuffer);
598   theFbo.Nullify();
599 }
600
601 //=======================================================================
602 //function : FBOGetDimensions
603 //purpose  :
604 //=======================================================================
605 void OpenGl_View::FBOGetDimensions (const Handle(Standard_Transient)& theFbo,
606                                     Standard_Integer& theWidth,
607                                     Standard_Integer& theHeight,
608                                     Standard_Integer& theWidthMax,
609                                     Standard_Integer& theHeightMax)
610 {
611   const Handle(OpenGl_FrameBuffer) aFrameBuffer = Handle(OpenGl_FrameBuffer)::DownCast (theFbo);
612   if (aFrameBuffer.IsNull())
613   {
614     return;
615   }
616
617   theWidth     = aFrameBuffer->GetVPSizeX(); // current viewport size
618   theHeight    = aFrameBuffer->GetVPSizeY();
619   theWidthMax  = aFrameBuffer->GetSizeX(); // texture size
620   theHeightMax = aFrameBuffer->GetSizeY();
621 }
622
623 //=======================================================================
624 //function : FBOChangeViewport
625 //purpose  :
626 //=======================================================================
627 void OpenGl_View::FBOChangeViewport (const Handle(Standard_Transient)& theFbo,
628                                      const Standard_Integer theWidth,
629                                      const Standard_Integer theHeight)
630 {
631   const Handle(OpenGl_FrameBuffer) aFrameBuffer = Handle(OpenGl_FrameBuffer)::DownCast (theFbo);
632   if (aFrameBuffer.IsNull())
633   {
634     return;
635   }
636
637   aFrameBuffer->ChangeViewport (theWidth, theHeight);
638 }
639
640 // =======================================================================
641 // function : Export
642 // purpose  :
643 // =======================================================================
644 #ifdef HAVE_GL2PS
645 Standard_Boolean OpenGl_View::Export (const Standard_CString theFileName,
646                                       const Graphic3d_ExportFormat theFormat,
647                                       const Graphic3d_SortType theSortType)
648 {
649   // gl2psBeginPage() will call OpenGL functions
650   // so we should activate correct GL context before redraw scene call
651   if (!myWorkspace->Activate())
652   {
653     return Standard_False;
654   }
655
656   Standard_Integer aFormat = -1;
657   Standard_Integer aSortType = Graphic3d_ST_BSP_Tree;
658   switch (theFormat)
659   {
660     case Graphic3d_EF_PostScript:
661       aFormat = GL2PS_PS;
662       break;
663     case Graphic3d_EF_EnhPostScript:
664       aFormat = GL2PS_EPS;
665       break;
666     case Graphic3d_EF_TEX:
667       aFormat = GL2PS_TEX;
668       break;
669     case Graphic3d_EF_PDF:
670       aFormat = GL2PS_PDF;
671       break;
672     case Graphic3d_EF_SVG:
673       aFormat = GL2PS_SVG;
674       break;
675     case Graphic3d_EF_PGF:
676       aFormat = GL2PS_PGF;
677       break;
678     case Graphic3d_EF_EMF:
679       //aFormat = GL2PS_EMF;
680       aFormat = GL2PS_PGF + 1; // 6
681       break;
682     default:
683       // unsupported format
684       return Standard_False;
685   }
686
687   switch (theSortType)
688   {
689     case Graphic3d_ST_Simple:
690       aSortType = GL2PS_SIMPLE_SORT;
691       break;
692     case Graphic3d_ST_BSP_Tree:
693       aSortType = GL2PS_BSP_SORT;
694       break;
695   }
696
697   GLint aViewport[4];
698   aViewport[0] = 0;
699   aViewport[1] = 0;
700   aViewport[2] = myWindow->Width();
701   aViewport[3] = myWindow->Height();
702
703   GLint aBufferSize = 1024 * 1024;
704   GLint anErrCode = GL2PS_SUCCESS;
705
706   // gl2ps uses standard write functions and do not check locale
707   Standard_CLocaleSentry aLocaleSentry;
708
709   while (aBufferSize > 0)
710   {
711     // current patch for EMF support in gl2ps uses WinAPI functions to create file
712     FILE* aFileH = (theFormat != Graphic3d_EF_EMF) ? fopen (theFileName, "wb") : NULL;
713     anErrCode = gl2psBeginPage ("", "", aViewport, aFormat, aSortType,
714                     GL2PS_DRAW_BACKGROUND | GL2PS_OCCLUSION_CULL | GL2PS_BEST_ROOT/* | GL2PS_SIMPLE_LINE_OFFSET*/,
715                     GL_RGBA, 0, NULL,
716                     0, 0, 0, aBufferSize, aFileH, theFileName);
717     if (anErrCode != GL2PS_SUCCESS)
718     {
719       // initialization failed
720       if (aFileH != NULL)
721         fclose (aFileH);
722       break;
723     }
724     Redraw();
725
726     anErrCode = gl2psEndPage();
727     if (aFileH != NULL)
728       fclose (aFileH);
729
730     if (anErrCode == GL2PS_OVERFLOW)
731       aBufferSize *= 2;
732     else
733       break;
734   }
735   return anErrCode == GL2PS_SUCCESS;
736 }
737 #else
738 Standard_Boolean OpenGl_View::Export (const Standard_CString /*theFileName*/,
739                                       const Graphic3d_ExportFormat /*theFormat*/,
740                                       const Graphic3d_SortType /*theSortType*/)
741 {
742     return Standard_False;
743 }
744 #endif
745
746 //=======================================================================
747 //function : displayStructure
748 //purpose  :
749 //=======================================================================
750 void OpenGl_View::displayStructure (const Handle(Graphic3d_CStructure)& theStructure,
751                                     const Standard_Integer              thePriority)
752 {
753   const OpenGl_Structure*  aStruct = reinterpret_cast<const OpenGl_Structure*> (theStructure.operator->());
754   const Graphic3d_ZLayerId aZLayer = aStruct->ZLayer();
755   myZLayers.AddStructure (aStruct, aZLayer, thePriority);
756 }
757
758 //=======================================================================
759 //function : eraseStructure
760 //purpose  :
761 //=======================================================================
762 void OpenGl_View::eraseStructure (const Handle(Graphic3d_CStructure)& theStructure)
763 {
764   const OpenGl_Structure*  aStruct = reinterpret_cast<const OpenGl_Structure*> (theStructure.operator->());
765   myZLayers.RemoveStructure (aStruct);
766 }
767
768 //=======================================================================
769 //function : changeZLayer
770 //purpose  :
771 //=======================================================================
772 void OpenGl_View::changeZLayer (const Handle(Graphic3d_CStructure)& theStructure,
773                                 const Graphic3d_ZLayerId theNewLayerId)
774 {
775   const Graphic3d_ZLayerId anOldLayer = theStructure->ZLayer();
776   const OpenGl_Structure* aStruct = reinterpret_cast<const OpenGl_Structure*> (theStructure.operator->());
777   myZLayers.ChangeLayer (aStruct, anOldLayer, theNewLayerId);
778   Update (Aspect_TOU_WAIT, anOldLayer);
779   Update (Aspect_TOU_WAIT, theNewLayerId);
780 }
781
782 //=======================================================================
783 //function : changePriority
784 //purpose  :
785 //=======================================================================
786 void OpenGl_View::changePriority (const Handle(Graphic3d_CStructure)& theStructure,
787                                   const Standard_Integer theNewPriority)
788 {
789   const Graphic3d_ZLayerId aLayerId = theStructure->ZLayer();
790   const OpenGl_Structure* aStruct = reinterpret_cast<const OpenGl_Structure*> (theStructure.operator->());
791   myZLayers.ChangePriority (aStruct, aLayerId, theNewPriority);
792 }
793
794 //=======================================================================
795 //function : DiagnosticInformation
796 //purpose  :
797 //=======================================================================
798 void OpenGl_View::DiagnosticInformation (TColStd_IndexedDataMapOfStringString& theDict,
799                                          Graphic3d_DiagnosticInfo theFlags) const
800 {
801   Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext();
802   if (!myWorkspace->Activate()
803    || aCtx.IsNull())
804   {
805     return;
806   }
807
808   aCtx->DiagnosticInformation (theDict, theFlags);
809   if ((theFlags & Graphic3d_DiagnosticInfo_FrameBuffer) != 0)
810   {
811     TCollection_AsciiString aResRatio (myRenderParams.ResolutionRatio());
812     theDict.ChangeFromIndex (theDict.Add ("ResolutionRatio", aResRatio)) = aResRatio;
813   }
814 }