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

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