0026711: Visualization, TKOpenGl - support creation of multisampling off-screen FBOs
[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_Workspace.hxx>
17
18 #include <InterfaceGraphic.hxx>
19
20 #include <OpenGl_ArbFBO.hxx>
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_GlCore15.hxx>
29 #include <OpenGl_SceneGeometry.hxx>
30 #include <OpenGl_Structure.hxx>
31 #include <OpenGl_Sampler.hxx>
32 #include <OpenGl_Texture.hxx>
33 #include <OpenGl_View.hxx>
34 #include <OpenGl_Window.hxx>
35
36 #include <Graphic3d_TextureParams.hxx>
37 #include <Graphic3d_TransformUtils.hxx>
38
39 #ifdef HAVE_GL2PS
40   #include <gl2ps.h>
41   /* OCC22216 NOTE: linker dependency can be switched off by undefining macro.
42      Pragma comment for gl2ps.lib is defined only here. */
43   #ifdef _MSC_VER
44   #pragma comment( lib, "gl2ps.lib" )
45   #endif
46 #endif
47
48 namespace
49 {
50   static const TEL_COLOUR  THE_WHITE_COLOR = { { 1.0f, 1.0f, 1.0f, 1.0f } };
51   static const OpenGl_Vec4 THE_BLACK_COLOR      (0.0f, 0.0f, 0.0f, 1.0f);
52
53   static const OpenGl_AspectLine myDefaultAspectLine;
54   static const OpenGl_AspectFace myDefaultAspectFace;
55   static const OpenGl_AspectMarker myDefaultAspectMarker;
56
57   static const OpenGl_TextParam myDefaultTextParam =
58   {
59     16, Graphic3d_HTA_LEFT, Graphic3d_VTA_BOTTOM
60   };
61
62   static const OpenGl_Matrix myDefaultMatrix =
63   {
64     {{ 1.0F, 0.0F, 0.0F, 0.0F },
65      { 0.0F, 1.0F, 0.0F, 0.0F },
66      { 0.0F, 0.0F, 1.0F, 0.0F },
67      { 0.0F, 0.0F, 0.0F, 1.0F }}
68   };
69
70 };
71
72 // =======================================================================
73 // function : Init
74 // purpose  :
75 // =======================================================================
76 void OpenGl_Material::Init (const OPENGL_SURF_PROP& theProp)
77 {
78   // ambient component
79   if (theProp.color_mask & OPENGL_AMBIENT_MASK)
80   {
81     const float* aSrcAmb = theProp.isphysic ? theProp.ambcol.rgb : theProp.matcol.rgb;
82     Ambient = OpenGl_Vec4 (aSrcAmb[0] * theProp.amb,
83                            aSrcAmb[1] * theProp.amb,
84                            aSrcAmb[2] * theProp.amb,
85                            1.0f);
86   }
87   else
88   {
89     Ambient = THE_BLACK_COLOR;
90   }
91
92   // diffusion component
93   if (theProp.color_mask & OPENGL_DIFFUSE_MASK)
94   {
95     const float* aSrcDif = theProp.isphysic ? theProp.difcol.rgb : theProp.matcol.rgb;
96     Diffuse = OpenGl_Vec4 (aSrcDif[0] * theProp.diff,
97                            aSrcDif[1] * theProp.diff,
98                            aSrcDif[2] * theProp.diff,
99                            1.0f);
100   }
101   else
102   {
103     Diffuse = THE_BLACK_COLOR;
104   }
105
106   // specular component
107   if (theProp.color_mask & OPENGL_SPECULAR_MASK)
108   {
109     const float* aSrcSpe = theProp.isphysic ? theProp.speccol.rgb : THE_WHITE_COLOR.rgb;
110     Specular = OpenGl_Vec4 (aSrcSpe[0] * theProp.spec,
111                             aSrcSpe[1] * theProp.spec,
112                             aSrcSpe[2] * theProp.spec,
113                             1.0f);
114   }
115   else
116   {
117     Specular = THE_BLACK_COLOR;
118   }
119
120   // emission component
121   if (theProp.color_mask & OPENGL_EMISSIVE_MASK)
122   {
123     const float* aSrcEms = theProp.isphysic ? theProp.emscol.rgb : theProp.matcol.rgb;
124     Emission = OpenGl_Vec4 (aSrcEms[0] * theProp.emsv,
125                             aSrcEms[1] * theProp.emsv,
126                             aSrcEms[2] * theProp.emsv,
127                             1.0f);
128   }
129   else
130   {
131     Emission = THE_BLACK_COLOR;
132   }
133
134   ChangeShine()        = theProp.shine;
135   ChangeTransparency() = theProp.trans;
136 }
137
138 // =======================================================================
139 // function : OpenGl_Workspace
140 // purpose  :
141 // =======================================================================
142 OpenGl_Workspace::OpenGl_Workspace (OpenGl_View* theView, const Handle(OpenGl_Window)& theWindow)
143 : NamedStatus (0),
144   HighlightColor (&THE_WHITE_COLOR),
145   myView (theView),
146   myWindow (theWindow),
147   myGlContext (!theWindow.IsNull() ? theWindow->GetGlContext() : NULL),
148   myUseZBuffer    (Standard_True),
149   myUseDepthWrite (Standard_True),
150   myUseGLLight (Standard_True),
151   //
152   AspectLine_set (&myDefaultAspectLine),
153   AspectLine_applied (NULL),
154   AspectFace_set (&myDefaultAspectFace),
155   AspectFace_applied (NULL),
156   AspectMarker_set (&myDefaultAspectMarker),
157   AspectMarker_applied (NULL),
158   ViewMatrix_applied (&myDefaultMatrix),
159   StructureMatrix_applied (&myDefaultMatrix),
160   myCullingMode (TelCullUndefined),
161   myModelViewMatrix (myDefaultMatrix),
162   PolygonOffset_applied (THE_DEFAULT_POFFSET)
163 {
164   if (!myGlContext.IsNull() && myGlContext->MakeCurrent())
165   {
166     myGlContext->core11fwd->glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
167
168     if (!myGlContext->GetResource ("OpenGl_LineAttributes", myLineAttribs))
169     {
170       // share and register for release once the resource is no longer used
171       myLineAttribs = new OpenGl_LineAttributes();
172       myGlContext->ShareResource ("OpenGl_LineAttributes", myLineAttribs);
173       myLineAttribs->Init (myGlContext);
174     }
175
176     // General initialization of the context
177
178   #if !defined(GL_ES_VERSION_2_0)
179     if (myGlContext->core11 != NULL)
180     {
181       // Eviter d'avoir les faces mal orientees en noir.
182       // Pourrait etre utiliser pour detecter les problemes d'orientation
183       glLightModeli ((GLenum )GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
184
185       // Optimisation pour le Fog et l'antialiasing
186       glHint (GL_FOG_HINT,            GL_FASTEST);
187       glHint (GL_POINT_SMOOTH_HINT,   GL_FASTEST);
188     }
189
190     glHint (GL_LINE_SMOOTH_HINT,    GL_FASTEST);
191     glHint (GL_POLYGON_SMOOTH_HINT, GL_FASTEST);
192   #endif
193   }
194
195   myDefaultCappingAlgoFilter         = new OpenGl_CappingAlgoFilter();
196   myNoneCulling.ChangeCullingMode()  = TelCullNone;
197   myNoneCulling.ChangeEdge()         = 0;
198   myFrontCulling.ChangeCullingMode() = TelCullBack;
199   myFrontCulling.ChangeEdge()        = 0;
200 }
201
202 // =======================================================================
203 // function : ~OpenGl_Workspace
204 // purpose  :
205 // =======================================================================
206 OpenGl_Workspace::~OpenGl_Workspace()
207 {
208   if (!myLineAttribs.IsNull())
209   {
210     myLineAttribs.Nullify();
211     myGlContext->ReleaseResource ("OpenGl_LineAttributes", Standard_True);
212   }
213 }
214
215 // =======================================================================
216 // function : Activate
217 // purpose  :
218 // =======================================================================
219 Standard_Boolean OpenGl_Workspace::Activate()
220 {
221   if (myWindow.IsNull() || !myWindow->Activate())
222   {
223     return Standard_False;
224   }
225
226   ViewMatrix_applied      = &myDefaultMatrix;
227   StructureMatrix_applied = &myDefaultMatrix;
228
229   ResetAppliedAspect();
230
231   return Standard_True;
232 }
233
234 //=======================================================================
235 //function : ResetAppliedAspect
236 //purpose  : Sets default values of GL parameters in accordance with default aspects
237 //=======================================================================
238 void OpenGl_Workspace::ResetAppliedAspect()
239 {
240   myGlContext->BindDefaultVao();
241
242   NamedStatus           = !myTextureBound.IsNull() ? OPENGL_NS_TEXTURE : 0;
243   HighlightColor        = &THE_WHITE_COLOR;
244   AspectLine_set        = &myDefaultAspectLine;
245   AspectLine_applied    = NULL;
246   AspectFace_set        = &myDefaultAspectFace;
247   AspectFace_applied    = NULL;
248   AspectMarker_set      = &myDefaultAspectMarker;
249   AspectMarker_applied  = NULL;
250   PolygonOffset_applied = THE_DEFAULT_POFFSET;
251   myCullingMode         = TelCullUndefined;
252
253   AspectLine(Standard_True);
254   AspectFace(Standard_True);
255   AspectMarker(Standard_True);
256   AspectText(Standard_True);
257
258   myGlContext->SetTypeOfLine (myDefaultAspectLine.Type());
259   myGlContext->SetLineWidth  (myDefaultAspectLine.Width());
260 }
261
262 // =======================================================================
263 // function : DisableTexture
264 // purpose  :
265 // =======================================================================
266 Handle(OpenGl_Texture) OpenGl_Workspace::DisableTexture()
267 {
268   if (myTextureBound.IsNull())
269   {
270     return myTextureBound;
271   }
272
273   const Handle(OpenGl_Sampler)& aSampler = myGlContext->TextureSampler();
274   if (!aSampler.IsNull())
275   {
276     aSampler->Unbind (*myGlContext);
277   }
278
279 #if !defined(GL_ES_VERSION_2_0)
280   // reset texture matrix because some code may expect it is identity
281   if (myGlContext->core11 != NULL)
282   {
283     GLint aMatrixMode = GL_TEXTURE;
284     glGetIntegerv (GL_MATRIX_MODE, &aMatrixMode);
285     glMatrixMode (GL_TEXTURE);
286     glLoadIdentity();
287     glMatrixMode (aMatrixMode);
288   }
289 #endif
290
291   myTextureBound->Unbind (myGlContext);
292   switch (myTextureBound->GetTarget())
293   {
294   #if !defined(GL_ES_VERSION_2_0)
295     case GL_TEXTURE_1D:
296     {
297       if (myGlContext->core11 != NULL)
298       {
299         if (myTextureBound->GetParams()->GenMode() != GL_NONE)
300         {
301           glDisable (GL_TEXTURE_GEN_S);
302         }
303         glDisable (GL_TEXTURE_1D);
304       }
305       break;
306     }
307   #endif
308     case GL_TEXTURE_2D:
309     {
310     #if !defined(GL_ES_VERSION_2_0)
311       if (myGlContext->core11 != NULL)
312       {
313         if (myTextureBound->GetParams()->GenMode() != GL_NONE)
314         {
315           glDisable (GL_TEXTURE_GEN_S);
316           glDisable (GL_TEXTURE_GEN_T);
317           if (myTextureBound->GetParams()->GenMode() == Graphic3d_TOTM_SPRITE)
318           {
319             glDisable (GL_POINT_SPRITE);
320           }
321         }
322         glDisable (GL_TEXTURE_2D);
323       }
324     #endif
325       break;
326     }
327     default: break;
328   }
329
330   Handle(OpenGl_Texture) aPrevTexture = myTextureBound;
331   myTextureBound.Nullify();
332   return aPrevTexture;
333 }
334
335 // =======================================================================
336 // function : setTextureParams
337 // purpose  :
338 // =======================================================================
339 void OpenGl_Workspace::setTextureParams (Handle(OpenGl_Texture)&                theTexture,
340                                          const Handle(Graphic3d_TextureParams)& theParams)
341 {
342   const Handle(Graphic3d_TextureParams)& aParams = theParams.IsNull() ? theTexture->GetParams() : theParams;
343   if (aParams.IsNull())
344   {
345     return;
346   }
347
348 #if !defined(GL_ES_VERSION_2_0)
349   if (myGlContext->core11 != NULL)
350   {
351     GLint anEnvMode = GL_MODULATE; // lighting mode
352     if (!aParams->IsModulate())
353     {
354       anEnvMode = GL_DECAL;
355       if (theTexture->GetFormat() == GL_ALPHA
356        || theTexture->GetFormat() == GL_LUMINANCE)
357       {
358         anEnvMode = GL_REPLACE;
359       }
360     }
361
362     // setup generation of texture coordinates
363     switch (aParams->GenMode())
364     {
365       case Graphic3d_TOTM_OBJECT:
366       {
367         glTexGeni  (GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
368         glTexGenfv (GL_S, GL_OBJECT_PLANE,     aParams->GenPlaneS().GetData());
369         if (theTexture->GetTarget() != GL_TEXTURE_1D)
370         {
371           glTexGeni  (GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
372           glTexGenfv (GL_T, GL_OBJECT_PLANE,     aParams->GenPlaneT().GetData());
373         }
374         break;
375       }
376       case Graphic3d_TOTM_SPHERE:
377       {
378         glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
379         if (theTexture->GetTarget() != GL_TEXTURE_1D)
380         {
381           glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
382         }
383         break;
384       }
385       case Graphic3d_TOTM_EYE:
386       {
387         myGlContext->WorldViewState.Push();
388
389         myGlContext->WorldViewState.SetIdentity();
390         myGlContext->ApplyWorldViewMatrix();
391
392         glTexGeni  (GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
393         glTexGenfv (GL_S, GL_EYE_PLANE,        aParams->GenPlaneS().GetData());
394
395         if (theTexture->GetTarget() != GL_TEXTURE_1D)
396         {
397           glTexGeni  (GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
398           glTexGenfv (GL_T, GL_EYE_PLANE,        aParams->GenPlaneT().GetData());
399         }
400
401         myGlContext->WorldViewState.Pop();
402
403         break;
404       }
405       case Graphic3d_TOTM_SPRITE:
406       {
407         if (myGlContext->core20fwd != NULL)
408         {
409           glEnable  (GL_POINT_SPRITE);
410           glTexEnvi (GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE);
411           anEnvMode = GL_REPLACE;
412           myGlContext->core15->glPointParameteri (GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT);
413         }
414         break;
415       }
416       case Graphic3d_TOTM_MANUAL:
417       default: break;
418     }
419
420     // setup lighting
421     glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, anEnvMode);
422   }
423 #endif
424
425   // get active sampler object to override default texture parameters
426   const Handle(OpenGl_Sampler)& aSampler = myGlContext->TextureSampler();
427
428   // setup texture filtering and wrapping
429   //if (theTexture->GetParams() != theParams)
430   const GLenum aFilter   = (aParams->Filter() == Graphic3d_TOTF_NEAREST) ? GL_NEAREST : GL_LINEAR;
431   const GLenum aWrapMode = aParams->IsRepeat() ? GL_REPEAT : myGlContext->TextureWrapClamp();
432   switch (theTexture->GetTarget())
433   {
434   #if !defined(GL_ES_VERSION_2_0)
435     case GL_TEXTURE_1D:
436     {
437       if (aSampler.IsNull() || !aSampler->IsValid())
438       {
439         glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, aFilter);
440         glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, aFilter);
441         glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_S,     aWrapMode);
442       }
443       else
444       {
445         aSampler->SetParameter (*myGlContext, GL_TEXTURE_MAG_FILTER, aFilter);
446         aSampler->SetParameter (*myGlContext, GL_TEXTURE_MIN_FILTER, aFilter);
447         aSampler->SetParameter (*myGlContext, GL_TEXTURE_WRAP_S,     aWrapMode);
448       }
449
450       break;
451     }
452   #endif
453     case GL_TEXTURE_2D:
454     {
455       GLenum aFilterMin = aFilter;
456       if (theTexture->HasMipmaps())
457       {
458         aFilterMin = GL_NEAREST_MIPMAP_NEAREST;
459         if (aParams->Filter() == Graphic3d_TOTF_BILINEAR)
460         {
461           aFilterMin = GL_LINEAR_MIPMAP_NEAREST;
462         }
463         else if (aParams->Filter() == Graphic3d_TOTF_TRILINEAR)
464         {
465           aFilterMin = GL_LINEAR_MIPMAP_LINEAR;
466         }
467
468         if (myGlContext->extAnis)
469         {
470           // setup degree of anisotropy filter
471           const GLint aMaxDegree = myGlContext->MaxDegreeOfAnisotropy();
472           GLint aDegree;
473           switch (aParams->AnisoFilter())
474           {
475             case Graphic3d_LOTA_QUALITY:
476             {
477               aDegree = aMaxDegree;
478               break;
479             }
480             case Graphic3d_LOTA_MIDDLE:
481             {
482               aDegree = (aMaxDegree <= 4) ? 2 : (aMaxDegree / 2);
483               break;
484             }
485             case Graphic3d_LOTA_FAST:
486             {
487               aDegree = 2;
488               break;
489             }
490             case Graphic3d_LOTA_OFF:
491             default:
492             {
493               aDegree = 1;
494               break;
495             }
496           }
497
498           if (aSampler.IsNull() || !aSampler->IsValid())
499           {
500             glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, aDegree);
501           }
502           else
503           {
504             aSampler->SetParameter (*myGlContext, GL_TEXTURE_MAX_ANISOTROPY_EXT, aDegree);
505           }
506         }
507       }
508
509       if (aSampler.IsNull() || !aSampler->IsValid())
510       {
511         glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, aFilterMin);
512         glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, aFilter);
513         glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,     aWrapMode);
514         glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,     aWrapMode);
515       }
516       else
517       {
518         aSampler->SetParameter (*myGlContext, GL_TEXTURE_MIN_FILTER, aFilterMin);
519         aSampler->SetParameter (*myGlContext, GL_TEXTURE_MAG_FILTER, aFilter);
520         aSampler->SetParameter (*myGlContext, GL_TEXTURE_WRAP_S,     aWrapMode);
521         aSampler->SetParameter (*myGlContext, GL_TEXTURE_WRAP_T,     aWrapMode);
522       }
523
524       break;
525     }
526     default: break;
527   }
528
529   switch (theTexture->GetTarget())
530   {
531   #if !defined(GL_ES_VERSION_2_0)
532     case GL_TEXTURE_1D:
533     {
534       if (myGlContext->core11 != NULL)
535       {
536         if (aParams->GenMode() != Graphic3d_TOTM_MANUAL)
537         {
538           glEnable (GL_TEXTURE_GEN_S);
539         }
540         glEnable (GL_TEXTURE_1D);
541       }
542       break;
543     }
544   #endif
545     case GL_TEXTURE_2D:
546     {
547     #if !defined(GL_ES_VERSION_2_0)
548       if (myGlContext->core11 != NULL)
549       {
550         if (aParams->GenMode() != Graphic3d_TOTM_MANUAL)
551         {
552           glEnable (GL_TEXTURE_GEN_S);
553           glEnable (GL_TEXTURE_GEN_T);
554         }
555         glEnable (GL_TEXTURE_2D);
556       }
557     #endif
558       break;
559     }
560     default: break;
561   }
562
563   theTexture->SetParams (aParams);
564 }
565
566 // =======================================================================
567 // function : EnableTexture
568 // purpose  :
569 // =======================================================================
570 Handle(OpenGl_Texture) OpenGl_Workspace::EnableTexture (const Handle(OpenGl_Texture)&          theTexture,
571                                                         const Handle(Graphic3d_TextureParams)& theParams)
572 {
573   if (theTexture.IsNull() || !theTexture->IsValid())
574   {
575     return DisableTexture();
576   }
577
578   if (myTextureBound == theTexture
579    && (theParams.IsNull() || theParams == theTexture->GetParams()))
580   {
581     // already bound
582     return myTextureBound;
583   }
584
585   Handle(OpenGl_Texture) aPrevTexture = DisableTexture();
586   myTextureBound = theTexture;
587   myTextureBound->Bind (myGlContext);
588   setTextureParams (myTextureBound, theParams);
589
590   // If custom sampler object is available it will be
591   // used for overriding default texture parameters
592   const Handle(OpenGl_Sampler)& aSampler = myGlContext->TextureSampler();
593
594   if (!aSampler.IsNull() && aSampler->IsValid())
595   {
596     aSampler->Bind (*myGlContext);
597   }
598
599   return aPrevTexture;
600 }
601
602 // =======================================================================
603 // function : TelUpdatePolygonOffsets
604 // purpose  :
605 // =======================================================================
606 static void TelUpdatePolygonOffsets (const TEL_POFFSET_PARAM& theOffsetData)
607 {
608   if ((theOffsetData.mode & Aspect_POM_Fill) == Aspect_POM_Fill)
609   {
610     glEnable (GL_POLYGON_OFFSET_FILL);
611   }
612   else
613   {
614     glDisable (GL_POLYGON_OFFSET_FILL);
615   }
616
617 #if !defined(GL_ES_VERSION_2_0)
618   if ((theOffsetData.mode & Aspect_POM_Line) == Aspect_POM_Line)
619   {
620     glEnable (GL_POLYGON_OFFSET_LINE);
621   }
622   else
623   {
624     glDisable (GL_POLYGON_OFFSET_LINE);
625   }
626
627   if ((theOffsetData.mode & Aspect_POM_Point) == Aspect_POM_Point)
628   {
629     glEnable (GL_POLYGON_OFFSET_POINT);
630   }
631   else
632   {
633     glDisable (GL_POLYGON_OFFSET_POINT);
634   }
635 #endif
636
637   glPolygonOffset (theOffsetData.factor, theOffsetData.units);
638 }
639
640 // =======================================================================
641 // function : updateMaterial
642 // purpose  :
643 // =======================================================================
644 void OpenGl_Workspace::updateMaterial (const int theFlag)
645 {
646   // Case of hidden line
647   if (AspectFace_set->InteriorStyle() == Aspect_IS_HIDDENLINE)
648   {
649     myAspectFaceHl = *AspectFace_set; // copy all values including line edge aspect
650     myAspectFaceHl.ChangeIntFront().matcol     = myView->BackgroundColor();
651     myAspectFaceHl.ChangeIntFront().color_mask = 0;
652     myAspectFaceHl.ChangeIntFront().color_mask = 0;
653
654     AspectFace_set = &myAspectFaceHl;
655     return;
656   }
657
658   const OPENGL_SURF_PROP* aProps = &AspectFace_set->IntFront();
659   GLenum aFace = GL_FRONT_AND_BACK;
660   if (theFlag == TEL_BACK_MATERIAL)
661   {
662     aFace  = GL_BACK;
663     aProps = &AspectFace_set->IntBack();
664   }
665   else if (AspectFace_set->DistinguishingMode() == TOn
666         && !(NamedStatus & OPENGL_NS_RESMAT))
667   {
668     aFace = GL_FRONT;
669   }
670
671   myMatTmp.Init (*aProps);
672
673   // handling transparency
674   if (NamedStatus & OPENGL_NS_2NDPASSDO)
675   {
676     // second pass
677     myMatTmp.Diffuse.a() = aProps->env_reflexion;
678   }
679   else
680   {
681     if (aProps->env_reflexion != 0.0f)
682     {
683       // if the material reflects the environment scene, the second pass is needed
684       NamedStatus |= OPENGL_NS_2NDPASSNEED;
685     }
686
687     if (aProps->trans != 1.0f)
688     {
689       // render transparent
690       myMatTmp.Diffuse.a() = aProps->trans;
691       glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
692       glEnable    (GL_BLEND);
693       if (myUseDepthWrite)
694       {
695         glDepthMask (GL_FALSE);
696       }
697     }
698     else
699     {
700       // render opaque
701       if ((NamedStatus & OPENGL_NS_ANTIALIASING) == 0)
702       {
703         glBlendFunc (GL_ONE, GL_ZERO);
704         glDisable   (GL_BLEND);
705       }
706       if (myUseDepthWrite)
707       {
708         glDepthMask (GL_TRUE);
709       }
710     }
711   }
712
713   // do not update material properties in case of zero reflection mode,
714   // because GL lighting will be disabled by OpenGl_PrimitiveArray::DrawArray() anyway.
715   if (aProps->color_mask == 0)
716   {
717     return;
718   }
719
720   // reset material
721   if (NamedStatus & OPENGL_NS_RESMAT)
722   {
723   #if !defined(GL_ES_VERSION_2_0)
724     if (myGlContext->core11 != NULL)
725     {
726       myGlContext->core11->glMaterialfv (aFace, GL_AMBIENT,   myMatTmp.Ambient.GetData());
727       myGlContext->core11->glMaterialfv (aFace, GL_DIFFUSE,   myMatTmp.Diffuse.GetData());
728       myGlContext->core11->glMaterialfv (aFace, GL_SPECULAR,  myMatTmp.Specular.GetData());
729       myGlContext->core11->glMaterialfv (aFace, GL_EMISSION,  myMatTmp.Emission.GetData());
730       myGlContext->core11->glMaterialf  (aFace, GL_SHININESS, myMatTmp.Shine());
731     }
732   #endif
733
734     if (theFlag == TEL_FRONT_MATERIAL)
735     {
736       myMatFront = myMatTmp;
737       myMatBack  = myMatTmp;
738     }
739     else
740     {
741       myMatBack = myMatTmp;
742     }
743
744     NamedStatus &= ~OPENGL_NS_RESMAT;
745     return;
746   }
747
748   // reduce updates
749   OpenGl_Material& anOld = (theFlag == TEL_FRONT_MATERIAL)
750                          ? myMatFront
751                          : myMatBack;
752 #if !defined(GL_ES_VERSION_2_0)
753   if (myGlContext->core11 != NULL)
754   {
755     if (myMatTmp.Ambient.r() != anOld.Ambient.r()
756      || myMatTmp.Ambient.g() != anOld.Ambient.g()
757      || myMatTmp.Ambient.b() != anOld.Ambient.b())
758     {
759       myGlContext->core11->glMaterialfv (aFace, GL_AMBIENT, myMatTmp.Ambient.GetData());
760     }
761     if (myMatTmp.Diffuse.r() != anOld.Diffuse.r()
762      || myMatTmp.Diffuse.g() != anOld.Diffuse.g()
763      || myMatTmp.Diffuse.b() != anOld.Diffuse.b()
764      || fabs (myMatTmp.Diffuse.a() - anOld.Diffuse.a()) > 0.01f)
765     {
766       myGlContext->core11->glMaterialfv (aFace, GL_DIFFUSE, myMatTmp.Diffuse.GetData());
767     }
768     if (myMatTmp.Specular.r() != anOld.Specular.r()
769      || myMatTmp.Specular.g() != anOld.Specular.g()
770      || myMatTmp.Specular.b() != anOld.Specular.b())
771     {
772       myGlContext->core11->glMaterialfv (aFace, GL_SPECULAR, myMatTmp.Specular.GetData());
773     }
774     if (myMatTmp.Emission.r() != anOld.Emission.r()
775      || myMatTmp.Emission.g() != anOld.Emission.g()
776      || myMatTmp.Emission.b() != anOld.Emission.b())
777     {
778       myGlContext->core11->glMaterialfv (aFace, GL_EMISSION, myMatTmp.Emission.GetData());
779     }
780     if (myMatTmp.Shine() != anOld.Shine())
781     {
782       myGlContext->core11->glMaterialf (aFace, GL_SHININESS, myMatTmp.Shine());
783     }
784   }
785 #endif
786   anOld = myMatTmp;
787   if (aFace == GL_FRONT_AND_BACK)
788   {
789     myMatBack = myMatTmp;
790   }
791 }
792
793 // =======================================================================
794 // function : SetAspectLine
795 // purpose  :
796 // =======================================================================
797 const OpenGl_AspectLine * OpenGl_Workspace::SetAspectLine(const OpenGl_AspectLine *AnAspect)
798 {
799   const OpenGl_AspectLine *AspectLine_old = AspectLine_set;
800   AspectLine_set = AnAspect;
801   return AspectLine_old;
802 }
803
804 // =======================================================================
805 // function : SetAspectFace
806 // purpose  :
807 // =======================================================================
808 const OpenGl_AspectFace * OpenGl_Workspace::SetAspectFace(const OpenGl_AspectFace *AnAspect)
809 {
810   const OpenGl_AspectFace *AspectFace_old = AspectFace_set;
811   AspectFace_set = AnAspect;
812   return AspectFace_old;
813 }
814
815 // =======================================================================
816 // function : SetAspectMarker
817 // purpose  :
818 // =======================================================================
819 const OpenGl_AspectMarker * OpenGl_Workspace::SetAspectMarker(const OpenGl_AspectMarker *AnAspect)
820 {
821   const OpenGl_AspectMarker *AspectMarker_old = AspectMarker_set;
822   AspectMarker_set = AnAspect;
823   return AspectMarker_old;
824 }
825
826 // =======================================================================
827 // function : SetAspectText
828 // purpose  :
829 // =======================================================================
830 const OpenGl_AspectText * OpenGl_Workspace::SetAspectText(const OpenGl_AspectText *AnAspect)
831 {
832   const OpenGl_AspectText *AspectText_old = AspectText_set;
833   AspectText_set = AnAspect;
834   return AspectText_old;
835 }
836
837 // =======================================================================
838 // function : AspectLine
839 // purpose  :
840 // =======================================================================
841 const OpenGl_AspectLine * OpenGl_Workspace::AspectLine(const Standard_Boolean theWithApply)
842 {
843   if (theWithApply)
844   {
845     AspectLine_applied = AspectLine_set;
846   }
847
848   return AspectLine_set;
849 }
850
851 // =======================================================================
852 // function : AspectFace
853 // purpose  :
854 // =======================================================================
855 const OpenGl_AspectFace* OpenGl_Workspace::AspectFace (const Standard_Boolean theToApply)
856 {
857   if (!theToApply)
858   {
859     return AspectFace_set;
860   }
861
862   if (myView->BackfacingModel() == Graphic3d_TOBM_AUTOMATIC)
863   {
864     // manage back face culling mode, disable culling when clipping is enabled
865     TelCullMode aCullingMode = (myGlContext->Clipping().IsClippingOrCappingOn()
866                              || AspectFace_set->InteriorStyle() == Aspect_IS_HATCH)
867                              ? TelCullNone
868                              : (TelCullMode )AspectFace_set->CullingMode();
869     if (aCullingMode != TelCullNone
870      && !(NamedStatus & OPENGL_NS_2NDPASSDO))
871     {
872       // disable culling in case of translucent shading aspect
873       if (AspectFace_set->IntFront().trans != 1.0f)
874       {
875         aCullingMode = TelCullNone;
876       }
877     }
878     if (myCullingMode != aCullingMode)
879     {
880       myCullingMode = aCullingMode;
881       switch (myCullingMode)
882       {
883         case TelCullNone:
884         case TelCullUndefined:
885         {
886           glDisable (GL_CULL_FACE);
887           break;
888         }
889         case TelCullFront:
890         {
891           glCullFace (GL_FRONT);
892           glEnable (GL_CULL_FACE);
893           break;
894         }
895         case TelCullBack:
896         {
897           glCullFace (GL_BACK);
898           glEnable (GL_CULL_FACE);
899           break;
900         }
901       }
902     }
903   }
904
905   if (AspectFace_set == AspectFace_applied)
906   {
907     return AspectFace_set;
908   }
909
910 #if !defined(GL_ES_VERSION_2_0)
911   const Aspect_InteriorStyle anIntstyle = AspectFace_set->InteriorStyle();
912   if (AspectFace_applied == NULL || AspectFace_applied->InteriorStyle() != anIntstyle)
913   {
914     switch (anIntstyle)
915     {
916       case Aspect_IS_EMPTY:
917       case Aspect_IS_HOLLOW:
918       {
919         glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
920         break;
921       }
922       case Aspect_IS_HATCH:
923       {
924         glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
925         myLineAttribs->SetTypeOfHatch (AspectFace_applied != NULL ? AspectFace_applied->Hatch() : TEL_HS_SOLID);
926         break;
927       }
928       case Aspect_IS_SOLID:
929       case Aspect_IS_HIDDENLINE:
930       {
931         glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
932         if (myGlContext->core11 != NULL)
933         {
934           glDisable (GL_POLYGON_STIPPLE);
935         }
936         break;
937       }
938       case Aspect_IS_POINT:
939       {
940         glPolygonMode (GL_FRONT_AND_BACK, GL_POINT);
941         break;
942       }
943     }
944   }
945
946   if (anIntstyle == Aspect_IS_HATCH)
947   {
948     const Tint hatchstyle = AspectFace_set->Hatch();
949     if (AspectFace_applied == NULL || AspectFace_applied->Hatch() != hatchstyle)
950     {
951       myLineAttribs->SetTypeOfHatch (hatchstyle);
952     }
953   }
954 #endif
955
956   // Aspect_POM_None means: do not change current settings
957   if ((AspectFace_set->PolygonOffset().mode & Aspect_POM_None) != Aspect_POM_None)
958   {
959     if (PolygonOffset_applied.mode   != AspectFace_set->PolygonOffset().mode
960      || PolygonOffset_applied.factor != AspectFace_set->PolygonOffset().factor
961      || PolygonOffset_applied.units  != AspectFace_set->PolygonOffset().units)
962     {
963       SetPolygonOffset (AspectFace_set->PolygonOffset().mode,
964                         AspectFace_set->PolygonOffset().factor,
965                         AspectFace_set->PolygonOffset().units);
966     }
967   }
968
969   updateMaterial (TEL_FRONT_MATERIAL);
970   if (AspectFace_set->DistinguishingMode() == TOn)
971   {
972     updateMaterial (TEL_BACK_MATERIAL);
973   }
974
975   if ((NamedStatus & OPENGL_NS_FORBIDSETTEX) == 0)
976   {
977     if (AspectFace_set->DoTextureMap())
978     {
979       EnableTexture (AspectFace_set->TextureRes (myGlContext),
980                      AspectFace_set->TextureParams());
981     }
982     else
983     {
984       DisableTexture();
985     }
986   }
987
988   AspectFace_applied = AspectFace_set;
989   return AspectFace_set;
990 }
991
992 //=======================================================================
993 //function : SetPolygonOffset
994 //purpose  :
995 //=======================================================================
996 void OpenGl_Workspace::SetPolygonOffset (int theMode,
997                                          Standard_ShortReal theFactor,
998                                          Standard_ShortReal theUnits)
999 {
1000   PolygonOffset_applied.mode   = theMode;
1001   PolygonOffset_applied.factor = theFactor;
1002   PolygonOffset_applied.units  = theUnits;
1003
1004   TelUpdatePolygonOffsets (PolygonOffset_applied);
1005 }
1006
1007 // =======================================================================
1008 // function : AspectMarker
1009 // purpose  :
1010 // =======================================================================
1011 const OpenGl_AspectMarker* OpenGl_Workspace::AspectMarker (const Standard_Boolean theToApply)
1012 {
1013   if (theToApply && (AspectMarker_set != AspectMarker_applied))
1014   {
1015     if (!AspectMarker_applied || (AspectMarker_set->Scale() != AspectMarker_applied->Scale()))
1016     {
1017     #if !defined(GL_ES_VERSION_2_0)
1018       glPointSize (AspectMarker_set->Scale());
1019     #ifdef HAVE_GL2PS
1020       gl2psPointSize (AspectMarker_set->Scale());
1021     #endif
1022     #endif
1023     }
1024     AspectMarker_applied = AspectMarker_set;
1025   }
1026   return AspectMarker_set;
1027 }
1028
1029 // =======================================================================
1030 // function : AspectText
1031 // purpose  :
1032 // =======================================================================
1033 const OpenGl_AspectText* OpenGl_Workspace::AspectText (const Standard_Boolean theWithApply)
1034 {
1035   if (theWithApply)
1036   {
1037     AspectText_applied = AspectText_set;
1038   }
1039
1040   return AspectText_set;
1041 }
1042
1043 // =======================================================================
1044 // function : Width
1045 // purpose  :
1046 // =======================================================================
1047 Standard_Integer OpenGl_Workspace::Width()  const
1048 {
1049   return !myView->GlWindow().IsNull() ? myView->GlWindow()->Width() : 0;
1050 }
1051
1052 // =======================================================================
1053 // function : Height
1054 // purpose  :
1055 // =======================================================================
1056 Standard_Integer OpenGl_Workspace::Height() const
1057 {
1058   return !myView->GlWindow().IsNull() ? myView->GlWindow()->Height() : 0;
1059 }
1060
1061 // =======================================================================
1062 // function : UseGLLight
1063 // purpose  :
1064 // =======================================================================
1065 Standard_Boolean OpenGl_Workspace::UseGLLight() const
1066 {
1067   return myView->IsGLLightEnabled();
1068 }
1069
1070 // =======================================================================
1071 // function : AntiAliasingMode
1072 // purpose  :
1073 // =======================================================================
1074 Standard_Integer OpenGl_Workspace::AntiAliasingMode() const
1075 {
1076   return myView->IsAntialiasingEnabled();
1077 }
1078
1079 // =======================================================================
1080 // function : IsCullingEnabled
1081 // purpose  :
1082 // =======================================================================
1083 Standard_Boolean OpenGl_Workspace::IsCullingEnabled() const
1084 {
1085   return myView->IsCullingEnabled();
1086 }
1087
1088 // =======================================================================
1089 // function : FBOCreate
1090 // purpose  :
1091 // =======================================================================
1092 Graphic3d_PtrFrameBuffer OpenGl_Workspace::FBOCreate (const Standard_Integer theWidth,
1093                                                       const Standard_Integer theHeight)
1094 {
1095   // activate OpenGL context
1096   if (!Activate())
1097     return NULL;
1098
1099   // create the FBO
1100   const Handle(OpenGl_Context)& aCtx = GetGlContext();
1101   OpenGl_FrameBuffer* aFrameBuffer = new OpenGl_FrameBuffer();
1102   if (!aFrameBuffer->Init (aCtx, theWidth, theHeight, GL_RGBA8, GL_DEPTH24_STENCIL8, 0))
1103   {
1104     aFrameBuffer->Release (aCtx.operator->());
1105     delete aFrameBuffer;
1106     return NULL;
1107   }
1108   return (Graphic3d_PtrFrameBuffer )aFrameBuffer;
1109 }
1110
1111 // =======================================================================
1112 // function : FBORelease
1113 // purpose  :
1114 // =======================================================================
1115 void OpenGl_Workspace::FBORelease (Graphic3d_PtrFrameBuffer theFBOPtr)
1116 {
1117   // activate OpenGL context
1118   if (!Activate()
1119    || theFBOPtr == NULL)
1120   {
1121     return;
1122   }
1123
1124   // release the object
1125   OpenGl_FrameBuffer* aFrameBuffer = (OpenGl_FrameBuffer*)theFBOPtr;
1126   if (aFrameBuffer != NULL)
1127   {
1128     aFrameBuffer->Release (GetGlContext().operator->());
1129   }
1130   delete aFrameBuffer;
1131 }
1132
1133 inline bool getDataFormat (const Image_PixMap& theData,
1134                            GLenum&             thePixelFormat,
1135                            GLenum&             theDataType)
1136 {
1137   thePixelFormat = GL_RGB;
1138   theDataType    = GL_UNSIGNED_BYTE;
1139   switch (theData.Format())
1140   {
1141   #if !defined(GL_ES_VERSION_2_0)
1142     case Image_PixMap::ImgGray:
1143       thePixelFormat = GL_DEPTH_COMPONENT;
1144       theDataType    = GL_UNSIGNED_BYTE;
1145       return true;
1146     case Image_PixMap::ImgGrayF:
1147       thePixelFormat = GL_DEPTH_COMPONENT;
1148       theDataType    = GL_FLOAT;
1149       return true;
1150     case Image_PixMap::ImgBGR:
1151       thePixelFormat = GL_BGR;
1152       theDataType    = GL_UNSIGNED_BYTE;
1153       return true;
1154     case Image_PixMap::ImgBGRA:
1155     case Image_PixMap::ImgBGR32:
1156       thePixelFormat = GL_BGRA;
1157       theDataType    = GL_UNSIGNED_BYTE;
1158       return true;
1159     case Image_PixMap::ImgBGRF:
1160       thePixelFormat = GL_BGR;
1161       theDataType    = GL_FLOAT;
1162       return true;
1163     case Image_PixMap::ImgBGRAF:
1164       thePixelFormat = GL_BGRA;
1165       theDataType    = GL_FLOAT;
1166       return true;
1167   #else
1168     case Image_PixMap::ImgGray:
1169     case Image_PixMap::ImgGrayF:
1170     case Image_PixMap::ImgBGR:
1171     case Image_PixMap::ImgBGRA:
1172     case Image_PixMap::ImgBGR32:
1173     case Image_PixMap::ImgBGRF:
1174     case Image_PixMap::ImgBGRAF:
1175       return false;
1176   #endif
1177     case Image_PixMap::ImgRGB:
1178       thePixelFormat = GL_RGB;
1179       theDataType    = GL_UNSIGNED_BYTE;
1180       return true;
1181     case Image_PixMap::ImgRGBA:
1182     case Image_PixMap::ImgRGB32:
1183       thePixelFormat = GL_RGBA;
1184       theDataType    = GL_UNSIGNED_BYTE;
1185       return true;
1186     case Image_PixMap::ImgRGBF:
1187       thePixelFormat = GL_RGB;
1188       theDataType    = GL_FLOAT;
1189       return true;
1190     case Image_PixMap::ImgRGBAF:
1191       thePixelFormat = GL_RGBA;
1192       theDataType    = GL_FLOAT;
1193       return true;
1194     case Image_PixMap::ImgAlpha:
1195     case Image_PixMap::ImgAlphaF:
1196       return false; // GL_ALPHA is no more supported in core context
1197     case Image_PixMap::ImgUNKNOWN:
1198       return false;
1199   }
1200   return false;
1201 }
1202
1203 // =======================================================================
1204 // function : getAligned
1205 // purpose  :
1206 // =======================================================================
1207 inline Standard_Size getAligned (const Standard_Size theNumber,
1208                                  const Standard_Size theAlignment)
1209 {
1210   return theNumber + theAlignment - 1 - (theNumber - 1) % theAlignment;
1211 }
1212
1213 // =======================================================================
1214 // function : BufferDump
1215 // purpose  :
1216 // =======================================================================
1217 Standard_Boolean OpenGl_Workspace::BufferDump (OpenGl_FrameBuffer*         theFBOPtr,
1218                                                Image_PixMap&               theImage,
1219                                                const Graphic3d_BufferType& theBufferType)
1220 {
1221   GLenum aFormat, aType;
1222   if (theImage.IsEmpty()
1223    || !getDataFormat (theImage, aFormat, aType)
1224    || !Activate())
1225   {
1226     return Standard_False;
1227   }
1228 #if !defined(GL_ES_VERSION_2_0)
1229   GLint aReadBufferPrev = GL_BACK;
1230   if (theBufferType == Graphic3d_BT_Depth
1231    && aFormat != GL_DEPTH_COMPONENT)
1232   {
1233     return Standard_False;
1234   }
1235 #endif
1236
1237   // bind FBO if used
1238   if (theFBOPtr != NULL && theFBOPtr->IsValid())
1239   {
1240     theFBOPtr->BindBuffer (GetGlContext());
1241   }
1242   else
1243   {
1244   #if !defined(GL_ES_VERSION_2_0)
1245     glGetIntegerv (GL_READ_BUFFER, &aReadBufferPrev);
1246     GLint aDrawBufferPrev = GL_BACK;
1247     glGetIntegerv (GL_DRAW_BUFFER, &aDrawBufferPrev);
1248     glReadBuffer (aDrawBufferPrev);
1249   #endif
1250   }
1251
1252   // setup alignment
1253   const GLint anAligment   = Min (GLint(theImage.MaxRowAligmentBytes()), 8); // limit to 8 bytes for OpenGL
1254   glPixelStorei (GL_PACK_ALIGNMENT, anAligment);
1255   bool isBatchCopy = !theImage.IsTopDown();
1256
1257   const GLint   anExtraBytes       = GLint(theImage.RowExtraBytes());
1258   GLint         aPixelsWidth       = GLint(theImage.SizeRowBytes() / theImage.SizePixelBytes());
1259   Standard_Size aSizeRowBytesEstim = getAligned (theImage.SizePixelBytes() * aPixelsWidth, anAligment);
1260   if (anExtraBytes < anAligment)
1261   {
1262     aPixelsWidth = 0;
1263   }
1264   else if (aSizeRowBytesEstim != theImage.SizeRowBytes())
1265   {
1266     aPixelsWidth = 0;
1267     isBatchCopy  = false;
1268   }
1269 #if !defined(GL_ES_VERSION_2_0)
1270   glPixelStorei (GL_PACK_ROW_LENGTH, aPixelsWidth);
1271 #else
1272   if (aPixelsWidth != 0)
1273   {
1274     isBatchCopy = false;
1275   }
1276 #endif
1277
1278   if (!isBatchCopy)
1279   {
1280     // copy row by row
1281     for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
1282     {
1283       // Image_PixMap rows indexation always starts from the upper corner
1284       // while order in memory depends on the flag and processed by ChangeRow() method
1285       glReadPixels (0, GLint(theImage.SizeY() - aRow - 1), GLsizei (theImage.SizeX()), 1, aFormat, aType, theImage.ChangeRow (aRow));
1286     }
1287   }
1288   else
1289   {
1290     glReadPixels (0, 0, GLsizei (theImage.SizeX()), GLsizei (theImage.SizeY()), aFormat, aType, theImage.ChangeData());
1291   }
1292
1293   glPixelStorei (GL_PACK_ALIGNMENT,  1);
1294 #if !defined(GL_ES_VERSION_2_0)
1295   glPixelStorei (GL_PACK_ROW_LENGTH, 0);
1296 #endif
1297
1298   if (theFBOPtr != NULL && theFBOPtr->IsValid())
1299   {
1300     theFBOPtr->UnbindBuffer (GetGlContext());
1301   }
1302   else
1303   {
1304   #if !defined(GL_ES_VERSION_2_0)
1305     glReadBuffer (aReadBufferPrev);
1306   #endif
1307   }
1308   return Standard_True;
1309 }
1310
1311 // =======================================================================
1312 // function : CanRender
1313 // purpose  :
1314 // =======================================================================
1315 Standard_Boolean OpenGl_RaytraceFilter::CanRender (const OpenGl_Element* theElement)
1316 {
1317   Standard_Boolean aPrevFilterResult = Standard_True;
1318   if (!myPrevRenderFilter.IsNull())
1319   {
1320     aPrevFilterResult = myPrevRenderFilter->CanRender (theElement);
1321   }
1322   return aPrevFilterResult &&
1323     !OpenGl_Raytrace::IsRaytracedElement (theElement);
1324 }