0027670: Visualization - avoid duplication of structures defining primitive array...
[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->Aspect()->ToMapTexture()
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->Aspect()->ToMapTexture())
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     const OpenGl_Vec4& aBgColor = myBgColor;
692     glClearColor (aBgColor.r(), aBgColor.g(), aBgColor.b(), 0.0f);
693   }
694
695   glClear (toClear);
696
697   render (theProjection, theReadDrawFbo, Standard_False);
698 }
699
700 // =======================================================================
701 // function : redrawMonoImmediate
702 // purpose  :
703 // =======================================================================
704 bool OpenGl_View::redrawImmediate (const Graphic3d_Camera::Projection theProjection,
705                                    OpenGl_FrameBuffer*    theReadFbo,
706                                    OpenGl_FrameBuffer*    theDrawFbo,
707                                    const Standard_Boolean theIsPartialUpdate)
708 {
709   Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext();
710   GLboolean toCopyBackToFront = GL_FALSE;
711   if (!myTransientDrawToFront)
712   {
713     myBackBufferRestored = Standard_False;
714   }
715   else if (theReadFbo != NULL
716         && theReadFbo->IsValid()
717         && aCtx->IsRender())
718   {
719     if (!blitBuffers (theReadFbo, theDrawFbo))
720     {
721       return true;
722     }
723   }
724   else if (theDrawFbo == NULL)
725   {
726   #if !defined(GL_ES_VERSION_2_0)
727     aCtx->core11fwd->glGetBooleanv (GL_DOUBLEBUFFER, &toCopyBackToFront);
728   #endif
729     if (toCopyBackToFront)
730     {
731       if (!HasImmediateStructures()
732        && !theIsPartialUpdate)
733       {
734         // prefer Swap Buffers within Redraw in compatibility mode (without FBO)
735         return true;
736       }
737       copyBackToFront();
738     }
739     else
740     {
741       myBackBufferRestored = Standard_False;
742     }
743   }
744   else
745   {
746     myBackBufferRestored = Standard_False;
747   }
748   myIsImmediateDrawn = Standard_True;
749
750   myWorkspace->UseZBuffer()    = Standard_True;
751   myWorkspace->UseDepthWrite() = Standard_True;
752   glDepthFunc (GL_LEQUAL);
753   glDepthMask (GL_TRUE);
754   glEnable (GL_DEPTH_TEST);
755 #if !defined(GL_ES_VERSION_2_0)
756   glClearDepth (1.0);
757 #else
758   glClearDepthf (1.0f);
759 #endif
760
761   render (theProjection, theDrawFbo, Standard_True);
762
763   return !toCopyBackToFront;
764 }
765
766 //=======================================================================
767 //function : Render
768 //purpose  :
769 //=======================================================================
770 void OpenGl_View::render (Graphic3d_Camera::Projection theProjection,
771                           OpenGl_FrameBuffer*          theOutputFBO,
772                           const Standard_Boolean       theToDrawImmediate)
773 {
774   // ==================================
775   //      Step 1: Prepare for render
776   // ==================================
777
778   const Handle(OpenGl_Context)& aContext = myWorkspace->GetGlContext();
779
780 #if !defined(GL_ES_VERSION_2_0)
781   // Disable current clipping planes
782   if (aContext->core11 != NULL)
783   {
784     const Standard_Integer aMaxPlanes = aContext->MaxClipPlanes();
785     for (Standard_Integer aClipPlaneId = GL_CLIP_PLANE0; aClipPlaneId < GL_CLIP_PLANE0 + aMaxPlanes; ++aClipPlaneId)
786     {
787       aContext->core11fwd->glDisable (aClipPlaneId);
788     }
789   }
790 #endif
791
792   // Update states of OpenGl_BVHTreeSelector (frustum culling algorithm).
793   myBVHSelector.SetViewVolume (myCamera);
794   myBVHSelector.SetViewportSize (myWindow->Width(), myWindow->Height());
795
796   const Handle(OpenGl_ShaderManager)& aManager   = aContext->ShaderManager();
797   if (StateInfo (myCurrLightSourceState, aManager->LightSourceState().Index()) != myLastLightSourceState)
798   {
799     aManager->UpdateLightSourceStateTo (myShadingModel == Graphic3d_TOSM_NONE ? &myNoShadingLight : &myLights);
800     myLastLightSourceState = StateInfo (myCurrLightSourceState, aManager->LightSourceState().Index());
801   }
802
803   // Update matrices if camera has changed.
804   Graphic3d_WorldViewProjState aWVPState = myCamera->WorldViewProjState();
805   const Standard_Boolean isCameraChanged = myWorldViewProjState != aWVPState;
806   const Standard_Boolean isSameView      = aManager->IsSameView (this);
807   if (isCameraChanged)
808   {
809     aContext->ProjectionState.SetCurrent (myCamera->ProjectionMatrixF());
810     aContext->WorldViewState .SetCurrent (myCamera->OrientationMatrixF());
811     myAccumFrames = 0;
812   }
813
814   // Apply new matrix state if camera has changed or this view differs from the one
815   // that was previously used for configuring matrices of shader manager
816   // (ApplyProjectionMatrix and ApplyWorldViewMatrix will affect the manager).
817   if (isCameraChanged || !isSameView)
818   {
819     aContext->ApplyProjectionMatrix();
820     aContext->ApplyWorldViewMatrix();
821   }
822
823   if (aManager->ModelWorldState().Index() == 0)
824   {
825     aContext->ShaderManager()->UpdateModelWorldStateTo (OpenGl_Mat4());
826   }
827
828   myWorldViewProjState = aWVPState;
829
830   // ====================================
831   //      Step 2: Redraw background
832   // ====================================
833
834   // Render background
835   if (!theToDrawImmediate)
836   {
837     drawBackground (myWorkspace);
838   }
839
840 #if !defined(GL_ES_VERSION_2_0)
841   // Switch off lighting by default
842   if (aContext->core11 != NULL)
843   {
844     glDisable(GL_LIGHTING);
845   }
846 #endif
847
848   // =================================
849   //      Step 3: Redraw main plane
850   // =================================
851
852   // Setup face culling
853   GLboolean isCullFace = GL_FALSE;
854   if (myBackfacing != Graphic3d_TOBM_AUTOMATIC)
855   {
856     isCullFace = glIsEnabled (GL_CULL_FACE);
857     if (myBackfacing == Graphic3d_TOBM_DISABLE)
858     {
859       glEnable (GL_CULL_FACE);
860       glCullFace (GL_BACK);
861     }
862     else
863       glDisable (GL_CULL_FACE);
864   }
865
866 #if !defined(GL_ES_VERSION_2_0)
867   // if the view is scaled normal vectors are scaled to unit
868   // length for correct displaying of shaded objects
869   const gp_Pnt anAxialScale = myCamera->AxialScale();
870   if (anAxialScale.X() != 1.F ||
871       anAxialScale.Y() != 1.F ||
872       anAxialScale.Z() != 1.F)
873   {
874     aContext->SetGlNormalizeEnabled (Standard_True);
875   }
876   else
877   {
878     aContext->SetGlNormalizeEnabled (Standard_False);
879   }
880
881   // Apply Fog
882   if (myFog.IsOn
883    && aContext->core11 != NULL)
884   {
885     Standard_Real aFogFrontConverted = (Standard_Real )myFog.Front + myCamera->Distance();
886     if (myCamera->ZFar() < aFogFrontConverted)
887     {
888       aFogFrontConverted = myCamera->ZFar();
889       myFog.Front = (Standard_ShortReal )(aFogFrontConverted - myCamera->Distance());
890     }
891
892     Standard_Real aFogBackConverted = (Standard_Real )myFog.Back + myCamera->Distance();
893     if (myCamera->ZFar() < aFogFrontConverted)
894     {
895       aFogBackConverted = myCamera->ZFar();
896       myFog.Back = (Standard_ShortReal )(aFogBackConverted - myCamera->Distance());
897     }
898
899     if (aFogFrontConverted > aFogBackConverted)
900     {
901       myFog.Front = (Standard_ShortReal )(aFogFrontConverted - myCamera->Distance());
902       myFog.Back = (Standard_ShortReal )(aFogBackConverted - myCamera->Distance());
903     }
904
905     glFogi(GL_FOG_MODE, GL_LINEAR);
906     glFogf(GL_FOG_START, (Standard_ShortReal )aFogFrontConverted);
907     glFogf(GL_FOG_END, (Standard_ShortReal )aFogBackConverted);
908     glFogfv(GL_FOG_COLOR, myFog.Color.GetData());
909     glEnable(GL_FOG);
910   }
911   else if (aContext->core11 != NULL)
912   {
913     glDisable (GL_FOG);
914   }
915
916   // Apply InteriorShadingMethod
917   if (aContext->core11 != NULL)
918   {
919     aContext->core11->glShadeModel (myShadingModel == Graphic3d_TOSM_FACET
920                                  || myShadingModel == Graphic3d_TOSM_NONE ? GL_FLAT : GL_SMOOTH);
921   }
922 #endif
923
924   aManager->SetShadingModel (myShadingModel);
925
926   // Apply AntiAliasing
927   if (myAntiAliasing)
928     myWorkspace->NamedStatus |= OPENGL_NS_ANTIALIASING;
929   else
930     myWorkspace->NamedStatus &= ~OPENGL_NS_ANTIALIASING;
931
932   if (!aManager->IsEmpty())
933   {
934     aManager->UpdateClippingState();
935   }
936
937   // Redraw 3d scene
938   if (theProjection == Graphic3d_Camera::Projection_MonoLeftEye)
939   {
940     aContext->ProjectionState.SetCurrent (myCamera->ProjectionStereoLeftF());
941     aContext->ApplyProjectionMatrix();
942   }
943   else if (theProjection == Graphic3d_Camera::Projection_MonoRightEye)
944   {
945     aContext->ProjectionState.SetCurrent (myCamera->ProjectionStereoRightF());
946     aContext->ApplyProjectionMatrix();
947   }
948
949   myWorkspace->SetEnvironmentTexture (myTextureEnv);
950
951   renderScene (theProjection, theOutputFBO, theToDrawImmediate);
952
953   myWorkspace->SetEnvironmentTexture (Handle(OpenGl_Texture)());
954
955   // ===============================
956   //      Step 4: Trihedron
957   // ===============================
958
959   // Resetting GL parameters according to the default aspects
960   // in order to synchronize GL state with the graphic driver state
961   // before drawing auxiliary stuff (trihedrons, overlayer)
962   myWorkspace->ResetAppliedAspect();
963
964   aContext->ChangeClipping().RemoveAll (aContext);
965
966   if (!aManager->IsEmpty())
967   {
968     aManager->RevertClippingState();
969
970     // We need to disable (unbind) all shaders programs to ensure
971     // that all objects without specified aspect will be drawn
972     // correctly (such as background)
973     aContext->BindProgram (NULL);
974   }
975
976   // Render trihedron
977   if (!theToDrawImmediate)
978   {
979     renderTrihedron (myWorkspace);
980
981     // Restore face culling
982     if (myBackfacing != Graphic3d_TOBM_AUTOMATIC)
983     {
984       if (isCullFace)
985       {
986         glEnable (GL_CULL_FACE);
987         glCullFace (GL_BACK);
988       }
989       else
990         glDisable (GL_CULL_FACE);
991     }
992   }
993
994   // ==============================================================
995   //      Step 6: Keep shader manager informed about last View
996   // ==============================================================
997
998   if (!aManager.IsNull())
999   {
1000     aManager->SetLastView (this);
1001   }
1002 }
1003
1004 // =======================================================================
1005 // function : InvalidateBVHData
1006 // purpose  :
1007 // =======================================================================
1008 void OpenGl_View::InvalidateBVHData (const Graphic3d_ZLayerId theLayerId)
1009 {
1010   myZLayers.InvalidateBVHData (theLayerId);
1011 }
1012
1013 //=======================================================================
1014 //function : renderStructs
1015 //purpose  :
1016 //=======================================================================
1017 void OpenGl_View::renderStructs (Graphic3d_Camera::Projection theProjection,
1018                                  OpenGl_FrameBuffer*          theReadDrawFbo,
1019                                  const Standard_Boolean       theToDrawImmediate)
1020 {
1021   if ( myZLayers.NbStructures() <= 0 )
1022     return;
1023
1024   Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext();
1025   if ( (myWorkspace->NamedStatus & OPENGL_NS_2NDPASSNEED) == 0 )
1026   {
1027   #if !defined(GL_ES_VERSION_2_0)
1028     const int anAntiAliasingMode = myWorkspace->AntiAliasingMode();
1029   #endif
1030
1031     if ( !myAntiAliasing )
1032     {
1033     #if !defined(GL_ES_VERSION_2_0)
1034       if (aCtx->core11 != NULL)
1035       {
1036         glDisable (GL_POINT_SMOOTH);
1037       }
1038       glDisable(GL_LINE_SMOOTH);
1039       if( anAntiAliasingMode & 2 ) glDisable(GL_POLYGON_SMOOTH);
1040     #endif
1041       glBlendFunc (GL_ONE, GL_ZERO);
1042       glDisable (GL_BLEND);
1043     }
1044     else
1045     {
1046     #if !defined(GL_ES_VERSION_2_0)
1047       if (aCtx->core11 != NULL)
1048       {
1049         glEnable(GL_POINT_SMOOTH);
1050       }
1051       glEnable(GL_LINE_SMOOTH);
1052       if( anAntiAliasingMode & 2 ) glEnable(GL_POLYGON_SMOOTH);
1053     #endif
1054       glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1055       glEnable (GL_BLEND);
1056     }
1057   }
1058
1059   Standard_Boolean toRenderGL = theToDrawImmediate ||
1060     myRenderParams.Method != Graphic3d_RM_RAYTRACING ||
1061     myRaytraceInitStatus == OpenGl_RT_FAIL ||
1062     aCtx->IsFeedback();
1063
1064   if (!toRenderGL)
1065   {
1066     toRenderGL = !initRaytraceResources (aCtx) ||
1067       !updateRaytraceGeometry (OpenGl_GUM_CHECK, myId, aCtx);
1068
1069     toRenderGL |= !myIsRaytraceDataValid; // if no ray-trace data use OpenGL
1070
1071     if (!toRenderGL)
1072     {
1073       const Standard_Integer aSizeX = theReadDrawFbo != NULL ? theReadDrawFbo->GetVPSizeX() : myWindow->Width();
1074       const Standard_Integer aSizeY = theReadDrawFbo != NULL ? theReadDrawFbo->GetVPSizeY() : myWindow->Height();
1075       myOpenGlFBO ->InitLazy (aCtx, aSizeX, aSizeY, myFboColorFormat, myFboDepthFormat, 0);
1076
1077       if (myRaytraceFilter.IsNull())
1078         myRaytraceFilter = new OpenGl_RaytraceFilter;
1079
1080       myRaytraceFilter->SetPrevRenderFilter (myWorkspace->GetRenderFilter());
1081
1082       if (theReadDrawFbo != NULL)
1083         theReadDrawFbo->UnbindBuffer (aCtx);
1084
1085       // Prepare preliminary OpenGL output
1086       if (aCtx->arbFBOBlit != NULL)
1087       {
1088         // Render bottom OSD layer
1089         myZLayers.Render (myWorkspace, theToDrawImmediate, OpenGl_LF_Bottom);
1090
1091         myWorkspace->SetRenderFilter (myRaytraceFilter);
1092         {
1093           if (theReadDrawFbo != NULL)
1094           {
1095             theReadDrawFbo->BindReadBuffer (aCtx);
1096           }
1097           else
1098           {
1099             aCtx->arbFBO->glBindFramebuffer (GL_READ_FRAMEBUFFER, 0);
1100           }
1101
1102           myOpenGlFBO->BindDrawBuffer (aCtx);
1103
1104           aCtx->arbFBOBlit->glBlitFramebuffer (0, 0, aSizeX, aSizeY,
1105                                                0, 0, aSizeX, aSizeY,
1106                                                GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT,
1107                                                GL_NEAREST);
1108
1109           // Render non-polygonal elements in default layer
1110           myZLayers.Render (myWorkspace, theToDrawImmediate, OpenGl_LF_Default);
1111         }
1112         myWorkspace->SetRenderFilter (myRaytraceFilter->PrevRenderFilter());
1113       }
1114
1115       if (theReadDrawFbo != NULL)
1116       {
1117         theReadDrawFbo->BindBuffer (aCtx);
1118       }
1119       else
1120       {
1121         aCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, 0);
1122       }
1123
1124       // Reset OpenGl aspects state to default to avoid enabling of
1125       // backface culling which is not supported in ray-tracing.
1126       myWorkspace->ResetAppliedAspect();
1127
1128       // Ray-tracing polygonal primitive arrays
1129       raytrace (aSizeX, aSizeY, theProjection, theReadDrawFbo, aCtx);
1130
1131       // Render upper (top and topmost) OpenGL layers
1132       myZLayers.Render (myWorkspace, theToDrawImmediate, OpenGl_LF_Upper);
1133     }
1134   }
1135
1136   // Redraw 3D scene using OpenGL in standard
1137   // mode or in case of ray-tracing failure
1138   if (toRenderGL)
1139   {
1140     myZLayers.Render (myWorkspace, theToDrawImmediate, OpenGl_LF_All);
1141
1142     // Set flag that scene was redrawn by standard pipeline
1143     myWasRedrawnGL = Standard_True;
1144   }
1145 }
1146
1147 //=======================================================================
1148 //function : renderTrihedron
1149 //purpose  :
1150 //=======================================================================
1151 void OpenGl_View::renderTrihedron (const Handle(OpenGl_Workspace) &theWorkspace)
1152 {
1153   // display global trihedron
1154   if (myToShowTrihedron)
1155   {
1156     // disable environment texture
1157     Handle(OpenGl_Texture) anEnvironmentTexture = theWorkspace->EnvironmentTexture();
1158     theWorkspace->SetEnvironmentTexture (Handle(OpenGl_Texture)());
1159
1160     myTrihedron.Render (theWorkspace);
1161
1162     // restore environment texture
1163     theWorkspace->SetEnvironmentTexture (anEnvironmentTexture);
1164   }
1165   if (myToShowGradTrihedron)
1166   {
1167     myGraduatedTrihedron.Render (theWorkspace);
1168   }
1169 }
1170
1171 // =======================================================================
1172 // function : Invalidate
1173 // purpose  :
1174 // =======================================================================
1175 void OpenGl_View::Invalidate()
1176 {
1177   myBackBufferRestored = Standard_False;
1178 }
1179
1180 //=======================================================================
1181 //function : renderScene
1182 //purpose  :
1183 //=======================================================================
1184 void OpenGl_View::renderScene (Graphic3d_Camera::Projection theProjection,
1185                                OpenGl_FrameBuffer*          theReadDrawFbo,
1186                                const Standard_Boolean       theToDrawImmediate)
1187 {
1188   const Handle(OpenGl_Context)& aContext = myWorkspace->GetGlContext();
1189
1190   if (myZClip.Back.IsOn || myZClip.Front.IsOn)
1191   {
1192     Handle(Graphic3d_ClipPlane) aPlaneBack;
1193     Handle(Graphic3d_ClipPlane) aPlaneFront;
1194
1195     if (myZClip.Back.IsOn)
1196     {
1197       Standard_Real aClipBackConverted = (Standard_Real )myZClip.Front.Limit + myCamera->Distance();
1198       if (myCamera->ZFar() < aClipBackConverted)
1199       {
1200         aClipBackConverted = myCamera->ZFar();
1201         myZClip.Back.Limit = (Standard_ShortReal )(aClipBackConverted - myCamera->Distance());
1202       }
1203       const Graphic3d_ClipPlane::Equation aBackEquation (0.0, 0.0, 1.0, (Standard_ShortReal )aClipBackConverted);
1204       aPlaneBack = new Graphic3d_ClipPlane (aBackEquation);
1205     }
1206
1207     if (myZClip.Front.IsOn)
1208     {
1209       Standard_Real aClipFrontConverted = (Standard_Real )myZClip.Front.Limit + myCamera->Distance();
1210       if (myCamera->ZNear() > aClipFrontConverted)
1211       {
1212         aClipFrontConverted = myCamera->ZNear();
1213         myZClip.Front.Limit = (Standard_ShortReal )(aClipFrontConverted - myCamera->Distance());
1214       }
1215       const Graphic3d_ClipPlane::Equation aFrontEquation (0.0, 0.0, -1.0, (Standard_ShortReal )-aClipFrontConverted);
1216       aPlaneFront = new Graphic3d_ClipPlane (aFrontEquation);
1217     }
1218
1219     // Specify slicing planes with identity transformation
1220     if (!aPlaneBack.IsNull() || !aPlaneFront.IsNull())
1221     {
1222       Graphic3d_SequenceOfHClipPlane aSlicingPlanes;
1223       if (!aPlaneBack.IsNull())
1224       {
1225         aSlicingPlanes.Append (aPlaneBack);
1226       }
1227
1228       if (!aPlaneFront.IsNull())
1229       {
1230         aSlicingPlanes.Append (aPlaneFront);
1231       }
1232
1233       // add planes at loaded view matrix state
1234       aContext->ChangeClipping().AddView (aContext, aSlicingPlanes);
1235     }
1236   }
1237
1238 #ifdef _WIN32
1239   // set printing scale/tiling transformation
1240   Handle(OpenGl_PrinterContext) aPrintContext = myWorkspace->PrinterContext();
1241   if (!aPrintContext.IsNull())
1242   {
1243     aContext->ProjectionState.Push();
1244     aContext->ProjectionState.SetCurrent (aPrintContext->ProjTransformation() * aContext->ProjectionState.Current());
1245     aContext->ApplyProjectionMatrix();
1246   }
1247 #endif
1248
1249   // Specify clipping planes in view transformation space
1250   if (!myClipPlanes.IsEmpty())
1251   {
1252     Graphic3d_SequenceOfHClipPlane aUserPlanes;
1253     Graphic3d_SequenceOfHClipPlane::Iterator aClippingIt (myClipPlanes);
1254     for (; aClippingIt.More(); aClippingIt.Next())
1255     {
1256       const Handle(Graphic3d_ClipPlane)& aClipPlane = aClippingIt.Value();
1257       if (aClipPlane->IsOn())
1258       {
1259         aUserPlanes.Append (aClipPlane);
1260       }
1261     }
1262
1263     if (!aUserPlanes.IsEmpty())
1264     {
1265       aContext->ChangeClipping().AddWorldLazy (aContext, aUserPlanes);
1266     }
1267
1268     if (!aContext->ShaderManager()->IsEmpty())
1269     {
1270       aContext->ShaderManager()->UpdateClippingState();
1271     }
1272   }
1273
1274 #if !defined(GL_ES_VERSION_2_0)
1275   // Apply Lights
1276   if (aContext->core11 != NULL)
1277   {
1278     // setup lights
1279     Graphic3d_Vec4 anAmbientColor (THE_DEFAULT_AMBIENT[0],
1280                                    THE_DEFAULT_AMBIENT[1],
1281                                    THE_DEFAULT_AMBIENT[2],
1282                                    THE_DEFAULT_AMBIENT[3]);
1283     GLenum aLightGlId = GL_LIGHT0;
1284
1285     OpenGl_ListOfLight::Iterator aLightIt (myShadingModel == Graphic3d_TOSM_NONE ? myNoShadingLight : myLights);
1286     for (; aLightIt.More(); aLightIt.Next())
1287     {
1288       bindLight (aLightIt.Value(), aLightGlId, anAmbientColor, myWorkspace);
1289     }
1290
1291     // apply accumulated ambient color
1292     anAmbientColor.a() = 1.0f;
1293     glLightModelfv (GL_LIGHT_MODEL_AMBIENT, anAmbientColor.GetData());
1294
1295     if (aLightGlId != GL_LIGHT0)
1296     {
1297       glEnable (GL_LIGHTING);
1298     }
1299     // switch off unused lights
1300     for (; aLightGlId <= GL_LIGHT7; ++aLightGlId)
1301     {
1302       glDisable (aLightGlId);
1303     }
1304   }
1305 #endif
1306
1307   // Clear status bitfields
1308   myWorkspace->NamedStatus &= ~(OPENGL_NS_2NDPASSNEED | OPENGL_NS_2NDPASSDO);
1309
1310   // First pass
1311   renderStructs (theProjection, theReadDrawFbo, theToDrawImmediate);
1312   myWorkspace->DisableTexture();
1313
1314   // Second pass
1315   if (myWorkspace->NamedStatus & OPENGL_NS_2NDPASSNEED)
1316   {
1317     myWorkspace->NamedStatus |= OPENGL_NS_2NDPASSDO;
1318
1319     // Remember OpenGl properties
1320     GLint aSaveBlendDst = GL_ONE_MINUS_SRC_ALPHA, aSaveBlendSrc = GL_SRC_ALPHA;
1321     GLint aSaveZbuffFunc;
1322     GLboolean aSaveZbuffWrite;
1323     glGetBooleanv (GL_DEPTH_WRITEMASK, &aSaveZbuffWrite);
1324     glGetIntegerv (GL_DEPTH_FUNC, &aSaveZbuffFunc);
1325   #if !defined(GL_ES_VERSION_2_0)
1326     glGetIntegerv (GL_BLEND_DST, &aSaveBlendDst);
1327     glGetIntegerv (GL_BLEND_SRC, &aSaveBlendSrc);
1328   #endif
1329     GLboolean wasZbuffEnabled = glIsEnabled (GL_DEPTH_TEST);
1330     GLboolean wasBlendEnabled = glIsEnabled (GL_BLEND);
1331
1332     // Change the properties for second rendering pass
1333     glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1334     glEnable (GL_BLEND);
1335
1336     glDepthFunc (GL_EQUAL);
1337     glDepthMask (GL_FALSE);
1338     glEnable (GL_DEPTH_TEST);
1339
1340     // Render the view
1341     renderStructs (theProjection, theReadDrawFbo, theToDrawImmediate);
1342     myWorkspace->DisableTexture();
1343
1344     // Restore properties back
1345     glBlendFunc (aSaveBlendSrc, aSaveBlendDst);
1346     if (!wasBlendEnabled)
1347       glDisable (GL_BLEND);
1348
1349     glDepthFunc (aSaveZbuffFunc);
1350     glDepthMask (aSaveZbuffWrite);
1351     if (!wasZbuffEnabled)
1352       glDisable (GL_DEPTH_FUNC);
1353   }
1354
1355   // Apply restored view matrix.
1356   aContext->ApplyWorldViewMatrix();
1357
1358 #ifdef _WIN32
1359   // set printing scale/tiling transformation
1360   if (!aPrintContext.IsNull())
1361   {
1362     aContext->ProjectionState.Pop();
1363     aContext->ApplyProjectionMatrix();
1364   }
1365 #endif
1366 }
1367
1368 // =======================================================================
1369 // function : bindDefaultFbo
1370 // purpose  :
1371 // =======================================================================
1372 void OpenGl_View::bindDefaultFbo (OpenGl_FrameBuffer* theCustomFbo)
1373 {
1374   Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext();
1375   OpenGl_FrameBuffer* anFbo = (theCustomFbo != NULL && theCustomFbo->IsValid())
1376                             ?  theCustomFbo
1377                             : (!aCtx->DefaultFrameBuffer().IsNull()
1378                              && aCtx->DefaultFrameBuffer()->IsValid()
1379                               ? aCtx->DefaultFrameBuffer().operator->()
1380                               : NULL);
1381   if (anFbo != NULL)
1382   {
1383     anFbo->BindBuffer (aCtx);
1384   }
1385   else
1386   {
1387   #if !defined(GL_ES_VERSION_2_0)
1388     aCtx->SetReadDrawBuffer (GL_BACK);
1389   #else
1390     if (aCtx->arbFBO != NULL)
1391     {
1392       aCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
1393     }
1394   #endif
1395   }
1396   aCtx->core11fwd->glViewport (0, 0, myWindow->Width(), myWindow->Height());
1397 }
1398
1399 // =======================================================================
1400 // function : initBlitQuad
1401 // purpose  :
1402 // =======================================================================
1403 OpenGl_VertexBuffer* OpenGl_View::initBlitQuad (const Standard_Boolean theToFlip)
1404 {
1405   OpenGl_VertexBuffer* aVerts = NULL;
1406   if (!theToFlip)
1407   {
1408     aVerts = &myFullScreenQuad;
1409     if (!aVerts->IsValid())
1410     {
1411       OpenGl_Vec4 aQuad[4] =
1412       {
1413         OpenGl_Vec4( 1.0f, -1.0f, 1.0f, 0.0f),
1414         OpenGl_Vec4( 1.0f,  1.0f, 1.0f, 1.0f),
1415         OpenGl_Vec4(-1.0f, -1.0f, 0.0f, 0.0f),
1416         OpenGl_Vec4(-1.0f,  1.0f, 0.0f, 1.0f)
1417       };
1418       aVerts->Init (myWorkspace->GetGlContext(), 4, 4, aQuad[0].GetData());
1419     }
1420   }
1421   else
1422   {
1423     aVerts = &myFullScreenQuadFlip;
1424     if (!aVerts->IsValid())
1425     {
1426       OpenGl_Vec4 aQuad[4] =
1427       {
1428         OpenGl_Vec4( 1.0f, -1.0f, 1.0f, 1.0f),
1429         OpenGl_Vec4( 1.0f,  1.0f, 1.0f, 0.0f),
1430         OpenGl_Vec4(-1.0f, -1.0f, 0.0f, 1.0f),
1431         OpenGl_Vec4(-1.0f,  1.0f, 0.0f, 0.0f)
1432       };
1433       aVerts->Init (myWorkspace->GetGlContext(), 4, 4, aQuad[0].GetData());
1434     }
1435   }
1436   return aVerts;
1437 }
1438
1439 // =======================================================================
1440 // function : blitBuffers
1441 // purpose  :
1442 // =======================================================================
1443 bool OpenGl_View::blitBuffers (OpenGl_FrameBuffer*    theReadFbo,
1444                                OpenGl_FrameBuffer*    theDrawFbo,
1445                                const Standard_Boolean theToFlip)
1446 {
1447   Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext();
1448   if (theReadFbo == NULL || aCtx->IsFeedback())
1449   {
1450     return false;
1451   }
1452   else if (theReadFbo == theDrawFbo)
1453   {
1454     return true;
1455   }
1456
1457   // clear destination before blitting
1458   if (theDrawFbo != NULL
1459   &&  theDrawFbo->IsValid())
1460   {
1461     theDrawFbo->BindBuffer (aCtx);
1462   }
1463   else
1464   {
1465     aCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
1466   }
1467 #if !defined(GL_ES_VERSION_2_0)
1468   aCtx->core20fwd->glClearDepth  (1.0);
1469 #else
1470   aCtx->core20fwd->glClearDepthf (1.0f);
1471 #endif
1472   aCtx->core20fwd->glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1473
1474 #if !defined(GL_ES_VERSION_2_0)
1475   if (aCtx->arbFBOBlit != NULL
1476    && theReadFbo->NbSamples() != 0)
1477   {
1478     GLbitfield aCopyMask = 0;
1479     theReadFbo->BindReadBuffer (aCtx);
1480     if (theDrawFbo != NULL
1481      && theDrawFbo->IsValid())
1482     {
1483       theDrawFbo->BindDrawBuffer (aCtx);
1484       if (theDrawFbo->HasColor()
1485        && theReadFbo->HasColor())
1486       {
1487         aCopyMask |= GL_COLOR_BUFFER_BIT;
1488       }
1489       if (theDrawFbo->HasDepth()
1490        && theReadFbo->HasDepth())
1491       {
1492         aCopyMask |= GL_DEPTH_BUFFER_BIT;
1493       }
1494     }
1495     else
1496     {
1497       if (theReadFbo->HasColor())
1498       {
1499         aCopyMask |= GL_COLOR_BUFFER_BIT;
1500       }
1501       if (theReadFbo->HasDepth())
1502       {
1503         aCopyMask |= GL_DEPTH_BUFFER_BIT;
1504       }
1505       aCtx->arbFBO->glBindFramebuffer (GL_DRAW_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
1506     }
1507
1508     // we don't copy stencil buffer here... does it matter for performance?
1509     aCtx->arbFBOBlit->glBlitFramebuffer (0, 0, theReadFbo->GetVPSizeX(), theReadFbo->GetVPSizeY(),
1510                                          0, 0, theReadFbo->GetVPSizeX(), theReadFbo->GetVPSizeY(),
1511                                          aCopyMask, GL_NEAREST);
1512     const int anErr = ::glGetError();
1513     if (anErr != GL_NO_ERROR)
1514     {
1515       // glBlitFramebuffer() might fail in several cases:
1516       // - Both FBOs have MSAA and they are samples number does not match.
1517       //   OCCT checks that this does not happen,
1518       //   however some graphics drivers provide an option for overriding MSAA.
1519       //   In this case window MSAA might be non-zero (and application can not check it)
1520       //   and might not match MSAA of our offscreen FBOs.
1521       // - Pixel formats of FBOs do not match.
1522       //   This also might happen with window has pixel format,
1523       //   e.g. Mesa fails blitting RGBA8 -> RGB8 while other drivers support this conversion.
1524       TCollection_ExtendedString aMsg = TCollection_ExtendedString() + "FBO blitting has failed [Error #" + anErr + "]\n"
1525                                       + "  Please check your graphics driver settings or try updating driver.";
1526       if (theReadFbo->NbSamples() != 0)
1527       {
1528         myToDisableMSAA = true;
1529         aMsg += "\n  MSAA settings should not be overridden by driver!";
1530       }
1531       aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
1532                          GL_DEBUG_TYPE_ERROR,
1533                          0,
1534                          GL_DEBUG_SEVERITY_HIGH,
1535                          aMsg);
1536     }
1537
1538     if (theDrawFbo != NULL
1539      && theDrawFbo->IsValid())
1540     {
1541       theDrawFbo->BindBuffer (aCtx);
1542     }
1543     else
1544     {
1545       aCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
1546     }
1547   }
1548   else
1549 #endif
1550   {
1551     aCtx->core20fwd->glDepthFunc (GL_ALWAYS);
1552     aCtx->core20fwd->glDepthMask (GL_TRUE);
1553     aCtx->core20fwd->glEnable (GL_DEPTH_TEST);
1554
1555     myWorkspace->DisableTexture();
1556
1557     OpenGl_VertexBuffer* aVerts = initBlitQuad (theToFlip);
1558     const Handle(OpenGl_ShaderManager)& aManager = aCtx->ShaderManager();
1559     if (aVerts->IsValid()
1560      && aManager->BindFboBlitProgram())
1561     {
1562       theReadFbo->ColorTexture()       ->Bind   (aCtx, GL_TEXTURE0 + 0);
1563       theReadFbo->DepthStencilTexture()->Bind   (aCtx, GL_TEXTURE0 + 1);
1564       aVerts->BindVertexAttrib (aCtx, Graphic3d_TOA_POS);
1565
1566       aCtx->core20fwd->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
1567
1568       aVerts->UnbindVertexAttrib (aCtx, Graphic3d_TOA_POS);
1569       theReadFbo->DepthStencilTexture()->Unbind (aCtx, GL_TEXTURE0 + 1);
1570       theReadFbo->ColorTexture()       ->Unbind (aCtx, GL_TEXTURE0 + 0);
1571       aCtx->BindProgram (NULL);
1572     }
1573     else
1574     {
1575       TCollection_ExtendedString aMsg = TCollection_ExtendedString()
1576         + "Error! FBO blitting has failed";
1577       aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
1578                          GL_DEBUG_TYPE_ERROR,
1579                          0,
1580                          GL_DEBUG_SEVERITY_HIGH,
1581                          aMsg);
1582       myHasFboBlit = Standard_False;
1583       theReadFbo->Release (aCtx.operator->());
1584       return true;
1585     }
1586   }
1587   return true;
1588 }
1589
1590 // =======================================================================
1591 // function : drawStereoPair
1592 // purpose  :
1593 // =======================================================================
1594 void OpenGl_View::drawStereoPair (OpenGl_FrameBuffer* theDrawFbo)
1595 {
1596   const Handle(OpenGl_Context)& aCtx = myWorkspace->GetGlContext();
1597   bindDefaultFbo (theDrawFbo);
1598   OpenGl_FrameBuffer* aPair[2] =
1599   {
1600     myImmediateSceneFbos[0]->IsValid() ? myImmediateSceneFbos[0].operator->() : NULL,
1601     myImmediateSceneFbos[1]->IsValid() ? myImmediateSceneFbos[1].operator->() : NULL
1602   };
1603   if (aPair[0] == NULL
1604   ||  aPair[1] == NULL
1605   || !myTransientDrawToFront)
1606   {
1607     aPair[0] = myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL;
1608     aPair[1] = myMainSceneFbos[1]->IsValid() ? myMainSceneFbos[1].operator->() : NULL;
1609   }
1610
1611   if (aPair[0] == NULL
1612    || aPair[1] == NULL)
1613   {
1614     return;
1615   }
1616
1617   if (aPair[0]->NbSamples() != 0)
1618   {
1619     // resolve MSAA buffers before drawing
1620     if (!myOpenGlFBO ->InitLazy (aCtx, aPair[0]->GetVPSizeX(), aPair[0]->GetVPSizeY(), myFboColorFormat, myFboDepthFormat, 0)
1621      || !myOpenGlFBO2->InitLazy (aCtx, aPair[0]->GetVPSizeX(), aPair[0]->GetVPSizeY(), myFboColorFormat, 0, 0))
1622     {
1623       aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
1624                          GL_DEBUG_TYPE_ERROR,
1625                          0,
1626                          GL_DEBUG_SEVERITY_HIGH,
1627                          "Error! Unable to allocate FBO for blitting stereo pair");
1628       bindDefaultFbo (theDrawFbo);
1629       return;
1630     }
1631
1632     if (!blitBuffers (aPair[0], myOpenGlFBO .operator->(), Standard_False)
1633      || !blitBuffers (aPair[1], myOpenGlFBO2.operator->(), Standard_False))
1634     {
1635       bindDefaultFbo (theDrawFbo);
1636       return;
1637     }
1638
1639     aPair[0] = myOpenGlFBO .operator->();
1640     aPair[1] = myOpenGlFBO2.operator->();
1641     bindDefaultFbo (theDrawFbo);
1642   }
1643
1644   struct
1645   {
1646     Standard_Integer left;
1647     Standard_Integer top;
1648     Standard_Integer right;
1649     Standard_Integer bottom;
1650     Standard_Integer dx() { return right  - left; }
1651     Standard_Integer dy() { return bottom - top; }
1652   } aGeom;
1653
1654   myWindow->PlatformWindow()->Position (aGeom.left, aGeom.top, aGeom.right, aGeom.bottom);
1655
1656   Standard_Boolean toReverse = myRenderParams.ToReverseStereo;
1657   const Standard_Boolean isOddY = (aGeom.top + aGeom.dy()) % 2 == 1;
1658   const Standard_Boolean isOddX =  aGeom.left % 2 == 1;
1659   if (isOddY
1660    && (myRenderParams.StereoMode == Graphic3d_StereoMode_RowInterlaced
1661     || myRenderParams.StereoMode == Graphic3d_StereoMode_ChessBoard))
1662   {
1663     toReverse = !toReverse;
1664   }
1665   if (isOddX
1666    && (myRenderParams.StereoMode == Graphic3d_StereoMode_ColumnInterlaced
1667     || myRenderParams.StereoMode == Graphic3d_StereoMode_ChessBoard))
1668   {
1669     toReverse = !toReverse;
1670   }
1671
1672   if (toReverse)
1673   {
1674     std::swap (aPair[0], aPair[1]);
1675   }
1676
1677   aCtx->core20fwd->glDepthFunc (GL_ALWAYS);
1678   aCtx->core20fwd->glDepthMask (GL_TRUE);
1679   aCtx->core20fwd->glEnable (GL_DEPTH_TEST);
1680
1681   myWorkspace->DisableTexture();
1682   OpenGl_VertexBuffer* aVerts = initBlitQuad (myToFlipOutput);
1683
1684   const Handle(OpenGl_ShaderManager)& aManager = aCtx->ShaderManager();
1685   if (aVerts->IsValid()
1686    && aManager->BindStereoProgram (myRenderParams.StereoMode))
1687   {
1688     if (myRenderParams.StereoMode == Graphic3d_StereoMode_Anaglyph)
1689     {
1690       OpenGl_Mat4 aFilterL, aFilterR;
1691       aFilterL.SetDiagonal (Graphic3d_Vec4 (0.0f, 0.0f, 0.0f, 0.0f));
1692       aFilterR.SetDiagonal (Graphic3d_Vec4 (0.0f, 0.0f, 0.0f, 0.0f));
1693       switch (myRenderParams.AnaglyphFilter)
1694       {
1695         case Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple:
1696         {
1697           aFilterL.SetRow (0, Graphic3d_Vec4 (1.0f, 0.0f, 0.0f, 0.0f));
1698           aFilterR.SetRow (1, Graphic3d_Vec4 (0.0f, 1.0f, 0.0f, 0.0f));
1699           aFilterR.SetRow (2, Graphic3d_Vec4 (0.0f, 0.0f, 1.0f, 0.0f));
1700           break;
1701         }
1702         case Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized:
1703         {
1704           aFilterL.SetRow (0, Graphic3d_Vec4 ( 0.4154f,      0.4710f,      0.16666667f, 0.0f));
1705           aFilterL.SetRow (1, Graphic3d_Vec4 (-0.0458f,     -0.0484f,     -0.0257f,     0.0f));
1706           aFilterL.SetRow (2, Graphic3d_Vec4 (-0.0547f,     -0.0615f,      0.0128f,     0.0f));
1707           aFilterL.SetRow (3, Graphic3d_Vec4 ( 0.0f,         0.0f,         0.0f,        0.0f));
1708           aFilterR.SetRow (0, Graphic3d_Vec4 (-0.01090909f, -0.03636364f, -0.00606061f, 0.0f));
1709           aFilterR.SetRow (1, Graphic3d_Vec4 ( 0.37560000f,  0.73333333f,  0.01111111f, 0.0f));
1710           aFilterR.SetRow (2, Graphic3d_Vec4 (-0.06510000f, -0.12870000f,  1.29710000f, 0.0f));
1711           aFilterR.SetRow (3, Graphic3d_Vec4 ( 0.0f,                0.0f,  0.0f,        0.0f));
1712           break;
1713         }
1714         case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple:
1715         {
1716           aFilterL.SetRow (0, Graphic3d_Vec4 (1.0f, 0.0f, 0.0f, 0.0f));
1717           aFilterL.SetRow (1, Graphic3d_Vec4 (0.0f, 1.0f, 0.0f, 0.0f));
1718           aFilterR.SetRow (2, Graphic3d_Vec4 (0.0f, 0.0f, 1.0f, 0.0f));
1719           break;
1720         }
1721         case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized:
1722         {
1723           aFilterL.SetRow (0, Graphic3d_Vec4 ( 1.062f, -0.205f,  0.299f, 0.0f));
1724           aFilterL.SetRow (1, Graphic3d_Vec4 (-0.026f,  0.908f,  0.068f, 0.0f));
1725           aFilterL.SetRow (2, Graphic3d_Vec4 (-0.038f, -0.173f,  0.022f, 0.0f));
1726           aFilterL.SetRow (3, Graphic3d_Vec4 ( 0.0f,    0.0f,    0.0f,   0.0f));
1727           aFilterR.SetRow (0, Graphic3d_Vec4 (-0.016f, -0.123f, -0.017f, 0.0f));
1728           aFilterR.SetRow (1, Graphic3d_Vec4 ( 0.006f,  0.062f, -0.017f, 0.0f));
1729           aFilterR.SetRow (2, Graphic3d_Vec4 ( 0.094f,  0.185f,  0.911f, 0.0f));
1730           aFilterR.SetRow (3, Graphic3d_Vec4 ( 0.0f,    0.0f,    0.0f,   0.0f));
1731           break;
1732         }
1733         case Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple:
1734         {
1735           aFilterR.SetRow (0, Graphic3d_Vec4 (1.0f, 0.0f, 0.0f, 0.0f));
1736           aFilterL.SetRow (1, Graphic3d_Vec4 (0.0f, 1.0f, 0.0f, 0.0f));
1737           aFilterR.SetRow (2, Graphic3d_Vec4 (0.0f, 0.0f, 1.0f, 0.0f));
1738           break;
1739         }
1740         case Graphic3d_RenderingParams::Anaglyph_UserDefined:
1741         {
1742           aFilterL = myRenderParams.AnaglyphLeft;
1743           aFilterR = myRenderParams.AnaglyphRight;
1744           break;
1745         }
1746       }
1747       aCtx->ActiveProgram()->SetUniform (aCtx, "uMultL", aFilterL);
1748       aCtx->ActiveProgram()->SetUniform (aCtx, "uMultR", aFilterR);
1749     }
1750
1751     aPair[0]->ColorTexture()->Bind (aCtx, GL_TEXTURE0 + 0);
1752     aPair[1]->ColorTexture()->Bind (aCtx, GL_TEXTURE0 + 1);
1753     aVerts->BindVertexAttrib (aCtx, 0);
1754
1755     aCtx->core20fwd->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
1756
1757     aVerts->UnbindVertexAttrib (aCtx, 0);
1758     aPair[1]->ColorTexture()->Unbind (aCtx, GL_TEXTURE0 + 1);
1759     aPair[0]->ColorTexture()->Unbind (aCtx, GL_TEXTURE0 + 0);
1760   }
1761   else
1762   {
1763     TCollection_ExtendedString aMsg = TCollection_ExtendedString()
1764       + "Error! Anaglyph has failed";
1765     aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
1766                        GL_DEBUG_TYPE_ERROR,
1767                        0,
1768                        GL_DEBUG_SEVERITY_HIGH,
1769                        aMsg);
1770   }
1771 }
1772
1773 // =======================================================================
1774 // function : copyBackToFront
1775 // purpose  :
1776 // =======================================================================
1777 void OpenGl_View::copyBackToFront()
1778 {
1779 #if !defined(GL_ES_VERSION_2_0)
1780
1781   OpenGl_Mat4 aProjectMat;
1782   Graphic3d_TransformUtils::Ortho2D (aProjectMat,
1783     0.f, static_cast<GLfloat> (myWindow->Width()), 0.f, static_cast<GLfloat> (myWindow->Height()));
1784
1785   Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext();
1786   aCtx->WorldViewState.Push();
1787   aCtx->ProjectionState.Push();
1788
1789   aCtx->WorldViewState.SetIdentity();
1790   aCtx->ProjectionState.SetCurrent (aProjectMat);
1791
1792   aCtx->ApplyProjectionMatrix();
1793   aCtx->ApplyWorldViewMatrix();
1794
1795   aCtx->DisableFeatures();
1796
1797   switch (aCtx->DrawBuffer())
1798   {
1799     case GL_BACK_LEFT:
1800     {
1801       aCtx->SetReadBuffer (GL_BACK_LEFT);
1802       aCtx->SetDrawBuffer (GL_FRONT_LEFT);
1803       break;
1804     }
1805     case GL_BACK_RIGHT:
1806     {
1807       aCtx->SetReadBuffer (GL_BACK_RIGHT);
1808       aCtx->SetDrawBuffer (GL_FRONT_RIGHT);
1809       break;
1810     }
1811     default:
1812     {
1813       aCtx->SetReadBuffer (GL_BACK);
1814       aCtx->SetDrawBuffer (GL_FRONT);
1815       break;
1816     }
1817   }
1818
1819   glRasterPos2i (0, 0);
1820   glCopyPixels  (0, 0, myWindow->Width() + 1, myWindow->Height() + 1, GL_COLOR);
1821   //glCopyPixels  (0, 0, myWidth + 1, myHeight + 1, GL_DEPTH);
1822
1823   aCtx->EnableFeatures();
1824
1825   aCtx->WorldViewState.Pop();
1826   aCtx->ProjectionState.Pop();
1827   aCtx->ApplyProjectionMatrix();
1828
1829   // read/write from front buffer now
1830   aCtx->SetReadBuffer (aCtx->DrawBuffer());
1831 #endif
1832   myIsImmediateDrawn = Standard_False;
1833 }