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