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