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