0030488: Visualization, Ray Tracing - empty error message on GLSL program compilation
[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>
25ef750e 27#include <OpenGl_ArbTexBindless.hxx>
30f0ad28 28
47e9c178 29#include <OpenGl_GlCore32.hxx>
30f0ad28 30
ee5befae 31#include "../Shaders/Shaders_DeclarationsImpl_glsl.pxx"
32#include "../Shaders/Shaders_Declarations_glsl.pxx"
33
7c65581d 34#ifdef _WIN32
35 #include <malloc.h> // for alloca()
36#endif
37
cc8cbabe 38IMPLEMENT_STANDARD_RTTIEXT(OpenGl_ShaderProgram, OpenGl_NamedResource)
92efcf78 39
30f0ad28 40OpenGl_VariableSetterSelector OpenGl_ShaderProgram::mySetterSelector = OpenGl_VariableSetterSelector();
41
42// Declare OCCT-specific OpenGL/GLSL shader variables
43Standard_CString OpenGl_ShaderProgram::PredefinedKeywords[] =
44{
12381341 45 "occModelWorldMatrix", // OpenGl_OCC_MODEL_WORLD_MATRIX
46 "occWorldViewMatrix", // OpenGl_OCC_WORLD_VIEW_MATRIX
47 "occProjectionMatrix", // OpenGl_OCC_PROJECTION_MATRIX
48 "occModelWorldMatrixInverse", // OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE
49 "occWorldViewMatrixInverse", // OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE
50 "occProjectionMatrixInverse", // OpenGl_OCC_PROJECTION_MATRIX_INVERSE
51 "occModelWorldMatrixTranspose", // OpenGl_OCC_MODEL_WORLD_MATRIX_TRANSPOSE
52 "occWorldViewMatrixTranspose", // OpenGl_OCC_WORLD_VIEW_MATRIX_TRANSPOSE
53 "occProjectionMatrixTranspose", // OpenGl_OCC_PROJECTION_MATRIX_TRANSPOSE
54 "occModelWorldMatrixInverseTranspose", // OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE_TRANSPOSE
55 "occWorldViewMatrixInverseTranspose", // OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE_TRANSPOSE
56 "occProjectionMatrixInverseTranspose", // OpenGl_OCC_PROJECTION_MATRIX_INVERSE_TRANSPOSE
57
58 "occClipPlaneEquations", // OpenGl_OCC_CLIP_PLANE_EQUATIONS
25c35042 59 "occClipPlaneChains", // OpenGl_OCC_CLIP_PLANE_CHAINS
5495fa7e 60 "occClipPlaneCount", // OpenGl_OCC_CLIP_PLANE_COUNT
12381341 61
62 "occLightSourcesCount", // OpenGl_OCC_LIGHT_SOURCE_COUNT
63 "occLightSourcesTypes", // OpenGl_OCC_LIGHT_SOURCE_TYPES
64 "occLightSources", // OpenGl_OCC_LIGHT_SOURCE_PARAMS
65 "occLightAmbient", // OpenGl_OCC_LIGHT_AMBIENT
66
12381341 67 "occTextureEnable", // OpenGl_OCCT_TEXTURE_ENABLE
68 "occDistinguishingMode", // OpenGl_OCCT_DISTINGUISH_MODE
69 "occFrontMaterial", // OpenGl_OCCT_FRONT_MATERIAL
8625ef7e 70 "occBackMaterial", // OpenGl_OCCT_BACK_MATERIAL
c40eb6b9 71 "occAlphaCutoff", // OpenGl_OCCT_ALPHA_CUTOFF
8625ef7e 72 "occColor", // OpenGl_OCCT_COLOR
73
a1073ae2 74 "occOitOutput", // OpenGl_OCCT_OIT_OUTPUT
75 "occOitDepthFactor", // OpenGl_OCCT_OIT_DEPTH_FACTOR
76
79f4f036 77 "occTexTrsf2d", // OpenGl_OCCT_TEXTURE_TRSF2D
8625ef7e 78 "occPointSize" // OpenGl_OCCT_POINT_SIZE
30f0ad28 79};
80
8e0a2b19 81namespace
82{
83 //! Convert Graphic3d_TypeOfShaderObject enumeration into OpenGL enumeration.
84 static GLenum shaderTypeToGl (Graphic3d_TypeOfShaderObject theType)
85 {
86 switch (theType)
87 {
88 case Graphic3d_TOS_VERTEX: return GL_VERTEX_SHADER;
89 case Graphic3d_TOS_FRAGMENT: return GL_FRAGMENT_SHADER;
90 case Graphic3d_TOS_GEOMETRY: return GL_GEOMETRY_SHADER;
91 case Graphic3d_TOS_TESS_CONTROL: return GL_TESS_CONTROL_SHADER;
92 case Graphic3d_TOS_TESS_EVALUATION: return GL_TESS_EVALUATION_SHADER;
93 case Graphic3d_TOS_COMPUTE: return GL_COMPUTE_SHADER;
94 }
95 return 0;
96 }
97}
98
30f0ad28 99// =======================================================================
100// function : OpenGl_VariableSetterSelector
101// purpose : Creates new variable setter selector
102// =======================================================================
103OpenGl_VariableSetterSelector::OpenGl_VariableSetterSelector()
104{
105 // Note: Add new variable setters here
106 mySetterList = OpenGl_HashMapInitializer::CreateListOf<size_t, OpenGl_SetterInterface*>
107 (Graphic3d_UniformValueTypeID<int>::ID, new OpenGl_VariableSetter<int>())
108 (Graphic3d_UniformValueTypeID<float>::ID, new OpenGl_VariableSetter<float>())
109 (Graphic3d_UniformValueTypeID<OpenGl_Vec2>::ID, new OpenGl_VariableSetter<OpenGl_Vec2>())
110 (Graphic3d_UniformValueTypeID<OpenGl_Vec3>::ID, new OpenGl_VariableSetter<OpenGl_Vec3>())
111 (Graphic3d_UniformValueTypeID<OpenGl_Vec4>::ID, new OpenGl_VariableSetter<OpenGl_Vec4>())
112 (Graphic3d_UniformValueTypeID<OpenGl_Vec2i>::ID, new OpenGl_VariableSetter<OpenGl_Vec2i>())
113 (Graphic3d_UniformValueTypeID<OpenGl_Vec3i>::ID, new OpenGl_VariableSetter<OpenGl_Vec3i>())
114 (Graphic3d_UniformValueTypeID<OpenGl_Vec4i>::ID, new OpenGl_VariableSetter<OpenGl_Vec4i>());
115}
116
117// =======================================================================
118// function : ~OpenGl_VariableSetterSelector
119// purpose : Releases memory resources of variable setter selector
120// =======================================================================
121OpenGl_VariableSetterSelector::~OpenGl_VariableSetterSelector()
122{
123 for (OpenGl_SetterList::Iterator anIt (mySetterList); anIt.More(); anIt.Next())
124 {
125 delete anIt.Value();
126 }
127
128 mySetterList.Clear();
129}
130
131// =======================================================================
132// function : Set
133// purpose : Sets generic variable to specified shader program
134// =======================================================================
135void OpenGl_VariableSetterSelector::Set (const Handle(OpenGl_Context)& theCtx,
136 const Handle(Graphic3d_ShaderVariable)& theVariable,
137 OpenGl_ShaderProgram* theProgram) const
138{
139 Standard_ASSERT_RETURN (mySetterList.IsBound (theVariable->Value()->TypeID()),
140 "The type of user-defined uniform variable is not supported...", );
141
142 mySetterList.Find (theVariable->Value()->TypeID())->Set (theCtx, theVariable, theProgram);
143}
144
145// =======================================================================
146// function : OpenGl_ShaderProgram
147// purpose : Creates uninitialized shader program
148// =======================================================================
149OpenGl_ShaderProgram::OpenGl_ShaderProgram (const Handle(Graphic3d_ShaderProgram)& theProxy)
cc8cbabe 150: OpenGl_NamedResource (!theProxy.IsNull() ? theProxy->GetId() : ""),
151 myProgramID (NO_PROGRAM),
392ac980 152 myProxy (theProxy),
8e0a2b19 153 myShareCount(1),
daf73ab7 154 myNbLightsMax (0),
155 myNbClipPlanesMax (0),
b17e5bae 156 myNbFragOutputs (1),
c40eb6b9 157 myHasAlphaTest (false),
b17e5bae 158 myHasWeightOitOutput (false),
8e0a2b19 159 myHasTessShader (false)
30f0ad28 160{
161 memset (myCurrentState, 0, sizeof (myCurrentState));
162 for (GLint aVar = 0; aVar < OpenGl_OCCT_NUMBER_OF_STATE_VARIABLES; ++aVar)
163 {
164 myStateLocations[aVar] = INVALID_LOCATION;
165 }
166}
167
168// =======================================================================
169// function : Initialize
170// purpose : Initializes program object with the list of shader objects
171// =======================================================================
172Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)& theCtx,
173 const Graphic3d_ShaderObjectList& theShaders)
174{
8e0a2b19 175 myHasTessShader = false;
30f0ad28 176 if (theCtx.IsNull() || !Create (theCtx))
177 {
178 return Standard_False;
179 }
180
8e0a2b19 181 TCollection_AsciiString aHeaderVer = !myProxy.IsNull() ? myProxy->Header() : TCollection_AsciiString();
182 int aShaderMask = 0;
183 for (Graphic3d_ShaderObjectList::Iterator anIter (theShaders); anIter.More(); anIter.Next())
184 {
185 aShaderMask |= anIter.Value()->Type();
186 }
187 myHasTessShader = (aShaderMask & (Graphic3d_TOS_TESS_CONTROL | Graphic3d_TOS_TESS_EVALUATION)) != 0;
b17e5bae 188 myNbFragOutputs = !myProxy.IsNull() ? myProxy->NbFragmentOutputs() : 1;
c40eb6b9 189 myHasAlphaTest = !myProxy.IsNull() && myProxy->HasAlphaTest();
b17e5bae 190 myHasWeightOitOutput = !myProxy.IsNull() ? myProxy->HasWeightOitOutput() && myNbFragOutputs >= 2 : 1;
30f0ad28 191
8e0a2b19 192 // detect the minimum GLSL version required for defined Shader Objects
193#if defined(GL_ES_VERSION_2_0)
194 if (myHasTessShader
195 || (aShaderMask & Graphic3d_TOS_GEOMETRY) != 0)
196 {
197 if (!theCtx->IsGlGreaterEqual (3, 2))
198 {
199 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
200 "Error! Geometry and Tessellation shaders require OpenGL ES 3.2+");
201 return false;
202 }
203 else if (aHeaderVer.IsEmpty())
204 {
205 aHeaderVer = "#version 320 es";
206 }
207 }
208 else if ((aShaderMask & Graphic3d_TOS_COMPUTE) != 0)
209 {
210 if (!theCtx->IsGlGreaterEqual (3, 1))
211 {
212 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
213 "Error! Compute shaders require OpenGL ES 3.1+");
214 return false;
215 }
216 else if (aHeaderVer.IsEmpty())
217 {
218 aHeaderVer = "#version 310 es";
219 }
220 }
221#else
222 if ((aShaderMask & Graphic3d_TOS_COMPUTE) != 0)
223 {
224 if (!theCtx->IsGlGreaterEqual (4, 3))
225 {
226 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
227 "Error! Compute shaders require OpenGL 4.3+");
228 return 0;
229 }
230 else if (aHeaderVer.IsEmpty())
231 {
232 aHeaderVer = "#version 430";
233 }
234 }
235 else if (myHasTessShader)
236 {
237 if (!theCtx->IsGlGreaterEqual (4, 0))
238 {
239 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
240 "Error! Tessellation shaders require OpenGL 4.0+");
241 return 0;
242 }
243 else if (aHeaderVer.IsEmpty())
244 {
245 aHeaderVer = "#version 400";
246 }
247 }
248 else if ((aShaderMask & Graphic3d_TOS_GEOMETRY) != 0)
249 {
250 if (!theCtx->IsGlGreaterEqual (3, 2))
251 {
252 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
253 "Error! Geometry shaders require OpenGL 3.2+");
254 return 0;
255 }
256 else if (aHeaderVer.IsEmpty())
257 {
258 aHeaderVer = "#version 150";
259 }
260 }
261#endif
12381341 262
8e0a2b19 263 for (Graphic3d_ShaderObjectList::Iterator anIter (theShaders); anIter.More(); anIter.Next())
30f0ad28 264 {
265 if (!anIter.Value()->IsDone())
266 {
392ac980 267 const TCollection_ExtendedString aMsg = "Error! Failed to get shader source";
8e0a2b19 268 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aMsg);
30f0ad28 269 return Standard_False;
270 }
271
8e0a2b19 272 const GLenum aShaderType = shaderTypeToGl (anIter.Value()->Type());
273 if (aShaderType == 0)
30f0ad28 274 {
30f0ad28 275 return Standard_False;
276 }
277
8e0a2b19 278 Handle(OpenGl_ShaderObject) aShader = new OpenGl_ShaderObject (aShaderType);
30f0ad28 279 if (!aShader->Create (theCtx))
280 {
392ac980 281 aShader->Release (theCtx.operator->());
30f0ad28 282 return Standard_False;
283 }
284
177781da 285 TCollection_AsciiString anExtensions = "// Enable extensions used in OCCT GLSL programs\n";
b17e5bae 286 if (myNbFragOutputs > 1)
a1073ae2 287 {
b17e5bae 288 if (theCtx->hasDrawBuffers)
a1073ae2 289 {
b17e5bae 290 anExtensions += "#define OCC_ENABLE_draw_buffers\n";
291 if (myHasWeightOitOutput)
292 {
293 anExtensions += "#define OCC_WRITE_WEIGHT_OIT_COVERAGE\n";
294 }
a1073ae2 295 }
b17e5bae 296 else
297 {
298 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
299 "Error! Multiple draw buffers required by the program, but aren't supported by OpenGL");
300 return Standard_False;
301 }
302
303 if (theCtx->hasDrawBuffers == OpenGl_FeatureInExtensions)
a1073ae2 304 {
b17e5bae 305 if (theCtx->arbDrawBuffers)
306 {
307 anExtensions += "#extension GL_ARB_draw_buffers : enable\n";
308 }
309 else if (theCtx->extDrawBuffers)
310 {
311 anExtensions += "#extension GL_EXT_draw_buffers : enable\n";
312 }
a1073ae2 313 }
314 }
c40eb6b9 315 if (myHasAlphaTest)
316 {
317 anExtensions += "#define OCC_ALPHA_TEST\n";
318 }
a1073ae2 319
320 if (theCtx->hasSampleVariables == OpenGl_FeatureInExtensions)
321 {
322#if defined(GL_ES_VERSION_2_0)
323 if (theCtx->oesSampleVariables)
324 {
325 anExtensions += "#extension GL_OES_sample_variables : enable\n";
326 }
327#else
328 if (theCtx->arbSampleShading)
329 {
330 anExtensions += "#extension GL_ARB_sample_shading : enable\n";
331 }
332#endif
333 }
334
8e0a2b19 335 TCollection_AsciiString aPrecisionHeader;
336 if (anIter.Value()->Type() == Graphic3d_TOS_FRAGMENT)
337 {
338 #if defined(GL_ES_VERSION_2_0)
339 aPrecisionHeader = theCtx->hasHighp
340 ? "precision highp float;\n"
341 "precision highp int;\n"
342 : "precision mediump float;\n"
343 "precision mediump int;\n";
344 #endif
345 }
346
347 TCollection_AsciiString aHeaderType;
8625ef7e 348 switch (anIter.Value()->Type())
30f0ad28 349 {
8e0a2b19 350 case Graphic3d_TOS_COMPUTE: { aHeaderType = "#define COMPUTE_SHADER\n"; break; }
351 case Graphic3d_TOS_VERTEX: { aHeaderType = "#define VERTEX_SHADER\n"; break; }
352 case Graphic3d_TOS_TESS_CONTROL: { aHeaderType = "#define TESS_CONTROL_SHADER\n"; break; }
353 case Graphic3d_TOS_TESS_EVALUATION: { aHeaderType = "#define TESS_EVALUATION_SHADER\n"; break; }
354 case Graphic3d_TOS_GEOMETRY: { aHeaderType = "#define GEOMETRY_SHADER\n"; break; }
355 case Graphic3d_TOS_FRAGMENT: { aHeaderType = "#define FRAGMENT_SHADER\n"; break; }
30f0ad28 356 }
357
daf73ab7 358 TCollection_AsciiString aHeaderConstants;
359 myNbLightsMax = !myProxy.IsNull() ? myProxy->NbLightsMax() : 0;
360 myNbClipPlanesMax = !myProxy.IsNull() ? myProxy->NbClipPlanesMax() : 0;
05fb2b05 361 aHeaderConstants += TCollection_AsciiString("#define THE_MAX_LIGHTS ") + myNbLightsMax + "\n";
362 aHeaderConstants += TCollection_AsciiString("#define THE_MAX_CLIP_PLANES ") + myNbClipPlanesMax + "\n";
b17e5bae 363 aHeaderConstants += TCollection_AsciiString("#define THE_NB_FRAG_OUTPUTS ") + myNbFragOutputs + "\n";
daf73ab7 364
8e0a2b19 365 const TCollection_AsciiString aSource = aHeaderVer // #version - header defining GLSL version, should be first
366 + (!aHeaderVer.IsEmpty() ? "\n" : "")
367 + anExtensions // #extension - list of enabled extensions, should be second
368 + aPrecisionHeader // precision - default precision qualifiers, should be before any code
369 + aHeaderType // auxiliary macros defining a shader stage (type)
daf73ab7 370 + aHeaderConstants
8e0a2b19 371 + Shaders_Declarations_glsl // common declarations (global constants and Vertex Shader inputs)
372 + Shaders_DeclarationsImpl_glsl
373 + anIter.Value()->Source(); // the source code itself (defining main() function)
2bda8346 374 if (!aShader->LoadAndCompile (theCtx, aSource))
30f0ad28 375 {
392ac980 376 return Standard_False;
377 }
30f0ad28 378
84e84755 379 if (theCtx->caps->glslDumpLevel)
380 {
381 TCollection_AsciiString aShaderTypeMsg;
382 switch (anIter.Value()->Type())
383 {
384 case Graphic3d_TOS_COMPUTE: { aShaderTypeMsg = "Compute shader source code:\n"; break; }
385 case Graphic3d_TOS_VERTEX: { aShaderTypeMsg = "Vertex shader source code:\n"; break; }
386 case Graphic3d_TOS_TESS_CONTROL: { aShaderTypeMsg = "Tesselation control shader source code:\n"; break; }
387 case Graphic3d_TOS_TESS_EVALUATION: { aShaderTypeMsg = "Tesselation evaluation shader source code:\n"; break; }
388 case Graphic3d_TOS_GEOMETRY: { aShaderTypeMsg = "Geometry shader source code:\n"; break; }
389 case Graphic3d_TOS_FRAGMENT: { aShaderTypeMsg = "Fragment shader source code:\n"; break; }
390 }
391 TCollection_AsciiString anOutputSource = aSource;
392 if (theCtx->caps->glslDumpLevel == OpenGl_ShaderProgramDumpLevel_Short)
393 {
394 anOutputSource = aHeaderVer
395 + (!aHeaderVer.IsEmpty() ? "\n" : "")
396 + anExtensions
397 + aPrecisionHeader
398 + aHeaderType
399 + aHeaderConstants
400 + anIter.Value()->Source();
401 }
402 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_OTHER, 0, GL_DEBUG_SEVERITY_MEDIUM,
403 TCollection_ExtendedString (aShaderTypeMsg + anOutputSource));
404 }
405
30f0ad28 406 if (!AttachShader (theCtx, aShader))
407 {
392ac980 408 aShader->Release (theCtx.operator->());
30f0ad28 409 return Standard_False;
410 }
411 }
412
7d3e64ef 413 // bind locations for pre-defined Vertex Attributes
414 SetAttributeName (theCtx, Graphic3d_TOA_POS, "occVertex");
415 SetAttributeName (theCtx, Graphic3d_TOA_NORM, "occNormal");
416 SetAttributeName (theCtx, Graphic3d_TOA_UV, "occTexCoord");
8625ef7e 417 SetAttributeName (theCtx, Graphic3d_TOA_COLOR, "occVertColor");
7d3e64ef 418
4a535d3f 419 // bind custom Vertex Attributes
420 if (!myProxy.IsNull())
421 {
422 for (Graphic3d_ShaderAttributeList::Iterator anAttribIter (myProxy->VertexAttributes());
423 anAttribIter.More(); anAttribIter.Next())
424 {
425 SetAttributeName (theCtx, anAttribIter.Value()->Location(), anAttribIter.Value()->Name().ToCString());
426 }
427 }
428
30f0ad28 429 if (!Link (theCtx))
430 {
392ac980 431 return Standard_False;
432 }
30f0ad28 433
299e0ab9 434 // set uniform defaults
cc8cbabe 435 const Handle(OpenGl_ShaderProgram)& anOldProgram = theCtx->ActiveProgram();
436 theCtx->core20fwd->glUseProgram (myProgramID);
299e0ab9 437 {
cc8cbabe 438 const GLint aLocTexEnable = GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE);
439 if (aLocTexEnable != INVALID_LOCATION)
440 {
441 SetUniform (theCtx, aLocTexEnable, 0); // Off
442 }
443 }
444 {
445 const GLint aLocSampler = GetUniformLocation (theCtx, "occActiveSampler");
446 if (aLocSampler != INVALID_LOCATION)
447 {
448 SetUniform (theCtx, aLocSampler, GLint(Graphic3d_TextureUnit_0));
449 }
450 }
451
452 const TCollection_AsciiString aSamplerNamePrefix ("occSampler");
453 const Standard_Integer aNbUnitsMax = Max (theCtx->MaxCombinedTextureUnits(), Graphic3d_TextureUnit_NB);
454 for (GLint aUnitIter = 0; aUnitIter < aNbUnitsMax; ++aUnitIter)
455 {
456 const TCollection_AsciiString aName = aSamplerNamePrefix + aUnitIter;
457 const GLint aLocSampler = GetUniformLocation (theCtx, aName.ToCString());
458 if (aLocSampler != INVALID_LOCATION)
459 {
460 SetUniform (theCtx, aLocSampler, aUnitIter);
461 }
299e0ab9 462 }
463
cc8cbabe 464 theCtx->core20fwd->glUseProgram (!anOldProgram.IsNull() ? anOldProgram->ProgramId() : OpenGl_ShaderProgram::NO_PROGRAM);
30f0ad28 465 return Standard_True;
466}
467
468// =======================================================================
469// function : ~OpenGl_ShaderProgram
470// purpose : Releases resources of shader program
471// =======================================================================
472OpenGl_ShaderProgram::~OpenGl_ShaderProgram()
473{
474 Release (NULL);
475}
476
477// =======================================================================
478// function : AttachShader
479// purpose : Attaches shader object to the program object
480// =======================================================================
481Standard_Boolean OpenGl_ShaderProgram::AttachShader (const Handle(OpenGl_Context)& theCtx,
482 const Handle(OpenGl_ShaderObject)& theShader)
483{
484 if (myProgramID == NO_PROGRAM || theShader.IsNull())
485 {
486 return Standard_False;
487 }
488
489 for (OpenGl_ShaderList::Iterator anIter (myShaderObjects); anIter.More(); anIter.Next())
490 {
491 if (theShader == anIter.Value())
492 {
493 return Standard_False;
494 }
495 }
496
497 myShaderObjects.Append (theShader);
4e1523ef 498 theCtx->core20fwd->glAttachShader (myProgramID, theShader->myShaderID);
30f0ad28 499 return Standard_True;
500}
501
502// =======================================================================
503// function : DetachShader
504// purpose : Detaches shader object to the program object
505// =======================================================================
506Standard_Boolean OpenGl_ShaderProgram::DetachShader (const Handle(OpenGl_Context)& theCtx,
507 const Handle(OpenGl_ShaderObject)& theShader)
508{
509 if (myProgramID == NO_PROGRAM
510 || theShader.IsNull())
511 {
512 return Standard_False;
513 }
514
515 OpenGl_ShaderList::Iterator anIter (myShaderObjects);
516 while (anIter.More())
517 {
518 if (theShader == anIter.Value())
519 {
520 myShaderObjects.Remove (anIter);
521 break;
522 }
523
524 anIter.Next();
525 }
526
527 if (!anIter.More())
528 {
529 return Standard_False;
530 }
531
4e1523ef 532 theCtx->core20fwd->glDetachShader (myProgramID, theShader->myShaderID);
30f0ad28 533 return Standard_True;
534}
535
536// =======================================================================
537// function : Link
538// purpose : Links the program object
539// =======================================================================
2bda8346 540Standard_Boolean OpenGl_ShaderProgram::link (const Handle(OpenGl_Context)& theCtx)
30f0ad28 541{
542 if (myProgramID == NO_PROGRAM)
543 {
544 return Standard_False;
545 }
546
30f0ad28 547 GLint aStatus = GL_FALSE;
4e1523ef 548 theCtx->core20fwd->glLinkProgram (myProgramID);
549 theCtx->core20fwd->glGetProgramiv (myProgramID, GL_LINK_STATUS, &aStatus);
fc73a202 550 if (aStatus == GL_FALSE)
551 {
552 return Standard_False;
553 }
30f0ad28 554
555 for (GLint aVar = 0; aVar < OpenGl_OCCT_NUMBER_OF_STATE_VARIABLES; ++aVar)
556 {
557 myStateLocations[aVar] = GetUniformLocation (theCtx, PredefinedKeywords[aVar]);
558 }
fc73a202 559 return Standard_True;
30f0ad28 560}
561
562// =======================================================================
2bda8346 563// function : Link
564// purpose :
565// =======================================================================
566Standard_Boolean OpenGl_ShaderProgram::Link (const Handle(OpenGl_Context)& theCtx,
567 bool theIsVerbose)
568{
569 if (!theIsVerbose)
570 {
571 return link (theCtx);
572 }
573
574 if (!link (theCtx))
575 {
576 TCollection_AsciiString aLog;
577 FetchInfoLog (theCtx, aLog);
578 if (aLog.IsEmpty())
579 {
580 aLog = "Linker log is empty.";
581 }
582 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
583 TCollection_AsciiString ("Failed to link program object! Linker log:\n") + aLog);
584 return false;
585 }
586 else if (theCtx->caps->glslWarnings)
587 {
588 TCollection_AsciiString aLog;
589 FetchInfoLog (theCtx, aLog);
590 if (!aLog.IsEmpty()
591 && !aLog.IsEqual ("No errors.\n"))
592 {
593 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_LOW,
594 TCollection_AsciiString ("GLSL linker log:\n") + aLog);
595 }
596 }
597 return true;
598}
599
600// =======================================================================
30f0ad28 601// function : FetchInfoLog
602// purpose : Fetches information log of the last link operation
603// =======================================================================
604Standard_Boolean OpenGl_ShaderProgram::FetchInfoLog (const Handle(OpenGl_Context)& theCtx,
605 TCollection_AsciiString& theOutput)
606{
607 if (myProgramID == NO_PROGRAM)
608 {
609 return Standard_False;
610 }
611
612 GLint aLength = 0;
4e1523ef 613 theCtx->core20fwd->glGetProgramiv (myProgramID, GL_INFO_LOG_LENGTH, &aLength);
30f0ad28 614 if (aLength > 0)
615 {
616 GLchar* aLog = (GLchar*) alloca (aLength);
617 memset (aLog, 0, aLength);
4e1523ef 618 theCtx->core20fwd->glGetProgramInfoLog (myProgramID, aLength, NULL, aLog);
30f0ad28 619 theOutput = aLog;
620 }
621 return Standard_True;
622}
623
624// =======================================================================
30f0ad28 625// function : ApplyVariables
626// purpose : Fetches uniform variables from proxy shader program
627// =======================================================================
628Standard_Boolean OpenGl_ShaderProgram::ApplyVariables(const Handle(OpenGl_Context)& theCtx)
629{
630 if (myProxy.IsNull() || myProxy->Variables().IsEmpty())
631 {
632 return Standard_False;
633 }
634
635 for (Graphic3d_ShaderVariableList::Iterator anIter (myProxy->Variables()); anIter.More(); anIter.Next())
636 {
637 mySetterSelector.Set (theCtx, anIter.Value(), this);
638 }
639
640 myProxy->ClearVariables();
641 return Standard_True;
642}
643
644// =======================================================================
30f0ad28 645// function : GetUniformLocation
646// purpose : Returns location (index) of the specific uniform variable
647// =======================================================================
648GLint OpenGl_ShaderProgram::GetUniformLocation (const Handle(OpenGl_Context)& theCtx,
649 const GLchar* theName) const
650{
651 return myProgramID != NO_PROGRAM
4e1523ef 652 ? theCtx->core20fwd->glGetUniformLocation (myProgramID, theName)
30f0ad28 653 : INVALID_LOCATION;
654}
655
656// =======================================================================
657// function : GetAttributeLocation
658// purpose : Returns location (index) of the generic vertex attribute
659// =======================================================================
660GLint OpenGl_ShaderProgram::GetAttributeLocation (const Handle(OpenGl_Context)& theCtx,
661 const GLchar* theName) const
662{
663 return myProgramID != NO_PROGRAM
4e1523ef 664 ? theCtx->core20fwd->glGetAttribLocation (myProgramID, theName)
30f0ad28 665 : INVALID_LOCATION;
666}
667
668// =======================================================================
669// function : GetStateLocation
670// purpose : Returns location of the OCCT state uniform variable
671// =======================================================================
672GLint OpenGl_ShaderProgram::GetStateLocation (const GLuint theVariable) const
673{
674 if (theVariable < OpenGl_OCCT_NUMBER_OF_STATE_VARIABLES)
675 {
676 return myStateLocations[theVariable];
677 }
678 return INVALID_LOCATION;
679}
680
681// =======================================================================
682// function : GetUniform
683// purpose : Returns the value of the integer uniform variable
684// =======================================================================
685Standard_Boolean OpenGl_ShaderProgram::GetUniform (const Handle(OpenGl_Context)& theCtx,
686 const GLchar* theName,
687 OpenGl_Vec4i& theValue) const
688{
689 return GetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
690}
691
692// =======================================================================
693// function : GetUniform
694// purpose : Returns the value of the integer uniform variable
695// =======================================================================
696Standard_Boolean OpenGl_ShaderProgram::GetUniform (const Handle(OpenGl_Context)& theCtx,
697 GLint theLocation,
698 OpenGl_Vec4i& theValue) const
699{
700 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
701 {
702 return Standard_False;
703 }
704
4e1523ef 705 theCtx->core20fwd->glGetUniformiv (myProgramID, theLocation, theValue);
30f0ad28 706 return Standard_True;
707}
708
709// =======================================================================
710// function : GetUniform
711// purpose : Returns the value of the floating-point uniform variable
712// =======================================================================
713Standard_Boolean OpenGl_ShaderProgram::GetUniform (const Handle(OpenGl_Context)& theCtx,
714 const GLchar* theName,
715 OpenGl_Vec4& theValue) const
716{
717 return GetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
718}
719
720// =======================================================================
721// function : GetUniform
722// purpose : Returns the value of the floating-point uniform variable
723// =======================================================================
724Standard_Boolean OpenGl_ShaderProgram::GetUniform (const Handle(OpenGl_Context)& theCtx,
725 GLint theLocation,
726 OpenGl_Vec4& theValue) const
727{
728 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
729 {
730 return Standard_False;
731 }
732
4e1523ef 733 theCtx->core20fwd->glGetUniformfv (myProgramID, theLocation, theValue);
30f0ad28 734 return Standard_True;
735}
736
737// =======================================================================
738// function : GetAttribute
739// purpose : Returns the integer vertex attribute
740// =======================================================================
741Standard_Boolean OpenGl_ShaderProgram::GetAttribute (const Handle(OpenGl_Context)& theCtx,
742 const GLchar* theName,
743 OpenGl_Vec4i& theValue) const
744{
745 return GetAttribute (theCtx, GetAttributeLocation (theCtx, theName), theValue);
746}
747
748// =======================================================================
749// function : GetAttribute
750// purpose : Returns the integer vertex attribute
751// =======================================================================
752Standard_Boolean OpenGl_ShaderProgram::GetAttribute (const Handle(OpenGl_Context)& theCtx,
753 GLint theIndex,
754 OpenGl_Vec4i& theValue) const
755{
756 if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION)
757 {
758 return Standard_False;
759 }
760
4e1523ef 761 theCtx->core20fwd->glGetVertexAttribiv (theIndex, GL_CURRENT_VERTEX_ATTRIB, theValue);
30f0ad28 762 return Standard_True;
763}
764
765// =======================================================================
766// function : GetAttribute
767// purpose : Returns the floating-point vertex attribute
768// =======================================================================
769Standard_Boolean OpenGl_ShaderProgram::GetAttribute (const Handle(OpenGl_Context)& theCtx,
770 const GLchar* theName,
771 OpenGl_Vec4& theValue) const
772{
773 return GetAttribute (theCtx, GetAttributeLocation (theCtx, theName), theValue);
774}
775
776// =======================================================================
777// function : GetAttribute
778// purpose : Returns the floating-point vertex attribute
779// =======================================================================
780Standard_Boolean OpenGl_ShaderProgram::GetAttribute (const Handle(OpenGl_Context)& theCtx,
781 GLint theIndex,
782 OpenGl_Vec4& theValue) const
783{
784 if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION)
785 {
786 return Standard_False;
787 }
788
4e1523ef 789 theCtx->core20fwd->glGetVertexAttribfv (theIndex, GL_CURRENT_VERTEX_ATTRIB, theValue);
30f0ad28 790 return Standard_True;
791}
792
793// =======================================================================
fc73a202 794// function : SetAttributeName
795// purpose :
796// =======================================================================
797Standard_Boolean OpenGl_ShaderProgram::SetAttributeName (const Handle(OpenGl_Context)& theCtx,
798 GLint theIndex,
799 const GLchar* theName)
800{
801 theCtx->core20fwd->glBindAttribLocation (myProgramID, theIndex, theName);
802 return Standard_True;
803}
b86bb3df 804
fc73a202 805// =======================================================================
806// function : SetAttribute
807// purpose :
808// =======================================================================
809Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
810 const GLchar* theName,
811 GLfloat theValue)
812{
813 return SetAttribute (theCtx, GetAttributeLocation (theCtx, theName), theValue);
814}
815
816// =======================================================================
817// function : SetAttribute
818// purpose :
819// =======================================================================
820Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
821 GLint theIndex,
822 GLfloat theValue)
823{
824 if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION)
825 {
826 return Standard_False;
827 }
828
829 theCtx->core20fwd->glVertexAttrib1f (theIndex, theValue);
830 return Standard_True;
831}
832
833// =======================================================================
834// function : SetAttribute
835// purpose :
836// =======================================================================
837Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
838 const GLchar* theName,
839 const OpenGl_Vec2& theValue)
840{
841 return SetAttribute (theCtx, GetAttributeLocation (theCtx, theName), theValue);
842}
843
844// =======================================================================
845// function : SetAttribute
846// purpose :
847// =======================================================================
848Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
849 GLint theIndex,
850 const OpenGl_Vec2& theValue)
851{
852 if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION)
853 {
854 return Standard_False;
855 }
856
857 theCtx->core20fwd->glVertexAttrib2fv (theIndex, theValue);
858 return Standard_True;
859}
860
861// =======================================================================
862// function : SetAttribute
863// purpose :
864// =======================================================================
865Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
866 const GLchar* theName,
867 const OpenGl_Vec3& theValue)
868{
869 return SetAttribute (theCtx, GetAttributeLocation (theCtx, theName), theValue);
870}
871
872// =======================================================================
873// function : SetAttribute
874// purpose :
875// =======================================================================
876Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
877 GLint theIndex,
878 const OpenGl_Vec3& theValue)
879{
880 if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION)
881 {
882 return Standard_False;
883 }
884
885 theCtx->core20fwd->glVertexAttrib3fv (theIndex, theValue);
886 return Standard_True;
887}
888
889// =======================================================================
890// function : SetAttribute
891// purpose :
892// =======================================================================
893Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
894 const GLchar* theName,
895 const OpenGl_Vec4& theValue)
896{
897 return SetAttribute (theCtx, GetAttributeLocation (theCtx, theName), theValue);
898}
899
900// =======================================================================
901// function : SetAttribute
902// purpose :
903// =======================================================================
904Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
905 GLint theIndex,
906 const OpenGl_Vec4& theValue)
907{
908 if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION)
909 {
910 return Standard_False;
911 }
912
913 theCtx->core20fwd->glVertexAttrib4fv (theIndex, theValue);
914 return Standard_True;
915}
916
917// =======================================================================
30f0ad28 918// function : SetUniform
919// purpose : Specifies the value of the integer uniform variable
920// =======================================================================
921Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
922 const GLchar* theName,
923 GLint theValue)
924{
925 return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
926}
927
928// =======================================================================
929// function : SetUniform
930// purpose : Specifies the value of the integer uniform variable
931// =======================================================================
932Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
933 GLint theLocation,
934 GLint theValue)
935{
936 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
937 {
938 return Standard_False;
939 }
940
4e1523ef 941 theCtx->core20fwd->glUniform1i (theLocation, theValue);
30f0ad28 942 return Standard_True;
943}
944
945// =======================================================================
946// function : SetUniform
47e9c178 947// purpose :
25ef750e 948// =======================================================================
949Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
950 const GLchar* theName,
47e9c178 951 const OpenGl_Vec2u& theValue)
25ef750e 952{
953 return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
954}
955
956// =======================================================================
957// function : SetUniform
47e9c178 958// purpose :
25ef750e 959// =======================================================================
960Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
961 GLint theLocation,
47e9c178 962 const OpenGl_Vec2u& theValue)
25ef750e 963{
47e9c178 964 if (theCtx->core32 == NULL || myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
25ef750e 965 {
966 return Standard_False;
967 }
968
969#if !defined(GL_ES_VERSION_2_0)
47e9c178 970 theCtx->core32->glUniform2uiv (theLocation, 1, theValue.GetData());
25ef750e 971 return Standard_True;
20aeeb7b 972#else
973 (void )theValue;
974 return Standard_False;
975#endif
25ef750e 976}
977
978// =======================================================================
979// function : SetUniform
47e9c178 980// purpose :
25ef750e 981// =======================================================================
982Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
983 const GLchar* theName,
984 const GLsizei theCount,
47e9c178 985 const OpenGl_Vec2u* theValue)
25ef750e 986{
987 return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theCount, theValue);
988}
989
990// =======================================================================
991// function : SetUniform
47e9c178 992// purpose :
25ef750e 993// =======================================================================
994Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
995 GLint theLocation,
996 const GLsizei theCount,
47e9c178 997 const OpenGl_Vec2u* theValue)
25ef750e 998{
47e9c178 999 if (theCtx->core32 == NULL || myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
25ef750e 1000 {
1001 return Standard_False;
1002 }
1003
1004#if !defined(GL_ES_VERSION_2_0)
47e9c178 1005 theCtx->core32->glUniform2uiv (theLocation, theCount, theValue->GetData());
25ef750e 1006 return Standard_True;
20aeeb7b 1007#else
1008 (void )theCount;
1009 (void )theValue;
1010 return Standard_False;
1011#endif
25ef750e 1012}
1013
1014// =======================================================================
1015// function : SetUniform
30f0ad28 1016// purpose : Specifies the value of the floating-point uniform variable
1017// =======================================================================
1018Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1019 const GLchar* theName,
1020 GLfloat theValue)
1021{
1022 return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
1023}
1024
1025// =======================================================================
1026// function : SetUniform
1027// purpose : Specifies the value of the floating-point uniform variable
1028// =======================================================================
1029Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1030 GLint theLocation,
1031 GLfloat theValue)
1032{
1033 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1034 {
1035 return Standard_False;
1036 }
1037
4e1523ef 1038 theCtx->core20fwd->glUniform1f (theLocation, theValue);
30f0ad28 1039 return Standard_True;
1040}
1041
1042// =======================================================================
1043// function : SetUniform
1044// purpose : Specifies the value of the integer uniform 2D vector
1045// =======================================================================
1046Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1047 const GLchar* theName,
1048 const OpenGl_Vec2i& theValue)
1049{
1050 return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
1051}
1052
1053// =======================================================================
1054// function : SetUniform
1055// purpose : Specifies the value of the integer uniform 2D vector
1056// =======================================================================
1057Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1058 GLint theLocation,
1059 const OpenGl_Vec2i& theValue)
1060{
1061 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1062 {
1063 return Standard_False;
1064 }
1065
4e1523ef 1066 theCtx->core20fwd->glUniform2iv (theLocation, 1, theValue);
30f0ad28 1067 return Standard_True;
1068}
1069
1070// =======================================================================
1071// function : SetUniform
1072// purpose : Specifies the value of the integer uniform 3D vector
1073// =======================================================================
1074Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1075 const GLchar* theName,
1076 const OpenGl_Vec3i& theValue)
1077{
1078 return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
1079}
1080
1081// =======================================================================
1082// function : SetUniform
1083// purpose : Specifies the value of the integer uniform 3D vector
1084// =======================================================================
1085Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1086 GLint theLocation,
1087 const OpenGl_Vec3i& theValue)
1088{
1089 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1090 {
1091 return Standard_False;
1092 }
1093
4e1523ef 1094 theCtx->core20fwd->glUniform3iv (theLocation, 1, theValue);
30f0ad28 1095 return Standard_True;
1096}
1097
1098// =======================================================================
1099// function : SetUniform
1100// purpose : Specifies the value of the integer uniform 4D vector
1101// =======================================================================
1102Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1103 const GLchar* theName,
1104 const OpenGl_Vec4i& theValue)
1105{
1106 return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
1107}
1108
1109// =======================================================================
1110// function : SetUniform
1111// purpose : Specifies the value of the integer uniform 4D vector
1112// =======================================================================
1113Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1114 GLint theLocation,
1115 const OpenGl_Vec4i& theValue)
1116{
1117 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1118 {
1119 return Standard_False;
1120 }
1121
4e1523ef 1122 theCtx->core20fwd->glUniform4iv (theLocation, 1, theValue);
30f0ad28 1123 return Standard_True;
1124}
1125
1126// =======================================================================
1127// function : SetUniform
1128// purpose : Specifies the value of the floating-point uniform 2D vector
1129// =======================================================================
1130Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1131 const GLchar* theName,
1132 const OpenGl_Vec2& theValue)
1133{
1134 return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
1135}
1136
1137// =======================================================================
1138// function : SetUniform
1139// purpose : Specifies the value of the floating-point uniform 2D vector
1140// =======================================================================
1141Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1142 GLint theLocation,
1143 const OpenGl_Vec2& theValue)
1144{
1145 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1146 {
1147 return Standard_False;
1148 }
1149
4e1523ef 1150 theCtx->core20fwd->glUniform2fv (theLocation, 1, theValue);
30f0ad28 1151 return Standard_True;
1152}
1153
1154// =======================================================================
1155// function : SetUniform
1156// purpose : Specifies the value of the floating-point uniform 3D vector
1157// =======================================================================
1158Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1159 const GLchar* theName,
1160 const OpenGl_Vec3& theValue)
1161{
1162 return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
1163}
1164
1165// =======================================================================
1166// function : SetUniform
1167// purpose : Specifies the value of the floating-point uniform 3D vector
1168// =======================================================================
1169Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1170 GLint theLocation,
1171 const OpenGl_Vec3& theValue)
1172{
1173 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1174 {
1175 return Standard_False;
1176 }
1177
4e1523ef 1178 theCtx->core20fwd->glUniform3fv (theLocation, 1, theValue);
30f0ad28 1179 return Standard_True;
1180}
1181
1182// =======================================================================
1183// function : SetUniform
1184// purpose : Specifies the value of the floating-point uniform 4D vector
1185// =======================================================================
1186Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1187 const GLchar* theName,
1188 const OpenGl_Vec4& theValue)
1189{
1190 return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
1191}
1192
1193// =======================================================================
1194// function : SetUniform
1195// purpose : Specifies the value of the floating-point uniform 4D vector
1196// =======================================================================
1197Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1198 GLint theLocation,
1199 const OpenGl_Vec4& theValue)
1200{
1201 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1202 {
1203 return Standard_False;
1204 }
1205
4e1523ef 1206 theCtx->core20fwd->glUniform4fv (theLocation, 1, theValue);
30f0ad28 1207 return Standard_True;
1208}
1209
1210// =======================================================================
1211// function : SetUniform
1212// purpose : Specifies the value of the floating-point uniform 4x4 matrix
1213// =======================================================================
1214Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1215 const GLchar* theName,
25ef750e 1216 const OpenGl_Mat4& theValue,
1217 GLboolean theTranspose)
1218{
1219 return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue, theTranspose);
1220}
1221
1222// =======================================================================
1223// function : SetUniform
1224// purpose : Specifies the value of the floating-point uniform 4x4 matrix
1225// =======================================================================
1226Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1227 GLint theLocation,
1228 const OpenGl_Mat4& theValue,
1229 GLboolean theTranspose)
1230{
1231 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1232 {
1233 return Standard_False;
1234 }
1235
4e1523ef 1236 theCtx->core20fwd->glUniformMatrix4fv (theLocation, 1, GL_FALSE, theTranspose ? theValue.Transposed() : theValue);
25ef750e 1237 return Standard_True;
1238}
1239
1240// =======================================================================
1241// function : SetUniform
1242// purpose : Specifies the value of the floating-point uniform 4x4 matrix
1243// =======================================================================
1244Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1245 const GLchar* theName,
30f0ad28 1246 const OpenGl_Matrix& theValue,
1247 GLboolean theTranspose)
1248{
1249 return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue, theTranspose);
1250}
1251
1252// =======================================================================
1253// function : SetUniform
1254// purpose : Specifies the value of the floating-point uniform 4x4 matrix
1255// =======================================================================
1256Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1257 GLint theLocation,
1258 const OpenGl_Matrix& theValue,
1259 GLboolean theTranspose)
1260{
c827ea3a 1261 return SetUniform (theCtx, theLocation, OpenGl_Mat4::Map (*theValue.mat), theTranspose);
30f0ad28 1262}
1263
1264// =======================================================================
4fe9ad57 1265// function : SetUniform
1266// purpose : Specifies the value of the float uniform array
1267// =======================================================================
1268Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1269 GLint theLocation,
1270 GLuint theCount,
1271 const Standard_ShortReal* theData)
1272{
1273 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1274 {
1275 return Standard_False;
1276 }
1277
4e1523ef 1278 theCtx->core20fwd->glUniform1fv (theLocation, theCount, theData);
4fe9ad57 1279 return Standard_True;
1280}
1281
1282// =======================================================================
1283// function : SetUniform
1284// purpose : Specifies the value of the float2 uniform array
1285// =======================================================================
1286Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1287 GLint theLocation,
1288 GLuint theCount,
1289 const OpenGl_Vec2* theData)
1290{
1291 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1292 {
1293 return Standard_False;
1294 }
1295
4e1523ef 1296 theCtx->core20fwd->glUniform2fv (theLocation, theCount, theData[0].GetData());
4fe9ad57 1297 return Standard_True;
1298}
1299
1300// =======================================================================
1301// function : SetUniform
1302// purpose : Specifies the value of the float3 uniform array
1303// =======================================================================
1304Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1305 GLint theLocation,
1306 GLuint theCount,
1307 const OpenGl_Vec3* theData)
1308{
1309 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1310 {
1311 return Standard_False;
1312 }
1313
4e1523ef 1314 theCtx->core20fwd->glUniform3fv (theLocation, theCount, theData[0].GetData());
4fe9ad57 1315 return Standard_True;
1316}
1317
1318// =======================================================================
1319// function : SetUniform
1320// purpose : Specifies the value of the float4 uniform array
1321// =======================================================================
1322Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1323 GLint theLocation,
1324 GLuint theCount,
1325 const OpenGl_Vec4* theData)
1326{
1327 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1328 {
1329 return Standard_False;
1330 }
1331
4e1523ef 1332 theCtx->core20fwd->glUniform4fv (theLocation, theCount, theData[0].GetData());
4fe9ad57 1333 return Standard_True;
1334}
1335
1336// =======================================================================
1337// function : SetUniform
1338// purpose : Specifies the value of the integer uniform array
1339// =======================================================================
1340Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1341 GLint theLocation,
1342 GLuint theCount,
1343 const Standard_Integer* theData)
1344{
1345 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1346 {
1347 return Standard_False;
1348 }
1349
4e1523ef 1350 theCtx->core20fwd->glUniform1iv (theLocation, theCount, theData);
4fe9ad57 1351 return Standard_True;
1352}
1353
1354// =======================================================================
1355// function : SetUniform
1356// purpose : Specifies the value of the int2 uniform array
1357// =======================================================================
1358Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1359 GLint theLocation,
1360 GLuint theCount,
1361 const OpenGl_Vec2i* theData)
1362{
1363 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1364 {
1365 return Standard_False;
1366 }
1367
4e1523ef 1368 theCtx->core20fwd->glUniform2iv (theLocation, theCount, theData[0].GetData());
4fe9ad57 1369 return Standard_True;
1370}
1371
1372// =======================================================================
1373// function : SetUniform
1374// purpose : Specifies the value of the int3 uniform array
1375// =======================================================================
1376Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1377 GLint theLocation,
1378 GLuint theCount,
1379 const OpenGl_Vec3i* theData)
1380{
1381 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1382 {
1383 return Standard_False;
1384 }
1385
4e1523ef 1386 theCtx->core20fwd->glUniform3iv (theLocation, theCount, theData[0].GetData());
4fe9ad57 1387 return Standard_True;
1388}
1389
1390// =======================================================================
1391// function : SetUniform
1392// purpose : Specifies the value of the int4 uniform array
1393// =======================================================================
1394Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1395 GLint theLocation,
1396 GLuint theCount,
1397 const OpenGl_Vec4i* theData)
1398{
1399 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1400 {
1401 return Standard_False;
1402 }
1403
4e1523ef 1404 theCtx->core20fwd->glUniform4iv (theLocation, theCount, theData[0].GetData());
4fe9ad57 1405 return Standard_True;
1406}
1407
1408// =======================================================================
30f0ad28 1409// function : SetSampler
1410// purpose : Specifies the value of the sampler uniform variable
1411// =======================================================================
1412Standard_Boolean OpenGl_ShaderProgram::SetSampler (const Handle(OpenGl_Context)& theCtx,
1413 const GLchar* theName,
cc8cbabe 1414 const Graphic3d_TextureUnit theTextureUnit)
30f0ad28 1415{
1416 return SetSampler (theCtx, GetUniformLocation (theCtx, theName), theTextureUnit);
1417}
1418
1419// =======================================================================
1420// function : SetSampler
1421// purpose : Specifies the value of the sampler uniform variable
1422// =======================================================================
1423Standard_Boolean OpenGl_ShaderProgram::SetSampler (const Handle(OpenGl_Context)& theCtx,
1424 GLint theLocation,
cc8cbabe 1425 const Graphic3d_TextureUnit theTextureUnit)
30f0ad28 1426{
1427 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1428 {
1429 return Standard_False;
1430 }
1431
4e1523ef 1432 theCtx->core20fwd->glUniform1i (theLocation, theTextureUnit);
30f0ad28 1433 return Standard_True;
1434}
1435
1436// =======================================================================
1437// function : Create
1438// purpose : Creates new empty shader program of specified type
1439// =======================================================================
1440Standard_Boolean OpenGl_ShaderProgram::Create (const Handle(OpenGl_Context)& theCtx)
1441{
1442 if (myProgramID == NO_PROGRAM
4e1523ef 1443 && theCtx->core20fwd != NULL)
30f0ad28 1444 {
4e1523ef 1445 myProgramID = theCtx->core20fwd->glCreateProgram();
30f0ad28 1446 }
1447
1448 return myProgramID != NO_PROGRAM;
1449}
1450
1451// =======================================================================
1452// function : Release
1453// purpose : Destroys shader program
1454// =======================================================================
10b9c7df 1455void OpenGl_ShaderProgram::Release (OpenGl_Context* theCtx)
30f0ad28 1456{
1457 if (myProgramID == NO_PROGRAM)
1458 {
1459 return;
1460 }
1461
1462 Standard_ASSERT_RETURN (theCtx != NULL,
1463 "OpenGl_ShaderProgram destroyed without GL context! Possible GPU memory leakage...",);
1464
1465 for (OpenGl_ShaderList::Iterator anIter (myShaderObjects); anIter.More(); anIter.Next())
1466 {
fc73a202 1467 if (!anIter.Value().IsNull())
1468 {
1469 anIter.ChangeValue()->Release (theCtx);
1470 anIter.ChangeValue().Nullify();
1471 }
30f0ad28 1472 }
1473
4e1523ef 1474 if (theCtx->core20fwd != NULL
ec2eeb2d 1475 && theCtx->IsValid())
30f0ad28 1476 {
4e1523ef 1477 theCtx->core20fwd->glDeleteProgram (myProgramID);
30f0ad28 1478 }
1479
1480 myProgramID = NO_PROGRAM;
1481}