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