5fb382dc9d171fe49f9f3b6f415df1300e2b52b1
[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   if ( aFrameBuffer == NULL
293    && !aCtx->DefaultFrameBuffer().IsNull()
294    &&  aCtx->DefaultFrameBuffer()->IsValid())
295   {
296     aFrameBuffer = aCtx->DefaultFrameBuffer().operator->();
297   }
298
299   if (myHasFboBlit
300    && (myTransientDrawToFront || aProjectType == Graphic3d_Camera::Projection_Stereo))
301   {
302     if (myMainSceneFbos[0]->GetVPSizeX() != aSizeX
303      || myMainSceneFbos[0]->GetVPSizeY() != aSizeY)
304     {
305       // prepare FBOs containing main scene
306       // for further blitting and rendering immediate presentations on top
307       if (aCtx->core20fwd != NULL)
308       {
309         myMainSceneFbos[0]->Init (aCtx, aSizeX, aSizeY);
310       }
311       if (!aCtx->caps->useSystemBuffer && myMainSceneFbos[0]->IsValid())
312       {
313         myImmediateSceneFbos[0]->InitLazy (aCtx, aSizeX, aSizeY);
314       }
315     }
316   }
317   else
318   {
319     myMainSceneFbos     [0]->Release (aCtx.operator->());
320     myMainSceneFbos     [1]->Release (aCtx.operator->());
321     myImmediateSceneFbos[0]->Release (aCtx.operator->());
322     myImmediateSceneFbos[1]->Release (aCtx.operator->());
323     myMainSceneFbos     [0]->ChangeViewport (0, 0);
324     myMainSceneFbos     [1]->ChangeViewport (0, 0);
325     myImmediateSceneFbos[0]->ChangeViewport (0, 0);
326     myImmediateSceneFbos[1]->ChangeViewport (0, 0);
327   }
328
329   if (aProjectType == Graphic3d_Camera::Projection_Stereo
330    && myMainSceneFbos[0]->IsValid())
331   {
332     myMainSceneFbos[1]->InitLazy (aCtx, aSizeX, aSizeY);
333     if (!myMainSceneFbos[1]->IsValid())
334     {
335       // no enough memory?
336       aProjectType = Graphic3d_Camera::Projection_Perspective;
337     }
338     else if (!myTransientDrawToFront)
339     {
340       //
341     }
342     else if (!aCtx->HasStereoBuffers() || aStereoMode != Graphic3d_StereoMode_QuadBuffer)
343     {
344       myImmediateSceneFbos[0]->InitLazy (aCtx, aSizeX, aSizeY);
345       myImmediateSceneFbos[1]->InitLazy (aCtx, aSizeX, aSizeY);
346       if (!myImmediateSceneFbos[0]->IsValid()
347        || !myImmediateSceneFbos[1]->IsValid())
348       {
349         aProjectType = Graphic3d_Camera::Projection_Perspective;
350       }
351     }
352   }
353
354   if (aProjectType == Graphic3d_Camera::Projection_Stereo)
355   {
356     OpenGl_FrameBuffer* aMainFbos[2] =
357     {
358       myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL,
359       myMainSceneFbos[1]->IsValid() ? myMainSceneFbos[1].operator->() : NULL
360     };
361     OpenGl_FrameBuffer* anImmFbos[2] =
362     {
363       myImmediateSceneFbos[0]->IsValid() ? myImmediateSceneFbos[0].operator->() : NULL,
364       myImmediateSceneFbos[1]->IsValid() ? myImmediateSceneFbos[1].operator->() : NULL
365     };
366
367     if (!myTransientDrawToFront)
368     {
369       anImmFbos[0] = aMainFbos[0];
370       anImmFbos[1] = aMainFbos[1];
371     }
372     else if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip
373           || aStereoMode == Graphic3d_StereoMode_QuadBuffer)
374     {
375       anImmFbos[0] = NULL;
376       anImmFbos[1] = NULL;
377     }
378
379   #if !defined(GL_ES_VERSION_2_0)
380     aCtx->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_LEFT : GL_BACK);
381   #endif
382     redraw (Graphic3d_Camera::Projection_MonoLeftEye, aMainFbos[0]);
383     myBackBufferRestored = Standard_True;
384     myIsImmediateDrawn   = Standard_False;
385   #if !defined(GL_ES_VERSION_2_0)
386     aCtx->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_LEFT : GL_BACK);
387   #endif
388     if (!redrawImmediate (Graphic3d_Camera::Projection_MonoLeftEye, aMainFbos[0], anImmFbos[0]))
389     {
390       toSwap = false;
391     }
392     else if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip && toSwap)
393     {
394       aCtx->SwapBuffers();
395     }
396
397   #if !defined(GL_ES_VERSION_2_0)
398     aCtx->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_RIGHT : GL_BACK);
399   #endif
400     redraw (Graphic3d_Camera::Projection_MonoRightEye, aMainFbos[1]);
401     myBackBufferRestored = Standard_True;
402     myIsImmediateDrawn   = Standard_False;
403     if (!redrawImmediate (Graphic3d_Camera::Projection_MonoRightEye, aMainFbos[1], anImmFbos[1]))
404     {
405       toSwap = false;
406     }
407
408     if (anImmFbos[0] != NULL)
409     {
410       bindDefaultFbo (aFrameBuffer);
411       drawStereoPair();
412     }
413   }
414   else
415   {
416     OpenGl_FrameBuffer* aMainFbo = myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL;
417     OpenGl_FrameBuffer* anImmFbo = aFrameBuffer;
418     if (!aCtx->caps->useSystemBuffer && myImmediateSceneFbos[0]->IsValid())
419     {
420       anImmFbo = myImmediateSceneFbos[0].operator->();
421     }
422
423   #if !defined(GL_ES_VERSION_2_0)
424     if (aMainFbo     == NULL
425      && aFrameBuffer == NULL)
426     {
427       aCtx->SetReadDrawBuffer (GL_BACK);
428     }
429   #endif
430     redraw (aProjectType, aMainFbo != NULL ? aMainFbo : aFrameBuffer);
431     myBackBufferRestored = Standard_True;
432     myIsImmediateDrawn   = Standard_False;
433     if (!redrawImmediate (aProjectType, aMainFbo, anImmFbo))
434     {
435       toSwap = false;
436     }
437
438     if (anImmFbo != NULL
439      && anImmFbo != aFrameBuffer)
440     {
441       blitBuffers (anImmFbo, aFrameBuffer, myToFlipOutput);
442     }
443   }
444
445 #if defined(_WIN32) && defined(HAVE_VIDEOCAPTURE)
446   if (OpenGl_AVIWriter_AllowWriting (myWindow->PlatformWindow()->NativeHandle()))
447   {
448     GLint params[4];
449     glGetIntegerv (GL_VIEWPORT, params);
450     int nWidth  = params[2] & ~0x7;
451     int nHeight = params[3] & ~0x7;
452
453     const int nBitsPerPixel = 24;
454     GLubyte* aDumpData = new GLubyte[nWidth * nHeight * nBitsPerPixel / 8];
455
456     glPixelStorei (GL_PACK_ALIGNMENT, 1);
457     glReadPixels (0, 0, nWidth, nHeight, GL_BGR_EXT, GL_UNSIGNED_BYTE, aDumpData);
458     OpenGl_AVIWriter_AVIWriter (aDumpData, nWidth, nHeight, nBitsPerPixel);
459     delete[] aDumpData;
460   }
461 #endif
462
463   if (myRenderParams.Method == Graphic3d_RM_RAYTRACING
464    && myRenderParams.IsGlobalIlluminationEnabled)
465   {
466     myAccumFrames++;
467   }
468
469   // bind default FBO
470   bindDefaultFbo();
471
472   // Swap the buffers
473   if (toSwap)
474   {
475     aCtx->SwapBuffers();
476     if (!myMainSceneFbos[0]->IsValid())
477     {
478       myBackBufferRestored = Standard_False;
479     }
480   }
481   else
482   {
483     aCtx->core11fwd->glFlush();
484   }
485
486   // reset render mode state
487   aCtx->FetchState();
488
489   myWasRedrawnGL = Standard_True;
490 }
491
492 // =======================================================================
493 // function : RedrawImmediate
494 // purpose  :
495 // =======================================================================
496 void OpenGl_View::RedrawImmediate()
497 {
498   if (!myWorkspace->Activate())
499     return;
500
501   Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext();
502   if (!myTransientDrawToFront
503    || !myBackBufferRestored
504    || (aCtx->caps->buffersNoSwap && !myMainSceneFbos[0]->IsValid()))
505   {
506     Redraw();
507     return;
508   }
509
510   const Graphic3d_StereoMode   aStereoMode  = myRenderParams.StereoMode;
511   Graphic3d_Camera::Projection aProjectType = myCamera->ProjectionType();
512   OpenGl_FrameBuffer*          aFrameBuffer = (OpenGl_FrameBuffer* )myFBO;
513
514   if ( aFrameBuffer == NULL
515    && !aCtx->DefaultFrameBuffer().IsNull()
516    &&  aCtx->DefaultFrameBuffer()->IsValid())
517   {
518     aFrameBuffer = aCtx->DefaultFrameBuffer().operator->();
519   }
520
521   if (aProjectType == Graphic3d_Camera::Projection_Stereo)
522   {
523     if (myMainSceneFbos[0]->IsValid()
524     && !myMainSceneFbos[1]->IsValid())
525     {
526       aProjectType = Graphic3d_Camera::Projection_Perspective;
527     }
528   }
529
530   bool toSwap = false;
531   if (aProjectType == Graphic3d_Camera::Projection_Stereo)
532   {
533     OpenGl_FrameBuffer* aMainFbos[2] =
534     {
535       myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL,
536       myMainSceneFbos[1]->IsValid() ? myMainSceneFbos[1].operator->() : NULL
537     };
538     OpenGl_FrameBuffer* anImmFbos[2] =
539     {
540       myImmediateSceneFbos[0]->IsValid() ? myImmediateSceneFbos[0].operator->() : NULL,
541       myImmediateSceneFbos[1]->IsValid() ? myImmediateSceneFbos[1].operator->() : NULL
542     };
543     if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip
544      || aStereoMode == Graphic3d_StereoMode_QuadBuffer)
545     {
546       anImmFbos[0] = NULL;
547       anImmFbos[1] = NULL;
548     }
549
550     if (aCtx->arbFBO != NULL)
551     {
552       aCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
553     }
554   #if !defined(GL_ES_VERSION_2_0)
555     if (anImmFbos[0] == NULL)
556     {
557       aCtx->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_LEFT : GL_BACK);
558     }
559   #endif
560     toSwap = redrawImmediate (Graphic3d_Camera::Projection_MonoLeftEye,
561                               aMainFbos[0],
562                               anImmFbos[0],
563                               Standard_True) || toSwap;
564     if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip
565     &&  toSwap
566     && !aCtx->caps->buffersNoSwap)
567     {
568       aCtx->SwapBuffers();
569     }
570
571     if (aCtx->arbFBO != NULL)
572     {
573       aCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
574     }
575   #if !defined(GL_ES_VERSION_2_0)
576     if (anImmFbos[1] == NULL)
577     {
578       aCtx->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_RIGHT : GL_BACK);
579     }
580   #endif
581     toSwap = redrawImmediate (Graphic3d_Camera::Projection_MonoRightEye,
582                               aMainFbos[1],
583                               anImmFbos[1],
584                               Standard_True) || toSwap;
585     if (anImmFbos[0] != NULL)
586     {
587       bindDefaultFbo (aFrameBuffer);
588       drawStereoPair();
589     }
590   }
591   else
592   {
593     OpenGl_FrameBuffer* aMainFbo = myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL;
594     OpenGl_FrameBuffer* anImmFbo = aFrameBuffer;
595     if (!aCtx->caps->useSystemBuffer && myImmediateSceneFbos[0]->IsValid())
596     {
597       anImmFbo = myImmediateSceneFbos[0].operator->();
598     }
599   #if !defined(GL_ES_VERSION_2_0)
600     if (aMainFbo == NULL)
601     {
602       aCtx->SetReadDrawBuffer (GL_BACK);
603     }
604   #endif
605     toSwap = redrawImmediate (aProjectType,
606                               aMainFbo,
607                               anImmFbo,
608                               Standard_True) || toSwap;
609     if (anImmFbo != NULL
610      && anImmFbo != aFrameBuffer)
611     {
612       blitBuffers (anImmFbo, aFrameBuffer, myToFlipOutput);
613     }
614   }
615
616   // bind default FBO
617   bindDefaultFbo();
618
619   if (toSwap && !aCtx->caps->buffersNoSwap)
620   {
621     aCtx->SwapBuffers();
622   }
623   else
624   {
625     aCtx->core11fwd->glFlush();
626   }
627
628   myWasRedrawnGL = Standard_True;
629 }
630
631 // =======================================================================
632 // function : redraw
633 // purpose  :
634 // =======================================================================
635 void OpenGl_View::redraw (const Graphic3d_Camera::Projection theProjection, OpenGl_FrameBuffer* theReadDrawFbo)
636 {
637   Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext();
638   if (theReadDrawFbo != NULL)
639   {
640     theReadDrawFbo->BindBuffer    (aCtx);
641     theReadDrawFbo->SetupViewport (aCtx);
642   }
643   else
644   {
645     aCtx->core11fwd->glViewport (0, 0, myWindow->Width(), myWindow->Height());
646   }
647
648   // request reset of material
649   myWorkspace->NamedStatus    |= OPENGL_NS_RESMAT;
650   myWorkspace->UseZBuffer()    = Standard_True;
651   myWorkspace->UseDepthWrite() = Standard_True;
652   GLbitfield toClear = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT;
653   glDepthFunc (GL_LEQUAL);
654   glDepthMask (GL_TRUE);
655   glEnable (GL_DEPTH_TEST);
656
657 #if !defined(GL_ES_VERSION_2_0)
658   glClearDepth (1.0);
659 #else
660   glClearDepthf (1.0f);
661 #endif
662
663   if (myWorkspace->NamedStatus & OPENGL_NS_WHITEBACK)
664   {
665     // set background to white
666     glClearColor (1.0f, 1.0f, 1.0f, 1.0f);
667   }
668   else
669   {
670     glClearColor (myBgColor.rgb[0], myBgColor.rgb[1], myBgColor.rgb[2], 0.0f);
671   }
672
673   glClear (toClear);
674
675   render (theProjection, theReadDrawFbo, Standard_False);
676 }
677
678 // =======================================================================
679 // function : redrawMonoImmediate
680 // purpose  :
681 // =======================================================================
682 bool OpenGl_View::redrawImmediate (const Graphic3d_Camera::Projection theProjection,
683                                    OpenGl_FrameBuffer*    theReadFbo,
684                                    OpenGl_FrameBuffer*    theDrawFbo,
685                                    const Standard_Boolean theIsPartialUpdate)
686 {
687   Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext();
688   GLboolean toCopyBackToFront = GL_FALSE;
689   if (!myTransientDrawToFront)
690   {
691     myBackBufferRestored = Standard_False;
692   }
693   else if (theReadFbo != NULL
694         && theReadFbo->IsValid()
695         && aCtx->IsRender())
696   {
697     if (!blitBuffers (theReadFbo, theDrawFbo))
698     {
699       return true;
700     }
701   }
702   else if (theDrawFbo == NULL)
703   {
704   #if !defined(GL_ES_VERSION_2_0)
705     aCtx->core11fwd->glGetBooleanv (GL_DOUBLEBUFFER, &toCopyBackToFront);
706   #endif
707     if (toCopyBackToFront)
708     {
709       if (!HasImmediateStructures()
710        && !theIsPartialUpdate)
711       {
712         // prefer Swap Buffers within Redraw in compatibility mode (without FBO)
713         return true;
714       }
715       copyBackToFront();
716     }
717     else
718     {
719       myBackBufferRestored = Standard_False;
720     }
721   }
722   else
723   {
724     myBackBufferRestored = Standard_False;
725   }
726   myIsImmediateDrawn = Standard_True;
727
728   myWorkspace->UseZBuffer()    = Standard_True;
729   myWorkspace->UseDepthWrite() = Standard_True;
730   glDepthFunc (GL_LEQUAL);
731   glDepthMask (GL_TRUE);
732   glEnable (GL_DEPTH_TEST);
733 #if !defined(GL_ES_VERSION_2_0)
734   glClearDepth (1.0);
735 #else
736   glClearDepthf (1.0f);
737 #endif
738
739   render (theProjection, theDrawFbo, Standard_True);
740
741   return !toCopyBackToFront;
742 }
743
744 //=======================================================================
745 //function : Render
746 //purpose  :
747 //=======================================================================
748 void OpenGl_View::render (Graphic3d_Camera::Projection theProjection,
749                           OpenGl_FrameBuffer*          theOutputFBO,
750                           const Standard_Boolean       theToDrawImmediate)
751 {
752   // ==================================
753   //      Step 1: Prepare for render
754   // ==================================
755
756   const Handle(OpenGl_Context)& aContext = myWorkspace->GetGlContext();
757
758 #if !defined(GL_ES_VERSION_2_0)
759   // Disable current clipping planes
760   if (aContext->core11 != NULL)
761   {
762     const Standard_Integer aMaxPlanes = aContext->MaxClipPlanes();
763     for (Standard_Integer aClipPlaneId = GL_CLIP_PLANE0; aClipPlaneId < GL_CLIP_PLANE0 + aMaxPlanes; ++aClipPlaneId)
764     {
765       aContext->core11fwd->glDisable (aClipPlaneId);
766     }
767   }
768 #endif
769
770   // Update states of OpenGl_BVHTreeSelector (frustum culling algorithm).
771   myBVHSelector.SetViewVolume (myCamera);
772
773   const Handle(OpenGl_ShaderManager)& aManager   = aContext->ShaderManager();
774   if (StateInfo (myCurrLightSourceState, aManager->LightSourceState().Index()) != myLastLightSourceState)
775   {
776     aManager->UpdateLightSourceStateTo (myShadingModel == Graphic3d_TOSM_NONE ? &OpenGl_NoShadingLight() : &myLights);
777     myLastLightSourceState = StateInfo (myCurrLightSourceState, aManager->LightSourceState().Index());
778   }
779
780   // Update matrices if camera has changed.
781   Graphic3d_WorldViewProjState aWVPState = myCamera->WorldViewProjState();
782   const Standard_Boolean isCameraChanged = myWorldViewProjState != aWVPState;
783   const Standard_Boolean isSameView      = aManager->IsSameView (this);
784   if (isCameraChanged)
785   {
786     aContext->ProjectionState.SetCurrent (myCamera->ProjectionMatrixF());
787     aContext->WorldViewState .SetCurrent (myCamera->OrientationMatrixF());
788     myAccumFrames = 0;
789   }
790
791   // Apply new matrix state if camera has changed or this view differs from the one
792   // that was previously used for configuring matrices of shader manager
793   // (ApplyProjectionMatrix and ApplyWorldViewMatrix will affect the manager).
794   if (isCameraChanged || !isSameView)
795   {
796     aContext->ApplyProjectionMatrix();
797     aContext->ApplyWorldViewMatrix();
798   }
799
800   if (aManager->ModelWorldState().Index() == 0)
801   {
802     aContext->ShaderManager()->UpdateModelWorldStateTo (OpenGl_Mat4());
803   }
804
805   myWorldViewProjState = aWVPState;
806
807   // ====================================
808   //      Step 2: Redraw background
809   // ====================================
810
811   // Render background
812   if (!theToDrawImmediate)
813   {
814     drawBackground (myWorkspace);
815   }
816
817 #if !defined(GL_ES_VERSION_2_0)
818   // Switch off lighting by default
819   if (aContext->core11 != NULL)
820   {
821     glDisable(GL_LIGHTING);
822   }
823 #endif
824
825   // =================================
826   //      Step 3: Redraw main plane
827   // =================================
828
829   // Setup face culling
830   GLboolean isCullFace = GL_FALSE;
831   if (myBackfacing != Graphic3d_TOBM_AUTOMATIC)
832   {
833     isCullFace = glIsEnabled (GL_CULL_FACE);
834     if (myBackfacing == Graphic3d_TOBM_DISABLE)
835     {
836       glEnable (GL_CULL_FACE);
837       glCullFace (GL_BACK);
838     }
839     else
840       glDisable (GL_CULL_FACE);
841   }
842
843 #if !defined(GL_ES_VERSION_2_0)
844   // if the view is scaled normal vectors are scaled to unit
845   // length for correct displaying of shaded objects
846   const gp_Pnt anAxialScale = myCamera->AxialScale();
847   if (anAxialScale.X() != 1.F ||
848       anAxialScale.Y() != 1.F ||
849       anAxialScale.Z() != 1.F)
850   {
851     aContext->SetGlNormalizeEnabled (Standard_True);
852   }
853   else
854   {
855     aContext->SetGlNormalizeEnabled (Standard_False);
856   }
857
858   // Apply Fog
859   if (myFog.IsOn
860    && aContext->core11 != NULL)
861   {
862     Standard_Real aFogFrontConverted = (Standard_Real )myFog.Front + myCamera->Distance();
863     if (myCamera->ZFar() < aFogFrontConverted)
864     {
865       aFogFrontConverted = myCamera->ZFar();
866       myFog.Front = (Standard_ShortReal )(aFogFrontConverted - myCamera->Distance());
867     }
868
869     Standard_Real aFogBackConverted = (Standard_Real )myFog.Back + myCamera->Distance();
870     if (myCamera->ZFar() < aFogFrontConverted)
871     {
872       aFogBackConverted = myCamera->ZFar();
873       myFog.Back = (Standard_ShortReal )(aFogBackConverted - myCamera->Distance());
874     }
875
876     if (aFogFrontConverted > aFogBackConverted)
877     {
878       myFog.Front = (Standard_ShortReal )(aFogFrontConverted - myCamera->Distance());
879       myFog.Back = (Standard_ShortReal )(aFogBackConverted - myCamera->Distance());
880     }
881
882     glFogi(GL_FOG_MODE, GL_LINEAR);
883     glFogf(GL_FOG_START, (Standard_ShortReal )aFogFrontConverted);
884     glFogf(GL_FOG_END, (Standard_ShortReal )aFogBackConverted);
885     glFogfv(GL_FOG_COLOR, myFog.Color.rgb);
886     glEnable(GL_FOG);
887   }
888   else if (aContext->core11 != NULL)
889   {
890     glDisable (GL_FOG);
891   }
892
893   // Apply InteriorShadingMethod
894   if (aContext->core11 != NULL)
895   {
896     aContext->core11->glShadeModel (myShadingModel == Graphic3d_TOSM_FACET
897                                  || myShadingModel == Graphic3d_TOSM_NONE ? GL_FLAT : GL_SMOOTH);
898   }
899 #endif
900
901   aManager->SetShadingModel (myShadingModel);
902
903   // Apply AntiAliasing
904   if (myAntiAliasing)
905     myWorkspace->NamedStatus |= OPENGL_NS_ANTIALIASING;
906   else
907     myWorkspace->NamedStatus &= ~OPENGL_NS_ANTIALIASING;
908
909   if (!aManager->IsEmpty())
910   {
911     aManager->UpdateClippingState();
912   }
913
914   // Redraw 3d scene
915   if (theProjection == Graphic3d_Camera::Projection_MonoLeftEye)
916   {
917     aContext->ProjectionState.SetCurrent (myCamera->ProjectionStereoLeftF());
918     aContext->ApplyProjectionMatrix();
919   }
920   else if (theProjection == Graphic3d_Camera::Projection_MonoRightEye)
921   {
922     aContext->ProjectionState.SetCurrent (myCamera->ProjectionStereoRightF());
923     aContext->ApplyProjectionMatrix();
924   }
925   renderScene (theProjection, theOutputFBO, theToDrawImmediate);
926
927   // ===============================
928   //      Step 4: Trihedron
929   // ===============================
930
931   // Resetting GL parameters according to the default aspects
932   // in order to synchronize GL state with the graphic driver state
933   // before drawing auxiliary stuff (trihedrons, overlayer)
934   myWorkspace->ResetAppliedAspect();
935
936   aContext->ChangeClipping().RemoveAll (aContext);
937
938   if (!aManager->IsEmpty())
939   {
940     aManager->ResetMaterialStates();
941     aManager->RevertClippingState();
942
943     // We need to disable (unbind) all shaders programs to ensure
944     // that all objects without specified aspect will be drawn
945     // correctly (such as background)
946     aContext->BindProgram (NULL);
947   }
948
949   // Render trihedron
950   if (!theToDrawImmediate)
951   {
952     renderTrihedron (myWorkspace);
953
954     // Restore face culling
955     if (myBackfacing != Graphic3d_TOBM_AUTOMATIC)
956     {
957       if (isCullFace)
958       {
959         glEnable (GL_CULL_FACE);
960         glCullFace (GL_BACK);
961       }
962       else
963         glDisable (GL_CULL_FACE);
964     }
965   }
966
967   // ==============================================================
968   //      Step 6: Keep shader manager informed about last View
969   // ==============================================================
970
971   if (!aManager.IsNull())
972   {
973     aManager->SetLastView (this);
974   }
975 }
976
977 // =======================================================================
978 // function : InvalidateBVHData
979 // purpose  :
980 // =======================================================================
981 void OpenGl_View::InvalidateBVHData (const Graphic3d_ZLayerId theLayerId)
982 {
983   myZLayers.InvalidateBVHData (theLayerId);
984 }
985
986 //=======================================================================
987 //function : renderStructs
988 //purpose  :
989 //=======================================================================
990 void OpenGl_View::renderStructs (Graphic3d_Camera::Projection theProjection,
991                                  OpenGl_FrameBuffer*          theReadDrawFbo,
992                                  const Standard_Boolean       theToDrawImmediate)
993 {
994   if ( myZLayers.NbStructures() <= 0 )
995     return;
996
997   Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext();
998   if ( (myWorkspace->NamedStatus & OPENGL_NS_2NDPASSNEED) == 0 )
999   {
1000   #if !defined(GL_ES_VERSION_2_0)
1001     const int anAntiAliasingMode = myWorkspace->AntiAliasingMode();
1002   #endif
1003
1004     if ( !myAntiAliasing )
1005     {
1006     #if !defined(GL_ES_VERSION_2_0)
1007       if (aCtx->core11 != NULL)
1008       {
1009         glDisable (GL_POINT_SMOOTH);
1010       }
1011       glDisable(GL_LINE_SMOOTH);
1012       if( anAntiAliasingMode & 2 ) glDisable(GL_POLYGON_SMOOTH);
1013     #endif
1014       glBlendFunc (GL_ONE, GL_ZERO);
1015       glDisable (GL_BLEND);
1016     }
1017     else
1018     {
1019     #if !defined(GL_ES_VERSION_2_0)
1020       if (aCtx->core11 != NULL)
1021       {
1022         glEnable(GL_POINT_SMOOTH);
1023       }
1024       glEnable(GL_LINE_SMOOTH);
1025       if( anAntiAliasingMode & 2 ) glEnable(GL_POLYGON_SMOOTH);
1026     #endif
1027       glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1028       glEnable (GL_BLEND);
1029     }
1030   }
1031
1032   Standard_Boolean toRenderGL = theToDrawImmediate ||
1033     myRenderParams.Method != Graphic3d_RM_RAYTRACING ||
1034     myRaytraceInitStatus == OpenGl_RT_FAIL ||
1035     aCtx->IsFeedback();
1036
1037   if (!toRenderGL)
1038   {
1039     toRenderGL = !initRaytraceResources (aCtx) ||
1040       !updateRaytraceGeometry (OpenGl_GUM_CHECK, myId, aCtx);
1041
1042     toRenderGL |= !myIsRaytraceDataValid; // if no ray-trace data use OpenGL
1043
1044     if (!toRenderGL)
1045     {
1046       const Standard_Integer aSizeX = theReadDrawFbo != NULL ? theReadDrawFbo->GetVPSizeX() : myWindow->Width();
1047       const Standard_Integer aSizeY = theReadDrawFbo != NULL ? theReadDrawFbo->GetVPSizeY() : myWindow->Height();
1048
1049       if (myOpenGlFBO.IsNull())
1050         myOpenGlFBO = new OpenGl_FrameBuffer;
1051
1052       if (myOpenGlFBO->GetVPSizeX() != aSizeX
1053        || myOpenGlFBO->GetVPSizeY() != aSizeY)
1054       {
1055         myOpenGlFBO->Init (aCtx, aSizeX, aSizeY);
1056       }
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   {
1482     theReadFbo->BindReadBuffer (aCtx);
1483     if (theDrawFbo != NULL
1484      && theDrawFbo->IsValid())
1485     {
1486       theDrawFbo->BindDrawBuffer (aCtx);
1487     }
1488     else
1489     {
1490       aCtx->arbFBO->glBindFramebuffer (GL_DRAW_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
1491     }
1492     // we don't copy stencil buffer here... does it matter for performance?
1493     aCtx->arbFBOBlit->glBlitFramebuffer (0, 0, theReadFbo->GetVPSizeX(), theReadFbo->GetVPSizeY(),
1494                                          0, 0, theReadFbo->GetVPSizeX(), theReadFbo->GetVPSizeY(),
1495                                          GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST);
1496
1497     if (theDrawFbo != NULL
1498       && theDrawFbo->IsValid())
1499     {
1500       theDrawFbo->BindBuffer (aCtx);
1501     }
1502     else
1503     {
1504       aCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
1505     }
1506   }
1507   else
1508 #endif*/
1509   {
1510     aCtx->core20fwd->glDepthFunc (GL_ALWAYS);
1511     aCtx->core20fwd->glDepthMask (GL_TRUE);
1512     aCtx->core20fwd->glEnable (GL_DEPTH_TEST);
1513
1514     myWorkspace->DisableTexture();
1515
1516     OpenGl_VertexBuffer* aVerts = initBlitQuad (theToFlip);
1517     const Handle(OpenGl_ShaderManager)& aManager = aCtx->ShaderManager();
1518     if (aVerts->IsValid()
1519      && aManager->BindFboBlitProgram())
1520     {
1521       theReadFbo->ColorTexture()       ->Bind   (aCtx, GL_TEXTURE0 + 0);
1522       theReadFbo->DepthStencilTexture()->Bind   (aCtx, GL_TEXTURE0 + 1);
1523       aVerts->BindVertexAttrib (aCtx, Graphic3d_TOA_POS);
1524
1525       aCtx->core20fwd->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
1526
1527       aVerts->UnbindVertexAttrib (aCtx, Graphic3d_TOA_POS);
1528       theReadFbo->DepthStencilTexture()->Unbind (aCtx, GL_TEXTURE0 + 1);
1529       theReadFbo->ColorTexture()       ->Unbind (aCtx, GL_TEXTURE0 + 0);
1530       aCtx->BindProgram (NULL);
1531     }
1532     else
1533     {
1534       TCollection_ExtendedString aMsg = TCollection_ExtendedString()
1535         + "Error! FBO blitting has failed";
1536       aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
1537                          GL_DEBUG_TYPE_ERROR_ARB,
1538                          0,
1539                          GL_DEBUG_SEVERITY_HIGH_ARB,
1540                          aMsg);
1541       myHasFboBlit = Standard_False;
1542       theReadFbo->Release (aCtx.operator->());
1543       return true;
1544     }
1545   }
1546   return true;
1547 }
1548
1549 // =======================================================================
1550 // function : drawStereoPair
1551 // purpose  :
1552 // =======================================================================
1553 void OpenGl_View::drawStereoPair()
1554 {
1555   OpenGl_FrameBuffer* aPair[2] =
1556   {
1557     myImmediateSceneFbos[0]->IsValid() ? myImmediateSceneFbos[0].operator->() : NULL,
1558     myImmediateSceneFbos[1]->IsValid() ? myImmediateSceneFbos[1].operator->() : NULL
1559   };
1560   if (aPair[0] == NULL
1561   ||  aPair[1] == NULL
1562   || !myTransientDrawToFront)
1563   {
1564     aPair[0] = myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL;
1565     aPair[1] = myMainSceneFbos[1]->IsValid() ? myMainSceneFbos[1].operator->() : NULL;
1566   }
1567
1568   if (aPair[0] == NULL
1569    || aPair[1] == NULL)
1570   {
1571     return;
1572   }
1573
1574   struct
1575   {
1576     Standard_Integer left;
1577     Standard_Integer top;
1578     Standard_Integer right;
1579     Standard_Integer bottom;
1580     Standard_Integer dx() { return right  - left; }
1581     Standard_Integer dy() { return bottom - top; }
1582   } aGeom;
1583
1584   myWindow->PlatformWindow()->Position (aGeom.left, aGeom.top, aGeom.right, aGeom.bottom);
1585
1586   Standard_Boolean toReverse = myRenderParams.ToReverseStereo;
1587   const Standard_Boolean isOddY = (aGeom.top + aGeom.dy()) % 2 == 1;
1588   const Standard_Boolean isOddX =  aGeom.left % 2 == 1;
1589   if (isOddY
1590    && (myRenderParams.StereoMode == Graphic3d_StereoMode_RowInterlaced
1591     || myRenderParams.StereoMode == Graphic3d_StereoMode_ChessBoard))
1592   {
1593     toReverse = !toReverse;
1594   }
1595   if (isOddX
1596    && (myRenderParams.StereoMode == Graphic3d_StereoMode_ColumnInterlaced
1597     || myRenderParams.StereoMode == Graphic3d_StereoMode_ChessBoard))
1598   {
1599     toReverse = !toReverse;
1600   }
1601
1602   if (toReverse)
1603   {
1604     std::swap (aPair[0], aPair[1]);
1605   }
1606
1607   Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext();
1608   aCtx->core20fwd->glDepthFunc (GL_ALWAYS);
1609   aCtx->core20fwd->glDepthMask (GL_TRUE);
1610   aCtx->core20fwd->glEnable (GL_DEPTH_TEST);
1611
1612   myWorkspace->DisableTexture();
1613   OpenGl_VertexBuffer* aVerts = initBlitQuad (myToFlipOutput);
1614
1615   const Handle(OpenGl_ShaderManager)& aManager = aCtx->ShaderManager();
1616   if (aVerts->IsValid()
1617    && aManager->BindStereoProgram (myRenderParams.StereoMode))
1618   {
1619     if (myRenderParams.StereoMode == Graphic3d_StereoMode_Anaglyph)
1620     {
1621       OpenGl_Mat4 aFilterL, aFilterR;
1622       aFilterL.SetDiagonal (Graphic3d_Vec4 (0.0f, 0.0f, 0.0f, 0.0f));
1623       aFilterR.SetDiagonal (Graphic3d_Vec4 (0.0f, 0.0f, 0.0f, 0.0f));
1624       switch (myRenderParams.AnaglyphFilter)
1625       {
1626         case Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple:
1627         {
1628           aFilterL.SetRow (0, Graphic3d_Vec4 (1.0f, 0.0f, 0.0f, 0.0f));
1629           aFilterR.SetRow (1, Graphic3d_Vec4 (0.0f, 1.0f, 0.0f, 0.0f));
1630           aFilterR.SetRow (2, Graphic3d_Vec4 (0.0f, 0.0f, 1.0f, 0.0f));
1631           break;
1632         }
1633         case Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized:
1634         {
1635           aFilterL.SetRow (0, Graphic3d_Vec4 ( 0.4154f,      0.4710f,      0.16666667f, 0.0f));
1636           aFilterL.SetRow (1, Graphic3d_Vec4 (-0.0458f,     -0.0484f,     -0.0257f,     0.0f));
1637           aFilterL.SetRow (2, Graphic3d_Vec4 (-0.0547f,     -0.0615f,      0.0128f,     0.0f));
1638           aFilterL.SetRow (3, Graphic3d_Vec4 ( 0.0f,         0.0f,         0.0f,        0.0f));
1639           aFilterR.SetRow (0, Graphic3d_Vec4 (-0.01090909f, -0.03636364f, -0.00606061f, 0.0f));
1640           aFilterR.SetRow (1, Graphic3d_Vec4 ( 0.37560000f,  0.73333333f,  0.01111111f, 0.0f));
1641           aFilterR.SetRow (2, Graphic3d_Vec4 (-0.06510000f, -0.12870000f,  1.29710000f, 0.0f));
1642           aFilterR.SetRow (3, Graphic3d_Vec4 ( 0.0f,                0.0f,  0.0f,        0.0f));
1643           break;
1644         }
1645         case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple:
1646         {
1647           aFilterL.SetRow (0, Graphic3d_Vec4 (1.0f, 0.0f, 0.0f, 0.0f));
1648           aFilterL.SetRow (1, Graphic3d_Vec4 (0.0f, 1.0f, 0.0f, 0.0f));
1649           aFilterR.SetRow (2, Graphic3d_Vec4 (0.0f, 0.0f, 1.0f, 0.0f));
1650           break;
1651         }
1652         case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized:
1653         {
1654           aFilterL.SetRow (0, Graphic3d_Vec4 ( 1.062f, -0.205f,  0.299f, 0.0f));
1655           aFilterL.SetRow (1, Graphic3d_Vec4 (-0.026f,  0.908f,  0.068f, 0.0f));
1656           aFilterL.SetRow (2, Graphic3d_Vec4 (-0.038f, -0.173f,  0.022f, 0.0f));
1657           aFilterL.SetRow (3, Graphic3d_Vec4 ( 0.0f,    0.0f,    0.0f,   0.0f));
1658           aFilterR.SetRow (0, Graphic3d_Vec4 (-0.016f, -0.123f, -0.017f, 0.0f));
1659           aFilterR.SetRow (1, Graphic3d_Vec4 ( 0.006f,  0.062f, -0.017f, 0.0f));
1660           aFilterR.SetRow (2, Graphic3d_Vec4 ( 0.094f,  0.185f,  0.911f, 0.0f));
1661           aFilterR.SetRow (3, Graphic3d_Vec4 ( 0.0f,    0.0f,    0.0f,   0.0f));
1662           break;
1663         }
1664         case Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple:
1665         {
1666           aFilterR.SetRow (0, Graphic3d_Vec4 (1.0f, 0.0f, 0.0f, 0.0f));
1667           aFilterL.SetRow (1, Graphic3d_Vec4 (0.0f, 1.0f, 0.0f, 0.0f));
1668           aFilterR.SetRow (2, Graphic3d_Vec4 (0.0f, 0.0f, 1.0f, 0.0f));
1669           break;
1670         }
1671         case Graphic3d_RenderingParams::Anaglyph_UserDefined:
1672         {
1673           aFilterL = myRenderParams.AnaglyphLeft;
1674           aFilterR = myRenderParams.AnaglyphRight;
1675           break;
1676         }
1677       }
1678       aCtx->ActiveProgram()->SetUniform (aCtx, "uMultL", aFilterL);
1679       aCtx->ActiveProgram()->SetUniform (aCtx, "uMultR", aFilterR);
1680     }
1681
1682     aPair[0]->ColorTexture()->Bind (aCtx, GL_TEXTURE0 + 0);
1683     aPair[1]->ColorTexture()->Bind (aCtx, GL_TEXTURE0 + 1);
1684     aVerts->BindVertexAttrib (aCtx, 0);
1685
1686     aCtx->core20fwd->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
1687
1688     aVerts->UnbindVertexAttrib (aCtx, 0);
1689     aPair[1]->ColorTexture()->Unbind (aCtx, GL_TEXTURE0 + 1);
1690     aPair[0]->ColorTexture()->Unbind (aCtx, GL_TEXTURE0 + 0);
1691   }
1692   else
1693   {
1694     TCollection_ExtendedString aMsg = TCollection_ExtendedString()
1695       + "Error! Anaglyph has failed";
1696     aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
1697                        GL_DEBUG_TYPE_ERROR_ARB,
1698                        0,
1699                        GL_DEBUG_SEVERITY_HIGH_ARB,
1700                        aMsg);
1701   }
1702 }
1703
1704 // =======================================================================
1705 // function : copyBackToFront
1706 // purpose  :
1707 // =======================================================================
1708 void OpenGl_View::copyBackToFront()
1709 {
1710 #if !defined(GL_ES_VERSION_2_0)
1711
1712   OpenGl_Mat4 aProjectMat;
1713   Graphic3d_TransformUtils::Ortho2D (aProjectMat,
1714     0.f, static_cast<GLfloat> (myWindow->Width()), 0.f, static_cast<GLfloat> (myWindow->Height()));
1715
1716   Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext();
1717   aCtx->WorldViewState.Push();
1718   aCtx->ProjectionState.Push();
1719
1720   aCtx->WorldViewState.SetIdentity();
1721   aCtx->ProjectionState.SetCurrent (aProjectMat);
1722
1723   aCtx->ApplyProjectionMatrix();
1724   aCtx->ApplyWorldViewMatrix();
1725
1726   aCtx->DisableFeatures();
1727
1728   switch (aCtx->DrawBuffer())
1729   {
1730     case GL_BACK_LEFT:
1731     {
1732       aCtx->SetReadBuffer (GL_BACK_LEFT);
1733       aCtx->SetDrawBuffer (GL_FRONT_LEFT);
1734       break;
1735     }
1736     case GL_BACK_RIGHT:
1737     {
1738       aCtx->SetReadBuffer (GL_BACK_RIGHT);
1739       aCtx->SetDrawBuffer (GL_FRONT_RIGHT);
1740       break;
1741     }
1742     default:
1743     {
1744       aCtx->SetReadBuffer (GL_BACK);
1745       aCtx->SetDrawBuffer (GL_FRONT);
1746       break;
1747     }
1748   }
1749
1750   glRasterPos2i (0, 0);
1751   glCopyPixels  (0, 0, myWindow->Width() + 1, myWindow->Height() + 1, GL_COLOR);
1752   //glCopyPixels  (0, 0, myWidth + 1, myHeight + 1, GL_DEPTH);
1753
1754   aCtx->EnableFeatures();
1755
1756   aCtx->WorldViewState.Pop();
1757   aCtx->ProjectionState.Pop();
1758   aCtx->ApplyProjectionMatrix();
1759
1760   // read/write from front buffer now
1761   aCtx->SetReadBuffer (aCtx->DrawBuffer());
1762 #endif
1763   myIsImmediateDrawn = Standard_False;
1764 }