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