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