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