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