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