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