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