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