4f17f247b20da03266e6d9e579412873667b6f50
[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 <OpenGl_ArbFBO.hxx>
19 #include <OpenGl_AspectLine.hxx>
20 #include <OpenGl_AspectFace.hxx>
21 #include <OpenGl_AspectMarker.hxx>
22 #include <OpenGl_AspectText.hxx>
23 #include <OpenGl_Context.hxx>
24 #include <OpenGl_Element.hxx>
25 #include <OpenGl_FrameBuffer.hxx>
26 #include <OpenGl_GlCore15.hxx>
27 #include <OpenGl_SceneGeometry.hxx>
28 #include <OpenGl_Structure.hxx>
29 #include <OpenGl_Sampler.hxx>
30 #include <OpenGl_ShaderManager.hxx>
31 #include <OpenGl_Texture.hxx>
32 #include <OpenGl_View.hxx>
33 #include <OpenGl_Window.hxx>
34
35 #include <Graphic3d_TextureParams.hxx>
36 #include <Graphic3d_TransformUtils.hxx>
37 #include <NCollection_AlignedAllocator.hxx>
38
39 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Workspace,Standard_Transient)
40 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_RaytraceFilter,OpenGl_RenderFilter)
41
42 #ifdef HAVE_GL2PS
43   #include <gl2ps.h>
44   /* OCC22216 NOTE: linker dependency can be switched off by undefining macro.
45      Pragma comment for gl2ps.lib is defined only here. */
46   #ifdef _MSC_VER
47   #pragma comment( lib, "gl2ps.lib" )
48   #endif
49 #endif
50
51 namespace
52 {
53   static const OpenGl_Vec4 THE_WHITE_COLOR (1.0f, 1.0f, 1.0f, 1.0f);
54   static const OpenGl_Vec4 THE_BLACK_COLOR (0.0f, 0.0f, 0.0f, 1.0f);
55
56   static const OpenGl_AspectLine myDefaultAspectLine;
57   static const OpenGl_AspectFace myDefaultAspectFace;
58   static const OpenGl_AspectMarker myDefaultAspectMarker;
59   static const OpenGl_AspectText myDefaultAspectText;
60
61   static const OpenGl_Matrix myDefaultMatrix =
62   {
63     {{ 1.0F, 0.0F, 0.0F, 0.0F },
64      { 0.0F, 1.0F, 0.0F, 0.0F },
65      { 0.0F, 0.0F, 1.0F, 0.0F },
66      { 0.0F, 0.0F, 0.0F, 1.0F }}
67   };
68
69 }
70
71 // =======================================================================
72 // function : Init
73 // purpose  :
74 // =======================================================================
75 void OpenGl_Material::Init (const Graphic3d_MaterialAspect& theMat,
76                             const Quantity_Color&           theInteriorColor)
77 {
78   const bool isPhysic = theMat.MaterialType (Graphic3d_MATERIAL_PHYSIC);
79
80   // ambient component
81   if (theMat.ReflectionMode (Graphic3d_TOR_AMBIENT))
82   {
83     const OpenGl_Vec3& aSrcAmb = isPhysic ? theMat.AmbientColor() : theInteriorColor;
84     Ambient = OpenGl_Vec4 (aSrcAmb * theMat.Ambient(), 1.0f);
85   }
86   else
87   {
88     Ambient = THE_BLACK_COLOR;
89   }
90
91   // diffusion component
92   if (theMat.ReflectionMode (Graphic3d_TOR_DIFFUSE))
93   {
94     const OpenGl_Vec3& aSrcDif = isPhysic ? theMat.DiffuseColor() : theInteriorColor;
95     Diffuse = OpenGl_Vec4 (aSrcDif * theMat.Diffuse(), 1.0f);
96   }
97   else
98   {
99     Diffuse = THE_BLACK_COLOR;
100   }
101
102   // specular component
103   if (theMat.ReflectionMode (Graphic3d_TOR_SPECULAR))
104   {
105     const OpenGl_Vec3& aSrcSpe = isPhysic ? (const OpenGl_Vec3& )theMat.SpecularColor() : THE_WHITE_COLOR.rgb();
106     Specular = OpenGl_Vec4 (aSrcSpe * theMat.Specular(), 1.0f);
107   }
108   else
109   {
110     Specular = THE_BLACK_COLOR;
111   }
112
113   // emission component
114   if (theMat.ReflectionMode (Graphic3d_TOR_EMISSION))
115   {
116     const OpenGl_Vec3& aSrcEms = isPhysic ? theMat.EmissiveColor() : theInteriorColor;
117     Emission = OpenGl_Vec4 (aSrcEms * theMat.Emissive(), 1.0f);
118   }
119   else
120   {
121     Emission = THE_BLACK_COLOR;
122   }
123
124   ChangeShine()        = 128.0f * theMat.Shininess();
125   ChangeTransparency() = 1.0f - theMat.Transparency();
126 }
127
128 // =======================================================================
129 // function : OpenGl_Workspace
130 // purpose  :
131 // =======================================================================
132 OpenGl_Workspace::OpenGl_Workspace (OpenGl_View* theView, const Handle(OpenGl_Window)& theWindow)
133 : myView (theView),
134   myWindow (theWindow),
135   myGlContext (!theWindow.IsNull() ? theWindow->GetGlContext() : NULL),
136   myUseZBuffer    (Standard_True),
137   myUseDepthWrite (Standard_True),
138   //
139   myAspectLineSet (&myDefaultAspectLine),
140   myAspectFaceSet (&myDefaultAspectFace),
141   myAspectMarkerSet (&myDefaultAspectMarker),
142   myAspectTextSet (&myDefaultAspectText),
143   //
144   ViewMatrix_applied (&myDefaultMatrix),
145   StructureMatrix_applied (&myDefaultMatrix),
146   myToAllowFaceCulling (false),
147   myModelViewMatrix (myDefaultMatrix)
148 {
149   if (!myGlContext.IsNull() && myGlContext->MakeCurrent())
150   {
151     myGlContext->core11fwd->glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
152
153     // General initialization of the context
154   #if !defined(GL_ES_VERSION_2_0)
155     if (myGlContext->core11 != NULL)
156     {
157       // Eviter d'avoir les faces mal orientees en noir.
158       // Pourrait etre utiliser pour detecter les problemes d'orientation
159       glLightModeli ((GLenum )GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
160
161       // Optimisation pour le Fog et l'antialiasing
162       glHint (GL_FOG_HINT,            GL_FASTEST);
163       glHint (GL_POINT_SMOOTH_HINT,   GL_FASTEST);
164     }
165
166     glHint (GL_LINE_SMOOTH_HINT,    GL_FASTEST);
167     glHint (GL_POLYGON_SMOOTH_HINT, GL_FASTEST);
168   #endif
169   }
170
171   myDefaultCappingAlgoFilter = new OpenGl_CappingAlgoFilter();
172
173   myNoneCulling .Aspect()->SetSuppressBackFaces (false);
174   myNoneCulling .Aspect()->SetDrawEdges (false);
175   myFrontCulling.Aspect()->SetSuppressBackFaces (true);
176   myFrontCulling.Aspect()->SetDrawEdges (false);
177 }
178
179 // =======================================================================
180 // function : Activate
181 // purpose  :
182 // =======================================================================
183 Standard_Boolean OpenGl_Workspace::Activate()
184 {
185   if (myWindow.IsNull() || !myWindow->Activate())
186   {
187     return Standard_False;
188   }
189
190   ViewMatrix_applied      = &myDefaultMatrix;
191   StructureMatrix_applied = &myDefaultMatrix;
192
193   ResetAppliedAspect();
194
195   // reset state for safety
196   myGlContext->BindProgram (Handle(OpenGl_ShaderProgram)());
197   if (myGlContext->core20fwd != NULL)
198   {
199     myGlContext->core20fwd->glUseProgram (OpenGl_ShaderProgram::NO_PROGRAM);
200   }
201   myGlContext->ShaderManager()->PushState (Handle(OpenGl_ShaderProgram)());
202   return Standard_True;
203 }
204
205 //=======================================================================
206 //function : ResetAppliedAspect
207 //purpose  : Sets default values of GL parameters in accordance with default aspects
208 //=======================================================================
209 void OpenGl_Workspace::ResetAppliedAspect()
210 {
211   myGlContext->BindDefaultVao();
212
213   myHighlightStyle.Nullify();
214   myToAllowFaceCulling  = false;
215   myAspectLineSet       = &myDefaultAspectLine;
216   myAspectFaceSet       = &myDefaultAspectFace;
217   myAspectFaceApplied.Nullify();
218   myAspectMarkerSet     = &myDefaultAspectMarker;
219   myAspectMarkerApplied.Nullify();
220   myAspectTextSet       = &myDefaultAspectText;
221   myPolygonOffsetApplied= Graphic3d_PolygonOffset();
222
223   ApplyAspectLine();
224   ApplyAspectFace();
225   ApplyAspectMarker();
226   ApplyAspectText();
227
228   myGlContext->SetTypeOfLine (myDefaultAspectLine.Aspect()->Type());
229   myGlContext->SetLineWidth  (myDefaultAspectLine.Aspect()->Width());
230 }
231
232 // =======================================================================
233 // function : DisableTexture
234 // purpose  :
235 // =======================================================================
236 Handle(OpenGl_Texture) OpenGl_Workspace::DisableTexture()
237 {
238   if (myTextureBound.IsNull())
239   {
240     return myTextureBound;
241   }
242
243   const Handle(OpenGl_Sampler)& aSampler = myGlContext->TextureSampler();
244   if (!aSampler.IsNull())
245   {
246     aSampler->Unbind (*myGlContext);
247   }
248
249 #if !defined(GL_ES_VERSION_2_0)
250   // reset texture matrix because some code may expect it is identity
251   if (myGlContext->core11 != NULL)
252   {
253     GLint aMatrixMode = GL_TEXTURE;
254     glGetIntegerv (GL_MATRIX_MODE, &aMatrixMode);
255     glMatrixMode (GL_TEXTURE);
256     glLoadIdentity();
257     glMatrixMode (aMatrixMode);
258   }
259 #endif
260
261   myTextureBound->Unbind (myGlContext);
262   switch (myTextureBound->GetTarget())
263   {
264   #if !defined(GL_ES_VERSION_2_0)
265     case GL_TEXTURE_1D:
266     {
267       if (myGlContext->core11 != NULL)
268       {
269         if (myTextureBound->GetParams()->GenMode() != GL_NONE)
270         {
271           glDisable (GL_TEXTURE_GEN_S);
272         }
273         glDisable (GL_TEXTURE_1D);
274       }
275       break;
276     }
277   #endif
278     case GL_TEXTURE_2D:
279     {
280     #if !defined(GL_ES_VERSION_2_0)
281       if (myGlContext->core11 != NULL)
282       {
283         if (myTextureBound->GetParams()->GenMode() != GL_NONE)
284         {
285           glDisable (GL_TEXTURE_GEN_S);
286           glDisable (GL_TEXTURE_GEN_T);
287           if (myTextureBound->GetParams()->GenMode() == Graphic3d_TOTM_SPRITE)
288           {
289             glDisable (GL_POINT_SPRITE);
290           }
291         }
292         glDisable (GL_TEXTURE_2D);
293       }
294     #endif
295       break;
296     }
297     default: break;
298   }
299
300   Handle(OpenGl_Texture) aPrevTexture = myTextureBound;
301   myTextureBound.Nullify();
302   return aPrevTexture;
303 }
304
305 // =======================================================================
306 // function : setTextureParams
307 // purpose  :
308 // =======================================================================
309 void OpenGl_Workspace::setTextureParams (Handle(OpenGl_Texture)&                theTexture,
310                                          const Handle(Graphic3d_TextureParams)& theParams)
311 {
312   const Handle(Graphic3d_TextureParams)& aParams = theParams.IsNull() ? theTexture->GetParams() : theParams;
313   if (aParams.IsNull())
314   {
315     return;
316   }
317
318 #if !defined(GL_ES_VERSION_2_0)
319   if (myGlContext->core11 != NULL)
320   {
321     GLint anEnvMode = GL_MODULATE; // lighting mode
322     if (!aParams->IsModulate())
323     {
324       anEnvMode = GL_DECAL;
325       if (theTexture->GetFormat() == GL_ALPHA
326        || theTexture->GetFormat() == GL_LUMINANCE)
327       {
328         anEnvMode = GL_REPLACE;
329       }
330     }
331
332     // setup generation of texture coordinates
333     switch (aParams->GenMode())
334     {
335       case Graphic3d_TOTM_OBJECT:
336       {
337         glTexGeni  (GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
338         glTexGenfv (GL_S, GL_OBJECT_PLANE,     aParams->GenPlaneS().GetData());
339         if (theTexture->GetTarget() != GL_TEXTURE_1D)
340         {
341           glTexGeni  (GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
342           glTexGenfv (GL_T, GL_OBJECT_PLANE,     aParams->GenPlaneT().GetData());
343         }
344         break;
345       }
346       case Graphic3d_TOTM_SPHERE:
347       {
348         glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
349         if (theTexture->GetTarget() != GL_TEXTURE_1D)
350         {
351           glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
352         }
353         break;
354       }
355       case Graphic3d_TOTM_EYE:
356       {
357         myGlContext->WorldViewState.Push();
358
359         myGlContext->WorldViewState.SetIdentity();
360         myGlContext->ApplyWorldViewMatrix();
361
362         glTexGeni  (GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
363         glTexGenfv (GL_S, GL_EYE_PLANE,        aParams->GenPlaneS().GetData());
364
365         if (theTexture->GetTarget() != GL_TEXTURE_1D)
366         {
367           glTexGeni  (GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
368           glTexGenfv (GL_T, GL_EYE_PLANE,        aParams->GenPlaneT().GetData());
369         }
370
371         myGlContext->WorldViewState.Pop();
372
373         break;
374       }
375       case Graphic3d_TOTM_SPRITE:
376       {
377         if (myGlContext->core20fwd != NULL)
378         {
379           glEnable  (GL_POINT_SPRITE);
380           glTexEnvi (GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE);
381           anEnvMode = GL_REPLACE;
382         }
383         break;
384       }
385       case Graphic3d_TOTM_MANUAL:
386       default: break;
387     }
388
389     // setup lighting
390     glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, anEnvMode);
391   }
392 #endif
393
394   // get active sampler object to override default texture parameters
395   const Handle(OpenGl_Sampler)& aSampler = myGlContext->TextureSampler();
396
397   // setup texture filtering and wrapping
398   //if (theTexture->GetParams() != theParams)
399   const GLenum aFilter   = (aParams->Filter() == Graphic3d_TOTF_NEAREST) ? GL_NEAREST : GL_LINEAR;
400   const GLenum aWrapMode = aParams->IsRepeat() ? GL_REPEAT : myGlContext->TextureWrapClamp();
401   switch (theTexture->GetTarget())
402   {
403   #if !defined(GL_ES_VERSION_2_0)
404     case GL_TEXTURE_1D:
405     {
406       if (aSampler.IsNull() || !aSampler->IsValid())
407       {
408         glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, aFilter);
409         glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, aFilter);
410         glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_S,     aWrapMode);
411       }
412       else
413       {
414         aSampler->SetParameter (*myGlContext, GL_TEXTURE_MAG_FILTER, aFilter);
415         aSampler->SetParameter (*myGlContext, GL_TEXTURE_MIN_FILTER, aFilter);
416         aSampler->SetParameter (*myGlContext, GL_TEXTURE_WRAP_S,     aWrapMode);
417       }
418
419       break;
420     }
421   #endif
422     case GL_TEXTURE_2D:
423     {
424       GLenum aFilterMin = aFilter;
425       if (theTexture->HasMipmaps())
426       {
427         aFilterMin = GL_NEAREST_MIPMAP_NEAREST;
428         if (aParams->Filter() == Graphic3d_TOTF_BILINEAR)
429         {
430           aFilterMin = GL_LINEAR_MIPMAP_NEAREST;
431         }
432         else if (aParams->Filter() == Graphic3d_TOTF_TRILINEAR)
433         {
434           aFilterMin = GL_LINEAR_MIPMAP_LINEAR;
435         }
436
437         if (myGlContext->extAnis)
438         {
439           // setup degree of anisotropy filter
440           const GLint aMaxDegree = myGlContext->MaxDegreeOfAnisotropy();
441           GLint aDegree;
442           switch (aParams->AnisoFilter())
443           {
444             case Graphic3d_LOTA_QUALITY:
445             {
446               aDegree = aMaxDegree;
447               break;
448             }
449             case Graphic3d_LOTA_MIDDLE:
450             {
451               aDegree = (aMaxDegree <= 4) ? 2 : (aMaxDegree / 2);
452               break;
453             }
454             case Graphic3d_LOTA_FAST:
455             {
456               aDegree = 2;
457               break;
458             }
459             case Graphic3d_LOTA_OFF:
460             default:
461             {
462               aDegree = 1;
463               break;
464             }
465           }
466
467           if (aSampler.IsNull() || !aSampler->IsValid())
468           {
469             glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, aDegree);
470           }
471           else
472           {
473             aSampler->SetParameter (*myGlContext, GL_TEXTURE_MAX_ANISOTROPY_EXT, aDegree);
474           }
475         }
476       }
477
478       if (aSampler.IsNull() || !aSampler->IsValid())
479       {
480         glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, aFilterMin);
481         glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, aFilter);
482         glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,     aWrapMode);
483         glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,     aWrapMode);
484       }
485       else
486       {
487         aSampler->SetParameter (*myGlContext, GL_TEXTURE_MIN_FILTER, aFilterMin);
488         aSampler->SetParameter (*myGlContext, GL_TEXTURE_MAG_FILTER, aFilter);
489         aSampler->SetParameter (*myGlContext, GL_TEXTURE_WRAP_S,     aWrapMode);
490         aSampler->SetParameter (*myGlContext, GL_TEXTURE_WRAP_T,     aWrapMode);
491       }
492
493       break;
494     }
495     default: break;
496   }
497
498   switch (theTexture->GetTarget())
499   {
500   #if !defined(GL_ES_VERSION_2_0)
501     case GL_TEXTURE_1D:
502     {
503       if (myGlContext->core11 != NULL)
504       {
505         if (aParams->GenMode() != Graphic3d_TOTM_MANUAL)
506         {
507           glEnable (GL_TEXTURE_GEN_S);
508         }
509         glEnable (GL_TEXTURE_1D);
510       }
511       break;
512     }
513   #endif
514     case GL_TEXTURE_2D:
515     {
516     #if !defined(GL_ES_VERSION_2_0)
517       if (myGlContext->core11 != NULL)
518       {
519         if (aParams->GenMode() != Graphic3d_TOTM_MANUAL)
520         {
521           glEnable (GL_TEXTURE_GEN_S);
522           glEnable (GL_TEXTURE_GEN_T);
523         }
524         glEnable (GL_TEXTURE_2D);
525       }
526     #endif
527       break;
528     }
529     default: break;
530   }
531
532   theTexture->SetParams (aParams);
533 }
534
535 // =======================================================================
536 // function : EnableTexture
537 // purpose  :
538 // =======================================================================
539 Handle(OpenGl_Texture) OpenGl_Workspace::EnableTexture (const Handle(OpenGl_Texture)&          theTexture,
540                                                         const Handle(Graphic3d_TextureParams)& theParams)
541 {
542   if (theTexture.IsNull() || !theTexture->IsValid())
543   {
544     return DisableTexture();
545   }
546
547   if (myTextureBound == theTexture
548    && (theParams.IsNull() || theParams == theTexture->GetParams()))
549   {
550     // already bound
551     return myTextureBound;
552   }
553
554   Handle(OpenGl_Texture) aPrevTexture = DisableTexture();
555   myTextureBound = theTexture;
556   myTextureBound->Bind (myGlContext);
557   setTextureParams (myTextureBound, theParams);
558
559   // If custom sampler object is available it will be
560   // used for overriding default texture parameters
561   const Handle(OpenGl_Sampler)& aSampler = myGlContext->TextureSampler();
562
563   if (!aSampler.IsNull() && aSampler->IsValid())
564   {
565     aSampler->Bind (*myGlContext);
566   }
567
568   return aPrevTexture;
569 }
570
571 // =======================================================================
572 // function : SetAspectLine
573 // purpose  :
574 // =======================================================================
575 const OpenGl_AspectLine* OpenGl_Workspace::SetAspectLine (const OpenGl_AspectLine* theAspect)
576 {
577   const OpenGl_AspectLine* aPrevAspectLine = myAspectLineSet;
578   myAspectLineSet = theAspect;
579   return aPrevAspectLine;
580 }
581
582 // =======================================================================
583 // function : SetAspectFace
584 // purpose  :
585 // =======================================================================
586 const OpenGl_AspectFace * OpenGl_Workspace::SetAspectFace (const OpenGl_AspectFace* theAspect)
587 {
588   const OpenGl_AspectFace* aPrevAspectFace = myAspectFaceSet;
589   myAspectFaceSet = theAspect;
590   return aPrevAspectFace;
591 }
592
593 // =======================================================================
594 // function : SetAspectMarker
595 // purpose  :
596 // =======================================================================
597 const OpenGl_AspectMarker* OpenGl_Workspace::SetAspectMarker (const OpenGl_AspectMarker* theAspect)
598 {
599   const OpenGl_AspectMarker* aPrevAspectMarker = myAspectMarkerSet;
600   myAspectMarkerSet = theAspect;
601   return aPrevAspectMarker;
602 }
603
604 // =======================================================================
605 // function : SetAspectText
606 // purpose  :
607 // =======================================================================
608 const OpenGl_AspectText * OpenGl_Workspace::SetAspectText (const OpenGl_AspectText* theAspect)
609 {
610   const OpenGl_AspectText* aPrevAspectText = myAspectTextSet;
611   myAspectTextSet = theAspect;
612   return aPrevAspectText;
613 }
614
615 // =======================================================================
616 // function : ApplyAspectFace
617 // purpose  :
618 // =======================================================================
619 const OpenGl_AspectFace* OpenGl_Workspace::ApplyAspectFace()
620 {
621   if (myView->BackfacingModel() == Graphic3d_TOBM_AUTOMATIC)
622   {
623     // manage back face culling mode, disable culling when clipping is enabled
624     bool toSuppressBackFaces = myToAllowFaceCulling
625                             && myAspectFaceSet->Aspect()->ToSuppressBackFaces();
626     if (toSuppressBackFaces)
627     {
628       if (myGlContext->Clipping().IsClippingOrCappingOn()
629        || myAspectFaceSet->Aspect()->InteriorStyle() == Aspect_IS_HATCH)
630       {
631         toSuppressBackFaces = false;
632       }
633     }
634     if (toSuppressBackFaces)
635     {
636       if ((float )myAspectFaceSet->Aspect()->FrontMaterial().Transparency() != 0.0f)
637       {
638         // disable culling in case of translucent shading aspect
639         toSuppressBackFaces = false;
640       }
641     }
642     myGlContext->SetCullBackFaces (toSuppressBackFaces);
643   }
644
645   if (myAspectFaceSet->Aspect() == myAspectFaceApplied
646    && myHighlightStyle == myAspectFaceAppliedWithHL)
647   {
648     return myAspectFaceSet;
649   }
650   myAspectFaceAppliedWithHL = myHighlightStyle;
651
652 #if !defined(GL_ES_VERSION_2_0)
653   const Aspect_InteriorStyle anIntstyle = myAspectFaceSet->Aspect()->InteriorStyle();
654   if (myAspectFaceApplied.IsNull()
655    || myAspectFaceApplied->InteriorStyle() != anIntstyle)
656   {
657     switch (anIntstyle)
658     {
659       case Aspect_IS_EMPTY:
660       case Aspect_IS_HOLLOW:
661       {
662         myGlContext->SetPolygonMode (GL_LINE);
663         break;
664       }
665       case Aspect_IS_HATCH:
666       {
667         myGlContext->SetPolygonMode (GL_FILL);
668         myGlContext->SetPolygonHatchEnabled (true);
669         break;
670       }
671       case Aspect_IS_SOLID:
672       case Aspect_IS_HIDDENLINE:
673       {
674         myGlContext->SetPolygonMode (GL_FILL);
675         myGlContext->SetPolygonHatchEnabled (false);
676         break;
677       }
678       case Aspect_IS_POINT:
679       {
680         myGlContext->SetPolygonMode (GL_POINT);
681         break;
682       }
683     }
684   }
685
686   if (anIntstyle == Aspect_IS_HATCH)
687   {
688     myGlContext->SetPolygonHatchStyle (myAspectFaceSet->Aspect()->HatchStyle());
689   }
690 #endif
691
692   // Aspect_POM_None means: do not change current settings
693   if ((myAspectFaceSet->Aspect()->PolygonOffset().Mode & Aspect_POM_None) != Aspect_POM_None)
694   {
695     if (myPolygonOffsetApplied.Mode   != myAspectFaceSet->Aspect()->PolygonOffset().Mode
696      || myPolygonOffsetApplied.Factor != myAspectFaceSet->Aspect()->PolygonOffset().Factor
697      || myPolygonOffsetApplied.Units  != myAspectFaceSet->Aspect()->PolygonOffset().Units)
698     {
699       SetPolygonOffset (myAspectFaceSet->Aspect()->PolygonOffset());
700     }
701   }
702
703   // Case of hidden line
704   if (myAspectFaceSet->Aspect()->InteriorStyle() == Aspect_IS_HIDDENLINE)
705   {
706     // copy all values including line edge aspect
707     *myAspectFaceHl.Aspect().operator->() = *myAspectFaceSet->Aspect();
708     myAspectFaceHl.SetAspectEdge (myAspectFaceSet->AspectEdge());
709     myAspectFaceHl.Aspect()->SetInteriorColor (myView->BackgroundColor().GetRGB());
710     myAspectFaceHl.SetNoLighting (true);
711     myAspectFaceSet = &myAspectFaceHl;
712   }
713   else
714   {
715     myGlContext->SetShadingMaterial (myAspectFaceSet, myHighlightStyle, myUseDepthWrite);
716   }
717
718   if (myAspectFaceSet->Aspect()->ToMapTexture())
719   {
720     EnableTexture (myAspectFaceSet->TextureRes (myGlContext),
721                    myAspectFaceSet->TextureParams());
722   }
723   else
724   {
725     if (!myEnvironmentTexture.IsNull())
726     {
727       EnableTexture (myEnvironmentTexture,
728                      myEnvironmentTexture->GetParams());
729     }
730     else
731     {
732       DisableTexture();
733     }
734   }
735
736   myAspectFaceApplied = myAspectFaceSet->Aspect();
737   return myAspectFaceSet;
738 }
739
740 //=======================================================================
741 //function : SetPolygonOffset
742 //purpose  :
743 //=======================================================================
744 void OpenGl_Workspace::SetPolygonOffset (const Graphic3d_PolygonOffset& theParams)
745 {
746   myPolygonOffsetApplied = theParams;
747
748   if ((theParams.Mode & Aspect_POM_Fill) == Aspect_POM_Fill)
749   {
750     glEnable (GL_POLYGON_OFFSET_FILL);
751   }
752   else
753   {
754     glDisable (GL_POLYGON_OFFSET_FILL);
755   }
756
757 #if !defined(GL_ES_VERSION_2_0)
758   if ((theParams.Mode & Aspect_POM_Line) == Aspect_POM_Line)
759   {
760     glEnable (GL_POLYGON_OFFSET_LINE);
761   }
762   else
763   {
764     glDisable (GL_POLYGON_OFFSET_LINE);
765   }
766
767   if ((theParams.Mode & Aspect_POM_Point) == Aspect_POM_Point)
768   {
769     glEnable (GL_POLYGON_OFFSET_POINT);
770   }
771   else
772   {
773     glDisable (GL_POLYGON_OFFSET_POINT);
774   }
775 #endif
776   glPolygonOffset (theParams.Factor, theParams.Units);
777 }
778
779 // =======================================================================
780 // function : ApplyAspectMarker
781 // purpose  :
782 // =======================================================================
783 const OpenGl_AspectMarker* OpenGl_Workspace::ApplyAspectMarker()
784 {
785   if (myAspectMarkerSet->Aspect() != myAspectMarkerApplied)
786   {
787     if (myAspectMarkerApplied.IsNull()
788     || (myAspectMarkerSet->Aspect()->Scale() != myAspectMarkerApplied->Scale()))
789     {
790     #if !defined(GL_ES_VERSION_2_0)
791       glPointSize (myAspectMarkerSet->Aspect()->Scale());
792     #ifdef HAVE_GL2PS
793       gl2psPointSize (myAspectMarkerSet->Aspect()->Scale());
794     #endif
795     #endif
796     }
797     myAspectMarkerApplied = myAspectMarkerSet->Aspect();
798   }
799   return myAspectMarkerSet;
800 }
801
802 // =======================================================================
803 // function : Width
804 // purpose  :
805 // =======================================================================
806 Standard_Integer OpenGl_Workspace::Width()  const
807 {
808   return !myView->GlWindow().IsNull() ? myView->GlWindow()->Width() : 0;
809 }
810
811 // =======================================================================
812 // function : Height
813 // purpose  :
814 // =======================================================================
815 Standard_Integer OpenGl_Workspace::Height() const
816 {
817   return !myView->GlWindow().IsNull() ? myView->GlWindow()->Height() : 0;
818 }
819
820 // =======================================================================
821 // function : IsCullingEnabled
822 // purpose  :
823 // =======================================================================
824 Standard_Boolean OpenGl_Workspace::IsCullingEnabled() const
825 {
826   return myView->IsCullingEnabled();
827 }
828
829 // =======================================================================
830 // function : FBOCreate
831 // purpose  :
832 // =======================================================================
833 Handle(OpenGl_FrameBuffer) OpenGl_Workspace::FBOCreate (const Standard_Integer theWidth,
834                                                         const Standard_Integer theHeight)
835 {
836   // activate OpenGL context
837   if (!Activate())
838     return Handle(OpenGl_FrameBuffer)();
839
840   DisableTexture();
841
842   // create the FBO
843   const Handle(OpenGl_Context)& aCtx = GetGlContext();
844   Handle(OpenGl_FrameBuffer) aFrameBuffer = new OpenGl_FrameBuffer();
845   if (!aFrameBuffer->Init (aCtx, theWidth, theHeight, GL_RGBA8, GL_DEPTH24_STENCIL8, 0))
846   {
847     aFrameBuffer->Release (aCtx.operator->());
848     return Handle(OpenGl_FrameBuffer)();
849   }
850   return aFrameBuffer;
851 }
852
853 // =======================================================================
854 // function : FBORelease
855 // purpose  :
856 // =======================================================================
857 void OpenGl_Workspace::FBORelease (Handle(OpenGl_FrameBuffer)& theFbo)
858 {
859   // activate OpenGL context
860   if (!Activate()
861    || theFbo.IsNull())
862   {
863     return;
864   }
865
866   theFbo->Release (GetGlContext().operator->());
867   theFbo.Nullify();
868 }
869
870 // =======================================================================
871 // function : getAligned
872 // purpose  :
873 // =======================================================================
874 inline Standard_Size getAligned (const Standard_Size theNumber,
875                                  const Standard_Size theAlignment)
876 {
877   return theNumber + theAlignment - 1 - (theNumber - 1) % theAlignment;
878 }
879
880 template<typename T>
881 inline void convertRowFromRgba (T* theRgbRow,
882                                 const Image_ColorRGBA* theRgbaRow,
883                                 const Standard_Size theWidth)
884 {
885   for (Standard_Size aCol = 0; aCol < theWidth; ++aCol)
886   {
887     const Image_ColorRGBA& anRgba = theRgbaRow[aCol];
888     T& anRgb = theRgbRow[aCol];
889     anRgb.r() = anRgba.r();
890     anRgb.g() = anRgba.g();
891     anRgb.b() = anRgba.b();
892   }
893 }
894
895 // =======================================================================
896 // function : BufferDump
897 // purpose  :
898 // =======================================================================
899 Standard_Boolean OpenGl_Workspace::BufferDump (const Handle(OpenGl_FrameBuffer)& theFbo,
900                                                Image_PixMap&                     theImage,
901                                                const Graphic3d_BufferType&       theBufferType)
902 {
903   if (theImage.IsEmpty()
904   || !Activate())
905   {
906     return Standard_False;
907   }
908
909   GLenum aFormat = 0;
910   GLenum aType   = 0;
911   bool toSwapRgbaBgra = false;
912   bool toConvRgba2Rgb = false;
913   switch (theImage.Format())
914   {
915   #if !defined(GL_ES_VERSION_2_0)
916     case Image_Format_Gray:
917       aFormat = GL_DEPTH_COMPONENT;
918       aType   = GL_UNSIGNED_BYTE;
919       break;
920     case Image_Format_GrayF:
921       aFormat = GL_DEPTH_COMPONENT;
922       aType   = GL_FLOAT;
923       break;
924     case Image_Format_RGB:
925       aFormat = GL_RGB;
926       aType   = GL_UNSIGNED_BYTE;
927       break;
928     case Image_Format_BGR:
929       aFormat = GL_BGR;
930       aType   = GL_UNSIGNED_BYTE;
931       break;
932     case Image_Format_BGRA:
933     case Image_Format_BGR32:
934       aFormat = GL_BGRA;
935       aType   = GL_UNSIGNED_BYTE;
936       break;
937     case Image_Format_BGRF:
938       aFormat = GL_BGR;
939       aType   = GL_FLOAT;
940       break;
941     case Image_Format_BGRAF:
942       aFormat = GL_BGRA;
943       aType   = GL_FLOAT;
944       break;
945   #else
946     case Image_Format_Gray:
947     case Image_Format_GrayF:
948     case Image_Format_BGRF:
949     case Image_Format_BGRAF:
950       return Standard_False;
951     case Image_Format_BGRA:
952     case Image_Format_BGR32:
953       aFormat = GL_RGBA;
954       aType   = GL_UNSIGNED_BYTE;
955       toSwapRgbaBgra = true;
956       break;
957     case Image_Format_BGR:
958     case Image_Format_RGB:
959       aFormat = GL_RGBA;
960       aType   = GL_UNSIGNED_BYTE;
961       toConvRgba2Rgb = true;
962       break;
963   #endif
964     case Image_Format_RGBA:
965     case Image_Format_RGB32:
966       aFormat = GL_RGBA;
967       aType   = GL_UNSIGNED_BYTE;
968       break;
969     case Image_Format_RGBF:
970       aFormat = GL_RGB;
971       aType   = GL_FLOAT;
972       break;
973     case Image_Format_RGBAF:
974       aFormat = GL_RGBA;
975       aType   = GL_FLOAT;
976       break;
977     case Image_Format_Alpha:
978     case Image_Format_AlphaF:
979       return Standard_False; // GL_ALPHA is no more supported in core context
980     case Image_Format_UNKNOWN:
981       return Standard_False;
982   }
983
984   if (aFormat == 0)
985   {
986     return Standard_False;
987   }
988
989 #if !defined(GL_ES_VERSION_2_0)
990   GLint aReadBufferPrev = GL_BACK;
991   if (theBufferType == Graphic3d_BT_Depth
992    && aFormat != GL_DEPTH_COMPONENT)
993   {
994     return Standard_False;
995   }
996 #else
997   (void )theBufferType;
998 #endif
999
1000   // bind FBO if used
1001   if (!theFbo.IsNull() && theFbo->IsValid())
1002   {
1003     theFbo->BindBuffer (GetGlContext());
1004   }
1005   else
1006   {
1007   #if !defined(GL_ES_VERSION_2_0)
1008     glGetIntegerv (GL_READ_BUFFER, &aReadBufferPrev);
1009     GLint aDrawBufferPrev = GL_BACK;
1010     glGetIntegerv (GL_DRAW_BUFFER, &aDrawBufferPrev);
1011     glReadBuffer (aDrawBufferPrev);
1012   #endif
1013   }
1014
1015   // setup alignment
1016   const GLint anAligment   = Min (GLint(theImage.MaxRowAligmentBytes()), 8); // limit to 8 bytes for OpenGL
1017   glPixelStorei (GL_PACK_ALIGNMENT, anAligment);
1018   bool isBatchCopy = !theImage.IsTopDown();
1019
1020   const GLint   anExtraBytes       = GLint(theImage.RowExtraBytes());
1021   GLint         aPixelsWidth       = GLint(theImage.SizeRowBytes() / theImage.SizePixelBytes());
1022   Standard_Size aSizeRowBytesEstim = getAligned (theImage.SizePixelBytes() * aPixelsWidth, anAligment);
1023   if (anExtraBytes < anAligment)
1024   {
1025     aPixelsWidth = 0;
1026   }
1027   else if (aSizeRowBytesEstim != theImage.SizeRowBytes())
1028   {
1029     aPixelsWidth = 0;
1030     isBatchCopy  = false;
1031   }
1032 #if !defined(GL_ES_VERSION_2_0)
1033   glPixelStorei (GL_PACK_ROW_LENGTH, aPixelsWidth);
1034 #else
1035   if (aPixelsWidth != 0)
1036   {
1037     isBatchCopy = false;
1038   }
1039 #endif
1040   if (toConvRgba2Rgb)
1041   {
1042     Handle(NCollection_BaseAllocator) anAlloc = new NCollection_AlignedAllocator (16);
1043     const Standard_Size aRowSize = theImage.SizeX() * 4;
1044     NCollection_Buffer aRowBuffer (anAlloc);
1045     if (!aRowBuffer.Allocate (aRowSize))
1046     {
1047       return Standard_False;
1048     }
1049
1050     for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
1051     {
1052       // Image_PixMap rows indexation always starts from the upper corner
1053       // while order in memory depends on the flag and processed by ChangeRow() method
1054       glReadPixels (0, GLint(theImage.SizeY() - aRow - 1), GLsizei (theImage.SizeX()), 1, aFormat, aType, aRowBuffer.ChangeData());
1055       const Image_ColorRGBA* aRowDataRgba = (const Image_ColorRGBA* )aRowBuffer.Data();
1056       if (theImage.Format() == Image_Format_BGR)
1057       {
1058         convertRowFromRgba ((Image_ColorBGR* )theImage.ChangeRow (aRow), aRowDataRgba, theImage.SizeX());
1059       }
1060       else
1061       {
1062         convertRowFromRgba ((Image_ColorRGB* )theImage.ChangeRow (aRow), aRowDataRgba, theImage.SizeX());
1063       }
1064     }
1065   }
1066   else if (!isBatchCopy)
1067   {
1068     // copy row by row
1069     for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
1070     {
1071       // Image_PixMap rows indexation always starts from the upper corner
1072       // while order in memory depends on the flag and processed by ChangeRow() method
1073       glReadPixels (0, GLint(theImage.SizeY() - aRow - 1), GLsizei (theImage.SizeX()), 1, aFormat, aType, theImage.ChangeRow (aRow));
1074     }
1075   }
1076   else
1077   {
1078     glReadPixels (0, 0, GLsizei (theImage.SizeX()), GLsizei (theImage.SizeY()), aFormat, aType, theImage.ChangeData());
1079   }
1080   const bool hasErrors = myGlContext->ResetErrors (true);
1081
1082   glPixelStorei (GL_PACK_ALIGNMENT,  1);
1083 #if !defined(GL_ES_VERSION_2_0)
1084   glPixelStorei (GL_PACK_ROW_LENGTH, 0);
1085 #endif
1086
1087   if (!theFbo.IsNull() && theFbo->IsValid())
1088   {
1089     theFbo->UnbindBuffer (GetGlContext());
1090   }
1091   else
1092   {
1093   #if !defined(GL_ES_VERSION_2_0)
1094     glReadBuffer (aReadBufferPrev);
1095   #endif
1096   }
1097
1098   if (toSwapRgbaBgra)
1099   {
1100     Image_PixMap::SwapRgbaBgra (theImage);
1101   }
1102
1103   return !hasErrors;
1104 }
1105
1106 // =======================================================================
1107 // function : CanRender
1108 // purpose  :
1109 // =======================================================================
1110 Standard_Boolean OpenGl_RaytraceFilter::CanRender (const OpenGl_Element* theElement)
1111 {
1112   Standard_Boolean aPrevFilterResult = Standard_True;
1113   if (!myPrevRenderFilter.IsNull())
1114   {
1115     aPrevFilterResult = myPrevRenderFilter->CanRender (theElement);
1116   }
1117   return aPrevFilterResult &&
1118     !OpenGl_Raytrace::IsRaytracedElement (theElement);
1119 }