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