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