0029076: Visualization - implement element shrinking Shader
[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 #include <OpenGl_GlCore32.hxx>
30
31 #include "../Shaders/Shaders_DeclarationsImpl_glsl.pxx"
32 #include "../Shaders/Shaders_Declarations_glsl.pxx"
33
34 #ifdef _WIN32
35   #include <malloc.h> // for alloca()
36 #endif
37
38 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_ShaderProgram, OpenGl_NamedResource)
39
40 OpenGl_VariableSetterSelector OpenGl_ShaderProgram::mySetterSelector = OpenGl_VariableSetterSelector();
41
42 // Declare OCCT-specific OpenGL/GLSL shader variables
43 Standard_CString OpenGl_ShaderProgram::PredefinedKeywords[] =
44 {
45   "occModelWorldMatrix",                 // OpenGl_OCC_MODEL_WORLD_MATRIX
46   "occWorldViewMatrix",                  // OpenGl_OCC_WORLD_VIEW_MATRIX
47   "occProjectionMatrix",                 // OpenGl_OCC_PROJECTION_MATRIX
48   "occModelWorldMatrixInverse",          // OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE
49   "occWorldViewMatrixInverse",           // OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE
50   "occProjectionMatrixInverse",          // OpenGl_OCC_PROJECTION_MATRIX_INVERSE
51   "occModelWorldMatrixTranspose",        // OpenGl_OCC_MODEL_WORLD_MATRIX_TRANSPOSE
52   "occWorldViewMatrixTranspose",         // OpenGl_OCC_WORLD_VIEW_MATRIX_TRANSPOSE
53   "occProjectionMatrixTranspose",        // OpenGl_OCC_PROJECTION_MATRIX_TRANSPOSE
54   "occModelWorldMatrixInverseTranspose", // OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE_TRANSPOSE
55   "occWorldViewMatrixInverseTranspose",  // OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE_TRANSPOSE
56   "occProjectionMatrixInverseTranspose", // OpenGl_OCC_PROJECTION_MATRIX_INVERSE_TRANSPOSE
57
58   "occClipPlaneEquations", // OpenGl_OCC_CLIP_PLANE_EQUATIONS
59   "occClipPlaneChains",    // OpenGl_OCC_CLIP_PLANE_CHAINS
60   "occClipPlaneCount",     // OpenGl_OCC_CLIP_PLANE_COUNT
61
62   "occLightSourcesCount",  // OpenGl_OCC_LIGHT_SOURCE_COUNT
63   "occLightSourcesTypes",  // OpenGl_OCC_LIGHT_SOURCE_TYPES
64   "occLightSources",       // OpenGl_OCC_LIGHT_SOURCE_PARAMS
65   "occLightAmbient",       // OpenGl_OCC_LIGHT_AMBIENT
66
67   "occTextureEnable",      // OpenGl_OCCT_TEXTURE_ENABLE
68   "occDistinguishingMode", // OpenGl_OCCT_DISTINGUISH_MODE
69   "occFrontMaterial",      // OpenGl_OCCT_FRONT_MATERIAL
70   "occBackMaterial",       // OpenGl_OCCT_BACK_MATERIAL
71   "occAlphaCutoff",        // OpenGl_OCCT_ALPHA_CUTOFF
72   "occColor",              // OpenGl_OCCT_COLOR
73
74   "occOitOutput",          // OpenGl_OCCT_OIT_OUTPUT
75   "occOitDepthFactor",     // OpenGl_OCCT_OIT_DEPTH_FACTOR
76
77   "occTexTrsf2d",          // OpenGl_OCCT_TEXTURE_TRSF2D
78   "occPointSize",          // OpenGl_OCCT_POINT_SIZE
79
80   "occViewport",           // OpenGl_OCCT_VIEWPORT
81   "occLineWidth",          // OpenGl_OCCT_LINE_WIDTH
82   "occLineFeather",        // OpenGl_OCCT_LINE_FEATHER
83   "occWireframeColor",     // OpenGl_OCCT_WIREFRAME_COLOR
84   "occIsQuadMode",         // OpenGl_OCCT_QUAD_MODE_STATE
85 };
86
87 namespace
88 {
89   //! Convert Graphic3d_TypeOfShaderObject enumeration into OpenGL enumeration.
90   static GLenum shaderTypeToGl (Graphic3d_TypeOfShaderObject theType)
91   {
92     switch (theType)
93     {
94       case Graphic3d_TOS_VERTEX:          return GL_VERTEX_SHADER;
95       case Graphic3d_TOS_FRAGMENT:        return GL_FRAGMENT_SHADER;
96       case Graphic3d_TOS_GEOMETRY:        return GL_GEOMETRY_SHADER;
97       case Graphic3d_TOS_TESS_CONTROL:    return GL_TESS_CONTROL_SHADER;
98       case Graphic3d_TOS_TESS_EVALUATION: return GL_TESS_EVALUATION_SHADER;
99       case Graphic3d_TOS_COMPUTE:         return GL_COMPUTE_SHADER;
100     }
101     return 0;
102   }
103 }
104
105 // =======================================================================
106 // function : OpenGl_VariableSetterSelector
107 // purpose  : Creates new variable setter selector
108 // =======================================================================
109 OpenGl_VariableSetterSelector::OpenGl_VariableSetterSelector()
110 {
111   // Note: Add new variable setters here
112   mySetterList = OpenGl_HashMapInitializer::CreateListOf<size_t, OpenGl_SetterInterface*>
113     (Graphic3d_UniformValueTypeID<int>::ID,          new OpenGl_VariableSetter<int>())
114     (Graphic3d_UniformValueTypeID<float>::ID,        new OpenGl_VariableSetter<float>())
115     (Graphic3d_UniformValueTypeID<OpenGl_Vec2>::ID,  new OpenGl_VariableSetter<OpenGl_Vec2>())
116     (Graphic3d_UniformValueTypeID<OpenGl_Vec3>::ID,  new OpenGl_VariableSetter<OpenGl_Vec3>())
117     (Graphic3d_UniformValueTypeID<OpenGl_Vec4>::ID,  new OpenGl_VariableSetter<OpenGl_Vec4>())
118     (Graphic3d_UniformValueTypeID<OpenGl_Vec2i>::ID, new OpenGl_VariableSetter<OpenGl_Vec2i>())
119     (Graphic3d_UniformValueTypeID<OpenGl_Vec3i>::ID, new OpenGl_VariableSetter<OpenGl_Vec3i>())
120     (Graphic3d_UniformValueTypeID<OpenGl_Vec4i>::ID, new OpenGl_VariableSetter<OpenGl_Vec4i>());
121 }
122
123 // =======================================================================
124 // function : ~OpenGl_VariableSetterSelector
125 // purpose  : Releases memory resources of variable setter selector
126 // =======================================================================
127 OpenGl_VariableSetterSelector::~OpenGl_VariableSetterSelector()
128 {
129   for (OpenGl_SetterList::Iterator anIt (mySetterList); anIt.More(); anIt.Next())
130   {
131     delete anIt.Value();
132   }
133
134   mySetterList.Clear();
135 }
136
137 // =======================================================================
138 // function : Set
139 // purpose  : Sets generic variable to specified shader program
140 // =======================================================================
141 void OpenGl_VariableSetterSelector::Set (const Handle(OpenGl_Context)&           theCtx,
142                                          const Handle(Graphic3d_ShaderVariable)& theVariable,
143                                          OpenGl_ShaderProgram*                   theProgram) const
144 {
145   Standard_ASSERT_RETURN (mySetterList.IsBound (theVariable->Value()->TypeID()),
146     "The type of user-defined uniform variable is not supported...", );
147
148   mySetterList.Find (theVariable->Value()->TypeID())->Set (theCtx, theVariable, theProgram);
149 }
150
151 // =======================================================================
152 // function : OpenGl_ShaderProgram
153 // purpose  : Creates uninitialized shader program
154 // =======================================================================
155 OpenGl_ShaderProgram::OpenGl_ShaderProgram (const Handle(Graphic3d_ShaderProgram)& theProxy)
156 : OpenGl_NamedResource (!theProxy.IsNull() ? theProxy->GetId() : ""),
157   myProgramID (NO_PROGRAM),
158   myProxy     (theProxy),
159   myShareCount(1),
160   myNbLightsMax (0),
161   myNbClipPlanesMax (0),
162   myNbFragOutputs (1),
163   myHasAlphaTest (false),
164   myHasWeightOitOutput (false),
165   myHasTessShader (false)
166 {
167   memset (myCurrentState, 0, sizeof (myCurrentState));
168 }
169
170 // =======================================================================
171 // function : Initialize
172 // purpose  : Initializes program object with the list of shader objects
173 // =======================================================================
174 Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)&     theCtx,
175                                                    const Graphic3d_ShaderObjectList& theShaders)
176 {
177   myHasTessShader = false;
178   if (theCtx.IsNull() || !Create (theCtx))
179   {
180     return Standard_False;
181   }
182
183   TCollection_AsciiString aHeaderVer = !myProxy.IsNull() ? myProxy->Header() : TCollection_AsciiString();
184   int aShaderMask = 0;
185   for (Graphic3d_ShaderObjectList::Iterator anIter (theShaders); anIter.More(); anIter.Next())
186   {
187     aShaderMask |= anIter.Value()->Type();
188   }
189   myHasTessShader = (aShaderMask & (Graphic3d_TOS_TESS_CONTROL | Graphic3d_TOS_TESS_EVALUATION)) != 0;
190   myNbFragOutputs = !myProxy.IsNull() ? myProxy->NbFragmentOutputs() : 1;
191   myHasAlphaTest  = !myProxy.IsNull() && myProxy->HasAlphaTest();
192   myHasWeightOitOutput = !myProxy.IsNull() ? myProxy->HasWeightOitOutput() && myNbFragOutputs >= 2 : 1;
193
194   // detect the minimum GLSL version required for defined Shader Objects
195 #if defined(GL_ES_VERSION_2_0)
196   if (myHasTessShader)
197   {
198     if (!theCtx->IsGlGreaterEqual (3, 2))
199     {
200       theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
201                            "Error! Tessellation shader requires OpenGL ES 3.2+");
202       return false;
203     }
204     else if (aHeaderVer.IsEmpty())
205     {
206       aHeaderVer = "#version 320 es";
207     }
208   }
209   else if ((aShaderMask & Graphic3d_TOS_GEOMETRY) != 0)
210   {
211     switch (theCtx->hasGeometryStage)
212     {
213       case OpenGl_FeatureNotAvailable:
214       {
215         theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
216                              "Error! Geometry shader requires OpenGL ES 3.2+ or GL_EXT_geometry_shader");
217         return false;
218       }
219       case OpenGl_FeatureInExtensions:
220       {
221         if (aHeaderVer.IsEmpty())
222         {
223           aHeaderVer = "#version 310 es";
224         }
225         break;
226       }
227       case OpenGl_FeatureInCore:
228       {
229         if (aHeaderVer.IsEmpty())
230         {
231           aHeaderVer = "#version 320 es";
232         }
233         break;
234       }
235     }
236   }
237   else if ((aShaderMask & Graphic3d_TOS_COMPUTE) != 0)
238   {
239     if (!theCtx->IsGlGreaterEqual (3, 1))
240     {
241       theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
242                            "Error! Compute shaders require OpenGL ES 3.1+");
243       return false;
244     }
245     else if (aHeaderVer.IsEmpty())
246     {
247       aHeaderVer = "#version 310 es";
248     }
249   }
250 #else
251   if ((aShaderMask & Graphic3d_TOS_COMPUTE) != 0)
252   {
253     if (!theCtx->IsGlGreaterEqual (4, 3))
254     {
255       theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
256                            "Error! Compute shaders require OpenGL 4.3+");
257       return 0;
258     }
259     else if (aHeaderVer.IsEmpty())
260     {
261       aHeaderVer = "#version 430";
262     }
263   }
264   else if (myHasTessShader)
265   {
266     if (!theCtx->IsGlGreaterEqual (4, 0))
267     {
268       theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
269                            "Error! Tessellation shaders require OpenGL 4.0+");
270       return 0;
271     }
272     else if (aHeaderVer.IsEmpty())
273     {
274       aHeaderVer = "#version 400";
275     }
276   }
277   else if ((aShaderMask & Graphic3d_TOS_GEOMETRY) != 0)
278   {
279     if (!theCtx->IsGlGreaterEqual (3, 2))
280     {
281       theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
282                            "Error! Geometry shaders require OpenGL 3.2+");
283       return 0;
284     }
285     else if (aHeaderVer.IsEmpty())
286     {
287       aHeaderVer = "#version 150";
288     }
289   }
290 #endif
291
292   for (Graphic3d_ShaderObjectList::Iterator anIter (theShaders); anIter.More(); anIter.Next())
293   {
294     if (!anIter.Value()->IsDone())
295     {
296       const TCollection_ExtendedString aMsg = "Error! Failed to get shader source";
297       theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aMsg);
298       return Standard_False;
299     }
300
301     const GLenum aShaderType = shaderTypeToGl (anIter.Value()->Type());
302     if (aShaderType == 0)
303     {
304       return Standard_False;
305     }
306
307     Handle(OpenGl_ShaderObject) aShader = new OpenGl_ShaderObject (aShaderType);
308     if (!aShader->Create (theCtx))
309     {
310       aShader->Release (theCtx.operator->());
311       return Standard_False;
312     }
313
314     TCollection_AsciiString anExtensions = "// Enable extensions used in OCCT GLSL programs\n";
315     if (myNbFragOutputs > 1)
316     {
317       if (theCtx->hasDrawBuffers)
318       {
319         anExtensions += "#define OCC_ENABLE_draw_buffers\n";
320         if (myHasWeightOitOutput)
321         {
322           anExtensions += "#define OCC_WRITE_WEIGHT_OIT_COVERAGE\n";
323         }
324       }
325       else
326       {
327         theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
328                              "Error! Multiple draw buffers required by the program, but aren't supported by OpenGL");
329         return Standard_False;
330       }
331
332       if (theCtx->hasDrawBuffers == OpenGl_FeatureInExtensions)
333       {
334         if (theCtx->arbDrawBuffers)
335         {
336           anExtensions += "#extension GL_ARB_draw_buffers : enable\n";
337         }
338         else if (theCtx->extDrawBuffers)
339         {
340           anExtensions += "#extension GL_EXT_draw_buffers : enable\n";
341         }
342       }
343     }
344     if (myHasAlphaTest)
345     {
346       anExtensions += "#define OCC_ALPHA_TEST\n";
347     }
348
349     if (theCtx->hasSampleVariables == OpenGl_FeatureInExtensions)
350     {
351 #if defined(GL_ES_VERSION_2_0)
352       if (theCtx->oesSampleVariables)
353       {
354         anExtensions += "#extension GL_OES_sample_variables : enable\n";
355       }
356 #else
357       if (theCtx->arbSampleShading)
358       {
359         anExtensions += "#extension GL_ARB_sample_shading : enable\n";
360       }
361 #endif
362     }
363 #if defined(GL_ES_VERSION_2_0)
364     if (theCtx->hasGeometryStage == OpenGl_FeatureInExtensions)
365     {
366       anExtensions += "#extension GL_EXT_geometry_shader : enable\n"
367                       "#extension GL_EXT_shader_io_blocks : enable\n";
368     }
369 #endif
370
371     TCollection_AsciiString aPrecisionHeader;
372     if (anIter.Value()->Type() == Graphic3d_TOS_FRAGMENT)
373     {
374     #if defined(GL_ES_VERSION_2_0)
375       aPrecisionHeader = theCtx->hasHighp
376                        ? "precision highp float;\n"
377                          "precision highp int;\n"
378                        : "precision mediump float;\n"
379                          "precision mediump int;\n";
380     #endif
381     }
382
383     TCollection_AsciiString aHeaderType;
384     switch (anIter.Value()->Type())
385     {
386       case Graphic3d_TOS_COMPUTE:         { aHeaderType = "#define COMPUTE_SHADER\n";         break; }
387       case Graphic3d_TOS_VERTEX:          { aHeaderType = "#define VERTEX_SHADER\n";          break; }
388       case Graphic3d_TOS_TESS_CONTROL:    { aHeaderType = "#define TESS_CONTROL_SHADER\n";    break; }
389       case Graphic3d_TOS_TESS_EVALUATION: { aHeaderType = "#define TESS_EVALUATION_SHADER\n"; break; }
390       case Graphic3d_TOS_GEOMETRY:        { aHeaderType = "#define GEOMETRY_SHADER\n";        break; }
391       case Graphic3d_TOS_FRAGMENT:        { aHeaderType = "#define FRAGMENT_SHADER\n";        break; }
392     }
393
394     TCollection_AsciiString aHeaderConstants;
395     myNbLightsMax     = !myProxy.IsNull() ? myProxy->NbLightsMax() : 0;
396     myNbClipPlanesMax = !myProxy.IsNull() ? myProxy->NbClipPlanesMax() : 0;
397     aHeaderConstants += TCollection_AsciiString("#define THE_MAX_LIGHTS ") + myNbLightsMax + "\n";
398     aHeaderConstants += TCollection_AsciiString("#define THE_MAX_CLIP_PLANES ") + myNbClipPlanesMax + "\n";
399     aHeaderConstants += TCollection_AsciiString("#define THE_NB_FRAG_OUTPUTS ") + myNbFragOutputs + "\n";
400
401     const TCollection_AsciiString aSource = aHeaderVer                     // #version   - header defining GLSL version, should be first
402                                           + (!aHeaderVer.IsEmpty() ? "\n" : "")
403                                           + anExtensions                   // #extension - list of enabled extensions,   should be second
404                                           + aPrecisionHeader               // precision  - default precision qualifiers, should be before any code
405                                           + aHeaderType                    // auxiliary macros defining a shader stage (type)
406                                           + aHeaderConstants
407                                           + Shaders_Declarations_glsl      // common declarations (global constants and Vertex Shader inputs)
408                                           + Shaders_DeclarationsImpl_glsl
409                                           + anIter.Value()->Source();      // the source code itself (defining main() function)
410     if (!aShader->LoadAndCompile (theCtx, aSource))
411     {
412       return Standard_False;
413     }
414
415     if (theCtx->caps->glslDumpLevel)
416     {
417       TCollection_AsciiString aShaderTypeMsg;
418       switch (anIter.Value()->Type())
419       {
420         case Graphic3d_TOS_COMPUTE:         { aShaderTypeMsg = "Compute shader source code:\n";                break; }
421         case Graphic3d_TOS_VERTEX:          { aShaderTypeMsg = "Vertex shader source code:\n";                 break; }
422         case Graphic3d_TOS_TESS_CONTROL:    { aShaderTypeMsg = "Tesselation control shader source code:\n";    break; }
423         case Graphic3d_TOS_TESS_EVALUATION: { aShaderTypeMsg = "Tesselation evaluation shader source code:\n"; break; }
424         case Graphic3d_TOS_GEOMETRY:        { aShaderTypeMsg = "Geometry shader source code:\n";               break; }
425         case Graphic3d_TOS_FRAGMENT:        { aShaderTypeMsg = "Fragment shader source code:\n";               break; }
426       }
427       TCollection_AsciiString anOutputSource = aSource;
428       if (theCtx->caps->glslDumpLevel == OpenGl_ShaderProgramDumpLevel_Short)
429       {
430         anOutputSource = aHeaderVer
431                        + (!aHeaderVer.IsEmpty() ? "\n" : "")
432                        + anExtensions
433                        + aPrecisionHeader
434                        + aHeaderType
435                        + aHeaderConstants
436                        + anIter.Value()->Source();
437       }
438       theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_OTHER, 0, GL_DEBUG_SEVERITY_MEDIUM,
439                            TCollection_ExtendedString (aShaderTypeMsg + anOutputSource));
440     }
441
442     if (!AttachShader (theCtx, aShader))
443     {
444       aShader->Release (theCtx.operator->());
445       return Standard_False;
446     }
447   }
448
449   // bind locations for pre-defined Vertex Attributes
450   SetAttributeName (theCtx, Graphic3d_TOA_POS,   "occVertex");
451   SetAttributeName (theCtx, Graphic3d_TOA_NORM,  "occNormal");
452   SetAttributeName (theCtx, Graphic3d_TOA_UV,    "occTexCoord");
453   SetAttributeName (theCtx, Graphic3d_TOA_COLOR, "occVertColor");
454
455   // bind custom Vertex Attributes
456   if (!myProxy.IsNull())
457   {
458     for (Graphic3d_ShaderAttributeList::Iterator anAttribIter (myProxy->VertexAttributes());
459          anAttribIter.More(); anAttribIter.Next())
460     {
461       SetAttributeName (theCtx, anAttribIter.Value()->Location(), anAttribIter.Value()->Name().ToCString());
462     }
463   }
464
465   if (!Link (theCtx))
466   {
467     return Standard_False;
468   }
469
470   // set uniform defaults
471   const Handle(OpenGl_ShaderProgram)& anOldProgram = theCtx->ActiveProgram();
472   theCtx->core20fwd->glUseProgram (myProgramID);
473   if (const OpenGl_ShaderUniformLocation aLocTexEnable = GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE))
474   {
475     SetUniform (theCtx, aLocTexEnable, 0); // Off
476   }
477   if (const OpenGl_ShaderUniformLocation aLocSampler = GetUniformLocation (theCtx, "occActiveSampler"))
478   {
479     SetUniform (theCtx, aLocSampler, GLint(Graphic3d_TextureUnit_0));
480   }
481
482   const TCollection_AsciiString aSamplerNamePrefix ("occSampler");
483   const Standard_Integer aNbUnitsMax = Max (theCtx->MaxCombinedTextureUnits(), Graphic3d_TextureUnit_NB);
484   for (GLint aUnitIter = 0; aUnitIter < aNbUnitsMax; ++aUnitIter)
485   {
486     const TCollection_AsciiString aName = aSamplerNamePrefix + aUnitIter;
487     if (const OpenGl_ShaderUniformLocation aLocSampler = GetUniformLocation (theCtx, aName.ToCString()))
488     {
489       SetUniform (theCtx, aLocSampler, aUnitIter);
490     }
491   }
492
493   theCtx->core20fwd->glUseProgram (!anOldProgram.IsNull() ? anOldProgram->ProgramId() : OpenGl_ShaderProgram::NO_PROGRAM);
494   return Standard_True;
495 }
496
497 // =======================================================================
498 // function : ~OpenGl_ShaderProgram
499 // purpose  : Releases resources of shader program
500 // =======================================================================
501 OpenGl_ShaderProgram::~OpenGl_ShaderProgram()
502 {
503   Release (NULL);
504 }
505
506 // =======================================================================
507 // function : AttachShader
508 // purpose  : Attaches shader object to the program object
509 // =======================================================================
510 Standard_Boolean OpenGl_ShaderProgram::AttachShader (const Handle(OpenGl_Context)&      theCtx,
511                                                      const Handle(OpenGl_ShaderObject)& theShader)
512 {
513   if (myProgramID == NO_PROGRAM || theShader.IsNull())
514   {
515     return Standard_False;
516   }
517
518   for (OpenGl_ShaderList::Iterator anIter (myShaderObjects); anIter.More(); anIter.Next())
519   {
520     if (theShader == anIter.Value())
521     {
522       return Standard_False;
523     }
524   }
525
526   myShaderObjects.Append (theShader);
527   theCtx->core20fwd->glAttachShader (myProgramID, theShader->myShaderID);
528   return Standard_True;
529 }
530
531 // =======================================================================
532 // function : DetachShader
533 // purpose  : Detaches shader object to the program object
534 // =======================================================================
535 Standard_Boolean OpenGl_ShaderProgram::DetachShader (const Handle(OpenGl_Context)&      theCtx,
536                                                      const Handle(OpenGl_ShaderObject)& theShader)
537 {
538   if (myProgramID == NO_PROGRAM
539    || theShader.IsNull())
540   {
541     return Standard_False;
542   }
543
544   OpenGl_ShaderList::Iterator anIter (myShaderObjects);
545   while (anIter.More())
546   {
547     if (theShader == anIter.Value())
548     {
549       myShaderObjects.Remove (anIter);
550       break;
551     }
552
553     anIter.Next();
554   }
555
556   if (!anIter.More())
557   {
558     return Standard_False;
559   }
560
561   theCtx->core20fwd->glDetachShader (myProgramID, theShader->myShaderID);
562   return Standard_True;
563 }
564
565 // =======================================================================
566 // function : Link
567 // purpose  : Links the program object
568 // =======================================================================
569 Standard_Boolean OpenGl_ShaderProgram::link (const Handle(OpenGl_Context)& theCtx)
570 {
571   if (myProgramID == NO_PROGRAM)
572   {
573     return Standard_False;
574   }
575
576   GLint aStatus = GL_FALSE;
577   theCtx->core20fwd->glLinkProgram (myProgramID);
578   theCtx->core20fwd->glGetProgramiv (myProgramID, GL_LINK_STATUS, &aStatus);
579   if (aStatus == GL_FALSE)
580   {
581     return Standard_False;
582   }
583
584   for (GLint aVar = 0; aVar < OpenGl_OCCT_NUMBER_OF_STATE_VARIABLES; ++aVar)
585   {
586     myStateLocations[aVar] = GetUniformLocation (theCtx, PredefinedKeywords[aVar]);
587   }
588   return Standard_True;
589 }
590
591 // =======================================================================
592 // function : Link
593 // purpose  :
594 // =======================================================================
595 Standard_Boolean OpenGl_ShaderProgram::Link (const Handle(OpenGl_Context)& theCtx,
596                                              bool theIsVerbose)
597 {
598   if (!theIsVerbose)
599   {
600     return link (theCtx);
601   }
602
603   if (!link (theCtx))
604   {
605     TCollection_AsciiString aLog;
606     FetchInfoLog (theCtx, aLog);
607     if (aLog.IsEmpty())
608     {
609       aLog = "Linker log is empty.";
610     }
611     theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
612                          TCollection_AsciiString ("Failed to link program object! Linker log:\n") + aLog);
613     return false;
614   }
615   else if (theCtx->caps->glslWarnings)
616   {
617     TCollection_AsciiString aLog;
618     FetchInfoLog (theCtx, aLog);
619     if (!aLog.IsEmpty()
620      && !aLog.IsEqual ("No errors.\n"))
621     {
622       theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_LOW,
623                            TCollection_AsciiString ("GLSL linker log:\n") + aLog);
624     }
625   }
626   return true;
627 }
628
629 // =======================================================================
630 // function : FetchInfoLog
631 // purpose  : Fetches information log of the last link operation
632 // =======================================================================
633 Standard_Boolean OpenGl_ShaderProgram::FetchInfoLog (const Handle(OpenGl_Context)& theCtx,
634                                                      TCollection_AsciiString&      theOutput)
635 {
636   if (myProgramID == NO_PROGRAM)
637   {
638     return Standard_False;
639   }
640
641   GLint aLength = 0;
642   theCtx->core20fwd->glGetProgramiv (myProgramID, GL_INFO_LOG_LENGTH, &aLength);
643   if (aLength > 0)
644   {
645     GLchar* aLog = (GLchar*) alloca (aLength);
646     memset (aLog, 0, aLength);
647     theCtx->core20fwd->glGetProgramInfoLog (myProgramID, aLength, NULL, aLog);
648     theOutput = aLog;
649   }
650   return Standard_True;
651 }
652
653 // =======================================================================
654 // function : ApplyVariables
655 // purpose  : Fetches uniform variables from proxy shader program
656 // =======================================================================
657 Standard_Boolean OpenGl_ShaderProgram::ApplyVariables(const Handle(OpenGl_Context)& theCtx)
658 {
659   if (myProxy.IsNull() || myProxy->Variables().IsEmpty())
660   {
661     return Standard_False;
662   }
663
664   for (Graphic3d_ShaderVariableList::Iterator anIter (myProxy->Variables()); anIter.More(); anIter.Next())
665   {
666     mySetterSelector.Set (theCtx, anIter.Value(), this);
667   }
668
669   myProxy->ClearVariables();
670   return Standard_True;
671 }
672
673 // =======================================================================
674 // function : GetUniformLocation
675 // purpose  : Returns location (index) of the specific uniform variable
676 // =======================================================================
677 OpenGl_ShaderUniformLocation OpenGl_ShaderProgram::GetUniformLocation (const Handle(OpenGl_Context)& theCtx,
678                                                                        const GLchar*                 theName) const
679 {
680   return OpenGl_ShaderUniformLocation (myProgramID != NO_PROGRAM
681                                      ? theCtx->core20fwd->glGetUniformLocation (myProgramID, theName)
682                                      : INVALID_LOCATION);
683 }
684
685 // =======================================================================
686 // function : GetAttributeLocation
687 // purpose  : Returns location (index) of the generic vertex attribute
688 // =======================================================================
689 GLint OpenGl_ShaderProgram::GetAttributeLocation (const Handle(OpenGl_Context)& theCtx,
690                                                   const GLchar*                 theName) const
691 {
692   return myProgramID != NO_PROGRAM
693        ? theCtx->core20fwd->glGetAttribLocation (myProgramID, theName)
694        : INVALID_LOCATION;
695 }
696
697 // =======================================================================
698 // function : GetUniform
699 // purpose  : Returns the value of the integer uniform variable
700 // =======================================================================
701 Standard_Boolean OpenGl_ShaderProgram::GetUniform (const Handle(OpenGl_Context)& theCtx,
702                                                    const GLchar*                 theName,
703                                                    OpenGl_Vec4i&                 theValue) const
704 {
705   return GetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
706 }
707
708 // =======================================================================
709 // function : GetUniform
710 // purpose  : Returns the value of the integer uniform variable
711 // =======================================================================
712 Standard_Boolean OpenGl_ShaderProgram::GetUniform (const Handle(OpenGl_Context)& theCtx,
713                                                    GLint                         theLocation,
714                                                    OpenGl_Vec4i&                 theValue) const
715 {
716   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
717   {
718     return Standard_False;
719   }
720
721   theCtx->core20fwd->glGetUniformiv (myProgramID, theLocation, theValue);
722   return Standard_True;
723 }
724
725 // =======================================================================
726 // function : GetUniform
727 // purpose  : Returns the value of the floating-point uniform variable
728 // =======================================================================
729 Standard_Boolean OpenGl_ShaderProgram::GetUniform (const Handle(OpenGl_Context)& theCtx,
730                                                    const GLchar*                 theName,
731                                                    OpenGl_Vec4&                  theValue) const
732 {
733   return GetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
734 }
735
736 // =======================================================================
737 // function : GetUniform
738 // purpose  : Returns the value of the floating-point uniform variable
739 // =======================================================================
740 Standard_Boolean OpenGl_ShaderProgram::GetUniform (const Handle(OpenGl_Context)& theCtx,
741                                                    GLint                         theLocation,
742                                                    OpenGl_Vec4&                  theValue) const
743 {
744   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
745   {
746     return Standard_False;
747   }
748
749   theCtx->core20fwd->glGetUniformfv (myProgramID, theLocation, theValue);
750   return Standard_True;
751 }
752
753 // =======================================================================
754 // function : GetAttribute
755 // purpose  : Returns the integer vertex attribute
756 // =======================================================================
757 Standard_Boolean OpenGl_ShaderProgram::GetAttribute (const Handle(OpenGl_Context)& theCtx,
758                                                      const GLchar*                 theName,
759                                                      OpenGl_Vec4i&                 theValue) const
760 {
761   return GetAttribute (theCtx, GetAttributeLocation (theCtx, theName), theValue);
762 }
763
764 // =======================================================================
765 // function : GetAttribute
766 // purpose  : Returns the integer vertex attribute
767 // =======================================================================
768 Standard_Boolean OpenGl_ShaderProgram::GetAttribute (const Handle(OpenGl_Context)& theCtx,
769                                                      GLint                         theIndex,
770                                                      OpenGl_Vec4i&                 theValue) const
771 {
772   if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION)
773   {
774     return Standard_False;
775   }
776
777   theCtx->core20fwd->glGetVertexAttribiv (theIndex, GL_CURRENT_VERTEX_ATTRIB, theValue);
778   return Standard_True;
779 }
780
781 // =======================================================================
782 // function : GetAttribute
783 // purpose  : Returns the floating-point vertex attribute
784 // =======================================================================
785 Standard_Boolean OpenGl_ShaderProgram::GetAttribute (const Handle(OpenGl_Context)& theCtx,
786                                                      const GLchar*                 theName,
787                                                      OpenGl_Vec4&                  theValue) const
788 {
789   return GetAttribute (theCtx, GetAttributeLocation (theCtx, theName), theValue);
790 }
791
792 // =======================================================================
793 // function : GetAttribute
794 // purpose  : Returns the floating-point vertex attribute
795 // =======================================================================
796 Standard_Boolean OpenGl_ShaderProgram::GetAttribute (const Handle(OpenGl_Context)& theCtx,
797                                                      GLint                         theIndex,
798                                                      OpenGl_Vec4&                  theValue) const
799 {
800   if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION)
801   {
802     return Standard_False;
803   }
804
805   theCtx->core20fwd->glGetVertexAttribfv (theIndex, GL_CURRENT_VERTEX_ATTRIB, theValue);
806   return Standard_True;
807 }
808
809 // =======================================================================
810 // function : SetAttributeName
811 // purpose  :
812 // =======================================================================
813 Standard_Boolean OpenGl_ShaderProgram::SetAttributeName (const Handle(OpenGl_Context)& theCtx,
814                                                          GLint                         theIndex,
815                                                          const GLchar*                 theName)
816 {
817   theCtx->core20fwd->glBindAttribLocation (myProgramID, theIndex, theName);
818   return Standard_True;
819 }
820
821 // =======================================================================
822 // function : SetAttribute
823 // purpose  :
824 // =======================================================================
825 Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
826                                                      const GLchar*                 theName,
827                                                      GLfloat                       theValue)
828 {
829   return SetAttribute (theCtx, GetAttributeLocation (theCtx, theName), theValue);
830 }
831
832 // =======================================================================
833 // function : SetAttribute
834 // purpose  :
835 // =======================================================================
836 Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
837                                                      GLint                         theIndex,
838                                                      GLfloat                       theValue)
839 {
840   if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION)
841   {
842     return Standard_False;
843   }
844
845   theCtx->core20fwd->glVertexAttrib1f (theIndex, theValue);
846   return Standard_True;
847 }
848
849 // =======================================================================
850 // function : SetAttribute
851 // purpose  :
852 // =======================================================================
853 Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
854                                                      const GLchar*                 theName,
855                                                      const OpenGl_Vec2&            theValue)
856 {
857   return SetAttribute (theCtx, GetAttributeLocation (theCtx, theName), theValue);
858 }
859
860 // =======================================================================
861 // function : SetAttribute
862 // purpose  :
863 // =======================================================================
864 Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
865                                                      GLint                         theIndex,
866                                                      const OpenGl_Vec2&            theValue)
867 {
868   if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION)
869   {
870     return Standard_False;
871   }
872
873   theCtx->core20fwd->glVertexAttrib2fv (theIndex, theValue);
874   return Standard_True;
875 }
876
877 // =======================================================================
878 // function : SetAttribute
879 // purpose  :
880 // =======================================================================
881 Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
882                                                      const GLchar*                 theName,
883                                                      const OpenGl_Vec3&            theValue)
884 {
885   return SetAttribute (theCtx, GetAttributeLocation (theCtx, theName), theValue);
886 }
887
888 // =======================================================================
889 // function : SetAttribute
890 // purpose  :
891 // =======================================================================
892 Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
893                                                      GLint                         theIndex,
894                                                      const OpenGl_Vec3&            theValue)
895 {
896   if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION)
897   {
898     return Standard_False;
899   }
900
901   theCtx->core20fwd->glVertexAttrib3fv (theIndex, theValue);
902   return Standard_True;
903 }
904
905 // =======================================================================
906 // function : SetAttribute
907 // purpose  :
908 // =======================================================================
909 Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
910                                                      const GLchar*                 theName,
911                                                      const OpenGl_Vec4&            theValue)
912 {
913   return SetAttribute (theCtx, GetAttributeLocation (theCtx, theName), theValue);
914 }
915
916 // =======================================================================
917 // function : SetAttribute
918 // purpose  :
919 // =======================================================================
920 Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
921                                                      GLint                         theIndex,
922                                                      const OpenGl_Vec4&            theValue)
923 {
924   if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION)
925   {
926     return Standard_False;
927   }
928
929   theCtx->core20fwd->glVertexAttrib4fv (theIndex, theValue);
930   return Standard_True;
931 }
932
933 // =======================================================================
934 // function : SetUniform
935 // purpose  : Specifies the value of the integer uniform variable
936 // =======================================================================
937 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
938                                                    const GLchar*                 theName,
939                                                    GLint                         theValue)
940 {
941   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
942 }
943
944 // =======================================================================
945 // function : SetUniform
946 // purpose  : Specifies the value of the integer uniform variable
947 // =======================================================================
948 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
949                                                    GLint                         theLocation,
950                                                    GLint                         theValue)
951 {
952   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
953   {
954     return Standard_False;
955   }
956
957   theCtx->core20fwd->glUniform1i (theLocation, theValue);
958   return Standard_True;
959 }
960
961 // =======================================================================
962 // function : SetUniform
963 // purpose  :
964 // =======================================================================
965 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
966                                                    const GLchar*                 theName,
967                                                    const OpenGl_Vec2u&           theValue)
968 {
969   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
970 }
971
972 // =======================================================================
973 // function : SetUniform
974 // purpose  :
975 // =======================================================================
976 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
977                                                    GLint                         theLocation,
978                                                    const OpenGl_Vec2u&           theValue)
979 {
980   if (theCtx->core32 == NULL || myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
981   {
982     return Standard_False;
983   }
984
985 #if !defined(GL_ES_VERSION_2_0)
986   theCtx->core32->glUniform2uiv (theLocation, 1, theValue.GetData());
987   return Standard_True;
988 #else
989   (void )theValue;
990   return Standard_False;
991 #endif
992 }
993
994 // =======================================================================
995 // function : SetUniform
996 // purpose  :
997 // =======================================================================
998 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
999                                                    const GLchar*                 theName,
1000                                                    const GLsizei                 theCount,
1001                                                    const OpenGl_Vec2u*           theValue)
1002 {
1003   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theCount, theValue);
1004 }
1005
1006 // =======================================================================
1007 // function : SetUniform
1008 // purpose  :
1009 // =======================================================================
1010 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1011                                                    GLint                         theLocation,
1012                                                    const GLsizei                 theCount,
1013                                                    const OpenGl_Vec2u*           theValue)
1014 {
1015   if (theCtx->core32 == NULL || myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1016   {
1017     return Standard_False;
1018   }
1019
1020 #if !defined(GL_ES_VERSION_2_0)
1021   theCtx->core32->glUniform2uiv (theLocation, theCount, theValue->GetData());
1022   return Standard_True;
1023 #else
1024   (void )theCount;
1025   (void )theValue;
1026   return Standard_False;
1027 #endif
1028 }
1029
1030 // =======================================================================
1031 // function : SetUniform
1032 // purpose  : Specifies the value of the floating-point uniform variable
1033 // =======================================================================
1034 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1035                                                    const GLchar*                 theName,
1036                                                    GLfloat                       theValue)
1037 {
1038   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
1039 }
1040
1041 // =======================================================================
1042 // function : SetUniform
1043 // purpose  : Specifies the value of the floating-point uniform variable
1044 // =======================================================================
1045 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1046                                                    GLint                         theLocation,
1047                                                    GLfloat                       theValue)
1048 {
1049   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1050   {
1051     return Standard_False;
1052   }
1053
1054   theCtx->core20fwd->glUniform1f (theLocation, theValue);
1055   return Standard_True;
1056 }
1057
1058 // =======================================================================
1059 // function : SetUniform
1060 // purpose  : Specifies the value of the integer uniform 2D vector
1061 // =======================================================================
1062 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1063                                                    const GLchar*                 theName,
1064                                                    const OpenGl_Vec2i&           theValue)
1065 {
1066   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
1067 }
1068
1069 // =======================================================================
1070 // function : SetUniform
1071 // purpose  : Specifies the value of the integer uniform 2D vector
1072 // =======================================================================
1073 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1074                                                    GLint                         theLocation,
1075                                                    const OpenGl_Vec2i&           theValue)
1076 {
1077   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1078   {
1079     return Standard_False;
1080   }
1081
1082   theCtx->core20fwd->glUniform2iv (theLocation, 1, theValue);
1083   return Standard_True;
1084 }
1085
1086 // =======================================================================
1087 // function : SetUniform
1088 // purpose  : Specifies the value of the integer uniform 3D vector
1089 // =======================================================================
1090 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1091                                                    const GLchar*                 theName,
1092                                                    const OpenGl_Vec3i&           theValue)
1093 {
1094   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
1095 }
1096
1097 // =======================================================================
1098 // function : SetUniform
1099 // purpose  : Specifies the value of the integer uniform 3D vector
1100 // =======================================================================
1101 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1102                                                    GLint                         theLocation,
1103                                                    const OpenGl_Vec3i&           theValue)
1104 {
1105   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1106   {
1107     return Standard_False;
1108   }
1109
1110   theCtx->core20fwd->glUniform3iv (theLocation, 1, theValue);
1111   return Standard_True;
1112 }
1113
1114 // =======================================================================
1115 // function : SetUniform
1116 // purpose  : Specifies the value of the integer uniform 4D vector
1117 // =======================================================================
1118 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1119                                                    const GLchar*                 theName,
1120                                                    const OpenGl_Vec4i&           theValue)
1121 {
1122   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
1123 }
1124
1125 // =======================================================================
1126 // function : SetUniform
1127 // purpose  : Specifies the value of the integer uniform 4D vector
1128 // =======================================================================
1129 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1130                                                    GLint                         theLocation,
1131                                                    const OpenGl_Vec4i&           theValue)
1132 {
1133   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1134   {
1135     return Standard_False;
1136   }
1137
1138   theCtx->core20fwd->glUniform4iv (theLocation, 1, theValue);
1139   return Standard_True;
1140 }
1141
1142 // =======================================================================
1143 // function : SetUniform
1144 // purpose  : Specifies the value of the floating-point uniform 2D vector
1145 // =======================================================================
1146 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1147                                                    const GLchar*                 theName,
1148                                                    const OpenGl_Vec2&            theValue)
1149 {
1150   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
1151 }
1152
1153 // =======================================================================
1154 // function : SetUniform
1155 // purpose  : Specifies the value of the floating-point uniform 2D vector
1156 // =======================================================================
1157 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1158                                                    GLint                         theLocation,
1159                                                    const OpenGl_Vec2&            theValue)
1160 {
1161   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1162   {
1163     return Standard_False;
1164   }
1165
1166   theCtx->core20fwd->glUniform2fv (theLocation, 1, theValue);
1167   return Standard_True;
1168 }
1169
1170 // =======================================================================
1171 // function : SetUniform
1172 // purpose  : Specifies the value of the floating-point uniform 3D vector
1173 // =======================================================================
1174 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1175                                                    const GLchar*                 theName,
1176                                                    const OpenGl_Vec3&            theValue)
1177 {
1178   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
1179 }
1180
1181 // =======================================================================
1182 // function : SetUniform
1183 // purpose  : Specifies the value of the floating-point uniform 3D vector
1184 // =======================================================================
1185 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1186                                                    GLint                         theLocation,
1187                                                    const OpenGl_Vec3&            theValue)
1188 {
1189   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1190   {
1191     return Standard_False;
1192   }
1193
1194   theCtx->core20fwd->glUniform3fv (theLocation, 1, theValue);
1195   return Standard_True;
1196 }
1197
1198 // =======================================================================
1199 // function : SetUniform
1200 // purpose  : Specifies the value of the floating-point uniform 4D vector
1201 // =======================================================================
1202 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1203                                                    const GLchar*                 theName,
1204                                                    const OpenGl_Vec4&            theValue)
1205 {
1206   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
1207 }
1208
1209 // =======================================================================
1210 // function : SetUniform
1211 // purpose  : Specifies the value of the floating-point uniform 4D vector
1212 // =======================================================================
1213 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1214                                                    GLint                         theLocation,
1215                                                    const OpenGl_Vec4&            theValue)
1216 {
1217   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1218   {
1219     return Standard_False;
1220   }
1221
1222   theCtx->core20fwd->glUniform4fv (theLocation, 1, theValue);
1223   return Standard_True;
1224 }
1225
1226 // =======================================================================
1227 // function : SetUniform
1228 // purpose  : Specifies the value of the floating-point uniform 4x4 matrix
1229 // =======================================================================
1230 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1231                                                    const GLchar*                 theName,
1232                                                    const OpenGl_Mat4&            theValue,
1233                                                    GLboolean                     theTranspose)
1234 {
1235   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue, theTranspose);
1236 }
1237
1238 // =======================================================================
1239 // function : SetUniform
1240 // purpose  : Specifies the value of the floating-point uniform 4x4 matrix
1241 // =======================================================================
1242 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1243                                                    GLint                         theLocation,
1244                                                    const OpenGl_Mat4&            theValue,
1245                                                    GLboolean                     theTranspose)
1246 {
1247   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1248   {
1249     return Standard_False;
1250   }
1251
1252   theCtx->core20fwd->glUniformMatrix4fv (theLocation, 1, GL_FALSE, theTranspose ? theValue.Transposed() : theValue);
1253   return Standard_True;
1254 }
1255
1256 // =======================================================================
1257 // function : SetUniform
1258 // purpose  : Specifies the value of the floating-point uniform 4x4 matrix
1259 // =======================================================================
1260 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1261                                                    const GLchar*                 theName,
1262                                                    const OpenGl_Matrix&          theValue,
1263                                                    GLboolean                     theTranspose)
1264 {
1265   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue, theTranspose);
1266 }
1267
1268 // =======================================================================
1269 // function : SetUniform
1270 // purpose  : Specifies the value of the floating-point uniform 4x4 matrix
1271 // =======================================================================
1272 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1273                                                    GLint                         theLocation,
1274                                                    const OpenGl_Matrix&          theValue,
1275                                                    GLboolean                     theTranspose)
1276 {
1277   return SetUniform (theCtx, theLocation, OpenGl_Mat4::Map (*theValue.mat), theTranspose);
1278 }
1279
1280 // =======================================================================
1281 // function : SetUniform
1282 // purpose  : Specifies the value of the float uniform array
1283 // =======================================================================
1284 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1285                                                    GLint                         theLocation,
1286                                                    GLuint                        theCount,
1287                                                    const Standard_ShortReal*     theData)
1288 {
1289   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1290   {
1291     return Standard_False;
1292   }
1293
1294   theCtx->core20fwd->glUniform1fv (theLocation, theCount, theData);
1295   return Standard_True;
1296 }
1297
1298 // =======================================================================
1299 // function : SetUniform
1300 // purpose  : Specifies the value of the float2 uniform array
1301 // =======================================================================
1302 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1303                                                    GLint                         theLocation,
1304                                                    GLuint                        theCount,
1305                                                    const OpenGl_Vec2*            theData)
1306 {
1307   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1308   {
1309     return Standard_False;
1310   }
1311
1312   theCtx->core20fwd->glUniform2fv (theLocation, theCount, theData[0].GetData());
1313   return Standard_True;
1314 }
1315
1316 // =======================================================================
1317 // function : SetUniform
1318 // purpose  : Specifies the value of the float3 uniform array
1319 // =======================================================================
1320 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1321                                                    GLint                         theLocation,
1322                                                    GLuint                        theCount,
1323                                                    const OpenGl_Vec3*            theData)
1324 {
1325   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1326   {
1327     return Standard_False;
1328   }
1329
1330   theCtx->core20fwd->glUniform3fv (theLocation, theCount, theData[0].GetData());
1331   return Standard_True;
1332 }
1333
1334 // =======================================================================
1335 // function : SetUniform
1336 // purpose  : Specifies the value of the float4 uniform array
1337 // =======================================================================
1338 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1339                                                    GLint                         theLocation,
1340                                                    GLuint                        theCount,
1341                                                    const OpenGl_Vec4*            theData)
1342 {
1343   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1344   {
1345     return Standard_False;
1346   }
1347
1348   theCtx->core20fwd->glUniform4fv (theLocation, theCount, theData[0].GetData());
1349   return Standard_True;
1350 }
1351
1352 // =======================================================================
1353 // function : SetUniform
1354 // purpose  : Specifies the value of the integer uniform array
1355 // =======================================================================
1356 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1357                                                    GLint                         theLocation,
1358                                                    GLuint                        theCount,
1359                                                    const Standard_Integer*       theData)
1360 {
1361   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1362   {
1363     return Standard_False;
1364   }
1365
1366   theCtx->core20fwd->glUniform1iv (theLocation, theCount, theData);
1367   return Standard_True;
1368 }
1369
1370 // =======================================================================
1371 // function : SetUniform
1372 // purpose  : Specifies the value of the int2 uniform array
1373 // =======================================================================
1374 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1375                                                    GLint                         theLocation,
1376                                                    GLuint                        theCount,
1377                                                    const OpenGl_Vec2i*           theData)
1378 {
1379   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1380   {
1381     return Standard_False;
1382   }
1383
1384   theCtx->core20fwd->glUniform2iv (theLocation, theCount, theData[0].GetData());
1385   return Standard_True;
1386 }
1387
1388 // =======================================================================
1389 // function : SetUniform
1390 // purpose  : Specifies the value of the int3 uniform array
1391 // =======================================================================
1392 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1393                                                    GLint                         theLocation,
1394                                                    GLuint                        theCount,
1395                                                    const OpenGl_Vec3i*           theData)
1396 {
1397   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1398   {
1399     return Standard_False;
1400   }
1401
1402   theCtx->core20fwd->glUniform3iv (theLocation, theCount, theData[0].GetData());
1403   return Standard_True;
1404 }
1405
1406 // =======================================================================
1407 // function : SetUniform
1408 // purpose  : Specifies the value of the int4 uniform array
1409 // =======================================================================
1410 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1411                                                    GLint                         theLocation,
1412                                                    GLuint                        theCount,
1413                                                    const OpenGl_Vec4i*           theData)
1414 {
1415   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1416   {
1417     return Standard_False;
1418   }
1419
1420   theCtx->core20fwd->glUniform4iv (theLocation, theCount, theData[0].GetData());
1421   return Standard_True;
1422 }
1423
1424 // =======================================================================
1425 // function : SetSampler
1426 // purpose  : Specifies the value of the sampler uniform variable
1427 // =======================================================================
1428 Standard_Boolean OpenGl_ShaderProgram::SetSampler (const Handle(OpenGl_Context)& theCtx,
1429                                                    const GLchar*                 theName,
1430                                                    const Graphic3d_TextureUnit   theTextureUnit)
1431 {
1432   return SetSampler (theCtx, GetUniformLocation (theCtx, theName), theTextureUnit);
1433 }
1434
1435 // =======================================================================
1436 // function : SetSampler
1437 // purpose  : Specifies the value of the sampler uniform variable
1438 // =======================================================================
1439 Standard_Boolean OpenGl_ShaderProgram::SetSampler (const Handle(OpenGl_Context)& theCtx,
1440                                                    GLint                         theLocation,
1441                                                    const Graphic3d_TextureUnit   theTextureUnit)
1442 {
1443   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1444   {
1445     return Standard_False;
1446   }
1447
1448   theCtx->core20fwd->glUniform1i (theLocation, theTextureUnit);
1449   return Standard_True;
1450 }
1451
1452 // =======================================================================
1453 // function : Create
1454 // purpose  : Creates new empty shader program of specified type
1455 // =======================================================================
1456 Standard_Boolean OpenGl_ShaderProgram::Create (const Handle(OpenGl_Context)& theCtx)
1457 {
1458   if (myProgramID == NO_PROGRAM
1459    && theCtx->core20fwd != NULL)
1460   {
1461     myProgramID = theCtx->core20fwd->glCreateProgram();
1462   }
1463
1464   return myProgramID != NO_PROGRAM;
1465 }
1466
1467 // =======================================================================
1468 // function : Release
1469 // purpose  : Destroys shader program
1470 // =======================================================================
1471 void OpenGl_ShaderProgram::Release (OpenGl_Context* theCtx)
1472 {
1473   if (myProgramID == NO_PROGRAM)
1474   {
1475     return;
1476   }
1477
1478   Standard_ASSERT_RETURN (theCtx != NULL,
1479     "OpenGl_ShaderProgram destroyed without GL context! Possible GPU memory leakage...",);
1480
1481   for (OpenGl_ShaderList::Iterator anIter (myShaderObjects); anIter.More(); anIter.Next())
1482   {
1483     if (!anIter.Value().IsNull())
1484     {
1485       anIter.ChangeValue()->Release (theCtx);
1486       anIter.ChangeValue().Nullify();
1487     }
1488   }
1489
1490   if (theCtx->core20fwd != NULL
1491    && theCtx->IsValid())
1492   {
1493     theCtx->core20fwd->glDeleteProgram (myProgramID);
1494   }
1495
1496   myProgramID = NO_PROGRAM;
1497 }