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