0025556: Visualization - support stereo pair formats recognized by consumer display...
[occt.git] / src / OpenGl / OpenGl_Workspace.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 <OpenGl_GlCore15.hxx>
17 #include <OpenGl_ArbFBO.hxx>
18
19 #include <InterfaceGraphic.hxx>
20
21 #include <OpenGl_AspectLine.hxx>
22 #include <OpenGl_AspectFace.hxx>
23 #include <OpenGl_AspectMarker.hxx>
24 #include <OpenGl_AspectText.hxx>
25 #include <OpenGl_Context.hxx>
26 #include <OpenGl_Element.hxx>
27 #include <OpenGl_FrameBuffer.hxx>
28 #include <OpenGl_Structure.hxx>
29 #include <OpenGl_Sampler.hxx>
30 #include <OpenGl_ShaderManager.hxx>
31 #include <OpenGl_Texture.hxx>
32 #include <OpenGl_Utils.hxx>
33 #include <OpenGl_View.hxx>
34 #include <OpenGl_Workspace.hxx>
35
36 #include <Graphic3d_TextureParams.hxx>
37
38 #if defined(_WIN32) && defined(HAVE_VIDEOCAPTURE)
39   #include <OpenGl_AVIWriter.hxx>
40 #endif
41
42 IMPLEMENT_STANDARD_HANDLE(OpenGl_Workspace,OpenGl_Window)
43 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Workspace,OpenGl_Window)
44
45 namespace
46 {
47   static const TEL_COLOUR  THE_WHITE_COLOR = { { 1.0f, 1.0f, 1.0f, 1.0f } };
48   static const OpenGl_Vec4 THE_BLACK_COLOR      (0.0f, 0.0f, 0.0f, 1.0f);
49
50   static const OpenGl_AspectLine myDefaultAspectLine;
51   static const OpenGl_AspectFace myDefaultAspectFace;
52   static const OpenGl_AspectMarker myDefaultAspectMarker;
53   static const OpenGl_AspectText myDefaultAspectText;
54
55   static const OpenGl_TextParam myDefaultTextParam =
56   {
57     16, Graphic3d_HTA_LEFT, Graphic3d_VTA_BOTTOM
58   };
59
60   static const OpenGl_Matrix myDefaultMatrix =
61   {
62     {{ 1.0F, 0.0F, 0.0F, 0.0F },
63      { 0.0F, 1.0F, 0.0F, 0.0F },
64      { 0.0F, 0.0F, 1.0F, 0.0F },
65      { 0.0F, 0.0F, 0.0F, 1.0F }}
66   };
67
68 };
69
70 // =======================================================================
71 // function : Init
72 // purpose  :
73 // =======================================================================
74 void OpenGl_Material::Init (const OPENGL_SURF_PROP& theProp)
75 {
76   // ambient component
77   if (theProp.color_mask & OPENGL_AMBIENT_MASK)
78   {
79     const float* aSrcAmb = theProp.isphysic ? theProp.ambcol.rgb : theProp.matcol.rgb;
80     Ambient = OpenGl_Vec4 (aSrcAmb[0] * theProp.amb,
81                            aSrcAmb[1] * theProp.amb,
82                            aSrcAmb[2] * theProp.amb,
83                            1.0f);
84   }
85   else
86   {
87     Ambient = THE_BLACK_COLOR;
88   }
89
90   // diffusion component
91   if (theProp.color_mask & OPENGL_DIFFUSE_MASK)
92   {
93     const float* aSrcDif = theProp.isphysic ? theProp.difcol.rgb : theProp.matcol.rgb;
94     Diffuse = OpenGl_Vec4 (aSrcDif[0] * theProp.diff,
95                            aSrcDif[1] * theProp.diff,
96                            aSrcDif[2] * theProp.diff,
97                            1.0f);
98   }
99   else
100   {
101     Diffuse = THE_BLACK_COLOR;
102   }
103
104   // specular component
105   if (theProp.color_mask & OPENGL_SPECULAR_MASK)
106   {
107     const float* aSrcSpe = theProp.isphysic ? theProp.speccol.rgb : THE_WHITE_COLOR.rgb;
108     Specular = OpenGl_Vec4 (aSrcSpe[0] * theProp.spec,
109                             aSrcSpe[1] * theProp.spec,
110                             aSrcSpe[2] * theProp.spec,
111                             1.0f);
112   }
113   else
114   {
115     Specular = THE_BLACK_COLOR;
116   }
117
118   // emission component
119   if (theProp.color_mask & OPENGL_EMISSIVE_MASK)
120   {
121     const float* aSrcEms = theProp.isphysic ? theProp.emscol.rgb : theProp.matcol.rgb;
122     Emission = OpenGl_Vec4 (aSrcEms[0] * theProp.emsv,
123                             aSrcEms[1] * theProp.emsv,
124                             aSrcEms[2] * theProp.emsv,
125                             1.0f);
126   }
127   else
128   {
129     Emission = THE_BLACK_COLOR;
130   }
131
132   ChangeShine()        = theProp.shine;
133   ChangeTransparency() = theProp.trans;
134 }
135
136 // =======================================================================
137 // function : OpenGl_Workspace
138 // purpose  :
139 // =======================================================================
140 OpenGl_Workspace::OpenGl_Workspace (const Handle(OpenGl_GraphicDriver)& theDriver,
141                                     const CALL_DEF_WINDOW&        theCWindow,
142                                     Aspect_RenderingContext       theGContext,
143                                     const Handle(OpenGl_Caps)&    theCaps,
144                                     const Handle(OpenGl_Context)& theShareCtx)
145 : OpenGl_Window (theDriver, theCWindow, theGContext, theCaps, theShareCtx),
146   NamedStatus (0),
147   HighlightColor (&THE_WHITE_COLOR),
148   //
149   myHasFboBlit (Standard_True),
150   //
151   myViewId               (-1),
152   myAntiAliasingMode     (3),
153   myTransientDrawToFront (Standard_True),
154   myBackBufferRestored   (Standard_False),
155   myIsImmediateDrawn     (Standard_False),
156   myUseZBuffer    (Standard_True),
157   myUseDepthWrite (Standard_True),
158   myUseGLLight (Standard_True),
159   myIsCullingEnabled (Standard_False),
160   myFrameCounter (0),
161   //
162   AspectLine_set (&myDefaultAspectLine),
163   AspectLine_applied (NULL),
164   AspectFace_set (&myDefaultAspectFace),
165   AspectFace_applied (NULL),
166   AspectMarker_set (&myDefaultAspectMarker),
167   AspectMarker_applied (NULL),
168   AspectText_set (&myDefaultAspectText),
169   AspectText_applied (NULL),
170   TextParam_set (&myDefaultTextParam),
171   TextParam_applied (NULL),
172   ViewMatrix_applied (&myDefaultMatrix),
173   StructureMatrix_applied (&myDefaultMatrix),
174   myCullingMode (TelCullUndefined),
175   myModelViewMatrix (myDefaultMatrix),
176   PolygonOffset_applied (THE_DEFAULT_POFFSET)
177 {
178   myGlContext->core11fwd->glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
179   myMainSceneFbos[0]      = new OpenGl_FrameBuffer();
180   myMainSceneFbos[1]      = new OpenGl_FrameBuffer();
181   myImmediateSceneFbos[0] = new OpenGl_FrameBuffer();
182   myImmediateSceneFbos[1] = new OpenGl_FrameBuffer();
183
184   if (!myGlContext->GetResource ("OpenGl_LineAttributes", myLineAttribs))
185   {
186     // share and register for release once the resource is no longer used
187     myLineAttribs = new OpenGl_LineAttributes();
188     myGlContext->ShareResource ("OpenGl_LineAttributes", myLineAttribs);
189     myLineAttribs->Init (myGlContext);
190   }
191
192   // General initialization of the context
193
194 #if !defined(GL_ES_VERSION_2_0)
195   if (myGlContext->core11 != NULL)
196   {
197     // Eviter d'avoir les faces mal orientees en noir.
198     // Pourrait etre utiliser pour detecter les problemes d'orientation
199     glLightModeli ((GLenum )GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
200
201     // Optimisation pour le Fog et l'antialiasing
202     glHint (GL_FOG_HINT,            GL_FASTEST);
203     glHint (GL_POINT_SMOOTH_HINT,   GL_FASTEST);
204   }
205
206   glHint (GL_LINE_SMOOTH_HINT,    GL_FASTEST);
207   glHint (GL_POLYGON_SMOOTH_HINT, GL_FASTEST);
208 #endif
209
210   // AA mode
211   const char* anAaEnv = ::getenv ("CALL_OPENGL_ANTIALIASING_MODE");
212   if (anAaEnv != NULL)
213   {
214     int v;
215     if (sscanf (anAaEnv, "%d", &v) > 0) myAntiAliasingMode = v;
216   }
217 }
218
219 // =======================================================================
220 // function : SetImmediateModeDrawToFront
221 // purpose  :
222 // =======================================================================
223 Standard_Boolean OpenGl_Workspace::SetImmediateModeDrawToFront (const Standard_Boolean theDrawToFrontBuffer)
224 {
225   const Standard_Boolean aPrevMode = myTransientDrawToFront;
226   myTransientDrawToFront = theDrawToFrontBuffer;
227   return aPrevMode;
228 }
229
230 inline void nullifyGlResource (Handle(OpenGl_Resource)&      theResource,
231                                const Handle(OpenGl_Context)& theCtx)
232 {
233   if (!theResource.IsNull())
234   {
235     theResource->Release (theCtx.operator->());
236     theResource.Nullify();
237   }
238 }
239
240 // =======================================================================
241 // function : ~OpenGl_Workspace
242 // purpose  :
243 // =======================================================================
244 OpenGl_Workspace::~OpenGl_Workspace()
245 {
246   if (!myLineAttribs.IsNull())
247   {
248     myLineAttribs.Nullify();
249     myGlContext->ReleaseResource ("OpenGl_LineAttributes", Standard_True);
250   }
251
252   nullifyGlResource (myMainSceneFbos[0],      myGlContext);
253   nullifyGlResource (myMainSceneFbos[1],      myGlContext);
254   nullifyGlResource (myImmediateSceneFbos[0], myGlContext);
255   nullifyGlResource (myImmediateSceneFbos[1], myGlContext);
256
257   myFullScreenQuad.Release (myGlContext.operator->());
258 }
259
260 // =======================================================================
261 // function : Activate
262 // purpose  :
263 // =======================================================================
264 Standard_Boolean OpenGl_Workspace::Activate()
265 {
266   if (!OpenGl_Window::Activate())
267     return Standard_False;
268
269   ViewMatrix_applied      = &myDefaultMatrix;
270   StructureMatrix_applied = &myDefaultMatrix;
271
272   ResetAppliedAspect();
273
274   return Standard_True;
275 }
276
277 //=======================================================================
278 //function : ResetAppliedAspect
279 //purpose  : Sets default values of GL parameters in accordance with default aspects
280 //=======================================================================
281 void OpenGl_Workspace::ResetAppliedAspect()
282 {
283   myGlContext->BindDefaultVao();
284
285   NamedStatus           = !myTextureBound.IsNull() ? OPENGL_NS_TEXTURE : 0;
286   HighlightColor        = &THE_WHITE_COLOR;
287   AspectLine_set        = &myDefaultAspectLine;
288   AspectLine_applied    = NULL;
289   AspectFace_set        = &myDefaultAspectFace;
290   AspectFace_applied    = NULL;
291   AspectMarker_set      = &myDefaultAspectMarker;
292   AspectMarker_applied  = NULL;
293   AspectText_set        = &myDefaultAspectText;
294   AspectText_applied    = NULL;
295   TextParam_set         = &myDefaultTextParam;
296   TextParam_applied     = NULL;
297   PolygonOffset_applied = THE_DEFAULT_POFFSET;
298   myCullingMode         = TelCullUndefined;
299
300   AspectLine(Standard_True);
301   AspectFace(Standard_True);
302   AspectMarker(Standard_True);
303   AspectText(Standard_True);
304
305   myGlContext->SetTypeOfLine (myDefaultAspectLine.Type());
306   myGlContext->SetLineWidth  (myDefaultAspectLine.Width());
307 }
308
309 // =======================================================================
310 // function : DisableTexture
311 // purpose  :
312 // =======================================================================
313 Handle(OpenGl_Texture) OpenGl_Workspace::DisableTexture()
314 {
315   if (myTextureBound.IsNull())
316   {
317     return myTextureBound;
318   }
319
320   const Handle(OpenGl_Sampler)& aSampler = myGlContext->TextureSampler();
321   if (!aSampler.IsNull())
322   {
323     aSampler->Unbind (*myGlContext);
324   }
325
326 #if !defined(GL_ES_VERSION_2_0)
327   // reset texture matrix because some code may expect it is identity
328   if (myGlContext->core11 != NULL)
329   {
330     GLint aMatrixMode = GL_TEXTURE;
331     glGetIntegerv (GL_MATRIX_MODE, &aMatrixMode);
332     glMatrixMode (GL_TEXTURE);
333     glLoadIdentity();
334     glMatrixMode (aMatrixMode);
335   }
336 #endif
337
338   myTextureBound->Unbind (myGlContext);
339   switch (myTextureBound->GetTarget())
340   {
341   #if !defined(GL_ES_VERSION_2_0)
342     case GL_TEXTURE_1D:
343     {
344       if (myGlContext->core11 != NULL)
345       {
346         if (myTextureBound->GetParams()->GenMode() != GL_NONE)
347         {
348           glDisable (GL_TEXTURE_GEN_S);
349         }
350         glDisable (GL_TEXTURE_1D);
351       }
352       break;
353     }
354   #endif
355     case GL_TEXTURE_2D:
356     {
357     #if !defined(GL_ES_VERSION_2_0)
358       if (myGlContext->core11 != NULL)
359       {
360         if (myTextureBound->GetParams()->GenMode() != GL_NONE)
361         {
362           glDisable (GL_TEXTURE_GEN_S);
363           glDisable (GL_TEXTURE_GEN_T);
364           if (myTextureBound->GetParams()->GenMode() == Graphic3d_TOTM_SPRITE)
365           {
366             glDisable (GL_POINT_SPRITE);
367           }
368         }
369         glDisable (GL_TEXTURE_2D);
370       }
371     #endif
372       break;
373     }
374     default: break;
375   }
376
377   Handle(OpenGl_Texture) aPrevTexture = myTextureBound;
378   myTextureBound.Nullify();
379   return aPrevTexture;
380 }
381
382 // =======================================================================
383 // function : setTextureParams
384 // purpose  :
385 // =======================================================================
386 void OpenGl_Workspace::setTextureParams (Handle(OpenGl_Texture)&                theTexture,
387                                          const Handle(Graphic3d_TextureParams)& theParams)
388 {
389   const Handle(Graphic3d_TextureParams)& aParams = theParams.IsNull() ? theTexture->GetParams() : theParams;
390   if (aParams.IsNull())
391   {
392     return;
393   }
394
395 #if !defined(GL_ES_VERSION_2_0)
396   GLint aMatrixMode = GL_TEXTURE;
397   if (myGlContext->core11 != NULL)
398   {
399     glGetIntegerv (GL_MATRIX_MODE, &aMatrixMode);
400
401     // setup texture matrix
402     glMatrixMode (GL_TEXTURE);
403     OpenGl_Mat4 aTextureMat;
404     const Graphic3d_Vec2& aScale = aParams->Scale();
405     const Graphic3d_Vec2& aTrans = aParams->Translation();
406     OpenGl_Utils::Scale     (aTextureMat,  aScale.x(),  aScale.y(), 1.0f);
407     OpenGl_Utils::Translate (aTextureMat, -aTrans.x(), -aTrans.y(), 0.0f);
408     OpenGl_Utils::Rotate    (aTextureMat, -aParams->Rotation(), 0.0f, 0.0f, 1.0f);
409     glLoadMatrixf (aTextureMat);
410
411     GLint anEnvMode = GL_MODULATE; // lighting mode
412     if (!aParams->IsModulate())
413     {
414       anEnvMode = GL_DECAL;
415       if (theTexture->GetFormat() == GL_ALPHA
416        || theTexture->GetFormat() == GL_LUMINANCE)
417       {
418         anEnvMode = GL_REPLACE;
419       }
420     }
421
422     // setup generation of texture coordinates
423     switch (aParams->GenMode())
424     {
425       case Graphic3d_TOTM_OBJECT:
426       {
427         glTexGeni  (GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
428         glTexGenfv (GL_S, GL_OBJECT_PLANE,     aParams->GenPlaneS().GetData());
429         if (theTexture->GetTarget() != GL_TEXTURE_1D)
430         {
431           glTexGeni  (GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
432           glTexGenfv (GL_T, GL_OBJECT_PLANE,     aParams->GenPlaneT().GetData());
433         }
434         break;
435       }
436       case Graphic3d_TOTM_SPHERE:
437       {
438         glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
439         if (theTexture->GetTarget() != GL_TEXTURE_1D)
440         {
441           glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
442         }
443         break;
444       }
445       case Graphic3d_TOTM_EYE:
446       {
447         myGlContext->WorldViewState.Push();
448
449         myGlContext->WorldViewState.SetIdentity();
450         myGlContext->ApplyWorldViewMatrix();
451
452         glTexGeni  (GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
453         glTexGenfv (GL_S, GL_EYE_PLANE,        aParams->GenPlaneS().GetData());
454
455         if (theTexture->GetTarget() != GL_TEXTURE_1D)
456         {
457           glTexGeni  (GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
458           glTexGenfv (GL_T, GL_EYE_PLANE,        aParams->GenPlaneT().GetData());
459         }
460
461         myGlContext->WorldViewState.Pop();
462
463         break;
464       }
465       case Graphic3d_TOTM_SPRITE:
466       {
467         if (GetGlContext()->core20fwd != NULL)
468         {
469           glEnable  (GL_POINT_SPRITE);
470           glTexEnvi (GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE);
471           anEnvMode = GL_REPLACE;
472           GetGlContext()->core15->glPointParameteri (GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT);
473         }
474         break;
475       }
476       case Graphic3d_TOTM_MANUAL:
477       default: break;
478     }
479
480     // setup lighting
481     glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, anEnvMode);
482   }
483 #endif
484
485   // get active sampler object to override default texture parameters
486   const Handle(OpenGl_Sampler)& aSampler = myGlContext->TextureSampler();
487
488   // setup texture filtering and wrapping
489   //if (theTexture->GetParams() != theParams)
490   const GLenum aFilter   = (aParams->Filter() == Graphic3d_TOTF_NEAREST) ? GL_NEAREST : GL_LINEAR;
491   const GLenum aWrapMode = aParams->IsRepeat() ? GL_REPEAT : myGlContext->TextureWrapClamp();
492   switch (theTexture->GetTarget())
493   {
494   #if !defined(GL_ES_VERSION_2_0)
495     case GL_TEXTURE_1D:
496     {
497       if (aSampler.IsNull() || !aSampler->IsValid())
498       {
499         glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, aFilter);
500         glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, aFilter);
501         glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_S,     aWrapMode);
502       }
503       else
504       {
505         aSampler->SetParameter (*myGlContext, GL_TEXTURE_MAG_FILTER, aFilter);
506         aSampler->SetParameter (*myGlContext, GL_TEXTURE_MIN_FILTER, aFilter);
507         aSampler->SetParameter (*myGlContext, GL_TEXTURE_WRAP_S,     aWrapMode);
508       }
509
510       break;
511     }
512   #endif
513     case GL_TEXTURE_2D:
514     {
515       GLenum aFilterMin = aFilter;
516       if (theTexture->HasMipmaps())
517       {
518         aFilterMin = GL_NEAREST_MIPMAP_NEAREST;
519         if (aParams->Filter() == Graphic3d_TOTF_BILINEAR)
520         {
521           aFilterMin = GL_LINEAR_MIPMAP_NEAREST;
522         }
523         else if (aParams->Filter() == Graphic3d_TOTF_TRILINEAR)
524         {
525           aFilterMin = GL_LINEAR_MIPMAP_LINEAR;
526         }
527
528         if (myGlContext->extAnis)
529         {
530           // setup degree of anisotropy filter
531           const GLint aMaxDegree = myGlContext->MaxDegreeOfAnisotropy();
532           GLint aDegree;
533           switch (aParams->AnisoFilter())
534           {
535             case Graphic3d_LOTA_QUALITY:
536             {
537               aDegree = aMaxDegree;
538               break;
539             }
540             case Graphic3d_LOTA_MIDDLE:
541             {
542               aDegree = (aMaxDegree <= 4) ? 2 : (aMaxDegree / 2);
543               break;
544             }
545             case Graphic3d_LOTA_FAST:
546             {
547               aDegree = 2;
548               break;
549             }
550             case Graphic3d_LOTA_OFF:
551             default:
552             {
553               aDegree = 1;
554               break;
555             }
556           }
557
558           if (aSampler.IsNull() || !aSampler->IsValid())
559           {
560             glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, aDegree);
561           }
562           else
563           {
564             aSampler->SetParameter (*myGlContext, GL_TEXTURE_MAX_ANISOTROPY_EXT, aDegree);
565           }
566         }
567       }
568
569       if (aSampler.IsNull() || !aSampler->IsValid())
570       {
571         glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, aFilterMin);
572         glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, aFilter);
573         glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,     aWrapMode);
574         glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,     aWrapMode);
575       }
576       else
577       {
578         aSampler->SetParameter (*myGlContext, GL_TEXTURE_MIN_FILTER, aFilterMin);
579         aSampler->SetParameter (*myGlContext, GL_TEXTURE_MAG_FILTER, aFilter);
580         aSampler->SetParameter (*myGlContext, GL_TEXTURE_WRAP_S,     aWrapMode);
581         aSampler->SetParameter (*myGlContext, GL_TEXTURE_WRAP_T,     aWrapMode);
582       }
583
584       break;
585     }
586     default: break;
587   }
588
589   switch (theTexture->GetTarget())
590   {
591   #if !defined(GL_ES_VERSION_2_0)
592     case GL_TEXTURE_1D:
593     {
594       if (myGlContext->core11 != NULL)
595       {
596         if (aParams->GenMode() != Graphic3d_TOTM_MANUAL)
597         {
598           glEnable (GL_TEXTURE_GEN_S);
599         }
600         glEnable (GL_TEXTURE_1D);
601       }
602       break;
603     }
604   #endif
605     case GL_TEXTURE_2D:
606     {
607     #if !defined(GL_ES_VERSION_2_0)
608       if (myGlContext->core11 != NULL)
609       {
610         if (aParams->GenMode() != Graphic3d_TOTM_MANUAL)
611         {
612           glEnable (GL_TEXTURE_GEN_S);
613           glEnable (GL_TEXTURE_GEN_T);
614         }
615         glEnable (GL_TEXTURE_2D);
616       }
617     #endif
618       break;
619     }
620     default: break;
621   }
622
623 #if !defined(GL_ES_VERSION_2_0)
624   if (myGlContext->core11 != NULL)
625   {
626     glMatrixMode (aMatrixMode); // turn back active matrix
627   }
628 #endif
629   theTexture->SetParams (aParams);
630 }
631
632 // =======================================================================
633 // function : EnableTexture
634 // purpose  :
635 // =======================================================================
636 Handle(OpenGl_Texture) OpenGl_Workspace::EnableTexture (const Handle(OpenGl_Texture)&          theTexture,
637                                                         const Handle(Graphic3d_TextureParams)& theParams)
638 {
639   if (theTexture.IsNull() || !theTexture->IsValid())
640   {
641     return DisableTexture();
642   }
643
644   if (myTextureBound == theTexture
645    && (theParams.IsNull() || theParams == theTexture->GetParams()))
646   {
647     // already bound
648     return myTextureBound;
649   }
650
651   Handle(OpenGl_Texture) aPrevTexture = DisableTexture();
652   myTextureBound = theTexture;
653   myTextureBound->Bind (myGlContext);
654   setTextureParams (myTextureBound, theParams);
655
656   // If custom sampler object is available it will be
657   // used for overriding default texture parameters
658   const Handle(OpenGl_Sampler)& aSampler = myGlContext->TextureSampler();
659
660   if (!aSampler.IsNull() && aSampler->IsValid())
661   {
662     aSampler->Bind (*myGlContext);
663   }
664
665   return aPrevTexture;
666 }
667
668 // =======================================================================
669 // function : bindDefaultFbo
670 // purpose  :
671 // =======================================================================
672 void OpenGl_Workspace::bindDefaultFbo (OpenGl_FrameBuffer* theCustomFbo)
673 {
674   OpenGl_FrameBuffer* anFbo = (theCustomFbo != NULL && theCustomFbo->IsValid())
675                             ?  theCustomFbo
676                             : (!myGlContext->DefaultFrameBuffer().IsNull()
677                              && myGlContext->DefaultFrameBuffer()->IsValid()
678                               ? myGlContext->DefaultFrameBuffer().operator->()
679                               : NULL);
680   if (anFbo != NULL)
681   {
682     anFbo->BindBuffer (myGlContext);
683   }
684   else
685   {
686   #if !defined(GL_ES_VERSION_2_0)
687     myGlContext->SetReadDrawBuffer (GL_BACK);
688   #else
689     if (myGlContext->arbFBO != NULL)
690     {
691       myGlContext->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
692     }
693   #endif
694   }
695   myGlContext->core11fwd->glViewport (0, 0, myWidth, myHeight);
696 }
697
698 // =======================================================================
699 // function : blitBuffers
700 // purpose  :
701 // =======================================================================
702 bool OpenGl_Workspace::blitBuffers (OpenGl_FrameBuffer* theReadFbo,
703                                     OpenGl_FrameBuffer* theDrawFbo)
704 {
705   if (theReadFbo == NULL)
706   {
707     return false;
708   }
709   else if (theReadFbo == theDrawFbo)
710   {
711     return true;
712   }
713
714   // clear destination before blitting
715   if (theDrawFbo != NULL
716   &&  theDrawFbo->IsValid())
717   {
718     theDrawFbo->BindBuffer (myGlContext);
719   }
720   else
721   {
722     myGlContext->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
723   }
724 #if !defined(GL_ES_VERSION_2_0)
725   myGlContext->core20fwd->glClearDepth  (1.0);
726 #else
727   myGlContext->core20fwd->glClearDepthf (1.0f);
728 #endif
729   myGlContext->core20fwd->glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
730
731 /*#if !defined(GL_ES_VERSION_2_0)
732   if (myGlContext->arbFBOBlit != NULL)
733   {
734     theReadFbo->BindReadBuffer (myGlContext);
735     if (theDrawFbo != NULL
736      && theDrawFbo->IsValid())
737     {
738       theDrawFbo->BindDrawBuffer (myGlContext);
739     }
740     else
741     {
742       myGlContext->arbFBO->glBindFramebuffer (GL_DRAW_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
743     }
744     // we don't copy stencil buffer here... does it matter for performance?
745     myGlContext->arbFBOBlit->glBlitFramebuffer (0, 0, theReadFbo->GetVPSizeX(), theReadFbo->GetVPSizeY(),
746                                                 0, 0, theReadFbo->GetVPSizeX(), theReadFbo->GetVPSizeY(),
747                                                 GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST);
748
749     if (theDrawFbo != NULL
750       && theDrawFbo->IsValid())
751     {
752       theDrawFbo->BindBuffer (myGlContext);
753     }
754     else
755     {
756       myGlContext->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
757     }
758   }
759   else
760 #endif*/
761   {
762     myGlContext->core20fwd->glDepthFunc (GL_ALWAYS);
763     myGlContext->core20fwd->glDepthMask (GL_TRUE);
764     myGlContext->core20fwd->glEnable (GL_DEPTH_TEST);
765
766     DisableTexture();
767     if (!myFullScreenQuad.IsValid())
768     {
769       OpenGl_Vec4 aQuad[4] =
770       {
771         OpenGl_Vec4( 1.0f, -1.0f, 1.0f, 0.0f),
772         OpenGl_Vec4( 1.0f,  1.0f, 1.0f, 1.0f),
773         OpenGl_Vec4(-1.0f, -1.0f, 0.0f, 0.0f),
774         OpenGl_Vec4(-1.0f,  1.0f, 0.0f, 1.0f)
775       };
776       myFullScreenQuad.Init (myGlContext, 4, 4, aQuad[0].GetData());
777     }
778
779     const Handle(OpenGl_ShaderManager)& aManager = myGlContext->ShaderManager();
780     if (myFullScreenQuad.IsValid()
781      && aManager->BindFboBlitProgram())
782     {
783       theReadFbo->ColorTexture()       ->Bind   (myGlContext, GL_TEXTURE0 + 0);
784       theReadFbo->DepthStencilTexture()->Bind   (myGlContext, GL_TEXTURE0 + 1);
785       myFullScreenQuad.BindVertexAttrib (myGlContext, Graphic3d_TOA_POS);
786
787       myGlContext->core20fwd->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
788
789       myFullScreenQuad.UnbindVertexAttrib (myGlContext, Graphic3d_TOA_POS);
790       theReadFbo->DepthStencilTexture()->Unbind (myGlContext, GL_TEXTURE0 + 1);
791       theReadFbo->ColorTexture()       ->Unbind (myGlContext, GL_TEXTURE0 + 0);
792     }
793     else
794     {
795       TCollection_ExtendedString aMsg = TCollection_ExtendedString()
796         + "Error! FBO blitting has failed";
797       myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
798                                 GL_DEBUG_TYPE_ERROR_ARB,
799                                 0,
800                                 GL_DEBUG_SEVERITY_HIGH_ARB,
801                                 aMsg);
802       myHasFboBlit = Standard_False;
803       theReadFbo->Release (myGlContext.operator->());
804       return true;
805     }
806   }
807   return true;
808 }
809
810 // =======================================================================
811 // function : drawStereoPair
812 // purpose  :
813 // =======================================================================
814 void OpenGl_Workspace::drawStereoPair (const Graphic3d_CView& theCView)
815 {
816   OpenGl_FrameBuffer* aPair[2] =
817   {
818     myImmediateSceneFbos[0]->IsValid() ? myImmediateSceneFbos[0].operator->() : NULL,
819     myImmediateSceneFbos[1]->IsValid() ? myImmediateSceneFbos[1].operator->() : NULL
820   };
821   if (aPair[0] == NULL
822   ||  aPair[1] == NULL
823   || !myTransientDrawToFront)
824   {
825     aPair[0] = myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL;
826     aPair[1] = myMainSceneFbos[1]->IsValid() ? myMainSceneFbos[1].operator->() : NULL;
827   }
828
829   if (aPair[0] == NULL
830    || aPair[1] == NULL)
831   {
832     return;
833   }
834
835   Standard_Boolean toReverse = theCView.RenderParams.ToReverseStereo;
836   const Standard_Boolean isOddY = (theCView.DefWindow.top + theCView.DefWindow.dy) % 2 == 1;
837   const Standard_Boolean isOddX =  theCView.DefWindow.left % 2 == 1;
838   if (isOddY
839    && (theCView.RenderParams.StereoMode == Graphic3d_StereoMode_RowInterlaced
840     || theCView.RenderParams.StereoMode == Graphic3d_StereoMode_ChessBoard))
841   {
842     toReverse = !toReverse;
843   }
844   if (isOddX
845    && (theCView.RenderParams.StereoMode == Graphic3d_StereoMode_ColumnInterlaced
846     || theCView.RenderParams.StereoMode == Graphic3d_StereoMode_ChessBoard))
847   {
848     toReverse = !toReverse;
849   }
850
851   if (toReverse)
852   {
853     std::swap (aPair[0], aPair[1]);
854   }
855
856   myGlContext->core20fwd->glDepthFunc (GL_ALWAYS);
857   myGlContext->core20fwd->glDepthMask (GL_TRUE);
858   myGlContext->core20fwd->glEnable (GL_DEPTH_TEST);
859
860   DisableTexture();
861   if (!myFullScreenQuad.IsValid())
862   {
863     OpenGl_Vec4 aQuad[4] =
864     {
865       OpenGl_Vec4( 1.0f, -1.0f, 1.0f, 0.0f),
866       OpenGl_Vec4( 1.0f,  1.0f, 1.0f, 1.0f),
867       OpenGl_Vec4(-1.0f, -1.0f, 0.0f, 0.0f),
868       OpenGl_Vec4(-1.0f,  1.0f, 0.0f, 1.0f)
869     };
870     myFullScreenQuad.Init (myGlContext, 4, 4, aQuad[0].GetData());
871   }
872
873   const Handle(OpenGl_ShaderManager)& aManager = myGlContext->ShaderManager();
874   if (myFullScreenQuad.IsValid()
875    && aManager->BindStereoProgram (theCView.RenderParams.StereoMode))
876   {
877     if (theCView.RenderParams.StereoMode == Graphic3d_StereoMode_Anaglyph)
878     {
879       OpenGl_Mat4 aFilterL, aFilterR;
880       aFilterL.SetDiagonal (Graphic3d_Vec4 (0.0f, 0.0f, 0.0f, 0.0f));
881       aFilterR.SetDiagonal (Graphic3d_Vec4 (0.0f, 0.0f, 0.0f, 0.0f));
882       switch (theCView.RenderParams.AnaglyphFilter)
883       {
884         case Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple:
885         {
886           aFilterL.SetRow (0, Graphic3d_Vec4 (1.0f, 0.0f, 0.0f, 0.0f));
887           aFilterR.SetRow (1, Graphic3d_Vec4 (0.0f, 1.0f, 0.0f, 0.0f));
888           aFilterR.SetRow (2, Graphic3d_Vec4 (0.0f, 0.0f, 1.0f, 0.0f));
889           break;
890         }
891         case Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized:
892         {
893           aFilterL.SetRow (0, Graphic3d_Vec4 ( 0.4154f,      0.4710f,      0.16666667f, 0.0f));
894           aFilterL.SetRow (1, Graphic3d_Vec4 (-0.0458f,     -0.0484f,     -0.0257f,     0.0f));
895           aFilterL.SetRow (2, Graphic3d_Vec4 (-0.0547f,     -0.0615f,      0.0128f,     0.0f));
896           aFilterL.SetRow (3, Graphic3d_Vec4 ( 0.0f,         0.0f,         0.0f,        0.0f));
897           aFilterR.SetRow (0, Graphic3d_Vec4 (-0.01090909f, -0.03636364f, -0.00606061f, 0.0f));
898           aFilterR.SetRow (1, Graphic3d_Vec4 ( 0.37560000f,  0.73333333f,  0.01111111f, 0.0f));
899           aFilterR.SetRow (2, Graphic3d_Vec4 (-0.06510000f, -0.12870000f,  1.29710000f, 0.0f));
900           aFilterR.SetRow (3, Graphic3d_Vec4 ( 0.0f,                0.0f,  0.0f,        0.0f));
901           break;
902         }
903         case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple:
904         {
905           aFilterL.SetRow (0, Graphic3d_Vec4 (1.0f, 0.0f, 0.0f, 0.0f));
906           aFilterL.SetRow (1, Graphic3d_Vec4 (0.0f, 1.0f, 0.0f, 0.0f));
907           aFilterR.SetRow (2, Graphic3d_Vec4 (0.0f, 0.0f, 1.0f, 0.0f));
908           break;
909         }
910         case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized:
911         {
912           aFilterL.SetRow (0, Graphic3d_Vec4 ( 1.062f, -0.205f,  0.299f, 0.0f));
913           aFilterL.SetRow (1, Graphic3d_Vec4 (-0.026f,  0.908f,  0.068f, 0.0f));
914           aFilterL.SetRow (2, Graphic3d_Vec4 (-0.038f, -0.173f,  0.022f, 0.0f));
915           aFilterL.SetRow (3, Graphic3d_Vec4 ( 0.0f,    0.0f,    0.0f,   0.0f));
916           aFilterR.SetRow (0, Graphic3d_Vec4 (-0.016f, -0.123f, -0.017f, 0.0f));
917           aFilterR.SetRow (1, Graphic3d_Vec4 ( 0.006f,  0.062f, -0.017f, 0.0f));
918           aFilterR.SetRow (2, Graphic3d_Vec4 ( 0.094f,  0.185f,  0.911f, 0.0f));
919           aFilterR.SetRow (3, Graphic3d_Vec4 ( 0.0f,    0.0f,    0.0f,   0.0f));
920           break;
921         }
922         case Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple:
923         {
924           aFilterR.SetRow (0, Graphic3d_Vec4 (1.0f, 0.0f, 0.0f, 0.0f));
925           aFilterL.SetRow (1, Graphic3d_Vec4 (0.0f, 1.0f, 0.0f, 0.0f));
926           aFilterR.SetRow (2, Graphic3d_Vec4 (0.0f, 0.0f, 1.0f, 0.0f));
927           break;
928         }
929         case Graphic3d_RenderingParams::Anaglyph_UserDefined:
930         {
931           aFilterL = theCView.RenderParams.AnaglyphLeft;
932           aFilterR = theCView.RenderParams.AnaglyphRight;
933           break;
934         }
935       }
936       myGlContext->ActiveProgram()->SetUniform (myGlContext, "uMultL", aFilterL);
937       myGlContext->ActiveProgram()->SetUniform (myGlContext, "uMultR", aFilterR);
938     }
939
940     aPair[0]->ColorTexture()->Bind (myGlContext, GL_TEXTURE0 + 0);
941     aPair[1]->ColorTexture()->Bind (myGlContext, GL_TEXTURE0 + 1);
942     myFullScreenQuad.BindVertexAttrib (myGlContext, 0);
943
944     myGlContext->core20fwd->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
945
946     myFullScreenQuad.UnbindVertexAttrib (myGlContext, 0);
947     aPair[1]->ColorTexture()->Unbind (myGlContext, GL_TEXTURE0 + 1);
948     aPair[0]->ColorTexture()->Unbind (myGlContext, GL_TEXTURE0 + 0);
949   }
950   else
951   {
952     TCollection_ExtendedString aMsg = TCollection_ExtendedString()
953       + "Error! Anaglyph has failed";
954     myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
955                               GL_DEBUG_TYPE_ERROR_ARB,
956                               0,
957                               GL_DEBUG_SEVERITY_HIGH_ARB,
958                               aMsg);
959   }
960 }
961
962 // =======================================================================
963 // function : Redraw
964 // purpose  :
965 // =======================================================================
966 void OpenGl_Workspace::Redraw (const Graphic3d_CView& theCView,
967                                const Aspect_CLayer2d& theCUnderLayer,
968                                const Aspect_CLayer2d& theCOverLayer)
969 {
970   if (!Activate())
971   {
972     return;
973   }
974
975   if (mySwapInterval != myGlContext->caps->swapInterval)
976   {
977     mySwapInterval = myGlContext->caps->swapInterval;
978     myGlContext->SetSwapInterval (mySwapInterval);
979   }
980
981   ++myFrameCounter;
982   myIsCullingEnabled = theCView.IsCullingEnabled;
983   const Graphic3d_StereoMode      aStereoMode  = theCView.RenderParams.StereoMode;
984   const Handle(Graphic3d_Camera)& aCamera      = myView->Camera();
985   Graphic3d_Camera::Projection    aProjectType = aCamera->ProjectionType();
986
987   // release pending GL resources
988   myGlContext->ReleaseDelayed();
989
990   // fetch OpenGl context state
991   myGlContext->FetchState();
992
993   OpenGl_FrameBuffer* aFrameBuffer = (OpenGl_FrameBuffer* )theCView.ptrFBO;
994   bool toSwap = myGlContext->IsRender()
995             && !myGlContext->caps->buffersNoSwap
996             &&  aFrameBuffer == NULL;
997
998   Standard_Integer aSizeX = aFrameBuffer != NULL ? aFrameBuffer->GetVPSizeX() : myWidth;
999   Standard_Integer aSizeY = aFrameBuffer != NULL ? aFrameBuffer->GetVPSizeY() : myHeight;
1000
1001   if ( aFrameBuffer == NULL
1002    && !myGlContext->DefaultFrameBuffer().IsNull()
1003    &&  myGlContext->DefaultFrameBuffer()->IsValid())
1004   {
1005     aFrameBuffer = myGlContext->DefaultFrameBuffer().operator->();
1006   }
1007
1008   if (myHasFboBlit
1009    && (myTransientDrawToFront || aProjectType == Graphic3d_Camera::Projection_Stereo))
1010   {
1011     if (myMainSceneFbos[0]->GetVPSizeX() != aSizeX
1012      || myMainSceneFbos[0]->GetVPSizeY() != aSizeY)
1013     {
1014       // prepare FBOs containing main scene
1015       // for further blitting and rendering immediate presentations on top
1016       if (myGlContext->core20fwd != NULL)
1017       {
1018         myMainSceneFbos[0]->Init (myGlContext, aSizeX, aSizeY);
1019       }
1020     }
1021   }
1022   else
1023   {
1024     myMainSceneFbos     [0]->Release (myGlContext.operator->());
1025     myMainSceneFbos     [1]->Release (myGlContext.operator->());
1026     myImmediateSceneFbos[0]->Release (myGlContext.operator->());
1027     myImmediateSceneFbos[1]->Release (myGlContext.operator->());
1028     myMainSceneFbos     [0]->ChangeViewport (0, 0);
1029     myMainSceneFbos     [1]->ChangeViewport (0, 0);
1030     myImmediateSceneFbos[0]->ChangeViewport (0, 0);
1031     myImmediateSceneFbos[1]->ChangeViewport (0, 0);
1032   }
1033
1034   if (aProjectType == Graphic3d_Camera::Projection_Stereo
1035    && myMainSceneFbos[0]->IsValid())
1036   {
1037     myMainSceneFbos[1]->InitLazy (myGlContext, aSizeX, aSizeY);
1038     if (!myMainSceneFbos[1]->IsValid())
1039     {
1040       // no enough memory?
1041       aProjectType = Graphic3d_Camera::Projection_Perspective;
1042     }
1043     else if (!myTransientDrawToFront)
1044     {
1045       //
1046     }
1047     else if (!myGlContext->HasStereoBuffers()
1048            || aStereoMode != Graphic3d_StereoMode_QuadBuffer)
1049     {
1050       myImmediateSceneFbos[0]->InitLazy (myGlContext, aSizeX, aSizeY);
1051       myImmediateSceneFbos[1]->InitLazy (myGlContext, aSizeX, aSizeY);
1052       if (!myImmediateSceneFbos[0]->IsValid()
1053        || !myImmediateSceneFbos[1]->IsValid())
1054       {
1055         aProjectType = Graphic3d_Camera::Projection_Perspective;
1056       }
1057     }
1058   }
1059
1060   if (aProjectType == Graphic3d_Camera::Projection_Stereo)
1061   {
1062     OpenGl_FrameBuffer* aMainFbos[2] =
1063     {
1064       myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL,
1065       myMainSceneFbos[1]->IsValid() ? myMainSceneFbos[1].operator->() : NULL
1066     };
1067     OpenGl_FrameBuffer* anImmFbos[2] =
1068     {
1069       myImmediateSceneFbos[0]->IsValid() ? myImmediateSceneFbos[0].operator->() : NULL,
1070       myImmediateSceneFbos[1]->IsValid() ? myImmediateSceneFbos[1].operator->() : NULL
1071     };
1072
1073     if (!myTransientDrawToFront)
1074     {
1075       anImmFbos[0] = aMainFbos[0];
1076       anImmFbos[1] = aMainFbos[1];
1077     }
1078     else if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip
1079           || aStereoMode == Graphic3d_StereoMode_QuadBuffer)
1080     {
1081       anImmFbos[0] = NULL;
1082       anImmFbos[1] = NULL;
1083     }
1084
1085   #if !defined(GL_ES_VERSION_2_0)
1086     myGlContext->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_LEFT : GL_BACK);
1087   #endif
1088     redraw1 (theCView, theCUnderLayer, theCOverLayer,
1089              aMainFbos[0], Graphic3d_Camera::Projection_MonoLeftEye);
1090     myBackBufferRestored = Standard_True;
1091     myIsImmediateDrawn   = Standard_False;
1092   #if !defined(GL_ES_VERSION_2_0)
1093     myGlContext->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_LEFT : GL_BACK);
1094   #endif
1095     if (!redrawImmediate (theCView, theCOverLayer, theCUnderLayer, aMainFbos[0], aProjectType, anImmFbos[0]))
1096     {
1097       toSwap = false;
1098     }
1099     else if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip
1100           && toSwap)
1101     {
1102       myGlContext->SwapBuffers();
1103     }
1104
1105   #if !defined(GL_ES_VERSION_2_0)
1106     myGlContext->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_RIGHT : GL_BACK);
1107   #endif
1108     redraw1 (theCView, theCUnderLayer, theCOverLayer,
1109              aMainFbos[1], Graphic3d_Camera::Projection_MonoRightEye);
1110     myBackBufferRestored = Standard_True;
1111     myIsImmediateDrawn   = Standard_False;
1112     if (!redrawImmediate (theCView, theCOverLayer, theCUnderLayer, aMainFbos[1], aProjectType, anImmFbos[1]))
1113     {
1114       toSwap = false;
1115     }
1116
1117     if (anImmFbos[0] != NULL)
1118     {
1119       bindDefaultFbo (aFrameBuffer);
1120       drawStereoPair (theCView);
1121     }
1122   }
1123   else
1124   {
1125     OpenGl_FrameBuffer* aMainFbo = myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL;
1126   #if !defined(GL_ES_VERSION_2_0)
1127     if (aMainFbo     == NULL
1128      && aFrameBuffer == NULL)
1129     {
1130       myGlContext->SetReadDrawBuffer (GL_BACK);
1131     }
1132   #endif
1133     redraw1 (theCView, theCUnderLayer, theCOverLayer,
1134              aMainFbo != NULL ? aMainFbo : aFrameBuffer, aProjectType);
1135     myBackBufferRestored = Standard_True;
1136     myIsImmediateDrawn   = Standard_False;
1137     if (!redrawImmediate (theCView, theCOverLayer, theCUnderLayer, aMainFbo, aProjectType, aFrameBuffer))
1138     {
1139       toSwap = false;
1140     }
1141   }
1142
1143 #if defined(_WIN32) && defined(HAVE_VIDEOCAPTURE)
1144   if (OpenGl_AVIWriter_AllowWriting (theCView.DefWindow.XWindow))
1145   {
1146     GLint params[4];
1147     glGetIntegerv (GL_VIEWPORT, params);
1148     int nWidth  = params[2] & ~0x7;
1149     int nHeight = params[3] & ~0x7;
1150
1151     const int nBitsPerPixel = 24;
1152     GLubyte* aDumpData = new GLubyte[nWidth * nHeight * nBitsPerPixel / 8];
1153
1154     glPixelStorei (GL_PACK_ALIGNMENT, 1);
1155     glReadPixels (0, 0, nWidth, nHeight, GL_BGR_EXT, GL_UNSIGNED_BYTE, aDumpData);
1156     OpenGl_AVIWriter_AVIWriter (aDumpData, nWidth, nHeight, nBitsPerPixel);
1157     delete[] aDumpData;
1158   }
1159 #endif
1160
1161   // bind default FBO
1162   bindDefaultFbo();
1163
1164   // Swap the buffers
1165   if (toSwap)
1166   {
1167     GetGlContext()->SwapBuffers();
1168     if (!myMainSceneFbos[0]->IsValid())
1169     {
1170       myBackBufferRestored = Standard_False;
1171     }
1172   }
1173   else
1174   {
1175     myGlContext->core11fwd->glFlush();
1176   }
1177
1178   // reset render mode state
1179   myGlContext->FetchState();
1180 }
1181
1182 // =======================================================================
1183 // function : redraw1
1184 // purpose  :
1185 // =======================================================================
1186 void OpenGl_Workspace::redraw1 (const Graphic3d_CView&               theCView,
1187                                 const Aspect_CLayer2d&               theCUnderLayer,
1188                                 const Aspect_CLayer2d&               theCOverLayer,
1189                                 OpenGl_FrameBuffer*                  theReadDrawFbo,
1190                                 const Graphic3d_Camera::Projection   theProjection)
1191 {
1192   if (myView.IsNull())
1193   {
1194     return;
1195   }
1196
1197   if (theReadDrawFbo != NULL)
1198   {
1199     theReadDrawFbo->BindBuffer    (myGlContext);
1200     theReadDrawFbo->SetupViewport (myGlContext);
1201   }
1202   else
1203   {
1204     myGlContext->core11fwd->glViewport (0, 0, myWidth, myHeight);
1205   }
1206
1207   // request reset of material
1208   NamedStatus |= OPENGL_NS_RESMAT;
1209
1210   myUseZBuffer    = Standard_True;
1211   myUseDepthWrite = Standard_True;
1212   GLbitfield toClear = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT;
1213   glDepthFunc (GL_LEQUAL);
1214   glDepthMask (GL_TRUE);
1215   glEnable (GL_DEPTH_TEST);
1216
1217 #if !defined(GL_ES_VERSION_2_0)
1218   glClearDepth (1.0);
1219 #else
1220   glClearDepthf (1.0f);
1221 #endif
1222
1223   if (NamedStatus & OPENGL_NS_WHITEBACK)
1224   {
1225     // set background to white
1226     glClearColor (1.0f, 1.0f, 1.0f, 1.0f);
1227   }
1228   else
1229   {
1230     glClearColor (myBgColor.rgb[0], myBgColor.rgb[1], myBgColor.rgb[2], 0.0f);
1231   }
1232
1233   glClear (toClear);
1234
1235   Handle(OpenGl_Workspace) aWS (this);
1236   myView->Render (myPrintContext, aWS, theReadDrawFbo, theProjection, theCView, theCUnderLayer, theCOverLayer, Standard_False);
1237 }
1238
1239 // =======================================================================
1240 // function : copyBackToFront
1241 // purpose  :
1242 // =======================================================================
1243 void OpenGl_Workspace::copyBackToFront()
1244 {
1245 #if !defined(GL_ES_VERSION_2_0)
1246
1247   OpenGl_Mat4 aProjectMat;
1248   OpenGl_Utils::Ortho2D<Standard_ShortReal> (aProjectMat,
1249     0.f, static_cast<GLfloat> (myWidth), 0.f, static_cast<GLfloat> (myHeight));
1250
1251   myGlContext->WorldViewState.Push();
1252   myGlContext->ProjectionState.Push();
1253
1254   myGlContext->WorldViewState.SetIdentity();
1255   myGlContext->ProjectionState.SetCurrent (aProjectMat);
1256
1257   myGlContext->ApplyProjectionMatrix();
1258   myGlContext->ApplyWorldViewMatrix();
1259
1260   DisableFeatures();
1261
1262   switch (myGlContext->DrawBuffer())
1263   {
1264     case GL_BACK_LEFT:
1265     {
1266       myGlContext->SetReadBuffer (GL_BACK_LEFT);
1267       myGlContext->SetDrawBuffer (GL_FRONT_LEFT);
1268       break;
1269     }
1270     case GL_BACK_RIGHT:
1271     {
1272       myGlContext->SetReadBuffer (GL_BACK_RIGHT);
1273       myGlContext->SetDrawBuffer (GL_FRONT_RIGHT);
1274       break;
1275     }
1276     default:
1277     {
1278       myGlContext->SetReadBuffer (GL_BACK);
1279       myGlContext->SetDrawBuffer (GL_FRONT);
1280       break;
1281     }
1282   }
1283
1284   glRasterPos2i (0, 0);
1285   glCopyPixels  (0, 0, myWidth + 1, myHeight + 1, GL_COLOR);
1286   //glCopyPixels  (0, 0, myWidth + 1, myHeight + 1, GL_DEPTH);
1287
1288   EnableFeatures();
1289
1290   myGlContext->WorldViewState.Pop();
1291   myGlContext->ProjectionState.Pop();
1292   myGlContext->ApplyProjectionMatrix();
1293
1294   // read/write from front buffer now
1295   myGlContext->SetReadBuffer (myGlContext->DrawBuffer());
1296 #endif
1297   myIsImmediateDrawn = Standard_False;
1298 }
1299
1300 // =======================================================================
1301 // function : DisplayCallback
1302 // purpose  :
1303 // =======================================================================
1304 void OpenGl_Workspace::DisplayCallback (const Graphic3d_CView& theCView,
1305                                         Standard_Integer       theReason)
1306 {
1307   if (theCView.GDisplayCB == NULL)
1308   {
1309     return;
1310   }
1311
1312   Aspect_GraphicCallbackStruct aCallData;
1313   aCallData.reason    = theReason;
1314   aCallData.glContext = myGlContext;
1315   aCallData.wsID      = theCView.WsId;
1316   aCallData.viewID    = theCView.ViewId;
1317   aCallData.IsCoreProfile = (myGlContext->core11 == NULL);
1318   theCView.GDisplayCB (theCView.DefWindow.XWindow, theCView.GClientData, &aCallData);
1319 }
1320
1321 // =======================================================================
1322 // function : RedrawImmediate
1323 // purpose  :
1324 // =======================================================================
1325 void OpenGl_Workspace::RedrawImmediate (const Graphic3d_CView& theCView,
1326                                         const Aspect_CLayer2d& theCUnderLayer,
1327                                         const Aspect_CLayer2d& theCOverLayer)
1328 {
1329   const Handle(Graphic3d_Camera)& aCamera      = myView->Camera();
1330   Graphic3d_Camera::Projection    aProjectType = aCamera->ProjectionType();
1331   OpenGl_FrameBuffer* aFrameBuffer = (OpenGl_FrameBuffer* )theCView.ptrFBO;
1332   if ( aFrameBuffer == NULL
1333    && !myGlContext->DefaultFrameBuffer().IsNull()
1334    &&  myGlContext->DefaultFrameBuffer()->IsValid())
1335   {
1336     aFrameBuffer = myGlContext->DefaultFrameBuffer().operator->();
1337   }
1338
1339   const Graphic3d_StereoMode aStereoMode = theCView.RenderParams.StereoMode;
1340   if (aProjectType == Graphic3d_Camera::Projection_Stereo)
1341   {
1342     if (aFrameBuffer != NULL)
1343     {
1344       // implicitly switch to mono camera for image dump
1345       aProjectType = Graphic3d_Camera::Projection_Perspective;
1346     }
1347     else if (myMainSceneFbos[0]->IsValid()
1348          && !myMainSceneFbos[1]->IsValid())
1349     {
1350       aProjectType = Graphic3d_Camera::Projection_Perspective;
1351     }
1352   }
1353
1354   if (!myTransientDrawToFront
1355    || !myBackBufferRestored
1356    || (myGlContext->caps->buffersNoSwap && !myMainSceneFbos[0]->IsValid()))
1357   {
1358     Redraw (theCView, theCUnderLayer, theCOverLayer);
1359     return;
1360   }
1361   else if (!Activate())
1362   {
1363     return;
1364   }
1365
1366   bool toSwap = false;
1367   if (aProjectType == Graphic3d_Camera::Projection_Stereo)
1368   {
1369     OpenGl_FrameBuffer* aMainFbos[2] =
1370     {
1371       myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL,
1372       myMainSceneFbos[1]->IsValid() ? myMainSceneFbos[1].operator->() : NULL
1373     };
1374     OpenGl_FrameBuffer* anImmFbos[2] =
1375     {
1376       myImmediateSceneFbos[0]->IsValid() ? myImmediateSceneFbos[0].operator->() : NULL,
1377       myImmediateSceneFbos[1]->IsValid() ? myImmediateSceneFbos[1].operator->() : NULL
1378     };
1379     if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip
1380      || aStereoMode == Graphic3d_StereoMode_QuadBuffer)
1381     {
1382       anImmFbos[0] = NULL;
1383       anImmFbos[1] = NULL;
1384     }
1385
1386     if (myGlContext->arbFBO != NULL)
1387     {
1388       myGlContext->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
1389     }
1390   #if !defined(GL_ES_VERSION_2_0)
1391     if (anImmFbos[0] == NULL)
1392     {
1393       myGlContext->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_LEFT : GL_BACK);
1394     }
1395   #endif
1396     toSwap = redrawImmediate (theCView, theCUnderLayer, theCOverLayer,
1397                               aMainFbos[0],
1398                               Graphic3d_Camera::Projection_MonoLeftEye,
1399                               anImmFbos[0],
1400                               Standard_True) || toSwap;
1401     if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip
1402     &&  toSwap
1403     && !myGlContext->caps->buffersNoSwap)
1404     {
1405       myGlContext->SwapBuffers();
1406     }
1407
1408     if (myGlContext->arbFBO != NULL)
1409     {
1410       myGlContext->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
1411     }
1412   #if !defined(GL_ES_VERSION_2_0)
1413     if (anImmFbos[1] == NULL)
1414     {
1415       myGlContext->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_RIGHT : GL_BACK);
1416     }
1417   #endif
1418     toSwap = redrawImmediate (theCView, theCUnderLayer, theCOverLayer,
1419                               aMainFbos[1],
1420                               Graphic3d_Camera::Projection_MonoRightEye,
1421                               anImmFbos[1],
1422                               Standard_True) || toSwap;
1423     if (anImmFbos[0] != NULL)
1424     {
1425       bindDefaultFbo (aFrameBuffer);
1426       drawStereoPair (theCView);
1427     }
1428   }
1429   else
1430   {
1431     OpenGl_FrameBuffer* aMainFbo = myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL;
1432   #if !defined(GL_ES_VERSION_2_0)
1433     if (aMainFbo == NULL)
1434     {
1435       myGlContext->SetReadDrawBuffer (GL_BACK);
1436     }
1437   #endif
1438     toSwap = redrawImmediate (theCView, theCUnderLayer, theCOverLayer,
1439                               aMainFbo,
1440                               aProjectType,
1441                               aFrameBuffer,
1442                               Standard_True) || toSwap;
1443   }
1444
1445   // bind default FBO
1446   bindDefaultFbo();
1447
1448   if (toSwap
1449   && !myGlContext->caps->buffersNoSwap)
1450   {
1451     myGlContext->SwapBuffers();
1452   }
1453   else
1454   {
1455     myGlContext->core11fwd->glFlush();
1456   }
1457 }
1458
1459 // =======================================================================
1460 // function : redrawImmediate
1461 // purpose  :
1462 // =======================================================================
1463 bool OpenGl_Workspace::redrawImmediate (const Graphic3d_CView& theCView,
1464                                         const Aspect_CLayer2d& theCUnderLayer,
1465                                         const Aspect_CLayer2d& theCOverLayer,
1466                                         OpenGl_FrameBuffer*    theReadFbo,
1467                                         const Graphic3d_Camera::Projection theProjection,
1468                                         OpenGl_FrameBuffer*    theDrawFbo,
1469                                         const Standard_Boolean theIsPartialUpdate)
1470 {
1471   GLboolean toCopyBackToFront = GL_FALSE;
1472   if (!myTransientDrawToFront)
1473   {
1474     myBackBufferRestored = Standard_False;
1475   }
1476   else if (theReadFbo != NULL
1477         && theReadFbo->IsValid()
1478         && myGlContext->IsRender())
1479   {
1480     if (!blitBuffers (theReadFbo, theDrawFbo))
1481     {
1482       return true;
1483     }
1484   }
1485   else if (theDrawFbo == NULL)
1486   {
1487   #if !defined(GL_ES_VERSION_2_0)
1488     myGlContext->core11fwd->glGetBooleanv (GL_DOUBLEBUFFER, &toCopyBackToFront);
1489   #endif
1490     if (toCopyBackToFront)
1491     {
1492       if (!myView->HasImmediateStructures()
1493        && !theIsPartialUpdate)
1494       {
1495         // prefer Swap Buffers within Redraw in compatibility mode (without FBO)
1496         return true;
1497       }
1498       copyBackToFront();
1499     }
1500     else
1501     {
1502       myBackBufferRestored = Standard_False;
1503     }
1504   }
1505   else
1506   {
1507     myBackBufferRestored = Standard_False;
1508   }
1509   myIsImmediateDrawn = Standard_True;
1510
1511   Handle(OpenGl_Workspace) aWS (this);
1512
1513   myUseZBuffer    = Standard_True;
1514   myUseDepthWrite = Standard_True;
1515   glDepthFunc (GL_LEQUAL);
1516   glDepthMask (GL_TRUE);
1517   glEnable (GL_DEPTH_TEST);
1518 #if !defined(GL_ES_VERSION_2_0)
1519   glClearDepth (1.0);
1520 #else
1521   glClearDepthf (1.0f);
1522 #endif
1523
1524   myView->Render (myPrintContext, aWS, theDrawFbo, theProjection,
1525                   theCView, theCUnderLayer, theCOverLayer, Standard_True);
1526   if (!myView->ImmediateStructures().IsEmpty())
1527   {
1528     myUseZBuffer = Standard_False;
1529     glDisable (GL_DEPTH_TEST);
1530   }
1531   for (OpenGl_IndexedMapOfStructure::Iterator anIter (myView->ImmediateStructures()); anIter.More(); anIter.Next())
1532   {
1533     const OpenGl_Structure* aStructure = anIter.Value();
1534     if (!aStructure->IsVisible())
1535     {
1536       continue;
1537     }
1538
1539     aStructure->Render (aWS);
1540   }
1541
1542   return !toCopyBackToFront;
1543 }
1544
1545 IMPLEMENT_STANDARD_HANDLE (OpenGl_RaytraceFilter, OpenGl_RenderFilter)
1546 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_RaytraceFilter, OpenGl_RenderFilter)
1547
1548 // =======================================================================
1549 // function : CanRender
1550 // purpose  :
1551 // =======================================================================
1552 Standard_Boolean OpenGl_RaytraceFilter::CanRender (const OpenGl_Element* theElement)
1553 {
1554   Standard_Boolean aPrevFilterResult = Standard_True;
1555   if (!myPrevRenderFilter.IsNull())
1556   {
1557     aPrevFilterResult = myPrevRenderFilter->CanRender (theElement);
1558   }
1559   return aPrevFilterResult &&
1560     !OpenGl_Raytrace::IsRaytracedElement (theElement);
1561 }