49310907342ad8f92d6bcbefec44539bcba0a677
[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
28 IMPLEMENT_STANDARD_HANDLE (OpenGl_ShaderProgram, OpenGl_Resource)
29 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_ShaderProgram, OpenGl_Resource)
30
31 OpenGl_VariableSetterSelector OpenGl_ShaderProgram::mySetterSelector = OpenGl_VariableSetterSelector();
32
33 // Declare OCCT-specific OpenGL/GLSL shader variables
34 Standard_CString OpenGl_ShaderProgram::PredefinedKeywords[] =
35 {
36   "occModelWorldMatrix",                 // OpenGl_OCC_MODEL_WORLD_MATRIX
37   "occWorldViewMatrix",                  // OpenGl_OCC_WORLD_VIEW_MATRIX
38   "occProjectionMatrix",                 // OpenGl_OCC_PROJECTION_MATRIX
39   "occModelWorldMatrixInverse",          // OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE
40   "occWorldViewMatrixInverse",           // OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE
41   "occProjectionMatrixInverse",          // OpenGl_OCC_PROJECTION_MATRIX_INVERSE
42   "occModelWorldMatrixTranspose",        // OpenGl_OCC_MODEL_WORLD_MATRIX_TRANSPOSE
43   "occWorldViewMatrixTranspose",         // OpenGl_OCC_WORLD_VIEW_MATRIX_TRANSPOSE
44   "occProjectionMatrixTranspose",        // OpenGl_OCC_PROJECTION_MATRIX_TRANSPOSE
45   "occModelWorldMatrixInverseTranspose", // OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE_TRANSPOSE
46   "occWorldViewMatrixInverseTranspose",  // OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE_TRANSPOSE
47   "occProjectionMatrixInverseTranspose", // OpenGl_OCC_PROJECTION_MATRIX_INVERSE_TRANSPOSE
48
49   "occClipPlaneEquations", // OpenGl_OCC_CLIP_PLANE_EQUATIONS
50   "occClipPlaneSpaces",    // OpenGl_OCC_CLIP_PLANE_SPACES
51   "occClipPlaneCount",     // OpenGl_OCC_CLIP_PLANE_COUNT
52
53   "occLightSourcesCount",  // OpenGl_OCC_LIGHT_SOURCE_COUNT
54   "occLightSourcesTypes",  // OpenGl_OCC_LIGHT_SOURCE_TYPES
55   "occLightSources",       // OpenGl_OCC_LIGHT_SOURCE_PARAMS
56   "occLightAmbient",       // OpenGl_OCC_LIGHT_AMBIENT
57
58   "occActiveSampler",      // OpenGl_OCCT_ACTIVE_SAMPLER
59   "occTextureEnable",      // OpenGl_OCCT_TEXTURE_ENABLE
60   "occDistinguishingMode", // OpenGl_OCCT_DISTINGUISH_MODE
61   "occFrontMaterial",      // OpenGl_OCCT_FRONT_MATERIAL
62   "occBackMaterial"        // OpenGl_OCCT_BACK_MATERIAL
63
64 };
65
66 // =======================================================================
67 // function : OpenGl_VariableSetterSelector
68 // purpose  : Creates new variable setter selector
69 // =======================================================================
70 OpenGl_VariableSetterSelector::OpenGl_VariableSetterSelector()
71 {
72   // Note: Add new variable setters here
73   mySetterList = OpenGl_HashMapInitializer::CreateListOf<size_t, OpenGl_SetterInterface*>
74     (Graphic3d_UniformValueTypeID<int>::ID,          new OpenGl_VariableSetter<int>())
75     (Graphic3d_UniformValueTypeID<float>::ID,        new OpenGl_VariableSetter<float>())
76     (Graphic3d_UniformValueTypeID<OpenGl_Vec2>::ID,  new OpenGl_VariableSetter<OpenGl_Vec2>())
77     (Graphic3d_UniformValueTypeID<OpenGl_Vec3>::ID,  new OpenGl_VariableSetter<OpenGl_Vec3>())
78     (Graphic3d_UniformValueTypeID<OpenGl_Vec4>::ID,  new OpenGl_VariableSetter<OpenGl_Vec4>())
79     (Graphic3d_UniformValueTypeID<OpenGl_Vec2i>::ID, new OpenGl_VariableSetter<OpenGl_Vec2i>())
80     (Graphic3d_UniformValueTypeID<OpenGl_Vec3i>::ID, new OpenGl_VariableSetter<OpenGl_Vec3i>())
81     (Graphic3d_UniformValueTypeID<OpenGl_Vec4i>::ID, new OpenGl_VariableSetter<OpenGl_Vec4i>());
82 }
83
84 // =======================================================================
85 // function : ~OpenGl_VariableSetterSelector
86 // purpose  : Releases memory resources of variable setter selector
87 // =======================================================================
88 OpenGl_VariableSetterSelector::~OpenGl_VariableSetterSelector()
89 {
90   for (OpenGl_SetterList::Iterator anIt (mySetterList); anIt.More(); anIt.Next())
91   {
92     delete anIt.Value();
93   }
94
95   mySetterList.Clear();
96 }
97
98 // =======================================================================
99 // function : Set
100 // purpose  : Sets generic variable to specified shader program
101 // =======================================================================
102 void OpenGl_VariableSetterSelector::Set (const Handle(OpenGl_Context)&           theCtx,
103                                          const Handle(Graphic3d_ShaderVariable)& theVariable,
104                                          OpenGl_ShaderProgram*                   theProgram) const
105 {
106   Standard_ASSERT_RETURN (mySetterList.IsBound (theVariable->Value()->TypeID()),
107     "The type of user-defined uniform variable is not supported...", );
108
109   mySetterList.Find (theVariable->Value()->TypeID())->Set (theCtx, theVariable, theProgram);
110 }
111
112 // =======================================================================
113 // function : OpenGl_ShaderProgram
114 // purpose  : Creates uninitialized shader program
115 // =======================================================================
116 OpenGl_ShaderProgram::OpenGl_ShaderProgram (const Handle(Graphic3d_ShaderProgram)& theProxy)
117 : myProgramID (NO_PROGRAM),
118   myProxy     (theProxy),
119   myShareCount(1)
120 {
121   memset (myCurrentState, 0, sizeof (myCurrentState));
122   for (GLint aVar = 0; aVar < OpenGl_OCCT_NUMBER_OF_STATE_VARIABLES; ++aVar)
123   {
124     myStateLocations[aVar] = INVALID_LOCATION;
125   }
126 }
127
128 // =======================================================================
129 // function : Initialize
130 // purpose  : Initializes program object with the list of shader objects
131 // =======================================================================
132 Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)&     theCtx,
133                                                    const Graphic3d_ShaderObjectList& theShaders)
134 {
135   if (theCtx.IsNull() || !Create (theCtx))
136   {
137     return Standard_False;
138   }
139
140   OSD_File aDeclFile     (Graphic3d_ShaderProgram::ShadersFolder() + "/Declarations.glsl");
141   OSD_File aDeclImplFile (Graphic3d_ShaderProgram::ShadersFolder() + "/DeclarationsImpl.glsl");
142   if (!aDeclFile.Exists()
143    || !aDeclImplFile.Exists())
144   {
145     const TCollection_ExtendedString aMsg = "Error! Failed to load OCCT shader declarations file";
146     theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
147                          GL_DEBUG_TYPE_ERROR_ARB,
148                          0,
149                          GL_DEBUG_SEVERITY_HIGH_ARB,
150                          aMsg);
151     return Standard_False;
152   }
153
154   TCollection_AsciiString aDeclarations;
155   aDeclFile.Open (OSD_ReadOnly, OSD_Protection());
156   aDeclFile.Read (aDeclarations, (int)aDeclFile.Size());
157   aDeclFile.Close();
158
159   TCollection_AsciiString aDeclImpl;
160   aDeclImplFile.Open (OSD_ReadOnly, OSD_Protection());
161   aDeclImplFile.Read (aDeclImpl, (int)aDeclImplFile.Size());
162   aDeclImplFile.Close();
163   aDeclarations += aDeclImpl;
164
165   for (Graphic3d_ShaderObjectList::Iterator anIter (theShaders);
166        anIter.More(); anIter.Next())
167   {
168     if (!anIter.Value()->IsDone())
169     {
170       const TCollection_ExtendedString aMsg = "Error! Failed to get shader source";
171       theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
172                            GL_DEBUG_TYPE_ERROR_ARB,
173                            0,
174                            GL_DEBUG_SEVERITY_HIGH_ARB,
175                            aMsg);
176       return Standard_False;
177     }
178
179     Handle(OpenGl_ShaderObject) aShader;
180
181     // Note: Add support of other shader types here
182     switch (anIter.Value()->Type())
183     {
184       case Graphic3d_TOS_VERTEX:
185         aShader = new OpenGl_ShaderObject (GL_VERTEX_SHADER);
186         break;
187       case Graphic3d_TOS_FRAGMENT:
188         aShader = new OpenGl_ShaderObject (GL_FRAGMENT_SHADER);
189         break;
190     }
191
192     // Is unsupported shader type?
193     if (aShader.IsNull())
194     {
195       TCollection_ExtendedString aMsg = "Error! Unsupported shader type";
196       theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
197                            GL_DEBUG_TYPE_ERROR_ARB,
198                            0,
199                            GL_DEBUG_SEVERITY_HIGH_ARB,
200                            aMsg);
201       return Standard_False;
202     }
203
204     if (!aShader->Create (theCtx))
205     {
206       aShader->Release (theCtx.operator->());
207       return Standard_False;
208     }
209
210     TCollection_AsciiString aSource = aDeclarations + anIter.Value()->Source();
211     if (anIter.Value()->Type() == Graphic3d_TOS_VERTEX)
212     {
213       aSource = TCollection_AsciiString ("#define VERTEX_SHADER\n") + aSource;
214     }
215
216     if (!aShader->LoadSource (theCtx, aSource))
217     {
218       const TCollection_ExtendedString aMsg = "Error! Failed to set shader source";
219       theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
220                            GL_DEBUG_TYPE_ERROR_ARB,
221                            0,
222                            GL_DEBUG_SEVERITY_HIGH_ARB,
223                            aMsg);
224       aShader->Release (theCtx.operator->());
225       return Standard_False;
226     }
227
228     if (!aShader->Compile (theCtx))
229     {
230       TCollection_AsciiString aLog;
231       aShader->FetchInfoLog (theCtx, aLog);
232       if (aLog.IsEmpty())
233       {
234         aLog = "Compilation log is empty.";
235       }
236       theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
237                            GL_DEBUG_TYPE_ERROR_ARB,
238                            0,
239                            GL_DEBUG_SEVERITY_HIGH_ARB,
240                            TCollection_ExtendedString ("Failed to compile shader object. Compilation log:\n") + aLog);
241       aShader->Release (theCtx.operator->());
242       return Standard_False;
243     }
244     else if (theCtx->caps->glslWarnings)
245     {
246       TCollection_AsciiString aLog;
247       aShader->FetchInfoLog (theCtx, aLog);
248       if (!aLog.IsEmpty()
249        && !aLog.IsEqual ("No errors.\n"))
250       {
251         theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
252                              GL_DEBUG_TYPE_PORTABILITY_ARB,
253                              0,
254                              GL_DEBUG_SEVERITY_LOW_ARB,
255                              TCollection_ExtendedString ("Shader compilation log:\n") + aLog);
256       }
257     }
258
259     if (!AttachShader (theCtx, aShader))
260     {
261       aShader->Release (theCtx.operator->());
262       return Standard_False;
263     }
264   }
265
266   // bind locations for pre-defined Vertex Attributes
267   SetAttributeName (theCtx, Graphic3d_TOA_POS,   "occVertex");
268   SetAttributeName (theCtx, Graphic3d_TOA_NORM,  "occNormal");
269   SetAttributeName (theCtx, Graphic3d_TOA_UV,    "occTexCoord");
270   SetAttributeName (theCtx, Graphic3d_TOA_COLOR, "occColor");
271
272   if (!Link (theCtx))
273   {
274     TCollection_AsciiString aLog;
275     FetchInfoLog (theCtx, aLog);
276     if (aLog.IsEmpty())
277     {
278       aLog = "Linker log is empty.";
279     }
280     theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
281                          GL_DEBUG_TYPE_ERROR_ARB,
282                          0,
283                          GL_DEBUG_SEVERITY_HIGH_ARB,
284                          TCollection_ExtendedString ("Failed to link program object! Linker log:\n") + aLog);
285     return Standard_False;
286   }
287   else if (theCtx->caps->glslWarnings)
288   {
289     TCollection_AsciiString aLog;
290     FetchInfoLog (theCtx, aLog);
291     if (!aLog.IsEmpty()
292      && !aLog.IsEqual ("No errors.\n"))
293     {
294       theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
295                            GL_DEBUG_TYPE_PORTABILITY_ARB,
296                            0,
297                            GL_DEBUG_SEVERITY_LOW_ARB,
298                            TCollection_ExtendedString ("GLSL linker log:\n") + aLog);
299     }
300   }
301
302   return Standard_True;
303 }
304
305 // =======================================================================
306 // function : ~OpenGl_ShaderProgram
307 // purpose  : Releases resources of shader program
308 // =======================================================================
309 OpenGl_ShaderProgram::~OpenGl_ShaderProgram()
310 {
311   Release (NULL);
312 }
313
314 // =======================================================================
315 // function : AttachShader
316 // purpose  : Attaches shader object to the program object
317 // =======================================================================
318 Standard_Boolean OpenGl_ShaderProgram::AttachShader (const Handle(OpenGl_Context)&      theCtx,
319                                                      const Handle(OpenGl_ShaderObject)& theShader)
320 {
321   if (myProgramID == NO_PROGRAM || theShader.IsNull())
322   {
323     return Standard_False;
324   }
325
326   for (OpenGl_ShaderList::Iterator anIter (myShaderObjects); anIter.More(); anIter.Next())
327   {
328     if (theShader == anIter.Value())
329     {
330       return Standard_False;
331     }
332   }
333
334   myShaderObjects.Append (theShader);
335   theCtx->core20->glAttachShader (myProgramID, theShader->myShaderID);
336   return Standard_True;
337 }
338
339 // =======================================================================
340 // function : DetachShader
341 // purpose  : Detaches shader object to the program object
342 // =======================================================================
343 Standard_Boolean OpenGl_ShaderProgram::DetachShader (const Handle(OpenGl_Context)&      theCtx,
344                                                      const Handle(OpenGl_ShaderObject)& theShader)
345 {
346   if (myProgramID == NO_PROGRAM
347    || theShader.IsNull())
348   {
349     return Standard_False;
350   }
351
352   OpenGl_ShaderList::Iterator anIter (myShaderObjects);
353   while (anIter.More())
354   {
355     if (theShader == anIter.Value())
356     {
357       myShaderObjects.Remove (anIter);
358       break;
359     }
360
361     anIter.Next();
362   }
363
364   if (!anIter.More())
365   {
366     return Standard_False;
367   }
368
369   theCtx->core20->glDetachShader (myProgramID, theShader->myShaderID);
370   return Standard_True;
371 }
372
373 // =======================================================================
374 // function : Link
375 // purpose  : Links the program object
376 // =======================================================================
377 Standard_Boolean OpenGl_ShaderProgram::Link (const Handle(OpenGl_Context)& theCtx)
378 {
379   if (myProgramID == NO_PROGRAM)
380   {
381     return Standard_False;
382   }
383
384   GLint aStatus = GL_FALSE;
385   theCtx->core20->glLinkProgram (myProgramID);
386   theCtx->core20->glGetProgramiv (myProgramID, GL_LINK_STATUS, &aStatus);
387   if (aStatus == GL_FALSE)
388   {
389     return Standard_False;
390   }
391
392   for (GLint aVar = 0; aVar < OpenGl_OCCT_NUMBER_OF_STATE_VARIABLES; ++aVar)
393   {
394     myStateLocations[aVar] = GetUniformLocation (theCtx, PredefinedKeywords[aVar]);
395   }
396   return Standard_True;
397 }
398
399 // =======================================================================
400 // function : FetchInfoLog
401 // purpose  : Fetches information log of the last link operation
402 // =======================================================================
403 Standard_Boolean OpenGl_ShaderProgram::FetchInfoLog (const Handle(OpenGl_Context)& theCtx,
404                                                      TCollection_AsciiString&      theOutput)
405 {
406   if (myProgramID == NO_PROGRAM)
407   {
408     return Standard_False;
409   }
410
411   GLint aLength = 0;
412   theCtx->core20->glGetProgramiv (myProgramID, GL_INFO_LOG_LENGTH, &aLength);
413   if (aLength > 0)
414   {
415     GLchar* aLog = (GLchar*) alloca (aLength);
416     memset (aLog, 0, aLength);
417     theCtx->core20->glGetProgramInfoLog (myProgramID, aLength, NULL, aLog);
418     theOutput = aLog;
419   }
420   return Standard_True;
421 }
422
423 // =======================================================================
424 // function : ApplyVariables
425 // purpose  : Fetches uniform variables from proxy shader program
426 // =======================================================================
427 Standard_Boolean OpenGl_ShaderProgram::ApplyVariables(const Handle(OpenGl_Context)& theCtx)
428 {
429   if (myProxy.IsNull() || myProxy->Variables().IsEmpty())
430   {
431     return Standard_False;
432   }
433
434   for (Graphic3d_ShaderVariableList::Iterator anIter (myProxy->Variables()); anIter.More(); anIter.Next())
435   {
436     mySetterSelector.Set (theCtx, anIter.Value(), this);
437   }
438
439   myProxy->ClearVariables();
440   return Standard_True;
441 }
442
443 // =======================================================================
444 // function : ActiveState
445 // purpose  : Returns index of last modification for specified state type
446 // =======================================================================
447 Standard_Size OpenGl_ShaderProgram::ActiveState (const OpenGl_UniformStateType theType) const
448 {
449   if (theType < MaxStateTypes)
450   {
451     return myCurrentState[theType];
452   }
453   return 0;
454 }
455
456 // =======================================================================
457 // function : UpdateState
458 // purpose  : Updates index of last modification for specified state type
459 // =======================================================================
460 void OpenGl_ShaderProgram::UpdateState (const OpenGl_UniformStateType theType,
461                                         const Standard_Size           theIndex)
462 {
463   if (theType < MaxStateTypes)
464   {
465     myCurrentState[theType] = theIndex;
466   }
467 }
468
469 // =======================================================================
470 // function : GetUniformLocation
471 // purpose  : Returns location (index) of the specific uniform variable
472 // =======================================================================
473 GLint OpenGl_ShaderProgram::GetUniformLocation (const Handle(OpenGl_Context)& theCtx,
474                                                 const GLchar*                 theName) const
475 {
476   return myProgramID != NO_PROGRAM
477        ? theCtx->core20->glGetUniformLocation (myProgramID, theName)
478        : INVALID_LOCATION;
479 }
480
481 // =======================================================================
482 // function : GetAttributeLocation
483 // purpose  : Returns location (index) of the generic vertex attribute
484 // =======================================================================
485 GLint OpenGl_ShaderProgram::GetAttributeLocation (const Handle(OpenGl_Context)& theCtx,
486                                                   const GLchar*                 theName) const
487 {
488   return myProgramID != NO_PROGRAM
489        ? theCtx->core20->glGetAttribLocation (myProgramID, theName)
490        : INVALID_LOCATION;
491 }
492
493 // =======================================================================
494 // function : GetStateLocation
495 // purpose  : Returns location of the OCCT state uniform variable
496 // =======================================================================
497 GLint OpenGl_ShaderProgram::GetStateLocation (const GLuint theVariable) const
498 {
499   if (theVariable < OpenGl_OCCT_NUMBER_OF_STATE_VARIABLES)
500   {
501     return myStateLocations[theVariable];
502   }
503   return INVALID_LOCATION;
504 }
505
506 // =======================================================================
507 // function : GetUniform
508 // purpose  : Returns the value of the integer uniform variable
509 // =======================================================================
510 Standard_Boolean OpenGl_ShaderProgram::GetUniform (const Handle(OpenGl_Context)& theCtx,
511                                                    const GLchar*                 theName,
512                                                    OpenGl_Vec4i&                 theValue) const
513 {
514   return GetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
515 }
516
517 // =======================================================================
518 // function : GetUniform
519 // purpose  : Returns the value of the integer uniform variable
520 // =======================================================================
521 Standard_Boolean OpenGl_ShaderProgram::GetUniform (const Handle(OpenGl_Context)& theCtx,
522                                                    GLint                         theLocation,
523                                                    OpenGl_Vec4i&                 theValue) const
524 {
525   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
526   {
527     return Standard_False;
528   }
529
530   theCtx->core20->glGetUniformiv (myProgramID, theLocation, theValue);
531   return Standard_True;
532 }
533
534 // =======================================================================
535 // function : GetUniform
536 // purpose  : Returns the value of the floating-point uniform variable
537 // =======================================================================
538 Standard_Boolean OpenGl_ShaderProgram::GetUniform (const Handle(OpenGl_Context)& theCtx,
539                                                    const GLchar*                 theName,
540                                                    OpenGl_Vec4&                  theValue) const
541 {
542   return GetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
543 }
544
545 // =======================================================================
546 // function : GetUniform
547 // purpose  : Returns the value of the floating-point uniform variable
548 // =======================================================================
549 Standard_Boolean OpenGl_ShaderProgram::GetUniform (const Handle(OpenGl_Context)& theCtx,
550                                                    GLint                         theLocation,
551                                                    OpenGl_Vec4&                  theValue) const
552 {
553   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
554   {
555     return Standard_False;
556   }
557
558   theCtx->core20->glGetUniformfv (myProgramID, theLocation, theValue);
559   return Standard_True;
560 }
561
562 // =======================================================================
563 // function : GetAttribute
564 // purpose  : Returns the integer vertex attribute
565 // =======================================================================
566 Standard_Boolean OpenGl_ShaderProgram::GetAttribute (const Handle(OpenGl_Context)& theCtx,
567                                                      const GLchar*                 theName,
568                                                      OpenGl_Vec4i&                 theValue) const
569 {
570   return GetAttribute (theCtx, GetAttributeLocation (theCtx, theName), theValue);
571 }
572
573 // =======================================================================
574 // function : GetAttribute
575 // purpose  : Returns the integer vertex attribute
576 // =======================================================================
577 Standard_Boolean OpenGl_ShaderProgram::GetAttribute (const Handle(OpenGl_Context)& theCtx,
578                                                      GLint                         theIndex,
579                                                      OpenGl_Vec4i&                 theValue) const
580 {
581   if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION)
582   {
583     return Standard_False;
584   }
585
586   theCtx->core20->glGetVertexAttribiv (theIndex, GL_CURRENT_VERTEX_ATTRIB, theValue);
587   return Standard_True;
588 }
589
590 // =======================================================================
591 // function : GetAttribute
592 // purpose  : Returns the floating-point vertex attribute
593 // =======================================================================
594 Standard_Boolean OpenGl_ShaderProgram::GetAttribute (const Handle(OpenGl_Context)& theCtx,
595                                                      const GLchar*                 theName,
596                                                      OpenGl_Vec4&                  theValue) const
597 {
598   return GetAttribute (theCtx, GetAttributeLocation (theCtx, theName), theValue);
599 }
600
601 // =======================================================================
602 // function : GetAttribute
603 // purpose  : Returns the floating-point vertex attribute
604 // =======================================================================
605 Standard_Boolean OpenGl_ShaderProgram::GetAttribute (const Handle(OpenGl_Context)& theCtx,
606                                                      GLint                         theIndex,
607                                                      OpenGl_Vec4&                  theValue) const
608 {
609   if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION)
610   {
611     return Standard_False;
612   }
613
614   theCtx->core20->glGetVertexAttribfv (theIndex, GL_CURRENT_VERTEX_ATTRIB, theValue);
615   return Standard_True;
616 }
617
618 // =======================================================================
619 // function : SetAttributeName
620 // purpose  :
621 // =======================================================================
622 Standard_Boolean OpenGl_ShaderProgram::SetAttributeName (const Handle(OpenGl_Context)& theCtx,
623                                                          GLint                         theIndex,
624                                                          const GLchar*                 theName)
625 {
626   theCtx->core20fwd->glBindAttribLocation (myProgramID, theIndex, theName);
627   return Standard_True;
628 }
629   
630 // =======================================================================
631 // function : SetAttribute
632 // purpose  :
633 // =======================================================================
634 Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
635                                                      const GLchar*                 theName,
636                                                      GLfloat                       theValue)
637 {
638   return SetAttribute (theCtx, GetAttributeLocation (theCtx, theName), theValue);
639 }
640
641 // =======================================================================
642 // function : SetAttribute
643 // purpose  :
644 // =======================================================================
645 Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
646                                                      GLint                         theIndex,
647                                                      GLfloat                       theValue)
648 {
649   if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION)
650   {
651     return Standard_False;
652   }
653
654   theCtx->core20fwd->glVertexAttrib1f (theIndex, theValue);
655   return Standard_True;
656 }
657
658 // =======================================================================
659 // function : SetAttribute
660 // purpose  :
661 // =======================================================================
662 Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
663                                                      const GLchar*                 theName,
664                                                      const OpenGl_Vec2&            theValue)
665 {
666   return SetAttribute (theCtx, GetAttributeLocation (theCtx, theName), theValue);
667 }
668
669 // =======================================================================
670 // function : SetAttribute
671 // purpose  :
672 // =======================================================================
673 Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
674                                                      GLint                         theIndex,
675                                                      const OpenGl_Vec2&            theValue)
676 {
677   if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION)
678   {
679     return Standard_False;
680   }
681
682   theCtx->core20fwd->glVertexAttrib2fv (theIndex, theValue);
683   return Standard_True;
684 }
685
686 // =======================================================================
687 // function : SetAttribute
688 // purpose  :
689 // =======================================================================
690 Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
691                                                      const GLchar*                 theName,
692                                                      const OpenGl_Vec3&            theValue)
693 {
694   return SetAttribute (theCtx, GetAttributeLocation (theCtx, theName), theValue);
695 }
696
697 // =======================================================================
698 // function : SetAttribute
699 // purpose  :
700 // =======================================================================
701 Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
702                                                      GLint                         theIndex,
703                                                      const OpenGl_Vec3&            theValue)
704 {
705   if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION)
706   {
707     return Standard_False;
708   }
709
710   theCtx->core20fwd->glVertexAttrib3fv (theIndex, theValue);
711   return Standard_True;
712 }
713
714 // =======================================================================
715 // function : SetAttribute
716 // purpose  :
717 // =======================================================================
718 Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
719                                                      const GLchar*                 theName,
720                                                      const OpenGl_Vec4&            theValue)
721 {
722   return SetAttribute (theCtx, GetAttributeLocation (theCtx, theName), theValue);
723 }
724
725 // =======================================================================
726 // function : SetAttribute
727 // purpose  :
728 // =======================================================================
729 Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
730                                                      GLint                         theIndex,
731                                                      const OpenGl_Vec4&            theValue)
732 {
733   if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION)
734   {
735     return Standard_False;
736   }
737
738   theCtx->core20fwd->glVertexAttrib4fv (theIndex, theValue);
739   return Standard_True;
740 }
741
742 // =======================================================================
743 // function : SetUniform
744 // purpose  : Specifies the value of the integer uniform variable
745 // =======================================================================
746 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
747                                                    const GLchar*                 theName,
748                                                    GLint                         theValue)
749 {
750   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
751 }
752
753 // =======================================================================
754 // function : SetUniform
755 // purpose  : Specifies the value of the integer uniform variable
756 // =======================================================================
757 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
758                                                    GLint                         theLocation,
759                                                    GLint                         theValue)
760 {
761   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
762   {
763     return Standard_False;
764   }
765
766   theCtx->core20->glUniform1i (theLocation, theValue);
767   return Standard_True;
768 }
769
770 // =======================================================================
771 // function : SetUniform
772 // purpose  : Specifies the value of the floating-point uniform variable
773 // =======================================================================
774 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
775                                                    const GLchar*                 theName,
776                                                    GLfloat                       theValue)
777 {
778   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
779 }
780
781 // =======================================================================
782 // function : SetUniform
783 // purpose  : Specifies the value of the floating-point uniform variable
784 // =======================================================================
785 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
786                                                    GLint                         theLocation,
787                                                    GLfloat                       theValue)
788 {
789   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
790   {
791     return Standard_False;
792   }
793
794   theCtx->core20->glUniform1f (theLocation, theValue);
795   return Standard_True;
796 }
797
798 // =======================================================================
799 // function : SetUniform
800 // purpose  : Specifies the value of the integer uniform 2D vector
801 // =======================================================================
802 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
803                                                    const GLchar*                 theName,
804                                                    const OpenGl_Vec2i&           theValue)
805 {
806   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
807 }
808
809 // =======================================================================
810 // function : SetUniform
811 // purpose  : Specifies the value of the integer uniform 2D vector
812 // =======================================================================
813 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
814                                                    GLint                         theLocation,
815                                                    const OpenGl_Vec2i&           theValue)
816 {
817   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
818   {
819     return Standard_False;
820   }
821
822   theCtx->core20->glUniform2iv (theLocation, 1, theValue);
823   return Standard_True;
824 }
825
826 // =======================================================================
827 // function : SetUniform
828 // purpose  : Specifies the value of the integer uniform 3D vector
829 // =======================================================================
830 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
831                                                    const GLchar*                 theName,
832                                                    const OpenGl_Vec3i&           theValue)
833 {
834   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
835 }
836
837 // =======================================================================
838 // function : SetUniform
839 // purpose  : Specifies the value of the integer uniform 3D vector
840 // =======================================================================
841 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
842                                                    GLint                         theLocation,
843                                                    const OpenGl_Vec3i&           theValue)
844 {
845   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
846   {
847     return Standard_False;
848   }
849
850   theCtx->core20->glUniform3iv (theLocation, 1, theValue);
851   return Standard_True;
852 }
853
854 // =======================================================================
855 // function : SetUniform
856 // purpose  : Specifies the value of the integer uniform 4D vector
857 // =======================================================================
858 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
859                                                    const GLchar*                 theName,
860                                                    const OpenGl_Vec4i&           theValue)
861 {
862   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
863 }
864
865 // =======================================================================
866 // function : SetUniform
867 // purpose  : Specifies the value of the integer uniform 4D vector
868 // =======================================================================
869 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
870                                                    GLint                         theLocation,
871                                                    const OpenGl_Vec4i&           theValue)
872 {
873   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
874   {
875     return Standard_False;
876   }
877
878   theCtx->core20->glUniform4iv (theLocation, 1, theValue);
879   return Standard_True;
880 }
881
882 // =======================================================================
883 // function : SetUniform
884 // purpose  : Specifies the value of the floating-point uniform 2D vector
885 // =======================================================================
886 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
887                                                    const GLchar*                 theName,
888                                                    const OpenGl_Vec2&            theValue)
889 {
890   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
891 }
892
893 // =======================================================================
894 // function : SetUniform
895 // purpose  : Specifies the value of the floating-point uniform 2D vector
896 // =======================================================================
897 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
898                                                    GLint                         theLocation,
899                                                    const OpenGl_Vec2&            theValue)
900 {
901   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
902   {
903     return Standard_False;
904   }
905
906   theCtx->core20->glUniform2fv (theLocation, 1, theValue);
907   return Standard_True;
908 }
909
910 // =======================================================================
911 // function : SetUniform
912 // purpose  : Specifies the value of the floating-point uniform 3D vector
913 // =======================================================================
914 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
915                                                    const GLchar*                 theName,
916                                                    const OpenGl_Vec3&            theValue)
917 {
918   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
919 }
920
921 // =======================================================================
922 // function : SetUniform
923 // purpose  : Specifies the value of the floating-point uniform 3D vector
924 // =======================================================================
925 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
926                                                    GLint                         theLocation,
927                                                    const OpenGl_Vec3&            theValue)
928 {
929   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
930   {
931     return Standard_False;
932   }
933
934   theCtx->core20->glUniform3fv (theLocation, 1, theValue);
935   return Standard_True;
936 }
937
938 // =======================================================================
939 // function : SetUniform
940 // purpose  : Specifies the value of the floating-point uniform 4D vector
941 // =======================================================================
942 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
943                                                    const GLchar*                 theName,
944                                                    const OpenGl_Vec4&            theValue)
945 {
946   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
947 }
948
949 // =======================================================================
950 // function : SetUniform
951 // purpose  : Specifies the value of the floating-point uniform 4D vector
952 // =======================================================================
953 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
954                                                    GLint                         theLocation,
955                                                    const OpenGl_Vec4&            theValue)
956 {
957   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
958   {
959     return Standard_False;
960   }
961
962   theCtx->core20->glUniform4fv (theLocation, 1, theValue);
963   return Standard_True;
964 }
965
966 // =======================================================================
967 // function : SetUniform
968 // purpose  : Specifies the value of the floating-point uniform 4x4 matrix
969 // =======================================================================
970 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
971                                                    const GLchar*                 theName,
972                                                    const OpenGl_Matrix&          theValue,
973                                                    GLboolean                     theTranspose)
974 {
975   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue, theTranspose);
976 }
977
978 // =======================================================================
979 // function : SetUniform
980 // purpose  : Specifies the value of the floating-point uniform 4x4 matrix
981 // =======================================================================
982 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
983                                                    GLint                         theLocation,
984                                                    const OpenGl_Matrix&          theValue,
985                                                    GLboolean                     theTranspose)
986 {
987   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
988   {
989     return Standard_False;
990   }
991
992   theCtx->core20->glUniformMatrix4fv (theLocation, 1, theTranspose, *theValue.mat);
993   return Standard_True;
994 }
995
996 // =======================================================================
997 // function : SetUniform
998 // purpose  : Specifies the value of the floating-point uniform 4x4 matrix
999 // =======================================================================
1000 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1001                                                    const GLchar*                 theName,
1002                                                    const Tmatrix3&               theValue,
1003                                                    GLboolean                     theTranspose)
1004 {
1005   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue, theTranspose);
1006 }
1007
1008 // =======================================================================
1009 // function : SetUniform
1010 // purpose  : Specifies the value of the floating-point uniform 4x4 matrix
1011 // =======================================================================
1012 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1013                                                    GLint                         theLocation,
1014                                                    const Tmatrix3&               theValue,
1015                                                    GLboolean                     theTranspose)
1016 {
1017   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1018   {
1019     return Standard_False;
1020   }
1021
1022   theCtx->core20->glUniformMatrix4fv (theLocation, 1, theTranspose, *theValue);
1023   return Standard_True;
1024 }
1025
1026 // =======================================================================
1027 // function : SetUniform
1028 // purpose  : Specifies the value of the float uniform array
1029 // =======================================================================
1030 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1031                                                    GLint                         theLocation,
1032                                                    GLuint                        theCount,
1033                                                    const Standard_ShortReal*     theData)
1034 {
1035   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1036   {
1037     return Standard_False;
1038   }
1039
1040   theCtx->core20->glUniform1fv (theLocation, theCount, theData);
1041   return Standard_True;
1042 }
1043
1044 // =======================================================================
1045 // function : SetUniform
1046 // purpose  : Specifies the value of the float2 uniform array
1047 // =======================================================================
1048 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1049                                                    GLint                         theLocation,
1050                                                    GLuint                        theCount,
1051                                                    const OpenGl_Vec2*            theData)
1052 {
1053   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1054   {
1055     return Standard_False;
1056   }
1057
1058   theCtx->core20->glUniform2fv (theLocation, theCount, theData[0].GetData());
1059   return Standard_True;
1060 }
1061
1062 // =======================================================================
1063 // function : SetUniform
1064 // purpose  : Specifies the value of the float3 uniform array
1065 // =======================================================================
1066 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1067                                                    GLint                         theLocation,
1068                                                    GLuint                        theCount,
1069                                                    const OpenGl_Vec3*            theData)
1070 {
1071   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1072   {
1073     return Standard_False;
1074   }
1075
1076   theCtx->core20->glUniform3fv (theLocation, theCount, theData[0].GetData());
1077   return Standard_True;
1078 }
1079
1080 // =======================================================================
1081 // function : SetUniform
1082 // purpose  : Specifies the value of the float4 uniform array
1083 // =======================================================================
1084 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1085                                                    GLint                         theLocation,
1086                                                    GLuint                        theCount,
1087                                                    const OpenGl_Vec4*            theData)
1088 {
1089   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1090   {
1091     return Standard_False;
1092   }
1093
1094   theCtx->core20->glUniform4fv (theLocation, theCount, theData[0].GetData());
1095   return Standard_True;
1096 }
1097
1098 // =======================================================================
1099 // function : SetUniform
1100 // purpose  : Specifies the value of the integer uniform array
1101 // =======================================================================
1102 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1103                                                    GLint                         theLocation,
1104                                                    GLuint                        theCount,
1105                                                    const Standard_Integer*       theData)
1106 {
1107   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1108   {
1109     return Standard_False;
1110   }
1111
1112   theCtx->core20->glUniform1iv (theLocation, theCount, theData);
1113   return Standard_True;
1114 }
1115
1116 // =======================================================================
1117 // function : SetUniform
1118 // purpose  : Specifies the value of the int2 uniform array
1119 // =======================================================================
1120 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1121                                                    GLint                         theLocation,
1122                                                    GLuint                        theCount,
1123                                                    const OpenGl_Vec2i*           theData)
1124 {
1125   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1126   {
1127     return Standard_False;
1128   }
1129
1130   theCtx->core20->glUniform2iv (theLocation, theCount, theData[0].GetData());
1131   return Standard_True;
1132 }
1133
1134 // =======================================================================
1135 // function : SetUniform
1136 // purpose  : Specifies the value of the int3 uniform array
1137 // =======================================================================
1138 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1139                                                    GLint                         theLocation,
1140                                                    GLuint                        theCount,
1141                                                    const OpenGl_Vec3i*           theData)
1142 {
1143   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1144   {
1145     return Standard_False;
1146   }
1147
1148   theCtx->core20->glUniform3iv (theLocation, theCount, theData[0].GetData());
1149   return Standard_True;
1150 }
1151
1152 // =======================================================================
1153 // function : SetUniform
1154 // purpose  : Specifies the value of the int4 uniform array
1155 // =======================================================================
1156 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1157                                                    GLint                         theLocation,
1158                                                    GLuint                        theCount,
1159                                                    const OpenGl_Vec4i*           theData)
1160 {
1161   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1162   {
1163     return Standard_False;
1164   }
1165
1166   theCtx->core20->glUniform4iv (theLocation, theCount, theData[0].GetData());
1167   return Standard_True;
1168 }
1169
1170 // =======================================================================
1171 // function : SetSampler
1172 // purpose  : Specifies the value of the sampler uniform variable
1173 // =======================================================================
1174 Standard_Boolean OpenGl_ShaderProgram::SetSampler (const Handle(OpenGl_Context)& theCtx,
1175                                                    const GLchar*                 theName,
1176                                                    const GLenum                  theTextureUnit)
1177 {
1178   return SetSampler (theCtx, GetUniformLocation (theCtx, theName), theTextureUnit);
1179 }
1180
1181 // =======================================================================
1182 // function : SetSampler
1183 // purpose  : Specifies the value of the sampler uniform variable
1184 // =======================================================================
1185 Standard_Boolean OpenGl_ShaderProgram::SetSampler (const Handle(OpenGl_Context)& theCtx,
1186                                                    GLint                         theLocation,
1187                                                    const GLenum                  theTextureUnit)
1188 {
1189   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1190   {
1191     return Standard_False;
1192   }
1193
1194   theCtx->core20->glUniform1i (theLocation, theTextureUnit);
1195   return Standard_True;
1196 }
1197
1198 // =======================================================================
1199 // function : Create
1200 // purpose  : Creates new empty shader program of specified type
1201 // =======================================================================
1202 Standard_Boolean OpenGl_ShaderProgram::Create (const Handle(OpenGl_Context)& theCtx)
1203 {
1204   if (myProgramID == NO_PROGRAM
1205    && theCtx->core20 != NULL)
1206   {
1207     myProgramID = theCtx->core20->glCreateProgram();
1208   }
1209
1210   return myProgramID != NO_PROGRAM;
1211 }
1212
1213 // =======================================================================
1214 // function : Release
1215 // purpose  : Destroys shader program
1216 // =======================================================================
1217 void OpenGl_ShaderProgram::Release (OpenGl_Context* theCtx)
1218 {
1219   if (myProgramID == NO_PROGRAM)
1220   {
1221     return;
1222   }
1223
1224   Standard_ASSERT_RETURN (theCtx != NULL,
1225     "OpenGl_ShaderProgram destroyed without GL context! Possible GPU memory leakage...",);
1226
1227   for (OpenGl_ShaderList::Iterator anIter (myShaderObjects); anIter.More(); anIter.Next())
1228   {
1229     if (!anIter.Value().IsNull())
1230     {
1231       anIter.ChangeValue()->Release (theCtx);
1232       anIter.ChangeValue().Nullify();
1233     }
1234   }
1235
1236   if (theCtx->core20 != NULL
1237    && theCtx->IsValid())
1238   {
1239     theCtx->core20->glDeleteProgram (myProgramID);
1240   }
1241
1242   myProgramID = NO_PROGRAM;
1243 }