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