0024452: TKOpenGl - Memory leak in OpenGl_ShaderManager
[occt.git] / src / OpenGl / OpenGl_ShaderManager.cxx
1 // Created on: 2013-09-26
2 // Created by: Denis BOGOLEPOV
3 // Copyright (c) 2013 OPEN CASCADE SAS
4 //
5 // The content of this file is subject to the Open CASCADE Technology Public
6 // License Version 6.5 (the "License"). You may not use the content of this file
7 // except in compliance with the License. Please obtain a copy of the License
8 // at http://www.opencascade.org and read it completely before using this file.
9 //
10 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
11 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
12 //
13 // The Original Code and all software distributed under the License is
14 // distributed on an "AS IS" basis, without warranty of any kind, and the
15 // Initial Developer hereby disclaims all such warranties, including without
16 // limitation, any warranties of merchantability, fitness for a particular
17 // purpose or non-infringement. Please see the License for the specific terms
18 // and conditions governing the rights and limitations under the License.
19
20 #include <typeinfo>
21
22 #include <OpenGl_AspectFace.hxx>
23 #include <OpenGl_AspectLine.hxx>
24 #include <OpenGl_AspectMarker.hxx>
25 #include <OpenGl_AspectText.hxx>
26 #include <OpenGl_Clipping.hxx>
27 #include <OpenGl_Context.hxx>
28 #include <OpenGl_ShaderManager.hxx>
29 #include <OpenGl_ShaderProgram.hxx>
30 #include <OpenGl_Workspace.hxx>
31
32 IMPLEMENT_STANDARD_HANDLE (OpenGl_ShaderManager, Standard_Transient)
33 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_ShaderManager, Standard_Transient)
34
35 // =======================================================================
36 // function : OpenGl_ShaderManager
37 // purpose  : Creates new empty shader manager
38 // =======================================================================
39 OpenGl_ShaderManager::OpenGl_ShaderManager (OpenGl_Context* theContext)
40 : myContext (theContext),
41   myIsPP    (Standard_False)
42 {
43   //
44 }
45
46 // =======================================================================
47 // function : ~OpenGl_ShaderManager
48 // purpose  : Releases resources of shader manager
49 // =======================================================================
50 OpenGl_ShaderManager::~OpenGl_ShaderManager()
51 {
52   myProgramList.Clear();
53 }
54
55 // =======================================================================
56 // function : Create
57 // purpose  : Creates new shader program
58 // =======================================================================
59 void OpenGl_ShaderManager::Create (const Handle(Graphic3d_ShaderProgram)& theProxy,
60                                    TCollection_AsciiString&               theShareKey,
61                                    Handle(OpenGl_ShaderProgram)&          theProgram)
62 {
63   theProgram.Nullify();
64   if (theProxy.IsNull())
65   {
66     return;
67   }
68
69   theShareKey = theProxy->GetId();
70   if (myContext->GetResource<Handle(OpenGl_ShaderProgram)> (theShareKey, theProgram))
71   {
72     if (theProgram->Share())
73     {
74       myProgramList.Append (theProgram);
75     }
76     return;
77   }
78
79   theProgram = new OpenGl_ShaderProgram (theProxy);
80   if (!theProgram->Initialize (myContext, theProxy->ShaderObjects()))
81   {
82     theProgram->Release (myContext);
83     theShareKey.Clear();
84     theProgram.Nullify();
85     return;
86   }
87
88   myProgramList.Append (theProgram);
89   myContext->ShareResource (theShareKey, theProgram);
90 }
91
92 // =======================================================================
93 // function : Unregister
94 // purpose  : Removes specified shader program from the manager
95 // =======================================================================
96 void OpenGl_ShaderManager::Unregister (TCollection_AsciiString&      theShareKey,
97                                        Handle(OpenGl_ShaderProgram)& theProgram)
98 {
99   for (OpenGl_ShaderProgramList::Iterator anIt (myProgramList); anIt.More(); anIt.Next())
100   {
101     if (anIt.Value() == theProgram)
102     {
103       if (!theProgram->UnShare())
104       {
105         theShareKey.Clear();
106         theProgram.Nullify();
107         return;
108       }
109
110       myProgramList.Remove (anIt);
111       myMaterialStates.UnBind (theProgram);
112       break;
113     }
114   }
115
116   const TCollection_AsciiString anID = theProgram->myProxy->GetId();
117   if (anID.IsEmpty())
118   {
119     myContext->DelayedRelease (theProgram);
120     theProgram.Nullify();
121   }
122   else
123   {
124     theProgram.Nullify();
125     myContext->ReleaseResource (anID, Standard_True);
126   }
127 }
128
129 // =======================================================================
130 // function : ShaderPrograms
131 // purpose  : Returns list of registered shader programs
132 // =======================================================================
133 const OpenGl_ShaderProgramList& OpenGl_ShaderManager::ShaderPrograms() const
134 {
135   return myProgramList;
136 }
137
138 // =======================================================================
139 // function : Empty
140 // purpose  : Returns true if no program objects are attached
141 // =======================================================================
142 Standard_Boolean OpenGl_ShaderManager::IsEmpty() const
143 {
144   return myProgramList.IsEmpty();
145 }
146
147 // =======================================================================
148 // function : UpdateLightSourceStateTo
149 // purpose  : Updates state of OCCT light sources
150 // =======================================================================
151 void OpenGl_ShaderManager::UpdateLightSourceStateTo (const OpenGl_ListOfLight* theLights)
152 {
153   myLightSourceState.Set (theLights);
154   myLightSourceState.Update();
155 }
156
157 // =======================================================================
158 // function : SetProjectionState
159 // purpose  : Sets new state of OCCT projection transform
160 // =======================================================================
161 void OpenGl_ShaderManager::UpdateProjectionStateTo (const Tmatrix3& theProjectionMatrix)
162 {
163   myProjectionState.Set (theProjectionMatrix);
164   myProjectionState.Update();
165 }
166
167 // =======================================================================
168 // function : SetModelWorldState
169 // purpose  : Sets new state of OCCT model-world transform
170 // =======================================================================
171 void OpenGl_ShaderManager::UpdateModelWorldStateTo (const Tmatrix3& theModelWorldMatrix)
172 {
173   myModelWorldState.Set (theModelWorldMatrix);
174   myModelWorldState.Update();
175 }
176
177 // =======================================================================
178 // function : SetWorldViewState
179 // purpose  : Sets new state of OCCT world-view transform
180 // =======================================================================
181 void OpenGl_ShaderManager::UpdateWorldViewStateTo (const Tmatrix3& theWorldViewMatrix)
182 {
183   myWorldViewState.Set (theWorldViewMatrix);
184   myWorldViewState.Update();
185 }
186
187 // =======================================================================
188 // function : RevertProjectionStateTo
189 // purpose  : Reverts state of OCCT projection transform
190 // =======================================================================
191 void OpenGl_ShaderManager::RevertProjectionStateTo (const Tmatrix3& theProjectionMatrix)
192 {
193   myProjectionState.Set (theProjectionMatrix);
194   myProjectionState.Revert();
195 }
196
197 // =======================================================================
198 // function : RevertModelWorldStateTo
199 // purpose  : Reverts state of OCCT model-world transform
200 // =======================================================================
201 void OpenGl_ShaderManager::RevertModelWorldStateTo (const Tmatrix3& theModelWorldMatrix)
202 {
203   myModelWorldState.Set (theModelWorldMatrix);
204   myModelWorldState.Revert();
205 }
206
207 // =======================================================================
208 // function : RevertWorldViewStateTo
209 // purpose  : Reverts state of OCCT world-view transform
210 // =======================================================================
211 void OpenGl_ShaderManager::RevertWorldViewStateTo (const Tmatrix3& theWorldViewMatrix)
212 {
213   myWorldViewState.Set (theWorldViewMatrix);
214   myWorldViewState.Revert();
215 }
216
217 // =======================================================================
218 // function : LightSourceState
219 // purpose  : Returns current state of OCCT light sources
220 // =======================================================================
221 const OpenGl_LightSourceState& OpenGl_ShaderManager::LightSourceState() const
222 {
223   return myLightSourceState;
224 }
225
226 // =======================================================================
227 // function : ProjectionState
228 // purpose  : Returns current state of OCCT projection transform
229 // =======================================================================
230 const OpenGl_ProjectionState& OpenGl_ShaderManager::ProjectionState() const
231 {
232   return myProjectionState;
233 }
234
235 // =======================================================================
236 // function : ModelWorldState
237 // purpose  : Returns current state of OCCT model-world transform
238 // =======================================================================
239 const OpenGl_ModelWorldState& OpenGl_ShaderManager::ModelWorldState() const
240 {
241   return myModelWorldState;
242 }
243
244 // =======================================================================
245 // function : WorldViewState
246 // purpose  : Returns current state of OCCT world-view transform
247 // =======================================================================
248 const OpenGl_WorldViewState& OpenGl_ShaderManager::WorldViewState() const
249 {
250   return myWorldViewState;
251 }
252
253 //! Packed properties of light source
254 class OpenGl_ShaderLightParameters
255 {
256 public:
257
258   OpenGl_Vec4 Color;
259   OpenGl_Vec4 Position;
260   OpenGl_Vec4 Direction;
261   OpenGl_Vec4 Parameters;
262
263   //! Returns packed (serialized) representation of light source properties
264   const OpenGl_Vec4* Packed() const { return reinterpret_cast<const OpenGl_Vec4*> (this); }
265   static Standard_Integer NbOfVec4() { return 4; }
266
267 };
268
269 //! Packed light source type information
270 class OpenGl_ShaderLightType
271 {
272 public:
273
274   Standard_Integer Type;
275   Standard_Integer IsHeadlight;
276
277   //! Returns packed (serialized) representation of light source type
278   const OpenGl_Vec2i* Packed() const { return reinterpret_cast<const OpenGl_Vec2i*> (this); }
279   static Standard_Integer NbOfVec2i() { return 1; }
280
281 };
282
283 // =======================================================================
284 // function : PushLightSourceState
285 // purpose  : Pushes state of OCCT light sources to the program
286 // =======================================================================
287 void OpenGl_ShaderManager::PushLightSourceState (const Handle(OpenGl_ShaderProgram)& theProgram) const
288 {
289   if (myLightSourceState.Index() == theProgram->ActiveState (OpenGl_LIGHT_SOURCES_STATE)
290    || !theProgram->IsValid())
291   {
292     return;
293   }
294
295   OpenGl_ShaderLightType* aLightTypeArray = new OpenGl_ShaderLightType[OpenGLMaxLights];
296   for (Standard_Integer aLightIt = 0; aLightIt < OpenGLMaxLights; ++aLightIt)
297   {
298     aLightTypeArray[aLightIt].Type = -1;
299   }
300
301   const Standard_Integer aLightsDefNb = Min (myLightSourceState.LightSources()->Size(), OpenGLMaxLights);
302   if (aLightsDefNb < 1)
303   {
304     theProgram->SetUniform (myContext,
305                             theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_COUNT),
306                             0);
307     theProgram->SetUniform (myContext,
308                             theProgram->GetStateLocation (OpenGl_OCC_LIGHT_AMBIENT),
309                             OpenGl_Vec4 (0.0f, 0.0f, 0.0f, 0.0f));
310     theProgram->SetUniform (myContext,
311                             theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_TYPES),
312                             OpenGLMaxLights * OpenGl_ShaderLightType::NbOfVec2i(),
313                             aLightTypeArray[0].Packed());
314     theProgram->UpdateState (OpenGl_LIGHT_SOURCES_STATE, myLightSourceState.Index());
315     delete[] aLightTypeArray;
316     return;
317   }
318
319   OpenGl_ShaderLightParameters* aLightParamsArray = new OpenGl_ShaderLightParameters[aLightsDefNb];
320
321   OpenGl_Vec4 anAmbient (0.0f, 0.0f, 0.0f, 0.0f);
322   Standard_Integer aLightsNb = 0;
323   for (OpenGl_ListOfLight::Iterator anIter (*myLightSourceState.LightSources()); anIter.More(); anIter.Next())
324   {
325     const OpenGl_Light& aLight = anIter.Value();
326     if (aLight.Type == Visual3d_TOLS_AMBIENT)
327     {
328       anAmbient += aLight.Color;
329       continue;
330     }
331     else if (aLightsNb >= OpenGLMaxLights)
332     {
333       continue;
334     }
335
336     OpenGl_ShaderLightType& aLightType = aLightTypeArray[aLightsNb];
337     aLightType.Type        = aLight.Type;
338     aLightType.IsHeadlight = aLight.IsHeadlight;
339
340     OpenGl_ShaderLightParameters& aLightParams = aLightParamsArray[aLightsNb];
341     aLightParams.Color    = aLight.Color;
342     aLightParams.Position = aLight.Type == Visual3d_TOLS_DIRECTIONAL
343                          ? -aLight.Direction
344                          :  aLight.Position;
345     if (aLight.Type == Visual3d_TOLS_SPOT)
346     {
347       aLightParams.Direction = aLight.Direction;
348     }
349     aLightParams.Parameters = aLight.Params;
350     ++aLightsNb;
351   }
352
353   theProgram->SetUniform (myContext,
354                           theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_COUNT),
355                           aLightsNb);
356   theProgram->SetUniform (myContext,
357                           theProgram->GetStateLocation (OpenGl_OCC_LIGHT_AMBIENT),
358                           anAmbient);
359   theProgram->SetUniform (myContext,
360                           theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_TYPES),
361                           OpenGLMaxLights * OpenGl_ShaderLightType::NbOfVec2i(),
362                           aLightTypeArray[0].Packed());
363   if (aLightsNb > 0)
364   {
365     theProgram->SetUniform (myContext,
366                             theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_PARAMS),
367                             aLightsNb * OpenGl_ShaderLightParameters::NbOfVec4(),
368                             aLightParamsArray[0].Packed());
369   }
370   delete[] aLightParamsArray;
371   delete[] aLightTypeArray;
372
373   theProgram->UpdateState (OpenGl_LIGHT_SOURCES_STATE, myLightSourceState.Index());
374 }
375
376 // =======================================================================
377 // function : PushProjectionState
378 // purpose  : Pushes state of OCCT projection transform to the program
379 // =======================================================================
380 void OpenGl_ShaderManager::PushProjectionState (const Handle(OpenGl_ShaderProgram)& theProgram) const
381 {
382   if (myProjectionState.Index() == theProgram->ActiveState (OpenGl_PROJECTION_STATE))
383   {
384     return;
385   }
386
387   theProgram->SetUniform (myContext,
388                           theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX),
389                           myProjectionState.ProjectionMatrix());
390
391   GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_INVERSE);
392   if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
393   {
394     theProgram->SetUniform (myContext, aLocation, myProjectionState.ProjectionMatrixInverse());
395   }
396
397   theProgram->SetUniform (myContext,
398                           theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_TRANSPOSE),
399                           myProjectionState.ProjectionMatrix(), true);
400
401   aLocation = theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_INVERSE_TRANSPOSE);
402   if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
403   {
404     theProgram->SetUniform (myContext, aLocation, myProjectionState.ProjectionMatrixInverse(), true);
405   }
406
407   theProgram->UpdateState (OpenGl_PROJECTION_STATE, myProjectionState.Index());
408 }
409
410 // =======================================================================
411 // function : PushModelWorldState
412 // purpose  : Pushes state of OCCT model-world transform to the program
413 // =======================================================================
414 void OpenGl_ShaderManager::PushModelWorldState (const Handle(OpenGl_ShaderProgram)& theProgram) const
415 {
416   if (myModelWorldState.Index() == theProgram->ActiveState (OpenGl_MODEL_WORLD_STATE))
417   {
418     return;
419   }
420
421   theProgram->SetUniform (myContext,
422                           theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX),
423                           myModelWorldState.ModelWorldMatrix());
424
425   GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE);
426   if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
427   {
428     theProgram->SetUniform (myContext, aLocation, myModelWorldState.ModelWorldMatrixInverse());
429   }
430
431   theProgram->SetUniform (myContext,
432                           theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_TRANSPOSE),
433                           myModelWorldState.ModelWorldMatrix(), true);
434
435   aLocation = theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE_TRANSPOSE);
436   if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
437   {
438     theProgram->SetUniform (myContext, aLocation, myModelWorldState.ModelWorldMatrixInverse(), true);
439   }
440
441   theProgram->UpdateState (OpenGl_MODEL_WORLD_STATE, myModelWorldState.Index());
442 }
443
444 // =======================================================================
445 // function : PushWorldViewState
446 // purpose  : Pushes state of OCCT world-view transform to the program
447 // =======================================================================
448 void OpenGl_ShaderManager::PushWorldViewState (const Handle(OpenGl_ShaderProgram)& theProgram) const
449 {
450   if (myWorldViewState.Index() == theProgram->ActiveState (OpenGl_WORLD_VIEW_STATE))
451   {
452     return;
453   }
454
455   theProgram->SetUniform (myContext,
456                           theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX),
457                           myWorldViewState.WorldViewMatrix());
458
459   GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE);
460   if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
461   {
462     theProgram->SetUniform (myContext, aLocation, myWorldViewState.WorldViewMatrixInverse());
463   }
464
465   theProgram->SetUniform (myContext,
466                           theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_TRANSPOSE),
467                           myWorldViewState.WorldViewMatrix(), true);
468
469   aLocation = theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE_TRANSPOSE);
470   if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
471   {
472     theProgram->SetUniform (myContext, aLocation, myWorldViewState.WorldViewMatrixInverse(), true);
473   }
474
475   theProgram->UpdateState (OpenGl_WORLD_VIEW_STATE, myWorldViewState.Index());
476 }
477
478 // =======================================================================
479 // function : UpdateClippingState
480 // purpose  : Updates state of OCCT clipping planes
481 // =======================================================================
482 void OpenGl_ShaderManager::UpdateClippingState()
483 {
484   myClippingState.Update();
485 }
486
487 // =======================================================================
488 // function : RevertClippingState
489 // purpose  : Reverts state of OCCT clipping planes
490 // =======================================================================
491 void OpenGl_ShaderManager::RevertClippingState()
492 {
493   myClippingState.Revert();
494 }
495
496 // =======================================================================
497 // function : PushClippingState
498 // purpose  : Pushes state of OCCT clipping planes to the program
499 // =======================================================================
500 void OpenGl_ShaderManager::PushClippingState (const Handle(OpenGl_ShaderProgram)& theProgram) const
501 {
502   if (myClippingState.Index() == theProgram->ActiveState (OpenGl_CLIP_PLANES_STATE))
503   {
504     return;
505   }
506
507   theProgram->UpdateState (OpenGl_CLIP_PLANES_STATE, myClippingState.Index());
508   const GLint aLocEquations = theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_EQUATIONS);
509   const GLint aLocSpaces    = theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_SPACES);
510   if (aLocEquations == OpenGl_ShaderProgram::INVALID_LOCATION
511    && aLocSpaces    == OpenGl_ShaderProgram::INVALID_LOCATION)
512   {
513     return;
514   }
515
516   GLuint aPlanesNb = 0;
517   for (Graphic3d_SequenceOfHClipPlane::Iterator anIter (myContext->Clipping().Planes());
518        anIter.More(); anIter.Next())
519   {
520     const Handle(Graphic3d_ClipPlane)& aPlane = anIter.Value();
521     if (!myContext->Clipping().IsEnabled (aPlane))
522     {
523       continue;
524     }
525
526     ++aPlanesNb;
527   }
528   if (aPlanesNb < 1)
529   {
530     return;
531   }
532
533   OpenGl_Vec4* anEquations = new OpenGl_Vec4[aPlanesNb];
534   GLint*       aSpaces     = new GLint      [aPlanesNb];
535   GLuint aPlaneId = 0;
536   for (Graphic3d_SequenceOfHClipPlane::Iterator anIter (myContext->Clipping().Planes());
537        anIter.More(); anIter.Next())
538   {
539     const Handle(Graphic3d_ClipPlane)& aPlane = anIter.Value();
540     if (!myContext->Clipping().IsEnabled (aPlane))
541     {
542       continue;
543     }
544
545     const Graphic3d_ClipPlane::Equation& anEquation = aPlane->GetEquation();
546     anEquations[aPlaneId] = OpenGl_Vec4 ((float) anEquation.x(),
547                                          (float) anEquation.y(),
548                                          (float) anEquation.z(),
549                                          (float) anEquation.w());
550     aSpaces[aPlaneId] = myContext->Clipping().GetEquationSpace (aPlane);
551     ++aPlaneId;
552   }
553   theProgram->SetUniform (myContext, aLocEquations, aPlanesNb, anEquations[0].GetData());
554   theProgram->SetUniform (myContext, aLocSpaces,    aPlanesNb, aSpaces);
555
556   delete[] anEquations;
557   delete[] aSpaces;
558 }
559
560 // =======================================================================
561 // function : UpdateMaterialStateTo
562 // purpose  : Updates state of OCCT material for specified program
563 // =======================================================================
564 void OpenGl_ShaderManager::UpdateMaterialStateTo (const Handle(OpenGl_ShaderProgram)& theProgram,
565                                                   const OpenGl_Element*               theAspect)
566 {
567   if (myMaterialStates.IsBound (theProgram))
568   {
569     myMaterialStates.ChangeFind (theProgram).Set (theAspect);
570   }
571   else
572   {
573     myMaterialStates.Bind (theProgram, OpenGl_MaterialState (theAspect));
574   }
575
576   myMaterialStates.ChangeFind (theProgram).Update();
577 }
578
579 // =======================================================================
580 // function : ResetMaterialStates
581 // purpose  : Resets state of OCCT material for all programs
582 // =======================================================================
583 void OpenGl_ShaderManager::ResetMaterialStates()
584 {
585   for (OpenGl_ShaderProgramList::Iterator anIt (myProgramList); anIt.More(); anIt.Next())
586   {
587     anIt.Value()->UpdateState (OpenGl_MATERIALS_STATE, 0);
588   }
589 }
590
591 // =======================================================================
592 // function : MaterialState
593 // purpose  : Returns state of OCCT material for specified program
594 // =======================================================================
595 const OpenGl_MaterialState* OpenGl_ShaderManager::MaterialState (const Handle(OpenGl_ShaderProgram)& theProgram) const
596 {
597   if (!myMaterialStates.IsBound (theProgram))
598     return NULL;
599
600   return &myMaterialStates.Find (theProgram);
601 }
602
603 namespace
604 {
605
606 static const OpenGl_Vec4 THE_COLOR_BLACK_VEC4 (0.0f, 0.0f, 0.0f, 0.0f);
607
608 // =======================================================================
609 // function : PushAspectFace
610 // purpose  :
611 // =======================================================================
612 static void PushAspectFace (const Handle(OpenGl_Context)&       theCtx,
613                             const Handle(OpenGl_ShaderProgram)& theProgram,
614                             const OpenGl_AspectFace*            theAspect)
615 {
616   theProgram->SetUniform (theCtx,
617                           theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE),
618                           theAspect->DoTextureMap());
619   theProgram->SetUniform (theCtx,
620                           theProgram->GetStateLocation (OpenGl_OCCT_ACTIVE_SAMPLER),
621                           0 /* GL_TEXTURE0 */);
622   theProgram->SetUniform (theCtx,
623                           theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE),
624                           theAspect->DistinguishingMode());
625
626   OpenGl_Material aParams;
627   for (Standard_Integer anIndex = 0; anIndex < 2; ++anIndex)
628   {
629     const GLint aLoc = theProgram->GetStateLocation (anIndex == 0
630                                                    ? OpenGl_OCCT_FRONT_MATERIAL
631                                                    : OpenGl_OCCT_BACK_MATERIAL);
632     if (aLoc == OpenGl_ShaderProgram::INVALID_LOCATION)
633     {
634       continue;
635     }
636
637     aParams.Init (anIndex == 0 ? theAspect->IntFront() : theAspect->IntBack());
638     theProgram->SetUniform (theCtx, aLoc, OpenGl_Material::NbOfVec4(),
639                             aParams.Packed());
640   }
641 }
642
643 // =======================================================================
644 // function : PushAspectLine
645 // purpose  :
646 // =======================================================================
647 static void PushAspectLine (const Handle(OpenGl_Context)&       theCtx,
648                             const Handle(OpenGl_ShaderProgram)& theProgram,
649                             const OpenGl_AspectLine*            theAspect)
650 {
651   theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE),   TOff);
652   theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE), TOff);
653
654   const OpenGl_Vec4 aDiffuse (theAspect->Color().rgb[0],
655                               theAspect->Color().rgb[1],
656                               theAspect->Color().rgb[2],
657                               theAspect->Color().rgb[3]);
658   OpenGl_Vec4 aParams[5];
659   aParams[0] = THE_COLOR_BLACK_VEC4;
660   aParams[1] = THE_COLOR_BLACK_VEC4;
661   aParams[2] = aDiffuse;
662   aParams[3] = THE_COLOR_BLACK_VEC4;
663   aParams[4].x() = 0.0f; // shininess
664   aParams[4].y() = 0.0f; // transparency
665   theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL),
666                           5, aParams);
667 }
668
669 // =======================================================================
670 // function : PushAspectText
671 // purpose  :
672 // =======================================================================
673 static void PushAspectText (const Handle(OpenGl_Context)&       theCtx,
674                             const Handle(OpenGl_ShaderProgram)& theProgram,
675                             const OpenGl_AspectText*            theAspect)
676 {
677   theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE),   TOn);
678   theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE), TOff);
679   theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_ACTIVE_SAMPLER),   0 /* GL_TEXTURE0 */);
680
681   OpenGl_Vec4 aDiffuse (theAspect->Color().rgb[0],
682                         theAspect->Color().rgb[1],
683                         theAspect->Color().rgb[2],
684                         theAspect->Color().rgb[3]);
685   if (theAspect->DisplayType() == Aspect_TODT_DEKALE
686    || theAspect->DisplayType() == Aspect_TODT_SUBTITLE)
687   {
688     aDiffuse = OpenGl_Vec4 (theAspect->SubtitleColor().rgb[0],
689                             theAspect->SubtitleColor().rgb[1],
690                             theAspect->SubtitleColor().rgb[2],
691                             theAspect->SubtitleColor().rgb[3]);
692   }
693
694   OpenGl_Vec4 aParams[5];
695   aParams[0] = THE_COLOR_BLACK_VEC4;
696   aParams[1] = THE_COLOR_BLACK_VEC4;
697   aParams[2] = aDiffuse;
698   aParams[3] = THE_COLOR_BLACK_VEC4;
699   aParams[4].x() = 0.0f; // shininess
700   aParams[4].y() = 0.0f; // transparency
701   theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL),
702                           5, aParams);
703 }
704
705 // =======================================================================
706 // function : PushAspectMarker
707 // purpose  :
708 // =======================================================================
709 static void PushAspectMarker (const Handle(OpenGl_Context)&       theCtx,
710                               const Handle(OpenGl_ShaderProgram)& theProgram,
711                               const OpenGl_AspectMarker*          theAspect)
712 {
713   theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE),   TOn);
714   theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE), TOff);
715   theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_ACTIVE_SAMPLER),   0 /* GL_TEXTURE0 */);
716
717   const OpenGl_Vec4 aDiffuse (theAspect->Color().rgb[0],
718                               theAspect->Color().rgb[1],
719                               theAspect->Color().rgb[2],
720                               theAspect->Color().rgb[3]);
721   OpenGl_Vec4 aParams[5];
722   aParams[0] = THE_COLOR_BLACK_VEC4;
723   aParams[1] = THE_COLOR_BLACK_VEC4;
724   aParams[2] = aDiffuse;
725   aParams[3] = THE_COLOR_BLACK_VEC4;
726   aParams[4].x() = 0.0f; // shininess
727   aParams[4].y() = 0.0f; // transparency
728   theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL),
729                           5, aParams);
730 }
731
732 }; // nameless namespace
733
734 // =======================================================================
735 // function : PushMaterialState
736 // purpose  : Pushes current state of OCCT material to the program
737 // =======================================================================
738 void OpenGl_ShaderManager::PushMaterialState (const Handle(OpenGl_ShaderProgram)& theProgram) const
739 {
740   if (!myMaterialStates.IsBound (theProgram))
741   {
742     return;
743   }
744
745   const OpenGl_MaterialState& aState = myMaterialStates.Find (theProgram);
746   if (aState.Index() == theProgram->ActiveState (OpenGl_MATERIALS_STATE))
747   {
748     return;
749   }
750
751   if (typeid (*aState.Aspect()) == typeid (OpenGl_AspectFace))
752   {
753     PushAspectFace   (myContext, theProgram, dynamic_cast<const OpenGl_AspectFace*> (aState.Aspect()));
754   }
755   else if (typeid (*aState.Aspect()) == typeid (OpenGl_AspectLine))
756   {
757     PushAspectLine   (myContext, theProgram, dynamic_cast<const OpenGl_AspectLine*> (aState.Aspect()));
758   }
759   else if (typeid (*aState.Aspect()) == typeid (OpenGl_AspectText))
760   {
761     PushAspectText   (myContext, theProgram, dynamic_cast<const OpenGl_AspectText*> (aState.Aspect()));
762   }
763   else if (typeid (*aState.Aspect()) == typeid (OpenGl_AspectMarker))
764   {
765     PushAspectMarker (myContext, theProgram, dynamic_cast<const OpenGl_AspectMarker*> (aState.Aspect()));
766   }
767
768   theProgram->UpdateState (OpenGl_MATERIALS_STATE, aState.Index());
769 }
770
771 // =======================================================================
772 // function : PushWorldViewState
773 // purpose  : Pushes state of OCCT graphics parameters to the program
774 // =======================================================================
775 void OpenGl_ShaderManager::PushState (const Handle(OpenGl_ShaderProgram)& theProgram) const
776 {
777   PushClippingState    (theProgram);
778   PushMaterialState    (theProgram);
779   PushWorldViewState   (theProgram);
780   PushModelWorldState  (theProgram);
781   PushProjectionState  (theProgram);  
782   PushLightSourceState (theProgram);
783 }