0025789: Visualization - get rid of obsolete 2d layers implementation
[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_View.hxx>
33 #include <OpenGl_Workspace.hxx>
34
35 #include <Graphic3d_TextureParams.hxx>
36 #include <Graphic3d_GraphicDriver.hxx>
37 #include <Graphic3d_TransformUtils.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     Graphic3d_TransformUtils::Scale     (aTextureMat,  aScale.x(),  aScale.y(), 1.0f);
425     Graphic3d_TransformUtils::Translate (aTextureMat, -aTrans.x(), -aTrans.y(), 0.0f);
426     Graphic3d_TransformUtils::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 || myGlContext->IsFeedback())
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 {
1007   if (!Activate())
1008   {
1009     return;
1010   }
1011
1012   if (mySwapInterval != myGlContext->caps->swapInterval)
1013   {
1014     mySwapInterval = myGlContext->caps->swapInterval;
1015     myGlContext->SetSwapInterval (mySwapInterval);
1016   }
1017
1018   ++myFrameCounter;
1019   myIsCullingEnabled = theCView.IsCullingEnabled;
1020   const Graphic3d_StereoMode      aStereoMode  = theCView.RenderParams.StereoMode;
1021   const Handle(Graphic3d_Camera)& aCamera      = myView->Camera();
1022   Graphic3d_Camera::Projection    aProjectType = aCamera->ProjectionType();
1023
1024   // release pending GL resources
1025   myGlContext->ReleaseDelayed();
1026
1027   // fetch OpenGl context state
1028   myGlContext->FetchState();
1029
1030   OpenGl_FrameBuffer* aFrameBuffer = (OpenGl_FrameBuffer* )theCView.ptrFBO;
1031   bool toSwap = myGlContext->IsRender()
1032             && !myGlContext->caps->buffersNoSwap
1033             &&  aFrameBuffer == NULL;
1034
1035   Standard_Integer aSizeX = aFrameBuffer != NULL ? aFrameBuffer->GetVPSizeX() : myWidth;
1036   Standard_Integer aSizeY = aFrameBuffer != NULL ? aFrameBuffer->GetVPSizeY() : myHeight;
1037
1038   if ( aFrameBuffer == NULL
1039    && !myGlContext->DefaultFrameBuffer().IsNull()
1040    &&  myGlContext->DefaultFrameBuffer()->IsValid())
1041   {
1042     aFrameBuffer = myGlContext->DefaultFrameBuffer().operator->();
1043   }
1044
1045   if (myHasFboBlit
1046    && (myTransientDrawToFront || aProjectType == Graphic3d_Camera::Projection_Stereo))
1047   {
1048     if (myMainSceneFbos[0]->GetVPSizeX() != aSizeX
1049      || myMainSceneFbos[0]->GetVPSizeY() != aSizeY)
1050     {
1051       // prepare FBOs containing main scene
1052       // for further blitting and rendering immediate presentations on top
1053       if (myGlContext->core20fwd != NULL)
1054       {
1055         myMainSceneFbos[0]->Init (myGlContext, aSizeX, aSizeY);
1056       }
1057       if (!myGlContext->caps->useSystemBuffer && myMainSceneFbos[0]->IsValid())
1058       {
1059         myImmediateSceneFbos[0]->InitLazy (myGlContext, aSizeX, aSizeY);
1060       }
1061     }
1062   }
1063   else
1064   {
1065     myMainSceneFbos     [0]->Release (myGlContext.operator->());
1066     myMainSceneFbos     [1]->Release (myGlContext.operator->());
1067     myImmediateSceneFbos[0]->Release (myGlContext.operator->());
1068     myImmediateSceneFbos[1]->Release (myGlContext.operator->());
1069     myMainSceneFbos     [0]->ChangeViewport (0, 0);
1070     myMainSceneFbos     [1]->ChangeViewport (0, 0);
1071     myImmediateSceneFbos[0]->ChangeViewport (0, 0);
1072     myImmediateSceneFbos[1]->ChangeViewport (0, 0);
1073   }
1074
1075   if (aProjectType == Graphic3d_Camera::Projection_Stereo
1076    && myMainSceneFbos[0]->IsValid())
1077   {
1078     myMainSceneFbos[1]->InitLazy (myGlContext, aSizeX, aSizeY);
1079     if (!myMainSceneFbos[1]->IsValid())
1080     {
1081       // no enough memory?
1082       aProjectType = Graphic3d_Camera::Projection_Perspective;
1083     }
1084     else if (!myTransientDrawToFront)
1085     {
1086       //
1087     }
1088     else if (!myGlContext->HasStereoBuffers()
1089            || aStereoMode != Graphic3d_StereoMode_QuadBuffer)
1090     {
1091       myImmediateSceneFbos[0]->InitLazy (myGlContext, aSizeX, aSizeY);
1092       myImmediateSceneFbos[1]->InitLazy (myGlContext, aSizeX, aSizeY);
1093       if (!myImmediateSceneFbos[0]->IsValid()
1094        || !myImmediateSceneFbos[1]->IsValid())
1095       {
1096         aProjectType = Graphic3d_Camera::Projection_Perspective;
1097       }
1098     }
1099   }
1100
1101   if (aProjectType == Graphic3d_Camera::Projection_Stereo)
1102   {
1103     OpenGl_FrameBuffer* aMainFbos[2] =
1104     {
1105       myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL,
1106       myMainSceneFbos[1]->IsValid() ? myMainSceneFbos[1].operator->() : NULL
1107     };
1108     OpenGl_FrameBuffer* anImmFbos[2] =
1109     {
1110       myImmediateSceneFbos[0]->IsValid() ? myImmediateSceneFbos[0].operator->() : NULL,
1111       myImmediateSceneFbos[1]->IsValid() ? myImmediateSceneFbos[1].operator->() : NULL
1112     };
1113
1114     if (!myTransientDrawToFront)
1115     {
1116       anImmFbos[0] = aMainFbos[0];
1117       anImmFbos[1] = aMainFbos[1];
1118     }
1119     else if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip
1120           || aStereoMode == Graphic3d_StereoMode_QuadBuffer)
1121     {
1122       anImmFbos[0] = NULL;
1123       anImmFbos[1] = NULL;
1124     }
1125
1126   #if !defined(GL_ES_VERSION_2_0)
1127     myGlContext->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_LEFT : GL_BACK);
1128   #endif
1129     redraw1 (theCView, aMainFbos[0], Graphic3d_Camera::Projection_MonoLeftEye);
1130     myBackBufferRestored = Standard_True;
1131     myIsImmediateDrawn   = Standard_False;
1132   #if !defined(GL_ES_VERSION_2_0)
1133     myGlContext->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_LEFT : GL_BACK);
1134   #endif
1135     if (!redrawImmediate (theCView, aMainFbos[0], aProjectType, anImmFbos[0]))
1136     {
1137       toSwap = false;
1138     }
1139     else if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip
1140           && toSwap)
1141     {
1142       myGlContext->SwapBuffers();
1143     }
1144
1145   #if !defined(GL_ES_VERSION_2_0)
1146     myGlContext->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_RIGHT : GL_BACK);
1147   #endif
1148     redraw1 (theCView, aMainFbos[1], Graphic3d_Camera::Projection_MonoRightEye);
1149     myBackBufferRestored = Standard_True;
1150     myIsImmediateDrawn   = Standard_False;
1151     if (!redrawImmediate (theCView, aMainFbos[1], aProjectType, anImmFbos[1]))
1152     {
1153       toSwap = false;
1154     }
1155
1156     if (anImmFbos[0] != NULL)
1157     {
1158       bindDefaultFbo (aFrameBuffer);
1159       drawStereoPair (theCView);
1160     }
1161   }
1162   else
1163   {
1164     OpenGl_FrameBuffer* aMainFbo = myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL;
1165     OpenGl_FrameBuffer* anImmFbo = aFrameBuffer;
1166     if (!myGlContext->caps->useSystemBuffer && myImmediateSceneFbos[0]->IsValid())
1167     {
1168       anImmFbo = myImmediateSceneFbos[0].operator->();
1169     }
1170
1171   #if !defined(GL_ES_VERSION_2_0)
1172     if (aMainFbo     == NULL
1173      && aFrameBuffer == NULL)
1174     {
1175       myGlContext->SetReadDrawBuffer (GL_BACK);
1176     }
1177   #endif
1178     redraw1 (theCView, aMainFbo != NULL ? aMainFbo : aFrameBuffer, aProjectType);
1179     myBackBufferRestored = Standard_True;
1180     myIsImmediateDrawn   = Standard_False;
1181     if (!redrawImmediate (theCView, aMainFbo, aProjectType, anImmFbo))
1182     {
1183       toSwap = false;
1184     }
1185
1186     if (anImmFbo != NULL
1187      && anImmFbo != aFrameBuffer)
1188     {
1189       blitBuffers (anImmFbo, aFrameBuffer, myToFlipOutput);
1190     }
1191   }
1192
1193 #if defined(_WIN32) && defined(HAVE_VIDEOCAPTURE)
1194   if (OpenGl_AVIWriter_AllowWriting (theCView.DefWindow.XWindow))
1195   {
1196     GLint params[4];
1197     glGetIntegerv (GL_VIEWPORT, params);
1198     int nWidth  = params[2] & ~0x7;
1199     int nHeight = params[3] & ~0x7;
1200
1201     const int nBitsPerPixel = 24;
1202     GLubyte* aDumpData = new GLubyte[nWidth * nHeight * nBitsPerPixel / 8];
1203
1204     glPixelStorei (GL_PACK_ALIGNMENT, 1);
1205     glReadPixels (0, 0, nWidth, nHeight, GL_BGR_EXT, GL_UNSIGNED_BYTE, aDumpData);
1206     OpenGl_AVIWriter_AVIWriter (aDumpData, nWidth, nHeight, nBitsPerPixel);
1207     delete[] aDumpData;
1208   }
1209 #endif
1210
1211   // bind default FBO
1212   bindDefaultFbo();
1213
1214   // Swap the buffers
1215   if (toSwap)
1216   {
1217     GetGlContext()->SwapBuffers();
1218     if (!myMainSceneFbos[0]->IsValid())
1219     {
1220       myBackBufferRestored = Standard_False;
1221     }
1222   }
1223   else
1224   {
1225     myGlContext->core11fwd->glFlush();
1226   }
1227
1228   // reset render mode state
1229   myGlContext->FetchState();
1230 }
1231
1232 // =======================================================================
1233 // function : redraw1
1234 // purpose  :
1235 // =======================================================================
1236 void OpenGl_Workspace::redraw1 (const Graphic3d_CView&               theCView,
1237                                 OpenGl_FrameBuffer*                  theReadDrawFbo,
1238                                 const Graphic3d_Camera::Projection   theProjection)
1239 {
1240   if (myView.IsNull())
1241   {
1242     return;
1243   }
1244
1245   if (theReadDrawFbo != NULL)
1246   {
1247     theReadDrawFbo->BindBuffer    (myGlContext);
1248     theReadDrawFbo->SetupViewport (myGlContext);
1249   }
1250   else
1251   {
1252     myGlContext->core11fwd->glViewport (0, 0, myWidth, myHeight);
1253   }
1254
1255   // request reset of material
1256   NamedStatus |= OPENGL_NS_RESMAT;
1257
1258   myUseZBuffer    = Standard_True;
1259   myUseDepthWrite = Standard_True;
1260   GLbitfield toClear = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT;
1261   glDepthFunc (GL_LEQUAL);
1262   glDepthMask (GL_TRUE);
1263   glEnable (GL_DEPTH_TEST);
1264
1265 #if !defined(GL_ES_VERSION_2_0)
1266   glClearDepth (1.0);
1267 #else
1268   glClearDepthf (1.0f);
1269 #endif
1270
1271   if (NamedStatus & OPENGL_NS_WHITEBACK)
1272   {
1273     // set background to white
1274     glClearColor (1.0f, 1.0f, 1.0f, 1.0f);
1275   }
1276   else
1277   {
1278     glClearColor (myBgColor.rgb[0], myBgColor.rgb[1], myBgColor.rgb[2], 0.0f);
1279   }
1280
1281   glClear (toClear);
1282
1283   Handle(OpenGl_Workspace) aWS (this);
1284   myView->Render (myPrintContext, aWS, theReadDrawFbo, theProjection, theCView, Standard_False);
1285 }
1286
1287 // =======================================================================
1288 // function : copyBackToFront
1289 // purpose  :
1290 // =======================================================================
1291 void OpenGl_Workspace::copyBackToFront()
1292 {
1293 #if !defined(GL_ES_VERSION_2_0)
1294
1295   OpenGl_Mat4 aProjectMat;
1296   Graphic3d_TransformUtils::Ortho2D (aProjectMat,
1297     0.f, static_cast<GLfloat> (myWidth), 0.f, static_cast<GLfloat> (myHeight));
1298
1299   myGlContext->WorldViewState.Push();
1300   myGlContext->ProjectionState.Push();
1301
1302   myGlContext->WorldViewState.SetIdentity();
1303   myGlContext->ProjectionState.SetCurrent (aProjectMat);
1304
1305   myGlContext->ApplyProjectionMatrix();
1306   myGlContext->ApplyWorldViewMatrix();
1307
1308   DisableFeatures();
1309
1310   switch (myGlContext->DrawBuffer())
1311   {
1312     case GL_BACK_LEFT:
1313     {
1314       myGlContext->SetReadBuffer (GL_BACK_LEFT);
1315       myGlContext->SetDrawBuffer (GL_FRONT_LEFT);
1316       break;
1317     }
1318     case GL_BACK_RIGHT:
1319     {
1320       myGlContext->SetReadBuffer (GL_BACK_RIGHT);
1321       myGlContext->SetDrawBuffer (GL_FRONT_RIGHT);
1322       break;
1323     }
1324     default:
1325     {
1326       myGlContext->SetReadBuffer (GL_BACK);
1327       myGlContext->SetDrawBuffer (GL_FRONT);
1328       break;
1329     }
1330   }
1331
1332   glRasterPos2i (0, 0);
1333   glCopyPixels  (0, 0, myWidth + 1, myHeight + 1, GL_COLOR);
1334   //glCopyPixels  (0, 0, myWidth + 1, myHeight + 1, GL_DEPTH);
1335
1336   EnableFeatures();
1337
1338   myGlContext->WorldViewState.Pop();
1339   myGlContext->ProjectionState.Pop();
1340   myGlContext->ApplyProjectionMatrix();
1341
1342   // read/write from front buffer now
1343   myGlContext->SetReadBuffer (myGlContext->DrawBuffer());
1344 #endif
1345   myIsImmediateDrawn = Standard_False;
1346 }
1347
1348 // =======================================================================
1349 // function : DisplayCallback
1350 // purpose  :
1351 // =======================================================================
1352 void OpenGl_Workspace::DisplayCallback (const Graphic3d_CView& theCView,
1353                                         Standard_Integer       theReason)
1354 {
1355   if (theCView.GDisplayCB == NULL)
1356   {
1357     return;
1358   }
1359
1360   Aspect_GraphicCallbackStruct aCallData;
1361   aCallData.reason    = theReason;
1362   aCallData.glContext = myGlContext;
1363   aCallData.wsID      = theCView.WsId;
1364   aCallData.viewID    = theCView.ViewId;
1365   aCallData.IsCoreProfile = (myGlContext->core11 == NULL);
1366   theCView.GDisplayCB (theCView.DefWindow.XWindow, theCView.GClientData, &aCallData);
1367 }
1368
1369 // =======================================================================
1370 // function : RedrawImmediate
1371 // purpose  :
1372 // =======================================================================
1373 void OpenGl_Workspace::RedrawImmediate (const Graphic3d_CView& theCView)
1374 {
1375   if (!myTransientDrawToFront
1376    || !myBackBufferRestored
1377    || (myGlContext->caps->buffersNoSwap && !myMainSceneFbos[0]->IsValid()))
1378   {
1379     Redraw (theCView);
1380     return;
1381   }
1382   else if (!Activate())
1383   {
1384     return;
1385   }
1386
1387   const Handle(Graphic3d_Camera)& aCamera      = myView->Camera();
1388   Graphic3d_Camera::Projection    aProjectType = aCamera->ProjectionType();
1389   OpenGl_FrameBuffer* aFrameBuffer = (OpenGl_FrameBuffer* )theCView.ptrFBO;
1390   if ( aFrameBuffer == NULL
1391    && !myGlContext->DefaultFrameBuffer().IsNull()
1392    &&  myGlContext->DefaultFrameBuffer()->IsValid())
1393   {
1394     aFrameBuffer = myGlContext->DefaultFrameBuffer().operator->();
1395   }
1396
1397   const Graphic3d_StereoMode aStereoMode = theCView.RenderParams.StereoMode;
1398   if (aProjectType == Graphic3d_Camera::Projection_Stereo)
1399   {
1400     if (myMainSceneFbos[0]->IsValid()
1401     && !myMainSceneFbos[1]->IsValid())
1402     {
1403       aProjectType = Graphic3d_Camera::Projection_Perspective;
1404     }
1405   }
1406
1407   bool toSwap = false;
1408   if (aProjectType == Graphic3d_Camera::Projection_Stereo)
1409   {
1410     OpenGl_FrameBuffer* aMainFbos[2] =
1411     {
1412       myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL,
1413       myMainSceneFbos[1]->IsValid() ? myMainSceneFbos[1].operator->() : NULL
1414     };
1415     OpenGl_FrameBuffer* anImmFbos[2] =
1416     {
1417       myImmediateSceneFbos[0]->IsValid() ? myImmediateSceneFbos[0].operator->() : NULL,
1418       myImmediateSceneFbos[1]->IsValid() ? myImmediateSceneFbos[1].operator->() : NULL
1419     };
1420     if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip
1421      || aStereoMode == Graphic3d_StereoMode_QuadBuffer)
1422     {
1423       anImmFbos[0] = NULL;
1424       anImmFbos[1] = NULL;
1425     }
1426
1427     if (myGlContext->arbFBO != NULL)
1428     {
1429       myGlContext->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
1430     }
1431   #if !defined(GL_ES_VERSION_2_0)
1432     if (anImmFbos[0] == NULL)
1433     {
1434       myGlContext->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_LEFT : GL_BACK);
1435     }
1436   #endif
1437     toSwap = redrawImmediate (theCView,
1438                               aMainFbos[0],
1439                               Graphic3d_Camera::Projection_MonoLeftEye,
1440                               anImmFbos[0],
1441                               Standard_True) || toSwap;
1442     if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip
1443     &&  toSwap
1444     && !myGlContext->caps->buffersNoSwap)
1445     {
1446       myGlContext->SwapBuffers();
1447     }
1448
1449     if (myGlContext->arbFBO != NULL)
1450     {
1451       myGlContext->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
1452     }
1453   #if !defined(GL_ES_VERSION_2_0)
1454     if (anImmFbos[1] == NULL)
1455     {
1456       myGlContext->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_RIGHT : GL_BACK);
1457     }
1458   #endif
1459     toSwap = redrawImmediate (theCView,
1460                               aMainFbos[1],
1461                               Graphic3d_Camera::Projection_MonoRightEye,
1462                               anImmFbos[1],
1463                               Standard_True) || toSwap;
1464     if (anImmFbos[0] != NULL)
1465     {
1466       bindDefaultFbo (aFrameBuffer);
1467       drawStereoPair (theCView);
1468     }
1469   }
1470   else
1471   {
1472     OpenGl_FrameBuffer* aMainFbo = myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL;
1473     OpenGl_FrameBuffer* anImmFbo = aFrameBuffer;
1474     if (!myGlContext->caps->useSystemBuffer && myImmediateSceneFbos[0]->IsValid())
1475     {
1476       anImmFbo = myImmediateSceneFbos[0].operator->();
1477     }
1478   #if !defined(GL_ES_VERSION_2_0)
1479     if (aMainFbo == NULL)
1480     {
1481       myGlContext->SetReadDrawBuffer (GL_BACK);
1482     }
1483   #endif
1484     toSwap = redrawImmediate (theCView,
1485                               aMainFbo,
1486                               aProjectType,
1487                               anImmFbo,
1488                               Standard_True) || toSwap;
1489     if (anImmFbo != NULL
1490      && anImmFbo != aFrameBuffer)
1491     {
1492       blitBuffers (anImmFbo, aFrameBuffer, myToFlipOutput);
1493     }
1494   }
1495
1496   // bind default FBO
1497   bindDefaultFbo();
1498
1499   if (toSwap
1500   && !myGlContext->caps->buffersNoSwap)
1501   {
1502     myGlContext->SwapBuffers();
1503   }
1504   else
1505   {
1506     myGlContext->core11fwd->glFlush();
1507   }
1508 }
1509
1510 // =======================================================================
1511 // function : redrawImmediate
1512 // purpose  :
1513 // =======================================================================
1514 bool OpenGl_Workspace::redrawImmediate (const Graphic3d_CView& theCView,
1515                                         OpenGl_FrameBuffer*    theReadFbo,
1516                                         const Graphic3d_Camera::Projection theProjection,
1517                                         OpenGl_FrameBuffer*    theDrawFbo,
1518                                         const Standard_Boolean theIsPartialUpdate)
1519 {
1520   GLboolean toCopyBackToFront = GL_FALSE;
1521   if (!myTransientDrawToFront)
1522   {
1523     myBackBufferRestored = Standard_False;
1524   }
1525   else if (theReadFbo != NULL
1526         && theReadFbo->IsValid()
1527         && myGlContext->IsRender())
1528   {
1529     if (!blitBuffers (theReadFbo, theDrawFbo))
1530     {
1531       return true;
1532     }
1533   }
1534   else if (theDrawFbo == NULL)
1535   {
1536   #if !defined(GL_ES_VERSION_2_0)
1537     myGlContext->core11fwd->glGetBooleanv (GL_DOUBLEBUFFER, &toCopyBackToFront);
1538   #endif
1539     if (toCopyBackToFront)
1540     {
1541       if (!myView->HasImmediateStructures()
1542        && !theIsPartialUpdate)
1543       {
1544         // prefer Swap Buffers within Redraw in compatibility mode (without FBO)
1545         return true;
1546       }
1547       copyBackToFront();
1548     }
1549     else
1550     {
1551       myBackBufferRestored = Standard_False;
1552     }
1553   }
1554   else
1555   {
1556     myBackBufferRestored = Standard_False;
1557   }
1558   myIsImmediateDrawn = Standard_True;
1559
1560   Handle(OpenGl_Workspace) aWS (this);
1561
1562   myUseZBuffer    = Standard_True;
1563   myUseDepthWrite = Standard_True;
1564   glDepthFunc (GL_LEQUAL);
1565   glDepthMask (GL_TRUE);
1566   glEnable (GL_DEPTH_TEST);
1567 #if !defined(GL_ES_VERSION_2_0)
1568   glClearDepth (1.0);
1569 #else
1570   glClearDepthf (1.0f);
1571 #endif
1572
1573   myView->Render (myPrintContext, aWS, theDrawFbo, theProjection,
1574                   theCView, Standard_True);
1575
1576   return !toCopyBackToFront;
1577 }
1578
1579
1580 // =======================================================================
1581 // function : CanRender
1582 // purpose  :
1583 // =======================================================================
1584 Standard_Boolean OpenGl_RaytraceFilter::CanRender (const OpenGl_Element* theElement)
1585 {
1586   Standard_Boolean aPrevFilterResult = Standard_True;
1587   if (!myPrevRenderFilter.IsNull())
1588   {
1589     aPrevFilterResult = myPrevRenderFilter->CanRender (theElement);
1590   }
1591   return aPrevFilterResult &&
1592     !OpenGl_Raytrace::IsRaytracedElement (theElement);
1593 }