0030488: Visualization, Ray Tracing - empty error message on GLSL program compilation
[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->LoadAndCompile (theCtx, aSource))
375     {
376       return Standard_False;
377     }
378
379     if (theCtx->caps->glslDumpLevel)
380     {
381       TCollection_AsciiString aShaderTypeMsg;
382       switch (anIter.Value()->Type())
383       {
384         case Graphic3d_TOS_COMPUTE:         { aShaderTypeMsg = "Compute shader source code:\n";                break; }
385         case Graphic3d_TOS_VERTEX:          { aShaderTypeMsg = "Vertex shader source code:\n";                 break; }
386         case Graphic3d_TOS_TESS_CONTROL:    { aShaderTypeMsg = "Tesselation control shader source code:\n";    break; }
387         case Graphic3d_TOS_TESS_EVALUATION: { aShaderTypeMsg = "Tesselation evaluation shader source code:\n"; break; }
388         case Graphic3d_TOS_GEOMETRY:        { aShaderTypeMsg = "Geometry shader source code:\n";               break; }
389         case Graphic3d_TOS_FRAGMENT:        { aShaderTypeMsg = "Fragment shader source code:\n";               break; }
390       }
391       TCollection_AsciiString anOutputSource = aSource;
392       if (theCtx->caps->glslDumpLevel == OpenGl_ShaderProgramDumpLevel_Short)
393       {
394         anOutputSource = aHeaderVer
395                        + (!aHeaderVer.IsEmpty() ? "\n" : "")
396                        + anExtensions
397                        + aPrecisionHeader
398                        + aHeaderType
399                        + aHeaderConstants
400                        + anIter.Value()->Source();
401       }
402       theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_OTHER, 0, GL_DEBUG_SEVERITY_MEDIUM,
403                            TCollection_ExtendedString (aShaderTypeMsg + anOutputSource));
404     }
405
406     if (!AttachShader (theCtx, aShader))
407     {
408       aShader->Release (theCtx.operator->());
409       return Standard_False;
410     }
411   }
412
413   // bind locations for pre-defined Vertex Attributes
414   SetAttributeName (theCtx, Graphic3d_TOA_POS,   "occVertex");
415   SetAttributeName (theCtx, Graphic3d_TOA_NORM,  "occNormal");
416   SetAttributeName (theCtx, Graphic3d_TOA_UV,    "occTexCoord");
417   SetAttributeName (theCtx, Graphic3d_TOA_COLOR, "occVertColor");
418
419   // bind custom Vertex Attributes
420   if (!myProxy.IsNull())
421   {
422     for (Graphic3d_ShaderAttributeList::Iterator anAttribIter (myProxy->VertexAttributes());
423          anAttribIter.More(); anAttribIter.Next())
424     {
425       SetAttributeName (theCtx, anAttribIter.Value()->Location(), anAttribIter.Value()->Name().ToCString());
426     }
427   }
428
429   if (!Link (theCtx))
430   {
431     return Standard_False;
432   }
433
434   // set uniform defaults
435   const Handle(OpenGl_ShaderProgram)& anOldProgram = theCtx->ActiveProgram();
436   theCtx->core20fwd->glUseProgram (myProgramID);
437   {
438     const GLint aLocTexEnable = GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE);
439     if (aLocTexEnable != INVALID_LOCATION)
440     {
441       SetUniform (theCtx, aLocTexEnable, 0); // Off
442     }
443   }
444   {
445     const GLint aLocSampler = GetUniformLocation (theCtx, "occActiveSampler");
446     if (aLocSampler != INVALID_LOCATION)
447     {
448       SetUniform (theCtx, aLocSampler, GLint(Graphic3d_TextureUnit_0));
449     }
450   }
451
452   const TCollection_AsciiString aSamplerNamePrefix ("occSampler");
453   const Standard_Integer aNbUnitsMax = Max (theCtx->MaxCombinedTextureUnits(), Graphic3d_TextureUnit_NB);
454   for (GLint aUnitIter = 0; aUnitIter < aNbUnitsMax; ++aUnitIter)
455   {
456     const TCollection_AsciiString aName = aSamplerNamePrefix + aUnitIter;
457     const GLint aLocSampler = GetUniformLocation (theCtx, aName.ToCString());
458     if (aLocSampler != INVALID_LOCATION)
459     {
460       SetUniform (theCtx, aLocSampler, aUnitIter);
461     }
462   }
463
464   theCtx->core20fwd->glUseProgram (!anOldProgram.IsNull() ? anOldProgram->ProgramId() : OpenGl_ShaderProgram::NO_PROGRAM);
465   return Standard_True;
466 }
467
468 // =======================================================================
469 // function : ~OpenGl_ShaderProgram
470 // purpose  : Releases resources of shader program
471 // =======================================================================
472 OpenGl_ShaderProgram::~OpenGl_ShaderProgram()
473 {
474   Release (NULL);
475 }
476
477 // =======================================================================
478 // function : AttachShader
479 // purpose  : Attaches shader object to the program object
480 // =======================================================================
481 Standard_Boolean OpenGl_ShaderProgram::AttachShader (const Handle(OpenGl_Context)&      theCtx,
482                                                      const Handle(OpenGl_ShaderObject)& theShader)
483 {
484   if (myProgramID == NO_PROGRAM || theShader.IsNull())
485   {
486     return Standard_False;
487   }
488
489   for (OpenGl_ShaderList::Iterator anIter (myShaderObjects); anIter.More(); anIter.Next())
490   {
491     if (theShader == anIter.Value())
492     {
493       return Standard_False;
494     }
495   }
496
497   myShaderObjects.Append (theShader);
498   theCtx->core20fwd->glAttachShader (myProgramID, theShader->myShaderID);
499   return Standard_True;
500 }
501
502 // =======================================================================
503 // function : DetachShader
504 // purpose  : Detaches shader object to the program object
505 // =======================================================================
506 Standard_Boolean OpenGl_ShaderProgram::DetachShader (const Handle(OpenGl_Context)&      theCtx,
507                                                      const Handle(OpenGl_ShaderObject)& theShader)
508 {
509   if (myProgramID == NO_PROGRAM
510    || theShader.IsNull())
511   {
512     return Standard_False;
513   }
514
515   OpenGl_ShaderList::Iterator anIter (myShaderObjects);
516   while (anIter.More())
517   {
518     if (theShader == anIter.Value())
519     {
520       myShaderObjects.Remove (anIter);
521       break;
522     }
523
524     anIter.Next();
525   }
526
527   if (!anIter.More())
528   {
529     return Standard_False;
530   }
531
532   theCtx->core20fwd->glDetachShader (myProgramID, theShader->myShaderID);
533   return Standard_True;
534 }
535
536 // =======================================================================
537 // function : Link
538 // purpose  : Links the program object
539 // =======================================================================
540 Standard_Boolean OpenGl_ShaderProgram::link (const Handle(OpenGl_Context)& theCtx)
541 {
542   if (myProgramID == NO_PROGRAM)
543   {
544     return Standard_False;
545   }
546
547   GLint aStatus = GL_FALSE;
548   theCtx->core20fwd->glLinkProgram (myProgramID);
549   theCtx->core20fwd->glGetProgramiv (myProgramID, GL_LINK_STATUS, &aStatus);
550   if (aStatus == GL_FALSE)
551   {
552     return Standard_False;
553   }
554
555   for (GLint aVar = 0; aVar < OpenGl_OCCT_NUMBER_OF_STATE_VARIABLES; ++aVar)
556   {
557     myStateLocations[aVar] = GetUniformLocation (theCtx, PredefinedKeywords[aVar]);
558   }
559   return Standard_True;
560 }
561
562 // =======================================================================
563 // function : Link
564 // purpose  :
565 // =======================================================================
566 Standard_Boolean OpenGl_ShaderProgram::Link (const Handle(OpenGl_Context)& theCtx,
567                                              bool theIsVerbose)
568 {
569   if (!theIsVerbose)
570   {
571     return link (theCtx);
572   }
573
574   if (!link (theCtx))
575   {
576     TCollection_AsciiString aLog;
577     FetchInfoLog (theCtx, aLog);
578     if (aLog.IsEmpty())
579     {
580       aLog = "Linker log is empty.";
581     }
582     theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
583                          TCollection_AsciiString ("Failed to link program object! Linker log:\n") + aLog);
584     return false;
585   }
586   else if (theCtx->caps->glslWarnings)
587   {
588     TCollection_AsciiString aLog;
589     FetchInfoLog (theCtx, aLog);
590     if (!aLog.IsEmpty()
591      && !aLog.IsEqual ("No errors.\n"))
592     {
593       theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_LOW,
594                            TCollection_AsciiString ("GLSL linker log:\n") + aLog);
595     }
596   }
597   return true;
598 }
599
600 // =======================================================================
601 // function : FetchInfoLog
602 // purpose  : Fetches information log of the last link operation
603 // =======================================================================
604 Standard_Boolean OpenGl_ShaderProgram::FetchInfoLog (const Handle(OpenGl_Context)& theCtx,
605                                                      TCollection_AsciiString&      theOutput)
606 {
607   if (myProgramID == NO_PROGRAM)
608   {
609     return Standard_False;
610   }
611
612   GLint aLength = 0;
613   theCtx->core20fwd->glGetProgramiv (myProgramID, GL_INFO_LOG_LENGTH, &aLength);
614   if (aLength > 0)
615   {
616     GLchar* aLog = (GLchar*) alloca (aLength);
617     memset (aLog, 0, aLength);
618     theCtx->core20fwd->glGetProgramInfoLog (myProgramID, aLength, NULL, aLog);
619     theOutput = aLog;
620   }
621   return Standard_True;
622 }
623
624 // =======================================================================
625 // function : ApplyVariables
626 // purpose  : Fetches uniform variables from proxy shader program
627 // =======================================================================
628 Standard_Boolean OpenGl_ShaderProgram::ApplyVariables(const Handle(OpenGl_Context)& theCtx)
629 {
630   if (myProxy.IsNull() || myProxy->Variables().IsEmpty())
631   {
632     return Standard_False;
633   }
634
635   for (Graphic3d_ShaderVariableList::Iterator anIter (myProxy->Variables()); anIter.More(); anIter.Next())
636   {
637     mySetterSelector.Set (theCtx, anIter.Value(), this);
638   }
639
640   myProxy->ClearVariables();
641   return Standard_True;
642 }
643
644 // =======================================================================
645 // function : GetUniformLocation
646 // purpose  : Returns location (index) of the specific uniform variable
647 // =======================================================================
648 GLint OpenGl_ShaderProgram::GetUniformLocation (const Handle(OpenGl_Context)& theCtx,
649                                                 const GLchar*                 theName) const
650 {
651   return myProgramID != NO_PROGRAM
652        ? theCtx->core20fwd->glGetUniformLocation (myProgramID, theName)
653        : INVALID_LOCATION;
654 }
655
656 // =======================================================================
657 // function : GetAttributeLocation
658 // purpose  : Returns location (index) of the generic vertex attribute
659 // =======================================================================
660 GLint OpenGl_ShaderProgram::GetAttributeLocation (const Handle(OpenGl_Context)& theCtx,
661                                                   const GLchar*                 theName) const
662 {
663   return myProgramID != NO_PROGRAM
664        ? theCtx->core20fwd->glGetAttribLocation (myProgramID, theName)
665        : INVALID_LOCATION;
666 }
667
668 // =======================================================================
669 // function : GetStateLocation
670 // purpose  : Returns location of the OCCT state uniform variable
671 // =======================================================================
672 GLint OpenGl_ShaderProgram::GetStateLocation (const GLuint theVariable) const
673 {
674   if (theVariable < OpenGl_OCCT_NUMBER_OF_STATE_VARIABLES)
675   {
676     return myStateLocations[theVariable];
677   }
678   return INVALID_LOCATION;
679 }
680
681 // =======================================================================
682 // function : GetUniform
683 // purpose  : Returns the value of the integer uniform variable
684 // =======================================================================
685 Standard_Boolean OpenGl_ShaderProgram::GetUniform (const Handle(OpenGl_Context)& theCtx,
686                                                    const GLchar*                 theName,
687                                                    OpenGl_Vec4i&                 theValue) const
688 {
689   return GetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
690 }
691
692 // =======================================================================
693 // function : GetUniform
694 // purpose  : Returns the value of the integer uniform variable
695 // =======================================================================
696 Standard_Boolean OpenGl_ShaderProgram::GetUniform (const Handle(OpenGl_Context)& theCtx,
697                                                    GLint                         theLocation,
698                                                    OpenGl_Vec4i&                 theValue) const
699 {
700   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
701   {
702     return Standard_False;
703   }
704
705   theCtx->core20fwd->glGetUniformiv (myProgramID, theLocation, theValue);
706   return Standard_True;
707 }
708
709 // =======================================================================
710 // function : GetUniform
711 // purpose  : Returns the value of the floating-point uniform variable
712 // =======================================================================
713 Standard_Boolean OpenGl_ShaderProgram::GetUniform (const Handle(OpenGl_Context)& theCtx,
714                                                    const GLchar*                 theName,
715                                                    OpenGl_Vec4&                  theValue) const
716 {
717   return GetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
718 }
719
720 // =======================================================================
721 // function : GetUniform
722 // purpose  : Returns the value of the floating-point uniform variable
723 // =======================================================================
724 Standard_Boolean OpenGl_ShaderProgram::GetUniform (const Handle(OpenGl_Context)& theCtx,
725                                                    GLint                         theLocation,
726                                                    OpenGl_Vec4&                  theValue) const
727 {
728   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
729   {
730     return Standard_False;
731   }
732
733   theCtx->core20fwd->glGetUniformfv (myProgramID, theLocation, theValue);
734   return Standard_True;
735 }
736
737 // =======================================================================
738 // function : GetAttribute
739 // purpose  : Returns the integer vertex attribute
740 // =======================================================================
741 Standard_Boolean OpenGl_ShaderProgram::GetAttribute (const Handle(OpenGl_Context)& theCtx,
742                                                      const GLchar*                 theName,
743                                                      OpenGl_Vec4i&                 theValue) const
744 {
745   return GetAttribute (theCtx, GetAttributeLocation (theCtx, theName), theValue);
746 }
747
748 // =======================================================================
749 // function : GetAttribute
750 // purpose  : Returns the integer vertex attribute
751 // =======================================================================
752 Standard_Boolean OpenGl_ShaderProgram::GetAttribute (const Handle(OpenGl_Context)& theCtx,
753                                                      GLint                         theIndex,
754                                                      OpenGl_Vec4i&                 theValue) const
755 {
756   if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION)
757   {
758     return Standard_False;
759   }
760
761   theCtx->core20fwd->glGetVertexAttribiv (theIndex, GL_CURRENT_VERTEX_ATTRIB, theValue);
762   return Standard_True;
763 }
764
765 // =======================================================================
766 // function : GetAttribute
767 // purpose  : Returns the floating-point vertex attribute
768 // =======================================================================
769 Standard_Boolean OpenGl_ShaderProgram::GetAttribute (const Handle(OpenGl_Context)& theCtx,
770                                                      const GLchar*                 theName,
771                                                      OpenGl_Vec4&                  theValue) const
772 {
773   return GetAttribute (theCtx, GetAttributeLocation (theCtx, theName), theValue);
774 }
775
776 // =======================================================================
777 // function : GetAttribute
778 // purpose  : Returns the floating-point vertex attribute
779 // =======================================================================
780 Standard_Boolean OpenGl_ShaderProgram::GetAttribute (const Handle(OpenGl_Context)& theCtx,
781                                                      GLint                         theIndex,
782                                                      OpenGl_Vec4&                  theValue) const
783 {
784   if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION)
785   {
786     return Standard_False;
787   }
788
789   theCtx->core20fwd->glGetVertexAttribfv (theIndex, GL_CURRENT_VERTEX_ATTRIB, theValue);
790   return Standard_True;
791 }
792
793 // =======================================================================
794 // function : SetAttributeName
795 // purpose  :
796 // =======================================================================
797 Standard_Boolean OpenGl_ShaderProgram::SetAttributeName (const Handle(OpenGl_Context)& theCtx,
798                                                          GLint                         theIndex,
799                                                          const GLchar*                 theName)
800 {
801   theCtx->core20fwd->glBindAttribLocation (myProgramID, theIndex, theName);
802   return Standard_True;
803 }
804
805 // =======================================================================
806 // function : SetAttribute
807 // purpose  :
808 // =======================================================================
809 Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
810                                                      const GLchar*                 theName,
811                                                      GLfloat                       theValue)
812 {
813   return SetAttribute (theCtx, GetAttributeLocation (theCtx, theName), theValue);
814 }
815
816 // =======================================================================
817 // function : SetAttribute
818 // purpose  :
819 // =======================================================================
820 Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
821                                                      GLint                         theIndex,
822                                                      GLfloat                       theValue)
823 {
824   if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION)
825   {
826     return Standard_False;
827   }
828
829   theCtx->core20fwd->glVertexAttrib1f (theIndex, theValue);
830   return Standard_True;
831 }
832
833 // =======================================================================
834 // function : SetAttribute
835 // purpose  :
836 // =======================================================================
837 Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
838                                                      const GLchar*                 theName,
839                                                      const OpenGl_Vec2&            theValue)
840 {
841   return SetAttribute (theCtx, GetAttributeLocation (theCtx, theName), theValue);
842 }
843
844 // =======================================================================
845 // function : SetAttribute
846 // purpose  :
847 // =======================================================================
848 Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
849                                                      GLint                         theIndex,
850                                                      const OpenGl_Vec2&            theValue)
851 {
852   if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION)
853   {
854     return Standard_False;
855   }
856
857   theCtx->core20fwd->glVertexAttrib2fv (theIndex, theValue);
858   return Standard_True;
859 }
860
861 // =======================================================================
862 // function : SetAttribute
863 // purpose  :
864 // =======================================================================
865 Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
866                                                      const GLchar*                 theName,
867                                                      const OpenGl_Vec3&            theValue)
868 {
869   return SetAttribute (theCtx, GetAttributeLocation (theCtx, theName), theValue);
870 }
871
872 // =======================================================================
873 // function : SetAttribute
874 // purpose  :
875 // =======================================================================
876 Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
877                                                      GLint                         theIndex,
878                                                      const OpenGl_Vec3&            theValue)
879 {
880   if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION)
881   {
882     return Standard_False;
883   }
884
885   theCtx->core20fwd->glVertexAttrib3fv (theIndex, theValue);
886   return Standard_True;
887 }
888
889 // =======================================================================
890 // function : SetAttribute
891 // purpose  :
892 // =======================================================================
893 Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
894                                                      const GLchar*                 theName,
895                                                      const OpenGl_Vec4&            theValue)
896 {
897   return SetAttribute (theCtx, GetAttributeLocation (theCtx, theName), theValue);
898 }
899
900 // =======================================================================
901 // function : SetAttribute
902 // purpose  :
903 // =======================================================================
904 Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
905                                                      GLint                         theIndex,
906                                                      const OpenGl_Vec4&            theValue)
907 {
908   if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION)
909   {
910     return Standard_False;
911   }
912
913   theCtx->core20fwd->glVertexAttrib4fv (theIndex, theValue);
914   return Standard_True;
915 }
916
917 // =======================================================================
918 // function : SetUniform
919 // purpose  : Specifies the value of the integer uniform variable
920 // =======================================================================
921 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
922                                                    const GLchar*                 theName,
923                                                    GLint                         theValue)
924 {
925   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
926 }
927
928 // =======================================================================
929 // function : SetUniform
930 // purpose  : Specifies the value of the integer uniform variable
931 // =======================================================================
932 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
933                                                    GLint                         theLocation,
934                                                    GLint                         theValue)
935 {
936   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
937   {
938     return Standard_False;
939   }
940
941   theCtx->core20fwd->glUniform1i (theLocation, theValue);
942   return Standard_True;
943 }
944
945 // =======================================================================
946 // function : SetUniform
947 // purpose  :
948 // =======================================================================
949 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
950                                                    const GLchar*                 theName,
951                                                    const OpenGl_Vec2u&           theValue)
952 {
953   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
954 }
955
956 // =======================================================================
957 // function : SetUniform
958 // purpose  :
959 // =======================================================================
960 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
961                                                    GLint                         theLocation,
962                                                    const OpenGl_Vec2u&           theValue)
963 {
964   if (theCtx->core32 == NULL || myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
965   {
966     return Standard_False;
967   }
968
969 #if !defined(GL_ES_VERSION_2_0)
970   theCtx->core32->glUniform2uiv (theLocation, 1, theValue.GetData());
971   return Standard_True;
972 #else
973   (void )theValue;
974   return Standard_False;
975 #endif
976 }
977
978 // =======================================================================
979 // function : SetUniform
980 // purpose  :
981 // =======================================================================
982 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
983                                                    const GLchar*                 theName,
984                                                    const GLsizei                 theCount,
985                                                    const OpenGl_Vec2u*           theValue)
986 {
987   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theCount, theValue);
988 }
989
990 // =======================================================================
991 // function : SetUniform
992 // purpose  :
993 // =======================================================================
994 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
995                                                    GLint                         theLocation,
996                                                    const GLsizei                 theCount,
997                                                    const OpenGl_Vec2u*           theValue)
998 {
999   if (theCtx->core32 == NULL || myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1000   {
1001     return Standard_False;
1002   }
1003
1004 #if !defined(GL_ES_VERSION_2_0)
1005   theCtx->core32->glUniform2uiv (theLocation, theCount, theValue->GetData());
1006   return Standard_True;
1007 #else
1008   (void )theCount;
1009   (void )theValue;
1010   return Standard_False;
1011 #endif
1012 }
1013
1014 // =======================================================================
1015 // function : SetUniform
1016 // purpose  : Specifies the value of the floating-point uniform variable
1017 // =======================================================================
1018 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1019                                                    const GLchar*                 theName,
1020                                                    GLfloat                       theValue)
1021 {
1022   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
1023 }
1024
1025 // =======================================================================
1026 // function : SetUniform
1027 // purpose  : Specifies the value of the floating-point uniform variable
1028 // =======================================================================
1029 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1030                                                    GLint                         theLocation,
1031                                                    GLfloat                       theValue)
1032 {
1033   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1034   {
1035     return Standard_False;
1036   }
1037
1038   theCtx->core20fwd->glUniform1f (theLocation, theValue);
1039   return Standard_True;
1040 }
1041
1042 // =======================================================================
1043 // function : SetUniform
1044 // purpose  : Specifies the value of the integer uniform 2D vector
1045 // =======================================================================
1046 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1047                                                    const GLchar*                 theName,
1048                                                    const OpenGl_Vec2i&           theValue)
1049 {
1050   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
1051 }
1052
1053 // =======================================================================
1054 // function : SetUniform
1055 // purpose  : Specifies the value of the integer uniform 2D vector
1056 // =======================================================================
1057 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1058                                                    GLint                         theLocation,
1059                                                    const OpenGl_Vec2i&           theValue)
1060 {
1061   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1062   {
1063     return Standard_False;
1064   }
1065
1066   theCtx->core20fwd->glUniform2iv (theLocation, 1, theValue);
1067   return Standard_True;
1068 }
1069
1070 // =======================================================================
1071 // function : SetUniform
1072 // purpose  : Specifies the value of the integer uniform 3D vector
1073 // =======================================================================
1074 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1075                                                    const GLchar*                 theName,
1076                                                    const OpenGl_Vec3i&           theValue)
1077 {
1078   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
1079 }
1080
1081 // =======================================================================
1082 // function : SetUniform
1083 // purpose  : Specifies the value of the integer uniform 3D vector
1084 // =======================================================================
1085 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1086                                                    GLint                         theLocation,
1087                                                    const OpenGl_Vec3i&           theValue)
1088 {
1089   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1090   {
1091     return Standard_False;
1092   }
1093
1094   theCtx->core20fwd->glUniform3iv (theLocation, 1, theValue);
1095   return Standard_True;
1096 }
1097
1098 // =======================================================================
1099 // function : SetUniform
1100 // purpose  : Specifies the value of the integer uniform 4D vector
1101 // =======================================================================
1102 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1103                                                    const GLchar*                 theName,
1104                                                    const OpenGl_Vec4i&           theValue)
1105 {
1106   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
1107 }
1108
1109 // =======================================================================
1110 // function : SetUniform
1111 // purpose  : Specifies the value of the integer uniform 4D vector
1112 // =======================================================================
1113 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1114                                                    GLint                         theLocation,
1115                                                    const OpenGl_Vec4i&           theValue)
1116 {
1117   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1118   {
1119     return Standard_False;
1120   }
1121
1122   theCtx->core20fwd->glUniform4iv (theLocation, 1, theValue);
1123   return Standard_True;
1124 }
1125
1126 // =======================================================================
1127 // function : SetUniform
1128 // purpose  : Specifies the value of the floating-point uniform 2D vector
1129 // =======================================================================
1130 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1131                                                    const GLchar*                 theName,
1132                                                    const OpenGl_Vec2&            theValue)
1133 {
1134   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
1135 }
1136
1137 // =======================================================================
1138 // function : SetUniform
1139 // purpose  : Specifies the value of the floating-point uniform 2D vector
1140 // =======================================================================
1141 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1142                                                    GLint                         theLocation,
1143                                                    const OpenGl_Vec2&            theValue)
1144 {
1145   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1146   {
1147     return Standard_False;
1148   }
1149
1150   theCtx->core20fwd->glUniform2fv (theLocation, 1, theValue);
1151   return Standard_True;
1152 }
1153
1154 // =======================================================================
1155 // function : SetUniform
1156 // purpose  : Specifies the value of the floating-point uniform 3D vector
1157 // =======================================================================
1158 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1159                                                    const GLchar*                 theName,
1160                                                    const OpenGl_Vec3&            theValue)
1161 {
1162   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
1163 }
1164
1165 // =======================================================================
1166 // function : SetUniform
1167 // purpose  : Specifies the value of the floating-point uniform 3D vector
1168 // =======================================================================
1169 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1170                                                    GLint                         theLocation,
1171                                                    const OpenGl_Vec3&            theValue)
1172 {
1173   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1174   {
1175     return Standard_False;
1176   }
1177
1178   theCtx->core20fwd->glUniform3fv (theLocation, 1, theValue);
1179   return Standard_True;
1180 }
1181
1182 // =======================================================================
1183 // function : SetUniform
1184 // purpose  : Specifies the value of the floating-point uniform 4D vector
1185 // =======================================================================
1186 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1187                                                    const GLchar*                 theName,
1188                                                    const OpenGl_Vec4&            theValue)
1189 {
1190   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
1191 }
1192
1193 // =======================================================================
1194 // function : SetUniform
1195 // purpose  : Specifies the value of the floating-point uniform 4D vector
1196 // =======================================================================
1197 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1198                                                    GLint                         theLocation,
1199                                                    const OpenGl_Vec4&            theValue)
1200 {
1201   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1202   {
1203     return Standard_False;
1204   }
1205
1206   theCtx->core20fwd->glUniform4fv (theLocation, 1, theValue);
1207   return Standard_True;
1208 }
1209
1210 // =======================================================================
1211 // function : SetUniform
1212 // purpose  : Specifies the value of the floating-point uniform 4x4 matrix
1213 // =======================================================================
1214 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1215                                                    const GLchar*                 theName,
1216                                                    const OpenGl_Mat4&            theValue,
1217                                                    GLboolean                     theTranspose)
1218 {
1219   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue, theTranspose);
1220 }
1221
1222 // =======================================================================
1223 // function : SetUniform
1224 // purpose  : Specifies the value of the floating-point uniform 4x4 matrix
1225 // =======================================================================
1226 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1227                                                    GLint                         theLocation,
1228                                                    const OpenGl_Mat4&            theValue,
1229                                                    GLboolean                     theTranspose)
1230 {
1231   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1232   {
1233     return Standard_False;
1234   }
1235
1236   theCtx->core20fwd->glUniformMatrix4fv (theLocation, 1, GL_FALSE, theTranspose ? theValue.Transposed() : theValue);
1237   return Standard_True;
1238 }
1239
1240 // =======================================================================
1241 // function : SetUniform
1242 // purpose  : Specifies the value of the floating-point uniform 4x4 matrix
1243 // =======================================================================
1244 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1245                                                    const GLchar*                 theName,
1246                                                    const OpenGl_Matrix&          theValue,
1247                                                    GLboolean                     theTranspose)
1248 {
1249   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue, theTranspose);
1250 }
1251
1252 // =======================================================================
1253 // function : SetUniform
1254 // purpose  : Specifies the value of the floating-point uniform 4x4 matrix
1255 // =======================================================================
1256 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1257                                                    GLint                         theLocation,
1258                                                    const OpenGl_Matrix&          theValue,
1259                                                    GLboolean                     theTranspose)
1260 {
1261   return SetUniform (theCtx, theLocation, OpenGl_Mat4::Map (*theValue.mat), theTranspose);
1262 }
1263
1264 // =======================================================================
1265 // function : SetUniform
1266 // purpose  : Specifies the value of the float uniform array
1267 // =======================================================================
1268 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1269                                                    GLint                         theLocation,
1270                                                    GLuint                        theCount,
1271                                                    const Standard_ShortReal*     theData)
1272 {
1273   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1274   {
1275     return Standard_False;
1276   }
1277
1278   theCtx->core20fwd->glUniform1fv (theLocation, theCount, theData);
1279   return Standard_True;
1280 }
1281
1282 // =======================================================================
1283 // function : SetUniform
1284 // purpose  : Specifies the value of the float2 uniform array
1285 // =======================================================================
1286 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1287                                                    GLint                         theLocation,
1288                                                    GLuint                        theCount,
1289                                                    const OpenGl_Vec2*            theData)
1290 {
1291   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1292   {
1293     return Standard_False;
1294   }
1295
1296   theCtx->core20fwd->glUniform2fv (theLocation, theCount, theData[0].GetData());
1297   return Standard_True;
1298 }
1299
1300 // =======================================================================
1301 // function : SetUniform
1302 // purpose  : Specifies the value of the float3 uniform array
1303 // =======================================================================
1304 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1305                                                    GLint                         theLocation,
1306                                                    GLuint                        theCount,
1307                                                    const OpenGl_Vec3*            theData)
1308 {
1309   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1310   {
1311     return Standard_False;
1312   }
1313
1314   theCtx->core20fwd->glUniform3fv (theLocation, theCount, theData[0].GetData());
1315   return Standard_True;
1316 }
1317
1318 // =======================================================================
1319 // function : SetUniform
1320 // purpose  : Specifies the value of the float4 uniform array
1321 // =======================================================================
1322 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1323                                                    GLint                         theLocation,
1324                                                    GLuint                        theCount,
1325                                                    const OpenGl_Vec4*            theData)
1326 {
1327   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1328   {
1329     return Standard_False;
1330   }
1331
1332   theCtx->core20fwd->glUniform4fv (theLocation, theCount, theData[0].GetData());
1333   return Standard_True;
1334 }
1335
1336 // =======================================================================
1337 // function : SetUniform
1338 // purpose  : Specifies the value of the integer uniform array
1339 // =======================================================================
1340 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1341                                                    GLint                         theLocation,
1342                                                    GLuint                        theCount,
1343                                                    const Standard_Integer*       theData)
1344 {
1345   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1346   {
1347     return Standard_False;
1348   }
1349
1350   theCtx->core20fwd->glUniform1iv (theLocation, theCount, theData);
1351   return Standard_True;
1352 }
1353
1354 // =======================================================================
1355 // function : SetUniform
1356 // purpose  : Specifies the value of the int2 uniform array
1357 // =======================================================================
1358 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1359                                                    GLint                         theLocation,
1360                                                    GLuint                        theCount,
1361                                                    const OpenGl_Vec2i*           theData)
1362 {
1363   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1364   {
1365     return Standard_False;
1366   }
1367
1368   theCtx->core20fwd->glUniform2iv (theLocation, theCount, theData[0].GetData());
1369   return Standard_True;
1370 }
1371
1372 // =======================================================================
1373 // function : SetUniform
1374 // purpose  : Specifies the value of the int3 uniform array
1375 // =======================================================================
1376 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1377                                                    GLint                         theLocation,
1378                                                    GLuint                        theCount,
1379                                                    const OpenGl_Vec3i*           theData)
1380 {
1381   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1382   {
1383     return Standard_False;
1384   }
1385
1386   theCtx->core20fwd->glUniform3iv (theLocation, theCount, theData[0].GetData());
1387   return Standard_True;
1388 }
1389
1390 // =======================================================================
1391 // function : SetUniform
1392 // purpose  : Specifies the value of the int4 uniform array
1393 // =======================================================================
1394 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1395                                                    GLint                         theLocation,
1396                                                    GLuint                        theCount,
1397                                                    const OpenGl_Vec4i*           theData)
1398 {
1399   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1400   {
1401     return Standard_False;
1402   }
1403
1404   theCtx->core20fwd->glUniform4iv (theLocation, theCount, theData[0].GetData());
1405   return Standard_True;
1406 }
1407
1408 // =======================================================================
1409 // function : SetSampler
1410 // purpose  : Specifies the value of the sampler uniform variable
1411 // =======================================================================
1412 Standard_Boolean OpenGl_ShaderProgram::SetSampler (const Handle(OpenGl_Context)& theCtx,
1413                                                    const GLchar*                 theName,
1414                                                    const Graphic3d_TextureUnit   theTextureUnit)
1415 {
1416   return SetSampler (theCtx, GetUniformLocation (theCtx, theName), theTextureUnit);
1417 }
1418
1419 // =======================================================================
1420 // function : SetSampler
1421 // purpose  : Specifies the value of the sampler uniform variable
1422 // =======================================================================
1423 Standard_Boolean OpenGl_ShaderProgram::SetSampler (const Handle(OpenGl_Context)& theCtx,
1424                                                    GLint                         theLocation,
1425                                                    const Graphic3d_TextureUnit   theTextureUnit)
1426 {
1427   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1428   {
1429     return Standard_False;
1430   }
1431
1432   theCtx->core20fwd->glUniform1i (theLocation, theTextureUnit);
1433   return Standard_True;
1434 }
1435
1436 // =======================================================================
1437 // function : Create
1438 // purpose  : Creates new empty shader program of specified type
1439 // =======================================================================
1440 Standard_Boolean OpenGl_ShaderProgram::Create (const Handle(OpenGl_Context)& theCtx)
1441 {
1442   if (myProgramID == NO_PROGRAM
1443    && theCtx->core20fwd != NULL)
1444   {
1445     myProgramID = theCtx->core20fwd->glCreateProgram();
1446   }
1447
1448   return myProgramID != NO_PROGRAM;
1449 }
1450
1451 // =======================================================================
1452 // function : Release
1453 // purpose  : Destroys shader program
1454 // =======================================================================
1455 void OpenGl_ShaderProgram::Release (OpenGl_Context* theCtx)
1456 {
1457   if (myProgramID == NO_PROGRAM)
1458   {
1459     return;
1460   }
1461
1462   Standard_ASSERT_RETURN (theCtx != NULL,
1463     "OpenGl_ShaderProgram destroyed without GL context! Possible GPU memory leakage...",);
1464
1465   for (OpenGl_ShaderList::Iterator anIter (myShaderObjects); anIter.More(); anIter.Next())
1466   {
1467     if (!anIter.Value().IsNull())
1468     {
1469       anIter.ChangeValue()->Release (theCtx);
1470       anIter.ChangeValue().Nullify();
1471     }
1472   }
1473
1474   if (theCtx->core20fwd != NULL
1475    && theCtx->IsValid())
1476   {
1477     theCtx->core20fwd->glDeleteProgram (myProgramID);
1478   }
1479
1480   myProgramID = NO_PROGRAM;
1481 }