8b94e7264bb3b4eb6b43df8a0624d79a90d5c4be
[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   GLint aMatrixMode = GL_TEXTURE;
350   if (myGlContext->core11 != NULL)
351   {
352     glGetIntegerv (GL_MATRIX_MODE, &aMatrixMode);
353
354     // setup texture matrix
355     glMatrixMode (GL_TEXTURE);
356     OpenGl_Mat4 aTextureMat;
357     const Graphic3d_Vec2& aScale = aParams->Scale();
358     const Graphic3d_Vec2& aTrans = aParams->Translation();
359     Graphic3d_TransformUtils::Scale     (aTextureMat,  aScale.x(),  aScale.y(), 1.0f);
360     Graphic3d_TransformUtils::Translate (aTextureMat, -aTrans.x(), -aTrans.y(), 0.0f);
361     Graphic3d_TransformUtils::Rotate    (aTextureMat, -aParams->Rotation(), 0.0f, 0.0f, 1.0f);
362     glLoadMatrixf (aTextureMat);
363
364     GLint anEnvMode = GL_MODULATE; // lighting mode
365     if (!aParams->IsModulate())
366     {
367       anEnvMode = GL_DECAL;
368       if (theTexture->GetFormat() == GL_ALPHA
369        || theTexture->GetFormat() == GL_LUMINANCE)
370       {
371         anEnvMode = GL_REPLACE;
372       }
373     }
374
375     // setup generation of texture coordinates
376     switch (aParams->GenMode())
377     {
378       case Graphic3d_TOTM_OBJECT:
379       {
380         glTexGeni  (GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
381         glTexGenfv (GL_S, GL_OBJECT_PLANE,     aParams->GenPlaneS().GetData());
382         if (theTexture->GetTarget() != GL_TEXTURE_1D)
383         {
384           glTexGeni  (GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
385           glTexGenfv (GL_T, GL_OBJECT_PLANE,     aParams->GenPlaneT().GetData());
386         }
387         break;
388       }
389       case Graphic3d_TOTM_SPHERE:
390       {
391         glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
392         if (theTexture->GetTarget() != GL_TEXTURE_1D)
393         {
394           glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
395         }
396         break;
397       }
398       case Graphic3d_TOTM_EYE:
399       {
400         myGlContext->WorldViewState.Push();
401
402         myGlContext->WorldViewState.SetIdentity();
403         myGlContext->ApplyWorldViewMatrix();
404
405         glTexGeni  (GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
406         glTexGenfv (GL_S, GL_EYE_PLANE,        aParams->GenPlaneS().GetData());
407
408         if (theTexture->GetTarget() != GL_TEXTURE_1D)
409         {
410           glTexGeni  (GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
411           glTexGenfv (GL_T, GL_EYE_PLANE,        aParams->GenPlaneT().GetData());
412         }
413
414         myGlContext->WorldViewState.Pop();
415
416         break;
417       }
418       case Graphic3d_TOTM_SPRITE:
419       {
420         if (myGlContext->core20fwd != NULL)
421         {
422           glEnable  (GL_POINT_SPRITE);
423           glTexEnvi (GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE);
424           anEnvMode = GL_REPLACE;
425           myGlContext->core15->glPointParameteri (GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT);
426         }
427         break;
428       }
429       case Graphic3d_TOTM_MANUAL:
430       default: break;
431     }
432
433     // setup lighting
434     glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, anEnvMode);
435   }
436 #endif
437
438   // get active sampler object to override default texture parameters
439   const Handle(OpenGl_Sampler)& aSampler = myGlContext->TextureSampler();
440
441   // setup texture filtering and wrapping
442   //if (theTexture->GetParams() != theParams)
443   const GLenum aFilter   = (aParams->Filter() == Graphic3d_TOTF_NEAREST) ? GL_NEAREST : GL_LINEAR;
444   const GLenum aWrapMode = aParams->IsRepeat() ? GL_REPEAT : myGlContext->TextureWrapClamp();
445   switch (theTexture->GetTarget())
446   {
447   #if !defined(GL_ES_VERSION_2_0)
448     case GL_TEXTURE_1D:
449     {
450       if (aSampler.IsNull() || !aSampler->IsValid())
451       {
452         glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, aFilter);
453         glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, aFilter);
454         glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_S,     aWrapMode);
455       }
456       else
457       {
458         aSampler->SetParameter (*myGlContext, GL_TEXTURE_MAG_FILTER, aFilter);
459         aSampler->SetParameter (*myGlContext, GL_TEXTURE_MIN_FILTER, aFilter);
460         aSampler->SetParameter (*myGlContext, GL_TEXTURE_WRAP_S,     aWrapMode);
461       }
462
463       break;
464     }
465   #endif
466     case GL_TEXTURE_2D:
467     {
468       GLenum aFilterMin = aFilter;
469       if (theTexture->HasMipmaps())
470       {
471         aFilterMin = GL_NEAREST_MIPMAP_NEAREST;
472         if (aParams->Filter() == Graphic3d_TOTF_BILINEAR)
473         {
474           aFilterMin = GL_LINEAR_MIPMAP_NEAREST;
475         }
476         else if (aParams->Filter() == Graphic3d_TOTF_TRILINEAR)
477         {
478           aFilterMin = GL_LINEAR_MIPMAP_LINEAR;
479         }
480
481         if (myGlContext->extAnis)
482         {
483           // setup degree of anisotropy filter
484           const GLint aMaxDegree = myGlContext->MaxDegreeOfAnisotropy();
485           GLint aDegree;
486           switch (aParams->AnisoFilter())
487           {
488             case Graphic3d_LOTA_QUALITY:
489             {
490               aDegree = aMaxDegree;
491               break;
492             }
493             case Graphic3d_LOTA_MIDDLE:
494             {
495               aDegree = (aMaxDegree <= 4) ? 2 : (aMaxDegree / 2);
496               break;
497             }
498             case Graphic3d_LOTA_FAST:
499             {
500               aDegree = 2;
501               break;
502             }
503             case Graphic3d_LOTA_OFF:
504             default:
505             {
506               aDegree = 1;
507               break;
508             }
509           }
510
511           if (aSampler.IsNull() || !aSampler->IsValid())
512           {
513             glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, aDegree);
514           }
515           else
516           {
517             aSampler->SetParameter (*myGlContext, GL_TEXTURE_MAX_ANISOTROPY_EXT, aDegree);
518           }
519         }
520       }
521
522       if (aSampler.IsNull() || !aSampler->IsValid())
523       {
524         glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, aFilterMin);
525         glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, aFilter);
526         glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,     aWrapMode);
527         glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,     aWrapMode);
528       }
529       else
530       {
531         aSampler->SetParameter (*myGlContext, GL_TEXTURE_MIN_FILTER, aFilterMin);
532         aSampler->SetParameter (*myGlContext, GL_TEXTURE_MAG_FILTER, aFilter);
533         aSampler->SetParameter (*myGlContext, GL_TEXTURE_WRAP_S,     aWrapMode);
534         aSampler->SetParameter (*myGlContext, GL_TEXTURE_WRAP_T,     aWrapMode);
535       }
536
537       break;
538     }
539     default: break;
540   }
541
542   switch (theTexture->GetTarget())
543   {
544   #if !defined(GL_ES_VERSION_2_0)
545     case GL_TEXTURE_1D:
546     {
547       if (myGlContext->core11 != NULL)
548       {
549         if (aParams->GenMode() != Graphic3d_TOTM_MANUAL)
550         {
551           glEnable (GL_TEXTURE_GEN_S);
552         }
553         glEnable (GL_TEXTURE_1D);
554       }
555       break;
556     }
557   #endif
558     case GL_TEXTURE_2D:
559     {
560     #if !defined(GL_ES_VERSION_2_0)
561       if (myGlContext->core11 != NULL)
562       {
563         if (aParams->GenMode() != Graphic3d_TOTM_MANUAL)
564         {
565           glEnable (GL_TEXTURE_GEN_S);
566           glEnable (GL_TEXTURE_GEN_T);
567         }
568         glEnable (GL_TEXTURE_2D);
569       }
570     #endif
571       break;
572     }
573     default: break;
574   }
575
576 #if !defined(GL_ES_VERSION_2_0)
577   if (myGlContext->core11 != NULL)
578   {
579     glMatrixMode (aMatrixMode); // turn back active matrix
580   }
581 #endif
582   theTexture->SetParams (aParams);
583 }
584
585 // =======================================================================
586 // function : EnableTexture
587 // purpose  :
588 // =======================================================================
589 Handle(OpenGl_Texture) OpenGl_Workspace::EnableTexture (const Handle(OpenGl_Texture)&          theTexture,
590                                                         const Handle(Graphic3d_TextureParams)& theParams)
591 {
592   if (theTexture.IsNull() || !theTexture->IsValid())
593   {
594     return DisableTexture();
595   }
596
597   if (myTextureBound == theTexture
598    && (theParams.IsNull() || theParams == theTexture->GetParams()))
599   {
600     // already bound
601     return myTextureBound;
602   }
603
604   Handle(OpenGl_Texture) aPrevTexture = DisableTexture();
605   myTextureBound = theTexture;
606   myTextureBound->Bind (myGlContext);
607   setTextureParams (myTextureBound, theParams);
608
609   // If custom sampler object is available it will be
610   // used for overriding default texture parameters
611   const Handle(OpenGl_Sampler)& aSampler = myGlContext->TextureSampler();
612
613   if (!aSampler.IsNull() && aSampler->IsValid())
614   {
615     aSampler->Bind (*myGlContext);
616   }
617
618   return aPrevTexture;
619 }
620
621 // =======================================================================
622 // function : TelUpdatePolygonOffsets
623 // purpose  :
624 // =======================================================================
625 static void TelUpdatePolygonOffsets (const TEL_POFFSET_PARAM& theOffsetData)
626 {
627   if ((theOffsetData.mode & Aspect_POM_Fill) == Aspect_POM_Fill)
628   {
629     glEnable (GL_POLYGON_OFFSET_FILL);
630   }
631   else
632   {
633     glDisable (GL_POLYGON_OFFSET_FILL);
634   }
635
636 #if !defined(GL_ES_VERSION_2_0)
637   if ((theOffsetData.mode & Aspect_POM_Line) == Aspect_POM_Line)
638   {
639     glEnable (GL_POLYGON_OFFSET_LINE);
640   }
641   else
642   {
643     glDisable (GL_POLYGON_OFFSET_LINE);
644   }
645
646   if ((theOffsetData.mode & Aspect_POM_Point) == Aspect_POM_Point)
647   {
648     glEnable (GL_POLYGON_OFFSET_POINT);
649   }
650   else
651   {
652     glDisable (GL_POLYGON_OFFSET_POINT);
653   }
654 #endif
655
656   glPolygonOffset (theOffsetData.factor, theOffsetData.units);
657 }
658
659 // =======================================================================
660 // function : updateMaterial
661 // purpose  :
662 // =======================================================================
663 void OpenGl_Workspace::updateMaterial (const int theFlag)
664 {
665   // Case of hidden line
666   if (AspectFace_set->InteriorStyle() == Aspect_IS_HIDDENLINE)
667   {
668     myAspectFaceHl = *AspectFace_set; // copy all values including line edge aspect
669     myAspectFaceHl.ChangeIntFront().matcol     = myView->BackgroundColor();
670     myAspectFaceHl.ChangeIntFront().color_mask = 0;
671     myAspectFaceHl.ChangeIntFront().color_mask = 0;
672
673     AspectFace_set = &myAspectFaceHl;
674     return;
675   }
676
677   const OPENGL_SURF_PROP* aProps = &AspectFace_set->IntFront();
678   GLenum aFace = GL_FRONT_AND_BACK;
679   if (theFlag == TEL_BACK_MATERIAL)
680   {
681     aFace  = GL_BACK;
682     aProps = &AspectFace_set->IntBack();
683   }
684   else if (AspectFace_set->DistinguishingMode() == TOn
685         && !(NamedStatus & OPENGL_NS_RESMAT))
686   {
687     aFace = GL_FRONT;
688   }
689
690   myMatTmp.Init (*aProps);
691
692   // handling transparency
693   if (NamedStatus & OPENGL_NS_2NDPASSDO)
694   {
695     // second pass
696     myMatTmp.Diffuse.a() = aProps->env_reflexion;
697   }
698   else
699   {
700     if (aProps->env_reflexion != 0.0f)
701     {
702       // if the material reflects the environment scene, the second pass is needed
703       NamedStatus |= OPENGL_NS_2NDPASSNEED;
704     }
705
706     if (aProps->trans != 1.0f)
707     {
708       // render transparent
709       myMatTmp.Diffuse.a() = aProps->trans;
710       glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
711       glEnable    (GL_BLEND);
712       if (myUseDepthWrite)
713       {
714         glDepthMask (GL_FALSE);
715       }
716     }
717     else
718     {
719       // render opaque
720       if ((NamedStatus & OPENGL_NS_ANTIALIASING) == 0)
721       {
722         glBlendFunc (GL_ONE, GL_ZERO);
723         glDisable   (GL_BLEND);
724       }
725       if (myUseDepthWrite)
726       {
727         glDepthMask (GL_TRUE);
728       }
729     }
730   }
731
732   // do not update material properties in case of zero reflection mode,
733   // because GL lighting will be disabled by OpenGl_PrimitiveArray::DrawArray() anyway.
734   if (aProps->color_mask == 0)
735   {
736     return;
737   }
738
739   // reset material
740   if (NamedStatus & OPENGL_NS_RESMAT)
741   {
742   #if !defined(GL_ES_VERSION_2_0)
743     if (myGlContext->core11 != NULL)
744     {
745       myGlContext->core11->glMaterialfv (aFace, GL_AMBIENT,   myMatTmp.Ambient.GetData());
746       myGlContext->core11->glMaterialfv (aFace, GL_DIFFUSE,   myMatTmp.Diffuse.GetData());
747       myGlContext->core11->glMaterialfv (aFace, GL_SPECULAR,  myMatTmp.Specular.GetData());
748       myGlContext->core11->glMaterialfv (aFace, GL_EMISSION,  myMatTmp.Emission.GetData());
749       myGlContext->core11->glMaterialf  (aFace, GL_SHININESS, myMatTmp.Shine());
750     }
751   #endif
752
753     if (theFlag == TEL_FRONT_MATERIAL)
754     {
755       myMatFront = myMatTmp;
756       myMatBack  = myMatTmp;
757     }
758     else
759     {
760       myMatBack = myMatTmp;
761     }
762
763     NamedStatus &= ~OPENGL_NS_RESMAT;
764     return;
765   }
766
767   // reduce updates
768   OpenGl_Material& anOld = (theFlag == TEL_FRONT_MATERIAL)
769                          ? myMatFront
770                          : myMatBack;
771 #if !defined(GL_ES_VERSION_2_0)
772   if (myGlContext->core11 != NULL)
773   {
774     if (myMatTmp.Ambient.r() != anOld.Ambient.r()
775      || myMatTmp.Ambient.g() != anOld.Ambient.g()
776      || myMatTmp.Ambient.b() != anOld.Ambient.b())
777     {
778       myGlContext->core11->glMaterialfv (aFace, GL_AMBIENT, myMatTmp.Ambient.GetData());
779     }
780     if (myMatTmp.Diffuse.r() != anOld.Diffuse.r()
781      || myMatTmp.Diffuse.g() != anOld.Diffuse.g()
782      || myMatTmp.Diffuse.b() != anOld.Diffuse.b()
783      || fabs (myMatTmp.Diffuse.a() - anOld.Diffuse.a()) > 0.01f)
784     {
785       myGlContext->core11->glMaterialfv (aFace, GL_DIFFUSE, myMatTmp.Diffuse.GetData());
786     }
787     if (myMatTmp.Specular.r() != anOld.Specular.r()
788      || myMatTmp.Specular.g() != anOld.Specular.g()
789      || myMatTmp.Specular.b() != anOld.Specular.b())
790     {
791       myGlContext->core11->glMaterialfv (aFace, GL_SPECULAR, myMatTmp.Specular.GetData());
792     }
793     if (myMatTmp.Emission.r() != anOld.Emission.r()
794      || myMatTmp.Emission.g() != anOld.Emission.g()
795      || myMatTmp.Emission.b() != anOld.Emission.b())
796     {
797       myGlContext->core11->glMaterialfv (aFace, GL_EMISSION, myMatTmp.Emission.GetData());
798     }
799     if (myMatTmp.Shine() != anOld.Shine())
800     {
801       myGlContext->core11->glMaterialf (aFace, GL_SHININESS, myMatTmp.Shine());
802     }
803   }
804 #endif
805   anOld = myMatTmp;
806   if (aFace == GL_FRONT_AND_BACK)
807   {
808     myMatBack = myMatTmp;
809   }
810 }
811
812 // =======================================================================
813 // function : SetAspectLine
814 // purpose  :
815 // =======================================================================
816 const OpenGl_AspectLine * OpenGl_Workspace::SetAspectLine(const OpenGl_AspectLine *AnAspect)
817 {
818   const OpenGl_AspectLine *AspectLine_old = AspectLine_set;
819   AspectLine_set = AnAspect;
820   return AspectLine_old;
821 }
822
823 // =======================================================================
824 // function : SetAspectFace
825 // purpose  :
826 // =======================================================================
827 const OpenGl_AspectFace * OpenGl_Workspace::SetAspectFace(const OpenGl_AspectFace *AnAspect)
828 {
829   const OpenGl_AspectFace *AspectFace_old = AspectFace_set;
830   AspectFace_set = AnAspect;
831   return AspectFace_old;
832 }
833
834 // =======================================================================
835 // function : SetAspectMarker
836 // purpose  :
837 // =======================================================================
838 const OpenGl_AspectMarker * OpenGl_Workspace::SetAspectMarker(const OpenGl_AspectMarker *AnAspect)
839 {
840   const OpenGl_AspectMarker *AspectMarker_old = AspectMarker_set;
841   AspectMarker_set = AnAspect;
842   return AspectMarker_old;
843 }
844
845 // =======================================================================
846 // function : SetAspectText
847 // purpose  :
848 // =======================================================================
849 const OpenGl_AspectText * OpenGl_Workspace::SetAspectText(const OpenGl_AspectText *AnAspect)
850 {
851   const OpenGl_AspectText *AspectText_old = AspectText_set;
852   AspectText_set = AnAspect;
853   return AspectText_old;
854 }
855
856 // =======================================================================
857 // function : AspectLine
858 // purpose  :
859 // =======================================================================
860 const OpenGl_AspectLine * OpenGl_Workspace::AspectLine(const Standard_Boolean theWithApply)
861 {
862   if (theWithApply)
863   {
864     AspectLine_applied = AspectLine_set;
865   }
866
867   return AspectLine_set;
868 }
869
870 // =======================================================================
871 // function : AspectFace
872 // purpose  :
873 // =======================================================================
874 const OpenGl_AspectFace* OpenGl_Workspace::AspectFace (const Standard_Boolean theToApply)
875 {
876   if (!theToApply)
877   {
878     return AspectFace_set;
879   }
880
881   if (myView->BackfacingModel() == Graphic3d_TOBM_AUTOMATIC)
882   {
883     // manage back face culling mode, disable culling when clipping is enabled
884     TelCullMode aCullingMode = (myGlContext->Clipping().IsClippingOrCappingOn()
885                              || AspectFace_set->InteriorStyle() == Aspect_IS_HATCH)
886                              ? TelCullNone
887                              : (TelCullMode )AspectFace_set->CullingMode();
888     if (aCullingMode != TelCullNone
889      && !(NamedStatus & OPENGL_NS_2NDPASSDO))
890     {
891       // disable culling in case of translucent shading aspect
892       if (AspectFace_set->IntFront().trans != 1.0f)
893       {
894         aCullingMode = TelCullNone;
895       }
896     }
897     if (myCullingMode != aCullingMode)
898     {
899       myCullingMode = aCullingMode;
900       switch (myCullingMode)
901       {
902         case TelCullNone:
903         case TelCullUndefined:
904         {
905           glDisable (GL_CULL_FACE);
906           break;
907         }
908         case TelCullFront:
909         {
910           glCullFace (GL_FRONT);
911           glEnable (GL_CULL_FACE);
912           break;
913         }
914         case TelCullBack:
915         {
916           glCullFace (GL_BACK);
917           glEnable (GL_CULL_FACE);
918           break;
919         }
920       }
921     }
922   }
923
924   if (AspectFace_set == AspectFace_applied)
925   {
926     return AspectFace_set;
927   }
928
929 #if !defined(GL_ES_VERSION_2_0)
930   const Aspect_InteriorStyle anIntstyle = AspectFace_set->InteriorStyle();
931   if (AspectFace_applied == NULL || AspectFace_applied->InteriorStyle() != anIntstyle)
932   {
933     switch (anIntstyle)
934     {
935       case Aspect_IS_EMPTY:
936       case Aspect_IS_HOLLOW:
937       {
938         glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
939         break;
940       }
941       case Aspect_IS_HATCH:
942       {
943         glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
944         myLineAttribs->SetTypeOfHatch (AspectFace_applied != NULL ? AspectFace_applied->Hatch() : TEL_HS_SOLID);
945         break;
946       }
947       case Aspect_IS_SOLID:
948       case Aspect_IS_HIDDENLINE:
949       {
950         glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
951         if (myGlContext->core11 != NULL)
952         {
953           glDisable (GL_POLYGON_STIPPLE);
954         }
955         break;
956       }
957       case Aspect_IS_POINT:
958       {
959         glPolygonMode (GL_FRONT_AND_BACK, GL_POINT);
960         break;
961       }
962     }
963   }
964
965   if (anIntstyle == Aspect_IS_HATCH)
966   {
967     const Tint hatchstyle = AspectFace_set->Hatch();
968     if (AspectFace_applied == NULL || AspectFace_applied->Hatch() != hatchstyle)
969     {
970       myLineAttribs->SetTypeOfHatch (hatchstyle);
971     }
972   }
973 #endif
974
975   // Aspect_POM_None means: do not change current settings
976   if ((AspectFace_set->PolygonOffset().mode & Aspect_POM_None) != Aspect_POM_None)
977   {
978     if (PolygonOffset_applied.mode   != AspectFace_set->PolygonOffset().mode
979      || PolygonOffset_applied.factor != AspectFace_set->PolygonOffset().factor
980      || PolygonOffset_applied.units  != AspectFace_set->PolygonOffset().units)
981     {
982       SetPolygonOffset (AspectFace_set->PolygonOffset().mode,
983                         AspectFace_set->PolygonOffset().factor,
984                         AspectFace_set->PolygonOffset().units);
985     }
986   }
987
988   updateMaterial (TEL_FRONT_MATERIAL);
989   if (AspectFace_set->DistinguishingMode() == TOn)
990   {
991     updateMaterial (TEL_BACK_MATERIAL);
992   }
993
994   if ((NamedStatus & OPENGL_NS_FORBIDSETTEX) == 0)
995   {
996     if (AspectFace_set->DoTextureMap())
997     {
998       EnableTexture (AspectFace_set->TextureRes (myGlContext),
999                      AspectFace_set->TextureParams());
1000     }
1001     else
1002     {
1003       DisableTexture();
1004     }
1005   }
1006
1007   AspectFace_applied = AspectFace_set;
1008   return AspectFace_set;
1009 }
1010
1011 //=======================================================================
1012 //function : SetPolygonOffset
1013 //purpose  :
1014 //=======================================================================
1015 void OpenGl_Workspace::SetPolygonOffset (int theMode,
1016                                          Standard_ShortReal theFactor,
1017                                          Standard_ShortReal theUnits)
1018 {
1019   PolygonOffset_applied.mode   = theMode;
1020   PolygonOffset_applied.factor = theFactor;
1021   PolygonOffset_applied.units  = theUnits;
1022
1023   TelUpdatePolygonOffsets (PolygonOffset_applied);
1024 }
1025
1026 // =======================================================================
1027 // function : AspectMarker
1028 // purpose  :
1029 // =======================================================================
1030 const OpenGl_AspectMarker* OpenGl_Workspace::AspectMarker (const Standard_Boolean theToApply)
1031 {
1032   if (theToApply && (AspectMarker_set != AspectMarker_applied))
1033   {
1034     if (!AspectMarker_applied || (AspectMarker_set->Scale() != AspectMarker_applied->Scale()))
1035     {
1036     #if !defined(GL_ES_VERSION_2_0)
1037       glPointSize (AspectMarker_set->Scale());
1038     #ifdef HAVE_GL2PS
1039       gl2psPointSize (AspectMarker_set->Scale());
1040     #endif
1041     #endif
1042     }
1043     AspectMarker_applied = AspectMarker_set;
1044   }
1045   return AspectMarker_set;
1046 }
1047
1048 // =======================================================================
1049 // function : AspectText
1050 // purpose  :
1051 // =======================================================================
1052 const OpenGl_AspectText* OpenGl_Workspace::AspectText (const Standard_Boolean theWithApply)
1053 {
1054   if (theWithApply)
1055   {
1056     AspectText_applied = AspectText_set;
1057   }
1058
1059   return AspectText_set;
1060 }
1061
1062 // =======================================================================
1063 // function : Width
1064 // purpose  :
1065 // =======================================================================
1066 Standard_Integer OpenGl_Workspace::Width()  const
1067 {
1068   return !myView->GlWindow().IsNull() ? myView->GlWindow()->Width() : 0;
1069 }
1070
1071 // =======================================================================
1072 // function : Height
1073 // purpose  :
1074 // =======================================================================
1075 Standard_Integer OpenGl_Workspace::Height() const
1076 {
1077   return !myView->GlWindow().IsNull() ? myView->GlWindow()->Height() : 0;
1078 }
1079
1080 // =======================================================================
1081 // function : UseGLLight
1082 // purpose  :
1083 // =======================================================================
1084 Standard_Boolean OpenGl_Workspace::UseGLLight() const
1085 {
1086   return myView->IsGLLightEnabled();
1087 }
1088
1089 // =======================================================================
1090 // function : AntiAliasingMode
1091 // purpose  :
1092 // =======================================================================
1093 Standard_Integer OpenGl_Workspace::AntiAliasingMode() const
1094 {
1095   return myView->IsAntialiasingEnabled();
1096 }
1097
1098 // =======================================================================
1099 // function : IsCullingEnabled
1100 // purpose  :
1101 // =======================================================================
1102 Standard_Boolean OpenGl_Workspace::IsCullingEnabled() const
1103 {
1104   return myView->IsCullingEnabled();
1105 }
1106
1107 // =======================================================================
1108 // function : FBOCreate
1109 // purpose  :
1110 // =======================================================================
1111 Graphic3d_PtrFrameBuffer OpenGl_Workspace::FBOCreate (const Standard_Integer theWidth,
1112                                                       const Standard_Integer theHeight)
1113 {
1114   // activate OpenGL context
1115   if (!Activate())
1116     return NULL;
1117
1118   // create the FBO
1119   const Handle(OpenGl_Context)& aCtx = GetGlContext();
1120   OpenGl_FrameBuffer* aFrameBuffer = new OpenGl_FrameBuffer();
1121   if (!aFrameBuffer->Init (aCtx, theWidth, theHeight))
1122   {
1123     aFrameBuffer->Release (aCtx.operator->());
1124     delete aFrameBuffer;
1125     return NULL;
1126   }
1127   return (Graphic3d_PtrFrameBuffer )aFrameBuffer;
1128 }
1129
1130 // =======================================================================
1131 // function : FBORelease
1132 // purpose  :
1133 // =======================================================================
1134 void OpenGl_Workspace::FBORelease (Graphic3d_PtrFrameBuffer theFBOPtr)
1135 {
1136   // activate OpenGL context
1137   if (!Activate()
1138    || theFBOPtr == NULL)
1139   {
1140     return;
1141   }
1142
1143   // release the object
1144   OpenGl_FrameBuffer* aFrameBuffer = (OpenGl_FrameBuffer*)theFBOPtr;
1145   if (aFrameBuffer != NULL)
1146   {
1147     aFrameBuffer->Release (GetGlContext().operator->());
1148   }
1149   delete aFrameBuffer;
1150 }
1151
1152 inline bool getDataFormat (const Image_PixMap& theData,
1153                            GLenum&             thePixelFormat,
1154                            GLenum&             theDataType)
1155 {
1156   thePixelFormat = GL_RGB;
1157   theDataType    = GL_UNSIGNED_BYTE;
1158   switch (theData.Format())
1159   {
1160   #if !defined(GL_ES_VERSION_2_0)
1161     case Image_PixMap::ImgGray:
1162       thePixelFormat = GL_DEPTH_COMPONENT;
1163       theDataType    = GL_UNSIGNED_BYTE;
1164       return true;
1165     case Image_PixMap::ImgGrayF:
1166       thePixelFormat = GL_DEPTH_COMPONENT;
1167       theDataType    = GL_FLOAT;
1168       return true;
1169     case Image_PixMap::ImgBGR:
1170       thePixelFormat = GL_BGR;
1171       theDataType    = GL_UNSIGNED_BYTE;
1172       return true;
1173     case Image_PixMap::ImgBGRA:
1174     case Image_PixMap::ImgBGR32:
1175       thePixelFormat = GL_BGRA;
1176       theDataType    = GL_UNSIGNED_BYTE;
1177       return true;
1178     case Image_PixMap::ImgBGRF:
1179       thePixelFormat = GL_BGR;
1180       theDataType    = GL_FLOAT;
1181       return true;
1182     case Image_PixMap::ImgBGRAF:
1183       thePixelFormat = GL_BGRA;
1184       theDataType    = GL_FLOAT;
1185       return true;
1186   #else
1187     case Image_PixMap::ImgGray:
1188     case Image_PixMap::ImgGrayF:
1189     case Image_PixMap::ImgBGR:
1190     case Image_PixMap::ImgBGRA:
1191     case Image_PixMap::ImgBGR32:
1192     case Image_PixMap::ImgBGRF:
1193     case Image_PixMap::ImgBGRAF:
1194       return false;
1195   #endif
1196     case Image_PixMap::ImgRGB:
1197       thePixelFormat = GL_RGB;
1198       theDataType    = GL_UNSIGNED_BYTE;
1199       return true;
1200     case Image_PixMap::ImgRGBA:
1201     case Image_PixMap::ImgRGB32:
1202       thePixelFormat = GL_RGBA;
1203       theDataType    = GL_UNSIGNED_BYTE;
1204       return true;
1205     case Image_PixMap::ImgRGBF:
1206       thePixelFormat = GL_RGB;
1207       theDataType    = GL_FLOAT;
1208       return true;
1209     case Image_PixMap::ImgRGBAF:
1210       thePixelFormat = GL_RGBA;
1211       theDataType    = GL_FLOAT;
1212       return true;
1213     case Image_PixMap::ImgAlpha:
1214     case Image_PixMap::ImgAlphaF:
1215       return false; // GL_ALPHA is no more supported in core context
1216     case Image_PixMap::ImgUNKNOWN:
1217       return false;
1218   }
1219   return false;
1220 }
1221
1222 // =======================================================================
1223 // function : getAligned
1224 // purpose  :
1225 // =======================================================================
1226 inline Standard_Size getAligned (const Standard_Size theNumber,
1227                                  const Standard_Size theAlignment)
1228 {
1229   return theNumber + theAlignment - 1 - (theNumber - 1) % theAlignment;
1230 }
1231
1232 // =======================================================================
1233 // function : BufferDump
1234 // purpose  :
1235 // =======================================================================
1236 Standard_Boolean OpenGl_Workspace::BufferDump (OpenGl_FrameBuffer*         theFBOPtr,
1237                                                Image_PixMap&               theImage,
1238                                                const Graphic3d_BufferType& theBufferType)
1239 {
1240   GLenum aFormat, aType;
1241   if (theImage.IsEmpty()
1242    || !getDataFormat (theImage, aFormat, aType)
1243    || !Activate())
1244   {
1245     return Standard_False;
1246   }
1247 #if !defined(GL_ES_VERSION_2_0)
1248   GLint aReadBufferPrev = GL_BACK;
1249   if (theBufferType == Graphic3d_BT_Depth
1250    && aFormat != GL_DEPTH_COMPONENT)
1251   {
1252     return Standard_False;
1253   }
1254 #endif
1255
1256   // bind FBO if used
1257   if (theFBOPtr != NULL && theFBOPtr->IsValid())
1258   {
1259     theFBOPtr->BindBuffer (GetGlContext());
1260   }
1261   else
1262   {
1263   #if !defined(GL_ES_VERSION_2_0)
1264     glGetIntegerv (GL_READ_BUFFER, &aReadBufferPrev);
1265     GLint aDrawBufferPrev = GL_BACK;
1266     glGetIntegerv (GL_DRAW_BUFFER, &aDrawBufferPrev);
1267     glReadBuffer (aDrawBufferPrev);
1268   #endif
1269   }
1270
1271   // setup alignment
1272   const GLint anAligment   = Min (GLint(theImage.MaxRowAligmentBytes()), 8); // limit to 8 bytes for OpenGL
1273   glPixelStorei (GL_PACK_ALIGNMENT, anAligment);
1274   bool isBatchCopy = !theImage.IsTopDown();
1275
1276   const GLint   anExtraBytes       = GLint(theImage.RowExtraBytes());
1277   GLint         aPixelsWidth       = GLint(theImage.SizeRowBytes() / theImage.SizePixelBytes());
1278   Standard_Size aSizeRowBytesEstim = getAligned (theImage.SizePixelBytes() * aPixelsWidth, anAligment);
1279   if (anExtraBytes < anAligment)
1280   {
1281     aPixelsWidth = 0;
1282   }
1283   else if (aSizeRowBytesEstim != theImage.SizeRowBytes())
1284   {
1285     aPixelsWidth = 0;
1286     isBatchCopy  = false;
1287   }
1288 #if !defined(GL_ES_VERSION_2_0)
1289   glPixelStorei (GL_PACK_ROW_LENGTH, aPixelsWidth);
1290 #else
1291   if (aPixelsWidth != 0)
1292   {
1293     isBatchCopy = false;
1294   }
1295 #endif
1296
1297   if (!isBatchCopy)
1298   {
1299     // copy row by row
1300     for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
1301     {
1302       // Image_PixMap rows indexation always starts from the upper corner
1303       // while order in memory depends on the flag and processed by ChangeRow() method
1304       glReadPixels (0, GLint(theImage.SizeY() - aRow - 1), GLsizei (theImage.SizeX()), 1, aFormat, aType, theImage.ChangeRow (aRow));
1305     }
1306   }
1307   else
1308   {
1309     glReadPixels (0, 0, GLsizei (theImage.SizeX()), GLsizei (theImage.SizeY()), aFormat, aType, theImage.ChangeData());
1310   }
1311
1312   glPixelStorei (GL_PACK_ALIGNMENT,  1);
1313 #if !defined(GL_ES_VERSION_2_0)
1314   glPixelStorei (GL_PACK_ROW_LENGTH, 0);
1315 #endif
1316
1317   if (theFBOPtr != NULL && theFBOPtr->IsValid())
1318   {
1319     theFBOPtr->UnbindBuffer (GetGlContext());
1320   }
1321   else
1322   {
1323   #if !defined(GL_ES_VERSION_2_0)
1324     glReadBuffer (aReadBufferPrev);
1325   #endif
1326   }
1327   return Standard_True;
1328 }
1329
1330 // =======================================================================
1331 // function : CanRender
1332 // purpose  :
1333 // =======================================================================
1334 Standard_Boolean OpenGl_RaytraceFilter::CanRender (const OpenGl_Element* theElement)
1335 {
1336   Standard_Boolean aPrevFilterResult = Standard_True;
1337   if (!myPrevRenderFilter.IsNull())
1338   {
1339     aPrevFilterResult = myPrevRenderFilter->CanRender (theElement);
1340   }
1341   return aPrevFilterResult &&
1342     !OpenGl_Raytrace::IsRaytracedElement (theElement);
1343 }