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