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