a4366f60876a49020fff4e5d8675ca58d1264b1c
[occt.git] / src / OpenGl / OpenGl_ShaderProgram.cxx
1 // Created on: 2013-09-19
2 // Created by: Denis BOGOLEPOV
3 // Copyright (c) 2013-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 <OSD_File.hxx>
17 #include <OSD_Protection.hxx>
18
19 #include <Standard_Assert.hxx>
20 #include <Standard_Atomic.hxx>
21 #include <TCollection_ExtendedString.hxx>
22
23 #include <OpenGl_Context.hxx>
24 #include <OpenGl_ShaderProgram.hxx>
25 #include <OpenGl_ShaderManager.hxx>
26
27 IMPLEMENT_STANDARD_HANDLE (OpenGl_ShaderProgram, OpenGl_Resource)
28 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_ShaderProgram, OpenGl_Resource)
29
30 OpenGl_VariableSetterSelector OpenGl_ShaderProgram::mySetterSelector = OpenGl_VariableSetterSelector();
31
32 // Declare OCCT-specific OpenGL/GLSL shader variables
33 Standard_CString OpenGl_ShaderProgram::PredefinedKeywords[] =
34 {
35   "occModelWorldMatrix",                 // OpenGl_OCC_MODEL_WORLD_MATRIX
36   "occWorldViewMatrix",                  // OpenGl_OCC_WORLD_VIEW_MATRIX
37   "occProjectionMatrix",                 // OpenGl_OCC_PROJECTION_MATRIX
38   "occModelWorldMatrixInverse",          // OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE
39   "occWorldViewMatrixInverse",           // OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE
40   "occProjectionMatrixInverse",          // OpenGl_OCC_PROJECTION_MATRIX_INVERSE
41   "occModelWorldMatrixTranspose",        // OpenGl_OCC_MODEL_WORLD_MATRIX_TRANSPOSE
42   "occWorldViewMatrixTranspose",         // OpenGl_OCC_WORLD_VIEW_MATRIX_TRANSPOSE
43   "occProjectionMatrixTranspose",        // OpenGl_OCC_PROJECTION_MATRIX_TRANSPOSE
44   "occModelWorldMatrixInverseTranspose", // OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE_TRANSPOSE
45   "occWorldViewMatrixInverseTranspose",  // OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE_TRANSPOSE
46   "occProjectionMatrixInverseTranspose", // OpenGl_OCC_PROJECTION_MATRIX_INVERSE_TRANSPOSE
47
48   "occClipPlaneEquations", // OpenGl_OCC_CLIP_PLANE_EQUATIONS
49   "occClipPlaneSpaces",    // OpenGl_OCC_CLIP_PLANE_SPACES
50   "occClipPlaneCount",     // OpenGl_OCC_CLIP_PLANE_COUNT
51
52   "occLightSourcesCount",  // OpenGl_OCC_LIGHT_SOURCE_COUNT
53   "occLightSourcesTypes",  // OpenGl_OCC_LIGHT_SOURCE_TYPES
54   "occLightSources",       // OpenGl_OCC_LIGHT_SOURCE_PARAMS
55   "occLightAmbient",       // OpenGl_OCC_LIGHT_AMBIENT
56
57   "occActiveSampler",      // OpenGl_OCCT_ACTIVE_SAMPLER
58   "occTextureEnable",      // OpenGl_OCCT_TEXTURE_ENABLE
59   "occDistinguishingMode", // OpenGl_OCCT_DISTINGUISH_MODE
60   "occFrontMaterial",      // OpenGl_OCCT_FRONT_MATERIAL
61   "occBackMaterial"        // OpenGl_OCCT_BACK_MATERIAL
62
63 };
64
65 // =======================================================================
66 // function : OpenGl_VariableSetterSelector
67 // purpose  : Creates new variable setter selector
68 // =======================================================================
69 OpenGl_VariableSetterSelector::OpenGl_VariableSetterSelector()
70 {
71   // Note: Add new variable setters here
72   mySetterList = OpenGl_HashMapInitializer::CreateListOf<size_t, OpenGl_SetterInterface*>
73     (Graphic3d_UniformValueTypeID<int>::ID,          new OpenGl_VariableSetter<int>())
74     (Graphic3d_UniformValueTypeID<float>::ID,        new OpenGl_VariableSetter<float>())
75     (Graphic3d_UniformValueTypeID<OpenGl_Vec2>::ID,  new OpenGl_VariableSetter<OpenGl_Vec2>())
76     (Graphic3d_UniformValueTypeID<OpenGl_Vec3>::ID,  new OpenGl_VariableSetter<OpenGl_Vec3>())
77     (Graphic3d_UniformValueTypeID<OpenGl_Vec4>::ID,  new OpenGl_VariableSetter<OpenGl_Vec4>())
78     (Graphic3d_UniformValueTypeID<OpenGl_Vec2i>::ID, new OpenGl_VariableSetter<OpenGl_Vec2i>())
79     (Graphic3d_UniformValueTypeID<OpenGl_Vec3i>::ID, new OpenGl_VariableSetter<OpenGl_Vec3i>())
80     (Graphic3d_UniformValueTypeID<OpenGl_Vec4i>::ID, new OpenGl_VariableSetter<OpenGl_Vec4i>());
81 }
82
83 // =======================================================================
84 // function : ~OpenGl_VariableSetterSelector
85 // purpose  : Releases memory resources of variable setter selector
86 // =======================================================================
87 OpenGl_VariableSetterSelector::~OpenGl_VariableSetterSelector()
88 {
89   for (OpenGl_SetterList::Iterator anIt (mySetterList); anIt.More(); anIt.Next())
90   {
91     delete anIt.Value();
92   }
93
94   mySetterList.Clear();
95 }
96
97 // =======================================================================
98 // function : Set
99 // purpose  : Sets generic variable to specified shader program
100 // =======================================================================
101 void OpenGl_VariableSetterSelector::Set (const Handle(OpenGl_Context)&           theCtx,
102                                          const Handle(Graphic3d_ShaderVariable)& theVariable,
103                                          OpenGl_ShaderProgram*                   theProgram) const
104 {
105   Standard_ASSERT_RETURN (mySetterList.IsBound (theVariable->Value()->TypeID()),
106     "The type of user-defined uniform variable is not supported...", );
107
108   mySetterList.Find (theVariable->Value()->TypeID())->Set (theCtx, theVariable, theProgram);
109 }
110
111 // =======================================================================
112 // function : OpenGl_ShaderProgram
113 // purpose  : Creates uninitialized shader program
114 // =======================================================================
115 OpenGl_ShaderProgram::OpenGl_ShaderProgram (const Handle(Graphic3d_ShaderProgram)& theProxy)
116 : myProgramID (NO_PROGRAM),
117   myProxy     (theProxy),
118   myShareCount(1)
119 {
120   memset (myCurrentState, 0, sizeof (myCurrentState));
121   for (GLint aVar = 0; aVar < OpenGl_OCCT_NUMBER_OF_STATE_VARIABLES; ++aVar)
122   {
123     myStateLocations[aVar] = INVALID_LOCATION;
124   }
125 }
126
127 // =======================================================================
128 // function : Initialize
129 // purpose  : Initializes program object with the list of shader objects
130 // =======================================================================
131 Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)&     theCtx,
132                                                    const Graphic3d_ShaderObjectList& theShaders)
133 {
134   if (theCtx.IsNull() || !Create (theCtx))
135   {
136     return Standard_False;
137   }
138
139   OSD_File aDeclFile     (Graphic3d_ShaderProgram::ShadersFolder() + "/Declarations.glsl");
140   OSD_File aDeclImplFile (Graphic3d_ShaderProgram::ShadersFolder() + "/DeclarationsImpl.glsl");
141   if (!aDeclFile.Exists()
142    || !aDeclImplFile.Exists())
143   {
144     const TCollection_ExtendedString aMsg = "Error! Failed to load OCCT shader declarations file";
145     theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
146                          GL_DEBUG_TYPE_ERROR_ARB,
147                          0,
148                          GL_DEBUG_SEVERITY_HIGH_ARB,
149                          aMsg);
150     return Standard_False;
151   }
152
153   TCollection_AsciiString aDeclarations;
154   aDeclFile.Open (OSD_ReadOnly, OSD_Protection());
155   aDeclFile.Read (aDeclarations, (int)aDeclFile.Size());
156   aDeclFile.Close();
157
158   TCollection_AsciiString aDeclImpl;
159   aDeclImplFile.Open (OSD_ReadOnly, OSD_Protection());
160   aDeclImplFile.Read (aDeclImpl, (int)aDeclImplFile.Size());
161   aDeclImplFile.Close();
162   aDeclarations += aDeclImpl;
163
164   for (Graphic3d_ShaderObjectList::Iterator anIter (theShaders);
165        anIter.More(); anIter.Next())
166   {
167     if (!anIter.Value()->IsDone())
168     {
169       const TCollection_ExtendedString aMsg = "Error! Failed to get shader source";
170       theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
171                            GL_DEBUG_TYPE_ERROR_ARB,
172                            0,
173                            GL_DEBUG_SEVERITY_HIGH_ARB,
174                            aMsg);
175       return Standard_False;
176     }
177
178     Handle(OpenGl_ShaderObject) aShader;
179
180     // Note: Add support of other shader types here
181     switch (anIter.Value()->Type())
182     {
183       case Graphic3d_TOS_VERTEX:
184         aShader = new OpenGl_ShaderObject (GL_VERTEX_SHADER);
185         break;
186       case Graphic3d_TOS_FRAGMENT:
187         aShader = new OpenGl_ShaderObject (GL_FRAGMENT_SHADER);
188         break;
189     }
190
191     // Is unsupported shader type?
192     if (aShader.IsNull())
193     {
194       TCollection_ExtendedString aMsg = "Error! Unsupported shader type";
195       theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
196                            GL_DEBUG_TYPE_ERROR_ARB,
197                            0,
198                            GL_DEBUG_SEVERITY_HIGH_ARB,
199                            aMsg);
200       return Standard_False;
201     }
202
203     if (!aShader->Create (theCtx))
204     {
205       aShader->Release (theCtx.operator->());
206       return Standard_False;
207     }
208
209     TCollection_AsciiString aSource = aDeclarations + anIter.Value()->Source();
210     if (anIter.Value()->Type() == Graphic3d_TOS_VERTEX)
211     {
212       aSource = TCollection_AsciiString ("#define VERTEX_SHADER\n") + aSource;
213     }
214
215     if (!aShader->LoadSource (theCtx, aSource))
216     {
217       const TCollection_ExtendedString aMsg = "Error! Failed to set shader source";
218       theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
219                            GL_DEBUG_TYPE_ERROR_ARB,
220                            0,
221                            GL_DEBUG_SEVERITY_HIGH_ARB,
222                            aMsg);
223       aShader->Release (theCtx.operator->());
224       return Standard_False;
225     }
226
227     if (!aShader->Compile (theCtx))
228     {
229       TCollection_AsciiString aLog;
230       aShader->FetchInfoLog (theCtx, aLog);
231       if (aLog.IsEmpty())
232       {
233         aLog = "Compilation log is empty.";
234       }
235       theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
236                            GL_DEBUG_TYPE_ERROR_ARB,
237                            0,
238                            GL_DEBUG_SEVERITY_HIGH_ARB,
239                            TCollection_ExtendedString ("Failed to compile shader object. Compilation log:\n") + aLog);
240       aShader->Release (theCtx.operator->());
241       return Standard_False;
242     }
243     else if (theCtx->caps->glslWarnings)
244     {
245       TCollection_AsciiString aLog;
246       aShader->FetchInfoLog (theCtx, aLog);
247       if (!aLog.IsEmpty()
248        && !aLog.IsEqual ("No errors.\n"))
249       {
250         theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
251                              GL_DEBUG_TYPE_PORTABILITY_ARB,
252                              0,
253                              GL_DEBUG_SEVERITY_LOW_ARB,
254                              TCollection_ExtendedString ("Shader compilation log:\n") + aLog);
255       }
256     }
257
258     if (!AttachShader (theCtx, aShader))
259     {
260       aShader->Release (theCtx.operator->());
261       return Standard_False;
262     }
263   }
264
265   if (!Link (theCtx))
266   {
267     TCollection_AsciiString aLog;
268     FetchInfoLog (theCtx, aLog);
269     if (aLog.IsEmpty())
270     {
271       aLog = "Linker log is empty.";
272     }
273     theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
274                          GL_DEBUG_TYPE_ERROR_ARB,
275                          0,
276                          GL_DEBUG_SEVERITY_HIGH_ARB,
277                          TCollection_ExtendedString ("Failed to link program object! Linker log:\n") + aLog);
278     return Standard_False;
279   }
280   else if (theCtx->caps->glslWarnings)
281   {
282     TCollection_AsciiString aLog;
283     FetchInfoLog (theCtx, aLog);
284     if (!aLog.IsEmpty()
285      && !aLog.IsEqual ("No errors.\n"))
286     {
287       theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
288                            GL_DEBUG_TYPE_PORTABILITY_ARB,
289                            0,
290                            GL_DEBUG_SEVERITY_LOW_ARB,
291                            TCollection_ExtendedString ("GLSL linker log:\n") + aLog);
292     }
293   }
294
295   return Standard_True;
296 }
297
298 // =======================================================================
299 // function : ~OpenGl_ShaderProgram
300 // purpose  : Releases resources of shader program
301 // =======================================================================
302 OpenGl_ShaderProgram::~OpenGl_ShaderProgram()
303 {
304   Release (NULL);
305 }
306
307 // =======================================================================
308 // function : AttachShader
309 // purpose  : Attaches shader object to the program object
310 // =======================================================================
311 Standard_Boolean OpenGl_ShaderProgram::AttachShader (const Handle(OpenGl_Context)&      theCtx,
312                                                      const Handle(OpenGl_ShaderObject)& theShader)
313 {
314   if (myProgramID == NO_PROGRAM || theShader.IsNull())
315   {
316     return Standard_False;
317   }
318
319   for (OpenGl_ShaderList::Iterator anIter (myShaderObjects); anIter.More(); anIter.Next())
320   {
321     if (theShader == anIter.Value())
322     {
323       return Standard_False;
324     }
325   }
326
327   myShaderObjects.Append (theShader);
328   theCtx->core20->glAttachShader (myProgramID, theShader->myShaderID);
329   return Standard_True;
330 }
331
332 // =======================================================================
333 // function : DetachShader
334 // purpose  : Detaches shader object to the program object
335 // =======================================================================
336 Standard_Boolean OpenGl_ShaderProgram::DetachShader (const Handle(OpenGl_Context)&      theCtx,
337                                                      const Handle(OpenGl_ShaderObject)& theShader)
338 {
339   if (myProgramID == NO_PROGRAM
340    || theShader.IsNull())
341   {
342     return Standard_False;
343   }
344
345   OpenGl_ShaderList::Iterator anIter (myShaderObjects);
346   while (anIter.More())
347   {
348     if (theShader == anIter.Value())
349     {
350       myShaderObjects.Remove (anIter);
351       break;
352     }
353
354     anIter.Next();
355   }
356
357   if (!anIter.More())
358   {
359     return Standard_False;
360   }
361
362   theCtx->core20->glDetachShader (myProgramID, theShader->myShaderID);
363   return Standard_True;
364 }
365
366 // =======================================================================
367 // function : Link
368 // purpose  : Links the program object
369 // =======================================================================
370 Standard_Boolean OpenGl_ShaderProgram::Link (const Handle(OpenGl_Context)& theCtx)
371 {
372   if (myProgramID == NO_PROGRAM)
373   {
374     return Standard_False;
375   }
376
377   GLint aStatus = GL_FALSE;
378   theCtx->core20->glLinkProgram (myProgramID);
379   theCtx->core20->glGetProgramiv (myProgramID, GL_LINK_STATUS, &aStatus);
380   if (aStatus == GL_FALSE)
381   {
382     return Standard_False;
383   }
384
385   for (GLint aVar = 0; aVar < OpenGl_OCCT_NUMBER_OF_STATE_VARIABLES; ++aVar)
386   {
387     myStateLocations[aVar] = GetUniformLocation (theCtx, PredefinedKeywords[aVar]);
388   }
389   return Standard_True;
390 }
391
392 // =======================================================================
393 // function : FetchInfoLog
394 // purpose  : Fetches information log of the last link operation
395 // =======================================================================
396 Standard_Boolean OpenGl_ShaderProgram::FetchInfoLog (const Handle(OpenGl_Context)& theCtx,
397                                                      TCollection_AsciiString&      theOutput)
398 {
399   if (myProgramID == NO_PROGRAM)
400   {
401     return Standard_False;
402   }
403
404   GLint aLength = 0;
405   theCtx->core20->glGetProgramiv (myProgramID, GL_INFO_LOG_LENGTH, &aLength);
406   if (aLength > 0)
407   {
408     GLchar* aLog = (GLchar*) alloca (aLength);
409     memset (aLog, 0, aLength);
410     theCtx->core20->glGetProgramInfoLog (myProgramID, aLength, NULL, aLog);
411     theOutput = aLog;
412   }
413   return Standard_True;
414 }
415
416 // =======================================================================
417 // function : Bind
418 // purpose  : Sets the program object as part of current rendering state
419 // =======================================================================
420 void OpenGl_ShaderProgram::Bind (const Handle(OpenGl_Context)& theCtx) const
421 {
422   if (myProgramID == NO_PROGRAM)
423   {
424     return;
425   }
426
427   theCtx->core20->glUseProgram (myProgramID);
428   theCtx->ShaderManager()->myIsPP = Standard_True;
429 }
430
431 // =======================================================================
432 // function : ApplyVariables
433 // purpose  : Fetches uniform variables from proxy shader program
434 // =======================================================================
435 Standard_Boolean OpenGl_ShaderProgram::ApplyVariables(const Handle(OpenGl_Context)& theCtx)
436 {
437   if (myProxy.IsNull() || myProxy->Variables().IsEmpty())
438   {
439     return Standard_False;
440   }
441
442   for (Graphic3d_ShaderVariableList::Iterator anIter (myProxy->Variables()); anIter.More(); anIter.Next())
443   {
444     mySetterSelector.Set (theCtx, anIter.Value(), this);
445   }
446
447   myProxy->ClearVariables();
448   return Standard_True;
449 }
450
451 // =======================================================================
452 // function : BindWithVariables
453 // purpose  : Binds the program object and applies variables
454 // =======================================================================
455 Standard_Boolean OpenGl_ShaderProgram::BindWithVariables (const Handle(OpenGl_Context)& theCtx)
456 {
457   Bind (theCtx);
458   return ApplyVariables (theCtx);
459 }
460
461 // =======================================================================
462 // function : Unbind
463 // purpose  : Reverts to fixed-function graphics pipeline (FFP)
464 // =======================================================================
465 void OpenGl_ShaderProgram::Unbind (const Handle(OpenGl_Context)& theCtx)
466 {
467   if (theCtx->ShaderManager()->myIsPP)
468   {
469     theCtx->core20->glUseProgram (NO_PROGRAM);
470     theCtx->ShaderManager()->myIsPP = Standard_False;
471   }
472 }
473
474 // =======================================================================
475 // function : ActiveState
476 // purpose  : Returns index of last modification for specified state type
477 // =======================================================================
478 Standard_Size OpenGl_ShaderProgram::ActiveState (const OpenGl_UniformStateType theType) const
479 {
480   if (theType < MaxStateTypes)
481   {
482     return myCurrentState[theType];
483   }
484   return 0;
485 }
486
487 // =======================================================================
488 // function : UpdateState
489 // purpose  : Updates index of last modification for specified state type
490 // =======================================================================
491 void OpenGl_ShaderProgram::UpdateState (const OpenGl_UniformStateType theType,
492                                         const Standard_Size           theIndex)
493 {
494   if (theType < MaxStateTypes)
495   {
496     myCurrentState[theType] = theIndex;
497   }
498 }
499
500 // =======================================================================
501 // function : GetUniformLocation
502 // purpose  : Returns location (index) of the specific uniform variable
503 // =======================================================================
504 GLint OpenGl_ShaderProgram::GetUniformLocation (const Handle(OpenGl_Context)& theCtx,
505                                                 const GLchar*                 theName) const
506 {
507   return myProgramID != NO_PROGRAM
508        ? theCtx->core20->glGetUniformLocation (myProgramID, theName)
509        : INVALID_LOCATION;
510 }
511
512 // =======================================================================
513 // function : GetAttributeLocation
514 // purpose  : Returns location (index) of the generic vertex attribute
515 // =======================================================================
516 GLint OpenGl_ShaderProgram::GetAttributeLocation (const Handle(OpenGl_Context)& theCtx,
517                                                   const GLchar*                 theName) const
518 {
519   return myProgramID != NO_PROGRAM
520        ? theCtx->core20->glGetAttribLocation (myProgramID, theName)
521        : INVALID_LOCATION;
522 }
523
524 // =======================================================================
525 // function : GetStateLocation
526 // purpose  : Returns location of the OCCT state uniform variable
527 // =======================================================================
528 GLint OpenGl_ShaderProgram::GetStateLocation (const GLuint theVariable) const
529 {
530   if (theVariable < OpenGl_OCCT_NUMBER_OF_STATE_VARIABLES)
531   {
532     return myStateLocations[theVariable];
533   }
534   return INVALID_LOCATION;
535 }
536
537 // =======================================================================
538 // function : GetUniform
539 // purpose  : Returns the value of the integer uniform variable
540 // =======================================================================
541 Standard_Boolean OpenGl_ShaderProgram::GetUniform (const Handle(OpenGl_Context)& theCtx,
542                                                    const GLchar*                 theName,
543                                                    OpenGl_Vec4i&                 theValue) const
544 {
545   return GetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
546 }
547
548 // =======================================================================
549 // function : GetUniform
550 // purpose  : Returns the value of the integer uniform variable
551 // =======================================================================
552 Standard_Boolean OpenGl_ShaderProgram::GetUniform (const Handle(OpenGl_Context)& theCtx,
553                                                    GLint                         theLocation,
554                                                    OpenGl_Vec4i&                 theValue) const
555 {
556   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
557   {
558     return Standard_False;
559   }
560
561   theCtx->core20->glGetUniformiv (myProgramID, theLocation, theValue);
562   return Standard_True;
563 }
564
565 // =======================================================================
566 // function : GetUniform
567 // purpose  : Returns the value of the floating-point uniform variable
568 // =======================================================================
569 Standard_Boolean OpenGl_ShaderProgram::GetUniform (const Handle(OpenGl_Context)& theCtx,
570                                                    const GLchar*                 theName,
571                                                    OpenGl_Vec4&                  theValue) const
572 {
573   return GetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
574 }
575
576 // =======================================================================
577 // function : GetUniform
578 // purpose  : Returns the value of the floating-point uniform variable
579 // =======================================================================
580 Standard_Boolean OpenGl_ShaderProgram::GetUniform (const Handle(OpenGl_Context)& theCtx,
581                                                    GLint                         theLocation,
582                                                    OpenGl_Vec4&                  theValue) const
583 {
584   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
585   {
586     return Standard_False;
587   }
588
589   theCtx->core20->glGetUniformfv (myProgramID, theLocation, theValue);
590   return Standard_True;
591 }
592
593 // =======================================================================
594 // function : GetAttribute
595 // purpose  : Returns the integer vertex attribute
596 // =======================================================================
597 Standard_Boolean OpenGl_ShaderProgram::GetAttribute (const Handle(OpenGl_Context)& theCtx,
598                                                      const GLchar*                 theName,
599                                                      OpenGl_Vec4i&                 theValue) const
600 {
601   return GetAttribute (theCtx, GetAttributeLocation (theCtx, theName), theValue);
602 }
603
604 // =======================================================================
605 // function : GetAttribute
606 // purpose  : Returns the integer vertex attribute
607 // =======================================================================
608 Standard_Boolean OpenGl_ShaderProgram::GetAttribute (const Handle(OpenGl_Context)& theCtx,
609                                                      GLint                         theIndex,
610                                                      OpenGl_Vec4i&                 theValue) const
611 {
612   if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION)
613   {
614     return Standard_False;
615   }
616
617   theCtx->core20->glGetVertexAttribiv (theIndex, GL_CURRENT_VERTEX_ATTRIB, theValue);
618   return Standard_True;
619 }
620
621 // =======================================================================
622 // function : GetAttribute
623 // purpose  : Returns the floating-point vertex attribute
624 // =======================================================================
625 Standard_Boolean OpenGl_ShaderProgram::GetAttribute (const Handle(OpenGl_Context)& theCtx,
626                                                      const GLchar*                 theName,
627                                                      OpenGl_Vec4&                  theValue) const
628 {
629   return GetAttribute (theCtx, GetAttributeLocation (theCtx, theName), theValue);
630 }
631
632 // =======================================================================
633 // function : GetAttribute
634 // purpose  : Returns the floating-point vertex attribute
635 // =======================================================================
636 Standard_Boolean OpenGl_ShaderProgram::GetAttribute (const Handle(OpenGl_Context)& theCtx,
637                                                      GLint                         theIndex,
638                                                      OpenGl_Vec4&                  theValue) const
639 {
640   if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION)
641   {
642     return Standard_False;
643   }
644
645   theCtx->core20->glGetVertexAttribfv (theIndex, GL_CURRENT_VERTEX_ATTRIB, theValue);
646   return Standard_True;
647 }
648
649 // =======================================================================
650 // function : SetAttributeName
651 // purpose  :
652 // =======================================================================
653 Standard_Boolean OpenGl_ShaderProgram::SetAttributeName (const Handle(OpenGl_Context)& theCtx,
654                                                          GLint                         theIndex,
655                                                          const GLchar*                 theName)
656 {
657   theCtx->core20fwd->glBindAttribLocation (myProgramID, theIndex, theName);
658   return Standard_True;
659 }
660   
661 // =======================================================================
662 // function : SetAttribute
663 // purpose  :
664 // =======================================================================
665 Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
666                                                      const GLchar*                 theName,
667                                                      GLfloat                       theValue)
668 {
669   return SetAttribute (theCtx, GetAttributeLocation (theCtx, theName), theValue);
670 }
671
672 // =======================================================================
673 // function : SetAttribute
674 // purpose  :
675 // =======================================================================
676 Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
677                                                      GLint                         theIndex,
678                                                      GLfloat                       theValue)
679 {
680   if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION)
681   {
682     return Standard_False;
683   }
684
685   theCtx->core20fwd->glVertexAttrib1f (theIndex, theValue);
686   return Standard_True;
687 }
688
689 // =======================================================================
690 // function : SetAttribute
691 // purpose  :
692 // =======================================================================
693 Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
694                                                      const GLchar*                 theName,
695                                                      const OpenGl_Vec2&            theValue)
696 {
697   return SetAttribute (theCtx, GetAttributeLocation (theCtx, theName), theValue);
698 }
699
700 // =======================================================================
701 // function : SetAttribute
702 // purpose  :
703 // =======================================================================
704 Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
705                                                      GLint                         theIndex,
706                                                      const OpenGl_Vec2&            theValue)
707 {
708   if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION)
709   {
710     return Standard_False;
711   }
712
713   theCtx->core20fwd->glVertexAttrib2fv (theIndex, theValue);
714   return Standard_True;
715 }
716
717 // =======================================================================
718 // function : SetAttribute
719 // purpose  :
720 // =======================================================================
721 Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
722                                                      const GLchar*                 theName,
723                                                      const OpenGl_Vec3&            theValue)
724 {
725   return SetAttribute (theCtx, GetAttributeLocation (theCtx, theName), theValue);
726 }
727
728 // =======================================================================
729 // function : SetAttribute
730 // purpose  :
731 // =======================================================================
732 Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
733                                                      GLint                         theIndex,
734                                                      const OpenGl_Vec3&            theValue)
735 {
736   if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION)
737   {
738     return Standard_False;
739   }
740
741   theCtx->core20fwd->glVertexAttrib3fv (theIndex, theValue);
742   return Standard_True;
743 }
744
745 // =======================================================================
746 // function : SetAttribute
747 // purpose  :
748 // =======================================================================
749 Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
750                                                      const GLchar*                 theName,
751                                                      const OpenGl_Vec4&            theValue)
752 {
753   return SetAttribute (theCtx, GetAttributeLocation (theCtx, theName), theValue);
754 }
755
756 // =======================================================================
757 // function : SetAttribute
758 // purpose  :
759 // =======================================================================
760 Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
761                                                      GLint                         theIndex,
762                                                      const OpenGl_Vec4&            theValue)
763 {
764   if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION)
765   {
766     return Standard_False;
767   }
768
769   theCtx->core20fwd->glVertexAttrib4fv (theIndex, theValue);
770   return Standard_True;
771 }
772
773 // =======================================================================
774 // function : SetUniform
775 // purpose  : Specifies the value of the integer uniform variable
776 // =======================================================================
777 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
778                                                    const GLchar*                 theName,
779                                                    GLint                         theValue)
780 {
781   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
782 }
783
784 // =======================================================================
785 // function : SetUniform
786 // purpose  : Specifies the value of the integer uniform variable
787 // =======================================================================
788 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
789                                                    GLint                         theLocation,
790                                                    GLint                         theValue)
791 {
792   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
793   {
794     return Standard_False;
795   }
796
797   theCtx->core20->glUniform1i (theLocation, theValue);
798   return Standard_True;
799 }
800
801 // =======================================================================
802 // function : SetUniform
803 // purpose  : Specifies the value of the floating-point uniform variable
804 // =======================================================================
805 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
806                                                    const GLchar*                 theName,
807                                                    GLfloat                       theValue)
808 {
809   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
810 }
811
812 // =======================================================================
813 // function : SetUniform
814 // purpose  : Specifies the value of the floating-point uniform variable
815 // =======================================================================
816 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
817                                                    GLint                         theLocation,
818                                                    GLfloat                       theValue)
819 {
820   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
821   {
822     return Standard_False;
823   }
824
825   theCtx->core20->glUniform1f (theLocation, theValue);
826   return Standard_True;
827 }
828
829 // =======================================================================
830 // function : SetUniform
831 // purpose  : Specifies the value of the integer uniform 2D vector
832 // =======================================================================
833 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
834                                                    const GLchar*                 theName,
835                                                    const OpenGl_Vec2i&           theValue)
836 {
837   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
838 }
839
840 // =======================================================================
841 // function : SetUniform
842 // purpose  : Specifies the value of the integer uniform 2D vector
843 // =======================================================================
844 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
845                                                    GLint                         theLocation,
846                                                    const OpenGl_Vec2i&           theValue)
847 {
848   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
849   {
850     return Standard_False;
851   }
852
853   theCtx->core20->glUniform2iv (theLocation, 1, theValue);
854   return Standard_True;
855 }
856
857 // =======================================================================
858 // function : SetUniform
859 // purpose  : Specifies the value of the integer uniform 3D vector
860 // =======================================================================
861 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
862                                                    const GLchar*                 theName,
863                                                    const OpenGl_Vec3i&           theValue)
864 {
865   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
866 }
867
868 // =======================================================================
869 // function : SetUniform
870 // purpose  : Specifies the value of the integer uniform 3D vector
871 // =======================================================================
872 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
873                                                    GLint                         theLocation,
874                                                    const OpenGl_Vec3i&           theValue)
875 {
876   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
877   {
878     return Standard_False;
879   }
880
881   theCtx->core20->glUniform3iv (theLocation, 1, theValue);
882   return Standard_True;
883 }
884
885 // =======================================================================
886 // function : SetUniform
887 // purpose  : Specifies the value of the integer uniform 4D vector
888 // =======================================================================
889 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
890                                                    const GLchar*                 theName,
891                                                    const OpenGl_Vec4i&           theValue)
892 {
893   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
894 }
895
896 // =======================================================================
897 // function : SetUniform
898 // purpose  : Specifies the value of the integer uniform 4D vector
899 // =======================================================================
900 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
901                                                    GLint                         theLocation,
902                                                    const OpenGl_Vec4i&           theValue)
903 {
904   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
905   {
906     return Standard_False;
907   }
908
909   theCtx->core20->glUniform4iv (theLocation, 1, theValue);
910   return Standard_True;
911 }
912
913 // =======================================================================
914 // function : SetUniform
915 // purpose  : Specifies the value of the floating-point uniform 2D vector
916 // =======================================================================
917 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
918                                                    const GLchar*                 theName,
919                                                    const OpenGl_Vec2&            theValue)
920 {
921   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
922 }
923
924 // =======================================================================
925 // function : SetUniform
926 // purpose  : Specifies the value of the floating-point uniform 2D vector
927 // =======================================================================
928 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
929                                                    GLint                         theLocation,
930                                                    const OpenGl_Vec2&            theValue)
931 {
932   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
933   {
934     return Standard_False;
935   }
936
937   theCtx->core20->glUniform2fv (theLocation, 1, theValue);
938   return Standard_True;
939 }
940
941 // =======================================================================
942 // function : SetUniform
943 // purpose  : Specifies the value of the floating-point uniform 3D vector
944 // =======================================================================
945 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
946                                                    const GLchar*                 theName,
947                                                    const OpenGl_Vec3&            theValue)
948 {
949   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
950 }
951
952 // =======================================================================
953 // function : SetUniform
954 // purpose  : Specifies the value of the floating-point uniform 3D vector
955 // =======================================================================
956 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
957                                                    GLint                         theLocation,
958                                                    const OpenGl_Vec3&            theValue)
959 {
960   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
961   {
962     return Standard_False;
963   }
964
965   theCtx->core20->glUniform3fv (theLocation, 1, theValue);
966   return Standard_True;
967 }
968
969 // =======================================================================
970 // function : SetUniform
971 // purpose  : Specifies the value of the floating-point uniform 4D vector
972 // =======================================================================
973 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
974                                                    const GLchar*                 theName,
975                                                    const OpenGl_Vec4&            theValue)
976 {
977   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
978 }
979
980 // =======================================================================
981 // function : SetUniform
982 // purpose  : Specifies the value of the floating-point uniform 4D vector
983 // =======================================================================
984 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
985                                                    GLint                         theLocation,
986                                                    const OpenGl_Vec4&            theValue)
987 {
988   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
989   {
990     return Standard_False;
991   }
992
993   theCtx->core20->glUniform4fv (theLocation, 1, theValue);
994   return Standard_True;
995 }
996
997 // =======================================================================
998 // function : SetUniform
999 // purpose  : Specifies the value of the floating-point uniform 4x4 matrix
1000 // =======================================================================
1001 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1002                                                    const GLchar*                 theName,
1003                                                    const OpenGl_Matrix&          theValue,
1004                                                    GLboolean                     theTranspose)
1005 {
1006   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue, theTranspose);
1007 }
1008
1009 // =======================================================================
1010 // function : SetUniform
1011 // purpose  : Specifies the value of the floating-point uniform 4x4 matrix
1012 // =======================================================================
1013 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1014                                                    GLint                         theLocation,
1015                                                    const OpenGl_Matrix&          theValue,
1016                                                    GLboolean                     theTranspose)
1017 {
1018   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1019   {
1020     return Standard_False;
1021   }
1022
1023   theCtx->core20->glUniformMatrix4fv (theLocation, 1, theTranspose, *theValue.mat);
1024   return Standard_True;
1025 }
1026
1027 // =======================================================================
1028 // function : SetUniform
1029 // purpose  : Specifies the value of the floating-point uniform 4x4 matrix
1030 // =======================================================================
1031 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1032                                                    const GLchar*                 theName,
1033                                                    const Tmatrix3&               theValue,
1034                                                    GLboolean                     theTranspose)
1035 {
1036   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue, theTranspose);
1037 }
1038
1039 // =======================================================================
1040 // function : SetUniform
1041 // purpose  : Specifies the value of the floating-point uniform 4x4 matrix
1042 // =======================================================================
1043 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1044                                                    GLint                         theLocation,
1045                                                    const Tmatrix3&               theValue,
1046                                                    GLboolean                     theTranspose)
1047 {
1048   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1049   {
1050     return Standard_False;
1051   }
1052
1053   theCtx->core20->glUniformMatrix4fv (theLocation, 1, theTranspose, *theValue);
1054   return Standard_True;
1055 }
1056
1057 // =======================================================================
1058 // function : SetUniform
1059 // purpose  : Specifies the value of the float uniform array
1060 // =======================================================================
1061 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1062                                                    GLint                         theLocation,
1063                                                    GLuint                        theCount,
1064                                                    const Standard_ShortReal*     theData)
1065 {
1066   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1067   {
1068     return Standard_False;
1069   }
1070
1071   theCtx->core20->glUniform1fv (theLocation, theCount, theData);
1072   return Standard_True;
1073 }
1074
1075 // =======================================================================
1076 // function : SetUniform
1077 // purpose  : Specifies the value of the float2 uniform array
1078 // =======================================================================
1079 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1080                                                    GLint                         theLocation,
1081                                                    GLuint                        theCount,
1082                                                    const OpenGl_Vec2*            theData)
1083 {
1084   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1085   {
1086     return Standard_False;
1087   }
1088
1089   theCtx->core20->glUniform2fv (theLocation, theCount, theData[0].GetData());
1090   return Standard_True;
1091 }
1092
1093 // =======================================================================
1094 // function : SetUniform
1095 // purpose  : Specifies the value of the float3 uniform array
1096 // =======================================================================
1097 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1098                                                    GLint                         theLocation,
1099                                                    GLuint                        theCount,
1100                                                    const OpenGl_Vec3*            theData)
1101 {
1102   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1103   {
1104     return Standard_False;
1105   }
1106
1107   theCtx->core20->glUniform3fv (theLocation, theCount, theData[0].GetData());
1108   return Standard_True;
1109 }
1110
1111 // =======================================================================
1112 // function : SetUniform
1113 // purpose  : Specifies the value of the float4 uniform array
1114 // =======================================================================
1115 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1116                                                    GLint                         theLocation,
1117                                                    GLuint                        theCount,
1118                                                    const OpenGl_Vec4*            theData)
1119 {
1120   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1121   {
1122     return Standard_False;
1123   }
1124
1125   theCtx->core20->glUniform4fv (theLocation, theCount, theData[0].GetData());
1126   return Standard_True;
1127 }
1128
1129 // =======================================================================
1130 // function : SetUniform
1131 // purpose  : Specifies the value of the integer uniform array
1132 // =======================================================================
1133 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1134                                                    GLint                         theLocation,
1135                                                    GLuint                        theCount,
1136                                                    const Standard_Integer*       theData)
1137 {
1138   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1139   {
1140     return Standard_False;
1141   }
1142
1143   theCtx->core20->glUniform1iv (theLocation, theCount, theData);
1144   return Standard_True;
1145 }
1146
1147 // =======================================================================
1148 // function : SetUniform
1149 // purpose  : Specifies the value of the int2 uniform array
1150 // =======================================================================
1151 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1152                                                    GLint                         theLocation,
1153                                                    GLuint                        theCount,
1154                                                    const OpenGl_Vec2i*           theData)
1155 {
1156   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1157   {
1158     return Standard_False;
1159   }
1160
1161   theCtx->core20->glUniform2iv (theLocation, theCount, theData[0].GetData());
1162   return Standard_True;
1163 }
1164
1165 // =======================================================================
1166 // function : SetUniform
1167 // purpose  : Specifies the value of the int3 uniform array
1168 // =======================================================================
1169 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1170                                                    GLint                         theLocation,
1171                                                    GLuint                        theCount,
1172                                                    const OpenGl_Vec3i*           theData)
1173 {
1174   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1175   {
1176     return Standard_False;
1177   }
1178
1179   theCtx->core20->glUniform3iv (theLocation, theCount, theData[0].GetData());
1180   return Standard_True;
1181 }
1182
1183 // =======================================================================
1184 // function : SetUniform
1185 // purpose  : Specifies the value of the int4 uniform array
1186 // =======================================================================
1187 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1188                                                    GLint                         theLocation,
1189                                                    GLuint                        theCount,
1190                                                    const OpenGl_Vec4i*           theData)
1191 {
1192   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1193   {
1194     return Standard_False;
1195   }
1196
1197   theCtx->core20->glUniform4iv (theLocation, theCount, theData[0].GetData());
1198   return Standard_True;
1199 }
1200
1201 // =======================================================================
1202 // function : SetSampler
1203 // purpose  : Specifies the value of the sampler uniform variable
1204 // =======================================================================
1205 Standard_Boolean OpenGl_ShaderProgram::SetSampler (const Handle(OpenGl_Context)& theCtx,
1206                                                    const GLchar*                 theName,
1207                                                    const GLenum                  theTextureUnit)
1208 {
1209   return SetSampler (theCtx, GetUniformLocation (theCtx, theName), theTextureUnit);
1210 }
1211
1212 // =======================================================================
1213 // function : SetSampler
1214 // purpose  : Specifies the value of the sampler uniform variable
1215 // =======================================================================
1216 Standard_Boolean OpenGl_ShaderProgram::SetSampler (const Handle(OpenGl_Context)& theCtx,
1217                                                    GLint                         theLocation,
1218                                                    const GLenum                  theTextureUnit)
1219 {
1220   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1221   {
1222     return Standard_False;
1223   }
1224
1225   theCtx->core20->glUniform1i (theLocation, theTextureUnit);
1226   return Standard_True;
1227 }
1228
1229 // =======================================================================
1230 // function : Create
1231 // purpose  : Creates new empty shader program of specified type
1232 // =======================================================================
1233 Standard_Boolean OpenGl_ShaderProgram::Create (const Handle(OpenGl_Context)& theCtx)
1234 {
1235   if (myProgramID == NO_PROGRAM
1236    && theCtx->core20 != NULL)
1237   {
1238     myProgramID = theCtx->core20->glCreateProgram();
1239   }
1240
1241   return myProgramID != NO_PROGRAM;
1242 }
1243
1244 // =======================================================================
1245 // function : Release
1246 // purpose  : Destroys shader program
1247 // =======================================================================
1248 void OpenGl_ShaderProgram::Release (const OpenGl_Context* theCtx)
1249 {
1250   if (myProgramID == NO_PROGRAM)
1251   {
1252     return;
1253   }
1254
1255   Standard_ASSERT_RETURN (theCtx != NULL,
1256     "OpenGl_ShaderProgram destroyed without GL context! Possible GPU memory leakage...",);
1257
1258   for (OpenGl_ShaderList::Iterator anIter (myShaderObjects); anIter.More(); anIter.Next())
1259   {
1260     if (!anIter.Value().IsNull())
1261     {
1262       anIter.ChangeValue()->Release (theCtx);
1263       anIter.ChangeValue().Nullify();
1264     }
1265   }
1266
1267   if (theCtx->core20 != NULL
1268    && theCtx->IsValid())
1269   {
1270     theCtx->core20->glDeleteProgram (myProgramID);
1271   }
1272
1273   myProgramID = NO_PROGRAM;
1274 }