0026165: Visualization, TKOpenGl - fix FBO blitting on some mobile devices
[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_False),
157   myUseDepthTest (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
306 // =======================================================================
307 // function : DisableTexture
308 // purpose  :
309 // =======================================================================
310 Handle(OpenGl_Texture) OpenGl_Workspace::DisableTexture()
311 {
312   if (myTextureBound.IsNull())
313   {
314     return myTextureBound;
315   }
316
317   const Handle(OpenGl_Sampler)& aSampler = myGlContext->TextureSampler();
318   if (!aSampler.IsNull())
319   {
320     aSampler->Unbind (*myGlContext);
321   }
322
323 #if !defined(GL_ES_VERSION_2_0)
324   // reset texture matrix because some code may expect it is identity
325   if (myGlContext->core11 != NULL)
326   {
327     GLint aMatrixMode = GL_TEXTURE;
328     glGetIntegerv (GL_MATRIX_MODE, &aMatrixMode);
329     glMatrixMode (GL_TEXTURE);
330     glLoadIdentity();
331     glMatrixMode (aMatrixMode);
332   }
333 #endif
334
335   myTextureBound->Unbind (myGlContext);
336   switch (myTextureBound->GetTarget())
337   {
338   #if !defined(GL_ES_VERSION_2_0)
339     case GL_TEXTURE_1D:
340     {
341       if (myGlContext->core11 != NULL)
342       {
343         if (myTextureBound->GetParams()->GenMode() != GL_NONE)
344         {
345           glDisable (GL_TEXTURE_GEN_S);
346         }
347         glDisable (GL_TEXTURE_1D);
348       }
349       break;
350     }
351   #endif
352     case GL_TEXTURE_2D:
353     {
354     #if !defined(GL_ES_VERSION_2_0)
355       if (myGlContext->core11 != NULL)
356       {
357         if (myTextureBound->GetParams()->GenMode() != GL_NONE)
358         {
359           glDisable (GL_TEXTURE_GEN_S);
360           glDisable (GL_TEXTURE_GEN_T);
361           if (myTextureBound->GetParams()->GenMode() == Graphic3d_TOTM_SPRITE)
362           {
363             glDisable (GL_POINT_SPRITE);
364           }
365         }
366         glDisable (GL_TEXTURE_2D);
367       }
368     #endif
369       break;
370     }
371     default: break;
372   }
373
374   Handle(OpenGl_Texture) aPrevTexture = myTextureBound;
375   myTextureBound.Nullify();
376   return aPrevTexture;
377 }
378
379 // =======================================================================
380 // function : setTextureParams
381 // purpose  :
382 // =======================================================================
383 void OpenGl_Workspace::setTextureParams (Handle(OpenGl_Texture)&                theTexture,
384                                          const Handle(Graphic3d_TextureParams)& theParams)
385 {
386   const Handle(Graphic3d_TextureParams)& aParams = theParams.IsNull() ? theTexture->GetParams() : theParams;
387   if (aParams.IsNull())
388   {
389     return;
390   }
391
392 #if !defined(GL_ES_VERSION_2_0)
393   GLint aMatrixMode = GL_TEXTURE;
394   if (myGlContext->core11 != NULL)
395   {
396     glGetIntegerv (GL_MATRIX_MODE, &aMatrixMode);
397
398     // setup texture matrix
399     glMatrixMode (GL_TEXTURE);
400     OpenGl_Mat4 aTextureMat;
401     const Graphic3d_Vec2& aScale = aParams->Scale();
402     const Graphic3d_Vec2& aTrans = aParams->Translation();
403     OpenGl_Utils::Scale     (aTextureMat,  aScale.x(),  aScale.y(), 1.0f);
404     OpenGl_Utils::Translate (aTextureMat, -aTrans.x(), -aTrans.y(), 0.0f);
405     OpenGl_Utils::Rotate    (aTextureMat, -aParams->Rotation(), 0.0f, 0.0f, 1.0f);
406     glLoadMatrixf (aTextureMat);
407
408     GLint anEnvMode = GL_MODULATE; // lighting mode
409     if (!aParams->IsModulate())
410     {
411       anEnvMode = GL_DECAL;
412       if (theTexture->GetFormat() == GL_ALPHA
413        || theTexture->GetFormat() == GL_LUMINANCE)
414       {
415         anEnvMode = GL_REPLACE;
416       }
417     }
418
419     // setup generation of texture coordinates
420     switch (aParams->GenMode())
421     {
422       case Graphic3d_TOTM_OBJECT:
423       {
424         glTexGeni  (GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
425         glTexGenfv (GL_S, GL_OBJECT_PLANE,     aParams->GenPlaneS().GetData());
426         if (theTexture->GetTarget() != GL_TEXTURE_1D)
427         {
428           glTexGeni  (GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
429           glTexGenfv (GL_T, GL_OBJECT_PLANE,     aParams->GenPlaneT().GetData());
430         }
431         break;
432       }
433       case Graphic3d_TOTM_SPHERE:
434       {
435         glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
436         if (theTexture->GetTarget() != GL_TEXTURE_1D)
437         {
438           glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
439         }
440         break;
441       }
442       case Graphic3d_TOTM_EYE:
443       {
444         myGlContext->WorldViewState.Push();
445
446         myGlContext->WorldViewState.SetIdentity();
447         myGlContext->ApplyWorldViewMatrix();
448
449         glTexGeni  (GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
450         glTexGenfv (GL_S, GL_EYE_PLANE,        aParams->GenPlaneS().GetData());
451
452         if (theTexture->GetTarget() != GL_TEXTURE_1D)
453         {
454           glTexGeni  (GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
455           glTexGenfv (GL_T, GL_EYE_PLANE,        aParams->GenPlaneT().GetData());
456         }
457
458         myGlContext->WorldViewState.Pop();
459
460         break;
461       }
462       case Graphic3d_TOTM_SPRITE:
463       {
464         if (GetGlContext()->core20fwd != NULL)
465         {
466           glEnable  (GL_POINT_SPRITE);
467           glTexEnvi (GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE);
468           anEnvMode = GL_REPLACE;
469           GetGlContext()->core15->glPointParameteri (GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT);
470         }
471         break;
472       }
473       case Graphic3d_TOTM_MANUAL:
474       default: break;
475     }
476
477     // setup lighting
478     glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, anEnvMode);
479   }
480 #endif
481
482   // get active sampler object to override default texture parameters
483   const Handle(OpenGl_Sampler)& aSampler = myGlContext->TextureSampler();
484
485   // setup texture filtering and wrapping
486   //if (theTexture->GetParams() != theParams)
487   const GLenum aFilter   = (aParams->Filter() == Graphic3d_TOTF_NEAREST) ? GL_NEAREST : GL_LINEAR;
488   const GLenum aWrapMode = aParams->IsRepeat() ? GL_REPEAT : myGlContext->TextureWrapClamp();
489   switch (theTexture->GetTarget())
490   {
491   #if !defined(GL_ES_VERSION_2_0)
492     case GL_TEXTURE_1D:
493     {
494       if (aSampler.IsNull() || !aSampler->IsValid())
495       {
496         glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, aFilter);
497         glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, aFilter);
498         glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_S,     aWrapMode);
499       }
500       else
501       {
502         aSampler->SetParameter (*myGlContext, GL_TEXTURE_MAG_FILTER, aFilter);
503         aSampler->SetParameter (*myGlContext, GL_TEXTURE_MIN_FILTER, aFilter);
504         aSampler->SetParameter (*myGlContext, GL_TEXTURE_WRAP_S,     aWrapMode);
505       }
506
507       break;
508     }
509   #endif
510     case GL_TEXTURE_2D:
511     {
512       GLenum aFilterMin = aFilter;
513       if (theTexture->HasMipmaps())
514       {
515         aFilterMin = GL_NEAREST_MIPMAP_NEAREST;
516         if (aParams->Filter() == Graphic3d_TOTF_BILINEAR)
517         {
518           aFilterMin = GL_LINEAR_MIPMAP_NEAREST;
519         }
520         else if (aParams->Filter() == Graphic3d_TOTF_TRILINEAR)
521         {
522           aFilterMin = GL_LINEAR_MIPMAP_LINEAR;
523         }
524
525         if (myGlContext->extAnis)
526         {
527           // setup degree of anisotropy filter
528           const GLint aMaxDegree = myGlContext->MaxDegreeOfAnisotropy();
529           GLint aDegree;
530           switch (aParams->AnisoFilter())
531           {
532             case Graphic3d_LOTA_QUALITY:
533             {
534               aDegree = aMaxDegree;
535               break;
536             }
537             case Graphic3d_LOTA_MIDDLE:
538             {
539               aDegree = (aMaxDegree <= 4) ? 2 : (aMaxDegree / 2);
540               break;
541             }
542             case Graphic3d_LOTA_FAST:
543             {
544               aDegree = 2;
545               break;
546             }
547             case Graphic3d_LOTA_OFF:
548             default:
549             {
550               aDegree = 1;
551               break;
552             }
553           }
554
555           if (aSampler.IsNull() || !aSampler->IsValid())
556           {
557             glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, aDegree);
558           }
559           else
560           {
561             aSampler->SetParameter (*myGlContext, GL_TEXTURE_MAX_ANISOTROPY_EXT, aDegree);
562           }
563         }
564       }
565
566       if (aSampler.IsNull() || !aSampler->IsValid())
567       {
568         glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, aFilterMin);
569         glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, aFilter);
570         glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,     aWrapMode);
571         glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,     aWrapMode);
572       }
573       else
574       {
575         aSampler->SetParameter (*myGlContext, GL_TEXTURE_MIN_FILTER, aFilterMin);
576         aSampler->SetParameter (*myGlContext, GL_TEXTURE_MAG_FILTER, aFilter);
577         aSampler->SetParameter (*myGlContext, GL_TEXTURE_WRAP_S,     aWrapMode);
578         aSampler->SetParameter (*myGlContext, GL_TEXTURE_WRAP_T,     aWrapMode);
579       }
580
581       break;
582     }
583     default: break;
584   }
585
586   switch (theTexture->GetTarget())
587   {
588   #if !defined(GL_ES_VERSION_2_0)
589     case GL_TEXTURE_1D:
590     {
591       if (myGlContext->core11 != NULL)
592       {
593         if (aParams->GenMode() != Graphic3d_TOTM_MANUAL)
594         {
595           glEnable (GL_TEXTURE_GEN_S);
596         }
597         glEnable (GL_TEXTURE_1D);
598       }
599       break;
600     }
601   #endif
602     case GL_TEXTURE_2D:
603     {
604     #if !defined(GL_ES_VERSION_2_0)
605       if (myGlContext->core11 != NULL)
606       {
607         if (aParams->GenMode() != Graphic3d_TOTM_MANUAL)
608         {
609           glEnable (GL_TEXTURE_GEN_S);
610           glEnable (GL_TEXTURE_GEN_T);
611         }
612         glEnable (GL_TEXTURE_2D);
613       }
614     #endif
615       break;
616     }
617     default: break;
618   }
619
620 #if !defined(GL_ES_VERSION_2_0)
621   if (myGlContext->core11 != NULL)
622   {
623     glMatrixMode (aMatrixMode); // turn back active matrix
624   }
625 #endif
626   theTexture->SetParams (aParams);
627 }
628
629 // =======================================================================
630 // function : EnableTexture
631 // purpose  :
632 // =======================================================================
633 Handle(OpenGl_Texture) OpenGl_Workspace::EnableTexture (const Handle(OpenGl_Texture)&          theTexture,
634                                                         const Handle(Graphic3d_TextureParams)& theParams)
635 {
636   if (theTexture.IsNull() || !theTexture->IsValid())
637   {
638     return DisableTexture();
639   }
640
641   if (myTextureBound == theTexture
642    && (theParams.IsNull() || theParams == theTexture->GetParams()))
643   {
644     // already bound
645     return myTextureBound;
646   }
647
648   Handle(OpenGl_Texture) aPrevTexture = DisableTexture();
649   myTextureBound = theTexture;
650   myTextureBound->Bind (myGlContext);
651   setTextureParams (myTextureBound, theParams);
652
653   // If custom sampler object is available it will be
654   // used for overriding default texture parameters
655   const Handle(OpenGl_Sampler)& aSampler = myGlContext->TextureSampler();
656
657   if (!aSampler.IsNull() && aSampler->IsValid())
658   {
659     aSampler->Bind (*myGlContext);
660   }
661
662   return aPrevTexture;
663 }
664
665 // =======================================================================
666 // function : bindDefaultFbo
667 // purpose  :
668 // =======================================================================
669 void OpenGl_Workspace::bindDefaultFbo (OpenGl_FrameBuffer* theCustomFbo)
670 {
671   OpenGl_FrameBuffer* anFbo = (theCustomFbo != NULL && theCustomFbo->IsValid())
672                             ?  theCustomFbo
673                             : (!myGlContext->DefaultFrameBuffer().IsNull()
674                              && myGlContext->DefaultFrameBuffer()->IsValid()
675                               ? myGlContext->DefaultFrameBuffer().operator->()
676                               : NULL);
677   if (anFbo != NULL)
678   {
679     anFbo->BindBuffer (myGlContext);
680   }
681   else
682   {
683   #if !defined(GL_ES_VERSION_2_0)
684     myGlContext->SetReadDrawBuffer (GL_BACK);
685   #else
686     if (myGlContext->arbFBO != NULL)
687     {
688       myGlContext->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
689     }
690   #endif
691   }
692   myGlContext->core11fwd->glViewport (0, 0, myWidth, myHeight);
693 }
694
695 // =======================================================================
696 // function : blitBuffers
697 // purpose  :
698 // =======================================================================
699 bool OpenGl_Workspace::blitBuffers (OpenGl_FrameBuffer* theReadFbo,
700                                     OpenGl_FrameBuffer* theDrawFbo)
701 {
702   if (theReadFbo == NULL)
703   {
704     return false;
705   }
706
707   // clear destination before blitting
708   if (theDrawFbo != NULL
709   &&  theDrawFbo->IsValid())
710   {
711     theDrawFbo->BindBuffer (myGlContext);
712   }
713   else
714   {
715     myGlContext->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
716   }
717 #if !defined(GL_ES_VERSION_2_0)
718   myGlContext->core20fwd->glClearDepth  (1.0);
719 #else
720   myGlContext->core20fwd->glClearDepthf (1.0f);
721 #endif
722   myGlContext->core20fwd->glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
723
724 /*#if !defined(GL_ES_VERSION_2_0)
725   if (myGlContext->arbFBOBlit != NULL)
726   {
727     theReadFbo->BindReadBuffer (myGlContext);
728     if (theDrawFbo != NULL
729      && theDrawFbo->IsValid())
730     {
731       theDrawFbo->BindDrawBuffer (myGlContext);
732     }
733     else
734     {
735       myGlContext->arbFBO->glBindFramebuffer (GL_DRAW_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
736     }
737     // we don't copy stencil buffer here... does it matter for performance?
738     myGlContext->arbFBOBlit->glBlitFramebuffer (0, 0, theReadFbo->GetVPSizeX(), theReadFbo->GetVPSizeY(),
739                                                 0, 0, theReadFbo->GetVPSizeX(), theReadFbo->GetVPSizeY(),
740                                                 GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST);
741
742     if (theDrawFbo != NULL
743       && theDrawFbo->IsValid())
744     {
745       theDrawFbo->BindBuffer (myGlContext);
746     }
747     else
748     {
749       myGlContext->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
750     }
751   }
752   else
753 #endif*/
754   {
755     myGlContext->core20fwd->glDepthFunc (GL_ALWAYS);
756     myGlContext->core20fwd->glDepthMask (GL_TRUE);
757     myGlContext->core20fwd->glEnable (GL_DEPTH_TEST);
758
759     DisableTexture();
760     if (!myFullScreenQuad.IsValid())
761     {
762       OpenGl_Vec4 aQuad[4] =
763       {
764         OpenGl_Vec4( 1.0f, -1.0f, 1.0f, 0.0f),
765         OpenGl_Vec4( 1.0f,  1.0f, 1.0f, 1.0f),
766         OpenGl_Vec4(-1.0f, -1.0f, 0.0f, 0.0f),
767         OpenGl_Vec4(-1.0f,  1.0f, 0.0f, 1.0f)
768       };
769       myFullScreenQuad.Init (myGlContext, 4, 4, aQuad[0].GetData());
770     }
771
772     const Handle(OpenGl_ShaderManager)& aManager = myGlContext->ShaderManager();
773     if (myFullScreenQuad.IsValid()
774      && aManager->BindFboBlitProgram())
775     {
776       theReadFbo->ColorTexture()       ->Bind   (myGlContext, GL_TEXTURE0 + 0);
777       theReadFbo->DepthStencilTexture()->Bind   (myGlContext, GL_TEXTURE0 + 1);
778       myFullScreenQuad.BindVertexAttrib (myGlContext, Graphic3d_TOA_POS);
779
780       myGlContext->core20fwd->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
781
782       myFullScreenQuad.UnbindVertexAttrib (myGlContext, Graphic3d_TOA_POS);
783       theReadFbo->DepthStencilTexture()->Unbind (myGlContext, GL_TEXTURE0 + 1);
784       theReadFbo->ColorTexture()       ->Unbind (myGlContext, GL_TEXTURE0 + 0);
785     }
786     else
787     {
788       TCollection_ExtendedString aMsg = TCollection_ExtendedString()
789         + "Error! FBO blitting has failed";
790       myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
791                                 GL_DEBUG_TYPE_ERROR_ARB,
792                                 0,
793                                 GL_DEBUG_SEVERITY_HIGH_ARB,
794                                 aMsg);
795       myHasFboBlit = Standard_False;
796       theReadFbo->Release (myGlContext.operator->());
797       return true;
798     }
799   }
800   return true;
801 }
802
803 // =======================================================================
804 // function : drawStereoPair
805 // purpose  :
806 // =======================================================================
807 void OpenGl_Workspace::drawStereoPair()
808 {
809   OpenGl_FrameBuffer* aPair[2] =
810   {
811     myImmediateSceneFbos[0]->IsValid() ? myImmediateSceneFbos[0].operator->() : NULL,
812     myImmediateSceneFbos[1]->IsValid() ? myImmediateSceneFbos[1].operator->() : NULL
813   };
814   if (aPair[0] == NULL
815    || aPair[1] == NULL)
816   {
817     aPair[0] = myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL;
818     aPair[1] = myMainSceneFbos[1]->IsValid() ? myMainSceneFbos[1].operator->() : NULL;
819   }
820
821   if (aPair[0] == NULL
822    || aPair[1] == NULL)
823   {
824     return;
825   }
826
827   myGlContext->core20fwd->glDepthFunc (GL_ALWAYS);
828   myGlContext->core20fwd->glDepthMask (GL_TRUE);
829   myGlContext->core20fwd->glEnable (GL_DEPTH_TEST);
830
831   DisableTexture();
832   if (!myFullScreenQuad.IsValid())
833   {
834     OpenGl_Vec4 aQuad[4] =
835     {
836       OpenGl_Vec4( 1.0f, -1.0f, 1.0f, 0.0f),
837       OpenGl_Vec4( 1.0f,  1.0f, 1.0f, 1.0f),
838       OpenGl_Vec4(-1.0f, -1.0f, 0.0f, 0.0f),
839       OpenGl_Vec4(-1.0f,  1.0f, 0.0f, 1.0f)
840     };
841     myFullScreenQuad.Init (myGlContext, 4, 4, aQuad[0].GetData());
842   }
843
844   const Handle(OpenGl_ShaderManager)& aManager = myGlContext->ShaderManager();
845   if (myFullScreenQuad.IsValid()
846    && aManager->BindAnaglyphProgram())
847   {
848     aPair[0]->ColorTexture()->Bind (myGlContext, GL_TEXTURE0 + 0);
849     aPair[1]->ColorTexture()->Bind (myGlContext, GL_TEXTURE0 + 1);
850     myFullScreenQuad.BindVertexAttrib (myGlContext, 0);
851
852     myGlContext->core20fwd->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
853
854     myFullScreenQuad.UnbindVertexAttrib (myGlContext, 0);
855     aPair[1]->ColorTexture()->Unbind (myGlContext, GL_TEXTURE0 + 1);
856     aPair[0]->ColorTexture()->Unbind (myGlContext, GL_TEXTURE0 + 0);
857   }
858   else
859   {
860     TCollection_ExtendedString aMsg = TCollection_ExtendedString()
861       + "Error! Anaglyph has failed";
862     myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
863                               GL_DEBUG_TYPE_ERROR_ARB,
864                               0,
865                               GL_DEBUG_SEVERITY_HIGH_ARB,
866                               aMsg);
867   }
868 }
869
870 // =======================================================================
871 // function : Redraw
872 // purpose  :
873 // =======================================================================
874 void OpenGl_Workspace::Redraw (const Graphic3d_CView& theCView,
875                                const Aspect_CLayer2d& theCUnderLayer,
876                                const Aspect_CLayer2d& theCOverLayer)
877 {
878   if (!Activate())
879   {
880     return;
881   }
882
883   ++myFrameCounter;
884   myIsCullingEnabled = theCView.IsCullingEnabled;
885
886   // release pending GL resources
887   myGlContext->ReleaseDelayed();
888
889   // fetch OpenGl context state
890   myGlContext->FetchState();
891
892   OpenGl_FrameBuffer* aFrameBuffer = (OpenGl_FrameBuffer* )theCView.ptrFBO;
893   bool toSwap = myGlContext->IsRender()
894             && !myGlContext->caps->buffersNoSwap
895             &&  aFrameBuffer == NULL;
896
897   Standard_Integer aSizeX = aFrameBuffer != NULL ? aFrameBuffer->GetVPSizeX() : myWidth;
898   Standard_Integer aSizeY = aFrameBuffer != NULL ? aFrameBuffer->GetVPSizeY() : myHeight;
899
900   if ( aFrameBuffer == NULL
901    && !myGlContext->DefaultFrameBuffer().IsNull()
902    &&  myGlContext->DefaultFrameBuffer()->IsValid())
903   {
904     aFrameBuffer = myGlContext->DefaultFrameBuffer().operator->();
905   }
906
907   if (myHasFboBlit
908    && myTransientDrawToFront)
909   {
910     if (myMainSceneFbos[0]->GetVPSizeX() != aSizeX
911      || myMainSceneFbos[0]->GetVPSizeY() != aSizeY)
912     {
913       // prepare FBOs containing main scene
914       // for further blitting and rendering immediate presentations on top
915       if (myGlContext->core20fwd != NULL)
916       {
917         myMainSceneFbos[0]->Init (myGlContext, aSizeX, aSizeY);
918       }
919     }
920   }
921   else
922   {
923     myMainSceneFbos     [0]->Release (myGlContext.operator->());
924     myMainSceneFbos     [1]->Release (myGlContext.operator->());
925     myImmediateSceneFbos[0]->Release (myGlContext.operator->());
926     myImmediateSceneFbos[1]->Release (myGlContext.operator->());
927     myMainSceneFbos     [0]->ChangeViewport (0, 0);
928     myMainSceneFbos     [1]->ChangeViewport (0, 0);
929     myImmediateSceneFbos[0]->ChangeViewport (0, 0);
930     myImmediateSceneFbos[1]->ChangeViewport (0, 0);
931   }
932
933   // draw entire frame using normal OpenGL pipeline
934   const Handle(Graphic3d_Camera)& aCamera      = myView->Camera();
935   Graphic3d_Camera::Projection    aProjectType = aCamera->ProjectionType();
936   if (aProjectType == Graphic3d_Camera::Projection_Stereo)
937   {
938     if (aFrameBuffer != NULL
939     || !myGlContext->IsRender())
940     {
941       // implicitly switch to mono camera for image dump
942       aProjectType = Graphic3d_Camera::Projection_Perspective;
943     }
944     else if (myMainSceneFbos[0]->IsValid())
945     {
946       myMainSceneFbos[1]->InitLazy (myGlContext, aSizeX, aSizeY);
947       if (!myMainSceneFbos[1]->IsValid())
948       {
949         // no enough memory?
950         aProjectType = Graphic3d_Camera::Projection_Perspective;
951       }
952       else if (!myGlContext->HasStereoBuffers())
953       {
954         myImmediateSceneFbos[0]->InitLazy (myGlContext, aSizeX, aSizeY);
955         myImmediateSceneFbos[1]->InitLazy (myGlContext, aSizeX, aSizeY);
956         if (!myImmediateSceneFbos[0]->IsValid()
957          || !myImmediateSceneFbos[1]->IsValid())
958         {
959           aProjectType = Graphic3d_Camera::Projection_Perspective;
960         }
961       }
962     }
963   }
964
965   if (aProjectType == Graphic3d_Camera::Projection_Stereo)
966   {
967     OpenGl_FrameBuffer* aMainFbos[2] =
968     {
969       myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL,
970       myMainSceneFbos[1]->IsValid() ? myMainSceneFbos[1].operator->() : NULL
971     };
972     OpenGl_FrameBuffer* anImmFbos[2] =
973     {
974       myImmediateSceneFbos[0]->IsValid() ? myImmediateSceneFbos[0].operator->() : NULL,
975       myImmediateSceneFbos[1]->IsValid() ? myImmediateSceneFbos[1].operator->() : NULL
976     };
977
978   #if !defined(GL_ES_VERSION_2_0)
979     myGlContext->SetReadDrawBuffer (GL_BACK_LEFT);
980   #endif
981     redraw1 (theCView, theCUnderLayer, theCOverLayer,
982              aMainFbos[0], Graphic3d_Camera::Projection_MonoLeftEye);
983     myBackBufferRestored = Standard_True;
984     myIsImmediateDrawn   = Standard_False;
985   #if !defined(GL_ES_VERSION_2_0)
986     myGlContext->SetReadDrawBuffer (GL_BACK_LEFT);
987   #endif
988     if (!redrawImmediate (theCView, theCOverLayer, theCUnderLayer, aMainFbos[0], aProjectType, anImmFbos[0]))
989     {
990       toSwap = false;
991     }
992
993   #if !defined(GL_ES_VERSION_2_0)
994     myGlContext->SetReadDrawBuffer (GL_BACK_RIGHT);
995   #endif
996     redraw1 (theCView, theCUnderLayer, theCOverLayer,
997              aMainFbos[1], Graphic3d_Camera::Projection_MonoRightEye);
998     myBackBufferRestored = Standard_True;
999     myIsImmediateDrawn   = Standard_False;
1000     if (!redrawImmediate (theCView, theCOverLayer, theCUnderLayer, aMainFbos[1], aProjectType, anImmFbos[1]))
1001     {
1002       toSwap = false;
1003     }
1004
1005     if (anImmFbos[0] != NULL)
1006     {
1007       bindDefaultFbo (aFrameBuffer);
1008       drawStereoPair();
1009     }
1010   }
1011   else
1012   {
1013     OpenGl_FrameBuffer* aMainFbo = myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL;
1014   #if !defined(GL_ES_VERSION_2_0)
1015     if (aMainFbo     == NULL
1016      && aFrameBuffer == NULL)
1017     {
1018       myGlContext->SetReadDrawBuffer (GL_BACK);
1019     }
1020   #endif
1021     redraw1 (theCView, theCUnderLayer, theCOverLayer,
1022              aMainFbo != NULL ? aMainFbo : aFrameBuffer, aProjectType);
1023     myBackBufferRestored = Standard_True;
1024     myIsImmediateDrawn   = Standard_False;
1025     if (!redrawImmediate (theCView, theCOverLayer, theCUnderLayer, aMainFbo, aProjectType, aFrameBuffer))
1026     {
1027       toSwap = false;
1028     }
1029   }
1030
1031 #if defined(_WIN32) && defined(HAVE_VIDEOCAPTURE)
1032   if (OpenGl_AVIWriter_AllowWriting (theCView.DefWindow.XWindow))
1033   {
1034     GLint params[4];
1035     glGetIntegerv (GL_VIEWPORT, params);
1036     int nWidth  = params[2] & ~0x7;
1037     int nHeight = params[3] & ~0x7;
1038
1039     const int nBitsPerPixel = 24;
1040     GLubyte* aDumpData = new GLubyte[nWidth * nHeight * nBitsPerPixel / 8];
1041
1042     glPixelStorei (GL_PACK_ALIGNMENT, 1);
1043     glReadPixels (0, 0, nWidth, nHeight, GL_BGR_EXT, GL_UNSIGNED_BYTE, aDumpData);
1044     OpenGl_AVIWriter_AVIWriter (aDumpData, nWidth, nHeight, nBitsPerPixel);
1045     delete[] aDumpData;
1046   }
1047 #endif
1048
1049   // bind default FBO
1050   bindDefaultFbo();
1051
1052   // Swap the buffers
1053   if (toSwap)
1054   {
1055     GetGlContext()->SwapBuffers();
1056     if (!myMainSceneFbos[0]->IsValid())
1057     {
1058       myBackBufferRestored = Standard_False;
1059     }
1060   }
1061   else
1062   {
1063     myGlContext->core11fwd->glFlush();
1064   }
1065
1066   // reset render mode state
1067   myGlContext->FetchState();
1068 }
1069
1070 // =======================================================================
1071 // function : redraw1
1072 // purpose  :
1073 // =======================================================================
1074 void OpenGl_Workspace::redraw1 (const Graphic3d_CView&               theCView,
1075                                 const Aspect_CLayer2d&               theCUnderLayer,
1076                                 const Aspect_CLayer2d&               theCOverLayer,
1077                                 OpenGl_FrameBuffer*                  theReadDrawFbo,
1078                                 const Graphic3d_Camera::Projection   theProjection)
1079 {
1080   if (myView.IsNull())
1081   {
1082     return;
1083   }
1084
1085   if (theReadDrawFbo != NULL)
1086   {
1087     theReadDrawFbo->BindBuffer    (myGlContext);
1088     theReadDrawFbo->SetupViewport (myGlContext);
1089   }
1090   else
1091   {
1092     myGlContext->core11fwd->glViewport (0, 0, myWidth, myHeight);
1093   }
1094
1095   // request reset of material
1096   NamedStatus |= OPENGL_NS_RESMAT;
1097
1098   GLbitfield toClear = GL_COLOR_BUFFER_BIT;
1099   if (myUseZBuffer)
1100   {
1101     glDepthFunc (GL_LEQUAL);
1102     glDepthMask (GL_TRUE);
1103     if (myUseDepthTest)
1104     {
1105       glEnable (GL_DEPTH_TEST);
1106     }
1107     else
1108     {
1109       glDisable (GL_DEPTH_TEST);
1110     }
1111
1112   #if !defined(GL_ES_VERSION_2_0)
1113     glClearDepth (1.0);
1114   #else
1115     glClearDepthf (1.0f);
1116   #endif
1117     toClear |= GL_DEPTH_BUFFER_BIT;
1118   }
1119   else
1120   {
1121     glDisable (GL_DEPTH_TEST);
1122   }
1123
1124   if (NamedStatus & OPENGL_NS_WHITEBACK)
1125   {
1126     // set background to white
1127     glClearColor (1.0f, 1.0f, 1.0f, 1.0f);
1128     toClear |= GL_DEPTH_BUFFER_BIT;
1129   }
1130   else
1131   {
1132     glClearColor (myBgColor.rgb[0], myBgColor.rgb[1], myBgColor.rgb[2], 0.0f);
1133   }
1134
1135   glClear (toClear);
1136
1137   Handle(OpenGl_Workspace) aWS (this);
1138   myView->Render (myPrintContext, aWS, theReadDrawFbo, theProjection, theCView, theCUnderLayer, theCOverLayer, Standard_False);
1139 }
1140
1141 // =======================================================================
1142 // function : copyBackToFront
1143 // purpose  :
1144 // =======================================================================
1145 void OpenGl_Workspace::copyBackToFront()
1146 {
1147 #if !defined(GL_ES_VERSION_2_0)
1148
1149   OpenGl_Mat4 aProjectMat;
1150   OpenGl_Utils::Ortho2D<Standard_ShortReal> (aProjectMat,
1151     0.f, static_cast<GLfloat> (myWidth), 0.f, static_cast<GLfloat> (myHeight));
1152
1153   myGlContext->WorldViewState.Push();
1154   myGlContext->ProjectionState.Push();
1155
1156   myGlContext->WorldViewState.SetIdentity();
1157   myGlContext->ProjectionState.SetCurrent (aProjectMat);
1158
1159   myGlContext->ApplyProjectionMatrix();
1160   myGlContext->ApplyWorldViewMatrix();
1161
1162   DisableFeatures();
1163
1164   switch (myGlContext->DrawBuffer())
1165   {
1166     case GL_BACK_LEFT:
1167     {
1168       myGlContext->SetReadBuffer (GL_BACK_LEFT);
1169       myGlContext->SetDrawBuffer (GL_FRONT_LEFT);
1170       break;
1171     }
1172     case GL_BACK_RIGHT:
1173     {
1174       myGlContext->SetReadBuffer (GL_BACK_RIGHT);
1175       myGlContext->SetDrawBuffer (GL_FRONT_RIGHT);
1176       break;
1177     }
1178     default:
1179     {
1180       myGlContext->SetReadBuffer (GL_BACK);
1181       myGlContext->SetDrawBuffer (GL_FRONT);
1182       break;
1183     }
1184   }
1185
1186   glRasterPos2i (0, 0);
1187   glCopyPixels  (0, 0, myWidth + 1, myHeight + 1, GL_COLOR);
1188   //glCopyPixels  (0, 0, myWidth + 1, myHeight + 1, GL_DEPTH);
1189
1190   EnableFeatures();
1191
1192   myGlContext->WorldViewState.Pop();
1193   myGlContext->ProjectionState.Pop();
1194   myGlContext->ApplyProjectionMatrix();
1195
1196   // read/write from front buffer now
1197   myGlContext->SetReadBuffer (myGlContext->DrawBuffer());
1198 #endif
1199   myIsImmediateDrawn = Standard_False;
1200 }
1201
1202 // =======================================================================
1203 // function : DisplayCallback
1204 // purpose  :
1205 // =======================================================================
1206 void OpenGl_Workspace::DisplayCallback (const Graphic3d_CView& theCView,
1207                                         Standard_Integer       theReason)
1208 {
1209   if (theCView.GDisplayCB == NULL)
1210   {
1211     return;
1212   }
1213
1214   Aspect_GraphicCallbackStruct aCallData;
1215   aCallData.reason    = theReason;
1216   aCallData.glContext = myGlContext;
1217   aCallData.wsID      = theCView.WsId;
1218   aCallData.viewID    = theCView.ViewId;
1219   aCallData.IsCoreProfile = (myGlContext->core11 == NULL);
1220   theCView.GDisplayCB (theCView.DefWindow.XWindow, theCView.GClientData, &aCallData);
1221 }
1222
1223 // =======================================================================
1224 // function : RedrawImmediate
1225 // purpose  :
1226 // =======================================================================
1227 void OpenGl_Workspace::RedrawImmediate (const Graphic3d_CView& theCView,
1228                                         const Aspect_CLayer2d& theCUnderLayer,
1229                                         const Aspect_CLayer2d& theCOverLayer)
1230 {
1231   const Handle(Graphic3d_Camera)& aCamera      = myView->Camera();
1232   Graphic3d_Camera::Projection    aProjectType = aCamera->ProjectionType();
1233   OpenGl_FrameBuffer* aFrameBuffer = (OpenGl_FrameBuffer* )theCView.ptrFBO;
1234   if ( aFrameBuffer == NULL
1235    && !myGlContext->DefaultFrameBuffer().IsNull()
1236    &&  myGlContext->DefaultFrameBuffer()->IsValid())
1237   {
1238     aFrameBuffer = myGlContext->DefaultFrameBuffer().operator->();
1239   }
1240
1241   if (aProjectType == Graphic3d_Camera::Projection_Stereo)
1242   {
1243     if (aFrameBuffer != NULL)
1244     {
1245       // implicitly switch to mono camera for image dump
1246       aProjectType = Graphic3d_Camera::Projection_Perspective;
1247     }
1248     else if (myMainSceneFbos[0]->IsValid()
1249          && !myMainSceneFbos[1]->IsValid())
1250     {
1251       aProjectType = Graphic3d_Camera::Projection_Perspective;
1252     }
1253   }
1254
1255   if (!myTransientDrawToFront
1256    || !myBackBufferRestored
1257    || (myGlContext->caps->buffersNoSwap && !myMainSceneFbos[0]->IsValid()))
1258   {
1259     Redraw (theCView, theCUnderLayer, theCOverLayer);
1260     return;
1261   }
1262   else if (!Activate())
1263   {
1264     return;
1265   }
1266
1267   bool toSwap = false;
1268   if (aProjectType == Graphic3d_Camera::Projection_Stereo)
1269   {
1270     OpenGl_FrameBuffer* aMainFbos[2] =
1271     {
1272       myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL,
1273       myMainSceneFbos[1]->IsValid() ? myMainSceneFbos[1].operator->() : NULL
1274     };
1275     OpenGl_FrameBuffer* anImmFbos[2] =
1276     {
1277       myImmediateSceneFbos[0]->IsValid() ? myImmediateSceneFbos[0].operator->() : NULL,
1278       myImmediateSceneFbos[1]->IsValid() ? myImmediateSceneFbos[1].operator->() : NULL
1279     };
1280
1281     if (myGlContext->arbFBO != NULL)
1282     {
1283       myGlContext->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
1284     }
1285   #if !defined(GL_ES_VERSION_2_0)
1286     if (anImmFbos[0] == NULL)
1287     {
1288       myGlContext->SetReadDrawBuffer (GL_BACK_LEFT);
1289     }
1290   #endif
1291     toSwap = redrawImmediate (theCView, theCUnderLayer, theCOverLayer,
1292                               aMainFbos[0],
1293                               Graphic3d_Camera::Projection_MonoLeftEye,
1294                               anImmFbos[0],
1295                               Standard_True) || toSwap;
1296
1297     if (myGlContext->arbFBO != NULL)
1298     {
1299       myGlContext->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
1300     }
1301   #if !defined(GL_ES_VERSION_2_0)
1302     if (anImmFbos[1] == NULL)
1303     {
1304       myGlContext->SetReadDrawBuffer (GL_BACK_RIGHT);
1305     }
1306   #endif
1307     toSwap = redrawImmediate (theCView, theCUnderLayer, theCOverLayer,
1308                               aMainFbos[1],
1309                               Graphic3d_Camera::Projection_MonoRightEye,
1310                               anImmFbos[1],
1311                               Standard_True) || toSwap;
1312     if (anImmFbos[0] != NULL)
1313     {
1314       bindDefaultFbo (aFrameBuffer);
1315       drawStereoPair();
1316     }
1317   }
1318   else
1319   {
1320     OpenGl_FrameBuffer* aMainFbo = myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL;
1321   #if !defined(GL_ES_VERSION_2_0)
1322     if (aMainFbo == NULL)
1323     {
1324       myGlContext->SetReadDrawBuffer (GL_BACK);
1325     }
1326   #endif
1327     toSwap = redrawImmediate (theCView, theCUnderLayer, theCOverLayer,
1328                               aMainFbo,
1329                               aProjectType,
1330                               aFrameBuffer,
1331                               Standard_True) || toSwap;
1332   }
1333
1334   // bind default FBO
1335   bindDefaultFbo();
1336
1337   if (toSwap
1338   && !myGlContext->caps->buffersNoSwap)
1339   {
1340     myGlContext->SwapBuffers();
1341   }
1342   else
1343   {
1344     myGlContext->core11fwd->glFlush();
1345   }
1346 }
1347
1348 // =======================================================================
1349 // function : redrawImmediate
1350 // purpose  :
1351 // =======================================================================
1352 bool OpenGl_Workspace::redrawImmediate (const Graphic3d_CView& theCView,
1353                                         const Aspect_CLayer2d& theCUnderLayer,
1354                                         const Aspect_CLayer2d& theCOverLayer,
1355                                         OpenGl_FrameBuffer*    theReadFbo,
1356                                         const Graphic3d_Camera::Projection theProjection,
1357                                         OpenGl_FrameBuffer*    theDrawFbo,
1358                                         const Standard_Boolean theIsPartialUpdate)
1359 {
1360   GLboolean toCopyBackToFront = GL_FALSE;
1361   if (!myTransientDrawToFront)
1362   {
1363     myBackBufferRestored = Standard_False;
1364   }
1365   else if (theReadFbo != NULL
1366         && theReadFbo->IsValid()
1367         && myGlContext->IsRender())
1368   {
1369     if (!blitBuffers (theReadFbo, theDrawFbo))
1370     {
1371       return true;
1372     }
1373   }
1374   else if (theDrawFbo == NULL)
1375   {
1376   #if !defined(GL_ES_VERSION_2_0)
1377     myGlContext->core11fwd->glGetBooleanv (GL_DOUBLEBUFFER, &toCopyBackToFront);
1378   #endif
1379     if (toCopyBackToFront)
1380     {
1381       if (!myView->HasImmediateStructures()
1382        && !theIsPartialUpdate)
1383       {
1384         // prefer Swap Buffers within Redraw in compatibility mode (without FBO)
1385         return true;
1386       }
1387       copyBackToFront();
1388     }
1389     else
1390     {
1391       myBackBufferRestored = Standard_False;
1392     }
1393   }
1394   else
1395   {
1396     myBackBufferRestored = Standard_False;
1397   }
1398   myIsImmediateDrawn = Standard_True;
1399
1400   Handle(OpenGl_Workspace) aWS (this);
1401
1402   if (myUseZBuffer)
1403   {
1404     glDepthFunc (GL_LEQUAL);
1405     glDepthMask (GL_TRUE);
1406     if (myUseDepthTest)
1407     {
1408       glEnable (GL_DEPTH_TEST);
1409     }
1410     else
1411     {
1412       glDisable (GL_DEPTH_TEST);
1413     }
1414
1415   #if !defined(GL_ES_VERSION_2_0)
1416     glClearDepth (1.0);
1417   #else
1418     glClearDepthf (1.0f);
1419   #endif
1420   }
1421   else
1422   {
1423     glDisable (GL_DEPTH_TEST);
1424   }
1425
1426   myView->Render (myPrintContext, aWS, theDrawFbo, theProjection,
1427                   theCView, theCUnderLayer, theCOverLayer, Standard_True);
1428   if (!myView->ImmediateStructures().IsEmpty())
1429   {
1430     glDisable (GL_DEPTH_TEST);
1431   }
1432   for (OpenGl_SequenceOfStructure::Iterator anIter (myView->ImmediateStructures());
1433        anIter.More(); anIter.Next())
1434   {
1435     const OpenGl_Structure* aStructure = anIter.Value();
1436     if (!aStructure->IsVisible())
1437     {
1438       continue;
1439     }
1440
1441     aStructure->Render (aWS);
1442   }
1443
1444   return !toCopyBackToFront;
1445 }
1446
1447 IMPLEMENT_STANDARD_HANDLE (OpenGl_RaytraceFilter, OpenGl_RenderFilter)
1448 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_RaytraceFilter, OpenGl_RenderFilter)
1449
1450 // =======================================================================
1451 // function : CanRender
1452 // purpose  :
1453 // =======================================================================
1454 Standard_Boolean OpenGl_RaytraceFilter::CanRender (const OpenGl_Element* theElement)
1455 {
1456   Standard_Boolean aPrevFilterResult = Standard_True;
1457   if (!myPrevRenderFilter.IsNull())
1458   {
1459     aPrevFilterResult = myPrevRenderFilter->CanRender (theElement);
1460   }
1461   return aPrevFilterResult &&
1462     !OpenGl_Raytrace::IsRaytracedElement (theElement);
1463 }