0025885: Visualization, ray tracing - Improve layer processing
[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   myResultFBO = new OpenGl_FrameBuffer();
180
181   if (!myGlContext->GetResource ("OpenGl_LineAttributes", myLineAttribs))
182   {
183     // share and register for release once the resource is no longer used
184     myLineAttribs = new OpenGl_LineAttributes();
185     myGlContext->ShareResource ("OpenGl_LineAttributes", myLineAttribs);
186     myLineAttribs->Init (myGlContext);
187   }
188
189   // General initialization of the context
190
191 #if !defined(GL_ES_VERSION_2_0)
192   if (myGlContext->core11 != NULL)
193   {
194     // Eviter d'avoir les faces mal orientees en noir.
195     // Pourrait etre utiliser pour detecter les problemes d'orientation
196     glLightModeli ((GLenum )GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
197
198     // Optimisation pour le Fog et l'antialiasing
199     glHint (GL_FOG_HINT,            GL_FASTEST);
200     glHint (GL_POINT_SMOOTH_HINT,   GL_FASTEST);
201   }
202
203   glHint (GL_LINE_SMOOTH_HINT,    GL_FASTEST);
204   glHint (GL_POLYGON_SMOOTH_HINT, GL_FASTEST);
205 #endif
206
207   // AA mode
208   const char* anAaEnv = ::getenv ("CALL_OPENGL_ANTIALIASING_MODE");
209   if (anAaEnv != NULL)
210   {
211     int v;
212     if (sscanf (anAaEnv, "%d", &v) > 0) myAntiAliasingMode = v;
213   }
214 }
215
216 // =======================================================================
217 // function : SetImmediateModeDrawToFront
218 // purpose  :
219 // =======================================================================
220 Standard_Boolean OpenGl_Workspace::SetImmediateModeDrawToFront (const Standard_Boolean theDrawToFrontBuffer)
221 {
222   const Standard_Boolean aPrevMode = myTransientDrawToFront;
223   myTransientDrawToFront = theDrawToFrontBuffer;
224   return aPrevMode;
225 }
226
227 // =======================================================================
228 // function : ~OpenGl_Workspace
229 // purpose  :
230 // =======================================================================
231 OpenGl_Workspace::~OpenGl_Workspace()
232 {
233   if (!myLineAttribs.IsNull())
234   {
235     myLineAttribs.Nullify();
236     myGlContext->ReleaseResource ("OpenGl_LineAttributes", Standard_True);
237   }
238
239   if (!myResultFBO.IsNull())
240   {
241     myResultFBO->Release (myGlContext.operator->());
242     myResultFBO.Nullify();
243   }
244   if (myFullScreenQuad.IsValid())
245   {
246     myFullScreenQuad.Release (myGlContext.operator->());
247   }
248 }
249
250 // =======================================================================
251 // function : Activate
252 // purpose  :
253 // =======================================================================
254 Standard_Boolean OpenGl_Workspace::Activate()
255 {
256   if (!OpenGl_Window::Activate())
257     return Standard_False;
258
259   ViewMatrix_applied      = &myDefaultMatrix;
260   StructureMatrix_applied = &myDefaultMatrix;
261
262   ResetAppliedAspect();
263
264   return Standard_True;
265 }
266
267 //=======================================================================
268 //function : ResetAppliedAspect
269 //purpose  : Sets default values of GL parameters in accordance with default aspects
270 //=======================================================================
271 void OpenGl_Workspace::ResetAppliedAspect()
272 {
273   myGlContext->BindDefaultVao();
274
275   NamedStatus           = !myTextureBound.IsNull() ? OPENGL_NS_TEXTURE : 0;
276   HighlightColor        = &THE_WHITE_COLOR;
277   AspectLine_set        = &myDefaultAspectLine;
278   AspectLine_applied    = NULL;
279   AspectFace_set        = &myDefaultAspectFace;
280   AspectFace_applied    = NULL;
281   AspectMarker_set      = &myDefaultAspectMarker;
282   AspectMarker_applied  = NULL;
283   AspectText_set        = &myDefaultAspectText;
284   AspectText_applied    = NULL;
285   TextParam_set         = &myDefaultTextParam;
286   TextParam_applied     = NULL;
287   PolygonOffset_applied = THE_DEFAULT_POFFSET;
288   myCullingMode         = TelCullUndefined;
289
290   AspectLine(Standard_True);
291   AspectFace(Standard_True);
292   AspectMarker(Standard_True);
293   AspectText(Standard_True);
294 }
295
296 // =======================================================================
297 // function : DisableTexture
298 // purpose  :
299 // =======================================================================
300 Handle(OpenGl_Texture) OpenGl_Workspace::DisableTexture()
301 {
302   if (myTextureBound.IsNull())
303   {
304     return myTextureBound;
305   }
306
307   const Handle(OpenGl_Sampler)& aSampler = myGlContext->TextureSampler();
308   if (!aSampler.IsNull())
309   {
310     aSampler->Unbind (*myGlContext);
311   }
312
313 #if !defined(GL_ES_VERSION_2_0)
314   // reset texture matrix because some code may expect it is identity
315   if (myGlContext->core11 != NULL)
316   {
317     GLint aMatrixMode = GL_TEXTURE;
318     glGetIntegerv (GL_MATRIX_MODE, &aMatrixMode);
319     glMatrixMode (GL_TEXTURE);
320     glLoadIdentity();
321     glMatrixMode (aMatrixMode);
322   }
323 #endif
324
325   myTextureBound->Unbind (myGlContext);
326   switch (myTextureBound->GetTarget())
327   {
328   #if !defined(GL_ES_VERSION_2_0)
329     case GL_TEXTURE_1D:
330     {
331       if (myGlContext->core11 != NULL)
332       {
333         if (myTextureBound->GetParams()->GenMode() != GL_NONE)
334         {
335           glDisable (GL_TEXTURE_GEN_S);
336         }
337         glDisable (GL_TEXTURE_1D);
338       }
339       break;
340     }
341   #endif
342     case GL_TEXTURE_2D:
343     {
344     #if !defined(GL_ES_VERSION_2_0)
345       if (myGlContext->core11 != NULL)
346       {
347         if (myTextureBound->GetParams()->GenMode() != GL_NONE)
348         {
349           glDisable (GL_TEXTURE_GEN_S);
350           glDisable (GL_TEXTURE_GEN_T);
351           if (myTextureBound->GetParams()->GenMode() == Graphic3d_TOTM_SPRITE)
352           {
353             glDisable (GL_POINT_SPRITE);
354           }
355         }
356         glDisable (GL_TEXTURE_2D);
357       }
358     #endif
359       break;
360     }
361     default: break;
362   }
363
364   Handle(OpenGl_Texture) aPrevTexture = myTextureBound;
365   myTextureBound.Nullify();
366   return aPrevTexture;
367 }
368
369 // =======================================================================
370 // function : setTextureParams
371 // purpose  :
372 // =======================================================================
373 void OpenGl_Workspace::setTextureParams (Handle(OpenGl_Texture)&                theTexture,
374                                          const Handle(Graphic3d_TextureParams)& theParams)
375 {
376   const Handle(Graphic3d_TextureParams)& aParams = theParams.IsNull() ? theTexture->GetParams() : theParams;
377   if (aParams.IsNull())
378   {
379     return;
380   }
381
382 #if !defined(GL_ES_VERSION_2_0)
383   GLint aMatrixMode = GL_TEXTURE;
384   if (myGlContext->core11 != NULL)
385   {
386     glGetIntegerv (GL_MATRIX_MODE, &aMatrixMode);
387
388     // setup texture matrix
389     glMatrixMode (GL_TEXTURE);
390     OpenGl_Mat4 aTextureMat;
391     const Graphic3d_Vec2& aScale = aParams->Scale();
392     const Graphic3d_Vec2& aTrans = aParams->Translation();
393     OpenGl_Utils::Scale     (aTextureMat,  aScale.x(),  aScale.y(), 1.0f);
394     OpenGl_Utils::Translate (aTextureMat, -aTrans.x(), -aTrans.y(), 0.0f);
395     OpenGl_Utils::Rotate    (aTextureMat, -aParams->Rotation(), 0.0f, 0.0f, 1.0f);
396     glLoadMatrixf (aTextureMat);
397
398     GLint anEnvMode = GL_MODULATE; // lighting mode
399     if (!aParams->IsModulate())
400     {
401       anEnvMode = GL_DECAL;
402       if (theTexture->GetFormat() == GL_ALPHA
403        || theTexture->GetFormat() == GL_LUMINANCE)
404       {
405         anEnvMode = GL_REPLACE;
406       }
407     }
408
409     // setup generation of texture coordinates
410     switch (aParams->GenMode())
411     {
412       case Graphic3d_TOTM_OBJECT:
413       {
414         glTexGeni  (GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
415         glTexGenfv (GL_S, GL_OBJECT_PLANE,     aParams->GenPlaneS().GetData());
416         if (theTexture->GetTarget() != GL_TEXTURE_1D)
417         {
418           glTexGeni  (GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
419           glTexGenfv (GL_T, GL_OBJECT_PLANE,     aParams->GenPlaneT().GetData());
420         }
421         break;
422       }
423       case Graphic3d_TOTM_SPHERE:
424       {
425         glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
426         if (theTexture->GetTarget() != GL_TEXTURE_1D)
427         {
428           glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
429         }
430         break;
431       }
432       case Graphic3d_TOTM_EYE:
433       {
434         myGlContext->WorldViewState.Push();
435
436         myGlContext->WorldViewState.SetIdentity();
437         myGlContext->ApplyWorldViewMatrix();
438
439         glTexGeni  (GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
440         glTexGenfv (GL_S, GL_EYE_PLANE,        aParams->GenPlaneS().GetData());
441
442         if (theTexture->GetTarget() != GL_TEXTURE_1D)
443         {
444           glTexGeni  (GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
445           glTexGenfv (GL_T, GL_EYE_PLANE,        aParams->GenPlaneT().GetData());
446         }
447
448         myGlContext->WorldViewState.Pop();
449
450         break;
451       }
452       case Graphic3d_TOTM_SPRITE:
453       {
454         if (GetGlContext()->core20fwd != NULL)
455         {
456           glEnable  (GL_POINT_SPRITE);
457           glTexEnvi (GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE);
458           anEnvMode = GL_REPLACE;
459           GetGlContext()->core15->glPointParameteri (GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT);
460         }
461         break;
462       }
463       case Graphic3d_TOTM_MANUAL:
464       default: break;
465     }
466
467     // setup lighting
468     glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, anEnvMode);
469   }
470 #endif
471
472   // get active sampler object to override default texture parameters
473   const Handle(OpenGl_Sampler)& aSampler = myGlContext->TextureSampler();
474
475   // setup texture filtering and wrapping
476   //if (theTexture->GetParams() != theParams)
477   const GLenum aFilter   = (aParams->Filter() == Graphic3d_TOTF_NEAREST) ? GL_NEAREST : GL_LINEAR;
478   const GLenum aWrapMode = aParams->IsRepeat() ? GL_REPEAT : myGlContext->TextureWrapClamp();
479   switch (theTexture->GetTarget())
480   {
481   #if !defined(GL_ES_VERSION_2_0)
482     case GL_TEXTURE_1D:
483     {
484       if (aSampler.IsNull() || !aSampler->IsValid())
485       {
486         glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, aFilter);
487         glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, aFilter);
488         glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_S,     aWrapMode);
489       }
490       else
491       {
492         aSampler->SetParameter (*myGlContext, GL_TEXTURE_MAG_FILTER, aFilter);
493         aSampler->SetParameter (*myGlContext, GL_TEXTURE_MIN_FILTER, aFilter);
494         aSampler->SetParameter (*myGlContext, GL_TEXTURE_WRAP_S,     aWrapMode);
495       }
496
497       break;
498     }
499   #endif
500     case GL_TEXTURE_2D:
501     {
502       GLenum aFilterMin = aFilter;
503       if (theTexture->HasMipmaps())
504       {
505         aFilterMin = GL_NEAREST_MIPMAP_NEAREST;
506         if (aParams->Filter() == Graphic3d_TOTF_BILINEAR)
507         {
508           aFilterMin = GL_LINEAR_MIPMAP_NEAREST;
509         }
510         else if (aParams->Filter() == Graphic3d_TOTF_TRILINEAR)
511         {
512           aFilterMin = GL_LINEAR_MIPMAP_LINEAR;
513         }
514
515         if (myGlContext->extAnis)
516         {
517           // setup degree of anisotropy filter
518           const GLint aMaxDegree = myGlContext->MaxDegreeOfAnisotropy();
519           GLint aDegree;
520           switch (aParams->AnisoFilter())
521           {
522             case Graphic3d_LOTA_QUALITY:
523             {
524               aDegree = aMaxDegree;
525               break;
526             }
527             case Graphic3d_LOTA_MIDDLE:
528             {
529               aDegree = (aMaxDegree <= 4) ? 2 : (aMaxDegree / 2);
530               break;
531             }
532             case Graphic3d_LOTA_FAST:
533             {
534               aDegree = 2;
535               break;
536             }
537             case Graphic3d_LOTA_OFF:
538             default:
539             {
540               aDegree = 1;
541               break;
542             }
543           }
544
545           if (aSampler.IsNull() || !aSampler->IsValid())
546           {
547             glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, aDegree);
548           }
549           else
550           {
551             aSampler->SetParameter (*myGlContext, GL_TEXTURE_MAX_ANISOTROPY_EXT, aDegree);
552           }
553         }
554       }
555
556       if (aSampler.IsNull() || !aSampler->IsValid())
557       {
558         glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, aFilterMin);
559         glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, aFilter);
560         glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,     aWrapMode);
561         glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,     aWrapMode);
562       }
563       else
564       {
565         aSampler->SetParameter (*myGlContext, GL_TEXTURE_MIN_FILTER, aFilterMin);
566         aSampler->SetParameter (*myGlContext, GL_TEXTURE_MAG_FILTER, aFilter);
567         aSampler->SetParameter (*myGlContext, GL_TEXTURE_WRAP_S,     aWrapMode);
568         aSampler->SetParameter (*myGlContext, GL_TEXTURE_WRAP_T,     aWrapMode);
569       }
570
571       break;
572     }
573     default: break;
574   }
575
576   switch (theTexture->GetTarget())
577   {
578   #if !defined(GL_ES_VERSION_2_0)
579     case GL_TEXTURE_1D:
580     {
581       if (myGlContext->core11 != NULL)
582       {
583         if (aParams->GenMode() != Graphic3d_TOTM_MANUAL)
584         {
585           glEnable (GL_TEXTURE_GEN_S);
586         }
587         glEnable (GL_TEXTURE_1D);
588       }
589       break;
590     }
591   #endif
592     case GL_TEXTURE_2D:
593     {
594     #if !defined(GL_ES_VERSION_2_0)
595       if (myGlContext->core11 != NULL)
596       {
597         if (aParams->GenMode() != Graphic3d_TOTM_MANUAL)
598         {
599           glEnable (GL_TEXTURE_GEN_S);
600           glEnable (GL_TEXTURE_GEN_T);
601         }
602         glEnable (GL_TEXTURE_2D);
603       }
604     #endif
605       break;
606     }
607     default: break;
608   }
609
610 #if !defined(GL_ES_VERSION_2_0)
611   if (myGlContext->core11 != NULL)
612   {
613     glMatrixMode (aMatrixMode); // turn back active matrix
614   }
615 #endif
616   theTexture->SetParams (aParams);
617 }
618
619 // =======================================================================
620 // function : EnableTexture
621 // purpose  :
622 // =======================================================================
623 Handle(OpenGl_Texture) OpenGl_Workspace::EnableTexture (const Handle(OpenGl_Texture)&          theTexture,
624                                                         const Handle(Graphic3d_TextureParams)& theParams)
625 {
626   if (theTexture.IsNull() || !theTexture->IsValid())
627   {
628     return DisableTexture();
629   }
630
631   if (myTextureBound == theTexture
632    && (theParams.IsNull() || theParams == theTexture->GetParams()))
633   {
634     // already bound
635     return myTextureBound;
636   }
637
638   Handle(OpenGl_Texture) aPrevTexture = DisableTexture();
639   myTextureBound = theTexture;
640   myTextureBound->Bind (myGlContext);
641   setTextureParams (myTextureBound, theParams);
642
643   // If custom sampler object is available it will be
644   // used for overriding default texture parameters
645   const Handle(OpenGl_Sampler)& aSampler = myGlContext->TextureSampler();
646
647   if (!aSampler.IsNull() && aSampler->IsValid())
648   {
649     aSampler->Bind (*myGlContext);
650   }
651
652   return aPrevTexture;
653 }
654
655 // =======================================================================
656 // function : Redraw
657 // purpose  :
658 // =======================================================================
659 void OpenGl_Workspace::Redraw (const Graphic3d_CView& theCView,
660                                const Aspect_CLayer2d& theCUnderLayer,
661                                const Aspect_CLayer2d& theCOverLayer)
662 {
663   if (!Activate())
664   {
665     return;
666   }
667
668   ++myFrameCounter;
669   myIsCullingEnabled = theCView.IsCullingEnabled;
670
671   // release pending GL resources
672   myGlContext->ReleaseDelayed();
673
674   // fetch OpenGl context state
675   myGlContext->FetchState();
676
677   OpenGl_FrameBuffer* aFrameBuffer = (OpenGl_FrameBuffer* )theCView.ptrFBO;
678   if (aFrameBuffer != NULL)
679   {
680     aFrameBuffer->SetupViewport (myGlContext);
681   }
682   else
683   {
684     myGlContext->core11fwd->glViewport (0, 0, myWidth, myHeight);
685   }
686   bool toSwap = myGlContext->IsRender()
687             && !myGlContext->caps->buffersNoSwap
688             &&  aFrameBuffer == NULL;
689
690   Standard_Integer aSizeX = aFrameBuffer != NULL ? aFrameBuffer->GetVPSizeX() : myWidth;
691   Standard_Integer aSizeY = aFrameBuffer != NULL ? aFrameBuffer->GetVPSizeY() : myHeight;
692
693   if (!myGlContext->DefaultFrameBuffer().IsNull()
694     && myGlContext->DefaultFrameBuffer()->IsValid())
695   {
696     myGlContext->DefaultFrameBuffer()->BindBuffer (myGlContext);
697   }
698
699   if (myHasFboBlit
700    && myTransientDrawToFront)
701   {
702     if (myResultFBO->GetVPSizeX() != aSizeX
703      || myResultFBO->GetVPSizeY() != aSizeY)
704     {
705       // prepare FBOs containing main scene
706       // for further blitting and rendering immediate presentations on top
707       if (myGlContext->core20fwd != NULL)
708       {
709         myResultFBO->Init (myGlContext, aSizeX, aSizeY);
710       }
711     }
712
713     if (myResultFBO->IsValid())
714     {
715       myResultFBO->SetupViewport (myGlContext);
716     }
717   }
718   else
719   {
720     myResultFBO->Release (myGlContext.operator->());
721     myResultFBO->ChangeViewport (0, 0);
722   }
723
724   // draw entire frame using normal OpenGL pipeline
725   if (myResultFBO->IsValid())
726   {
727     myResultFBO->BindBuffer (myGlContext);
728   }
729   else if (aFrameBuffer != NULL)
730   {
731     aFrameBuffer->BindBuffer (myGlContext);
732   }
733
734   redraw1 (theCView, theCUnderLayer, theCOverLayer);
735   myBackBufferRestored = Standard_True;
736   myIsImmediateDrawn   = Standard_False;
737   if (!redrawImmediate (theCView, theCOverLayer, theCUnderLayer, aFrameBuffer))
738   {
739     toSwap = false;
740   }
741
742   if (aFrameBuffer != NULL)
743   {
744     aFrameBuffer->UnbindBuffer (myGlContext);
745     // move back original viewport
746     myGlContext->core11fwd->glViewport (0, 0, myWidth, myHeight);
747   }
748
749 #if defined(_WIN32) && defined(HAVE_VIDEOCAPTURE)
750   if (OpenGl_AVIWriter_AllowWriting (theCView.DefWindow.XWindow))
751   {
752     GLint params[4];
753     glGetIntegerv (GL_VIEWPORT, params);
754     int nWidth  = params[2] & ~0x7;
755     int nHeight = params[3] & ~0x7;
756
757     const int nBitsPerPixel = 24;
758     GLubyte* aDumpData = new GLubyte[nWidth * nHeight * nBitsPerPixel / 8];
759
760     glPixelStorei (GL_PACK_ALIGNMENT, 1);
761     glReadPixels (0, 0, nWidth, nHeight, GL_BGR_EXT, GL_UNSIGNED_BYTE, aDumpData);
762     OpenGl_AVIWriter_AVIWriter (aDumpData, nWidth, nHeight, nBitsPerPixel);
763     delete[] aDumpData;
764   }
765 #endif
766
767   // Swap the buffers
768   if (toSwap)
769   {
770     GetGlContext()->SwapBuffers();
771     if (!myResultFBO->IsValid())
772     {
773       myBackBufferRestored = Standard_False;
774     }
775   }
776   else
777   {
778     myGlContext->core11fwd->glFlush();
779   }
780
781   // reset render mode state
782   myGlContext->FetchState();
783 }
784
785 // =======================================================================
786 // function : redraw1
787 // purpose  :
788 // =======================================================================
789 void OpenGl_Workspace::redraw1 (const Graphic3d_CView& theCView,
790                                 const Aspect_CLayer2d& theCUnderLayer,
791                                 const Aspect_CLayer2d& theCOverLayer)
792 {
793   if (myView.IsNull())
794   {
795     return;
796   }
797
798   // request reset of material
799   NamedStatus |= OPENGL_NS_RESMAT;
800
801   GLbitfield toClear = GL_COLOR_BUFFER_BIT;
802   if (myUseZBuffer)
803   {
804     glDepthFunc (GL_LEQUAL);
805     glDepthMask (GL_TRUE);
806     if (myUseDepthTest)
807     {
808       glEnable (GL_DEPTH_TEST);
809     }
810     else
811     {
812       glDisable (GL_DEPTH_TEST);
813     }
814
815   #if !defined(GL_ES_VERSION_2_0)
816     glClearDepth (1.0);
817   #else
818     glClearDepthf (1.0f);
819   #endif
820     toClear |= GL_DEPTH_BUFFER_BIT;
821   }
822   else
823   {
824     glDisable (GL_DEPTH_TEST);
825   }
826
827   if (NamedStatus & OPENGL_NS_WHITEBACK)
828   {
829     // set background to white
830     glClearColor (1.0f, 1.0f, 1.0f, 1.0f);
831     toClear |= GL_DEPTH_BUFFER_BIT;
832   }
833   else
834   {
835     glClearColor (myBgColor.rgb[0], myBgColor.rgb[1], myBgColor.rgb[2], 0.0f);
836   }
837
838   glClear (toClear);
839
840   Handle(OpenGl_Workspace) aWS (this);
841   myView->Render (myPrintContext, aWS, theCView, theCUnderLayer, theCOverLayer, Standard_False);
842 }
843
844 // =======================================================================
845 // function : copyBackToFront
846 // purpose  :
847 // =======================================================================
848 void OpenGl_Workspace::copyBackToFront()
849 {
850 #if !defined(GL_ES_VERSION_2_0)
851
852   OpenGl_Mat4 aProjectMat;
853   OpenGl_Utils::Ortho2D<Standard_ShortReal> (aProjectMat,
854     0.f, static_cast<GLfloat> (myWidth), 0.f, static_cast<GLfloat> (myHeight));
855
856   myGlContext->WorldViewState.Push();
857   myGlContext->ProjectionState.Push();
858
859   myGlContext->WorldViewState.SetIdentity();
860   myGlContext->ProjectionState.SetCurrent (aProjectMat);
861
862   myGlContext->ApplyProjectionMatrix();
863   myGlContext->ApplyWorldViewMatrix();
864
865   DisableFeatures();
866
867   glDrawBuffer (GL_FRONT);
868   glReadBuffer (GL_BACK);
869
870   glRasterPos2i (0, 0);
871   glCopyPixels  (0, 0, myWidth + 1, myHeight + 1, GL_COLOR);
872   //glCopyPixels  (0, 0, myWidth + 1, myHeight + 1, GL_DEPTH);
873
874   EnableFeatures();
875
876   myGlContext->WorldViewState.Pop();
877   myGlContext->ProjectionState.Pop();
878   myGlContext->ApplyProjectionMatrix();
879   glDrawBuffer (GL_BACK);
880
881 #endif
882   myIsImmediateDrawn = Standard_False;
883 }
884
885 // =======================================================================
886 // function : DisplayCallback
887 // purpose  :
888 // =======================================================================
889 void OpenGl_Workspace::DisplayCallback (const Graphic3d_CView& theCView,
890                                         Standard_Integer       theReason)
891 {
892   if (theCView.GDisplayCB == NULL)
893   {
894     return;
895   }
896
897   Aspect_GraphicCallbackStruct aCallData;
898   aCallData.reason    = theReason;
899   aCallData.glContext = myGlContext;
900   aCallData.wsID      = theCView.WsId;
901   aCallData.viewID    = theCView.ViewId;
902   aCallData.IsCoreProfile = (myGlContext->core11 == NULL);
903   theCView.GDisplayCB (theCView.DefWindow.XWindow, theCView.GClientData, &aCallData);
904 }
905
906 // =======================================================================
907 // function : RedrawImmediate
908 // purpose  :
909 // =======================================================================
910 void OpenGl_Workspace::RedrawImmediate (const Graphic3d_CView& theCView,
911                                         const Aspect_CLayer2d& theCUnderLayer,
912                                         const Aspect_CLayer2d& theCOverLayer)
913 {
914   if (!myTransientDrawToFront
915    || !myBackBufferRestored
916    || (myGlContext->caps->buffersNoSwap && !myResultFBO->IsValid()))
917   {
918     Redraw (theCView, theCUnderLayer, theCOverLayer);
919     return;
920   }
921   else if (!Activate())
922   {
923     return;
924   }
925
926   if (!myGlContext->DefaultFrameBuffer().IsNull()
927    &&  myGlContext->DefaultFrameBuffer()->IsValid())
928   {
929     myGlContext->DefaultFrameBuffer()->BindBuffer (myGlContext);
930   }
931
932   if (redrawImmediate (theCView, theCUnderLayer, theCOverLayer, NULL, Standard_True)
933   && !myGlContext->caps->buffersNoSwap)
934   {
935     myGlContext->SwapBuffers();
936   }
937   else
938   {
939     myGlContext->core11fwd->glFlush();
940     MakeBackBufCurrent();
941   }
942 }
943
944 // =======================================================================
945 // function : redrawImmediate
946 // purpose  :
947 // =======================================================================
948 bool OpenGl_Workspace::redrawImmediate (const Graphic3d_CView& theCView,
949                                         const Aspect_CLayer2d& theCUnderLayer,
950                                         const Aspect_CLayer2d& theCOverLayer,
951                                         OpenGl_FrameBuffer*    theTargetFBO,
952                                         const Standard_Boolean theIsPartialUpdate)
953 {
954   GLboolean toCopyBackToFront = GL_FALSE;
955   if (!myTransientDrawToFront)
956   {
957     myBackBufferRestored = Standard_False;
958   }
959   else if (myResultFBO->IsValid()
960         && myGlContext->IsRender())
961   {
962     // clear destination before blitting
963     if (theTargetFBO != NULL)
964     {
965       theTargetFBO->BindBuffer (myGlContext);
966     }
967     else if (!myGlContext->DefaultFrameBuffer().IsNull()
968           &&  myGlContext->DefaultFrameBuffer()->IsValid())
969     {
970       myGlContext->DefaultFrameBuffer()->BindBuffer (myGlContext);
971     }
972     else
973     {
974       myGlContext->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
975     }
976   #if !defined(GL_ES_VERSION_2_0)
977     myGlContext->core20fwd->glClearDepth  (1.0);
978   #else
979     myGlContext->core20fwd->glClearDepthf (1.0f);
980   #endif
981     myGlContext->core20fwd->glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
982
983   /*#if !defined(GL_ES_VERSION_2_0)
984     if (myGlContext->arbFBOBlit != NULL)
985     {
986       myResultFBO->BindReadBuffer (myGlContext);
987       if (theTargetFBO != NULL)
988       {
989         theTargetFBO->BindDrawBuffer (myGlContext);
990       }
991       else if (!myGlContext->DefaultFrameBuffer().IsNull()
992             &&  myGlContext->DefaultFrameBuffer()->IsValid())
993       {
994         myGlContext->DefaultFrameBuffer()->BindDrawBuffer (myGlContext);
995       }
996       else
997       {
998         myGlContext->arbFBO->glBindFramebuffer (GL_DRAW_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
999       }
1000       // we don't copy stencil buffer here... does it matter for performance?
1001       myGlContext->arbFBOBlit->glBlitFramebuffer (0, 0, myResultFBO->GetVPSizeX(), myResultFBO->GetVPSizeY(),
1002                                                   0, 0, myResultFBO->GetVPSizeX(), myResultFBO->GetVPSizeY(),
1003                                                   GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST);
1004
1005       if (theTargetFBO != NULL)
1006       {
1007         theTargetFBO->BindBuffer (myGlContext);
1008       }
1009       else if (!myGlContext->DefaultFrameBuffer().IsNull()
1010             &&  myGlContext->DefaultFrameBuffer()->IsValid())
1011       {
1012         myGlContext->DefaultFrameBuffer()->BindBuffer (myGlContext);
1013       }
1014       else
1015       {
1016         myGlContext->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
1017       }
1018     }
1019     else
1020   #endif*/
1021     {
1022       myGlContext->core20fwd->glDepthFunc (GL_ALWAYS);
1023       myGlContext->core20fwd->glDepthMask (GL_TRUE);
1024       myGlContext->core20fwd->glEnable (GL_DEPTH_TEST);
1025
1026       DisableTexture();
1027       if (!myFullScreenQuad.IsValid())
1028       {
1029         OpenGl_Vec4 aQuad[4] =
1030         {
1031           OpenGl_Vec4( 1.0f, -1.0f, 1.0f, 0.0f),
1032           OpenGl_Vec4( 1.0f,  1.0f, 1.0f, 1.0f),
1033           OpenGl_Vec4(-1.0f, -1.0f, 0.0f, 0.0f),
1034           OpenGl_Vec4(-1.0f,  1.0f, 0.0f, 1.0f)
1035         };
1036         myFullScreenQuad.Init (myGlContext, 4, 4, aQuad[0].GetData());
1037       }
1038
1039       const Handle(OpenGl_ShaderManager)& aManager = myGlContext->ShaderManager();
1040       if (myFullScreenQuad.IsValid()
1041        && aManager->BindFboBlitProgram())
1042       {
1043         myResultFBO->ColorTexture()       ->Bind   (myGlContext, GL_TEXTURE0 + 0);
1044         myResultFBO->DepthStencilTexture()->Bind   (myGlContext, GL_TEXTURE0 + 1);
1045         myFullScreenQuad.BindVertexAttrib (myGlContext, 0);
1046
1047         myGlContext->core20fwd->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
1048
1049         myFullScreenQuad.UnbindVertexAttrib (myGlContext, 0);
1050         myResultFBO->DepthStencilTexture()->Unbind (myGlContext, GL_TEXTURE0 + 1);
1051         myResultFBO->ColorTexture()       ->Unbind (myGlContext, GL_TEXTURE0 + 0);
1052       }
1053       else
1054       {
1055         TCollection_ExtendedString aMsg = TCollection_ExtendedString()
1056           + "Error! FBO blitting has failed";
1057         myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
1058                                   GL_DEBUG_TYPE_ERROR_ARB,
1059                                   0,
1060                                   GL_DEBUG_SEVERITY_HIGH_ARB,
1061                                   aMsg);
1062         myHasFboBlit = Standard_False;
1063         myResultFBO->Release (myGlContext.operator->());
1064         return true;
1065       }
1066     }
1067   }
1068   else if (theTargetFBO == NULL)
1069   {
1070   #if !defined(GL_ES_VERSION_2_0)
1071     myGlContext->core11fwd->glGetBooleanv (GL_DOUBLEBUFFER, &toCopyBackToFront);
1072   #endif
1073     if (toCopyBackToFront)
1074     {
1075       if (!myView->HasImmediateStructures()
1076        && !theIsPartialUpdate)
1077       {
1078         // prefer Swap Buffers within Redraw in compatibility mode (without FBO)
1079         return true;
1080       }
1081       copyBackToFront();
1082       MakeFrontBufCurrent();
1083     }
1084     else
1085     {
1086       myBackBufferRestored = Standard_False;
1087     }
1088   }
1089   else
1090   {
1091     myBackBufferRestored = Standard_False;
1092   }
1093   myIsImmediateDrawn = Standard_True;
1094
1095   Handle(OpenGl_Workspace) aWS (this);
1096
1097   if (myUseZBuffer)
1098   {
1099     glDepthFunc (GL_LEQUAL);
1100     glDepthMask (GL_TRUE);
1101     if (myUseDepthTest)
1102     {
1103       glEnable (GL_DEPTH_TEST);
1104     }
1105     else
1106     {
1107       glDisable (GL_DEPTH_TEST);
1108     }
1109
1110   #if !defined(GL_ES_VERSION_2_0)
1111     glClearDepth (1.0);
1112   #else
1113     glClearDepthf (1.0f);
1114   #endif
1115   }
1116   else
1117   {
1118     glDisable (GL_DEPTH_TEST);
1119   }
1120
1121   myView->Render (myPrintContext, aWS, theCView, theCUnderLayer, theCOverLayer, Standard_True);
1122   if (!myView->ImmediateStructures().IsEmpty())
1123   {
1124     glDisable (GL_DEPTH_TEST);
1125   }
1126   for (OpenGl_SequenceOfStructure::Iterator anIter (myView->ImmediateStructures());
1127        anIter.More(); anIter.Next())
1128   {
1129     const OpenGl_Structure* aStructure = anIter.Value();
1130     if (!aStructure->IsVisible())
1131     {
1132       continue;
1133     }
1134
1135     aStructure->Render (aWS);
1136   }
1137
1138   if (toCopyBackToFront)
1139   {
1140     MakeBackBufCurrent();
1141     return false;
1142   }
1143   return true;
1144 }
1145
1146 IMPLEMENT_STANDARD_HANDLE (OpenGl_RaytraceFilter, OpenGl_RenderFilter)
1147 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_RaytraceFilter, OpenGl_RenderFilter)
1148
1149 // =======================================================================
1150 // function : CanRender
1151 // purpose  :
1152 // =======================================================================
1153 Standard_Boolean OpenGl_RaytraceFilter::CanRender (const OpenGl_Element* theElement)
1154 {
1155   Standard_Boolean aPrevFilterResult = Standard_True;
1156   if (!myPrevRenderFilter.IsNull())
1157   {
1158     aPrevFilterResult = myPrevRenderFilter->CanRender (theElement);
1159   }
1160   return aPrevFilterResult &&
1161     !OpenGl_Raytrace::IsRaytracedElement (theElement);
1162 }