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