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