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