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