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