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