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