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