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