1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qopenglshaderprogram.h"
5#include "qopenglextrafunctions.h"
6#include "private/qopenglcontext_p.h"
7#include <QtOpenGL/QOpenGLVersionFunctionsFactory>
8#include <QtCore/private/qobject_p.h>
9#include <QtCore/qdebug.h>
10#include <QtCore/qfile.h>
11#include <QtCore/qlist.h>
12#include <QtCore/qloggingcategory.h>
13#include <QtCore/qvarlengtharray.h>
14#include <QtGui/private/qopenglprogrambinarycache_p.h>
15#include <QtGui/qtransform.h>
16#include <QtGui/QColor>
17#include <QtGui/QSurfaceFormat>
18
19#if !QT_CONFIG(opengles2)
20#include <QtOpenGL/qopenglfunctions_4_0_core.h>
21#endif
22
23#include <algorithm>
24#include <memory>
25
26QT_BEGIN_NAMESPACE
27
28using namespace Qt::StringLiterals;
29
30/*!
31 \class QOpenGLShaderProgram
32 \brief The QOpenGLShaderProgram class allows OpenGL shader programs to be linked and used.
33 \since 5.0
34 \ingroup painting-3D
35 \inmodule QtOpenGL
36
37 \section1 Introduction
38
39 This class supports shader programs written in the OpenGL Shading
40 Language (GLSL) and in the OpenGL/ES Shading Language (GLSL/ES).
41
42 QOpenGLShader and QOpenGLShaderProgram shelter the programmer from the details of
43 compiling and linking vertex and fragment shaders.
44
45 The following example creates a vertex shader program using the
46 supplied source \c{code}. Once compiled and linked, the shader
47 program is activated in the current QOpenGLContext by calling
48 QOpenGLShaderProgram::bind():
49
50 \snippet code/src_gui_qopenglshaderprogram.cpp 0
51
52 \section1 Writing Portable Shaders
53
54 Shader programs can be difficult to reuse across OpenGL implementations
55 because of varying levels of support for standard vertex attributes and
56 uniform variables. In particular, GLSL/ES lacks all of the
57 standard variables that are present on desktop OpenGL systems:
58 \c{gl_Vertex}, \c{gl_Normal}, \c{gl_Color}, and so on. Desktop OpenGL
59 lacks the variable qualifiers \c{highp}, \c{mediump}, and \c{lowp}.
60
61 The QOpenGLShaderProgram class makes the process of writing portable shaders
62 easier by prefixing all shader programs with the following lines on
63 desktop OpenGL:
64
65 \code
66 #define highp
67 #define mediump
68 #define lowp
69 \endcode
70
71 This makes it possible to run most GLSL/ES shader programs
72 on desktop systems. The programmer should restrict themselves
73 to just features that are present in GLSL/ES, and avoid
74 standard variable names that only work on the desktop.
75
76 \section1 Simple Shader Example
77
78 \snippet code/src_gui_qopenglshaderprogram.cpp 1
79
80 With the above shader program active, we can draw a green triangle
81 as follows:
82
83 \snippet code/src_gui_qopenglshaderprogram.cpp 2
84
85 \section1 Binary Shaders and Programs
86
87 Binary shaders may be specified using \c{glShaderBinary()} on
88 the return value from QOpenGLShader::shaderId(). The QOpenGLShader instance
89 containing the binary can then be added to the shader program with
90 addShader() and linked in the usual fashion with link().
91
92 Binary programs may be specified using \c{glProgramBinaryOES()}
93 on the return value from programId(). Then the application should
94 call link(), which will notice that the program has already been
95 specified and linked, allowing other operations to be performed
96 on the shader program. The shader program's id can be explicitly
97 created using the create() function.
98
99 \section2 Caching Program Binaries
100
101 As of Qt 5.9, support for caching program binaries on disk is built in. To
102 enable this, switch to using addCacheableShaderFromSourceCode() and
103 addCacheableShaderFromSourceFile(). With an OpenGL ES 3.x context or support
104 for \c{GL_ARB_get_program_binary}, this will transparently cache program
105 binaries under QStandardPaths::GenericCacheLocation or
106 QStandardPaths::CacheLocation. When support is not available, calling the
107 cacheable function variants is equivalent to the normal ones.
108
109 \note Some drivers do not have any binary formats available, even though
110 they advertise the extension or offer OpenGL ES 3.0. In this case program
111 binary support will be disabled.
112
113 \sa QOpenGLShader
114*/
115
116/*!
117 \class QOpenGLShader
118 \brief The QOpenGLShader class allows OpenGL shaders to be compiled.
119 \since 5.0
120 \ingroup painting-3D
121 \inmodule QtOpenGL
122
123 This class supports shaders written in the OpenGL Shading Language (GLSL)
124 and in the OpenGL/ES Shading Language (GLSL/ES).
125
126 QOpenGLShader and QOpenGLShaderProgram shelter the programmer from the details of
127 compiling and linking vertex and fragment shaders.
128
129 \sa QOpenGLShaderProgram
130*/
131
132/*!
133 \enum QOpenGLShader::ShaderTypeBit
134 This enum specifies the type of QOpenGLShader that is being created.
135
136 \value Vertex Vertex shader written in the OpenGL Shading Language (GLSL).
137 \value Fragment Fragment shader written in the OpenGL Shading Language (GLSL).
138 \value Geometry Geometry shaders written in the OpenGL Shading Language (GLSL)
139 (requires OpenGL >= 3.2 or OpenGL ES >= 3.2).
140 \value TessellationControl Tessellation control shaders written in the OpenGL
141 shading language (GLSL) (requires OpenGL >= 4.0 or OpenGL ES >= 3.2).
142 \value TessellationEvaluation Tessellation evaluation shaders written in the OpenGL
143 shading language (GLSL) (requires OpenGL >= 4.0 or OpenGL ES >= 3.2).
144 \value Compute Compute shaders written in the OpenGL shading language (GLSL)
145 (requires OpenGL >= 4.3 or OpenGL ES >= 3.1).
146*/
147
148// For GLES 3.1/3.2
149#ifndef GL_GEOMETRY_SHADER
150#define GL_GEOMETRY_SHADER 0x8DD9
151#endif
152#ifndef GL_TESS_CONTROL_SHADER
153#define GL_TESS_CONTROL_SHADER 0x8E88
154#endif
155#ifndef GL_TESS_EVALUATION_SHADER
156#define GL_TESS_EVALUATION_SHADER 0x8E87
157#endif
158#ifndef GL_COMPUTE_SHADER
159#define GL_COMPUTE_SHADER 0x91B9
160#endif
161#ifndef GL_MAX_GEOMETRY_OUTPUT_VERTICES
162#define GL_MAX_GEOMETRY_OUTPUT_VERTICES 0x8DE0
163#endif
164#ifndef GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS
165#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS 0x8DE1
166#endif
167#ifndef GL_PATCH_VERTICES
168#define GL_PATCH_VERTICES 0x8E72
169#endif
170#ifndef GL_PATCH_DEFAULT_OUTER_LEVEL
171#define GL_PATCH_DEFAULT_OUTER_LEVEL 0x8E74
172#endif
173#ifndef GL_PATCH_DEFAULT_INNER_LEVEL
174#define GL_PATCH_DEFAULT_INNER_LEVEL 0x8E73
175#endif
176
177#if !QT_CONFIG(opengles2)
178static inline bool isFormatGLES(const QSurfaceFormat &f)
179{
180 return (f.renderableType() == QSurfaceFormat::OpenGLES);
181}
182#endif
183
184static inline bool supportsGeometry(const QSurfaceFormat &f)
185{
186 return f.version() >= qMakePair(value1: 3, value2: 2);
187}
188
189static inline bool supportsCompute(const QSurfaceFormat &f)
190{
191#if !QT_CONFIG(opengles2)
192 if (!isFormatGLES(f))
193 return f.version() >= qMakePair(value1: 4, value2: 3);
194 else
195 return f.version() >= qMakePair(value1: 3, value2: 1);
196#else
197 return f.version() >= qMakePair(3, 1);
198#endif
199}
200
201static inline bool supportsTessellation(const QSurfaceFormat &f)
202{
203#if !QT_CONFIG(opengles2)
204 if (!isFormatGLES(f))
205 return f.version() >= qMakePair(value1: 4, value2: 0);
206 else
207 return f.version() >= qMakePair(value1: 3, value2: 2);
208#else
209 return f.version() >= qMakePair(3, 2);
210#endif
211}
212
213class QOpenGLShaderPrivate : public QObjectPrivate
214{
215 Q_DECLARE_PUBLIC(QOpenGLShader)
216public:
217 QOpenGLShaderPrivate(QOpenGLContext *ctx, QOpenGLShader::ShaderType type)
218 : shaderGuard(nullptr)
219 , shaderType(type)
220 , compiled(false)
221 , glfuncs(new QOpenGLExtraFunctions(ctx))
222 , supportsGeometryShaders(false)
223 , supportsTessellationShaders(false)
224 , supportsComputeShaders(false)
225 {
226 if (shaderType & QOpenGLShader::Geometry)
227 supportsGeometryShaders = supportsGeometry(f: ctx->format());
228 else if (shaderType & (QOpenGLShader::TessellationControl | QOpenGLShader::TessellationEvaluation))
229 supportsTessellationShaders = supportsTessellation(f: ctx->format());
230 else if (shaderType & QOpenGLShader::Compute)
231 supportsComputeShaders = supportsCompute(f: ctx->format());
232 }
233 ~QOpenGLShaderPrivate();
234
235 QOpenGLSharedResourceGuard *shaderGuard;
236 QOpenGLShader::ShaderType shaderType;
237 bool compiled;
238 QString log;
239
240 QOpenGLExtraFunctions *glfuncs;
241
242 // Support for geometry shaders
243 bool supportsGeometryShaders;
244 // Support for tessellation shaders
245 bool supportsTessellationShaders;
246 // Support for compute shaders
247 bool supportsComputeShaders;
248
249
250 bool create();
251 bool compile(QOpenGLShader *q);
252 void deleteShader();
253};
254
255namespace {
256 void freeShaderFunc(QOpenGLFunctions *funcs, GLuint id)
257 {
258 funcs->glDeleteShader(shader: id);
259 }
260}
261
262QOpenGLShaderPrivate::~QOpenGLShaderPrivate()
263{
264 delete glfuncs;
265 if (shaderGuard)
266 shaderGuard->free();
267}
268
269bool QOpenGLShaderPrivate::create()
270{
271 QOpenGLContext *context = const_cast<QOpenGLContext *>(QOpenGLContext::currentContext());
272 if (!context)
273 return false;
274 GLuint shader = 0;
275 if (shaderType == QOpenGLShader::Vertex) {
276 shader = glfuncs->glCreateShader(GL_VERTEX_SHADER);
277 } else if (shaderType == QOpenGLShader::Geometry && supportsGeometryShaders) {
278 shader = glfuncs->glCreateShader(GL_GEOMETRY_SHADER);
279 } else if (shaderType == QOpenGLShader::TessellationControl && supportsTessellationShaders) {
280 shader = glfuncs->glCreateShader(GL_TESS_CONTROL_SHADER);
281 } else if (shaderType == QOpenGLShader::TessellationEvaluation && supportsTessellationShaders) {
282 shader = glfuncs->glCreateShader(GL_TESS_EVALUATION_SHADER);
283 } else if (shaderType == QOpenGLShader::Compute && supportsComputeShaders) {
284 shader = glfuncs->glCreateShader(GL_COMPUTE_SHADER);
285 } else if (shaderType == QOpenGLShader::Fragment) {
286 shader = glfuncs->glCreateShader(GL_FRAGMENT_SHADER);
287 }
288 if (!shader) {
289 qWarning(msg: "QOpenGLShader: could not create shader");
290 return false;
291 }
292 shaderGuard = new QOpenGLSharedResourceGuard(context, shader, freeShaderFunc);
293 return true;
294}
295
296bool QOpenGLShaderPrivate::compile(QOpenGLShader *q)
297{
298 GLuint shader = shaderGuard ? shaderGuard->id() : 0;
299 if (!shader)
300 return false;
301
302 // Try to compile shader
303 glfuncs->glCompileShader(shader);
304 GLint value = 0;
305
306 // Get compilation status
307 glfuncs->glGetShaderiv(shader, GL_COMPILE_STATUS, params: &value);
308 compiled = (value != 0);
309
310 if (!compiled) {
311 // Compilation failed, try to provide some information about the failure
312 QString name = q->objectName();
313
314 const char *types[] = {
315 "Fragment",
316 "Vertex",
317 "Geometry",
318 "Tessellation Control",
319 "Tessellation Evaluation",
320 "Compute",
321 ""
322 };
323
324 const char *type = types[6];
325 switch (shaderType) {
326 case QOpenGLShader::Fragment:
327 type = types[0]; break;
328 case QOpenGLShader::Vertex:
329 type = types[1]; break;
330 case QOpenGLShader::Geometry:
331 type = types[2]; break;
332 case QOpenGLShader::TessellationControl:
333 type = types[3]; break;
334 case QOpenGLShader::TessellationEvaluation:
335 type = types[4]; break;
336 case QOpenGLShader::Compute:
337 type = types[5]; break;
338 }
339
340 // Get info and source code lengths
341 GLint infoLogLength = 0;
342 GLint sourceCodeLength = 0;
343 char *logBuffer = nullptr;
344 char *sourceCodeBuffer = nullptr;
345
346 // Get the compilation info log
347 glfuncs->glGetShaderiv(shader, GL_INFO_LOG_LENGTH, params: &infoLogLength);
348
349 if (infoLogLength > 1) {
350 GLint temp;
351 logBuffer = new char [infoLogLength];
352 glfuncs->glGetShaderInfoLog(shader, bufsize: infoLogLength, length: &temp, infolog: logBuffer);
353 }
354
355 // Get the source code
356 glfuncs->glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, params: &sourceCodeLength);
357
358 if (sourceCodeLength > 1) {
359 GLint temp;
360 sourceCodeBuffer = new char [sourceCodeLength];
361 glfuncs->glGetShaderSource(shader, bufsize: sourceCodeLength, length: &temp, source: sourceCodeBuffer);
362 }
363
364 if (logBuffer)
365 log = QString::fromLatin1(ba: logBuffer);
366 else
367 log = u"failed"_s;
368
369 if (name.isEmpty())
370 qWarning(msg: "QOpenGLShader::compile(%s): %s", type, qPrintable(log));
371 else
372 qWarning(msg: "QOpenGLShader::compile(%s)[%s]: %s", type, qPrintable(name), qPrintable(log));
373
374 // Dump the source code if we got it
375 if (sourceCodeBuffer) {
376 qWarning(msg: "*** Problematic %s shader source code ***\n"
377 "%ls\n"
378 "***",
379 type, qUtf16Printable(QString::fromLatin1(sourceCodeBuffer)));
380 }
381
382 // Cleanup
383 delete [] logBuffer;
384 delete [] sourceCodeBuffer;
385 }
386
387 return compiled;
388}
389
390void QOpenGLShaderPrivate::deleteShader()
391{
392 if (shaderGuard) {
393 shaderGuard->free();
394 shaderGuard = nullptr;
395 }
396}
397
398/*!
399 Constructs a new QOpenGLShader object of the specified \a type
400 and attaches it to \a parent. If shader programs are not supported,
401 QOpenGLShaderProgram::hasOpenGLShaderPrograms() will return false.
402
403 This constructor is normally followed by a call to compileSourceCode()
404 or compileSourceFile().
405
406 The shader will be associated with the current QOpenGLContext.
407
408 \sa compileSourceCode(), compileSourceFile()
409*/
410QOpenGLShader::QOpenGLShader(QOpenGLShader::ShaderType type, QObject *parent)
411 : QObject(*new QOpenGLShaderPrivate(QOpenGLContext::currentContext(), type), parent)
412{
413 Q_D(QOpenGLShader);
414 d->create();
415}
416
417/*!
418 Deletes this shader. If the shader has been attached to a
419 QOpenGLShaderProgram object, then the actual shader will stay around
420 until the QOpenGLShaderProgram is destroyed.
421*/
422QOpenGLShader::~QOpenGLShader()
423{
424}
425
426/*!
427 Returns the type of this shader.
428*/
429QOpenGLShader::ShaderType QOpenGLShader::shaderType() const
430{
431 Q_D(const QOpenGLShader);
432 return d->shaderType;
433}
434
435static const char qualifierDefines[] =
436 "#define lowp\n"
437 "#define mediump\n"
438 "#define highp\n";
439
440#if QT_CONFIG(opengles2) && !defined(QT_OPENGL_FORCE_SHADER_DEFINES)
441// The "highp" qualifier doesn't exist in fragment shaders
442// on all ES platforms. When it doesn't exist, use "mediump".
443#define QOpenGL_REDEFINE_HIGHP 1
444static const char redefineHighp[] =
445 "#ifndef GL_FRAGMENT_PRECISION_HIGH\n"
446 "#define highp mediump\n"
447 "#endif\n";
448#endif
449
450// Boiler-plate header to have the layout attributes available we need later
451static const char blendEquationAdvancedHeader[] =
452 "#ifdef GL_KHR_blend_equation_advanced\n"
453 "#extension GL_ARB_fragment_coord_conventions : enable\n"
454 "#extension GL_KHR_blend_equation_advanced : enable\n"
455 "#endif\n";
456
457struct QVersionDirectivePosition
458{
459 constexpr QVersionDirectivePosition(int position = 0, int line = -1)
460 : position(position)
461 , line(line)
462 {
463 }
464
465 constexpr bool hasPosition() const
466 {
467 return position > 0;
468 }
469
470 const int position;
471 const int line;
472};
473
474static QVersionDirectivePosition findVersionDirectivePosition(const char *source)
475{
476 Q_ASSERT(source);
477
478 // According to the GLSL spec the #version directive must not be
479 // preceded by anything but whitespace and comments.
480 // In order to not get confused by #version directives within a
481 // multiline comment, we need to do some minimal comment parsing
482 // while searching for the directive.
483 enum {
484 Normal,
485 StartOfLine,
486 PreprocessorDirective,
487 CommentStarting,
488 MultiLineComment,
489 SingleLineComment,
490 CommentEnding
491 } state = StartOfLine;
492
493 const char *c = source;
494 while (*c) {
495 switch (state) {
496 case PreprocessorDirective:
497 if (*c == ' ' || *c == '\t')
498 break;
499 if (!strncmp(s1: c, s2: "version", n: strlen(s: "version"))) {
500 // Found version directive
501 c += strlen(s: "version");
502 while (*c && *c != '\n')
503 ++c;
504 int splitPosition = c - source + 1;
505 int linePosition = int(std::count(first: source, last: c, value: '\n')) + 1;
506 return QVersionDirectivePosition(splitPosition, linePosition);
507 } else if (*c == '/')
508 state = CommentStarting;
509 else if (*c == '\n')
510 state = StartOfLine;
511 else
512 state = Normal;
513 break;
514 case StartOfLine:
515 if (*c == ' ' || *c == '\t')
516 break;
517 else if (*c == '#') {
518 state = PreprocessorDirective;
519 break;
520 }
521 state = Normal;
522 Q_FALLTHROUGH();
523 case Normal:
524 if (*c == '/')
525 state = CommentStarting;
526 else if (*c == '\n')
527 state = StartOfLine;
528 break;
529 case CommentStarting:
530 if (*c == '*')
531 state = MultiLineComment;
532 else if (*c == '/')
533 state = SingleLineComment;
534 else
535 state = Normal;
536 break;
537 case MultiLineComment:
538 if (*c == '*')
539 state = CommentEnding;
540 break;
541 case SingleLineComment:
542 if (*c == '\n')
543 state = Normal;
544 break;
545 case CommentEnding:
546 if (*c == '/')
547 state = Normal;
548 else if (*c != u'*')
549 state = MultiLineComment;
550 break;
551 }
552 ++c;
553 }
554
555 return QVersionDirectivePosition(0, 1);
556}
557
558/*!
559 Sets the \a source code for this shader and compiles it.
560 Returns \c true if the source was successfully compiled, false otherwise.
561
562 \sa compileSourceFile()
563*/
564bool QOpenGLShader::compileSourceCode(const char *source)
565{
566 Q_D(QOpenGLShader);
567 // This method breaks the shader code into two parts:
568 // 1. Up to and including an optional #version directive.
569 // 2. The rest.
570 // If a #version directive exists, qualifierDefines and redefineHighp
571 // are inserted after. Otherwise they are inserted right at the start.
572 // In both cases a #line directive is appended in order to compensate
573 // for line number changes in case of compiler errors.
574
575 if (d->shaderGuard && d->shaderGuard->id() && source) {
576 const QVersionDirectivePosition versionDirectivePosition = findVersionDirectivePosition(source);
577
578 QVarLengthArray<const char *, 5> sourceChunks;
579 QVarLengthArray<GLint, 5> sourceChunkLengths;
580 QOpenGLContext *ctx = QOpenGLContext::currentContext();
581
582 if (versionDirectivePosition.hasPosition()) {
583 // Append source up to and including the #version directive
584 sourceChunks.append(t: source);
585 sourceChunkLengths.append(t: GLint(versionDirectivePosition.position));
586 } else {
587 // QTBUG-55733: Intel on Windows with Compatibility profile requires a #version always
588 if (ctx->format().profile() == QSurfaceFormat::CompatibilityProfile) {
589 const char *vendor = reinterpret_cast<const char *>(ctx->functions()->glGetString(GL_VENDOR));
590 if (vendor && !strcmp(s1: vendor, s2: "Intel")) {
591 static const char version110[] = "#version 110\n";
592 sourceChunks.append(t: version110);
593 sourceChunkLengths.append(t: GLint(sizeof(version110)) - 1);
594 }
595 }
596 }
597 if (d->shaderType == Fragment) {
598 sourceChunks.append(t: blendEquationAdvancedHeader);
599 sourceChunkLengths.append(t: GLint(sizeof(blendEquationAdvancedHeader) - 1));
600 }
601
602 // The precision qualifiers are useful on OpenGL/ES systems,
603 // but usually not present on desktop systems.
604 const QSurfaceFormat currentSurfaceFormat = ctx->format();
605 QOpenGLContextPrivate *ctx_d = QOpenGLContextPrivate::get(context: QOpenGLContext::currentContext());
606 if (currentSurfaceFormat.renderableType() == QSurfaceFormat::OpenGL
607 || ctx_d->workaround_missingPrecisionQualifiers
608#ifdef QT_OPENGL_FORCE_SHADER_DEFINES
609 || true
610#endif
611 ) {
612 sourceChunks.append(t: qualifierDefines);
613 sourceChunkLengths.append(t: GLint(sizeof(qualifierDefines) - 1));
614 }
615
616#ifdef QOpenGL_REDEFINE_HIGHP
617 if (d->shaderType == Fragment && !ctx_d->workaround_missingPrecisionQualifiers
618 && QOpenGLContext::currentContext()->isOpenGLES()) {
619 sourceChunks.append(redefineHighp);
620 sourceChunkLengths.append(GLint(sizeof(redefineHighp) - 1));
621 }
622#endif
623
624 QByteArray lineDirective;
625 // #line is rejected by some drivers:
626 // "2.1 Mesa 8.1-devel (git-48a3d4e)" or "MESA 2.1 Mesa 8.1-devel"
627 const char *version = reinterpret_cast<const char *>(ctx->functions()->glGetString(GL_VERSION));
628 if (!version || !strstr(haystack: version, needle: "2.1 Mesa 8")) {
629 // Append #line directive in order to compensate for text insertion
630 lineDirective = QStringLiteral("#line %1\n").arg(a: versionDirectivePosition.line).toUtf8();
631 sourceChunks.append(t: lineDirective.constData());
632 sourceChunkLengths.append(t: GLint(lineDirective.size()));
633 }
634
635 // Append rest of shader code
636 sourceChunks.append(t: source + versionDirectivePosition.position);
637 sourceChunkLengths.append(t: GLint(qstrlen(str: source + versionDirectivePosition.position)));
638
639 d->glfuncs->glShaderSource(shader: d->shaderGuard->id(), count: sourceChunks.size(), string: sourceChunks.data(), length: sourceChunkLengths.data());
640 return d->compile(q: this);
641 } else {
642 return false;
643 }
644}
645
646/*!
647 \overload
648
649 Sets the \a source code for this shader and compiles it.
650 Returns \c true if the source was successfully compiled, false otherwise.
651
652 \sa compileSourceFile()
653*/
654bool QOpenGLShader::compileSourceCode(const QByteArray& source)
655{
656 return compileSourceCode(source: source.constData());
657}
658
659/*!
660 \overload
661
662 Sets the \a source code for this shader and compiles it.
663 Returns \c true if the source was successfully compiled, false otherwise.
664
665 \sa compileSourceFile()
666*/
667bool QOpenGLShader::compileSourceCode(const QString& source)
668{
669 return compileSourceCode(source: source.toLatin1().constData());
670}
671
672/*!
673 Sets the source code for this shader to the contents of \a fileName
674 and compiles it. Returns \c true if the file could be opened and the
675 source compiled, false otherwise.
676
677 \sa compileSourceCode()
678*/
679bool QOpenGLShader::compileSourceFile(const QString& fileName)
680{
681 QFile file(fileName);
682 if (!file.open(flags: QFile::ReadOnly)) {
683 qWarning() << "QOpenGLShader: Unable to open file" << fileName;
684 return false;
685 }
686
687 QByteArray contents = file.readAll();
688 return compileSourceCode(source: contents.constData());
689}
690
691/*!
692 Returns the source code for this shader.
693
694 \sa compileSourceCode()
695*/
696QByteArray QOpenGLShader::sourceCode() const
697{
698 Q_D(const QOpenGLShader);
699 GLuint shader = d->shaderGuard ? d->shaderGuard->id() : 0;
700 if (!shader)
701 return QByteArray();
702 GLint size = 0;
703 d->glfuncs->glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, params: &size);
704 if (size <= 0)
705 return QByteArray();
706 GLint len = 0;
707 char *source = new char [size];
708 d->glfuncs->glGetShaderSource(shader, bufsize: size, length: &len, source);
709 QByteArray src(source);
710 delete [] source;
711 return src;
712}
713
714/*!
715 Returns \c true if this shader has been compiled; false otherwise.
716
717 \sa compileSourceCode(), compileSourceFile()
718*/
719bool QOpenGLShader::isCompiled() const
720{
721 Q_D(const QOpenGLShader);
722 return d->compiled;
723}
724
725/*!
726 Returns the errors and warnings that occurred during the last compile.
727
728 \sa compileSourceCode(), compileSourceFile()
729*/
730QString QOpenGLShader::log() const
731{
732 Q_D(const QOpenGLShader);
733 return d->log;
734}
735
736/*!
737 Returns the OpenGL identifier associated with this shader.
738
739 \sa QOpenGLShaderProgram::programId()
740*/
741GLuint QOpenGLShader::shaderId() const
742{
743 Q_D(const QOpenGLShader);
744 return d->shaderGuard ? d->shaderGuard->id() : 0;
745}
746
747class QOpenGLShaderProgramPrivate : public QObjectPrivate
748{
749 Q_DECLARE_PUBLIC(QOpenGLShaderProgram)
750public:
751 QOpenGLShaderProgramPrivate()
752 : programGuard(nullptr)
753 , linked(false)
754 , inited(false)
755 , removingShaders(false)
756 , glfuncs(new QOpenGLExtraFunctions)
757#if !QT_CONFIG(opengles2)
758 , tessellationFuncs(nullptr)
759#endif
760 , linkBinaryRecursion(false)
761 {
762 }
763 ~QOpenGLShaderProgramPrivate();
764
765 QOpenGLSharedResourceGuard *programGuard;
766 bool linked;
767 bool inited;
768 bool removingShaders;
769
770 QString log;
771 QList<QOpenGLShader *> shaders;
772 QList<QOpenGLShader *> anonShaders;
773
774 QOpenGLExtraFunctions *glfuncs;
775#if !QT_CONFIG(opengles2)
776 // for tessellation features not in GLES 3.2
777 QOpenGLFunctions_4_0_Core *tessellationFuncs;
778#endif
779
780 bool hasShader(QOpenGLShader::ShaderType type) const;
781
782 QOpenGLProgramBinaryCache::ProgramDesc binaryProgram;
783 bool isCacheDisabled() const;
784 bool compileCacheable();
785 bool linkBinary();
786
787 bool linkBinaryRecursion;
788};
789
790namespace {
791 void freeProgramFunc(QOpenGLFunctions *funcs, GLuint id)
792 {
793 funcs->glDeleteProgram(program: id);
794 }
795}
796
797
798QOpenGLShaderProgramPrivate::~QOpenGLShaderProgramPrivate()
799{
800 delete glfuncs;
801 if (programGuard)
802 programGuard->free();
803}
804
805bool QOpenGLShaderProgramPrivate::hasShader(QOpenGLShader::ShaderType type) const
806{
807 for (QOpenGLShader *shader : shaders) {
808 if (shader->shaderType() == type)
809 return true;
810 }
811 return false;
812}
813
814/*!
815 Constructs a new shader program and attaches it to \a parent.
816 The program will be invalid until addShader() is called.
817
818 The shader program will be associated with the current QOpenGLContext.
819
820 \sa addShader()
821*/
822QOpenGLShaderProgram::QOpenGLShaderProgram(QObject *parent)
823 : QObject(*new QOpenGLShaderProgramPrivate, parent)
824{
825}
826
827/*!
828 Deletes this shader program.
829*/
830QOpenGLShaderProgram::~QOpenGLShaderProgram()
831{
832}
833
834/*!
835 Requests the shader program's id to be created immediately. Returns \c true
836 if successful; \c false otherwise.
837
838 This function is primarily useful when combining QOpenGLShaderProgram
839 with other OpenGL functions that operate directly on the shader
840 program id, like \c {GL_OES_get_program_binary}.
841
842 When the shader program is used normally, the shader program's id will
843 be created on demand.
844
845 \sa programId()
846
847 \since 5.3
848 */
849bool QOpenGLShaderProgram::create()
850{
851 return init();
852}
853
854bool QOpenGLShaderProgram::init()
855{
856 Q_D(QOpenGLShaderProgram);
857 if ((d->programGuard && d->programGuard->id()) || d->inited)
858 return true;
859 d->inited = true;
860 QOpenGLContext *context = const_cast<QOpenGLContext *>(QOpenGLContext::currentContext());
861 if (!context)
862 return false;
863 d->glfuncs->initializeOpenGLFunctions();
864
865#if !QT_CONFIG(opengles2)
866 if (!context->isOpenGLES() && context->format().version() >= qMakePair(value1: 4, value2: 0)) {
867 d->tessellationFuncs = QOpenGLVersionFunctionsFactory::get<QOpenGLFunctions_4_0_Core>(context);
868 d->tessellationFuncs->initializeOpenGLFunctions();
869 }
870#endif
871
872 GLuint program = d->glfuncs->glCreateProgram();
873 if (!program) {
874 qWarning(msg: "QOpenGLShaderProgram: could not create shader program");
875 return false;
876 }
877 if (d->programGuard)
878 delete d->programGuard;
879 d->programGuard = new QOpenGLSharedResourceGuard(context, program, freeProgramFunc);
880 return true;
881}
882
883/*!
884 Adds a compiled \a shader to this shader program. Returns \c true
885 if the shader could be added, or false otherwise.
886
887 Ownership of the \a shader object remains with the caller.
888 It will not be deleted when this QOpenGLShaderProgram instance
889 is deleted. This allows the caller to add the same shader
890 to multiple shader programs.
891
892 \sa addShaderFromSourceCode(), addShaderFromSourceFile()
893 \sa removeShader(), link(), removeAllShaders()
894*/
895bool QOpenGLShaderProgram::addShader(QOpenGLShader *shader)
896{
897 Q_D(QOpenGLShaderProgram);
898 if (!init())
899 return false;
900 if (d->shaders.contains(t: shader))
901 return true; // Already added to this shader program.
902 if (d->programGuard && d->programGuard->id() && shader) {
903 if (!shader->d_func()->shaderGuard || !shader->d_func()->shaderGuard->id())
904 return false;
905 if (d->programGuard->group() != shader->d_func()->shaderGuard->group()) {
906 qWarning(msg: "QOpenGLShaderProgram::addShader: Program and shader are not associated with same context.");
907 return false;
908 }
909 d->glfuncs->glAttachShader(program: d->programGuard->id(), shader: shader->d_func()->shaderGuard->id());
910 d->linked = false; // Program needs to be relinked.
911 d->shaders.append(t: shader);
912 connect(sender: shader, SIGNAL(destroyed()), receiver: this, SLOT(shaderDestroyed()));
913 return true;
914 } else {
915 return false;
916 }
917}
918
919/*!
920 Compiles \a source as a shader of the specified \a type and
921 adds it to this shader program. Returns \c true if compilation
922 was successful, false otherwise. The compilation errors
923 and warnings will be made available via log().
924
925 This function is intended to be a short-cut for quickly
926 adding vertex and fragment shaders to a shader program without
927 creating an instance of QOpenGLShader first.
928
929 \sa addShader(), addShaderFromSourceFile()
930 \sa removeShader(), link(), log(), removeAllShaders()
931*/
932bool QOpenGLShaderProgram::addShaderFromSourceCode(QOpenGLShader::ShaderType type, const char *source)
933{
934 Q_D(QOpenGLShaderProgram);
935 if (!init())
936 return false;
937 QOpenGLShader *shader = new QOpenGLShader(type, this);
938 if (!shader->compileSourceCode(source)) {
939 d->log = shader->log();
940 delete shader;
941 return false;
942 }
943 d->anonShaders.append(t: shader);
944 return addShader(shader);
945}
946
947/*!
948 \overload
949
950 Compiles \a source as a shader of the specified \a type and
951 adds it to this shader program. Returns \c true if compilation
952 was successful, false otherwise. The compilation errors
953 and warnings will be made available via log().
954
955 This function is intended to be a short-cut for quickly
956 adding vertex and fragment shaders to a shader program without
957 creating an instance of QOpenGLShader first.
958
959 \sa addShader(), addShaderFromSourceFile()
960 \sa removeShader(), link(), log(), removeAllShaders()
961*/
962bool QOpenGLShaderProgram::addShaderFromSourceCode(QOpenGLShader::ShaderType type, const QByteArray& source)
963{
964 return addShaderFromSourceCode(type, source: source.constData());
965}
966
967/*!
968 \overload
969
970 Compiles \a source as a shader of the specified \a type and
971 adds it to this shader program. Returns \c true if compilation
972 was successful, false otherwise. The compilation errors
973 and warnings will be made available via log().
974
975 This function is intended to be a short-cut for quickly
976 adding vertex and fragment shaders to a shader program without
977 creating an instance of QOpenGLShader first.
978
979 \sa addShader(), addShaderFromSourceFile()
980 \sa removeShader(), link(), log(), removeAllShaders()
981*/
982bool QOpenGLShaderProgram::addShaderFromSourceCode(QOpenGLShader::ShaderType type, const QString& source)
983{
984 return addShaderFromSourceCode(type, source: source.toLatin1().constData());
985}
986
987/*!
988 Compiles the contents of \a fileName as a shader of the specified
989 \a type and adds it to this shader program. Returns \c true if
990 compilation was successful, false otherwise. The compilation errors
991 and warnings will be made available via log().
992
993 This function is intended to be a short-cut for quickly
994 adding vertex and fragment shaders to a shader program without
995 creating an instance of QOpenGLShader first.
996
997 \sa addShader(), addShaderFromSourceCode()
998*/
999bool QOpenGLShaderProgram::addShaderFromSourceFile
1000 (QOpenGLShader::ShaderType type, const QString& fileName)
1001{
1002 Q_D(QOpenGLShaderProgram);
1003 if (!init())
1004 return false;
1005 QOpenGLShader *shader = new QOpenGLShader(type, this);
1006 if (!shader->compileSourceFile(fileName)) {
1007 d->log = shader->log();
1008 delete shader;
1009 return false;
1010 }
1011 d->anonShaders.append(t: shader);
1012 return addShader(shader);
1013}
1014
1015/*!
1016 Registers the shader of the specified \a type and \a source to this
1017 program. Unlike addShaderFromSourceCode(), this function does not perform
1018 compilation. Compilation is deferred to link(), and may not happen at all,
1019 because link() may potentially use a program binary from Qt's shader disk
1020 cache. This will typically lead to a significant increase in performance.
1021
1022 \return true if the shader has been registered or, in the non-cached case,
1023 compiled successfully; false if there was an error. The compilation error
1024 messages can be retrieved via log().
1025
1026 When the disk cache is disabled, via Qt::AA_DisableShaderDiskCache for
1027 example, or the OpenGL context has no support for context binaries, calling
1028 this function is equivalent to addShaderFromSourceCode().
1029
1030 \since 5.9
1031 \sa addShaderFromSourceCode(), addCacheableShaderFromSourceFile()
1032 */
1033bool QOpenGLShaderProgram::addCacheableShaderFromSourceCode(QOpenGLShader::ShaderType type, const char *source)
1034{
1035 Q_D(QOpenGLShaderProgram);
1036 if (!init())
1037 return false;
1038 if (d->isCacheDisabled())
1039 return addShaderFromSourceCode(type, source);
1040
1041 return addCacheableShaderFromSourceCode(type, source: QByteArray(source));
1042}
1043
1044static inline QShader::Stage qt_shaderTypeToStage(QOpenGLShader::ShaderType type)
1045{
1046 switch (type) {
1047 case QOpenGLShader::Vertex:
1048 return QShader::VertexStage;
1049 case QOpenGLShader::Fragment:
1050 return QShader::FragmentStage;
1051 case QOpenGLShader::Geometry:
1052 return QShader::GeometryStage;
1053 case QOpenGLShader::TessellationControl:
1054 return QShader::TessellationControlStage;
1055 case QOpenGLShader::TessellationEvaluation:
1056 return QShader::TessellationEvaluationStage;
1057 case QOpenGLShader::Compute:
1058 return QShader::ComputeStage;
1059 }
1060 return QShader::VertexStage;
1061}
1062
1063static inline QOpenGLShader::ShaderType qt_shaderStageToType(QShader::Stage stage)
1064{
1065 switch (stage) {
1066 case QShader::VertexStage:
1067 return QOpenGLShader::Vertex;
1068 case QShader::TessellationControlStage:
1069 return QOpenGLShader::TessellationControl;
1070 case QShader::TessellationEvaluationStage:
1071 return QOpenGLShader::TessellationEvaluation;
1072 case QShader::GeometryStage:
1073 return QOpenGLShader::Geometry;
1074 case QShader::FragmentStage:
1075 return QOpenGLShader::Fragment;
1076 case QShader::ComputeStage:
1077 return QOpenGLShader::Compute;
1078 }
1079 return QOpenGLShader::Vertex;
1080}
1081
1082/*!
1083 \overload
1084
1085 Registers the shader of the specified \a type and \a source to this
1086 program. Unlike addShaderFromSourceCode(), this function does not perform
1087 compilation. Compilation is deferred to link(), and may not happen at all,
1088 because link() may potentially use a program binary from Qt's shader disk
1089 cache. This will typically lead to a significant increase in performance.
1090
1091 \return true if the shader has been registered or, in the non-cached case,
1092 compiled successfully; false if there was an error. The compilation error
1093 messages can be retrieved via log().
1094
1095 When the disk cache is disabled, via Qt::AA_DisableShaderDiskCache for
1096 example, or the OpenGL context has no support for context binaries, calling
1097 this function is equivalent to addShaderFromSourceCode().
1098
1099 \since 5.9
1100 \sa addShaderFromSourceCode(), addCacheableShaderFromSourceFile()
1101 */
1102bool QOpenGLShaderProgram::addCacheableShaderFromSourceCode(QOpenGLShader::ShaderType type, const QByteArray &source)
1103{
1104 Q_D(QOpenGLShaderProgram);
1105 if (!init())
1106 return false;
1107 if (d->isCacheDisabled())
1108 return addShaderFromSourceCode(type, source);
1109
1110 d->binaryProgram.shaders.append(t: QOpenGLProgramBinaryCache::ShaderDesc(qt_shaderTypeToStage(type), source));
1111 return true;
1112}
1113
1114/*!
1115 \overload
1116
1117 Registers the shader of the specified \a type and \a source to this
1118 program. Unlike addShaderFromSourceCode(), this function does not perform
1119 compilation. Compilation is deferred to link(), and may not happen at all,
1120 because link() may potentially use a program binary from Qt's shader disk
1121 cache. This will typically lead to a significant increase in performance.
1122
1123 When the disk cache is disabled, via Qt::AA_DisableShaderDiskCache for
1124 example, or the OpenGL context has no support for context binaries, calling
1125 this function is equivalent to addShaderFromSourceCode().
1126
1127 \since 5.9
1128 \sa addShaderFromSourceCode(), addCacheableShaderFromSourceFile()
1129 */
1130bool QOpenGLShaderProgram::addCacheableShaderFromSourceCode(QOpenGLShader::ShaderType type, const QString &source)
1131{
1132 Q_D(QOpenGLShaderProgram);
1133 if (!init())
1134 return false;
1135 if (d->isCacheDisabled())
1136 return addShaderFromSourceCode(type, source);
1137
1138 return addCacheableShaderFromSourceCode(type, source: source.toUtf8().constData());
1139}
1140
1141/*!
1142 Registers the shader of the specified \a type and \a fileName to this
1143 program. Unlike addShaderFromSourceFile(), this function does not perform
1144 compilation. Compilation is deferred to link(), and may not happen at all,
1145 because link() may potentially use a program binary from Qt's shader disk
1146 cache. This will typically lead to a significant increase in performance.
1147
1148 \return true if the file has been read successfully, false if the file could
1149 not be opened or the normal, non-cached compilation of the shader has
1150 failed. The compilation error messages can be retrieved via log().
1151
1152 When the disk cache is disabled, via Qt::AA_DisableShaderDiskCache for
1153 example, or the OpenGL context has no support for context binaries, calling
1154 this function is equivalent to addShaderFromSourceFile().
1155
1156 \since 5.9
1157 \sa addShaderFromSourceFile(), addCacheableShaderFromSourceCode()
1158 */
1159bool QOpenGLShaderProgram::addCacheableShaderFromSourceFile(QOpenGLShader::ShaderType type, const QString &fileName)
1160{
1161 Q_D(QOpenGLShaderProgram);
1162 if (!init())
1163 return false;
1164 if (d->isCacheDisabled())
1165 return addShaderFromSourceFile(type, fileName);
1166
1167 QOpenGLProgramBinaryCache::ShaderDesc shader(qt_shaderTypeToStage(type));
1168 // NB! It could be tempting to defer reading the file contents and just
1169 // hash the filename as the cache key, perhaps combined with last-modified
1170 // timestamp checks. However, this would raise a number of issues (no
1171 // timestamps for files in the resource system; preference for global, not
1172 // per-application cache items (where filenames may clash); resource-based
1173 // shaders from libraries like Qt Quick; etc.), so just avoid it.
1174 QFile f(fileName);
1175 if (f.open(flags: QIODevice::ReadOnly | QIODevice::Text)) {
1176 shader.source = f.readAll();
1177 f.close();
1178 } else {
1179 qWarning(msg: "QOpenGLShaderProgram: Unable to open file %s", qPrintable(fileName));
1180 return false;
1181 }
1182 d->binaryProgram.shaders.append(t: shader);
1183 return true;
1184}
1185
1186/*!
1187 Removes \a shader from this shader program. The object is not deleted.
1188
1189 The shader program must be valid in the current QOpenGLContext.
1190
1191 \sa addShader(), link(), removeAllShaders()
1192*/
1193void QOpenGLShaderProgram::removeShader(QOpenGLShader *shader)
1194{
1195 Q_D(QOpenGLShaderProgram);
1196 if (d->programGuard && d->programGuard->id()
1197 && shader && shader->d_func()->shaderGuard)
1198 {
1199 d->glfuncs->glDetachShader(program: d->programGuard->id(), shader: shader->d_func()->shaderGuard->id());
1200 }
1201 d->linked = false; // Program needs to be relinked.
1202 if (shader) {
1203 d->shaders.removeAll(t: shader);
1204 d->anonShaders.removeAll(t: shader);
1205 disconnect(sender: shader, SIGNAL(destroyed()), receiver: this, SLOT(shaderDestroyed()));
1206 }
1207}
1208
1209/*!
1210 Returns a list of all shaders that have been added to this shader
1211 program using addShader().
1212
1213 \sa addShader(), removeShader()
1214*/
1215QList<QOpenGLShader *> QOpenGLShaderProgram::shaders() const
1216{
1217 Q_D(const QOpenGLShaderProgram);
1218 return d->shaders;
1219}
1220
1221/*!
1222 Removes all of the shaders that were added to this program previously.
1223 The QOpenGLShader objects for the shaders will not be deleted if they
1224 were constructed externally. QOpenGLShader objects that are constructed
1225 internally by QOpenGLShaderProgram will be deleted.
1226
1227 \sa addShader(), removeShader()
1228*/
1229void QOpenGLShaderProgram::removeAllShaders()
1230{
1231 Q_D(QOpenGLShaderProgram);
1232 d->removingShaders = true;
1233 for (QOpenGLShader *shader : std::as_const(t&: d->shaders)) {
1234 if (d->programGuard && d->programGuard->id()
1235 && shader && shader->d_func()->shaderGuard)
1236 {
1237 d->glfuncs->glDetachShader(program: d->programGuard->id(), shader: shader->d_func()->shaderGuard->id());
1238 }
1239 }
1240 // Delete shader objects that were created anonymously.
1241 qDeleteAll(c: d->anonShaders);
1242 d->shaders.clear();
1243 d->anonShaders.clear();
1244 d->binaryProgram = QOpenGLProgramBinaryCache::ProgramDesc();
1245 d->linked = false; // Program needs to be relinked.
1246 d->removingShaders = false;
1247}
1248
1249/*!
1250 Links together the shaders that were added to this program with
1251 addShader(). Returns \c true if the link was successful or
1252 false otherwise. If the link failed, the error messages can
1253 be retrieved with log().
1254
1255 Subclasses can override this function to initialize attributes
1256 and uniform variables for use in specific shader programs.
1257
1258 If the shader program was already linked, calling this
1259 function again will force it to be re-linked.
1260
1261 When shaders were added to this program via
1262 addCacheableShaderFromSourceCode() or addCacheableShaderFromSourceFile(),
1263 program binaries are supported, and a cached binary is available on disk,
1264 actual compilation and linking are skipped. Instead, link() will initialize
1265 the program with the binary blob via glProgramBinary(). If there is no
1266 cached version of the program or it was generated with a different driver
1267 version, the shaders will be compiled from source and the program will get
1268 linked normally. This allows seamless upgrading of the graphics drivers,
1269 without having to worry about potentially incompatible binary formats.
1270
1271 \sa addShader(), log()
1272*/
1273bool QOpenGLShaderProgram::link()
1274{
1275 Q_D(QOpenGLShaderProgram);
1276 GLuint program = d->programGuard ? d->programGuard->id() : 0;
1277 if (!program)
1278 return false;
1279
1280 if (!d->linkBinaryRecursion && d->shaders.isEmpty() && !d->binaryProgram.shaders.isEmpty())
1281 return d->linkBinary();
1282
1283 GLint value;
1284 if (d->shaders.isEmpty()) {
1285 // If there are no explicit shaders, then it is possible that the
1286 // application added a program binary with glProgramBinaryOES(), or
1287 // otherwise populated the shaders itself. This is also the case when
1288 // we are recursively called back from linkBinary() after a successful
1289 // glProgramBinary(). Check to see if the program is already linked and
1290 // bail out if so.
1291 value = 0;
1292 d->glfuncs->glGetProgramiv(program, GL_LINK_STATUS, params: &value);
1293 d->linked = (value != 0);
1294 if (d->linked)
1295 return true;
1296 }
1297
1298 d->glfuncs->glLinkProgram(program);
1299 value = 0;
1300 d->glfuncs->glGetProgramiv(program, GL_LINK_STATUS, params: &value);
1301 d->linked = (value != 0);
1302 value = 0;
1303 d->glfuncs->glGetProgramiv(program, GL_INFO_LOG_LENGTH, params: &value);
1304 d->log = QString();
1305 if (value > 1) {
1306 char *logbuf = new char [value];
1307 GLint len;
1308 d->glfuncs->glGetProgramInfoLog(program, bufsize: value, length: &len, infolog: logbuf);
1309 d->log = QString::fromLatin1(ba: logbuf);
1310 if (!d->linked && !d->linkBinaryRecursion) {
1311 QString name = objectName();
1312 if (name.isEmpty())
1313 qWarning(msg: "QOpenGLShader::link: %ls", qUtf16Printable(d->log));
1314 else
1315 qWarning(msg: "QOpenGLShader::link[%ls]: %ls", qUtf16Printable(name), qUtf16Printable(d->log));
1316 }
1317 delete [] logbuf;
1318 }
1319 return d->linked;
1320}
1321
1322/*!
1323 Returns \c true if this shader program has been linked; false otherwise.
1324
1325 \sa link()
1326*/
1327bool QOpenGLShaderProgram::isLinked() const
1328{
1329 Q_D(const QOpenGLShaderProgram);
1330 return d->linked;
1331}
1332
1333/*!
1334 Returns the errors and warnings that occurred during the last link()
1335 or addShader() with explicitly specified source code.
1336
1337 \sa link()
1338*/
1339QString QOpenGLShaderProgram::log() const
1340{
1341 Q_D(const QOpenGLShaderProgram);
1342 return d->log;
1343}
1344
1345/*!
1346 Binds this shader program to the active QOpenGLContext and makes
1347 it the current shader program. Any previously bound shader program
1348 is released. This is equivalent to calling \c{glUseProgram()} on
1349 programId(). Returns \c true if the program was successfully bound;
1350 false otherwise. If the shader program has not yet been linked,
1351 or it needs to be re-linked, this function will call link().
1352
1353 \sa link(), release()
1354*/
1355bool QOpenGLShaderProgram::bind()
1356{
1357 Q_D(QOpenGLShaderProgram);
1358 GLuint program = d->programGuard ? d->programGuard->id() : 0;
1359 if (!program)
1360 return false;
1361 if (!d->linked && !link())
1362 return false;
1363#ifndef QT_NO_DEBUG
1364 if (d->programGuard->group() != QOpenGLContextGroup::currentContextGroup()) {
1365 qWarning(msg: "QOpenGLShaderProgram::bind: program is not valid in the current context.");
1366 return false;
1367 }
1368#endif
1369 d->glfuncs->glUseProgram(program);
1370 return true;
1371}
1372
1373/*!
1374 Releases the active shader program from the current QOpenGLContext.
1375 This is equivalent to calling \c{glUseProgram(0)}.
1376
1377 \sa bind()
1378*/
1379void QOpenGLShaderProgram::release()
1380{
1381 Q_D(QOpenGLShaderProgram);
1382#ifndef QT_NO_DEBUG
1383 if (d->programGuard && d->programGuard->group() != QOpenGLContextGroup::currentContextGroup())
1384 qWarning(msg: "QOpenGLShaderProgram::release: program is not valid in the current context.");
1385#endif
1386 d->glfuncs->glUseProgram(program: 0);
1387}
1388
1389/*!
1390 Returns the OpenGL identifier associated with this shader program.
1391
1392 \sa QOpenGLShader::shaderId()
1393*/
1394GLuint QOpenGLShaderProgram::programId() const
1395{
1396 Q_D(const QOpenGLShaderProgram);
1397 GLuint id = d->programGuard ? d->programGuard->id() : 0;
1398 if (id)
1399 return id;
1400
1401 // Create the identifier if we don't have one yet. This is for
1402 // applications that want to create the attached shader configuration
1403 // themselves, particularly those using program binaries.
1404 if (!const_cast<QOpenGLShaderProgram *>(this)->init())
1405 return 0;
1406 return d->programGuard ? d->programGuard->id() : 0;
1407}
1408
1409/*!
1410 Binds the attribute \a name to the specified \a location. This
1411 function can be called before or after the program has been linked.
1412 Any attributes that have not been explicitly bound when the program
1413 is linked will be assigned locations automatically.
1414
1415 When this function is called after the program has been linked,
1416 the program will need to be relinked for the change to take effect.
1417
1418 \sa attributeLocation()
1419*/
1420void QOpenGLShaderProgram::bindAttributeLocation(const char *name, int location)
1421{
1422 Q_D(QOpenGLShaderProgram);
1423 if (!init() || !d->programGuard || !d->programGuard->id())
1424 return;
1425 d->glfuncs->glBindAttribLocation(program: d->programGuard->id(), index: location, name);
1426 d->linked = false; // Program needs to be relinked.
1427}
1428
1429/*!
1430 \overload
1431
1432 Binds the attribute \a name to the specified \a location. This
1433 function can be called before or after the program has been linked.
1434 Any attributes that have not been explicitly bound when the program
1435 is linked will be assigned locations automatically.
1436
1437 When this function is called after the program has been linked,
1438 the program will need to be relinked for the change to take effect.
1439
1440 \sa attributeLocation()
1441*/
1442void QOpenGLShaderProgram::bindAttributeLocation(const QByteArray& name, int location)
1443{
1444 bindAttributeLocation(name: name.constData(), location);
1445}
1446
1447/*!
1448 \overload
1449
1450 Binds the attribute \a name to the specified \a location. This
1451 function can be called before or after the program has been linked.
1452 Any attributes that have not been explicitly bound when the program
1453 is linked will be assigned locations automatically.
1454
1455 When this function is called after the program has been linked,
1456 the program will need to be relinked for the change to take effect.
1457
1458 \sa attributeLocation()
1459*/
1460void QOpenGLShaderProgram::bindAttributeLocation(const QString& name, int location)
1461{
1462 bindAttributeLocation(name: name.toLatin1().constData(), location);
1463}
1464
1465/*!
1466 Returns the location of the attribute \a name within this shader
1467 program's parameter list. Returns -1 if \a name is not a valid
1468 attribute for this shader program.
1469
1470 \sa uniformLocation(), bindAttributeLocation()
1471*/
1472int QOpenGLShaderProgram::attributeLocation(const char *name) const
1473{
1474 Q_D(const QOpenGLShaderProgram);
1475 if (d->linked && d->programGuard && d->programGuard->id()) {
1476 return d->glfuncs->glGetAttribLocation(program: d->programGuard->id(), name);
1477 } else {
1478 qWarning(msg: "QOpenGLShaderProgram::attributeLocation(%s): shader program is not linked", name);
1479 return -1;
1480 }
1481}
1482
1483/*!
1484 \overload
1485
1486 Returns the location of the attribute \a name within this shader
1487 program's parameter list. Returns -1 if \a name is not a valid
1488 attribute for this shader program.
1489
1490 \sa uniformLocation(), bindAttributeLocation()
1491*/
1492int QOpenGLShaderProgram::attributeLocation(const QByteArray& name) const
1493{
1494 return attributeLocation(name: name.constData());
1495}
1496
1497/*!
1498 \overload
1499
1500 Returns the location of the attribute \a name within this shader
1501 program's parameter list. Returns -1 if \a name is not a valid
1502 attribute for this shader program.
1503
1504 \sa uniformLocation(), bindAttributeLocation()
1505*/
1506int QOpenGLShaderProgram::attributeLocation(const QString& name) const
1507{
1508 return attributeLocation(name: name.toLatin1().constData());
1509}
1510
1511/*!
1512 Sets the attribute at \a location in the current context to \a value.
1513
1514 \sa setUniformValue()
1515*/
1516void QOpenGLShaderProgram::setAttributeValue(int location, GLfloat value)
1517{
1518 Q_D(QOpenGLShaderProgram);
1519 if (location != -1)
1520 d->glfuncs->glVertexAttrib1fv(indx: location, values: &value);
1521}
1522
1523/*!
1524 \overload
1525
1526 Sets the attribute called \a name in the current context to \a value.
1527
1528 \sa setUniformValue()
1529*/
1530void QOpenGLShaderProgram::setAttributeValue(const char *name, GLfloat value)
1531{
1532 setAttributeValue(location: attributeLocation(name), value);
1533}
1534
1535/*!
1536 Sets the attribute at \a location in the current context to
1537 the 2D vector (\a x, \a y).
1538
1539 \sa setUniformValue()
1540*/
1541void QOpenGLShaderProgram::setAttributeValue(int location, GLfloat x, GLfloat y)
1542{
1543 Q_D(QOpenGLShaderProgram);
1544 if (location != -1) {
1545 GLfloat values[2] = {x, y};
1546 d->glfuncs->glVertexAttrib2fv(indx: location, values);
1547 }
1548}
1549
1550/*!
1551 \overload
1552
1553 Sets the attribute called \a name in the current context to
1554 the 2D vector (\a x, \a y).
1555
1556 \sa setUniformValue()
1557*/
1558void QOpenGLShaderProgram::setAttributeValue(const char *name, GLfloat x, GLfloat y)
1559{
1560 setAttributeValue(location: attributeLocation(name), x, y);
1561}
1562
1563/*!
1564 Sets the attribute at \a location in the current context to
1565 the 3D vector (\a x, \a y, \a z).
1566
1567 \sa setUniformValue()
1568*/
1569void QOpenGLShaderProgram::setAttributeValue
1570 (int location, GLfloat x, GLfloat y, GLfloat z)
1571{
1572 Q_D(QOpenGLShaderProgram);
1573 Q_UNUSED(d);
1574 if (location != -1) {
1575 GLfloat values[3] = {x, y, z};
1576 d->glfuncs->glVertexAttrib3fv(indx: location, values);
1577 }
1578}
1579
1580/*!
1581 \overload
1582
1583 Sets the attribute called \a name in the current context to
1584 the 3D vector (\a x, \a y, \a z).
1585
1586 \sa setUniformValue()
1587*/
1588void QOpenGLShaderProgram::setAttributeValue
1589 (const char *name, GLfloat x, GLfloat y, GLfloat z)
1590{
1591 setAttributeValue(location: attributeLocation(name), x, y, z);
1592}
1593
1594/*!
1595 Sets the attribute at \a location in the current context to
1596 the 4D vector (\a x, \a y, \a z, \a w).
1597
1598 \sa setUniformValue()
1599*/
1600void QOpenGLShaderProgram::setAttributeValue
1601 (int location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
1602{
1603 Q_D(QOpenGLShaderProgram);
1604 if (location != -1) {
1605 GLfloat values[4] = {x, y, z, w};
1606 d->glfuncs->glVertexAttrib4fv(indx: location, values);
1607 }
1608}
1609
1610/*!
1611 \overload
1612
1613 Sets the attribute called \a name in the current context to
1614 the 4D vector (\a x, \a y, \a z, \a w).
1615
1616 \sa setUniformValue()
1617*/
1618void QOpenGLShaderProgram::setAttributeValue
1619 (const char *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
1620{
1621 setAttributeValue(location: attributeLocation(name), x, y, z, w);
1622}
1623
1624/*!
1625 Sets the attribute at \a location in the current context to \a value.
1626
1627 \sa setUniformValue()
1628*/
1629void QOpenGLShaderProgram::setAttributeValue(int location, const QVector2D& value)
1630{
1631 Q_D(QOpenGLShaderProgram);
1632 if (location != -1)
1633 d->glfuncs->glVertexAttrib2fv(indx: location, values: reinterpret_cast<const GLfloat *>(&value));
1634}
1635
1636/*!
1637 \overload
1638
1639 Sets the attribute called \a name in the current context to \a value.
1640
1641 \sa setUniformValue()
1642*/
1643void QOpenGLShaderProgram::setAttributeValue(const char *name, const QVector2D& value)
1644{
1645 setAttributeValue(location: attributeLocation(name), value);
1646}
1647
1648/*!
1649 Sets the attribute at \a location in the current context to \a value.
1650
1651 \sa setUniformValue()
1652*/
1653void QOpenGLShaderProgram::setAttributeValue(int location, const QVector3D& value)
1654{
1655 Q_D(QOpenGLShaderProgram);
1656 Q_UNUSED(d);
1657 if (location != -1)
1658 d->glfuncs->glVertexAttrib3fv(indx: location, values: reinterpret_cast<const GLfloat *>(&value));
1659}
1660
1661/*!
1662 \overload
1663
1664 Sets the attribute called \a name in the current context to \a value.
1665
1666 \sa setUniformValue()
1667*/
1668void QOpenGLShaderProgram::setAttributeValue(const char *name, const QVector3D& value)
1669{
1670 setAttributeValue(location: attributeLocation(name), value);
1671}
1672
1673/*!
1674 Sets the attribute at \a location in the current context to \a value.
1675
1676 \sa setUniformValue()
1677*/
1678void QOpenGLShaderProgram::setAttributeValue(int location, const QVector4D& value)
1679{
1680 Q_D(QOpenGLShaderProgram);
1681 Q_UNUSED(d);
1682 if (location != -1)
1683 d->glfuncs->glVertexAttrib4fv(indx: location, values: reinterpret_cast<const GLfloat *>(&value));
1684}
1685
1686/*!
1687 \overload
1688
1689 Sets the attribute called \a name in the current context to \a value.
1690
1691 \sa setUniformValue()
1692*/
1693void QOpenGLShaderProgram::setAttributeValue(const char *name, const QVector4D& value)
1694{
1695 setAttributeValue(location: attributeLocation(name), value);
1696}
1697
1698/*!
1699 Sets the attribute at \a location in the current context to \a value.
1700
1701 \sa setUniformValue()
1702*/
1703void QOpenGLShaderProgram::setAttributeValue(int location, const QColor& value)
1704{
1705 Q_D(QOpenGLShaderProgram);
1706 Q_UNUSED(d);
1707 if (location != -1) {
1708 GLfloat values[4] = {GLfloat(value.redF()), GLfloat(value.greenF()),
1709 GLfloat(value.blueF()), GLfloat(value.alphaF())};
1710 d->glfuncs->glVertexAttrib4fv(indx: location, values);
1711 }
1712}
1713
1714/*!
1715 \overload
1716
1717 Sets the attribute called \a name in the current context to \a value.
1718
1719 \sa setUniformValue()
1720*/
1721void QOpenGLShaderProgram::setAttributeValue(const char *name, const QColor& value)
1722{
1723 setAttributeValue(location: attributeLocation(name), value);
1724}
1725
1726/*!
1727 Sets the attribute at \a location in the current context to the
1728 contents of \a values, which contains \a columns elements, each
1729 consisting of \a rows elements. The \a rows value should be
1730 1, 2, 3, or 4. This function is typically used to set matrix
1731 values and column vectors.
1732
1733 \sa setUniformValue()
1734*/
1735void QOpenGLShaderProgram::setAttributeValue
1736 (int location, const GLfloat *values, int columns, int rows)
1737{
1738 Q_D(QOpenGLShaderProgram);
1739 Q_UNUSED(d);
1740 if (rows < 1 || rows > 4) {
1741 qWarning(msg: "QOpenGLShaderProgram::setAttributeValue: rows %d not supported", rows);
1742 return;
1743 }
1744 if (location != -1) {
1745 while (columns-- > 0) {
1746 if (rows == 1)
1747 d->glfuncs->glVertexAttrib1fv(indx: location, values);
1748 else if (rows == 2)
1749 d->glfuncs->glVertexAttrib2fv(indx: location, values);
1750 else if (rows == 3)
1751 d->glfuncs->glVertexAttrib3fv(indx: location, values);
1752 else
1753 d->glfuncs->glVertexAttrib4fv(indx: location, values);
1754 values += rows;
1755 ++location;
1756 }
1757 }
1758}
1759
1760/*!
1761 \overload
1762
1763 Sets the attribute called \a name in the current context to the
1764 contents of \a values, which contains \a columns elements, each
1765 consisting of \a rows elements. The \a rows value should be
1766 1, 2, 3, or 4. This function is typically used to set matrix
1767 values and column vectors.
1768
1769 \sa setUniformValue()
1770*/
1771void QOpenGLShaderProgram::setAttributeValue
1772 (const char *name, const GLfloat *values, int columns, int rows)
1773{
1774 setAttributeValue(location: attributeLocation(name), values, columns, rows);
1775}
1776
1777/*!
1778 Sets an array of vertex \a values on the attribute at \a location
1779 in this shader program. The \a tupleSize indicates the number of
1780 components per vertex (1, 2, 3, or 4), and the \a stride indicates
1781 the number of bytes between vertices. A default \a stride value
1782 of zero indicates that the vertices are densely packed in \a values.
1783
1784 The array will become active when enableAttributeArray() is called
1785 on the \a location. Otherwise the value specified with
1786 setAttributeValue() for \a location will be used.
1787
1788 \sa setAttributeValue(), setUniformValue(), enableAttributeArray()
1789 \sa disableAttributeArray()
1790*/
1791void QOpenGLShaderProgram::setAttributeArray
1792 (int location, const GLfloat *values, int tupleSize, int stride)
1793{
1794 Q_D(QOpenGLShaderProgram);
1795 Q_UNUSED(d);
1796 if (location != -1) {
1797 d->glfuncs->glVertexAttribPointer(indx: location, size: tupleSize, GL_FLOAT, GL_FALSE,
1798 stride, ptr: values);
1799 }
1800}
1801
1802/*!
1803 Sets an array of 2D vertex \a values on the attribute at \a location
1804 in this shader program. The \a stride indicates the number of bytes
1805 between vertices. A default \a stride value of zero indicates that
1806 the vertices are densely packed in \a values.
1807
1808 The array will become active when enableAttributeArray() is called
1809 on the \a location. Otherwise the value specified with
1810 setAttributeValue() for \a location will be used.
1811
1812 \sa setAttributeValue(), setUniformValue(), enableAttributeArray()
1813 \sa disableAttributeArray()
1814*/
1815void QOpenGLShaderProgram::setAttributeArray
1816 (int location, const QVector2D *values, int stride)
1817{
1818 Q_D(QOpenGLShaderProgram);
1819 Q_UNUSED(d);
1820 if (location != -1) {
1821 d->glfuncs->glVertexAttribPointer(indx: location, size: 2, GL_FLOAT, GL_FALSE,
1822 stride, ptr: values);
1823 }
1824}
1825
1826/*!
1827 Sets an array of 3D vertex \a values on the attribute at \a location
1828 in this shader program. The \a stride indicates the number of bytes
1829 between vertices. A default \a stride value of zero indicates that
1830 the vertices are densely packed in \a values.
1831
1832 The array will become active when enableAttributeArray() is called
1833 on the \a location. Otherwise the value specified with
1834 setAttributeValue() for \a location will be used.
1835
1836 \sa setAttributeValue(), setUniformValue(), enableAttributeArray()
1837 \sa disableAttributeArray()
1838*/
1839void QOpenGLShaderProgram::setAttributeArray
1840 (int location, const QVector3D *values, int stride)
1841{
1842 Q_D(QOpenGLShaderProgram);
1843 Q_UNUSED(d);
1844 if (location != -1) {
1845 d->glfuncs->glVertexAttribPointer(indx: location, size: 3, GL_FLOAT, GL_FALSE,
1846 stride, ptr: values);
1847 }
1848}
1849
1850/*!
1851 Sets an array of 4D vertex \a values on the attribute at \a location
1852 in this shader program. The \a stride indicates the number of bytes
1853 between vertices. A default \a stride value of zero indicates that
1854 the vertices are densely packed in \a values.
1855
1856 The array will become active when enableAttributeArray() is called
1857 on the \a location. Otherwise the value specified with
1858 setAttributeValue() for \a location will be used.
1859
1860 \sa setAttributeValue(), setUniformValue(), enableAttributeArray()
1861 \sa disableAttributeArray()
1862*/
1863void QOpenGLShaderProgram::setAttributeArray
1864 (int location, const QVector4D *values, int stride)
1865{
1866 Q_D(QOpenGLShaderProgram);
1867 Q_UNUSED(d);
1868 if (location != -1) {
1869 d->glfuncs->glVertexAttribPointer(indx: location, size: 4, GL_FLOAT, GL_FALSE,
1870 stride, ptr: values);
1871 }
1872}
1873
1874/*!
1875 Sets an array of vertex \a values on the attribute at \a location
1876 in this shader program. The \a stride indicates the number of bytes
1877 between vertices. A default \a stride value of zero indicates that
1878 the vertices are densely packed in \a values.
1879
1880 The \a type indicates the type of elements in the \a values array,
1881 usually \c{GL_FLOAT}, \c{GL_UNSIGNED_BYTE}, etc. The \a tupleSize
1882 indicates the number of components per vertex: 1, 2, 3, or 4.
1883
1884 The array will become active when enableAttributeArray() is called
1885 on the \a location. Otherwise the value specified with
1886 setAttributeValue() for \a location will be used.
1887
1888 The setAttributeBuffer() function can be used to set the attribute
1889 array to an offset within a vertex buffer.
1890
1891 \note Normalization will be enabled. If this is not desired, call
1892 glVertexAttribPointer directly through QOpenGLFunctions.
1893
1894 \sa setAttributeValue(), setUniformValue(), enableAttributeArray()
1895 \sa disableAttributeArray(), setAttributeBuffer()
1896*/
1897void QOpenGLShaderProgram::setAttributeArray
1898 (int location, GLenum type, const void *values, int tupleSize, int stride)
1899{
1900 Q_D(QOpenGLShaderProgram);
1901 Q_UNUSED(d);
1902 if (location != -1) {
1903 d->glfuncs->glVertexAttribPointer(indx: location, size: tupleSize, type, GL_TRUE,
1904 stride, ptr: values);
1905 }
1906}
1907
1908/*!
1909 \overload
1910
1911 Sets an array of vertex \a values on the attribute called \a name
1912 in this shader program. The \a tupleSize indicates the number of
1913 components per vertex (1, 2, 3, or 4), and the \a stride indicates
1914 the number of bytes between vertices. A default \a stride value
1915 of zero indicates that the vertices are densely packed in \a values.
1916
1917 The array will become active when enableAttributeArray() is called
1918 on \a name. Otherwise the value specified with setAttributeValue()
1919 for \a name will be used.
1920
1921 \sa setAttributeValue(), setUniformValue(), enableAttributeArray()
1922 \sa disableAttributeArray()
1923*/
1924void QOpenGLShaderProgram::setAttributeArray
1925 (const char *name, const GLfloat *values, int tupleSize, int stride)
1926{
1927 setAttributeArray(location: attributeLocation(name), values, tupleSize, stride);
1928}
1929
1930/*!
1931 \overload
1932
1933 Sets an array of 2D vertex \a values on the attribute called \a name
1934 in this shader program. The \a stride indicates the number of bytes
1935 between vertices. A default \a stride value of zero indicates that
1936 the vertices are densely packed in \a values.
1937
1938 The array will become active when enableAttributeArray() is called
1939 on \a name. Otherwise the value specified with setAttributeValue()
1940 for \a name will be used.
1941
1942 \sa setAttributeValue(), setUniformValue(), enableAttributeArray()
1943 \sa disableAttributeArray()
1944*/
1945void QOpenGLShaderProgram::setAttributeArray
1946 (const char *name, const QVector2D *values, int stride)
1947{
1948 setAttributeArray(location: attributeLocation(name), values, stride);
1949}
1950
1951/*!
1952 \overload
1953
1954 Sets an array of 3D vertex \a values on the attribute called \a name
1955 in this shader program. The \a stride indicates the number of bytes
1956 between vertices. A default \a stride value of zero indicates that
1957 the vertices are densely packed in \a values.
1958
1959 The array will become active when enableAttributeArray() is called
1960 on \a name. Otherwise the value specified with setAttributeValue()
1961 for \a name will be used.
1962
1963 \sa setAttributeValue(), setUniformValue(), enableAttributeArray()
1964 \sa disableAttributeArray()
1965*/
1966void QOpenGLShaderProgram::setAttributeArray
1967 (const char *name, const QVector3D *values, int stride)
1968{
1969 setAttributeArray(location: attributeLocation(name), values, stride);
1970}
1971
1972/*!
1973 \overload
1974
1975 Sets an array of 4D vertex \a values on the attribute called \a name
1976 in this shader program. The \a stride indicates the number of bytes
1977 between vertices. A default \a stride value of zero indicates that
1978 the vertices are densely packed in \a values.
1979
1980 The array will become active when enableAttributeArray() is called
1981 on \a name. Otherwise the value specified with setAttributeValue()
1982 for \a name will be used.
1983
1984 \sa setAttributeValue(), setUniformValue(), enableAttributeArray()
1985 \sa disableAttributeArray()
1986*/
1987void QOpenGLShaderProgram::setAttributeArray
1988 (const char *name, const QVector4D *values, int stride)
1989{
1990 setAttributeArray(location: attributeLocation(name), values, stride);
1991}
1992
1993/*!
1994 \overload
1995
1996 Sets an array of vertex \a values on the attribute called \a name
1997 in this shader program. The \a stride indicates the number of bytes
1998 between vertices. A default \a stride value of zero indicates that
1999 the vertices are densely packed in \a values.
2000
2001 The \a type indicates the type of elements in the \a values array,
2002 usually \c{GL_FLOAT}, \c{GL_UNSIGNED_BYTE}, etc. The \a tupleSize
2003 indicates the number of components per vertex: 1, 2, 3, or 4.
2004
2005 The array will become active when enableAttributeArray() is called
2006 on the \a name. Otherwise the value specified with
2007 setAttributeValue() for \a name will be used.
2008
2009 The setAttributeBuffer() function can be used to set the attribute
2010 array to an offset within a vertex buffer.
2011
2012 \sa setAttributeValue(), setUniformValue(), enableAttributeArray()
2013 \sa disableAttributeArray(), setAttributeBuffer()
2014*/
2015void QOpenGLShaderProgram::setAttributeArray
2016 (const char *name, GLenum type, const void *values, int tupleSize, int stride)
2017{
2018 setAttributeArray(location: attributeLocation(name), type, values, tupleSize, stride);
2019}
2020
2021/*!
2022 Sets an array of vertex values on the attribute at \a location in
2023 this shader program, starting at a specific \a offset in the
2024 currently bound vertex buffer. The \a stride indicates the number
2025 of bytes between vertices. A default \a stride value of zero
2026 indicates that the vertices are densely packed in the value array.
2027
2028 The \a type indicates the type of elements in the vertex value
2029 array, usually \c{GL_FLOAT}, \c{GL_UNSIGNED_BYTE}, etc. The \a
2030 tupleSize indicates the number of components per vertex: 1, 2, 3,
2031 or 4.
2032
2033 The array will become active when enableAttributeArray() is called
2034 on the \a location. Otherwise the value specified with
2035 setAttributeValue() for \a location will be used.
2036
2037 \note Normalization will be enabled. If this is not desired, call
2038 glVertexAttribPointer directly through QOpenGLFunctions.
2039
2040 \sa setAttributeArray()
2041*/
2042void QOpenGLShaderProgram::setAttributeBuffer
2043 (int location, GLenum type, int offset, int tupleSize, int stride)
2044{
2045 Q_D(QOpenGLShaderProgram);
2046 Q_UNUSED(d);
2047 if (location != -1) {
2048 d->glfuncs->glVertexAttribPointer(indx: location, size: tupleSize, type, GL_TRUE, stride,
2049 ptr: reinterpret_cast<const void *>(qintptr(offset)));
2050 }
2051}
2052
2053/*!
2054 \overload
2055
2056 Sets an array of vertex values on the attribute called \a name
2057 in this shader program, starting at a specific \a offset in the
2058 currently bound vertex buffer. The \a stride indicates the number
2059 of bytes between vertices. A default \a stride value of zero
2060 indicates that the vertices are densely packed in the value array.
2061
2062 The \a type indicates the type of elements in the vertex value
2063 array, usually \c{GL_FLOAT}, \c{GL_UNSIGNED_BYTE}, etc. The \a
2064 tupleSize indicates the number of components per vertex: 1, 2, 3,
2065 or 4.
2066
2067 The array will become active when enableAttributeArray() is called
2068 on the \a name. Otherwise the value specified with
2069 setAttributeValue() for \a name will be used.
2070
2071 \sa setAttributeArray()
2072*/
2073void QOpenGLShaderProgram::setAttributeBuffer
2074 (const char *name, GLenum type, int offset, int tupleSize, int stride)
2075{
2076 setAttributeBuffer(location: attributeLocation(name), type, offset, tupleSize, stride);
2077}
2078
2079/*!
2080 Enables the vertex array at \a location in this shader program
2081 so that the value set by setAttributeArray() on \a location
2082 will be used by the shader program.
2083
2084 \sa disableAttributeArray(), setAttributeArray(), setAttributeValue()
2085 \sa setUniformValue()
2086*/
2087void QOpenGLShaderProgram::enableAttributeArray(int location)
2088{
2089 Q_D(QOpenGLShaderProgram);
2090 Q_UNUSED(d);
2091 if (location != -1)
2092 d->glfuncs->glEnableVertexAttribArray(index: location);
2093}
2094
2095/*!
2096 \overload
2097
2098 Enables the vertex array called \a name in this shader program
2099 so that the value set by setAttributeArray() on \a name
2100 will be used by the shader program.
2101
2102 \sa disableAttributeArray(), setAttributeArray(), setAttributeValue()
2103 \sa setUniformValue()
2104*/
2105void QOpenGLShaderProgram::enableAttributeArray(const char *name)
2106{
2107 enableAttributeArray(location: attributeLocation(name));
2108}
2109
2110/*!
2111 Disables the vertex array at \a location in this shader program
2112 that was enabled by a previous call to enableAttributeArray().
2113
2114 \sa enableAttributeArray(), setAttributeArray(), setAttributeValue()
2115 \sa setUniformValue()
2116*/
2117void QOpenGLShaderProgram::disableAttributeArray(int location)
2118{
2119 Q_D(QOpenGLShaderProgram);
2120 Q_UNUSED(d);
2121 if (location != -1)
2122 d->glfuncs->glDisableVertexAttribArray(index: location);
2123}
2124
2125/*!
2126 \overload
2127
2128 Disables the vertex array called \a name in this shader program
2129 that was enabled by a previous call to enableAttributeArray().
2130
2131 \sa enableAttributeArray(), setAttributeArray(), setAttributeValue()
2132 \sa setUniformValue()
2133*/
2134void QOpenGLShaderProgram::disableAttributeArray(const char *name)
2135{
2136 disableAttributeArray(location: attributeLocation(name));
2137}
2138
2139/*!
2140 Returns the location of the uniform variable \a name within this shader
2141 program's parameter list. Returns -1 if \a name is not a valid
2142 uniform variable for this shader program.
2143
2144 \sa attributeLocation()
2145*/
2146int QOpenGLShaderProgram::uniformLocation(const char *name) const
2147{
2148 Q_D(const QOpenGLShaderProgram);
2149 Q_UNUSED(d);
2150 if (d->linked && d->programGuard && d->programGuard->id()) {
2151 return d->glfuncs->glGetUniformLocation(program: d->programGuard->id(), name);
2152 } else {
2153 qWarning(msg: "QOpenGLShaderProgram::uniformLocation(%s): shader program is not linked", name);
2154 return -1;
2155 }
2156}
2157
2158/*!
2159 \overload
2160
2161 Returns the location of the uniform variable \a name within this shader
2162 program's parameter list. Returns -1 if \a name is not a valid
2163 uniform variable for this shader program.
2164
2165 \sa attributeLocation()
2166*/
2167int QOpenGLShaderProgram::uniformLocation(const QByteArray& name) const
2168{
2169 return uniformLocation(name: name.constData());
2170}
2171
2172/*!
2173 \overload
2174
2175 Returns the location of the uniform variable \a name within this shader
2176 program's parameter list. Returns -1 if \a name is not a valid
2177 uniform variable for this shader program.
2178
2179 \sa attributeLocation()
2180*/
2181int QOpenGLShaderProgram::uniformLocation(const QString& name) const
2182{
2183 return uniformLocation(name: name.toLatin1().constData());
2184}
2185
2186/*!
2187 Sets the uniform variable at \a location in the current context to \a value.
2188
2189 \sa setAttributeValue()
2190*/
2191void QOpenGLShaderProgram::setUniformValue(int location, GLfloat value)
2192{
2193 Q_D(QOpenGLShaderProgram);
2194 Q_UNUSED(d);
2195 if (location != -1)
2196 d->glfuncs->glUniform1fv(location, count: 1, v: &value);
2197}
2198
2199/*!
2200 \overload
2201
2202 Sets the uniform variable called \a name in the current context
2203 to \a value.
2204
2205 \sa setAttributeValue()
2206*/
2207void QOpenGLShaderProgram::setUniformValue(const char *name, GLfloat value)
2208{
2209 setUniformValue(location: uniformLocation(name), value);
2210}
2211
2212/*!
2213 Sets the uniform variable at \a location in the current context to \a value.
2214
2215 \sa setAttributeValue()
2216*/
2217void QOpenGLShaderProgram::setUniformValue(int location, GLint value)
2218{
2219 Q_D(QOpenGLShaderProgram);
2220 Q_UNUSED(d);
2221 if (location != -1)
2222 d->glfuncs->glUniform1i(location, x: value);
2223}
2224
2225/*!
2226 \overload
2227
2228 Sets the uniform variable called \a name in the current context
2229 to \a value.
2230
2231 \sa setAttributeValue()
2232*/
2233void QOpenGLShaderProgram::setUniformValue(const char *name, GLint value)
2234{
2235 setUniformValue(location: uniformLocation(name), value);
2236}
2237
2238/*!
2239 Sets the uniform variable at \a location in the current context to \a value.
2240 This function should be used when setting sampler values.
2241
2242 \note This function is not aware of unsigned int support in modern OpenGL
2243 versions and therefore treats \a value as a GLint and calls glUniform1i.
2244
2245 \sa setAttributeValue()
2246*/
2247void QOpenGLShaderProgram::setUniformValue(int location, GLuint value)
2248{
2249 Q_D(QOpenGLShaderProgram);
2250 Q_UNUSED(d);
2251 if (location != -1)
2252 d->glfuncs->glUniform1i(location, x: value);
2253}
2254
2255/*!
2256 \overload
2257
2258 Sets the uniform variable called \a name in the current context
2259 to \a value. This function should be used when setting sampler values.
2260
2261 \note This function is not aware of unsigned int support in modern OpenGL
2262 versions and therefore treats \a value as a GLint and calls glUniform1i.
2263
2264 \sa setAttributeValue()
2265*/
2266void QOpenGLShaderProgram::setUniformValue(const char *name, GLuint value)
2267{
2268 setUniformValue(location: uniformLocation(name), value);
2269}
2270
2271/*!
2272 Sets the uniform variable at \a location in the current context to
2273 the 2D vector (\a x, \a y).
2274
2275 \sa setAttributeValue()
2276*/
2277void QOpenGLShaderProgram::setUniformValue(int location, GLfloat x, GLfloat y)
2278{
2279 Q_D(QOpenGLShaderProgram);
2280 Q_UNUSED(d);
2281 if (location != -1) {
2282 GLfloat values[2] = {x, y};
2283 d->glfuncs->glUniform2fv(location, count: 1, v: values);
2284 }
2285}
2286
2287/*!
2288 \overload
2289
2290 Sets the uniform variable called \a name in the current context to
2291 the 2D vector (\a x, \a y).
2292
2293 \sa setAttributeValue()
2294*/
2295void QOpenGLShaderProgram::setUniformValue(const char *name, GLfloat x, GLfloat y)
2296{
2297 setUniformValue(location: uniformLocation(name), x, y);
2298}
2299
2300/*!
2301 Sets the uniform variable at \a location in the current context to
2302 the 3D vector (\a x, \a y, \a z).
2303
2304 \sa setAttributeValue()
2305*/
2306void QOpenGLShaderProgram::setUniformValue
2307 (int location, GLfloat x, GLfloat y, GLfloat z)
2308{
2309 Q_D(QOpenGLShaderProgram);
2310 Q_UNUSED(d);
2311 if (location != -1) {
2312 GLfloat values[3] = {x, y, z};
2313 d->glfuncs->glUniform3fv(location, count: 1, v: values);
2314 }
2315}
2316
2317/*!
2318 \overload
2319
2320 Sets the uniform variable called \a name in the current context to
2321 the 3D vector (\a x, \a y, \a z).
2322
2323 \sa setAttributeValue()
2324*/
2325void QOpenGLShaderProgram::setUniformValue
2326 (const char *name, GLfloat x, GLfloat y, GLfloat z)
2327{
2328 setUniformValue(location: uniformLocation(name), x, y, z);
2329}
2330
2331/*!
2332 Sets the uniform variable at \a location in the current context to
2333 the 4D vector (\a x, \a y, \a z, \a w).
2334
2335 \sa setAttributeValue()
2336*/
2337void QOpenGLShaderProgram::setUniformValue
2338 (int location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
2339{
2340 Q_D(QOpenGLShaderProgram);
2341 Q_UNUSED(d);
2342 if (location != -1) {
2343 GLfloat values[4] = {x, y, z, w};
2344 d->glfuncs->glUniform4fv(location, count: 1, v: values);
2345 }
2346}
2347
2348/*!
2349 \overload
2350
2351 Sets the uniform variable called \a name in the current context to
2352 the 4D vector (\a x, \a y, \a z, \a w).
2353
2354 \sa setAttributeValue()
2355*/
2356void QOpenGLShaderProgram::setUniformValue
2357 (const char *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
2358{
2359 setUniformValue(location: uniformLocation(name), x, y, z, w);
2360}
2361
2362/*!
2363 Sets the uniform variable at \a location in the current context to \a value.
2364
2365 \sa setAttributeValue()
2366*/
2367void QOpenGLShaderProgram::setUniformValue(int location, const QVector2D& value)
2368{
2369 Q_D(QOpenGLShaderProgram);
2370 Q_UNUSED(d);
2371 if (location != -1)
2372 d->glfuncs->glUniform2fv(location, count: 1, v: reinterpret_cast<const GLfloat *>(&value));
2373}
2374
2375/*!
2376 \overload
2377
2378 Sets the uniform variable called \a name in the current context
2379 to \a value.
2380
2381 \sa setAttributeValue()
2382*/
2383void QOpenGLShaderProgram::setUniformValue(const char *name, const QVector2D& value)
2384{
2385 setUniformValue(location: uniformLocation(name), value);
2386}
2387
2388/*!
2389 Sets the uniform variable at \a location in the current context to \a value.
2390
2391 \sa setAttributeValue()
2392*/
2393void QOpenGLShaderProgram::setUniformValue(int location, const QVector3D& value)
2394{
2395 Q_D(QOpenGLShaderProgram);
2396 Q_UNUSED(d);
2397 if (location != -1)
2398 d->glfuncs->glUniform3fv(location, count: 1, v: reinterpret_cast<const GLfloat *>(&value));
2399}
2400
2401/*!
2402 \overload
2403
2404 Sets the uniform variable called \a name in the current context
2405 to \a value.
2406
2407 \sa setAttributeValue()
2408*/
2409void QOpenGLShaderProgram::setUniformValue(const char *name, const QVector3D& value)
2410{
2411 setUniformValue(location: uniformLocation(name), value);
2412}
2413
2414/*!
2415 Sets the uniform variable at \a location in the current context to \a value.
2416
2417 \sa setAttributeValue()
2418*/
2419void QOpenGLShaderProgram::setUniformValue(int location, const QVector4D& value)
2420{
2421 Q_D(QOpenGLShaderProgram);
2422 Q_UNUSED(d);
2423 if (location != -1)
2424 d->glfuncs->glUniform4fv(location, count: 1, v: reinterpret_cast<const GLfloat *>(&value));
2425}
2426
2427/*!
2428 \overload
2429
2430 Sets the uniform variable called \a name in the current context
2431 to \a value.
2432
2433 \sa setAttributeValue()
2434*/
2435void QOpenGLShaderProgram::setUniformValue(const char *name, const QVector4D& value)
2436{
2437 setUniformValue(location: uniformLocation(name), value);
2438}
2439
2440/*!
2441 Sets the uniform variable at \a location in the current context to
2442 the red, green, blue, and alpha components of \a color.
2443
2444 \sa setAttributeValue()
2445*/
2446void QOpenGLShaderProgram::setUniformValue(int location, const QColor& color)
2447{
2448 Q_D(QOpenGLShaderProgram);
2449 Q_UNUSED(d);
2450 if (location != -1) {
2451 GLfloat values[4] = {GLfloat(color.redF()), GLfloat(color.greenF()),
2452 GLfloat(color.blueF()), GLfloat(color.alphaF())};
2453 d->glfuncs->glUniform4fv(location, count: 1, v: values);
2454 }
2455}
2456
2457/*!
2458 \overload
2459
2460 Sets the uniform variable called \a name in the current context to
2461 the red, green, blue, and alpha components of \a color.
2462
2463 \sa setAttributeValue()
2464*/
2465void QOpenGLShaderProgram::setUniformValue(const char *name, const QColor& color)
2466{
2467 setUniformValue(location: uniformLocation(name), color);
2468}
2469
2470/*!
2471 Sets the uniform variable at \a location in the current context to
2472 the x and y coordinates of \a point.
2473
2474 \sa setAttributeValue()
2475*/
2476void QOpenGLShaderProgram::setUniformValue(int location, const QPoint& point)
2477{
2478 Q_D(QOpenGLShaderProgram);
2479 Q_UNUSED(d);
2480 if (location != -1) {
2481 GLfloat values[4] = {GLfloat(point.x()), GLfloat(point.y())};
2482 d->glfuncs->glUniform2fv(location, count: 1, v: values);
2483 }
2484}
2485
2486/*!
2487 \overload
2488
2489 Sets the uniform variable associated with \a name in the current
2490 context to the x and y coordinates of \a point.
2491
2492 \sa setAttributeValue()
2493*/
2494void QOpenGLShaderProgram::setUniformValue(const char *name, const QPoint& point)
2495{
2496 setUniformValue(location: uniformLocation(name), point);
2497}
2498
2499/*!
2500 Sets the uniform variable at \a location in the current context to
2501 the x and y coordinates of \a point.
2502
2503 \sa setAttributeValue()
2504*/
2505void QOpenGLShaderProgram::setUniformValue(int location, const QPointF& point)
2506{
2507 Q_D(QOpenGLShaderProgram);
2508 Q_UNUSED(d);
2509 if (location != -1) {
2510 GLfloat values[4] = {GLfloat(point.x()), GLfloat(point.y())};
2511 d->glfuncs->glUniform2fv(location, count: 1, v: values);
2512 }
2513}
2514
2515/*!
2516 \overload
2517
2518 Sets the uniform variable associated with \a name in the current
2519 context to the x and y coordinates of \a point.
2520
2521 \sa setAttributeValue()
2522*/
2523void QOpenGLShaderProgram::setUniformValue(const char *name, const QPointF& point)
2524{
2525 setUniformValue(location: uniformLocation(name), point);
2526}
2527
2528/*!
2529 Sets the uniform variable at \a location in the current context to
2530 the width and height of the given \a size.
2531
2532 \sa setAttributeValue()
2533*/
2534void QOpenGLShaderProgram::setUniformValue(int location, const QSize& size)
2535{
2536 Q_D(QOpenGLShaderProgram);
2537 Q_UNUSED(d);
2538 if (location != -1) {
2539 GLfloat values[4] = {GLfloat(size.width()), GLfloat(size.height())};
2540 d->glfuncs->glUniform2fv(location, count: 1, v: values);
2541 }
2542}
2543
2544/*!
2545 \overload
2546
2547 Sets the uniform variable associated with \a name in the current
2548 context to the width and height of the given \a size.
2549
2550 \sa setAttributeValue()
2551*/
2552void QOpenGLShaderProgram::setUniformValue(const char *name, const QSize& size)
2553{
2554 setUniformValue(location: uniformLocation(name), size);
2555}
2556
2557/*!
2558 Sets the uniform variable at \a location in the current context to
2559 the width and height of the given \a size.
2560
2561 \sa setAttributeValue()
2562*/
2563void QOpenGLShaderProgram::setUniformValue(int location, const QSizeF& size)
2564{
2565 Q_D(QOpenGLShaderProgram);
2566 Q_UNUSED(d);
2567 if (location != -1) {
2568 GLfloat values[4] = {GLfloat(size.width()), GLfloat(size.height())};
2569 d->glfuncs->glUniform2fv(location, count: 1, v: values);
2570 }
2571}
2572
2573/*!
2574 \overload
2575
2576 Sets the uniform variable associated with \a name in the current
2577 context to the width and height of the given \a size.
2578
2579 \sa setAttributeValue()
2580*/
2581void QOpenGLShaderProgram::setUniformValue(const char *name, const QSizeF& size)
2582{
2583 setUniformValue(location: uniformLocation(name), size);
2584}
2585
2586/*!
2587 Sets the uniform variable at \a location in the current context
2588 to a 2x2 matrix \a value.
2589
2590 \sa setAttributeValue()
2591*/
2592void QOpenGLShaderProgram::setUniformValue(int location, const QMatrix2x2& value)
2593{
2594 Q_D(QOpenGLShaderProgram);
2595 Q_UNUSED(d);
2596 d->glfuncs->glUniformMatrix2fv(location, count: 1, GL_FALSE, value: value.constData());
2597}
2598
2599/*!
2600 \overload
2601
2602 Sets the uniform variable called \a name in the current context
2603 to a 2x2 matrix \a value.
2604
2605 \sa setAttributeValue()
2606*/
2607void QOpenGLShaderProgram::setUniformValue(const char *name, const QMatrix2x2& value)
2608{
2609 setUniformValue(location: uniformLocation(name), value);
2610}
2611
2612/*!
2613 Sets the uniform variable at \a location in the current context
2614 to a 2x3 matrix \a value.
2615
2616 \note This function is not aware of non square matrix support,
2617 that is, GLSL types like mat2x3, that is present in modern OpenGL
2618 versions. Instead, it treats the uniform as an array of vec3.
2619
2620 \sa setAttributeValue()
2621*/
2622void QOpenGLShaderProgram::setUniformValue(int location, const QMatrix2x3& value)
2623{
2624 Q_D(QOpenGLShaderProgram);
2625 Q_UNUSED(d);
2626 d->glfuncs->glUniform3fv(location, count: 2, v: value.constData());
2627}
2628
2629/*!
2630 \overload
2631
2632 Sets the uniform variable called \a name in the current context
2633 to a 2x3 matrix \a value.
2634
2635 \note This function is not aware of non square matrix support,
2636 that is, GLSL types like mat2x3, that is present in modern OpenGL
2637 versions. Instead, it treats the uniform as an array of vec3.
2638
2639 \sa setAttributeValue()
2640*/
2641void QOpenGLShaderProgram::setUniformValue(const char *name, const QMatrix2x3& value)
2642{
2643 setUniformValue(location: uniformLocation(name), value);
2644}
2645
2646/*!
2647 Sets the uniform variable at \a location in the current context
2648 to a 2x4 matrix \a value.
2649
2650 \note This function is not aware of non square matrix support,
2651 that is, GLSL types like mat2x4, that is present in modern OpenGL
2652 versions. Instead, it treats the uniform as an array of vec4.
2653
2654 \sa setAttributeValue()
2655*/
2656void QOpenGLShaderProgram::setUniformValue(int location, const QMatrix2x4& value)
2657{
2658 Q_D(QOpenGLShaderProgram);
2659 Q_UNUSED(d);
2660 d->glfuncs->glUniform4fv(location, count: 2, v: value.constData());
2661}
2662
2663/*!
2664 \overload
2665
2666 Sets the uniform variable called \a name in the current context
2667 to a 2x4 matrix \a value.
2668
2669 \note This function is not aware of non square matrix support,
2670 that is, GLSL types like mat2x4, that is present in modern OpenGL
2671 versions. Instead, it treats the uniform as an array of vec4.
2672
2673 \sa setAttributeValue()
2674*/
2675void QOpenGLShaderProgram::setUniformValue(const char *name, const QMatrix2x4& value)
2676{
2677 setUniformValue(location: uniformLocation(name), value);
2678}
2679
2680/*!
2681 Sets the uniform variable at \a location in the current context
2682 to a 3x2 matrix \a value.
2683
2684 \note This function is not aware of non square matrix support,
2685 that is, GLSL types like mat3x2, that is present in modern OpenGL
2686 versions. Instead, it treats the uniform as an array of vec2.
2687
2688 \sa setAttributeValue()
2689*/
2690void QOpenGLShaderProgram::setUniformValue(int location, const QMatrix3x2& value)
2691{
2692 Q_D(QOpenGLShaderProgram);
2693 Q_UNUSED(d);
2694 d->glfuncs->glUniform2fv(location, count: 3, v: value.constData());
2695}
2696
2697/*!
2698 \overload
2699
2700 Sets the uniform variable called \a name in the current context
2701 to a 3x2 matrix \a value.
2702
2703 \note This function is not aware of non square matrix support,
2704 that is, GLSL types like mat3x2, that is present in modern OpenGL
2705 versions. Instead, it treats the uniform as an array of vec2.
2706
2707 \sa setAttributeValue()
2708*/
2709void QOpenGLShaderProgram::setUniformValue(const char *name, const QMatrix3x2& value)
2710{
2711 setUniformValue(location: uniformLocation(name), value);
2712}
2713
2714/*!
2715 Sets the uniform variable at \a location in the current context
2716 to a 3x3 matrix \a value.
2717
2718 \sa setAttributeValue()
2719*/
2720void QOpenGLShaderProgram::setUniformValue(int location, const QMatrix3x3& value)
2721{
2722 Q_D(QOpenGLShaderProgram);
2723 Q_UNUSED(d);
2724 d->glfuncs->glUniformMatrix3fv(location, count: 1, GL_FALSE, value: value.constData());
2725}
2726
2727/*!
2728 \overload
2729
2730 Sets the uniform variable called \a name in the current context
2731 to a 3x3 matrix \a value.
2732
2733 \sa setAttributeValue()
2734*/
2735void QOpenGLShaderProgram::setUniformValue(const char *name, const QMatrix3x3& value)
2736{
2737 setUniformValue(location: uniformLocation(name), value);
2738}
2739
2740/*!
2741 Sets the uniform variable at \a location in the current context
2742 to a 3x4 matrix \a value.
2743
2744 \note This function is not aware of non square matrix support,
2745 that is, GLSL types like mat3x4, that is present in modern OpenGL
2746 versions. Instead, it treats the uniform as an array of vec4.
2747
2748 \sa setAttributeValue()
2749*/
2750void QOpenGLShaderProgram::setUniformValue(int location, const QMatrix3x4& value)
2751{
2752 Q_D(QOpenGLShaderProgram);
2753 Q_UNUSED(d);
2754 d->glfuncs->glUniform4fv(location, count: 3, v: value.constData());
2755}
2756
2757/*!
2758 \overload
2759
2760 Sets the uniform variable called \a name in the current context
2761 to a 3x4 matrix \a value.
2762
2763 \note This function is not aware of non square matrix support,
2764 that is, GLSL types like mat3x4, that is present in modern OpenGL
2765 versions. Instead, it treats the uniform as an array of vec4.
2766
2767 \sa setAttributeValue()
2768*/
2769void QOpenGLShaderProgram::setUniformValue(const char *name, const QMatrix3x4& value)
2770{
2771 setUniformValue(location: uniformLocation(name), value);
2772}
2773
2774/*!
2775 Sets the uniform variable at \a location in the current context
2776 to a 4x2 matrix \a value.
2777
2778 \note This function is not aware of non square matrix support,
2779 that is, GLSL types like mat4x2, that is present in modern OpenGL
2780 versions. Instead, it treats the uniform as an array of vec2.
2781
2782 \sa setAttributeValue()
2783*/
2784void QOpenGLShaderProgram::setUniformValue(int location, const QMatrix4x2& value)
2785{
2786 Q_D(QOpenGLShaderProgram);
2787 Q_UNUSED(d);
2788 d->glfuncs->glUniform2fv(location, count: 4, v: value.constData());
2789}
2790
2791/*!
2792 \overload
2793
2794 Sets the uniform variable called \a name in the current context
2795 to a 4x2 matrix \a value.
2796
2797 \note This function is not aware of non square matrix support,
2798 that is, GLSL types like mat4x2, that is present in modern OpenGL
2799 versions. Instead, it treats the uniform as an array of vec2.
2800
2801 \sa setAttributeValue()
2802*/
2803void QOpenGLShaderProgram::setUniformValue(const char *name, const QMatrix4x2& value)
2804{
2805 setUniformValue(location: uniformLocation(name), value);
2806}
2807
2808/*!
2809 Sets the uniform variable at \a location in the current context
2810 to a 4x3 matrix \a value.
2811
2812 \note This function is not aware of non square matrix support,
2813 that is, GLSL types like mat4x3, that is present in modern OpenGL
2814 versions. Instead, it treats the uniform as an array of vec3.
2815
2816 \sa setAttributeValue()
2817*/
2818void QOpenGLShaderProgram::setUniformValue(int location, const QMatrix4x3& value)
2819{
2820 Q_D(QOpenGLShaderProgram);
2821 Q_UNUSED(d);
2822 d->glfuncs->glUniform3fv(location, count: 4, v: value.constData());
2823}
2824
2825/*!
2826 \overload
2827
2828 Sets the uniform variable called \a name in the current context
2829 to a 4x3 matrix \a value.
2830
2831 \note This function is not aware of non square matrix support,
2832 that is, GLSL types like mat4x3, that is present in modern OpenGL
2833 versions. Instead, it treats the uniform as an array of vec3.
2834
2835 \sa setAttributeValue()
2836*/
2837void QOpenGLShaderProgram::setUniformValue(const char *name, const QMatrix4x3& value)
2838{
2839 setUniformValue(location: uniformLocation(name), value);
2840}
2841
2842/*!
2843 Sets the uniform variable at \a location in the current context
2844 to a 4x4 matrix \a value.
2845
2846 \sa setAttributeValue()
2847*/
2848void QOpenGLShaderProgram::setUniformValue(int location, const QMatrix4x4& value)
2849{
2850 Q_D(QOpenGLShaderProgram);
2851 Q_UNUSED(d);
2852 d->glfuncs->glUniformMatrix4fv(location, count: 1, GL_FALSE, value: value.constData());
2853}
2854
2855/*!
2856 \overload
2857
2858 Sets the uniform variable called \a name in the current context
2859 to a 4x4 matrix \a value.
2860
2861 \sa setAttributeValue()
2862*/
2863void QOpenGLShaderProgram::setUniformValue(const char *name, const QMatrix4x4& value)
2864{
2865 setUniformValue(location: uniformLocation(name), value);
2866}
2867
2868/*!
2869 \overload
2870
2871 Sets the uniform variable at \a location in the current context
2872 to a 2x2 matrix \a value. The matrix elements must be specified
2873 in column-major order.
2874
2875 \sa setAttributeValue()
2876*/
2877void QOpenGLShaderProgram::setUniformValue(int location, const GLfloat value[2][2])
2878{
2879 Q_D(QOpenGLShaderProgram);
2880 Q_UNUSED(d);
2881 if (location != -1)
2882 d->glfuncs->glUniformMatrix2fv(location, count: 1, GL_FALSE, value: value[0]);
2883}
2884
2885/*!
2886 \overload
2887
2888 Sets the uniform variable at \a location in the current context
2889 to a 3x3 matrix \a value. The matrix elements must be specified
2890 in column-major order.
2891
2892 \sa setAttributeValue()
2893*/
2894void QOpenGLShaderProgram::setUniformValue(int location, const GLfloat value[3][3])
2895{
2896 Q_D(QOpenGLShaderProgram);
2897 Q_UNUSED(d);
2898 if (location != -1)
2899 d->glfuncs->glUniformMatrix3fv(location, count: 1, GL_FALSE, value: value[0]);
2900}
2901
2902/*!
2903 \overload
2904
2905 Sets the uniform variable at \a location in the current context
2906 to a 4x4 matrix \a value. The matrix elements must be specified
2907 in column-major order.
2908
2909 \sa setAttributeValue()
2910*/
2911void QOpenGLShaderProgram::setUniformValue(int location, const GLfloat value[4][4])
2912{
2913 Q_D(QOpenGLShaderProgram);
2914 Q_UNUSED(d);
2915 if (location != -1)
2916 d->glfuncs->glUniformMatrix4fv(location, count: 1, GL_FALSE, value: value[0]);
2917}
2918
2919
2920/*!
2921 \overload
2922
2923 Sets the uniform variable called \a name in the current context
2924 to a 2x2 matrix \a value. The matrix elements must be specified
2925 in column-major order.
2926
2927 \sa setAttributeValue()
2928*/
2929void QOpenGLShaderProgram::setUniformValue(const char *name, const GLfloat value[2][2])
2930{
2931 setUniformValue(location: uniformLocation(name), value);
2932}
2933
2934/*!
2935 \overload
2936
2937 Sets the uniform variable called \a name in the current context
2938 to a 3x3 matrix \a value. The matrix elements must be specified
2939 in column-major order.
2940
2941 \sa setAttributeValue()
2942*/
2943void QOpenGLShaderProgram::setUniformValue(const char *name, const GLfloat value[3][3])
2944{
2945 setUniformValue(location: uniformLocation(name), value);
2946}
2947
2948/*!
2949 \overload
2950
2951 Sets the uniform variable called \a name in the current context
2952 to a 4x4 matrix \a value. The matrix elements must be specified
2953 in column-major order.
2954
2955 \sa setAttributeValue()
2956*/
2957void QOpenGLShaderProgram::setUniformValue(const char *name, const GLfloat value[4][4])
2958{
2959 setUniformValue(location: uniformLocation(name), value);
2960}
2961
2962/*!
2963 Sets the uniform variable at \a location in the current context to a
2964 3x3 transformation matrix \a value that is specified as a QTransform value.
2965
2966 To set a QTransform value as a 4x4 matrix in a shader, use
2967 \c{setUniformValue(location, QMatrix4x4(value))}.
2968*/
2969void QOpenGLShaderProgram::setUniformValue(int location, const QTransform& value)
2970{
2971 Q_D(QOpenGLShaderProgram);
2972 Q_UNUSED(d);
2973 if (location != -1) {
2974 GLfloat mat[3][3] = {
2975 {GLfloat(value.m11()), GLfloat(value.m12()), GLfloat(value.m13())},
2976 {GLfloat(value.m21()), GLfloat(value.m22()), GLfloat(value.m23())},
2977 {GLfloat(value.m31()), GLfloat(value.m32()), GLfloat(value.m33())}
2978 };
2979 d->glfuncs->glUniformMatrix3fv(location, count: 1, GL_FALSE, value: mat[0]);
2980 }
2981}
2982
2983/*!
2984 \overload
2985
2986 Sets the uniform variable called \a name in the current context to a
2987 3x3 transformation matrix \a value that is specified as a QTransform value.
2988
2989 To set a QTransform value as a 4x4 matrix in a shader, use
2990 \c{setUniformValue(name, QMatrix4x4(value))}.
2991*/
2992void QOpenGLShaderProgram::setUniformValue
2993 (const char *name, const QTransform& value)
2994{
2995 setUniformValue(location: uniformLocation(name), value);
2996}
2997
2998/*!
2999 Sets the uniform variable array at \a location in the current
3000 context to the \a count elements of \a values.
3001
3002 \sa setAttributeValue()
3003*/
3004void QOpenGLShaderProgram::setUniformValueArray(int location, const GLint *values, int count)
3005{
3006 Q_D(QOpenGLShaderProgram);
3007 Q_UNUSED(d);
3008 if (location != -1)
3009 d->glfuncs->glUniform1iv(location, count, v: values);
3010}
3011
3012/*!
3013 \overload
3014
3015 Sets the uniform variable array called \a name in the current
3016 context to the \a count elements of \a values.
3017
3018 \sa setAttributeValue()
3019*/
3020void QOpenGLShaderProgram::setUniformValueArray
3021 (const char *name, const GLint *values, int count)
3022{
3023 setUniformValueArray(location: uniformLocation(name), values, count);
3024}
3025
3026/*!
3027 Sets the uniform variable array at \a location in the current
3028 context to the \a count elements of \a values. This overload
3029 should be used when setting an array of sampler values.
3030
3031 \note This function is not aware of unsigned int support in modern OpenGL
3032 versions and therefore treats \a values as a GLint and calls glUniform1iv.
3033
3034 \sa setAttributeValue()
3035*/
3036void QOpenGLShaderProgram::setUniformValueArray(int location, const GLuint *values, int count)
3037{
3038 Q_D(QOpenGLShaderProgram);
3039 Q_UNUSED(d);
3040 if (location != -1)
3041 d->glfuncs->glUniform1iv(location, count, v: reinterpret_cast<const GLint *>(values));
3042}
3043
3044/*!
3045 \overload
3046
3047 Sets the uniform variable array called \a name in the current
3048 context to the \a count elements of \a values. This overload
3049 should be used when setting an array of sampler values.
3050
3051 \sa setAttributeValue()
3052*/
3053void QOpenGLShaderProgram::setUniformValueArray
3054 (const char *name, const GLuint *values, int count)
3055{
3056 setUniformValueArray(location: uniformLocation(name), values, count);
3057}
3058
3059/*!
3060 Sets the uniform variable array at \a location in the current
3061 context to the \a count elements of \a values. Each element
3062 has \a tupleSize components. The \a tupleSize must be 1, 2, 3, or 4.
3063
3064 \sa setAttributeValue()
3065*/
3066void QOpenGLShaderProgram::setUniformValueArray(int location, const GLfloat *values, int count, int tupleSize)
3067{
3068 Q_D(QOpenGLShaderProgram);
3069 Q_UNUSED(d);
3070 if (location != -1) {
3071 if (tupleSize == 1)
3072 d->glfuncs->glUniform1fv(location, count, v: values);
3073 else if (tupleSize == 2)
3074 d->glfuncs->glUniform2fv(location, count, v: values);
3075 else if (tupleSize == 3)
3076 d->glfuncs->glUniform3fv(location, count, v: values);
3077 else if (tupleSize == 4)
3078 d->glfuncs->glUniform4fv(location, count, v: values);
3079 else
3080 qWarning(msg: "QOpenGLShaderProgram::setUniformValue: size %d not supported", tupleSize);
3081 }
3082}
3083
3084/*!
3085 \overload
3086
3087 Sets the uniform variable array called \a name in the current
3088 context to the \a count elements of \a values. Each element
3089 has \a tupleSize components. The \a tupleSize must be 1, 2, 3, or 4.
3090
3091 \sa setAttributeValue()
3092*/
3093void QOpenGLShaderProgram::setUniformValueArray
3094 (const char *name, const GLfloat *values, int count, int tupleSize)
3095{
3096 setUniformValueArray(location: uniformLocation(name), values, count, tupleSize);
3097}
3098
3099/*!
3100 Sets the uniform variable array at \a location in the current
3101 context to the \a count 2D vector elements of \a values.
3102
3103 \sa setAttributeValue()
3104*/
3105void QOpenGLShaderProgram::setUniformValueArray(int location, const QVector2D *values, int count)
3106{
3107 Q_D(QOpenGLShaderProgram);
3108 Q_UNUSED(d);
3109 if (location != -1)
3110 d->glfuncs->glUniform2fv(location, count, v: reinterpret_cast<const GLfloat *>(values));
3111}
3112
3113/*!
3114 \overload
3115
3116 Sets the uniform variable array called \a name in the current
3117 context to the \a count 2D vector elements of \a values.
3118
3119 \sa setAttributeValue()
3120*/
3121void QOpenGLShaderProgram::setUniformValueArray(const char *name, const QVector2D *values, int count)
3122{
3123 setUniformValueArray(location: uniformLocation(name), values, count);
3124}
3125
3126/*!
3127 Sets the uniform variable array at \a location in the current
3128 context to the \a count 3D vector elements of \a values.
3129
3130 \sa setAttributeValue()
3131*/
3132void QOpenGLShaderProgram::setUniformValueArray(int location, const QVector3D *values, int count)
3133{
3134 Q_D(QOpenGLShaderProgram);
3135 Q_UNUSED(d);
3136 if (location != -1)
3137 d->glfuncs->glUniform3fv(location, count, v: reinterpret_cast<const GLfloat *>(values));
3138}
3139
3140/*!
3141 \overload
3142
3143 Sets the uniform variable array called \a name in the current
3144 context to the \a count 3D vector elements of \a values.
3145
3146 \sa setAttributeValue()
3147*/
3148void QOpenGLShaderProgram::setUniformValueArray(const char *name, const QVector3D *values, int count)
3149{
3150 setUniformValueArray(location: uniformLocation(name), values, count);
3151}
3152
3153/*!
3154 Sets the uniform variable array at \a location in the current
3155 context to the \a count 4D vector elements of \a values.
3156
3157 \sa setAttributeValue()
3158*/
3159void QOpenGLShaderProgram::setUniformValueArray(int location, const QVector4D *values, int count)
3160{
3161 Q_D(QOpenGLShaderProgram);
3162 Q_UNUSED(d);
3163 if (location != -1)
3164 d->glfuncs->glUniform4fv(location, count, v: reinterpret_cast<const GLfloat *>(values));
3165}
3166
3167/*!
3168 \overload
3169
3170 Sets the uniform variable array called \a name in the current
3171 context to the \a count 4D vector elements of \a values.
3172
3173 \sa setAttributeValue()
3174*/
3175void QOpenGLShaderProgram::setUniformValueArray(const char *name, const QVector4D *values, int count)
3176{
3177 setUniformValueArray(location: uniformLocation(name), values, count);
3178}
3179
3180// We have to repack matrix arrays from qreal to GLfloat.
3181#define setUniformMatrixArray(func,location,values,count,type,cols,rows) \
3182 if (location == -1 || count <= 0) \
3183 return; \
3184 if (sizeof(type) == sizeof(GLfloat) * cols * rows) { \
3185 func(location, count, GL_FALSE, \
3186 reinterpret_cast<const GLfloat *>(values[0].constData())); \
3187 } else { \
3188 QVarLengthArray<GLfloat> temp(cols * rows * count); \
3189 for (int index = 0; index < count; ++index) { \
3190 for (int index2 = 0; index2 < (cols * rows); ++index2) { \
3191 temp.data()[cols * rows * index + index2] = \
3192 values[index].constData()[index2]; \
3193 } \
3194 } \
3195 func(location, count, GL_FALSE, temp.constData()); \
3196 }
3197#define setUniformGenericMatrixArray(colfunc,location,values,count,type,cols,rows) \
3198 if (location == -1 || count <= 0) \
3199 return; \
3200 if (sizeof(type) == sizeof(GLfloat) * cols * rows) { \
3201 const GLfloat *data = reinterpret_cast<const GLfloat *> \
3202 (values[0].constData()); \
3203 colfunc(location, count * cols, data); \
3204 } else { \
3205 QVarLengthArray<GLfloat> temp(cols * rows * count); \
3206 for (int index = 0; index < count; ++index) { \
3207 for (int index2 = 0; index2 < (cols * rows); ++index2) { \
3208 temp.data()[cols * rows * index + index2] = \
3209 values[index].constData()[index2]; \
3210 } \
3211 } \
3212 colfunc(location, count * cols, temp.constData()); \
3213 }
3214
3215/*!
3216 Sets the uniform variable array at \a location in the current
3217 context to the \a count 2x2 matrix elements of \a values.
3218
3219 \sa setAttributeValue()
3220*/
3221void QOpenGLShaderProgram::setUniformValueArray(int location, const QMatrix2x2 *values, int count)
3222{
3223 Q_D(QOpenGLShaderProgram);
3224 Q_UNUSED(d);
3225 setUniformMatrixArray
3226 (d->glfuncs->glUniformMatrix2fv, location, values, count, QMatrix2x2, 2, 2);
3227}
3228
3229/*!
3230 \overload
3231
3232 Sets the uniform variable array called \a name in the current
3233 context to the \a count 2x2 matrix elements of \a values.
3234
3235 \sa setAttributeValue()
3236*/
3237void QOpenGLShaderProgram::setUniformValueArray(const char *name, const QMatrix2x2 *values, int count)
3238{
3239 setUniformValueArray(location: uniformLocation(name), values, count);
3240}
3241
3242/*!
3243 Sets the uniform variable array at \a location in the current
3244 context to the \a count 2x3 matrix elements of \a values.
3245
3246 \sa setAttributeValue()
3247*/
3248void QOpenGLShaderProgram::setUniformValueArray(int location, const QMatrix2x3 *values, int count)
3249{
3250 Q_D(QOpenGLShaderProgram);
3251 Q_UNUSED(d);
3252 setUniformGenericMatrixArray
3253 (d->glfuncs->glUniform3fv, location, values, count,
3254 QMatrix2x3, 2, 3);
3255}
3256
3257/*!
3258 \overload
3259
3260 Sets the uniform variable array called \a name in the current
3261 context to the \a count 2x3 matrix elements of \a values.
3262
3263 \sa setAttributeValue()
3264*/
3265void QOpenGLShaderProgram::setUniformValueArray(const char *name, const QMatrix2x3 *values, int count)
3266{
3267 setUniformValueArray(location: uniformLocation(name), values, count);
3268}
3269
3270/*!
3271 Sets the uniform variable array at \a location in the current
3272 context to the \a count 2x4 matrix elements of \a values.
3273
3274 \sa setAttributeValue()
3275*/
3276void QOpenGLShaderProgram::setUniformValueArray(int location, const QMatrix2x4 *values, int count)
3277{
3278 Q_D(QOpenGLShaderProgram);
3279 Q_UNUSED(d);
3280 setUniformGenericMatrixArray
3281 (d->glfuncs->glUniform4fv, location, values, count,
3282 QMatrix2x4, 2, 4);
3283}
3284
3285/*!
3286 \overload
3287
3288 Sets the uniform variable array called \a name in the current
3289 context to the \a count 2x4 matrix elements of \a values.
3290
3291 \sa setAttributeValue()
3292*/
3293void QOpenGLShaderProgram::setUniformValueArray(const char *name, const QMatrix2x4 *values, int count)
3294{
3295 setUniformValueArray(location: uniformLocation(name), values, count);
3296}
3297
3298/*!
3299 Sets the uniform variable array at \a location in the current
3300 context to the \a count 3x2 matrix elements of \a values.
3301
3302 \sa setAttributeValue()
3303*/
3304void QOpenGLShaderProgram::setUniformValueArray(int location, const QMatrix3x2 *values, int count)
3305{
3306 Q_D(QOpenGLShaderProgram);
3307 Q_UNUSED(d);
3308 setUniformGenericMatrixArray
3309 (d->glfuncs->glUniform2fv, location, values, count,
3310 QMatrix3x2, 3, 2);
3311}
3312
3313/*!
3314 \overload
3315
3316 Sets the uniform variable array called \a name in the current
3317 context to the \a count 3x2 matrix elements of \a values.
3318
3319 \sa setAttributeValue()
3320*/
3321void QOpenGLShaderProgram::setUniformValueArray(const char *name, const QMatrix3x2 *values, int count)
3322{
3323 setUniformValueArray(location: uniformLocation(name), values, count);
3324}
3325
3326/*!
3327 Sets the uniform variable array at \a location in the current
3328 context to the \a count 3x3 matrix elements of \a values.
3329
3330 \sa setAttributeValue()
3331*/
3332void QOpenGLShaderProgram::setUniformValueArray(int location, const QMatrix3x3 *values, int count)
3333{
3334 Q_D(QOpenGLShaderProgram);
3335 Q_UNUSED(d);
3336 setUniformMatrixArray
3337 (d->glfuncs->glUniformMatrix3fv, location, values, count, QMatrix3x3, 3, 3);
3338}
3339
3340/*!
3341 \overload
3342
3343 Sets the uniform variable array called \a name in the current
3344 context to the \a count 3x3 matrix elements of \a values.
3345
3346 \sa setAttributeValue()
3347*/
3348void QOpenGLShaderProgram::setUniformValueArray(const char *name, const QMatrix3x3 *values, int count)
3349{
3350 setUniformValueArray(location: uniformLocation(name), values, count);
3351}
3352
3353/*!
3354 Sets the uniform variable array at \a location in the current
3355 context to the \a count 3x4 matrix elements of \a values.
3356
3357 \sa setAttributeValue()
3358*/
3359void QOpenGLShaderProgram::setUniformValueArray(int location, const QMatrix3x4 *values, int count)
3360{
3361 Q_D(QOpenGLShaderProgram);
3362 Q_UNUSED(d);
3363 setUniformGenericMatrixArray
3364 (d->glfuncs->glUniform4fv, location, values, count,
3365 QMatrix3x4, 3, 4);
3366}
3367
3368/*!
3369 \overload
3370
3371 Sets the uniform variable array called \a name in the current
3372 context to the \a count 3x4 matrix elements of \a values.
3373
3374 \sa setAttributeValue()
3375*/
3376void QOpenGLShaderProgram::setUniformValueArray(const char *name, const QMatrix3x4 *values, int count)
3377{
3378 setUniformValueArray(location: uniformLocation(name), values, count);
3379}
3380
3381/*!
3382 Sets the uniform variable array at \a location in the current
3383 context to the \a count 4x2 matrix elements of \a values.
3384
3385 \sa setAttributeValue()
3386*/
3387void QOpenGLShaderProgram::setUniformValueArray(int location, const QMatrix4x2 *values, int count)
3388{
3389 Q_D(QOpenGLShaderProgram);
3390 Q_UNUSED(d);
3391 setUniformGenericMatrixArray
3392 (d->glfuncs->glUniform2fv, location, values, count,
3393 QMatrix4x2, 4, 2);
3394}
3395
3396/*!
3397 \overload
3398
3399 Sets the uniform variable array called \a name in the current
3400 context to the \a count 4x2 matrix elements of \a values.
3401
3402 \sa setAttributeValue()
3403*/
3404void QOpenGLShaderProgram::setUniformValueArray(const char *name, const QMatrix4x2 *values, int count)
3405{
3406 setUniformValueArray(location: uniformLocation(name), values, count);
3407}
3408
3409/*!
3410 Sets the uniform variable array at \a location in the current
3411 context to the \a count 4x3 matrix elements of \a values.
3412
3413 \sa setAttributeValue()
3414*/
3415void QOpenGLShaderProgram::setUniformValueArray(int location, const QMatrix4x3 *values, int count)
3416{
3417 Q_D(QOpenGLShaderProgram);
3418 Q_UNUSED(d);
3419 setUniformGenericMatrixArray
3420 (d->glfuncs->glUniform3fv, location, values, count,
3421 QMatrix4x3, 4, 3);
3422}
3423
3424/*!
3425 \overload
3426
3427 Sets the uniform variable array called \a name in the current
3428 context to the \a count 4x3 matrix elements of \a values.
3429
3430 \sa setAttributeValue()
3431*/
3432void QOpenGLShaderProgram::setUniformValueArray(const char *name, const QMatrix4x3 *values, int count)
3433{
3434 setUniformValueArray(location: uniformLocation(name), values, count);
3435}
3436
3437/*!
3438 Sets the uniform variable array at \a location in the current
3439 context to the \a count 4x4 matrix elements of \a values.
3440
3441 \sa setAttributeValue()
3442*/
3443void QOpenGLShaderProgram::setUniformValueArray(int location, const QMatrix4x4 *values, int count)
3444{
3445 Q_D(QOpenGLShaderProgram);
3446 Q_UNUSED(d);
3447 setUniformMatrixArray
3448 (d->glfuncs->glUniformMatrix4fv, location, values, count, QMatrix4x4, 4, 4);
3449}
3450
3451/*!
3452 \overload
3453
3454 Sets the uniform variable array called \a name in the current
3455 context to the \a count 4x4 matrix elements of \a values.
3456
3457 \sa setAttributeValue()
3458*/
3459void QOpenGLShaderProgram::setUniformValueArray(const char *name, const QMatrix4x4 *values, int count)
3460{
3461 setUniformValueArray(location: uniformLocation(name), values, count);
3462}
3463
3464/*!
3465 Returns the hardware limit for how many vertices a geometry shader
3466 can output.
3467*/
3468int QOpenGLShaderProgram::maxGeometryOutputVertices() const
3469{
3470 GLint n = 0;
3471 Q_D(const QOpenGLShaderProgram);
3472 d->glfuncs->glGetIntegerv(GL_MAX_GEOMETRY_OUTPUT_VERTICES, params: &n);
3473 return n;
3474}
3475
3476/*!
3477 Use this function to specify to OpenGL the number of vertices in
3478 a patch to \a count. A patch is a custom OpenGL primitive whose interpretation
3479 is entirely defined by the tessellation shader stages. Therefore, calling
3480 this function only makes sense when using a QOpenGLShaderProgram
3481 containing tessellation stage shaders. When using OpenGL tessellation,
3482 the only primitive that can be rendered with \c{glDraw*()} functions is
3483 \c{GL_PATCHES}.
3484
3485 This is equivalent to calling glPatchParameteri(GL_PATCH_VERTICES, count).
3486
3487 \note This modifies global OpenGL state and is not specific to this
3488 QOpenGLShaderProgram instance. You should call this in your render
3489 function when needed, as QOpenGLShaderProgram will not apply this for
3490 you. This is purely a convenience function.
3491
3492 \sa patchVertexCount()
3493*/
3494void QOpenGLShaderProgram::setPatchVertexCount(int count)
3495{
3496 Q_D(QOpenGLShaderProgram);
3497 d->glfuncs->glPatchParameteri(GL_PATCH_VERTICES, value: count);
3498}
3499
3500/*!
3501 Returns the number of vertices per-patch to be used when rendering.
3502
3503 \note This returns the global OpenGL state value. It is not specific to
3504 this QOpenGLShaderProgram instance.
3505
3506 \sa setPatchVertexCount()
3507*/
3508int QOpenGLShaderProgram::patchVertexCount() const
3509{
3510 int patchVertices = 0;
3511 Q_D(const QOpenGLShaderProgram);
3512 d->glfuncs->glGetIntegerv(GL_PATCH_VERTICES, params: &patchVertices);
3513 return patchVertices;
3514}
3515
3516/*!
3517 Sets the default outer tessellation levels to be used by the tessellation
3518 primitive generator in the event that the tessellation control shader
3519 does not output them to \a levels. For more details on OpenGL and Tessellation
3520 shaders see \l{OpenGL Tessellation Shaders}.
3521
3522 The \a levels argument should be a QList consisting of 4 floats. Not all
3523 of the values make sense for all tessellation modes. If you specify a vector with
3524 fewer than 4 elements, the remaining elements will be given a default value of 1.
3525
3526 \note This modifies global OpenGL state and is not specific to this
3527 QOpenGLShaderProgram instance. You should call this in your render
3528 function when needed, as QOpenGLShaderProgram will not apply this for
3529 you. This is purely a convenience function.
3530
3531 \note This function is only available with OpenGL >= 4.0 and is not supported
3532 with OpenGL ES 3.2.
3533
3534 \sa defaultOuterTessellationLevels(), setDefaultInnerTessellationLevels()
3535*/
3536void QOpenGLShaderProgram::setDefaultOuterTessellationLevels(const QList<float> &levels)
3537{
3538#if !QT_CONFIG(opengles2)
3539 Q_D(QOpenGLShaderProgram);
3540 if (d->tessellationFuncs) {
3541 QList<float> tessLevels = levels;
3542
3543 // Ensure we have the required 4 outer tessellation levels
3544 // Use default of 1 for missing entries (same as spec)
3545 const int argCount = 4;
3546 if (tessLevels.size() < argCount) {
3547 tessLevels.reserve(asize: argCount);
3548 for (int i = tessLevels.size(); i < argCount; ++i)
3549 tessLevels.append(t: 1.0f);
3550 }
3551 d->tessellationFuncs->glPatchParameterfv(GL_PATCH_DEFAULT_OUTER_LEVEL, values: tessLevels.data());
3552 }
3553#else
3554 Q_UNUSED(levels);
3555#endif
3556}
3557
3558/*!
3559 Returns the default outer tessellation levels to be used by the tessellation
3560 primitive generator in the event that the tessellation control shader
3561 does not output them. For more details on OpenGL and Tessellation shaders see
3562 \l{OpenGL Tessellation Shaders}.
3563
3564 Returns a QList of floats describing the outer tessellation levels. The vector
3565 will always have four elements but not all of them make sense for every mode
3566 of tessellation.
3567
3568 \note This returns the global OpenGL state value. It is not specific to
3569 this QOpenGLShaderProgram instance.
3570
3571 \note This function is only supported with OpenGL >= 4.0 and will not
3572 return valid results with OpenGL ES 3.2.
3573
3574 \sa setDefaultOuterTessellationLevels(), defaultInnerTessellationLevels()
3575*/
3576QList<float> QOpenGLShaderProgram::defaultOuterTessellationLevels() const
3577{
3578#if !QT_CONFIG(opengles2)
3579 QList<float> tessLevels(4, 1.0f);
3580 Q_D(const QOpenGLShaderProgram);
3581 if (d->tessellationFuncs)
3582 d->tessellationFuncs->glGetFloatv(GL_PATCH_DEFAULT_OUTER_LEVEL, params: tessLevels.data());
3583 return tessLevels;
3584#else
3585 return QList<float>();
3586#endif
3587}
3588
3589/*!
3590 Sets the default outer tessellation levels to be used by the tessellation
3591 primitive generator in the event that the tessellation control shader
3592 does not output them to \a levels. For more details on OpenGL and Tessellation shaders see
3593 \l{OpenGL Tessellation Shaders}.
3594
3595 The \a levels argument should be a QList consisting of 2 floats. Not all
3596 of the values make sense for all tessellation modes. If you specify a vector with
3597 fewer than 2 elements, the remaining elements will be given a default value of 1.
3598
3599 \note This modifies global OpenGL state and is not specific to this
3600 QOpenGLShaderProgram instance. You should call this in your render
3601 function when needed, as QOpenGLShaderProgram will not apply this for
3602 you. This is purely a convenience function.
3603
3604 \note This function is only available with OpenGL >= 4.0 and is not supported
3605 with OpenGL ES 3.2.
3606
3607 \sa defaultInnerTessellationLevels(), setDefaultOuterTessellationLevels()
3608*/
3609void QOpenGLShaderProgram::setDefaultInnerTessellationLevels(const QList<float> &levels)
3610{
3611#if !QT_CONFIG(opengles2)
3612 Q_D(QOpenGLShaderProgram);
3613 if (d->tessellationFuncs) {
3614 QList<float> tessLevels = levels;
3615
3616 // Ensure we have the required 2 inner tessellation levels
3617 // Use default of 1 for missing entries (same as spec)
3618 const int argCount = 2;
3619 if (tessLevels.size() < argCount) {
3620 tessLevels.reserve(asize: argCount);
3621 for (int i = tessLevels.size(); i < argCount; ++i)
3622 tessLevels.append(t: 1.0f);
3623 }
3624 d->tessellationFuncs->glPatchParameterfv(GL_PATCH_DEFAULT_INNER_LEVEL, values: tessLevels.data());
3625 }
3626#else
3627 Q_UNUSED(levels);
3628#endif
3629}
3630
3631/*!
3632 Returns the default inner tessellation levels to be used by the tessellation
3633 primitive generator in the event that the tessellation control shader
3634 does not output them. For more details on OpenGL and Tessellation shaders see
3635 \l{OpenGL Tessellation Shaders}.
3636
3637 Returns a QList of floats describing the inner tessellation levels. The vector
3638 will always have two elements but not all of them make sense for every mode
3639 of tessellation.
3640
3641 \note This returns the global OpenGL state value. It is not specific to
3642 this QOpenGLShaderProgram instance.
3643
3644 \note This function is only supported with OpenGL >= 4.0 and will not
3645 return valid results with OpenGL ES 3.2.
3646
3647 \sa setDefaultInnerTessellationLevels(), defaultOuterTessellationLevels()
3648*/
3649QList<float> QOpenGLShaderProgram::defaultInnerTessellationLevels() const
3650{
3651#if !QT_CONFIG(opengles2)
3652 QList<float> tessLevels(2, 1.0f);
3653 Q_D(const QOpenGLShaderProgram);
3654 if (d->tessellationFuncs)
3655 d->tessellationFuncs->glGetFloatv(GL_PATCH_DEFAULT_INNER_LEVEL, params: tessLevels.data());
3656 return tessLevels;
3657#else
3658 return QList<float>();
3659#endif
3660}
3661
3662
3663/*!
3664 Returns \c true if shader programs written in the OpenGL Shading
3665 Language (GLSL) are supported on this system; false otherwise.
3666
3667 The \a context is used to resolve the GLSL extensions.
3668 If \a context is \nullptr, then QOpenGLContext::currentContext()
3669 is used.
3670*/
3671bool QOpenGLShaderProgram::hasOpenGLShaderPrograms(QOpenGLContext *context)
3672{
3673 if (!context)
3674 context = QOpenGLContext::currentContext();
3675 if (!context)
3676 return false;
3677 return QOpenGLFunctions(context).hasOpenGLFeature(feature: QOpenGLFunctions::Shaders);
3678}
3679
3680/*!
3681 \internal
3682*/
3683void QOpenGLShaderProgram::shaderDestroyed()
3684{
3685 Q_D(QOpenGLShaderProgram);
3686 QOpenGLShader *shader = qobject_cast<QOpenGLShader *>(object: sender());
3687 if (shader && !d->removingShaders)
3688 removeShader(shader);
3689}
3690
3691/*!
3692 Returns \c true if shader programs of type \a type are supported on
3693 this system; false otherwise.
3694
3695 The \a context is used to resolve the GLSL extensions.
3696 If \a context is \nullptr, then QOpenGLContext::currentContext()
3697 is used.
3698*/
3699bool QOpenGLShader::hasOpenGLShaders(ShaderType type, QOpenGLContext *context)
3700{
3701 if (!context)
3702 context = QOpenGLContext::currentContext();
3703 if (!context)
3704 return false;
3705
3706 if ((type & ~(Geometry | Vertex | Fragment | TessellationControl | TessellationEvaluation | Compute)) || type == 0)
3707 return false;
3708
3709 if (type & QOpenGLShader::Geometry)
3710 return supportsGeometry(f: context->format());
3711 else if (type & (QOpenGLShader::TessellationControl | QOpenGLShader::TessellationEvaluation))
3712 return supportsTessellation(f: context->format());
3713 else if (type & QOpenGLShader::Compute)
3714 return supportsCompute(f: context->format());
3715
3716 // Unconditional support of vertex and fragment shaders implicitly assumes
3717 // a minimum OpenGL version of 2.0
3718 return true;
3719}
3720
3721bool QOpenGLShaderProgramPrivate::isCacheDisabled() const
3722{
3723 static QOpenGLProgramBinarySupportCheckWrapper binSupportCheck;
3724 return !binSupportCheck.get(context: QOpenGLContext::currentContext())->isSupported();
3725}
3726
3727bool QOpenGLShaderProgramPrivate::compileCacheable()
3728{
3729 Q_Q(QOpenGLShaderProgram);
3730 for (const QOpenGLProgramBinaryCache::ShaderDesc &shader : std::as_const(t&: binaryProgram.shaders)) {
3731 auto s = std::make_unique<QOpenGLShader>(args: qt_shaderStageToType(stage: shader.stage), args: q);
3732 if (!s->compileSourceCode(source: shader.source)) {
3733 log = s->log();
3734 return false;
3735 }
3736 anonShaders.append(t: s.release());
3737 if (!q->addShader(shader: anonShaders.last()))
3738 return false;
3739 }
3740 return true;
3741}
3742
3743bool QOpenGLShaderProgramPrivate::linkBinary()
3744{
3745 static QOpenGLProgramBinaryCache binCache;
3746
3747 Q_Q(QOpenGLShaderProgram);
3748
3749 const QByteArray cacheKey = binaryProgram.cacheKey();
3750 if (lcOpenGLProgramDiskCache().isEnabled(type: QtDebugMsg))
3751 qCDebug(lcOpenGLProgramDiskCache, "program with %d shaders, cache key %s",
3752 int(binaryProgram.shaders.size()), cacheKey.constData());
3753
3754 bool needsCompile = true;
3755 if (binCache.load(cacheKey, programId: q->programId())) {
3756 qCDebug(lcOpenGLProgramDiskCache, "Program binary received from cache");
3757 needsCompile = false;
3758 }
3759
3760 bool needsSave = false;
3761 if (needsCompile) {
3762 qCDebug(lcOpenGLProgramDiskCache, "Program binary not in cache, compiling");
3763 if (compileCacheable())
3764 needsSave = true;
3765 else
3766 return false;
3767 }
3768
3769 linkBinaryRecursion = true;
3770 bool ok = q->link();
3771 linkBinaryRecursion = false;
3772 if (ok && needsSave)
3773 binCache.save(cacheKey, programId: q->programId());
3774
3775 return ok;
3776}
3777
3778QT_END_NAMESPACE
3779
3780#include "moc_qopenglshaderprogram.cpp"
3781

source code of qtbase/src/opengl/qopenglshaderprogram.cpp