0029528: Visualization, TKOpenGl - allow defining sRGB textures
[occt.git] / src / OpenGl / OpenGl_View_Redraw.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 <stdio.h>
17 #include <stdlib.h>
18
19 #include <OpenGl_GlCore11.hxx>
20
21 #include <Graphic3d_GraphicDriver.hxx>
22 #include <Graphic3d_StructureManager.hxx>
23 #include <Graphic3d_TextureParams.hxx>
24 #include <Graphic3d_Texture2Dmanual.hxx>
25 #include <Graphic3d_TransformUtils.hxx>
26 #include <Image_AlienPixMap.hxx>
27
28 #include <NCollection_Mat4.hxx>
29
30 #include <OpenGl_Context.hxx>
31 #include <OpenGl_FrameStats.hxx>
32 #include <OpenGl_Matrix.hxx>
33 #include <OpenGl_Workspace.hxx>
34 #include <OpenGl_View.hxx>
35 #include <OpenGl_GraduatedTrihedron.hxx>
36 #include <OpenGl_PrimitiveArray.hxx>
37 #include <OpenGl_ShaderManager.hxx>
38 #include <OpenGl_ShaderProgram.hxx>
39 #include <OpenGl_Structure.hxx>
40 #include <OpenGl_ArbFBO.hxx>
41
42 namespace
43 {
44   //! Format Frame Buffer format for logging messages.
45   static TCollection_AsciiString printFboFormat (const Handle(OpenGl_FrameBuffer)& theFbo)
46   {
47     return TCollection_AsciiString() + theFbo->GetInitVPSizeX() + "x" + theFbo->GetInitVPSizeY() + "@" + theFbo->NbSamples();
48   }
49
50   //! Return TRUE if Frame Buffer initialized has failed with the same parameters.
51   static bool checkWasFailedFbo (const Handle(OpenGl_FrameBuffer)& theFboToCheck,
52                                  Standard_Integer theSizeX,
53                                  Standard_Integer theSizeY,
54                                  Standard_Integer theNbSamples)
55   {
56     return !theFboToCheck->IsValid()
57         &&  theFboToCheck->GetInitVPSizeX() == theSizeX
58         &&  theFboToCheck->GetInitVPSizeY() == theSizeY
59         &&  theFboToCheck->NbSamples()      == theNbSamples;
60   }
61
62   //! Return TRUE if Frame Buffer initialized has failed with the same parameters.
63   static bool checkWasFailedFbo (const Handle(OpenGl_FrameBuffer)& theFboToCheck,
64                                  const Handle(OpenGl_FrameBuffer)& theFboRef)
65   {
66     return checkWasFailedFbo (theFboToCheck, theFboRef->GetVPSizeX(), theFboRef->GetVPSizeY(), theFboRef->NbSamples());
67   }
68 }
69
70 //=======================================================================
71 //function : drawBackground
72 //purpose  :
73 //=======================================================================
74 void OpenGl_View::drawBackground (const Handle(OpenGl_Workspace)& theWorkspace)
75 {
76   const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
77   const Standard_Boolean wasUsedZBuffer = theWorkspace->SetUseZBuffer (Standard_False);
78   if (wasUsedZBuffer)
79   {
80     aCtx->core11fwd->glDisable (GL_DEPTH_TEST);
81   }
82
83   if (myBackgroundType == Graphic3d_TOB_CUBEMAP)
84   {
85     Graphic3d_Camera aCamera (theWorkspace->View()->Camera());
86     aCamera.SetZRange (0.01, 1.0); // is needed to avoid perspective camera exception
87     aCamera.SetProjectionType (Graphic3d_Camera::Projection_Perspective);
88
89     aCtx->ProjectionState.Push();
90     aCtx->ProjectionState.SetCurrent (aCamera.ProjectionMatrixF());
91
92     myCubeMapParams->Aspect()->ShaderProgram()->PushVariableInt ("uZCoeff", myBackgroundCubeMap->ZIsInverted() ? -1 : 1);
93     myCubeMapParams->Aspect()->ShaderProgram()->PushVariableInt ("uYCoeff", myBackgroundCubeMap->IsTopDown() ? 1 : -1);
94     const OpenGl_Aspects* anOldAspectFace = theWorkspace->SetAspects (myCubeMapParams);
95
96     myBackgrounds[Graphic3d_TOB_CUBEMAP]->Render (theWorkspace);
97
98     aCtx->ProjectionState.Pop();
99     aCtx->ApplyProjectionMatrix();
100     theWorkspace->SetAspects (anOldAspectFace);
101   }
102   else if (myBackgroundType == Graphic3d_TOB_GRADIENT
103         || myBackgroundType == Graphic3d_TOB_TEXTURE)
104   {
105     // Drawing background gradient if:
106     // - gradient fill type is not Aspect_GFM_NONE and
107     // - either background texture is no specified or it is drawn in Aspect_FM_CENTERED mode
108     if (myBackgrounds[Graphic3d_TOB_GRADIENT]->IsDefined()
109       && (!myTextureParams->Aspect()->ToMapTexture()
110         || myBackgrounds[Graphic3d_TOB_TEXTURE]->TextureFillMethod() == Aspect_FM_CENTERED
111         || myBackgrounds[Graphic3d_TOB_TEXTURE]->TextureFillMethod() == Aspect_FM_NONE))
112     {
113       #if !defined(GL_ES_VERSION_2_0)
114       GLint aShadingModelOld = GL_SMOOTH;
115       if (aCtx->core11 != NULL
116         && aCtx->caps->ffpEnable)
117       {
118         aCtx->core11fwd->glDisable (GL_LIGHTING);
119         aCtx->core11fwd->glGetIntegerv (GL_SHADE_MODEL, &aShadingModelOld);
120         aCtx->core11->glShadeModel (GL_SMOOTH);
121       }
122       #endif
123
124       myBackgrounds[Graphic3d_TOB_GRADIENT]->Render(theWorkspace);
125
126       #if !defined(GL_ES_VERSION_2_0)
127       if (aCtx->core11 != NULL
128         && aCtx->caps->ffpEnable)
129       {
130         aCtx->core11->glShadeModel (aShadingModelOld);
131       }
132       #endif
133     }
134
135     // Drawing background image if it is defined
136     // (texture is defined and fill type is not Aspect_FM_NONE)
137     if (myBackgrounds[Graphic3d_TOB_TEXTURE]->IsDefined()
138       && myTextureParams->Aspect()->ToMapTexture())
139     {
140       aCtx->core11fwd->glDisable (GL_BLEND);
141
142       const OpenGl_Aspects* anOldAspectFace = theWorkspace->SetAspects (myTextureParams);
143       myBackgrounds[Graphic3d_TOB_TEXTURE]->Render (theWorkspace);
144       theWorkspace->SetAspects (anOldAspectFace);
145     }
146   }
147
148   if (wasUsedZBuffer)
149   {
150     theWorkspace->SetUseZBuffer (Standard_True);
151     aCtx->core11fwd->glEnable (GL_DEPTH_TEST);
152   }
153 }
154
155 //=======================================================================
156 //function : Redraw
157 //purpose  :
158 //=======================================================================
159 void OpenGl_View::Redraw()
160 {
161   const Standard_Boolean wasDisabledMSAA = myToDisableMSAA;
162   const Standard_Boolean hadFboBlit      = myHasFboBlit;
163   if (myRenderParams.Method == Graphic3d_RM_RAYTRACING
164   && !myCaps->vboDisable
165   && !myCaps->keepArrayData)
166   {
167     // caps are shared across all views, thus we need to invalidate all of them
168     // if (myWasRedrawnGL) { myStructureManager->SetDeviceLost(); }
169     myDriver->setDeviceLost();
170     myCaps->keepArrayData = Standard_True;
171   }
172
173   if (!myWorkspace->Activate())
174   {
175     return;
176   }
177
178   myWindow->SetSwapInterval();
179
180   ++myFrameCounter;
181   const Graphic3d_StereoMode   aStereoMode  = myRenderParams.StereoMode;
182   Graphic3d_Camera::Projection aProjectType = myCamera->ProjectionType();
183   const Handle(OpenGl_Context)& aCtx        = myWorkspace->GetGlContext();
184   aCtx->FrameStats()->FrameStart (myWorkspace->View(), false);
185   aCtx->SetLineFeather (myRenderParams.LineFeather);
186
187   const Standard_Integer anSRgbState = aCtx->ToRenderSRGB() ? 1 : 0;
188   if (mySRgbState != -1
189    && mySRgbState != anSRgbState)
190   {
191     releaseSrgbResources (aCtx);
192     initTextureEnv (aCtx);
193   }
194   mySRgbState = anSRgbState;
195   aCtx->ShaderManager()->UpdateSRgbState();
196
197   // release pending GL resources
198   aCtx->ReleaseDelayed();
199
200   // fetch OpenGl context state
201   aCtx->FetchState();
202
203   OpenGl_FrameBuffer* aFrameBuffer = myFBO.get();
204   bool toSwap = aCtx->IsRender()
205             && !aCtx->caps->buffersNoSwap
206             &&  aFrameBuffer == NULL;
207
208   const Standard_Integer aSizeX = aFrameBuffer != NULL ? aFrameBuffer->GetVPSizeX() : myWindow->Width();
209   const Standard_Integer aSizeY = aFrameBuffer != NULL ? aFrameBuffer->GetVPSizeY() : myWindow->Height();
210   const Standard_Integer aRendSizeX = Standard_Integer(myRenderParams.RenderResolutionScale * aSizeX + 0.5f);
211   const Standard_Integer aRendSizeY = Standard_Integer(myRenderParams.RenderResolutionScale * aSizeY + 0.5f);
212   if (aSizeX < 1
213    || aSizeY < 1
214    || aRendSizeX < 1
215    || aRendSizeY < 1)
216   {
217     myBackBufferRestored = Standard_False;
218     myIsImmediateDrawn   = Standard_False;
219     return;
220   }
221
222   // determine multisampling parameters
223   Standard_Integer aNbSamples = !myToDisableMSAA && aSizeX == aRendSizeX
224                               ? Max (Min (myRenderParams.NbMsaaSamples, aCtx->MaxMsaaSamples()), 0)
225                               : 0;
226   if (aNbSamples != 0)
227   {
228     aNbSamples = OpenGl_Context::GetPowerOfTwo (aNbSamples, aCtx->MaxMsaaSamples());
229   }
230
231   bool toUseOit = myRenderParams.TransparencyMethod == Graphic3d_RTM_BLEND_OIT
232                && checkOitCompatibility (aCtx, aNbSamples > 0);
233
234   const bool toInitImmediateFbo = myTransientDrawToFront
235                                && (!aCtx->caps->useSystemBuffer || (toUseOit && HasImmediateStructures()));
236
237   if ( aFrameBuffer == NULL
238    && !aCtx->DefaultFrameBuffer().IsNull()
239    &&  aCtx->DefaultFrameBuffer()->IsValid())
240   {
241     aFrameBuffer = aCtx->DefaultFrameBuffer().operator->();
242   }
243
244   if (myHasFboBlit
245    && (myTransientDrawToFront
246     || aProjectType == Graphic3d_Camera::Projection_Stereo
247     || aNbSamples != 0
248     || toUseOit
249     || aSizeX != aRendSizeX))
250   {
251     if (myMainSceneFbos[0]->GetVPSizeX() != aRendSizeX
252      || myMainSceneFbos[0]->GetVPSizeY() != aRendSizeY
253      || myMainSceneFbos[0]->NbSamples()  != aNbSamples)
254     {
255       if (!myTransientDrawToFront)
256       {
257         myImmediateSceneFbos[0]->Release (aCtx.operator->());
258         myImmediateSceneFbos[1]->Release (aCtx.operator->());
259         myImmediateSceneFbos[0]->ChangeViewport (0, 0);
260         myImmediateSceneFbos[1]->ChangeViewport (0, 0);
261       }
262
263       // prepare FBOs containing main scene
264       // for further blitting and rendering immediate presentations on top
265       if (aCtx->core20fwd != NULL)
266       {
267         const bool wasFailedMain0 = checkWasFailedFbo (myMainSceneFbos[0], aRendSizeX, aRendSizeY, aNbSamples);
268         if (!myMainSceneFbos[0]->Init (aCtx, aRendSizeX, aRendSizeY, myFboColorFormat, myFboDepthFormat, aNbSamples)
269          && !wasFailedMain0)
270         {
271           TCollection_ExtendedString aMsg = TCollection_ExtendedString() + "Error! Main FBO "
272                                           + printFboFormat (myMainSceneFbos[0]) + " initialization has failed";
273           aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aMsg);
274         }
275       }
276     }
277     if (myMainSceneFbos[0]->IsValid() && (toInitImmediateFbo || myImmediateSceneFbos[0]->IsValid()))
278     {
279       const bool wasFailedImm0 = checkWasFailedFbo (myImmediateSceneFbos[0], myMainSceneFbos[0]);
280       if (!myImmediateSceneFbos[0]->InitLazy (aCtx, *myMainSceneFbos[0])
281        && !wasFailedImm0)
282       {
283         TCollection_ExtendedString aMsg = TCollection_ExtendedString() + "Error! Immediate FBO "
284                                         + printFboFormat (myImmediateSceneFbos[0]) + " initialization has failed";
285         aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aMsg);
286       }
287     }
288   }
289   else
290   {
291     myMainSceneFbos     [0]->Release (aCtx.operator->());
292     myMainSceneFbos     [1]->Release (aCtx.operator->());
293     myImmediateSceneFbos[0]->Release (aCtx.operator->());
294     myImmediateSceneFbos[1]->Release (aCtx.operator->());
295     myMainSceneFbos     [0]->ChangeViewport (0, 0);
296     myMainSceneFbos     [1]->ChangeViewport (0, 0);
297     myImmediateSceneFbos[0]->ChangeViewport (0, 0);
298     myImmediateSceneFbos[1]->ChangeViewport (0, 0);
299   }
300
301   if (aProjectType == Graphic3d_Camera::Projection_Stereo
302    && myMainSceneFbos[0]->IsValid())
303   {
304     const bool wasFailedMain1 = checkWasFailedFbo (myMainSceneFbos[1], myMainSceneFbos[0]);
305     if (!myMainSceneFbos[1]->InitLazy (aCtx, *myMainSceneFbos[0])
306      && !wasFailedMain1)
307     {
308       TCollection_ExtendedString aMsg = TCollection_ExtendedString() + "Error! Main FBO (second) "
309                                       + printFboFormat (myMainSceneFbos[1]) + " initialization has failed";
310       aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aMsg);
311     }
312     if (!myMainSceneFbos[1]->IsValid())
313     {
314       // no enough memory?
315       aProjectType = Graphic3d_Camera::Projection_Perspective;
316     }
317     else if (!myTransientDrawToFront)
318     {
319       //
320     }
321     else if (!aCtx->HasStereoBuffers() || aStereoMode != Graphic3d_StereoMode_QuadBuffer)
322     {
323       const bool wasFailedImm0 = checkWasFailedFbo (myImmediateSceneFbos[0], myMainSceneFbos[0]);
324       const bool wasFailedImm1 = checkWasFailedFbo (myImmediateSceneFbos[1], myMainSceneFbos[0]);
325       if (!myImmediateSceneFbos[0]->InitLazy (aCtx, *myMainSceneFbos[0])
326        && !wasFailedImm0)
327       {
328         TCollection_ExtendedString aMsg = TCollection_ExtendedString() + "Error! Immediate FBO (first) "
329                                         + printFboFormat (myImmediateSceneFbos[0]) + " initialization has failed";
330         aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aMsg);
331       }
332       if (!myImmediateSceneFbos[1]->InitLazy (aCtx, *myMainSceneFbos[0])
333        && !wasFailedImm1)
334       {
335         TCollection_ExtendedString aMsg = TCollection_ExtendedString() + "Error! Immediate FBO (first) "
336                                         + printFboFormat (myImmediateSceneFbos[1]) + " initialization has failed";
337         aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aMsg);
338       }
339       if (!myImmediateSceneFbos[0]->IsValid()
340        || !myImmediateSceneFbos[1]->IsValid())
341       {
342         aProjectType = Graphic3d_Camera::Projection_Perspective;
343       }
344     }
345   }
346
347   // create color and coverage accumulation buffers required for OIT algorithm
348   if (toUseOit)
349   {
350     Standard_Integer anFboIt = 0;
351     for (; anFboIt < 2; ++anFboIt)
352     {
353       Handle(OpenGl_FrameBuffer)& aMainSceneFbo          = myMainSceneFbos        [anFboIt];
354       Handle(OpenGl_FrameBuffer)& aMainSceneFboOit       = myMainSceneFbosOit     [anFboIt];
355       Handle(OpenGl_FrameBuffer)& anImmediateSceneFbo    = myImmediateSceneFbos   [anFboIt];
356       Handle(OpenGl_FrameBuffer)& anImmediateSceneFboOit = myImmediateSceneFbosOit[anFboIt];
357       if (aMainSceneFbo->IsValid()
358        && (aMainSceneFboOit->GetVPSizeX() != aRendSizeX
359         || aMainSceneFboOit->GetVPSizeY() != aRendSizeY
360         || aMainSceneFboOit->NbSamples()  != aNbSamples))
361       {
362         Standard_Integer aColorConfig = 0;
363         for (;;) // seemly responding to driver limitation (GL_FRAMEBUFFER_UNSUPPORTED)
364         {
365           if (myFboOitColorConfig.IsEmpty())
366           {
367             if (!chooseOitColorConfiguration (aCtx, aColorConfig++, myFboOitColorConfig))
368             {
369               break;
370             }
371           }
372           if (aMainSceneFboOit->Init (aCtx, aRendSizeX, aRendSizeY, myFboOitColorConfig, aMainSceneFbo->DepthStencilTexture(), aNbSamples))
373           {
374             break;
375           }
376           myFboOitColorConfig.Clear();
377         }
378         if (!aMainSceneFboOit->IsValid())
379         {
380           break;
381         }
382       }
383       else if (!aMainSceneFbo->IsValid())
384       {
385         aMainSceneFboOit->Release (aCtx.operator->());
386         aMainSceneFboOit->ChangeViewport (0, 0);
387       }
388
389       if (anImmediateSceneFbo->IsValid()
390        && (anImmediateSceneFboOit->GetVPSizeX() != aRendSizeX
391         || anImmediateSceneFboOit->GetVPSizeY() != aRendSizeY
392         || anImmediateSceneFboOit->NbSamples()  != aNbSamples))
393       {
394         if (!anImmediateSceneFboOit->Init (aCtx, aRendSizeX, aRendSizeY, myFboOitColorConfig,
395                                            anImmediateSceneFbo->DepthStencilTexture(), aNbSamples))
396         {
397           break;
398         }
399       }
400       else if (!anImmediateSceneFbo->IsValid())
401       {
402         anImmediateSceneFboOit->Release (aCtx.operator->());
403         anImmediateSceneFboOit->ChangeViewport (0, 0);
404       }
405     }
406     if (anFboIt == 0) // only the first OIT framebuffer is mandatory
407     {
408       aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
409                          "Initialization of float texture framebuffer for use with\n"
410                          "  blended order-independent transparency rendering algorithm has failed.\n"
411                          "  Blended order-independent transparency will not be available.\n");
412       if (aNbSamples > 0)
413       {
414         myToDisableOITMSAA = Standard_True;
415       }
416       else
417       {
418         myToDisableOIT     = Standard_True;
419       }
420       toUseOit = false;
421     }
422   }
423   if (!toUseOit && myMainSceneFbosOit[0]->IsValid())
424   {
425     myMainSceneFbosOit     [0]->Release (aCtx.operator->());
426     myMainSceneFbosOit     [1]->Release (aCtx.operator->());
427     myImmediateSceneFbosOit[0]->Release (aCtx.operator->());
428     myImmediateSceneFbosOit[1]->Release (aCtx.operator->());
429     myMainSceneFbosOit     [0]->ChangeViewport (0, 0);
430     myMainSceneFbosOit     [1]->ChangeViewport (0, 0);
431     myImmediateSceneFbosOit[0]->ChangeViewport (0, 0);
432     myImmediateSceneFbosOit[1]->ChangeViewport (0, 0);
433   }
434
435   if (aProjectType == Graphic3d_Camera::Projection_Stereo)
436   {
437     OpenGl_FrameBuffer* aMainFbos[2] =
438     {
439       myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL,
440       myMainSceneFbos[1]->IsValid() ? myMainSceneFbos[1].operator->() : NULL
441     };
442     OpenGl_FrameBuffer* aMainFbosOit[2] =
443     {
444       myMainSceneFbosOit[0]->IsValid() ? myMainSceneFbosOit[0].operator->() : NULL,
445       myMainSceneFbosOit[1]->IsValid() ? myMainSceneFbosOit[1].operator->() :
446         myMainSceneFbosOit[0]->IsValid() ? myMainSceneFbosOit[0].operator->() : NULL
447     };
448
449     OpenGl_FrameBuffer* anImmFbos[2] =
450     {
451       myImmediateSceneFbos[0]->IsValid() ? myImmediateSceneFbos[0].operator->() : NULL,
452       myImmediateSceneFbos[1]->IsValid() ? myImmediateSceneFbos[1].operator->() : NULL
453     };
454     OpenGl_FrameBuffer* anImmFbosOit[2] =
455     {
456       myImmediateSceneFbosOit[0]->IsValid() ? myImmediateSceneFbosOit[0].operator->() : NULL,
457       myImmediateSceneFbosOit[1]->IsValid() ? myImmediateSceneFbosOit[1].operator->() :
458         myImmediateSceneFbosOit[0]->IsValid() ? myImmediateSceneFbosOit[0].operator->() : NULL
459     };
460
461     if (!myTransientDrawToFront)
462     {
463       anImmFbos   [0] = aMainFbos   [0];
464       anImmFbos   [1] = aMainFbos   [1];
465       anImmFbosOit[0] = aMainFbosOit[0];
466       anImmFbosOit[1] = aMainFbosOit[1];
467     }
468     else if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip
469           || aStereoMode == Graphic3d_StereoMode_QuadBuffer)
470     {
471       anImmFbos   [0] = NULL;
472       anImmFbos   [1] = NULL;
473       anImmFbosOit[0] = NULL;
474       anImmFbosOit[1] = NULL;
475     }
476
477   #if !defined(GL_ES_VERSION_2_0)
478     aCtx->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_LEFT : GL_BACK);
479   #endif
480     aCtx->SetResolution (myRenderParams.Resolution, myRenderParams.ResolutionRatio(),
481                          aMainFbos[0] != NULL ? myRenderParams.RenderResolutionScale : 1.0f);
482
483     redraw (Graphic3d_Camera::Projection_MonoLeftEye, aMainFbos[0], aMainFbosOit[0]);
484     myBackBufferRestored = Standard_True;
485     myIsImmediateDrawn   = Standard_False;
486   #if !defined(GL_ES_VERSION_2_0)
487     aCtx->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_LEFT : GL_BACK);
488   #endif
489     aCtx->SetResolution (myRenderParams.Resolution, myRenderParams.ResolutionRatio(),
490                          anImmFbos[0] != NULL ? myRenderParams.RenderResolutionScale : 1.0f);
491     if (!redrawImmediate (Graphic3d_Camera::Projection_MonoLeftEye, aMainFbos[0], anImmFbos[0], anImmFbosOit[0]))
492     {
493       toSwap = false;
494     }
495     else if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip && toSwap)
496     {
497       aCtx->SwapBuffers();
498     }
499
500   #if !defined(GL_ES_VERSION_2_0)
501     aCtx->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_RIGHT : GL_BACK);
502   #endif
503     aCtx->SetResolution (myRenderParams.Resolution, myRenderParams.ResolutionRatio(),
504                          aMainFbos[1] != NULL ? myRenderParams.RenderResolutionScale : 1.0f);
505
506     redraw (Graphic3d_Camera::Projection_MonoRightEye, aMainFbos[1], aMainFbosOit[1]);
507     myBackBufferRestored = Standard_True;
508     myIsImmediateDrawn   = Standard_False;
509     aCtx->SetResolution (myRenderParams.Resolution, myRenderParams.ResolutionRatio(),
510                          anImmFbos[1] != NULL ? myRenderParams.RenderResolutionScale : 1.0f);
511     if (!redrawImmediate (Graphic3d_Camera::Projection_MonoRightEye, aMainFbos[1], anImmFbos[1], anImmFbosOit[1]))
512     {
513       toSwap = false;
514     }
515
516     if (anImmFbos[0] != NULL)
517     {
518       aCtx->SetResolution (myRenderParams.Resolution, myRenderParams.ResolutionRatio(), 1.0f);
519       drawStereoPair (aFrameBuffer);
520     }
521   }
522   else
523   {
524     OpenGl_FrameBuffer* aMainFbo    = myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : aFrameBuffer;
525     OpenGl_FrameBuffer* aMainFboOit = myMainSceneFbosOit[0]->IsValid() ? myMainSceneFbosOit[0].operator->() : NULL;
526     OpenGl_FrameBuffer* anImmFbo    = aFrameBuffer;
527     OpenGl_FrameBuffer* anImmFboOit = NULL;
528     if (!myTransientDrawToFront)
529     {
530       anImmFbo    = aMainFbo;
531       anImmFboOit = aMainFboOit;
532     }
533     else if (myImmediateSceneFbos[0]->IsValid())
534     {
535       anImmFbo    = myImmediateSceneFbos[0].operator->();
536       anImmFboOit = myImmediateSceneFbosOit[0]->IsValid() ? myImmediateSceneFbosOit[0].operator->() : NULL;
537     }
538
539   #if !defined(GL_ES_VERSION_2_0)
540     if (aMainFbo == NULL)
541     {
542       aCtx->SetReadDrawBuffer (GL_BACK);
543     }
544   #endif
545     aCtx->SetResolution (myRenderParams.Resolution, myRenderParams.ResolutionRatio(),
546                          aMainFbo != aFrameBuffer ? myRenderParams.RenderResolutionScale : 1.0f);
547
548     redraw (aProjectType, aMainFbo, aMainFboOit);
549     myBackBufferRestored = Standard_True;
550     myIsImmediateDrawn   = Standard_False;
551     aCtx->SetResolution (myRenderParams.Resolution, myRenderParams.ResolutionRatio(),
552                          anImmFbo != aFrameBuffer ? myRenderParams.RenderResolutionScale : 1.0f);
553     if (!redrawImmediate (aProjectType, aMainFbo, anImmFbo, anImmFboOit))
554     {
555       toSwap = false;
556     }
557
558     if (anImmFbo != NULL
559      && anImmFbo != aFrameBuffer)
560     {
561       blitBuffers (anImmFbo, aFrameBuffer, myToFlipOutput);
562     }
563   }
564
565   if (myRenderParams.Method == Graphic3d_RM_RAYTRACING
566    && myRenderParams.IsGlobalIlluminationEnabled)
567   {
568     myAccumFrames++;
569   }
570
571   // bind default FBO
572   bindDefaultFbo();
573
574   if (wasDisabledMSAA != myToDisableMSAA
575    || hadFboBlit      != myHasFboBlit)
576   {
577     // retry on error
578     Redraw();
579   }
580
581   // reset state for safety
582   aCtx->BindProgram (Handle(OpenGl_ShaderProgram)());
583   if (aCtx->caps->ffpEnable)
584   {
585     aCtx->ShaderManager()->PushState (Handle(OpenGl_ShaderProgram)());
586   }
587
588   // Swap the buffers
589   if (toSwap)
590   {
591     aCtx->SwapBuffers();
592     if (!myMainSceneFbos[0]->IsValid())
593     {
594       myBackBufferRestored = Standard_False;
595     }
596   }
597   else
598   {
599     aCtx->core11fwd->glFlush();
600   }
601
602   // reset render mode state
603   aCtx->FetchState();
604   aCtx->FrameStats()->FrameEnd (myWorkspace->View(), false);
605
606   myWasRedrawnGL = Standard_True;
607 }
608
609 // =======================================================================
610 // function : RedrawImmediate
611 // purpose  :
612 // =======================================================================
613 void OpenGl_View::RedrawImmediate()
614 {
615   if (!myWorkspace->Activate())
616     return;
617
618   Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext();
619   if (!myTransientDrawToFront
620    || !myBackBufferRestored
621    || (aCtx->caps->buffersNoSwap && !myMainSceneFbos[0]->IsValid()))
622   {
623     Redraw();
624     return;
625   }
626
627   const Graphic3d_StereoMode   aStereoMode  = myRenderParams.StereoMode;
628   Graphic3d_Camera::Projection aProjectType = myCamera->ProjectionType();
629   OpenGl_FrameBuffer*          aFrameBuffer = myFBO.get();
630   aCtx->FrameStats()->FrameStart (myWorkspace->View(), true);
631
632   if ( aFrameBuffer == NULL
633    && !aCtx->DefaultFrameBuffer().IsNull()
634    &&  aCtx->DefaultFrameBuffer()->IsValid())
635   {
636     aFrameBuffer = aCtx->DefaultFrameBuffer().operator->();
637   }
638
639   if (aProjectType == Graphic3d_Camera::Projection_Stereo)
640   {
641     if (myMainSceneFbos[0]->IsValid()
642     && !myMainSceneFbos[1]->IsValid())
643     {
644       aProjectType = Graphic3d_Camera::Projection_Perspective;
645     }
646   }
647
648   bool toSwap = false;
649   if (aProjectType == Graphic3d_Camera::Projection_Stereo)
650   {
651     OpenGl_FrameBuffer* aMainFbos[2] =
652     {
653       myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL,
654       myMainSceneFbos[1]->IsValid() ? myMainSceneFbos[1].operator->() : NULL
655     };
656     OpenGl_FrameBuffer* anImmFbos[2] =
657     {
658       myImmediateSceneFbos[0]->IsValid() ? myImmediateSceneFbos[0].operator->() : NULL,
659       myImmediateSceneFbos[1]->IsValid() ? myImmediateSceneFbos[1].operator->() : NULL
660     };
661     OpenGl_FrameBuffer* anImmFbosOit[2] =
662     {
663       myImmediateSceneFbosOit[0]->IsValid() ? myImmediateSceneFbosOit[0].operator->() : NULL,
664       myImmediateSceneFbosOit[1]->IsValid() ? myImmediateSceneFbosOit[1].operator->() :
665         myImmediateSceneFbosOit[0]->IsValid() ? myImmediateSceneFbosOit[0].operator->() : NULL
666     };
667     if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip
668      || aStereoMode == Graphic3d_StereoMode_QuadBuffer)
669     {
670       anImmFbos[0]    = NULL;
671       anImmFbos[1]    = NULL;
672       anImmFbosOit[0] = NULL;
673       anImmFbosOit[1] = NULL;
674     }
675
676     if (aCtx->arbFBO != NULL)
677     {
678       aCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
679     }
680   #if !defined(GL_ES_VERSION_2_0)
681     if (anImmFbos[0] == NULL)
682     {
683       aCtx->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_LEFT : GL_BACK);
684     }
685   #endif
686
687     aCtx->SetResolution (myRenderParams.Resolution, myRenderParams.ResolutionRatio(),
688                          anImmFbos[0] != NULL ? myRenderParams.RenderResolutionScale : 1.0f);
689     toSwap = redrawImmediate (Graphic3d_Camera::Projection_MonoLeftEye,
690                               aMainFbos[0],
691                               anImmFbos[0],
692                               anImmFbosOit[0],
693                               Standard_True) || toSwap;
694     if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip
695     &&  toSwap
696     && !aCtx->caps->buffersNoSwap)
697     {
698       aCtx->SwapBuffers();
699     }
700
701     if (aCtx->arbFBO != NULL)
702     {
703       aCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
704     }
705   #if !defined(GL_ES_VERSION_2_0)
706     if (anImmFbos[1] == NULL)
707     {
708       aCtx->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_RIGHT : GL_BACK);
709     }
710   #endif
711     aCtx->SetResolution (myRenderParams.Resolution, myRenderParams.ResolutionRatio(),
712                          anImmFbos[1] != NULL ? myRenderParams.RenderResolutionScale : 1.0f);
713     toSwap = redrawImmediate (Graphic3d_Camera::Projection_MonoRightEye,
714                               aMainFbos[1],
715                               anImmFbos[1],
716                               anImmFbosOit[1],
717                               Standard_True) || toSwap;
718     if (anImmFbos[0] != NULL)
719     {
720       drawStereoPair (aFrameBuffer);
721     }
722   }
723   else
724   {
725     OpenGl_FrameBuffer* aMainFbo = myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL;
726     OpenGl_FrameBuffer* anImmFbo = aFrameBuffer;
727     OpenGl_FrameBuffer* anImmFboOit = NULL;
728     if (myImmediateSceneFbos[0]->IsValid())
729     {
730       anImmFbo    = myImmediateSceneFbos[0].operator->();
731       anImmFboOit = myImmediateSceneFbosOit[0]->IsValid() ? myImmediateSceneFbosOit[0].operator->() : NULL;
732     }
733   #if !defined(GL_ES_VERSION_2_0)
734     if (aMainFbo == NULL)
735     {
736       aCtx->SetReadDrawBuffer (GL_BACK);
737     }
738   #endif
739     aCtx->SetResolution (myRenderParams.Resolution, myRenderParams.ResolutionRatio(),
740                          anImmFbo != aFrameBuffer ? myRenderParams.RenderResolutionScale : 1.0f);
741     toSwap = redrawImmediate (aProjectType,
742                               aMainFbo,
743                               anImmFbo,
744                               anImmFboOit,
745                               Standard_True) || toSwap;
746     if (anImmFbo != NULL
747      && anImmFbo != aFrameBuffer)
748     {
749       blitBuffers (anImmFbo, aFrameBuffer, myToFlipOutput);
750     }
751   }
752
753   // bind default FBO
754   bindDefaultFbo();
755
756   // reset state for safety
757   aCtx->BindProgram (Handle(OpenGl_ShaderProgram)());
758   if (aCtx->caps->ffpEnable)
759   {
760     aCtx->ShaderManager()->PushState (Handle(OpenGl_ShaderProgram)());
761   }
762
763   if (toSwap && !aCtx->caps->buffersNoSwap)
764   {
765     aCtx->SwapBuffers();
766   }
767   else
768   {
769     aCtx->core11fwd->glFlush();
770   }
771   aCtx->FrameStats()->FrameEnd (myWorkspace->View(), true);
772
773   myWasRedrawnGL = Standard_True;
774 }
775
776 // =======================================================================
777 // function : redraw
778 // purpose  :
779 // =======================================================================
780 void OpenGl_View::redraw (const Graphic3d_Camera::Projection theProjection,
781                           OpenGl_FrameBuffer*                theReadDrawFbo,
782                           OpenGl_FrameBuffer*                theOitAccumFbo)
783 {
784   Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext();
785   if (theReadDrawFbo != NULL)
786   {
787     theReadDrawFbo->BindBuffer    (aCtx);
788     theReadDrawFbo->SetupViewport (aCtx);
789   }
790   else
791   {
792     const Standard_Integer aViewport[4] = { 0, 0, myWindow->Width(), myWindow->Height() };
793     aCtx->ResizeViewport (aViewport);
794   }
795
796   // request reset of material
797   aCtx->ShaderManager()->UpdateMaterialState();
798
799   myWorkspace->UseZBuffer()    = Standard_True;
800   myWorkspace->UseDepthWrite() = Standard_True;
801   GLbitfield toClear = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT;
802   glDepthFunc (GL_LEQUAL);
803   glDepthMask (GL_TRUE);
804   glEnable (GL_DEPTH_TEST);
805
806 #if !defined(GL_ES_VERSION_2_0)
807   glClearDepth (1.0);
808 #else
809   glClearDepthf (1.0f);
810 #endif
811
812   const OpenGl_Vec4 aBgColor = aCtx->Vec4FromQuantityColor (myBgColor);
813   glClearColor (aBgColor.r(), aBgColor.g(), aBgColor.b(), 0.0f);
814
815   glClear (toClear);
816
817   render (theProjection, theReadDrawFbo, theOitAccumFbo, Standard_False);
818 }
819
820 // =======================================================================
821 // function : redrawMonoImmediate
822 // purpose  :
823 // =======================================================================
824 bool OpenGl_View::redrawImmediate (const Graphic3d_Camera::Projection theProjection,
825                                    OpenGl_FrameBuffer*                theReadFbo,
826                                    OpenGl_FrameBuffer*                theDrawFbo,
827                                    OpenGl_FrameBuffer*                theOitAccumFbo,
828                                    const Standard_Boolean             theIsPartialUpdate)
829 {
830   const Handle(OpenGl_Context)& aCtx = myWorkspace->GetGlContext();
831   GLboolean toCopyBackToFront = GL_FALSE;
832   if (theDrawFbo == theReadFbo
833    && theDrawFbo != NULL)
834   {
835     myBackBufferRestored = Standard_False;
836   }
837   else if (theReadFbo != NULL
838         && theReadFbo->IsValid()
839         && aCtx->IsRender())
840   {
841     if (!blitBuffers (theReadFbo, theDrawFbo))
842     {
843       return true;
844     }
845   }
846   else if (theDrawFbo == NULL)
847   {
848   #if !defined(GL_ES_VERSION_2_0)
849     aCtx->core11fwd->glGetBooleanv (GL_DOUBLEBUFFER, &toCopyBackToFront);
850   #endif
851     if (toCopyBackToFront
852      && myTransientDrawToFront)
853     {
854       if (!HasImmediateStructures()
855        && !theIsPartialUpdate)
856       {
857         // prefer Swap Buffers within Redraw in compatibility mode (without FBO)
858         return true;
859       }
860       if (!copyBackToFront())
861       {
862         toCopyBackToFront    = GL_FALSE;
863         myBackBufferRestored = Standard_False;
864       }
865     }
866     else
867     {
868       toCopyBackToFront    = GL_FALSE;
869       myBackBufferRestored = Standard_False;
870     }
871   }
872   else
873   {
874     myBackBufferRestored = Standard_False;
875   }
876   myIsImmediateDrawn = Standard_True;
877
878   myWorkspace->UseZBuffer()    = Standard_True;
879   myWorkspace->UseDepthWrite() = Standard_True;
880   glDepthFunc (GL_LEQUAL);
881   glDepthMask (GL_TRUE);
882   glEnable (GL_DEPTH_TEST);
883 #if !defined(GL_ES_VERSION_2_0)
884   glClearDepth (1.0);
885 #else
886   glClearDepthf (1.0f);
887 #endif
888
889   render (theProjection, theDrawFbo, theOitAccumFbo, Standard_True);
890
891   return !toCopyBackToFront;
892 }
893
894 //=======================================================================
895 //function : Render
896 //purpose  :
897 //=======================================================================
898 void OpenGl_View::render (Graphic3d_Camera::Projection theProjection,
899                           OpenGl_FrameBuffer*          theOutputFBO,
900                           OpenGl_FrameBuffer*          theOitAccumFbo,
901                           const Standard_Boolean       theToDrawImmediate)
902 {
903   // ==================================
904   //      Step 1: Prepare for render
905   // ==================================
906
907   const Handle(OpenGl_Context)& aContext = myWorkspace->GetGlContext();
908   aContext->SetAllowSampleAlphaToCoverage (myRenderParams.ToEnableAlphaToCoverage
909                                         && theOutputFBO != NULL
910                                         && theOutputFBO->NbSamples() != 0);
911
912 #if !defined(GL_ES_VERSION_2_0)
913   // Disable current clipping planes
914   if (aContext->core11 != NULL)
915   {
916     const Standard_Integer aMaxPlanes = aContext->MaxClipPlanes();
917     for (Standard_Integer aClipPlaneId = GL_CLIP_PLANE0; aClipPlaneId < GL_CLIP_PLANE0 + aMaxPlanes; ++aClipPlaneId)
918     {
919       aContext->core11fwd->glDisable (aClipPlaneId);
920     }
921   }
922 #endif
923
924   // update states of OpenGl_BVHTreeSelector (frustum culling algorithm);
925   // note that we pass here window dimensions ignoring Graphic3d_RenderingParams::RenderResolutionScale
926   myBVHSelector.SetViewVolume (myCamera);
927   myBVHSelector.SetViewportSize (myWindow->Width(), myWindow->Height(), myRenderParams.ResolutionRatio());
928   myBVHSelector.CacheClipPtsProjections();
929
930   const Handle(OpenGl_ShaderManager)& aManager = aContext->ShaderManager();
931   const Handle(Graphic3d_LightSet)&   aLights  = myShadingModel == Graphic3d_TOSM_UNLIT ? myNoShadingLight : myLights;
932   Standard_Size aLightsRevision = 0;
933   if (!aLights.IsNull())
934   {
935     aLightsRevision = aLights->UpdateRevision();
936   }
937   if (StateInfo (myCurrLightSourceState, aManager->LightSourceState().Index()) != myLastLightSourceState
938    || aLightsRevision != myLightsRevision)
939   {
940     myLightsRevision = aLightsRevision;
941     aManager->UpdateLightSourceStateTo (aLights);
942     myLastLightSourceState = StateInfo (myCurrLightSourceState, aManager->LightSourceState().Index());
943   }
944
945   // Update matrices if camera has changed.
946   Graphic3d_WorldViewProjState aWVPState = myCamera->WorldViewProjState();
947   if (myWorldViewProjState != aWVPState)
948   {
949     myAccumFrames = 0;
950     myWorldViewProjState = aWVPState;
951   }
952
953   myLocalOrigin.SetCoord (0.0, 0.0, 0.0);
954   aContext->ProjectionState.SetCurrent (myCamera->ProjectionMatrixF());
955   aContext->WorldViewState .SetCurrent (myCamera->OrientationMatrixF());
956   aContext->ApplyProjectionMatrix();
957   aContext->ApplyWorldViewMatrix();
958   if (aManager->ModelWorldState().Index() == 0)
959   {
960     aContext->ShaderManager()->UpdateModelWorldStateTo (OpenGl_Mat4());
961   }
962
963   // ====================================
964   //      Step 2: Redraw background
965   // ====================================
966
967   // Render background
968   if (!theToDrawImmediate)
969   {
970     drawBackground (myWorkspace);
971   }
972
973 #if !defined(GL_ES_VERSION_2_0)
974   // Switch off lighting by default
975   if (aContext->core11 != NULL
976    && aContext->caps->ffpEnable)
977   {
978     glDisable(GL_LIGHTING);
979   }
980 #endif
981
982   // =================================
983   //      Step 3: Redraw main plane
984   // =================================
985
986   // Setup face culling
987   GLboolean isCullFace = GL_FALSE;
988   if (myBackfacing != Graphic3d_TOBM_AUTOMATIC)
989   {
990     isCullFace = glIsEnabled (GL_CULL_FACE);
991     if (myBackfacing == Graphic3d_TOBM_DISABLE)
992     {
993       glEnable (GL_CULL_FACE);
994       glCullFace (GL_BACK);
995     }
996     else
997       glDisable (GL_CULL_FACE);
998   }
999
1000 #if !defined(GL_ES_VERSION_2_0)
1001   // if the view is scaled normal vectors are scaled to unit
1002   // length for correct displaying of shaded objects
1003   const gp_Pnt anAxialScale = myCamera->AxialScale();
1004   if (anAxialScale.X() != 1.F ||
1005       anAxialScale.Y() != 1.F ||
1006       anAxialScale.Z() != 1.F)
1007   {
1008     aContext->SetGlNormalizeEnabled (Standard_True);
1009   }
1010   else
1011   {
1012     aContext->SetGlNormalizeEnabled (Standard_False);
1013   }
1014
1015   // Apply InteriorShadingMethod
1016   if (aContext->core11 != NULL)
1017   {
1018     aContext->core11->glShadeModel (myShadingModel == Graphic3d_TOSM_FACET
1019                                  || myShadingModel == Graphic3d_TOSM_UNLIT ? GL_FLAT : GL_SMOOTH);
1020   }
1021 #endif
1022
1023   aManager->SetShadingModel (myShadingModel);
1024
1025   // Redraw 3d scene
1026   if (theProjection == Graphic3d_Camera::Projection_MonoLeftEye)
1027   {
1028     aContext->ProjectionState.SetCurrent (myCamera->ProjectionStereoLeftF());
1029     aContext->ApplyProjectionMatrix();
1030   }
1031   else if (theProjection == Graphic3d_Camera::Projection_MonoRightEye)
1032   {
1033     aContext->ProjectionState.SetCurrent (myCamera->ProjectionStereoRightF());
1034     aContext->ApplyProjectionMatrix();
1035   }
1036
1037   myWorkspace->SetEnvironmentTexture (myTextureEnv);
1038
1039   renderScene (theProjection, theOutputFBO, theOitAccumFbo, theToDrawImmediate);
1040
1041   myWorkspace->SetEnvironmentTexture (Handle(OpenGl_TextureSet)());
1042
1043   // ===============================
1044   //      Step 4: Trihedron
1045   // ===============================
1046
1047   // Resetting GL parameters according to the default aspects
1048   // in order to synchronize GL state with the graphic driver state
1049   // before drawing auxiliary stuff (trihedrons, overlayer)
1050   myWorkspace->ResetAppliedAspect();
1051
1052   // Render trihedron
1053   if (!theToDrawImmediate)
1054   {
1055     renderTrihedron (myWorkspace);
1056
1057     // Restore face culling
1058     if (myBackfacing != Graphic3d_TOBM_AUTOMATIC)
1059     {
1060       if (isCullFace)
1061       {
1062         glEnable (GL_CULL_FACE);
1063         glCullFace (GL_BACK);
1064       }
1065       else
1066         glDisable (GL_CULL_FACE);
1067     }
1068   }
1069   else
1070   {
1071     renderFrameStats();
1072   }
1073
1074   myWorkspace->ResetAppliedAspect();
1075   aContext->SetAllowSampleAlphaToCoverage (false);
1076   aContext->SetSampleAlphaToCoverage (false);
1077
1078   // reset FFP state for safety
1079   aContext->BindProgram (Handle(OpenGl_ShaderProgram)());
1080   if (aContext->caps->ffpEnable)
1081   {
1082     aContext->ShaderManager()->PushState (Handle(OpenGl_ShaderProgram)());
1083   }
1084
1085   // ==============================================================
1086   //      Step 6: Keep shader manager informed about last View
1087   // ==============================================================
1088
1089   if (!aManager.IsNull())
1090   {
1091     aManager->SetLastView (this);
1092   }
1093 }
1094
1095 // =======================================================================
1096 // function : InvalidateBVHData
1097 // purpose  :
1098 // =======================================================================
1099 void OpenGl_View::InvalidateBVHData (const Graphic3d_ZLayerId theLayerId)
1100 {
1101   myZLayers.InvalidateBVHData (theLayerId);
1102 }
1103
1104 //=======================================================================
1105 //function : renderStructs
1106 //purpose  :
1107 //=======================================================================
1108 void OpenGl_View::renderStructs (Graphic3d_Camera::Projection theProjection,
1109                                  OpenGl_FrameBuffer*          theReadDrawFbo,
1110                                  OpenGl_FrameBuffer*          theOitAccumFbo,
1111                                  const Standard_Boolean       theToDrawImmediate)
1112 {
1113   myZLayers.UpdateCulling (myWorkspace, theToDrawImmediate);
1114   if ( myZLayers.NbStructures() <= 0 )
1115     return;
1116
1117   Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext();
1118   Standard_Boolean toRenderGL = theToDrawImmediate ||
1119     myRenderParams.Method != Graphic3d_RM_RAYTRACING ||
1120     myRaytraceInitStatus == OpenGl_RT_FAIL ||
1121     aCtx->IsFeedback();
1122
1123   if (!toRenderGL)
1124   {
1125     const Standard_Integer aSizeX = theReadDrawFbo != NULL ? theReadDrawFbo->GetVPSizeX() : myWindow->Width();
1126     const Standard_Integer aSizeY = theReadDrawFbo != NULL ? theReadDrawFbo->GetVPSizeY() : myWindow->Height();
1127
1128     toRenderGL = !initRaytraceResources (aSizeX, aSizeY, aCtx)
1129               || !updateRaytraceGeometry (OpenGl_GUM_CHECK, myId, aCtx);
1130
1131     toRenderGL |= !myIsRaytraceDataValid; // if no ray-trace data use OpenGL
1132
1133     if (!toRenderGL)
1134     {
1135       myOpenGlFBO ->InitLazy (aCtx, aSizeX, aSizeY, myFboColorFormat, myFboDepthFormat, 0);
1136
1137       if (theReadDrawFbo != NULL)
1138         theReadDrawFbo->UnbindBuffer (aCtx);
1139
1140       // Prepare preliminary OpenGL output
1141       if (aCtx->arbFBOBlit != NULL)
1142       {
1143         // Render bottom OSD layer
1144         myZLayers.Render (myWorkspace, theToDrawImmediate, OpenGl_LF_Bottom, theReadDrawFbo, theOitAccumFbo);
1145
1146         const Standard_Integer aPrevFilter = myWorkspace->RenderFilter() & ~(Standard_Integer )(OpenGl_RenderFilter_NonRaytraceableOnly);
1147         myWorkspace->SetRenderFilter (aPrevFilter | OpenGl_RenderFilter_NonRaytraceableOnly);
1148         {
1149           if (theReadDrawFbo != NULL)
1150           {
1151             theReadDrawFbo->BindDrawBuffer (aCtx);
1152           }
1153           else
1154           {
1155             aCtx->arbFBO->glBindFramebuffer (GL_DRAW_FRAMEBUFFER, 0);
1156             aCtx->SetFrameBufferSRGB (false);
1157           }
1158
1159           // Render non-polygonal elements in default layer
1160           myZLayers.Render (myWorkspace, theToDrawImmediate, OpenGl_LF_RayTracable, theReadDrawFbo, theOitAccumFbo);
1161         }
1162         myWorkspace->SetRenderFilter (aPrevFilter);
1163       }
1164
1165       if (theReadDrawFbo != NULL)
1166       {
1167         theReadDrawFbo->BindBuffer (aCtx);
1168       }
1169       else
1170       {
1171         aCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, 0);
1172         aCtx->SetFrameBufferSRGB (false);
1173       }
1174
1175       // Reset OpenGl aspects state to default to avoid enabling of
1176       // backface culling which is not supported in ray-tracing.
1177       myWorkspace->ResetAppliedAspect();
1178
1179       // Ray-tracing polygonal primitive arrays
1180       raytrace (aSizeX, aSizeY, theProjection, theReadDrawFbo, aCtx);
1181
1182       // Render upper (top and topmost) OpenGL layers
1183       myZLayers.Render (myWorkspace, theToDrawImmediate, OpenGl_LF_Upper, theReadDrawFbo, theOitAccumFbo);
1184     }
1185   }
1186
1187   // Redraw 3D scene using OpenGL in standard
1188   // mode or in case of ray-tracing failure
1189   if (toRenderGL)
1190   {
1191     myZLayers.Render (myWorkspace, theToDrawImmediate, OpenGl_LF_All, theReadDrawFbo, theOitAccumFbo);
1192
1193     // Set flag that scene was redrawn by standard pipeline
1194     myWasRedrawnGL = Standard_True;
1195   }
1196 }
1197
1198 //=======================================================================
1199 //function : renderTrihedron
1200 //purpose  :
1201 //=======================================================================
1202 void OpenGl_View::renderTrihedron (const Handle(OpenGl_Workspace) &theWorkspace)
1203 {
1204   if (myToShowGradTrihedron)
1205   {
1206     myGraduatedTrihedron.Render (theWorkspace);
1207   }
1208 }
1209
1210 //=======================================================================
1211 //function : renderFrameStats
1212 //purpose  :
1213 //=======================================================================
1214 void OpenGl_View::renderFrameStats()
1215 {
1216   if (myRenderParams.ToShowStats
1217    && myRenderParams.CollectedStats != Graphic3d_RenderingParams::PerfCounters_NONE)
1218   {
1219     myFrameStatsPrs.Update (myWorkspace);
1220     myFrameStatsPrs.Render (myWorkspace);
1221   }
1222 }
1223
1224 // =======================================================================
1225 // function : Invalidate
1226 // purpose  :
1227 // =======================================================================
1228 void OpenGl_View::Invalidate()
1229 {
1230   myBackBufferRestored = Standard_False;
1231 }
1232
1233 //=======================================================================
1234 //function : renderScene
1235 //purpose  :
1236 //=======================================================================
1237 void OpenGl_View::renderScene (Graphic3d_Camera::Projection theProjection,
1238                                OpenGl_FrameBuffer*          theReadDrawFbo,
1239                                OpenGl_FrameBuffer*          theOitAccumFbo,
1240                                const Standard_Boolean       theToDrawImmediate)
1241 {
1242   const Handle(OpenGl_Context)& aContext = myWorkspace->GetGlContext();
1243
1244   // Specify clipping planes in view transformation space
1245   aContext->ChangeClipping().Reset (myClipPlanes);
1246   if (!myClipPlanes.IsNull()
1247    && !myClipPlanes->IsEmpty())
1248   {
1249     aContext->ShaderManager()->UpdateClippingState();
1250   }
1251
1252   renderStructs (theProjection, theReadDrawFbo, theOitAccumFbo, theToDrawImmediate);
1253   aContext->BindTextures (Handle(OpenGl_TextureSet)());
1254
1255   // Apply restored view matrix.
1256   aContext->ApplyWorldViewMatrix();
1257
1258   aContext->ChangeClipping().Reset (Handle(Graphic3d_SequenceOfHClipPlane)());
1259   if (!myClipPlanes.IsNull()
1260    && !myClipPlanes->IsEmpty())
1261   {
1262     aContext->ShaderManager()->RevertClippingState();
1263   }
1264 }
1265
1266 // =======================================================================
1267 // function : bindDefaultFbo
1268 // purpose  :
1269 // =======================================================================
1270 void OpenGl_View::bindDefaultFbo (OpenGl_FrameBuffer* theCustomFbo)
1271 {
1272   Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext();
1273   OpenGl_FrameBuffer* anFbo = (theCustomFbo != NULL && theCustomFbo->IsValid())
1274                             ?  theCustomFbo
1275                             : (!aCtx->DefaultFrameBuffer().IsNull()
1276                              && aCtx->DefaultFrameBuffer()->IsValid()
1277                               ? aCtx->DefaultFrameBuffer().operator->()
1278                               : NULL);
1279   if (anFbo != NULL)
1280   {
1281     anFbo->BindBuffer (aCtx);
1282     anFbo->SetupViewport (aCtx);
1283   }
1284   else
1285   {
1286   #if !defined(GL_ES_VERSION_2_0)
1287     aCtx->SetReadDrawBuffer (GL_BACK);
1288   #else
1289     if (aCtx->arbFBO != NULL)
1290     {
1291       aCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
1292     }
1293   #endif
1294     const Standard_Integer aViewport[4] = { 0, 0, myWindow->Width(), myWindow->Height() };
1295     aCtx->ResizeViewport (aViewport);
1296   }
1297 }
1298
1299 // =======================================================================
1300 // function : initBlitQuad
1301 // purpose  :
1302 // =======================================================================
1303 OpenGl_VertexBuffer* OpenGl_View::initBlitQuad (const Standard_Boolean theToFlip)
1304 {
1305   OpenGl_VertexBuffer* aVerts = NULL;
1306   if (!theToFlip)
1307   {
1308     aVerts = &myFullScreenQuad;
1309     if (!aVerts->IsValid())
1310     {
1311       OpenGl_Vec4 aQuad[4] =
1312       {
1313         OpenGl_Vec4( 1.0f, -1.0f, 1.0f, 0.0f),
1314         OpenGl_Vec4( 1.0f,  1.0f, 1.0f, 1.0f),
1315         OpenGl_Vec4(-1.0f, -1.0f, 0.0f, 0.0f),
1316         OpenGl_Vec4(-1.0f,  1.0f, 0.0f, 1.0f)
1317       };
1318       aVerts->Init (myWorkspace->GetGlContext(), 4, 4, aQuad[0].GetData());
1319     }
1320   }
1321   else
1322   {
1323     aVerts = &myFullScreenQuadFlip;
1324     if (!aVerts->IsValid())
1325     {
1326       OpenGl_Vec4 aQuad[4] =
1327       {
1328         OpenGl_Vec4( 1.0f, -1.0f, 1.0f, 1.0f),
1329         OpenGl_Vec4( 1.0f,  1.0f, 1.0f, 0.0f),
1330         OpenGl_Vec4(-1.0f, -1.0f, 0.0f, 1.0f),
1331         OpenGl_Vec4(-1.0f,  1.0f, 0.0f, 0.0f)
1332       };
1333       aVerts->Init (myWorkspace->GetGlContext(), 4, 4, aQuad[0].GetData());
1334     }
1335   }
1336   return aVerts;
1337 }
1338
1339 // =======================================================================
1340 // function : blitBuffers
1341 // purpose  :
1342 // =======================================================================
1343 bool OpenGl_View::blitBuffers (OpenGl_FrameBuffer*    theReadFbo,
1344                                OpenGl_FrameBuffer*    theDrawFbo,
1345                                const Standard_Boolean theToFlip)
1346 {
1347   Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext();
1348   const Standard_Integer aReadSizeX = theReadFbo != NULL ? theReadFbo->GetVPSizeX() : myWindow->Width();
1349   const Standard_Integer aReadSizeY = theReadFbo != NULL ? theReadFbo->GetVPSizeY() : myWindow->Height();
1350   const Standard_Integer aDrawSizeX = theDrawFbo != NULL ? theDrawFbo->GetVPSizeX() : myWindow->Width();
1351   const Standard_Integer aDrawSizeY = theDrawFbo != NULL ? theDrawFbo->GetVPSizeY() : myWindow->Height();
1352   if (theReadFbo == NULL || aCtx->IsFeedback())
1353   {
1354     return false;
1355   }
1356   else if (theReadFbo == theDrawFbo)
1357   {
1358     return true;
1359   }
1360
1361   // clear destination before blitting
1362   if (theDrawFbo != NULL
1363   &&  theDrawFbo->IsValid())
1364   {
1365     theDrawFbo->BindBuffer (aCtx);
1366   }
1367   else
1368   {
1369     aCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
1370     aCtx->SetFrameBufferSRGB (false);
1371   }
1372   const Standard_Integer aViewport[4] = { 0, 0, aDrawSizeX, aDrawSizeY };
1373   aCtx->ResizeViewport (aViewport);
1374
1375 #if !defined(GL_ES_VERSION_2_0)
1376   aCtx->core20fwd->glClearDepth  (1.0);
1377 #else
1378   aCtx->core20fwd->glClearDepthf (1.0f);
1379 #endif
1380   aCtx->core20fwd->glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1381
1382   const bool toApplyGamma = aCtx->ToRenderSRGB() != aCtx->IsFrameBufferSRGB();
1383   if (aCtx->arbFBOBlit != NULL
1384   && !toApplyGamma
1385   &&  theReadFbo->NbSamples() != 0)
1386   {
1387     GLbitfield aCopyMask = 0;
1388     theReadFbo->BindReadBuffer (aCtx);
1389     if (theDrawFbo != NULL
1390      && theDrawFbo->IsValid())
1391     {
1392       theDrawFbo->BindDrawBuffer (aCtx);
1393       if (theDrawFbo->HasColor()
1394        && theReadFbo->HasColor())
1395       {
1396         aCopyMask |= GL_COLOR_BUFFER_BIT;
1397       }
1398       if (theDrawFbo->HasDepth()
1399        && theReadFbo->HasDepth())
1400       {
1401         aCopyMask |= GL_DEPTH_BUFFER_BIT;
1402       }
1403     }
1404     else
1405     {
1406       if (theReadFbo->HasColor())
1407       {
1408         aCopyMask |= GL_COLOR_BUFFER_BIT;
1409       }
1410       if (theReadFbo->HasDepth())
1411       {
1412         aCopyMask |= GL_DEPTH_BUFFER_BIT;
1413       }
1414       aCtx->arbFBO->glBindFramebuffer (GL_DRAW_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
1415       aCtx->SetFrameBufferSRGB (false);
1416     }
1417
1418     // we don't copy stencil buffer here... does it matter for performance?
1419     aCtx->arbFBOBlit->glBlitFramebuffer (0, 0, aReadSizeX, aReadSizeY,
1420                                          0, 0, aDrawSizeX, aDrawSizeY,
1421                                          aCopyMask, GL_NEAREST);
1422     const int anErr = ::glGetError();
1423     if (anErr != GL_NO_ERROR)
1424     {
1425       // glBlitFramebuffer() might fail in several cases:
1426       // - Both FBOs have MSAA and they are samples number does not match.
1427       //   OCCT checks that this does not happen,
1428       //   however some graphics drivers provide an option for overriding MSAA.
1429       //   In this case window MSAA might be non-zero (and application can not check it)
1430       //   and might not match MSAA of our offscreen FBOs.
1431       // - Pixel formats of FBOs do not match.
1432       //   This also might happen with window has pixel format,
1433       //   e.g. Mesa fails blitting RGBA8 -> RGB8 while other drivers support this conversion.
1434       TCollection_ExtendedString aMsg = TCollection_ExtendedString() + "FBO blitting has failed [Error #" + anErr + "]\n"
1435                                       + "  Please check your graphics driver settings or try updating driver.";
1436       if (theReadFbo->NbSamples() != 0)
1437       {
1438         myToDisableMSAA = true;
1439         aMsg += "\n  MSAA settings should not be overridden by driver!";
1440       }
1441       aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
1442                          GL_DEBUG_TYPE_ERROR,
1443                          0,
1444                          GL_DEBUG_SEVERITY_HIGH,
1445                          aMsg);
1446     }
1447
1448     if (theDrawFbo != NULL
1449      && theDrawFbo->IsValid())
1450     {
1451       theDrawFbo->BindBuffer (aCtx);
1452     }
1453     else
1454     {
1455       aCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
1456       aCtx->SetFrameBufferSRGB (false);
1457     }
1458   }
1459   else
1460   {
1461     aCtx->core20fwd->glDepthFunc (GL_ALWAYS);
1462     aCtx->core20fwd->glDepthMask (GL_TRUE);
1463     aCtx->core20fwd->glEnable (GL_DEPTH_TEST);
1464   #if defined(GL_ES_VERSION_2_0)
1465     if (!aCtx->IsGlGreaterEqual (3, 0)
1466      && !aCtx->extFragDepth)
1467     {
1468       aCtx->core20fwd->glDisable (GL_DEPTH_TEST);
1469     }
1470   #endif
1471
1472     aCtx->BindTextures (Handle(OpenGl_TextureSet)());
1473
1474     const Graphic3d_TypeOfTextureFilter aFilter = (aDrawSizeX == aReadSizeX && aDrawSizeY == aReadSizeY) ? Graphic3d_TOTF_NEAREST : Graphic3d_TOTF_BILINEAR;
1475     const GLint aFilterGl = aFilter == Graphic3d_TOTF_NEAREST ? GL_NEAREST : GL_LINEAR;
1476
1477     OpenGl_VertexBuffer* aVerts = initBlitQuad (theToFlip);
1478     const Handle(OpenGl_ShaderManager)& aManager = aCtx->ShaderManager();
1479     if (aVerts->IsValid()
1480      && aManager->BindFboBlitProgram (theReadFbo != NULL ? theReadFbo->NbSamples() : 0, toApplyGamma))
1481     {
1482       aCtx->SetSampleAlphaToCoverage (false);
1483       theReadFbo->ColorTexture()->Bind (aCtx, Graphic3d_TextureUnit_0);
1484       if (theReadFbo->ColorTexture()->Sampler()->Parameters()->Filter() != aFilter)
1485       {
1486         theReadFbo->ColorTexture()->Sampler()->Parameters()->SetFilter (aFilter);
1487         aCtx->core20fwd->glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, aFilterGl);
1488         aCtx->core20fwd->glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, aFilterGl);
1489       }
1490
1491       theReadFbo->DepthStencilTexture()->Bind (aCtx, Graphic3d_TextureUnit_1);
1492       if (theReadFbo->DepthStencilTexture()->Sampler()->Parameters()->Filter() != aFilter)
1493       {
1494         theReadFbo->DepthStencilTexture()->Sampler()->Parameters()->SetFilter (aFilter);
1495         aCtx->core20fwd->glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, aFilterGl);
1496         aCtx->core20fwd->glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, aFilterGl);
1497       }
1498
1499       aVerts->BindVertexAttrib (aCtx, Graphic3d_TOA_POS);
1500
1501       aCtx->core20fwd->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
1502
1503       aVerts->UnbindVertexAttrib (aCtx, Graphic3d_TOA_POS);
1504       theReadFbo->DepthStencilTexture()->Unbind (aCtx, Graphic3d_TextureUnit_1);
1505       theReadFbo->ColorTexture()       ->Unbind (aCtx, Graphic3d_TextureUnit_0);
1506       aCtx->BindProgram (NULL);
1507     }
1508     else
1509     {
1510       TCollection_ExtendedString aMsg = TCollection_ExtendedString()
1511         + "Error! FBO blitting has failed";
1512       aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
1513                          GL_DEBUG_TYPE_ERROR,
1514                          0,
1515                          GL_DEBUG_SEVERITY_HIGH,
1516                          aMsg);
1517       myHasFboBlit = Standard_False;
1518       theReadFbo->Release (aCtx.operator->());
1519       return true;
1520     }
1521   }
1522   return true;
1523 }
1524
1525 // =======================================================================
1526 // function : drawStereoPair
1527 // purpose  :
1528 // =======================================================================
1529 void OpenGl_View::drawStereoPair (OpenGl_FrameBuffer* theDrawFbo)
1530 {
1531   const Handle(OpenGl_Context)& aCtx = myWorkspace->GetGlContext();
1532   bindDefaultFbo (theDrawFbo);
1533   OpenGl_FrameBuffer* aPair[2] =
1534   {
1535     myImmediateSceneFbos[0]->IsValid() ? myImmediateSceneFbos[0].operator->() : NULL,
1536     myImmediateSceneFbos[1]->IsValid() ? myImmediateSceneFbos[1].operator->() : NULL
1537   };
1538   if (aPair[0] == NULL
1539   ||  aPair[1] == NULL
1540   || !myTransientDrawToFront)
1541   {
1542     aPair[0] = myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL;
1543     aPair[1] = myMainSceneFbos[1]->IsValid() ? myMainSceneFbos[1].operator->() : NULL;
1544   }
1545
1546   if (aPair[0] == NULL
1547    || aPair[1] == NULL)
1548   {
1549     return;
1550   }
1551
1552   if (aPair[0]->NbSamples() != 0)
1553   {
1554     // resolve MSAA buffers before drawing
1555     if (!myOpenGlFBO ->InitLazy (aCtx, aPair[0]->GetVPSizeX(), aPair[0]->GetVPSizeY(), myFboColorFormat, myFboDepthFormat, 0)
1556      || !myOpenGlFBO2->InitLazy (aCtx, aPair[0]->GetVPSizeX(), aPair[0]->GetVPSizeY(), myFboColorFormat, 0, 0))
1557     {
1558       aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
1559                          GL_DEBUG_TYPE_ERROR,
1560                          0,
1561                          GL_DEBUG_SEVERITY_HIGH,
1562                          "Error! Unable to allocate FBO for blitting stereo pair");
1563       bindDefaultFbo (theDrawFbo);
1564       return;
1565     }
1566
1567     if (!blitBuffers (aPair[0], myOpenGlFBO .operator->(), Standard_False)
1568      || !blitBuffers (aPair[1], myOpenGlFBO2.operator->(), Standard_False))
1569     {
1570       bindDefaultFbo (theDrawFbo);
1571       return;
1572     }
1573
1574     aPair[0] = myOpenGlFBO .operator->();
1575     aPair[1] = myOpenGlFBO2.operator->();
1576     bindDefaultFbo (theDrawFbo);
1577   }
1578
1579   struct
1580   {
1581     Standard_Integer left;
1582     Standard_Integer top;
1583     Standard_Integer right;
1584     Standard_Integer bottom;
1585     Standard_Integer dx() { return right  - left; }
1586     Standard_Integer dy() { return bottom - top; }
1587   } aGeom;
1588
1589   myWindow->PlatformWindow()->Position (aGeom.left, aGeom.top, aGeom.right, aGeom.bottom);
1590
1591   Standard_Boolean toReverse = myRenderParams.ToReverseStereo;
1592   const Standard_Boolean isOddY = (aGeom.top + aGeom.dy()) % 2 == 1;
1593   const Standard_Boolean isOddX =  aGeom.left % 2 == 1;
1594   if (isOddY
1595    && (myRenderParams.StereoMode == Graphic3d_StereoMode_RowInterlaced
1596     || myRenderParams.StereoMode == Graphic3d_StereoMode_ChessBoard))
1597   {
1598     toReverse = !toReverse;
1599   }
1600   if (isOddX
1601    && (myRenderParams.StereoMode == Graphic3d_StereoMode_ColumnInterlaced
1602     || myRenderParams.StereoMode == Graphic3d_StereoMode_ChessBoard))
1603   {
1604     toReverse = !toReverse;
1605   }
1606
1607   if (toReverse)
1608   {
1609     std::swap (aPair[0], aPair[1]);
1610   }
1611
1612   aCtx->core20fwd->glDepthFunc (GL_ALWAYS);
1613   aCtx->core20fwd->glDepthMask (GL_TRUE);
1614   aCtx->core20fwd->glEnable (GL_DEPTH_TEST);
1615
1616   aCtx->BindTextures (Handle(OpenGl_TextureSet)());
1617   OpenGl_VertexBuffer* aVerts = initBlitQuad (myToFlipOutput);
1618
1619   const Handle(OpenGl_ShaderManager)& aManager = aCtx->ShaderManager();
1620   if (aVerts->IsValid()
1621    && aManager->BindStereoProgram (myRenderParams.StereoMode))
1622   {
1623     if (myRenderParams.StereoMode == Graphic3d_StereoMode_Anaglyph)
1624     {
1625       OpenGl_Mat4 aFilterL, aFilterR;
1626       aFilterL.SetDiagonal (Graphic3d_Vec4 (0.0f, 0.0f, 0.0f, 0.0f));
1627       aFilterR.SetDiagonal (Graphic3d_Vec4 (0.0f, 0.0f, 0.0f, 0.0f));
1628       switch (myRenderParams.AnaglyphFilter)
1629       {
1630         case Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple:
1631         {
1632           aFilterL.SetRow (0, Graphic3d_Vec4 (1.0f, 0.0f, 0.0f, 0.0f));
1633           aFilterR.SetRow (1, Graphic3d_Vec4 (0.0f, 1.0f, 0.0f, 0.0f));
1634           aFilterR.SetRow (2, Graphic3d_Vec4 (0.0f, 0.0f, 1.0f, 0.0f));
1635           break;
1636         }
1637         case Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized:
1638         {
1639           aFilterL.SetRow (0, Graphic3d_Vec4 ( 0.4154f,      0.4710f,      0.16666667f, 0.0f));
1640           aFilterL.SetRow (1, Graphic3d_Vec4 (-0.0458f,     -0.0484f,     -0.0257f,     0.0f));
1641           aFilterL.SetRow (2, Graphic3d_Vec4 (-0.0547f,     -0.0615f,      0.0128f,     0.0f));
1642           aFilterL.SetRow (3, Graphic3d_Vec4 ( 0.0f,         0.0f,         0.0f,        0.0f));
1643           aFilterR.SetRow (0, Graphic3d_Vec4 (-0.01090909f, -0.03636364f, -0.00606061f, 0.0f));
1644           aFilterR.SetRow (1, Graphic3d_Vec4 ( 0.37560000f,  0.73333333f,  0.01111111f, 0.0f));
1645           aFilterR.SetRow (2, Graphic3d_Vec4 (-0.06510000f, -0.12870000f,  1.29710000f, 0.0f));
1646           aFilterR.SetRow (3, Graphic3d_Vec4 ( 0.0f,                0.0f,  0.0f,        0.0f));
1647           break;
1648         }
1649         case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple:
1650         {
1651           aFilterL.SetRow (0, Graphic3d_Vec4 (1.0f, 0.0f, 0.0f, 0.0f));
1652           aFilterL.SetRow (1, Graphic3d_Vec4 (0.0f, 1.0f, 0.0f, 0.0f));
1653           aFilterR.SetRow (2, Graphic3d_Vec4 (0.0f, 0.0f, 1.0f, 0.0f));
1654           break;
1655         }
1656         case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized:
1657         {
1658           aFilterL.SetRow (0, Graphic3d_Vec4 ( 1.062f, -0.205f,  0.299f, 0.0f));
1659           aFilterL.SetRow (1, Graphic3d_Vec4 (-0.026f,  0.908f,  0.068f, 0.0f));
1660           aFilterL.SetRow (2, Graphic3d_Vec4 (-0.038f, -0.173f,  0.022f, 0.0f));
1661           aFilterL.SetRow (3, Graphic3d_Vec4 ( 0.0f,    0.0f,    0.0f,   0.0f));
1662           aFilterR.SetRow (0, Graphic3d_Vec4 (-0.016f, -0.123f, -0.017f, 0.0f));
1663           aFilterR.SetRow (1, Graphic3d_Vec4 ( 0.006f,  0.062f, -0.017f, 0.0f));
1664           aFilterR.SetRow (2, Graphic3d_Vec4 ( 0.094f,  0.185f,  0.911f, 0.0f));
1665           aFilterR.SetRow (3, Graphic3d_Vec4 ( 0.0f,    0.0f,    0.0f,   0.0f));
1666           break;
1667         }
1668         case Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple:
1669         {
1670           aFilterR.SetRow (0, Graphic3d_Vec4 (1.0f, 0.0f, 0.0f, 0.0f));
1671           aFilterL.SetRow (1, Graphic3d_Vec4 (0.0f, 1.0f, 0.0f, 0.0f));
1672           aFilterR.SetRow (2, Graphic3d_Vec4 (0.0f, 0.0f, 1.0f, 0.0f));
1673           break;
1674         }
1675         case Graphic3d_RenderingParams::Anaglyph_UserDefined:
1676         {
1677           aFilterL = myRenderParams.AnaglyphLeft;
1678           aFilterR = myRenderParams.AnaglyphRight;
1679           break;
1680         }
1681       }
1682       aCtx->ActiveProgram()->SetUniform (aCtx, "uMultL", aFilterL);
1683       aCtx->ActiveProgram()->SetUniform (aCtx, "uMultR", aFilterR);
1684     }
1685
1686     aPair[0]->ColorTexture()->Bind (aCtx, Graphic3d_TextureUnit_0);
1687     aPair[1]->ColorTexture()->Bind (aCtx, Graphic3d_TextureUnit_1);
1688     aVerts->BindVertexAttrib (aCtx, 0);
1689
1690     aCtx->core20fwd->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
1691
1692     aVerts->UnbindVertexAttrib (aCtx, 0);
1693     aPair[1]->ColorTexture()->Unbind (aCtx, Graphic3d_TextureUnit_1);
1694     aPair[0]->ColorTexture()->Unbind (aCtx, Graphic3d_TextureUnit_0);
1695   }
1696   else
1697   {
1698     TCollection_ExtendedString aMsg = TCollection_ExtendedString()
1699       + "Error! Anaglyph has failed";
1700     aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
1701                        GL_DEBUG_TYPE_ERROR,
1702                        0,
1703                        GL_DEBUG_SEVERITY_HIGH,
1704                        aMsg);
1705   }
1706 }
1707
1708 // =======================================================================
1709 // function : copyBackToFront
1710 // purpose  :
1711 // =======================================================================
1712 bool OpenGl_View::copyBackToFront()
1713 {
1714   myIsImmediateDrawn = Standard_False;
1715 #if !defined(GL_ES_VERSION_2_0)
1716   const Handle(OpenGl_Context)& aCtx = myWorkspace->GetGlContext();
1717   if (aCtx->core11 == NULL)
1718   {
1719     return false;
1720   }
1721
1722   OpenGl_Mat4 aProjectMat;
1723   Graphic3d_TransformUtils::Ortho2D (aProjectMat,
1724                                      0.0f, static_cast<GLfloat> (myWindow->Width()),
1725                                      0.0f, static_cast<GLfloat> (myWindow->Height()));
1726
1727   aCtx->WorldViewState.Push();
1728   aCtx->ProjectionState.Push();
1729
1730   aCtx->WorldViewState.SetIdentity();
1731   aCtx->ProjectionState.SetCurrent (aProjectMat);
1732
1733   aCtx->ApplyProjectionMatrix();
1734   aCtx->ApplyWorldViewMatrix();
1735
1736   // synchronize FFP state before copying pixels
1737   aCtx->BindProgram (Handle(OpenGl_ShaderProgram)());
1738   aCtx->ShaderManager()->PushState (Handle(OpenGl_ShaderProgram)());
1739   aCtx->DisableFeatures();
1740
1741   switch (aCtx->DrawBuffer())
1742   {
1743     case GL_BACK_LEFT:
1744     {
1745       aCtx->SetReadBuffer (GL_BACK_LEFT);
1746       aCtx->SetDrawBuffer (GL_FRONT_LEFT);
1747       break;
1748     }
1749     case GL_BACK_RIGHT:
1750     {
1751       aCtx->SetReadBuffer (GL_BACK_RIGHT);
1752       aCtx->SetDrawBuffer (GL_FRONT_RIGHT);
1753       break;
1754     }
1755     default:
1756     {
1757       aCtx->SetReadBuffer (GL_BACK);
1758       aCtx->SetDrawBuffer (GL_FRONT);
1759       break;
1760     }
1761   }
1762
1763   aCtx->core11->glRasterPos2i (0, 0);
1764   aCtx->core11->glCopyPixels  (0, 0, myWindow->Width() + 1, myWindow->Height() + 1, GL_COLOR);
1765   //aCtx->core11->glCopyPixels  (0, 0, myWidth + 1, myHeight + 1, GL_DEPTH);
1766
1767   aCtx->EnableFeatures();
1768
1769   aCtx->WorldViewState.Pop();
1770   aCtx->ProjectionState.Pop();
1771   aCtx->ApplyProjectionMatrix();
1772
1773   // read/write from front buffer now
1774   aCtx->SetReadBuffer (aCtx->DrawBuffer());
1775   return true;
1776 #else
1777   return false;
1778 #endif
1779 }
1780
1781 // =======================================================================
1782 // function : checkOitCompatibility
1783 // purpose  :
1784 // =======================================================================
1785 Standard_Boolean OpenGl_View::checkOitCompatibility (const Handle(OpenGl_Context)& theGlContext,
1786                                                      const Standard_Boolean theMSAA)
1787 {
1788   // determine if OIT is supported by current OpenGl context
1789   Standard_Boolean& aToDisableOIT = theMSAA ? myToDisableMSAA : myToDisableOIT;
1790   if (aToDisableOIT)
1791   {
1792     return Standard_False;
1793   }
1794
1795   TCollection_ExtendedString aCompatibilityMsg;
1796   if (theGlContext->hasFloatBuffer     == OpenGl_FeatureNotAvailable
1797    && theGlContext->hasHalfFloatBuffer == OpenGl_FeatureNotAvailable)
1798   {
1799     aCompatibilityMsg += "OpenGL context does not support floating-point RGBA color buffer format.\n";
1800   }
1801   if (theMSAA && theGlContext->hasSampleVariables == OpenGl_FeatureNotAvailable)
1802   {
1803     aCompatibilityMsg += "Current version of GLSL does not support built-in sample variables.\n";
1804   }
1805   if (theGlContext->hasDrawBuffers == OpenGl_FeatureNotAvailable)
1806   {
1807     aCompatibilityMsg += "OpenGL context does not support multiple draw buffers.\n";
1808   }
1809   if (aCompatibilityMsg.IsEmpty())
1810   {
1811     return Standard_True;
1812   }
1813
1814   aCompatibilityMsg += "  Blended order-independent transparency will not be available.\n";
1815   theGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
1816                           GL_DEBUG_TYPE_ERROR,
1817                           0,
1818                           GL_DEBUG_SEVERITY_HIGH,
1819                           aCompatibilityMsg);
1820
1821   aToDisableOIT = Standard_True;
1822   return Standard_False;
1823 }
1824
1825 // =======================================================================
1826 // function : chooseOitColorConfiguration
1827 // purpose  :
1828 // =======================================================================
1829 bool OpenGl_View::chooseOitColorConfiguration (const Handle(OpenGl_Context)& theGlContext,
1830                                                const Standard_Integer theConfigIndex,
1831                                                OpenGl_ColorFormats& theFormats)
1832 {
1833   theFormats.Clear();
1834   switch (theConfigIndex)
1835   {
1836     case 0: // choose best applicable color format combination
1837     {
1838       theFormats.Append (theGlContext->hasHalfFloatBuffer != OpenGl_FeatureNotAvailable ? GL_RGBA16F : GL_RGBA32F);
1839       theFormats.Append (theGlContext->hasHalfFloatBuffer != OpenGl_FeatureNotAvailable ? GL_R16F    : GL_R32F);
1840       return true;
1841     }
1842     case 1: // choose non-optimal applicable color format combination
1843     {
1844       theFormats.Append (theGlContext->hasHalfFloatBuffer != OpenGl_FeatureNotAvailable ? GL_RGBA16F : GL_RGBA32F);
1845       theFormats.Append (theGlContext->hasHalfFloatBuffer != OpenGl_FeatureNotAvailable ? GL_RGBA16F : GL_RGBA32F);
1846       return true;
1847     }
1848   }
1849   return false; // color combination does not exist
1850 }