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