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 "qglshaderprogram.h"
41 #include <private/qopenglextensions_p.h>
42 #include "qgl_p.h"
43 #include <QtCore/private/qobject_p.h>
44 #include <QtCore/qdebug.h>
45 #include <QtCore/qfile.h>
46 #include <QtCore/qvarlengtharray.h>
47 #include <QtCore/qvector.h>
48 #include <QDebug>
49 
50 QT_BEGIN_NAMESPACE
51 
52 /*!
53     \class QGLShaderProgram
54     \inmodule QtOpenGL
55     \brief The QGLShaderProgram class allows OpenGL shader programs to be linked and used.
56     \since 4.6
57     \obsolete
58     \ingroup painting-3D
59 
60     \section1 Introduction
61 
62     This class supports shader programs written in the OpenGL Shading
63     Language (GLSL) and in the OpenGL/ES Shading Language (GLSL/ES).
64 
65     QGLShader and QGLShaderProgram shelter the programmer from the details of
66     compiling and linking vertex and fragment shaders.
67 
68     The following example creates a vertex shader program using the
69     supplied source \c{code}.  Once compiled and linked, the shader
70     program is activated in the current QGLContext by calling
71     QGLShaderProgram::bind():
72 
73     \snippet code/src_opengl_qglshaderprogram.cpp 0
74 
75     \section1 Writing Portable Shaders
76 
77     Shader programs can be difficult to reuse across OpenGL implementations
78     because of varying levels of support for standard vertex attributes and
79     uniform variables.  In particular, GLSL/ES lacks all of the
80     standard variables that are present on desktop OpenGL systems:
81     \c{gl_Vertex}, \c{gl_Normal}, \c{gl_Color}, and so on.  Desktop OpenGL
82     lacks the variable qualifiers \c{highp}, \c{mediump}, and \c{lowp}.
83 
84     The QGLShaderProgram class makes the process of writing portable shaders
85     easier by prefixing all shader programs with the following lines on
86     desktop OpenGL:
87 
88     \code
89     #define highp
90     #define mediump
91     #define lowp
92     \endcode
93 
94     This makes it possible to run most GLSL/ES shader programs
95     on desktop systems.  The programmer should restrict themselves
96     to just features that are present in GLSL/ES, and avoid
97     standard variable names that only work on the desktop.
98 
99     \section1 Simple Shader Example
100 
101     \snippet code/src_opengl_qglshaderprogram.cpp 1
102 
103     With the above shader program active, we can draw a green triangle
104     as follows:
105 
106     \snippet code/src_opengl_qglshaderprogram.cpp 2
107 
108     \section1 Binary Shaders and Programs
109 
110     Binary shaders may be specified using \c{glShaderBinary()} on
111     the return value from QGLShader::shaderId().  The QGLShader instance
112     containing the binary can then be added to the shader program with
113     addShader() and linked in the usual fashion with link().
114 
115     Binary programs may be specified using \c{glProgramBinaryOES()}
116     on the return value from programId().  Then the application should
117     call link(), which will notice that the program has already been
118     specified and linked, allowing other operations to be performed
119     on the shader program.
120 
121     \note This class has been deprecated in favor of QOpenGLShaderProgram.
122 
123     \sa QGLShader
124 */
125 
126 /*!
127     \class QGLShader
128     \inmodule QtOpenGL
129     \brief The QGLShader class allows OpenGL shaders to be compiled.
130     \since 4.6
131     \obsolete
132     \ingroup painting-3D
133 
134     This class supports shaders written in the OpenGL Shading Language (GLSL)
135     and in the OpenGL/ES Shading Language (GLSL/ES).
136 
137     QGLShader and QGLShaderProgram shelter the programmer from the details of
138     compiling and linking vertex and fragment shaders.
139 
140     \note This class has been deprecated in favor of QOpenGLShader.
141 
142     \sa QGLShaderProgram
143 */
144 
145 /*!
146     \enum QGLShader::ShaderTypeBit
147     This enum specifies the type of QGLShader that is being created.
148 
149     \value Vertex Vertex shader written in the OpenGL Shading Language (GLSL).
150     \value Fragment Fragment shader written in the OpenGL Shading Language (GLSL).
151     \value Geometry Geometry shaders written in the OpenGL Shading
152            Language (GLSL), based on the GL_EXT_geometry_shader4 extension.
153 */
154 
155 #ifndef GL_FRAGMENT_SHADER
156 #define GL_FRAGMENT_SHADER 0x8B30
157 #endif
158 #ifndef GL_VERTEX_SHADER
159 #define GL_VERTEX_SHADER 0x8B31
160 #endif
161 #ifndef GL_COMPILE_STATUS
162 #define GL_COMPILE_STATUS 0x8B81
163 #endif
164 #ifndef GL_LINK_STATUS
165 #define GL_LINK_STATUS 0x8B82
166 #endif
167 #ifndef GL_INFO_LOG_LENGTH
168 #define GL_INFO_LOG_LENGTH 0x8B84
169 #endif
170 #ifndef GL_ACTIVE_UNIFORMS
171 #define GL_ACTIVE_UNIFORMS 0x8B86
172 #endif
173 #ifndef GL_ACTIVE_UNIFORM_MAX_LENGTH
174 #define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87
175 #endif
176 #ifndef GL_ACTIVE_ATTRIBUTES
177 #define GL_ACTIVE_ATTRIBUTES 0x8B89
178 #endif
179 #ifndef GL_ACTIVE_ATTRIBUTE_MAX_LENGTH
180 #define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A
181 #endif
182 #ifndef GL_CURRENT_VERTEX_ATTRIB
183 #define GL_CURRENT_VERTEX_ATTRIB 0x8626
184 #endif
185 #ifndef GL_SHADER_SOURCE_LENGTH
186 #define GL_SHADER_SOURCE_LENGTH 0x8B88
187 #endif
188 #ifndef GL_SHADER_BINARY_FORMATS
189 #define GL_SHADER_BINARY_FORMATS          0x8DF8
190 #endif
191 #ifndef GL_NUM_SHADER_BINARY_FORMATS
192 #define GL_NUM_SHADER_BINARY_FORMATS      0x8DF9
193 #endif
194 
195 class QGLShaderPrivate : public QObjectPrivate
196 {
197     Q_DECLARE_PUBLIC(QGLShader)
198 public:
QGLShaderPrivate(const QGLContext * ctx,QGLShader::ShaderType type)199     QGLShaderPrivate(const QGLContext *ctx, QGLShader::ShaderType type)
200         : shaderGuard(0)
201         , shaderType(type)
202         , compiled(false)
203         , glfuncs(new QOpenGLFunctions(ctx->contextHandle()))
204     {
205     }
206     ~QGLShaderPrivate();
207 
208     QGLSharedResourceGuardBase *shaderGuard;
209     QGLShader::ShaderType shaderType;
210     bool compiled;
211     QString log;
212 
213     QOpenGLFunctions *glfuncs;
214 
215     bool create();
216     bool compile(QGLShader *q);
217     void deleteShader();
218 };
219 
220 namespace {
freeShaderFunc(QGLContext * ctx,GLuint id)221     void freeShaderFunc(QGLContext *ctx, GLuint id)
222     {
223         Q_ASSERT(ctx);
224         ctx->contextHandle()->functions()->glDeleteShader(id);
225     }
226 }
227 
228 #define ctx QGLContext::currentContext()
229 
~QGLShaderPrivate()230 QGLShaderPrivate::~QGLShaderPrivate()
231 {
232     delete glfuncs;
233     if (shaderGuard)
234         shaderGuard->free();
235 }
236 
create()237 bool QGLShaderPrivate::create()
238 {
239     QGLContext *context = const_cast<QGLContext *>(QGLContext::currentContext());
240     if (!context)
241         return false;
242 
243     if (glfuncs->hasOpenGLFeature(QOpenGLFunctions::Shaders)) {
244         GLuint shader;
245         if (shaderType == QGLShader::Vertex)
246             shader = glfuncs->glCreateShader(GL_VERTEX_SHADER);
247 #if !defined(QT_OPENGL_ES_2)
248         else if (shaderType == QGLShader::Geometry
249                  && !context->contextHandle()->isOpenGLES())
250             shader = glfuncs->glCreateShader(GL_GEOMETRY_SHADER_EXT);
251 #endif
252         else
253             shader = glfuncs->glCreateShader(GL_FRAGMENT_SHADER);
254         if (!shader) {
255             qWarning("Could not create shader of type %d.", int(shaderType));
256             return false;
257         }
258         shaderGuard = createSharedResourceGuard(context, shader, freeShaderFunc);
259         return true;
260     } else {
261         return false;
262     }
263 }
264 
compile(QGLShader * q)265 bool QGLShaderPrivate::compile(QGLShader *q)
266 {
267     GLuint shader = shaderGuard ? shaderGuard->id() : 0;
268     if (!shader)
269         return false;
270     glfuncs->glCompileShader(shader);
271     GLint value = 0;
272     glfuncs->glGetShaderiv(shader, GL_COMPILE_STATUS, &value);
273     compiled = (value != 0);
274     value = 0;
275     glfuncs->glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &value);
276     if (!compiled && value > 1) {
277         char *logbuf = new char [value];
278         GLint len;
279         glfuncs->glGetShaderInfoLog(shader, value, &len, logbuf);
280         log = QString::fromLatin1(logbuf);
281         QString name = q->objectName();
282 
283         const char *types[] = {
284             "Fragment",
285             "Vertex",
286             "Geometry",
287             ""
288         };
289 
290         const char *type = types[3];
291         if (shaderType == QGLShader::Fragment)
292             type = types[0];
293         else if (shaderType == QGLShader::Vertex)
294             type = types[1];
295         else if (shaderType == QGLShader::Geometry)
296             type = types[2];
297 
298         if (name.isEmpty())
299             qWarning("QGLShader::compile(%s): %s", type, qPrintable(log));
300         else
301             qWarning("QGLShader::compile(%s)[%s]: %s", type, qPrintable(name), qPrintable(log));
302 
303         delete [] logbuf;
304     }
305     return compiled;
306 }
307 
deleteShader()308 void QGLShaderPrivate::deleteShader()
309 {
310     if (shaderGuard) {
311         shaderGuard->free();
312         shaderGuard = 0;
313     }
314 }
315 
316 /*!
317     Constructs a new QGLShader object of the specified \a type
318     and attaches it to \a parent.  If shader programs are not supported,
319     QGLShaderProgram::hasOpenGLShaderPrograms() will return false.
320 
321     This constructor is normally followed by a call to compileSourceCode()
322     or compileSourceFile().
323 
324     The shader will be associated with the current QGLContext.
325 
326     \sa compileSourceCode(), compileSourceFile()
327 */
QGLShader(QGLShader::ShaderType type,QObject * parent)328 QGLShader::QGLShader(QGLShader::ShaderType type, QObject *parent)
329     : QObject(*new QGLShaderPrivate(QGLContext::currentContext(), type), parent)
330 {
331     Q_D(QGLShader);
332     d->create();
333 }
334 
335 /*!
336     Constructs a new QGLShader object of the specified \a type
337     and attaches it to \a parent.  If shader programs are not supported,
338     then QGLShaderProgram::hasOpenGLShaderPrograms() will return false.
339 
340     This constructor is normally followed by a call to compileSourceCode()
341     or compileSourceFile().
342 
343     The shader will be associated with \a context.
344 
345     \sa compileSourceCode(), compileSourceFile()
346 */
QGLShader(QGLShader::ShaderType type,const QGLContext * context,QObject * parent)347 QGLShader::QGLShader(QGLShader::ShaderType type, const QGLContext *context, QObject *parent)
348     : QObject(*new QGLShaderPrivate(context ? context : QGLContext::currentContext(), type), parent)
349 {
350     Q_D(QGLShader);
351 #ifndef QT_NO_DEBUG
352     if (context && !QGLContext::areSharing(context, QGLContext::currentContext())) {
353         qWarning("QGLShader::QGLShader: \'context\' must be the current context or sharing with it.");
354         return;
355     }
356 #endif
357     d->create();
358 }
359 
360 /*!
361     Deletes this shader.  If the shader has been attached to a
362     QGLShaderProgram object, then the actual shader will stay around
363     until the QGLShaderProgram is destroyed.
364 */
~QGLShader()365 QGLShader::~QGLShader()
366 {
367 }
368 
369 /*!
370     Returns the type of this shader.
371 */
shaderType() const372 QGLShader::ShaderType QGLShader::shaderType() const
373 {
374     Q_D(const QGLShader);
375     return d->shaderType;
376 }
377 
378 // The precision qualifiers are useful on OpenGL/ES systems,
379 // but usually not present on desktop systems.  Define the
380 // keywords to empty strings on desktop systems.
381 #if !defined(QT_OPENGL_ES) || defined(QT_OPENGL_FORCE_SHADER_DEFINES)
382 #define QGL_DEFINE_QUALIFIERS 1
383 static const char qualifierDefines[] =
384     "#define lowp\n"
385     "#define mediump\n"
386     "#define highp\n";
387 
388 #else
389 
390 // The "highp" qualifier doesn't exist in fragment shaders
391 // on all ES platforms.  When it doesn't exist, use "mediump".
392 #define QGL_REDEFINE_HIGHP 1
393 static const char redefineHighp[] =
394     "#ifndef GL_FRAGMENT_PRECISION_HIGH\n"
395     "#define highp mediump\n"
396     "#endif\n";
397 #endif
398 
399 /*!
400     Sets the \a source code for this shader and compiles it.
401     Returns \c true if the source was successfully compiled, false otherwise.
402 
403     \sa compileSourceFile()
404 */
compileSourceCode(const char * source)405 bool QGLShader::compileSourceCode(const char *source)
406 {
407     Q_D(QGLShader);
408     if (d->shaderGuard && d->shaderGuard->id()) {
409         QVarLengthArray<const char *, 4> src;
410         QVarLengthArray<GLint, 4> srclen;
411         int headerLen = 0;
412         while (source && source[headerLen] == '#') {
413             // Skip #version and #extension directives at the start of
414             // the shader code.  We need to insert the qualifierDefines
415             // and redefineHighp just after them.
416             if (qstrncmp(source + headerLen, "#version", 8) != 0 &&
417                     qstrncmp(source + headerLen, "#extension", 10) != 0) {
418                 break;
419             }
420             while (source[headerLen] != '\0' && source[headerLen] != '\n')
421                 ++headerLen;
422             if (source[headerLen] == '\n')
423                 ++headerLen;
424         }
425         if (headerLen > 0) {
426             src.append(source);
427             srclen.append(GLint(headerLen));
428         }
429 #ifdef QGL_DEFINE_QUALIFIERS
430         if (!QOpenGLContext::currentContext()->isOpenGLES()) {
431             src.append(qualifierDefines);
432             srclen.append(GLint(sizeof(qualifierDefines) - 1));
433         }
434 #endif
435 #ifdef QGL_REDEFINE_HIGHP
436         if (d->shaderType == Fragment
437             && QOpenGLContext::currentContext()->isOpenGLES()) {
438             src.append(redefineHighp);
439             srclen.append(GLint(sizeof(redefineHighp) - 1));
440         }
441 #endif
442         src.append(source + headerLen);
443         srclen.append(GLint(qstrlen(source + headerLen)));
444         d->glfuncs->glShaderSource(d->shaderGuard->id(), src.size(), src.data(), srclen.data());
445         return d->compile(this);
446     } else {
447         return false;
448     }
449 }
450 
451 /*!
452     \overload
453 
454     Sets the \a source code for this shader and compiles it.
455     Returns \c true if the source was successfully compiled, false otherwise.
456 
457     \sa compileSourceFile()
458 */
compileSourceCode(const QByteArray & source)459 bool QGLShader::compileSourceCode(const QByteArray& source)
460 {
461     return compileSourceCode(source.constData());
462 }
463 
464 /*!
465     \overload
466 
467     Sets the \a source code for this shader and compiles it.
468     Returns \c true if the source was successfully compiled, false otherwise.
469 
470     \sa compileSourceFile()
471 */
compileSourceCode(const QString & source)472 bool QGLShader::compileSourceCode(const QString& source)
473 {
474     return compileSourceCode(source.toLatin1().constData());
475 }
476 
477 /*!
478     Sets the source code for this shader to the contents of \a fileName
479     and compiles it.  Returns \c true if the file could be opened and the
480     source compiled, false otherwise.
481 
482     \sa compileSourceCode()
483 */
compileSourceFile(const QString & fileName)484 bool QGLShader::compileSourceFile(const QString& fileName)
485 {
486     QFile file(fileName);
487     if (!file.open(QFile::ReadOnly)) {
488         qWarning() << "QGLShader: Unable to open file" << fileName;
489         return false;
490     }
491 
492     QByteArray contents = file.readAll();
493     return compileSourceCode(contents.constData());
494 }
495 
496 /*!
497     Returns the source code for this shader.
498 
499     \sa compileSourceCode()
500 */
sourceCode() const501 QByteArray QGLShader::sourceCode() const
502 {
503     Q_D(const QGLShader);
504     GLuint shader = d->shaderGuard ? d->shaderGuard->id() : 0;
505     if (!shader)
506         return QByteArray();
507     GLint size = 0;
508     d->glfuncs->glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &size);
509     if (size <= 0)
510         return QByteArray();
511     GLint len = 0;
512     char *source = new char [size];
513     d->glfuncs->glGetShaderSource(shader, size, &len, source);
514     QByteArray src(source);
515     delete [] source;
516     return src;
517 }
518 
519 /*!
520     Returns \c true if this shader has been compiled; false otherwise.
521 
522     \sa compileSourceCode(), compileSourceFile()
523 */
isCompiled() const524 bool QGLShader::isCompiled() const
525 {
526     Q_D(const QGLShader);
527     return d->compiled;
528 }
529 
530 /*!
531     Returns the errors and warnings that occurred during the last compile.
532 
533     \sa compileSourceCode(), compileSourceFile()
534 */
log() const535 QString QGLShader::log() const
536 {
537     Q_D(const QGLShader);
538     return d->log;
539 }
540 
541 /*!
542     Returns the OpenGL identifier associated with this shader.
543 
544     \sa QGLShaderProgram::programId()
545 */
shaderId() const546 GLuint QGLShader::shaderId() const
547 {
548     Q_D(const QGLShader);
549     return d->shaderGuard ? d->shaderGuard->id() : 0;
550 }
551 
552 #undef ctx
553 
554 class ShaderProgramOpenGLFunctions : public QOpenGLFunctions
555 {
556 public:
ShaderProgramOpenGLFunctions()557     ShaderProgramOpenGLFunctions()
558         : QOpenGLFunctions()
559         , glProgramParameteri(0)
560     {
561     }
562 
563     typedef void (QOPENGLF_APIENTRYP type_glProgramParameteri)(GLuint program, GLenum pname, GLint value);
564 
initializeGeometryShaderFunctions()565     void initializeGeometryShaderFunctions()
566     {
567         QOpenGLContext *context = QOpenGLContext::currentContext();
568         if (!context->isOpenGLES()) {
569             glProgramParameteri = (type_glProgramParameteri)
570                 context->getProcAddress("glProgramParameteri");
571 
572             if (!glProgramParameteri) {
573                 glProgramParameteri = (type_glProgramParameteri)
574                     context->getProcAddress("glProgramParameteriEXT");
575             }
576         }
577     }
578 
579     type_glProgramParameteri glProgramParameteri;
580 };
581 
582 class QGLShaderProgramPrivate : public QObjectPrivate
583 {
584     Q_DECLARE_PUBLIC(QGLShaderProgram)
585 public:
QGLShaderProgramPrivate(const QGLContext *)586     QGLShaderProgramPrivate(const QGLContext *)
587         : programGuard(0)
588         , linked(false)
589         , inited(false)
590         , removingShaders(false)
591         , geometryVertexCount(64)
592         , geometryInputType(0)
593         , geometryOutputType(0)
594         , glfuncs(new ShaderProgramOpenGLFunctions)
595     {
596     }
597     ~QGLShaderProgramPrivate();
598 
599     QGLSharedResourceGuardBase *programGuard;
600     bool linked;
601     bool inited;
602     bool removingShaders;
603 
604     int geometryVertexCount;
605     GLenum geometryInputType;
606     GLenum geometryOutputType;
607 
608     QString log;
609     QList<QGLShader *> shaders;
610     QList<QGLShader *> anonShaders;
611 
612     ShaderProgramOpenGLFunctions *glfuncs;
613 
614     bool hasShader(QGLShader::ShaderType type) const;
615 };
616 
617 namespace {
freeProgramFunc(QGLContext * ctx,GLuint id)618     void freeProgramFunc(QGLContext *ctx, GLuint id)
619     {
620         Q_ASSERT(ctx);
621         ctx->contextHandle()->functions()->glDeleteProgram(id);
622     }
623 }
624 
625 
~QGLShaderProgramPrivate()626 QGLShaderProgramPrivate::~QGLShaderProgramPrivate()
627 {
628     delete glfuncs;
629     if (programGuard)
630         programGuard->free();
631 }
632 
hasShader(QGLShader::ShaderType type) const633 bool QGLShaderProgramPrivate::hasShader(QGLShader::ShaderType type) const
634 {
635     for (QGLShader *shader : shaders) {
636         if (shader->shaderType() == type)
637             return true;
638     }
639     return false;
640 }
641 
642 #define ctx QGLContext::currentContext()
643 
644 /*!
645     Constructs a new shader program and attaches it to \a parent.
646     The program will be invalid until addShader() is called.
647 
648     The shader program will be associated with the current QGLContext.
649 
650     \sa addShader()
651 */
QGLShaderProgram(QObject * parent)652 QGLShaderProgram::QGLShaderProgram(QObject *parent)
653     : QObject(*new QGLShaderProgramPrivate(QGLContext::currentContext()), parent)
654 {
655 }
656 
657 /*!
658     Constructs a new shader program and attaches it to \a parent.
659     The program will be invalid until addShader() is called.
660 
661     The shader program will be associated with \a context.
662 
663     \sa addShader()
664 */
QGLShaderProgram(const QGLContext * context,QObject * parent)665 QGLShaderProgram::QGLShaderProgram(const QGLContext *context, QObject *parent)
666     : QObject(*new QGLShaderProgramPrivate(context), parent)
667 {
668 }
669 
670 /*!
671     Deletes this shader program.
672 */
~QGLShaderProgram()673 QGLShaderProgram::~QGLShaderProgram()
674 {
675 }
676 
init()677 bool QGLShaderProgram::init()
678 {
679     Q_D(QGLShaderProgram);
680     if ((d->programGuard && d->programGuard->id()) || d->inited)
681         return true;
682     d->inited = true;
683     QGLContext *context = const_cast<QGLContext *>(QGLContext::currentContext());
684     if (!context)
685         return false;
686     d->glfuncs->initializeOpenGLFunctions();
687     d->glfuncs->initializeGeometryShaderFunctions();
688     if (d->glfuncs->hasOpenGLFeature(QOpenGLFunctions::Shaders)) {
689         GLuint program = d->glfuncs->glCreateProgram();
690         if (!program) {
691             qWarning("QGLShaderProgram: could not create shader program");
692             return false;
693         }
694         if (d->programGuard)
695             delete d->programGuard;
696         d->programGuard = createSharedResourceGuard(context, program, freeProgramFunc);
697         return true;
698     } else {
699         qWarning("QGLShaderProgram: shader programs are not supported");
700         return false;
701     }
702 }
703 
704 /*!
705     Adds a compiled \a shader to this shader program.  Returns \c true
706     if the shader could be added, or false otherwise.
707 
708     Ownership of the \a shader object remains with the caller.
709     It will not be deleted when this QGLShaderProgram instance
710     is deleted.  This allows the caller to add the same shader
711     to multiple shader programs.
712 
713     \sa addShaderFromSourceCode(), addShaderFromSourceFile()
714     \sa removeShader(), link(), removeAllShaders()
715 */
addShader(QGLShader * shader)716 bool QGLShaderProgram::addShader(QGLShader *shader)
717 {
718     Q_D(QGLShaderProgram);
719     if (!init())
720         return false;
721     if (d->shaders.contains(shader))
722         return true;    // Already added to this shader program.
723     if (d->programGuard && d->programGuard->id() && shader) {
724         if (!shader->d_func()->shaderGuard || !shader->d_func()->shaderGuard->id())
725             return false;
726         if (d->programGuard->group() != shader->d_func()->shaderGuard->group()) {
727             qWarning("QGLShaderProgram::addShader: Program and shader are not associated with same context.");
728             return false;
729         }
730         d->glfuncs->glAttachShader(d->programGuard->id(), shader->d_func()->shaderGuard->id());
731         d->linked = false;  // Program needs to be relinked.
732         d->shaders.append(shader);
733         connect(shader, SIGNAL(destroyed()), this, SLOT(shaderDestroyed()));
734         return true;
735     } else {
736         return false;
737     }
738 }
739 
740 /*!
741     Compiles \a source as a shader of the specified \a type and
742     adds it to this shader program.  Returns \c true if compilation
743     was successful, false otherwise.  The compilation errors
744     and warnings will be made available via log().
745 
746     This function is intended to be a short-cut for quickly
747     adding vertex and fragment shaders to a shader program without
748     creating an instance of QGLShader first.
749 
750     \sa addShader(), addShaderFromSourceFile()
751     \sa removeShader(), link(), log(), removeAllShaders()
752 */
addShaderFromSourceCode(QGLShader::ShaderType type,const char * source)753 bool QGLShaderProgram::addShaderFromSourceCode(QGLShader::ShaderType type, const char *source)
754 {
755     Q_D(QGLShaderProgram);
756     if (!init())
757         return false;
758     QGLShader *shader = new QGLShader(type, this);
759     if (!shader->compileSourceCode(source)) {
760         d->log = shader->log();
761         delete shader;
762         return false;
763     }
764     d->anonShaders.append(shader);
765     return addShader(shader);
766 }
767 
768 /*!
769     \overload
770 
771     Compiles \a source as a shader of the specified \a type and
772     adds it to this shader program.  Returns \c true if compilation
773     was successful, false otherwise.  The compilation errors
774     and warnings will be made available via log().
775 
776     This function is intended to be a short-cut for quickly
777     adding vertex and fragment shaders to a shader program without
778     creating an instance of QGLShader first.
779 
780     \sa addShader(), addShaderFromSourceFile()
781     \sa removeShader(), link(), log(), removeAllShaders()
782 */
addShaderFromSourceCode(QGLShader::ShaderType type,const QByteArray & source)783 bool QGLShaderProgram::addShaderFromSourceCode(QGLShader::ShaderType type, const QByteArray& source)
784 {
785     return addShaderFromSourceCode(type, source.constData());
786 }
787 
788 /*!
789     \overload
790 
791     Compiles \a source as a shader of the specified \a type and
792     adds it to this shader program.  Returns \c true if compilation
793     was successful, false otherwise.  The compilation errors
794     and warnings will be made available via log().
795 
796     This function is intended to be a short-cut for quickly
797     adding vertex and fragment shaders to a shader program without
798     creating an instance of QGLShader first.
799 
800     \sa addShader(), addShaderFromSourceFile()
801     \sa removeShader(), link(), log(), removeAllShaders()
802 */
addShaderFromSourceCode(QGLShader::ShaderType type,const QString & source)803 bool QGLShaderProgram::addShaderFromSourceCode(QGLShader::ShaderType type, const QString& source)
804 {
805     return addShaderFromSourceCode(type, source.toLatin1().constData());
806 }
807 
808 /*!
809     Compiles the contents of \a fileName as a shader of the specified
810     \a type and adds it to this shader program.  Returns \c true if
811     compilation was successful, false otherwise.  The compilation errors
812     and warnings will be made available via log().
813 
814     This function is intended to be a short-cut for quickly
815     adding vertex and fragment shaders to a shader program without
816     creating an instance of QGLShader first.
817 
818     \sa addShader(), addShaderFromSourceCode()
819 */
addShaderFromSourceFile(QGLShader::ShaderType type,const QString & fileName)820 bool QGLShaderProgram::addShaderFromSourceFile
821     (QGLShader::ShaderType type, const QString& fileName)
822 {
823     Q_D(QGLShaderProgram);
824     if (!init())
825         return false;
826     QGLShader *shader = new QGLShader(type, this);
827     if (!shader->compileSourceFile(fileName)) {
828         d->log = shader->log();
829         delete shader;
830         return false;
831     }
832     d->anonShaders.append(shader);
833     return addShader(shader);
834 }
835 
836 /*!
837     Removes \a shader from this shader program.  The object is not deleted.
838 
839     The shader program must be valid in the current QGLContext.
840 
841     \sa addShader(), link(), removeAllShaders()
842 */
removeShader(QGLShader * shader)843 void QGLShaderProgram::removeShader(QGLShader *shader)
844 {
845     Q_D(QGLShaderProgram);
846     if (d->programGuard && d->programGuard->id()
847         && shader && shader->d_func()->shaderGuard)
848     {
849         d->glfuncs->glDetachShader(d->programGuard->id(), shader->d_func()->shaderGuard->id());
850     }
851     d->linked = false;  // Program needs to be relinked.
852     if (shader) {
853         d->shaders.removeAll(shader);
854         d->anonShaders.removeAll(shader);
855         disconnect(shader, SIGNAL(destroyed()), this, SLOT(shaderDestroyed()));
856     }
857 }
858 
859 /*!
860     Returns a list of all shaders that have been added to this shader
861     program using addShader().
862 
863     \sa addShader(), removeShader()
864 */
shaders() const865 QList<QGLShader *> QGLShaderProgram::shaders() const
866 {
867     Q_D(const QGLShaderProgram);
868     return d->shaders;
869 }
870 
871 /*!
872     Removes all of the shaders that were added to this program previously.
873     The QGLShader objects for the shaders will not be deleted if they
874     were constructed externally.  QGLShader objects that are constructed
875     internally by QGLShaderProgram will be deleted.
876 
877     \sa addShader(), removeShader()
878 */
removeAllShaders()879 void QGLShaderProgram::removeAllShaders()
880 {
881     Q_D(QGLShaderProgram);
882     d->removingShaders = true;
883     if (d->programGuard) {
884         if (const auto programGuardId = d->programGuard->id()) {
885             for (QGLShader *shader : qAsConst(d->shaders)) {
886                 if (shader && shader->d_func()->shaderGuard)
887                     d->glfuncs->glDetachShader(programGuardId, shader->d_func()->shaderGuard->id());
888             }
889         }
890     }
891     // Delete shader objects that were created anonymously.
892     qDeleteAll(d->anonShaders);
893     d->shaders.clear();
894     d->anonShaders.clear();
895     d->linked = false;  // Program needs to be relinked.
896     d->removingShaders = false;
897 }
898 
899 /*!
900     Links together the shaders that were added to this program with
901     addShader().  Returns \c true if the link was successful or
902     false otherwise.  If the link failed, the error messages can
903     be retrieved with log().
904 
905     Subclasses can override this function to initialize attributes
906     and uniform variables for use in specific shader programs.
907 
908     If the shader program was already linked, calling this
909     function again will force it to be re-linked.
910 
911     \sa addShader(), log()
912 */
link()913 bool QGLShaderProgram::link()
914 {
915     Q_D(QGLShaderProgram);
916     GLuint program = d->programGuard ? d->programGuard->id() : 0;
917     if (!program)
918         return false;
919 
920     GLint value;
921     if (d->shaders.isEmpty()) {
922         // If there are no explicit shaders, then it is possible that the
923         // application added a program binary with glProgramBinaryOES(),
924         // or otherwise populated the shaders itself.  Check to see if the
925         // program is already linked and bail out if so.
926         value = 0;
927         d->glfuncs->glGetProgramiv(program, GL_LINK_STATUS, &value);
928         d->linked = (value != 0);
929         if (d->linked)
930             return true;
931     }
932 
933 #if !defined(QT_OPENGL_ES_2)
934     // Set up the geometry shader parameters
935     if (!QOpenGLContext::currentContext()->isOpenGLES()
936         && d->glfuncs->glProgramParameteri) {
937         for (QGLShader *shader : qAsConst(d->shaders)) {
938             if (shader->shaderType() & QGLShader::Geometry) {
939                 d->glfuncs->glProgramParameteri(program, GL_GEOMETRY_INPUT_TYPE_EXT,
940                                        d->geometryInputType);
941                 d->glfuncs->glProgramParameteri(program, GL_GEOMETRY_OUTPUT_TYPE_EXT,
942                                        d->geometryOutputType);
943                 d->glfuncs->glProgramParameteri(program, GL_GEOMETRY_VERTICES_OUT_EXT,
944                                        d->geometryVertexCount);
945                 break;
946             }
947         }
948     }
949 #endif
950 
951     d->glfuncs->glLinkProgram(program);
952     value = 0;
953     d->glfuncs->glGetProgramiv(program, GL_LINK_STATUS, &value);
954     d->linked = (value != 0);
955     value = 0;
956     d->glfuncs->glGetProgramiv(program, GL_INFO_LOG_LENGTH, &value);
957     d->log = QString();
958     if (value > 1) {
959         char *logbuf = new char [value];
960         GLint len;
961         d->glfuncs->glGetProgramInfoLog(program, value, &len, logbuf);
962         d->log = QString::fromLatin1(logbuf);
963         QString name = objectName();
964         if (!d->linked) {
965             if (name.isEmpty())
966                 qWarning() << "QGLShader::link:" << d->log;
967             else
968                 qWarning() << "QGLShader::link[" << name << "]:" << d->log;
969         }
970         delete [] logbuf;
971     }
972     return d->linked;
973 }
974 
975 /*!
976     Returns \c true if this shader program has been linked; false otherwise.
977 
978     \sa link()
979 */
isLinked() const980 bool QGLShaderProgram::isLinked() const
981 {
982     Q_D(const QGLShaderProgram);
983     return d->linked;
984 }
985 
986 /*!
987     Returns the errors and warnings that occurred during the last link()
988     or addShader() with explicitly specified source code.
989 
990     \sa link()
991 */
log() const992 QString QGLShaderProgram::log() const
993 {
994     Q_D(const QGLShaderProgram);
995     return d->log;
996 }
997 
998 /*!
999     Binds this shader program to the active QGLContext and makes
1000     it the current shader program.  Any previously bound shader program
1001     is released.  This is equivalent to calling \c{glUseProgram()} on
1002     programId().  Returns \c true if the program was successfully bound;
1003     false otherwise.  If the shader program has not yet been linked,
1004     or it needs to be re-linked, this function will call link().
1005 
1006     \sa link(), release()
1007 */
bind()1008 bool QGLShaderProgram::bind()
1009 {
1010     Q_D(QGLShaderProgram);
1011     GLuint program = d->programGuard ? d->programGuard->id() : 0;
1012     if (!program)
1013         return false;
1014     if (!d->linked && !link())
1015         return false;
1016 #ifndef QT_NO_DEBUG
1017     if (d->programGuard->group() != QOpenGLContextGroup::currentContextGroup()) {
1018         qWarning("QGLShaderProgram::bind: program is not valid in the current context.");
1019         return false;
1020     }
1021 #endif
1022     d->glfuncs->glUseProgram(program);
1023     return true;
1024 }
1025 
1026 #undef ctx
1027 #define ctx QGLContext::currentContext()
1028 
1029 /*!
1030     Releases the active shader program from the current QGLContext.
1031     This is equivalent to calling \c{glUseProgram(0)}.
1032 
1033     \sa bind()
1034 */
release()1035 void QGLShaderProgram::release()
1036 {
1037     Q_D(QGLShaderProgram);
1038 #ifndef QT_NO_DEBUG
1039     if (d->programGuard && d->programGuard->group() != QOpenGLContextGroup::currentContextGroup())
1040         qWarning("QGLShaderProgram::release: program is not valid in the current context.");
1041 #endif
1042     d->glfuncs->glUseProgram(0);
1043 }
1044 
1045 /*!
1046     Returns the OpenGL identifier associated with this shader program.
1047 
1048     \sa QGLShader::shaderId()
1049 */
programId() const1050 GLuint QGLShaderProgram::programId() const
1051 {
1052     Q_D(const QGLShaderProgram);
1053     GLuint id = d->programGuard ? d->programGuard->id() : 0;
1054     if (id)
1055         return id;
1056 
1057     // Create the identifier if we don't have one yet.  This is for
1058     // applications that want to create the attached shader configuration
1059     // themselves, particularly those using program binaries.
1060     if (!const_cast<QGLShaderProgram *>(this)->init())
1061         return 0;
1062     return d->programGuard ? d->programGuard->id() : 0;
1063 }
1064 
1065 /*!
1066     Binds the attribute \a name to the specified \a location.  This
1067     function can be called before or after the program has been linked.
1068     Any attributes that have not been explicitly bound when the program
1069     is linked will be assigned locations automatically.
1070 
1071     When this function is called after the program has been linked,
1072     the program will need to be relinked for the change to take effect.
1073 
1074     \sa attributeLocation()
1075 */
bindAttributeLocation(const char * name,int location)1076 void QGLShaderProgram::bindAttributeLocation(const char *name, int location)
1077 {
1078     Q_D(QGLShaderProgram);
1079     if (!init() || !d->programGuard || !d->programGuard->id())
1080         return;
1081     d->glfuncs->glBindAttribLocation(d->programGuard->id(), location, name);
1082     d->linked = false;  // Program needs to be relinked.
1083 }
1084 
1085 /*!
1086     \overload
1087 
1088     Binds the attribute \a name to the specified \a location.  This
1089     function can be called before or after the program has been linked.
1090     Any attributes that have not been explicitly bound when the program
1091     is linked will be assigned locations automatically.
1092 
1093     When this function is called after the program has been linked,
1094     the program will need to be relinked for the change to take effect.
1095 
1096     \sa attributeLocation()
1097 */
bindAttributeLocation(const QByteArray & name,int location)1098 void QGLShaderProgram::bindAttributeLocation(const QByteArray& name, int location)
1099 {
1100     bindAttributeLocation(name.constData(), location);
1101 }
1102 
1103 /*!
1104     \overload
1105 
1106     Binds the attribute \a name to the specified \a location.  This
1107     function can be called before or after the program has been linked.
1108     Any attributes that have not been explicitly bound when the program
1109     is linked will be assigned locations automatically.
1110 
1111     When this function is called after the program has been linked,
1112     the program will need to be relinked for the change to take effect.
1113 
1114     \sa attributeLocation()
1115 */
bindAttributeLocation(const QString & name,int location)1116 void QGLShaderProgram::bindAttributeLocation(const QString& name, int location)
1117 {
1118     bindAttributeLocation(name.toLatin1().constData(), location);
1119 }
1120 
1121 /*!
1122     Returns the location of the attribute \a name within this shader
1123     program's parameter list.  Returns -1 if \a name is not a valid
1124     attribute for this shader program.
1125 
1126     \sa uniformLocation(), bindAttributeLocation()
1127 */
attributeLocation(const char * name) const1128 int QGLShaderProgram::attributeLocation(const char *name) const
1129 {
1130     Q_D(const QGLShaderProgram);
1131     if (d->linked && d->programGuard && d->programGuard->id()) {
1132         return d->glfuncs->glGetAttribLocation(d->programGuard->id(), name);
1133     } else {
1134         qWarning() << "QGLShaderProgram::attributeLocation(" << name
1135                    << "): shader program is not linked";
1136         return -1;
1137     }
1138 }
1139 
1140 /*!
1141     \overload
1142 
1143     Returns the location of the attribute \a name within this shader
1144     program's parameter list.  Returns -1 if \a name is not a valid
1145     attribute for this shader program.
1146 
1147     \sa uniformLocation(), bindAttributeLocation()
1148 */
attributeLocation(const QByteArray & name) const1149 int QGLShaderProgram::attributeLocation(const QByteArray& name) const
1150 {
1151     return attributeLocation(name.constData());
1152 }
1153 
1154 /*!
1155     \overload
1156 
1157     Returns the location of the attribute \a name within this shader
1158     program's parameter list.  Returns -1 if \a name is not a valid
1159     attribute for this shader program.
1160 
1161     \sa uniformLocation(), bindAttributeLocation()
1162 */
attributeLocation(const QString & name) const1163 int QGLShaderProgram::attributeLocation(const QString& name) const
1164 {
1165     return attributeLocation(name.toLatin1().constData());
1166 }
1167 
1168 /*!
1169     Sets the attribute at \a location in the current context to \a value.
1170 
1171     \sa setUniformValue()
1172 */
setAttributeValue(int location,GLfloat value)1173 void QGLShaderProgram::setAttributeValue(int location, GLfloat value)
1174 {
1175     Q_D(QGLShaderProgram);
1176     Q_UNUSED(d);
1177     if (location != -1)
1178         d->glfuncs->glVertexAttrib1fv(location, &value);
1179 }
1180 
1181 /*!
1182     \overload
1183 
1184     Sets the attribute called \a name in the current context to \a value.
1185 
1186     \sa setUniformValue()
1187 */
setAttributeValue(const char * name,GLfloat value)1188 void QGLShaderProgram::setAttributeValue(const char *name, GLfloat value)
1189 {
1190     setAttributeValue(attributeLocation(name), value);
1191 }
1192 
1193 /*!
1194     Sets the attribute at \a location in the current context to
1195     the 2D vector (\a x, \a y).
1196 
1197     \sa setUniformValue()
1198 */
setAttributeValue(int location,GLfloat x,GLfloat y)1199 void QGLShaderProgram::setAttributeValue(int location, GLfloat x, GLfloat y)
1200 {
1201     Q_D(QGLShaderProgram);
1202     Q_UNUSED(d);
1203     if (location != -1) {
1204         GLfloat values[2] = {x, y};
1205         d->glfuncs->glVertexAttrib2fv(location, values);
1206     }
1207 }
1208 
1209 /*!
1210     \overload
1211 
1212     Sets the attribute called \a name in the current context to
1213     the 2D vector (\a x, \a y).
1214 
1215     \sa setUniformValue()
1216 */
setAttributeValue(const char * name,GLfloat x,GLfloat y)1217 void QGLShaderProgram::setAttributeValue(const char *name, GLfloat x, GLfloat y)
1218 {
1219     setAttributeValue(attributeLocation(name), x, y);
1220 }
1221 
1222 /*!
1223     Sets the attribute at \a location in the current context to
1224     the 3D vector (\a x, \a y, \a z).
1225 
1226     \sa setUniformValue()
1227 */
setAttributeValue(int location,GLfloat x,GLfloat y,GLfloat z)1228 void QGLShaderProgram::setAttributeValue
1229         (int location, GLfloat x, GLfloat y, GLfloat z)
1230 {
1231     Q_D(QGLShaderProgram);
1232     Q_UNUSED(d);
1233     if (location != -1) {
1234         GLfloat values[3] = {x, y, z};
1235         d->glfuncs->glVertexAttrib3fv(location, values);
1236     }
1237 }
1238 
1239 /*!
1240     \overload
1241 
1242     Sets the attribute called \a name in the current context to
1243     the 3D vector (\a x, \a y, \a z).
1244 
1245     \sa setUniformValue()
1246 */
setAttributeValue(const char * name,GLfloat x,GLfloat y,GLfloat z)1247 void QGLShaderProgram::setAttributeValue
1248         (const char *name, GLfloat x, GLfloat y, GLfloat z)
1249 {
1250     setAttributeValue(attributeLocation(name), x, y, z);
1251 }
1252 
1253 /*!
1254     Sets the attribute at \a location in the current context to
1255     the 4D vector (\a x, \a y, \a z, \a w).
1256 
1257     \sa setUniformValue()
1258 */
setAttributeValue(int location,GLfloat x,GLfloat y,GLfloat z,GLfloat w)1259 void QGLShaderProgram::setAttributeValue
1260         (int location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
1261 {
1262     Q_D(QGLShaderProgram);
1263     Q_UNUSED(d);
1264     if (location != -1) {
1265         GLfloat values[4] = {x, y, z, w};
1266         d->glfuncs->glVertexAttrib4fv(location, values);
1267     }
1268 }
1269 
1270 /*!
1271     \overload
1272 
1273     Sets the attribute called \a name in the current context to
1274     the 4D vector (\a x, \a y, \a z, \a w).
1275 
1276     \sa setUniformValue()
1277 */
setAttributeValue(const char * name,GLfloat x,GLfloat y,GLfloat z,GLfloat w)1278 void QGLShaderProgram::setAttributeValue
1279         (const char *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
1280 {
1281     setAttributeValue(attributeLocation(name), x, y, z, w);
1282 }
1283 
1284 /*!
1285     Sets the attribute at \a location in the current context to \a value.
1286 
1287     \sa setUniformValue()
1288 */
setAttributeValue(int location,const QVector2D & value)1289 void QGLShaderProgram::setAttributeValue(int location, const QVector2D& value)
1290 {
1291     Q_D(QGLShaderProgram);
1292     Q_UNUSED(d);
1293     if (location != -1)
1294         d->glfuncs->glVertexAttrib2fv(location, reinterpret_cast<const GLfloat *>(&value));
1295 }
1296 
1297 /*!
1298     \overload
1299 
1300     Sets the attribute called \a name in the current context to \a value.
1301 
1302     \sa setUniformValue()
1303 */
setAttributeValue(const char * name,const QVector2D & value)1304 void QGLShaderProgram::setAttributeValue(const char *name, const QVector2D& value)
1305 {
1306     setAttributeValue(attributeLocation(name), value);
1307 }
1308 
1309 /*!
1310     Sets the attribute at \a location in the current context to \a value.
1311 
1312     \sa setUniformValue()
1313 */
setAttributeValue(int location,const QVector3D & value)1314 void QGLShaderProgram::setAttributeValue(int location, const QVector3D& value)
1315 {
1316     Q_D(QGLShaderProgram);
1317     Q_UNUSED(d);
1318     if (location != -1)
1319         d->glfuncs->glVertexAttrib3fv(location, reinterpret_cast<const GLfloat *>(&value));
1320 }
1321 
1322 /*!
1323     \overload
1324 
1325     Sets the attribute called \a name in the current context to \a value.
1326 
1327     \sa setUniformValue()
1328 */
setAttributeValue(const char * name,const QVector3D & value)1329 void QGLShaderProgram::setAttributeValue(const char *name, const QVector3D& value)
1330 {
1331     setAttributeValue(attributeLocation(name), value);
1332 }
1333 
1334 /*!
1335     Sets the attribute at \a location in the current context to \a value.
1336 
1337     \sa setUniformValue()
1338 */
setAttributeValue(int location,const QVector4D & value)1339 void QGLShaderProgram::setAttributeValue(int location, const QVector4D& value)
1340 {
1341     Q_D(QGLShaderProgram);
1342     Q_UNUSED(d);
1343     if (location != -1)
1344         d->glfuncs->glVertexAttrib4fv(location, reinterpret_cast<const GLfloat *>(&value));
1345 }
1346 
1347 /*!
1348     \overload
1349 
1350     Sets the attribute called \a name in the current context to \a value.
1351 
1352     \sa setUniformValue()
1353 */
setAttributeValue(const char * name,const QVector4D & value)1354 void QGLShaderProgram::setAttributeValue(const char *name, const QVector4D& value)
1355 {
1356     setAttributeValue(attributeLocation(name), value);
1357 }
1358 
1359 /*!
1360     Sets the attribute at \a location in the current context to \a value.
1361 
1362     \sa setUniformValue()
1363 */
setAttributeValue(int location,const QColor & value)1364 void QGLShaderProgram::setAttributeValue(int location, const QColor& value)
1365 {
1366     Q_D(QGLShaderProgram);
1367     Q_UNUSED(d);
1368     if (location != -1) {
1369         GLfloat values[4] = {GLfloat(value.redF()), GLfloat(value.greenF()),
1370                              GLfloat(value.blueF()), GLfloat(value.alphaF())};
1371         d->glfuncs->glVertexAttrib4fv(location, values);
1372     }
1373 }
1374 
1375 /*!
1376     \overload
1377 
1378     Sets the attribute called \a name in the current context to \a value.
1379 
1380     \sa setUniformValue()
1381 */
setAttributeValue(const char * name,const QColor & value)1382 void QGLShaderProgram::setAttributeValue(const char *name, const QColor& value)
1383 {
1384     setAttributeValue(attributeLocation(name), value);
1385 }
1386 
1387 /*!
1388     Sets the attribute at \a location in the current context to the
1389     contents of \a values, which contains \a columns elements, each
1390     consisting of \a rows elements.  The \a rows value should be
1391     1, 2, 3, or 4.  This function is typically used to set matrix
1392     values and column vectors.
1393 
1394     \sa setUniformValue()
1395 */
setAttributeValue(int location,const GLfloat * values,int columns,int rows)1396 void QGLShaderProgram::setAttributeValue
1397     (int location, const GLfloat *values, int columns, int rows)
1398 {
1399     Q_D(QGLShaderProgram);
1400     Q_UNUSED(d);
1401     if (rows < 1 || rows > 4) {
1402         qWarning() << "QGLShaderProgram::setAttributeValue: rows" << rows << "not supported";
1403         return;
1404     }
1405     if (location != -1) {
1406         while (columns-- > 0) {
1407             if (rows == 1)
1408                 d->glfuncs->glVertexAttrib1fv(location, values);
1409             else if (rows == 2)
1410                 d->glfuncs->glVertexAttrib2fv(location, values);
1411             else if (rows == 3)
1412                 d->glfuncs->glVertexAttrib3fv(location, values);
1413             else
1414                 d->glfuncs->glVertexAttrib4fv(location, values);
1415             values += rows;
1416             ++location;
1417         }
1418     }
1419 }
1420 
1421 /*!
1422     \overload
1423 
1424     Sets the attribute called \a name in the current context to the
1425     contents of \a values, which contains \a columns elements, each
1426     consisting of \a rows elements.  The \a rows value should be
1427     1, 2, 3, or 4.  This function is typically used to set matrix
1428     values and column vectors.
1429 
1430     \sa setUniformValue()
1431 */
setAttributeValue(const char * name,const GLfloat * values,int columns,int rows)1432 void QGLShaderProgram::setAttributeValue
1433     (const char *name, const GLfloat *values, int columns, int rows)
1434 {
1435     setAttributeValue(attributeLocation(name), values, columns, rows);
1436 }
1437 
1438 /*!
1439     Sets an array of vertex \a values on the attribute at \a location
1440     in this shader program.  The \a tupleSize indicates the number of
1441     components per vertex (1, 2, 3, or 4), and the \a stride indicates
1442     the number of bytes between vertices.  A default \a stride value
1443     of zero indicates that the vertices are densely packed in \a values.
1444 
1445     The array will become active when enableAttributeArray() is called
1446     on the \a location.  Otherwise the value specified with
1447     setAttributeValue() for \a location will be used.
1448 
1449     \sa setAttributeValue(), setUniformValue(), enableAttributeArray()
1450     \sa disableAttributeArray()
1451 */
setAttributeArray(int location,const GLfloat * values,int tupleSize,int stride)1452 void QGLShaderProgram::setAttributeArray
1453     (int location, const GLfloat *values, int tupleSize, int stride)
1454 {
1455     Q_D(QGLShaderProgram);
1456     Q_UNUSED(d);
1457     if (location != -1) {
1458         d->glfuncs->glVertexAttribPointer(location, tupleSize, GL_FLOAT, GL_FALSE,
1459                               stride, values);
1460     }
1461 }
1462 
1463 /*!
1464     Sets an array of 2D vertex \a values on the attribute at \a location
1465     in this shader program.  The \a stride indicates the number of bytes
1466     between vertices.  A default \a stride value of zero indicates that
1467     the vertices are densely packed in \a values.
1468 
1469     The array will become active when enableAttributeArray() is called
1470     on the \a location.  Otherwise the value specified with
1471     setAttributeValue() for \a location will be used.
1472 
1473     \sa setAttributeValue(), setUniformValue(), enableAttributeArray()
1474     \sa disableAttributeArray()
1475 */
setAttributeArray(int location,const QVector2D * values,int stride)1476 void QGLShaderProgram::setAttributeArray
1477         (int location, const QVector2D *values, int stride)
1478 {
1479     Q_D(QGLShaderProgram);
1480     Q_UNUSED(d);
1481     if (location != -1) {
1482         d->glfuncs->glVertexAttribPointer(location, 2, GL_FLOAT, GL_FALSE,
1483                               stride, values);
1484     }
1485 }
1486 
1487 /*!
1488     Sets an array of 3D vertex \a values on the attribute at \a location
1489     in this shader program.  The \a stride indicates the number of bytes
1490     between vertices.  A default \a stride value of zero indicates that
1491     the vertices are densely packed in \a values.
1492 
1493     The array will become active when enableAttributeArray() is called
1494     on the \a location.  Otherwise the value specified with
1495     setAttributeValue() for \a location will be used.
1496 
1497     \sa setAttributeValue(), setUniformValue(), enableAttributeArray()
1498     \sa disableAttributeArray()
1499 */
setAttributeArray(int location,const QVector3D * values,int stride)1500 void QGLShaderProgram::setAttributeArray
1501         (int location, const QVector3D *values, int stride)
1502 {
1503     Q_D(QGLShaderProgram);
1504     Q_UNUSED(d);
1505     if (location != -1) {
1506         d->glfuncs->glVertexAttribPointer(location, 3, GL_FLOAT, GL_FALSE,
1507                               stride, values);
1508     }
1509 }
1510 
1511 /*!
1512     Sets an array of 4D vertex \a values on the attribute at \a location
1513     in this shader program.  The \a stride indicates the number of bytes
1514     between vertices.  A default \a stride value of zero indicates that
1515     the vertices are densely packed in \a values.
1516 
1517     The array will become active when enableAttributeArray() is called
1518     on the \a location.  Otherwise the value specified with
1519     setAttributeValue() for \a location will be used.
1520 
1521     \sa setAttributeValue(), setUniformValue(), enableAttributeArray()
1522     \sa disableAttributeArray()
1523 */
setAttributeArray(int location,const QVector4D * values,int stride)1524 void QGLShaderProgram::setAttributeArray
1525         (int location, const QVector4D *values, int stride)
1526 {
1527     Q_D(QGLShaderProgram);
1528     Q_UNUSED(d);
1529     if (location != -1) {
1530         d->glfuncs->glVertexAttribPointer(location, 4, GL_FLOAT, GL_FALSE,
1531                               stride, values);
1532     }
1533 }
1534 
1535 /*!
1536     Sets an array of vertex \a values on the attribute at \a location
1537     in this shader program.  The \a stride indicates the number of bytes
1538     between vertices.  A default \a stride value of zero indicates that
1539     the vertices are densely packed in \a values.
1540 
1541     The \a type indicates the type of elements in the \a values array,
1542     usually \c{GL_FLOAT}, \c{GL_UNSIGNED_BYTE}, etc.  The \a tupleSize
1543     indicates the number of components per vertex: 1, 2, 3, or 4.
1544 
1545     The array will become active when enableAttributeArray() is called
1546     on the \a location.  Otherwise the value specified with
1547     setAttributeValue() for \a location will be used.
1548 
1549     The setAttributeBuffer() function can be used to set the attribute
1550     array to an offset within a vertex buffer.
1551 
1552     \note Normalization will be enabled. If this is not desired, call
1553     glVertexAttribPointer directly through QGLFunctions.
1554 
1555     \sa setAttributeValue(), setUniformValue(), enableAttributeArray()
1556     \sa disableAttributeArray(), setAttributeBuffer()
1557     \since 4.7
1558 */
setAttributeArray(int location,GLenum type,const void * values,int tupleSize,int stride)1559 void QGLShaderProgram::setAttributeArray
1560     (int location, GLenum type, const void *values, int tupleSize, int stride)
1561 {
1562     Q_D(QGLShaderProgram);
1563     Q_UNUSED(d);
1564     if (location != -1) {
1565         d->glfuncs->glVertexAttribPointer(location, tupleSize, type, GL_TRUE,
1566                               stride, values);
1567     }
1568 }
1569 
1570 /*!
1571     \overload
1572 
1573     Sets an array of vertex \a values on the attribute called \a name
1574     in this shader program.  The \a tupleSize indicates the number of
1575     components per vertex (1, 2, 3, or 4), and the \a stride indicates
1576     the number of bytes between vertices.  A default \a stride value
1577     of zero indicates that the vertices are densely packed in \a values.
1578 
1579     The array will become active when enableAttributeArray() is called
1580     on \a name.  Otherwise the value specified with setAttributeValue()
1581     for \a name will be used.
1582 
1583     \sa setAttributeValue(), setUniformValue(), enableAttributeArray()
1584     \sa disableAttributeArray()
1585 */
setAttributeArray(const char * name,const GLfloat * values,int tupleSize,int stride)1586 void QGLShaderProgram::setAttributeArray
1587     (const char *name, const GLfloat *values, int tupleSize, int stride)
1588 {
1589     setAttributeArray(attributeLocation(name), values, tupleSize, stride);
1590 }
1591 
1592 /*!
1593     \overload
1594 
1595     Sets an array of 2D vertex \a values on the attribute called \a name
1596     in this shader program.  The \a stride indicates the number of bytes
1597     between vertices.  A default \a stride value of zero indicates that
1598     the vertices are densely packed in \a values.
1599 
1600     The array will become active when enableAttributeArray() is called
1601     on \a name.  Otherwise the value specified with setAttributeValue()
1602     for \a name will be used.
1603 
1604     \sa setAttributeValue(), setUniformValue(), enableAttributeArray()
1605     \sa disableAttributeArray()
1606 */
setAttributeArray(const char * name,const QVector2D * values,int stride)1607 void QGLShaderProgram::setAttributeArray
1608         (const char *name, const QVector2D *values, int stride)
1609 {
1610     setAttributeArray(attributeLocation(name), values, stride);
1611 }
1612 
1613 /*!
1614     \overload
1615 
1616     Sets an array of 3D vertex \a values on the attribute called \a name
1617     in this shader program.  The \a stride indicates the number of bytes
1618     between vertices.  A default \a stride value of zero indicates that
1619     the vertices are densely packed in \a values.
1620 
1621     The array will become active when enableAttributeArray() is called
1622     on \a name.  Otherwise the value specified with setAttributeValue()
1623     for \a name will be used.
1624 
1625     \sa setAttributeValue(), setUniformValue(), enableAttributeArray()
1626     \sa disableAttributeArray()
1627 */
setAttributeArray(const char * name,const QVector3D * values,int stride)1628 void QGLShaderProgram::setAttributeArray
1629         (const char *name, const QVector3D *values, int stride)
1630 {
1631     setAttributeArray(attributeLocation(name), values, stride);
1632 }
1633 
1634 /*!
1635     \overload
1636 
1637     Sets an array of 4D vertex \a values on the attribute called \a name
1638     in this shader program.  The \a stride indicates the number of bytes
1639     between vertices.  A default \a stride value of zero indicates that
1640     the vertices are densely packed in \a values.
1641 
1642     The array will become active when enableAttributeArray() is called
1643     on \a name.  Otherwise the value specified with setAttributeValue()
1644     for \a name will be used.
1645 
1646     \sa setAttributeValue(), setUniformValue(), enableAttributeArray()
1647     \sa disableAttributeArray()
1648 */
setAttributeArray(const char * name,const QVector4D * values,int stride)1649 void QGLShaderProgram::setAttributeArray
1650         (const char *name, const QVector4D *values, int stride)
1651 {
1652     setAttributeArray(attributeLocation(name), values, stride);
1653 }
1654 
1655 /*!
1656     \overload
1657 
1658     Sets an array of vertex \a values on the attribute called \a name
1659     in this shader program.  The \a stride indicates the number of bytes
1660     between vertices.  A default \a stride value of zero indicates that
1661     the vertices are densely packed in \a values.
1662 
1663     The \a type indicates the type of elements in the \a values array,
1664     usually \c{GL_FLOAT}, \c{GL_UNSIGNED_BYTE}, etc.  The \a tupleSize
1665     indicates the number of components per vertex: 1, 2, 3, or 4.
1666 
1667     The array will become active when enableAttributeArray() is called
1668     on the \a name.  Otherwise the value specified with
1669     setAttributeValue() for \a name will be used.
1670 
1671     The setAttributeBuffer() function can be used to set the attribute
1672     array to an offset within a vertex buffer.
1673 
1674     \sa setAttributeValue(), setUniformValue(), enableAttributeArray()
1675     \sa disableAttributeArray(), setAttributeBuffer()
1676     \since 4.7
1677 */
setAttributeArray(const char * name,GLenum type,const void * values,int tupleSize,int stride)1678 void QGLShaderProgram::setAttributeArray
1679     (const char *name, GLenum type, const void *values, int tupleSize, int stride)
1680 {
1681     setAttributeArray(attributeLocation(name), type, values, tupleSize, stride);
1682 }
1683 
1684 /*!
1685     Sets an array of vertex values on the attribute at \a location in
1686     this shader program, starting at a specific \a offset in the
1687     currently bound vertex buffer.  The \a stride indicates the number
1688     of bytes between vertices.  A default \a stride value of zero
1689     indicates that the vertices are densely packed in the value array.
1690 
1691     The \a type indicates the type of elements in the vertex value
1692     array, usually \c{GL_FLOAT}, \c{GL_UNSIGNED_BYTE}, etc.  The \a
1693     tupleSize indicates the number of components per vertex: 1, 2, 3,
1694     or 4.
1695 
1696     The array will become active when enableAttributeArray() is called
1697     on the \a location.  Otherwise the value specified with
1698     setAttributeValue() for \a location will be used.
1699 
1700     \note Normalization will be enabled. If this is not desired, call
1701     glVertexAttribPointer directly though QGLFunctions.
1702 
1703     \sa setAttributeArray()
1704     \since 4.7
1705 */
setAttributeBuffer(int location,GLenum type,int offset,int tupleSize,int stride)1706 void QGLShaderProgram::setAttributeBuffer
1707     (int location, GLenum type, int offset, int tupleSize, int stride)
1708 {
1709     Q_D(QGLShaderProgram);
1710     Q_UNUSED(d);
1711     if (location != -1) {
1712         d->glfuncs->glVertexAttribPointer(location, tupleSize, type, GL_TRUE, stride,
1713                               reinterpret_cast<const void *>(qintptr(offset)));
1714     }
1715 }
1716 
1717 /*!
1718     \overload
1719 
1720     Sets an array of vertex values on the attribute called \a name
1721     in this shader program, starting at a specific \a offset in the
1722     currently bound vertex buffer.  The \a stride indicates the number
1723     of bytes between vertices.  A default \a stride value of zero
1724     indicates that the vertices are densely packed in the value array.
1725 
1726     The \a type indicates the type of elements in the vertex value
1727     array, usually \c{GL_FLOAT}, \c{GL_UNSIGNED_BYTE}, etc.  The \a
1728     tupleSize indicates the number of components per vertex: 1, 2, 3,
1729     or 4.
1730 
1731     The array will become active when enableAttributeArray() is called
1732     on the \a name.  Otherwise the value specified with
1733     setAttributeValue() for \a name will be used.
1734 
1735     \sa setAttributeArray()
1736     \since 4.7
1737 */
setAttributeBuffer(const char * name,GLenum type,int offset,int tupleSize,int stride)1738 void QGLShaderProgram::setAttributeBuffer
1739     (const char *name, GLenum type, int offset, int tupleSize, int stride)
1740 {
1741     setAttributeBuffer(attributeLocation(name), type, offset, tupleSize, stride);
1742 }
1743 
1744 /*!
1745     Enables the vertex array at \a location in this shader program
1746     so that the value set by setAttributeArray() on \a location
1747     will be used by the shader program.
1748 
1749     \sa disableAttributeArray(), setAttributeArray(), setAttributeValue()
1750     \sa setUniformValue()
1751 */
enableAttributeArray(int location)1752 void QGLShaderProgram::enableAttributeArray(int location)
1753 {
1754     Q_D(QGLShaderProgram);
1755     Q_UNUSED(d);
1756     if (location != -1)
1757         d->glfuncs->glEnableVertexAttribArray(location);
1758 }
1759 
1760 /*!
1761     \overload
1762 
1763     Enables the vertex array called \a name in this shader program
1764     so that the value set by setAttributeArray() on \a name
1765     will be used by the shader program.
1766 
1767     \sa disableAttributeArray(), setAttributeArray(), setAttributeValue()
1768     \sa setUniformValue()
1769 */
enableAttributeArray(const char * name)1770 void QGLShaderProgram::enableAttributeArray(const char *name)
1771 {
1772     enableAttributeArray(attributeLocation(name));
1773 }
1774 
1775 /*!
1776     Disables the vertex array at \a location in this shader program
1777     that was enabled by a previous call to enableAttributeArray().
1778 
1779     \sa enableAttributeArray(), setAttributeArray(), setAttributeValue()
1780     \sa setUniformValue()
1781 */
disableAttributeArray(int location)1782 void QGLShaderProgram::disableAttributeArray(int location)
1783 {
1784     Q_D(QGLShaderProgram);
1785     Q_UNUSED(d);
1786     if (location != -1)
1787         d->glfuncs->glDisableVertexAttribArray(location);
1788 }
1789 
1790 /*!
1791     \overload
1792 
1793     Disables the vertex array called \a name in this shader program
1794     that was enabled by a previous call to enableAttributeArray().
1795 
1796     \sa enableAttributeArray(), setAttributeArray(), setAttributeValue()
1797     \sa setUniformValue()
1798 */
disableAttributeArray(const char * name)1799 void QGLShaderProgram::disableAttributeArray(const char *name)
1800 {
1801     disableAttributeArray(attributeLocation(name));
1802 }
1803 
1804 /*!
1805     Returns the location of the uniform variable \a name within this shader
1806     program's parameter list.  Returns -1 if \a name is not a valid
1807     uniform variable for this shader program.
1808 
1809     \sa attributeLocation()
1810 */
uniformLocation(const char * name) const1811 int QGLShaderProgram::uniformLocation(const char *name) const
1812 {
1813     Q_D(const QGLShaderProgram);
1814     Q_UNUSED(d);
1815     if (d->linked && d->programGuard && d->programGuard->id()) {
1816         return d->glfuncs->glGetUniformLocation(d->programGuard->id(), name);
1817     } else {
1818         qWarning() << "QGLShaderProgram::uniformLocation(" << name
1819                    << "): shader program is not linked";
1820         return -1;
1821     }
1822 }
1823 
1824 /*!
1825     \overload
1826 
1827     Returns the location of the uniform variable \a name within this shader
1828     program's parameter list.  Returns -1 if \a name is not a valid
1829     uniform variable for this shader program.
1830 
1831     \sa attributeLocation()
1832 */
uniformLocation(const QByteArray & name) const1833 int QGLShaderProgram::uniformLocation(const QByteArray& name) const
1834 {
1835     return uniformLocation(name.constData());
1836 }
1837 
1838 /*!
1839     \overload
1840 
1841     Returns the location of the uniform variable \a name within this shader
1842     program's parameter list.  Returns -1 if \a name is not a valid
1843     uniform variable for this shader program.
1844 
1845     \sa attributeLocation()
1846 */
uniformLocation(const QString & name) const1847 int QGLShaderProgram::uniformLocation(const QString& name) const
1848 {
1849     return uniformLocation(name.toLatin1().constData());
1850 }
1851 
1852 /*!
1853     Sets the uniform variable at \a location in the current context to \a value.
1854 
1855     \sa setAttributeValue()
1856 */
setUniformValue(int location,GLfloat value)1857 void QGLShaderProgram::setUniformValue(int location, GLfloat value)
1858 {
1859     Q_D(QGLShaderProgram);
1860     Q_UNUSED(d);
1861     if (location != -1)
1862         d->glfuncs->glUniform1fv(location, 1, &value);
1863 }
1864 
1865 /*!
1866     \overload
1867 
1868     Sets the uniform variable called \a name in the current context
1869     to \a value.
1870 
1871     \sa setAttributeValue()
1872 */
setUniformValue(const char * name,GLfloat value)1873 void QGLShaderProgram::setUniformValue(const char *name, GLfloat value)
1874 {
1875     setUniformValue(uniformLocation(name), value);
1876 }
1877 
1878 /*!
1879     Sets the uniform variable at \a location in the current context to \a value.
1880 
1881     \sa setAttributeValue()
1882 */
setUniformValue(int location,GLint value)1883 void QGLShaderProgram::setUniformValue(int location, GLint value)
1884 {
1885     Q_D(QGLShaderProgram);
1886     Q_UNUSED(d);
1887     if (location != -1)
1888         d->glfuncs->glUniform1i(location, value);
1889 }
1890 
1891 /*!
1892     \overload
1893 
1894     Sets the uniform variable called \a name in the current context
1895     to \a value.
1896 
1897     \sa setAttributeValue()
1898 */
setUniformValue(const char * name,GLint value)1899 void QGLShaderProgram::setUniformValue(const char *name, GLint value)
1900 {
1901     setUniformValue(uniformLocation(name), value);
1902 }
1903 
1904 /*!
1905     Sets the uniform variable at \a location in the current context to \a value.
1906     This function should be used when setting sampler values.
1907 
1908     \sa setAttributeValue()
1909 */
setUniformValue(int location,GLuint value)1910 void QGLShaderProgram::setUniformValue(int location, GLuint value)
1911 {
1912     Q_D(QGLShaderProgram);
1913     Q_UNUSED(d);
1914     if (location != -1)
1915         d->glfuncs->glUniform1i(location, value);
1916 }
1917 
1918 /*!
1919     \overload
1920 
1921     Sets the uniform variable called \a name in the current context
1922     to \a value.  This function should be used when setting sampler values.
1923 
1924     \sa setAttributeValue()
1925 */
setUniformValue(const char * name,GLuint value)1926 void QGLShaderProgram::setUniformValue(const char *name, GLuint value)
1927 {
1928     setUniformValue(uniformLocation(name), value);
1929 }
1930 
1931 /*!
1932     Sets the uniform variable at \a location in the current context to
1933     the 2D vector (\a x, \a y).
1934 
1935     \sa setAttributeValue()
1936 */
setUniformValue(int location,GLfloat x,GLfloat y)1937 void QGLShaderProgram::setUniformValue(int location, GLfloat x, GLfloat y)
1938 {
1939     Q_D(QGLShaderProgram);
1940     Q_UNUSED(d);
1941     if (location != -1) {
1942         GLfloat values[2] = {x, y};
1943         d->glfuncs->glUniform2fv(location, 1, values);
1944     }
1945 }
1946 
1947 /*!
1948     \overload
1949 
1950     Sets the uniform variable called \a name in the current context to
1951     the 2D vector (\a x, \a y).
1952 
1953     \sa setAttributeValue()
1954 */
setUniformValue(const char * name,GLfloat x,GLfloat y)1955 void QGLShaderProgram::setUniformValue(const char *name, GLfloat x, GLfloat y)
1956 {
1957     setUniformValue(uniformLocation(name), x, y);
1958 }
1959 
1960 /*!
1961     Sets the uniform variable at \a location in the current context to
1962     the 3D vector (\a x, \a y, \a z).
1963 
1964     \sa setAttributeValue()
1965 */
setUniformValue(int location,GLfloat x,GLfloat y,GLfloat z)1966 void QGLShaderProgram::setUniformValue
1967         (int location, GLfloat x, GLfloat y, GLfloat z)
1968 {
1969     Q_D(QGLShaderProgram);
1970     Q_UNUSED(d);
1971     if (location != -1) {
1972         GLfloat values[3] = {x, y, z};
1973         d->glfuncs->glUniform3fv(location, 1, values);
1974     }
1975 }
1976 
1977 /*!
1978     \overload
1979 
1980     Sets the uniform variable called \a name in the current context to
1981     the 3D vector (\a x, \a y, \a z).
1982 
1983     \sa setAttributeValue()
1984 */
setUniformValue(const char * name,GLfloat x,GLfloat y,GLfloat z)1985 void QGLShaderProgram::setUniformValue
1986         (const char *name, GLfloat x, GLfloat y, GLfloat z)
1987 {
1988     setUniformValue(uniformLocation(name), x, y, z);
1989 }
1990 
1991 /*!
1992     Sets the uniform variable at \a location in the current context to
1993     the 4D vector (\a x, \a y, \a z, \a w).
1994 
1995     \sa setAttributeValue()
1996 */
setUniformValue(int location,GLfloat x,GLfloat y,GLfloat z,GLfloat w)1997 void QGLShaderProgram::setUniformValue
1998         (int location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
1999 {
2000     Q_D(QGLShaderProgram);
2001     Q_UNUSED(d);
2002     if (location != -1) {
2003         GLfloat values[4] = {x, y, z, w};
2004         d->glfuncs->glUniform4fv(location, 1, values);
2005     }
2006 }
2007 
2008 /*!
2009     \overload
2010 
2011     Sets the uniform variable called \a name in the current context to
2012     the 4D vector (\a x, \a y, \a z, \a w).
2013 
2014     \sa setAttributeValue()
2015 */
setUniformValue(const char * name,GLfloat x,GLfloat y,GLfloat z,GLfloat w)2016 void QGLShaderProgram::setUniformValue
2017         (const char *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
2018 {
2019     setUniformValue(uniformLocation(name), x, y, z, w);
2020 }
2021 
2022 /*!
2023     Sets the uniform variable at \a location in the current context to \a value.
2024 
2025     \sa setAttributeValue()
2026 */
setUniformValue(int location,const QVector2D & value)2027 void QGLShaderProgram::setUniformValue(int location, const QVector2D& value)
2028 {
2029     Q_D(QGLShaderProgram);
2030     Q_UNUSED(d);
2031     if (location != -1)
2032         d->glfuncs->glUniform2fv(location, 1, reinterpret_cast<const GLfloat *>(&value));
2033 }
2034 
2035 /*!
2036     \overload
2037 
2038     Sets the uniform variable called \a name in the current context
2039     to \a value.
2040 
2041     \sa setAttributeValue()
2042 */
setUniformValue(const char * name,const QVector2D & value)2043 void QGLShaderProgram::setUniformValue(const char *name, const QVector2D& value)
2044 {
2045     setUniformValue(uniformLocation(name), value);
2046 }
2047 
2048 /*!
2049     Sets the uniform variable at \a location in the current context to \a value.
2050 
2051     \sa setAttributeValue()
2052 */
setUniformValue(int location,const QVector3D & value)2053 void QGLShaderProgram::setUniformValue(int location, const QVector3D& value)
2054 {
2055     Q_D(QGLShaderProgram);
2056     Q_UNUSED(d);
2057     if (location != -1)
2058         d->glfuncs->glUniform3fv(location, 1, reinterpret_cast<const GLfloat *>(&value));
2059 }
2060 
2061 /*!
2062     \overload
2063 
2064     Sets the uniform variable called \a name in the current context
2065     to \a value.
2066 
2067     \sa setAttributeValue()
2068 */
setUniformValue(const char * name,const QVector3D & value)2069 void QGLShaderProgram::setUniformValue(const char *name, const QVector3D& value)
2070 {
2071     setUniformValue(uniformLocation(name), value);
2072 }
2073 
2074 /*!
2075     Sets the uniform variable at \a location in the current context to \a value.
2076 
2077     \sa setAttributeValue()
2078 */
setUniformValue(int location,const QVector4D & value)2079 void QGLShaderProgram::setUniformValue(int location, const QVector4D& value)
2080 {
2081     Q_D(QGLShaderProgram);
2082     Q_UNUSED(d);
2083     if (location != -1)
2084         d->glfuncs->glUniform4fv(location, 1, reinterpret_cast<const GLfloat *>(&value));
2085 }
2086 
2087 /*!
2088     \overload
2089 
2090     Sets the uniform variable called \a name in the current context
2091     to \a value.
2092 
2093     \sa setAttributeValue()
2094 */
setUniformValue(const char * name,const QVector4D & value)2095 void QGLShaderProgram::setUniformValue(const char *name, const QVector4D& value)
2096 {
2097     setUniformValue(uniformLocation(name), value);
2098 }
2099 
2100 /*!
2101     Sets the uniform variable at \a location in the current context to
2102     the red, green, blue, and alpha components of \a color.
2103 
2104     \sa setAttributeValue()
2105 */
setUniformValue(int location,const QColor & color)2106 void QGLShaderProgram::setUniformValue(int location, const QColor& color)
2107 {
2108     Q_D(QGLShaderProgram);
2109     Q_UNUSED(d);
2110     if (location != -1) {
2111         GLfloat values[4] = {GLfloat(color.redF()), GLfloat(color.greenF()),
2112                              GLfloat(color.blueF()), GLfloat(color.alphaF())};
2113         d->glfuncs->glUniform4fv(location, 1, values);
2114     }
2115 }
2116 
2117 /*!
2118     \overload
2119 
2120     Sets the uniform variable called \a name in the current context to
2121     the red, green, blue, and alpha components of \a color.
2122 
2123     \sa setAttributeValue()
2124 */
setUniformValue(const char * name,const QColor & color)2125 void QGLShaderProgram::setUniformValue(const char *name, const QColor& color)
2126 {
2127     setUniformValue(uniformLocation(name), color);
2128 }
2129 
2130 /*!
2131     Sets the uniform variable at \a location in the current context to
2132     the x and y coordinates of \a point.
2133 
2134     \sa setAttributeValue()
2135 */
setUniformValue(int location,const QPoint & point)2136 void QGLShaderProgram::setUniformValue(int location, const QPoint& point)
2137 {
2138     Q_D(QGLShaderProgram);
2139     Q_UNUSED(d);
2140     if (location != -1) {
2141         GLfloat values[4] = {GLfloat(point.x()), GLfloat(point.y())};
2142         d->glfuncs->glUniform2fv(location, 1, values);
2143     }
2144 }
2145 
2146 /*!
2147     \overload
2148 
2149     Sets the uniform variable associated with \a name in the current
2150     context to the x and y coordinates of \a point.
2151 
2152     \sa setAttributeValue()
2153 */
setUniformValue(const char * name,const QPoint & point)2154 void QGLShaderProgram::setUniformValue(const char *name, const QPoint& point)
2155 {
2156     setUniformValue(uniformLocation(name), point);
2157 }
2158 
2159 /*!
2160     Sets the uniform variable at \a location in the current context to
2161     the x and y coordinates of \a point.
2162 
2163     \sa setAttributeValue()
2164 */
setUniformValue(int location,const QPointF & point)2165 void QGLShaderProgram::setUniformValue(int location, const QPointF& point)
2166 {
2167     Q_D(QGLShaderProgram);
2168     Q_UNUSED(d);
2169     if (location != -1) {
2170         GLfloat values[4] = {GLfloat(point.x()), GLfloat(point.y())};
2171         d->glfuncs->glUniform2fv(location, 1, values);
2172     }
2173 }
2174 
2175 /*!
2176     \overload
2177 
2178     Sets the uniform variable associated with \a name in the current
2179     context to the x and y coordinates of \a point.
2180 
2181     \sa setAttributeValue()
2182 */
setUniformValue(const char * name,const QPointF & point)2183 void QGLShaderProgram::setUniformValue(const char *name, const QPointF& point)
2184 {
2185     setUniformValue(uniformLocation(name), point);
2186 }
2187 
2188 /*!
2189     Sets the uniform variable at \a location in the current context to
2190     the width and height of the given \a size.
2191 
2192     \sa setAttributeValue()
2193 */
setUniformValue(int location,const QSize & size)2194 void QGLShaderProgram::setUniformValue(int location, const QSize& size)
2195 {
2196     Q_D(QGLShaderProgram);
2197     Q_UNUSED(d);
2198     if (location != -1) {
2199         GLfloat values[4] = {GLfloat(size.width()), GLfloat(size.height())};
2200         d->glfuncs->glUniform2fv(location, 1, values);
2201     }
2202 }
2203 
2204 /*!
2205     \overload
2206 
2207     Sets the uniform variable associated with \a name in the current
2208     context to the width and height of the given \a size.
2209 
2210     \sa setAttributeValue()
2211 */
setUniformValue(const char * name,const QSize & size)2212 void QGLShaderProgram::setUniformValue(const char *name, const QSize& size)
2213 {
2214     setUniformValue(uniformLocation(name), size);
2215 }
2216 
2217 /*!
2218     Sets the uniform variable at \a location in the current context to
2219     the width and height of the given \a size.
2220 
2221     \sa setAttributeValue()
2222 */
setUniformValue(int location,const QSizeF & size)2223 void QGLShaderProgram::setUniformValue(int location, const QSizeF& size)
2224 {
2225     Q_D(QGLShaderProgram);
2226     Q_UNUSED(d);
2227     if (location != -1) {
2228         GLfloat values[4] = {GLfloat(size.width()), GLfloat(size.height())};
2229         d->glfuncs->glUniform2fv(location, 1, values);
2230     }
2231 }
2232 
2233 /*!
2234     \overload
2235 
2236     Sets the uniform variable associated with \a name in the current
2237     context to the width and height of the given \a size.
2238 
2239     \sa setAttributeValue()
2240 */
setUniformValue(const char * name,const QSizeF & size)2241 void QGLShaderProgram::setUniformValue(const char *name, const QSizeF& size)
2242 {
2243     setUniformValue(uniformLocation(name), size);
2244 }
2245 
2246 /*!
2247     Sets the uniform variable at \a location in the current context
2248     to a 2x2 matrix \a value.
2249 
2250     \sa setAttributeValue()
2251 */
setUniformValue(int location,const QMatrix2x2 & value)2252 void QGLShaderProgram::setUniformValue(int location, const QMatrix2x2& value)
2253 {
2254     Q_D(QGLShaderProgram);
2255     d->glfuncs->glUniformMatrix2fv(location, 1, GL_FALSE, value.constData());
2256 }
2257 
2258 /*!
2259     \overload
2260 
2261     Sets the uniform variable called \a name in the current context
2262     to a 2x2 matrix \a value.
2263 
2264     \sa setAttributeValue()
2265 */
setUniformValue(const char * name,const QMatrix2x2 & value)2266 void QGLShaderProgram::setUniformValue(const char *name, const QMatrix2x2& value)
2267 {
2268     setUniformValue(uniformLocation(name), value);
2269 }
2270 
2271 /*!
2272     Sets the uniform variable at \a location in the current context
2273     to a 2x3 matrix \a value.
2274 
2275     \sa setAttributeValue()
2276 */
setUniformValue(int location,const QMatrix2x3 & value)2277 void QGLShaderProgram::setUniformValue(int location, const QMatrix2x3& value)
2278 {
2279     Q_D(QGLShaderProgram);
2280     d->glfuncs->glUniform3fv(location, 2, value.constData());
2281 }
2282 
2283 /*!
2284     \overload
2285 
2286     Sets the uniform variable called \a name in the current context
2287     to a 2x3 matrix \a value.
2288 
2289     \sa setAttributeValue()
2290 */
setUniformValue(const char * name,const QMatrix2x3 & value)2291 void QGLShaderProgram::setUniformValue(const char *name, const QMatrix2x3& value)
2292 {
2293     setUniformValue(uniformLocation(name), value);
2294 }
2295 
2296 /*!
2297     Sets the uniform variable at \a location in the current context
2298     to a 2x4 matrix \a value.
2299 
2300     \sa setAttributeValue()
2301 */
setUniformValue(int location,const QMatrix2x4 & value)2302 void QGLShaderProgram::setUniformValue(int location, const QMatrix2x4& value)
2303 {
2304     Q_D(QGLShaderProgram);
2305     d->glfuncs->glUniform4fv(location, 2, value.constData());
2306 }
2307 
2308 /*!
2309     \overload
2310 
2311     Sets the uniform variable called \a name in the current context
2312     to a 2x4 matrix \a value.
2313 
2314     \sa setAttributeValue()
2315 */
setUniformValue(const char * name,const QMatrix2x4 & value)2316 void QGLShaderProgram::setUniformValue(const char *name, const QMatrix2x4& value)
2317 {
2318     setUniformValue(uniformLocation(name), value);
2319 }
2320 
2321 /*!
2322     Sets the uniform variable at \a location in the current context
2323     to a 3x2 matrix \a value.
2324 
2325     \sa setAttributeValue()
2326 */
setUniformValue(int location,const QMatrix3x2 & value)2327 void QGLShaderProgram::setUniformValue(int location, const QMatrix3x2& value)
2328 {
2329     Q_D(QGLShaderProgram);
2330     d->glfuncs->glUniform2fv(location, 3, value.constData());
2331 }
2332 
2333 /*!
2334     \overload
2335 
2336     Sets the uniform variable called \a name in the current context
2337     to a 3x2 matrix \a value.
2338 
2339     \sa setAttributeValue()
2340 */
setUniformValue(const char * name,const QMatrix3x2 & value)2341 void QGLShaderProgram::setUniformValue(const char *name, const QMatrix3x2& value)
2342 {
2343     setUniformValue(uniformLocation(name), value);
2344 }
2345 
2346 /*!
2347     Sets the uniform variable at \a location in the current context
2348     to a 3x3 matrix \a value.
2349 
2350     \sa setAttributeValue()
2351 */
setUniformValue(int location,const QMatrix3x3 & value)2352 void QGLShaderProgram::setUniformValue(int location, const QMatrix3x3& value)
2353 {
2354     Q_D(QGLShaderProgram);
2355     d->glfuncs->glUniformMatrix3fv(location, 1, GL_FALSE, value.constData());
2356 }
2357 
2358 /*!
2359     \overload
2360 
2361     Sets the uniform variable called \a name in the current context
2362     to a 3x3 matrix \a value.
2363 
2364     \sa setAttributeValue()
2365 */
setUniformValue(const char * name,const QMatrix3x3 & value)2366 void QGLShaderProgram::setUniformValue(const char *name, const QMatrix3x3& value)
2367 {
2368     setUniformValue(uniformLocation(name), value);
2369 }
2370 
2371 /*!
2372     Sets the uniform variable at \a location in the current context
2373     to a 3x4 matrix \a value.
2374 
2375     \sa setAttributeValue()
2376 */
setUniformValue(int location,const QMatrix3x4 & value)2377 void QGLShaderProgram::setUniformValue(int location, const QMatrix3x4& value)
2378 {
2379     Q_D(QGLShaderProgram);
2380     d->glfuncs->glUniform4fv(location, 3, value.constData());
2381 }
2382 
2383 /*!
2384     \overload
2385 
2386     Sets the uniform variable called \a name in the current context
2387     to a 3x4 matrix \a value.
2388 
2389     \sa setAttributeValue()
2390 */
setUniformValue(const char * name,const QMatrix3x4 & value)2391 void QGLShaderProgram::setUniformValue(const char *name, const QMatrix3x4& value)
2392 {
2393     setUniformValue(uniformLocation(name), value);
2394 }
2395 
2396 /*!
2397     Sets the uniform variable at \a location in the current context
2398     to a 4x2 matrix \a value.
2399 
2400     \sa setAttributeValue()
2401 */
setUniformValue(int location,const QMatrix4x2 & value)2402 void QGLShaderProgram::setUniformValue(int location, const QMatrix4x2& value)
2403 {
2404     Q_D(QGLShaderProgram);
2405     d->glfuncs->glUniform2fv(location, 4, value.constData());
2406 }
2407 
2408 /*!
2409     \overload
2410 
2411     Sets the uniform variable called \a name in the current context
2412     to a 4x2 matrix \a value.
2413 
2414     \sa setAttributeValue()
2415 */
setUniformValue(const char * name,const QMatrix4x2 & value)2416 void QGLShaderProgram::setUniformValue(const char *name, const QMatrix4x2& value)
2417 {
2418     setUniformValue(uniformLocation(name), value);
2419 }
2420 
2421 /*!
2422     Sets the uniform variable at \a location in the current context
2423     to a 4x3 matrix \a value.
2424 
2425     \sa setAttributeValue()
2426 */
setUniformValue(int location,const QMatrix4x3 & value)2427 void QGLShaderProgram::setUniformValue(int location, const QMatrix4x3& value)
2428 {
2429     Q_D(QGLShaderProgram);
2430     d->glfuncs->glUniform3fv(location, 4, value.constData());
2431 }
2432 
2433 /*!
2434     \overload
2435 
2436     Sets the uniform variable called \a name in the current context
2437     to a 4x3 matrix \a value.
2438 
2439     \sa setAttributeValue()
2440 */
setUniformValue(const char * name,const QMatrix4x3 & value)2441 void QGLShaderProgram::setUniformValue(const char *name, const QMatrix4x3& value)
2442 {
2443     setUniformValue(uniformLocation(name), value);
2444 }
2445 
2446 /*!
2447     Sets the uniform variable at \a location in the current context
2448     to a 4x4 matrix \a value.
2449 
2450     \sa setAttributeValue()
2451 */
setUniformValue(int location,const QMatrix4x4 & value)2452 void QGLShaderProgram::setUniformValue(int location, const QMatrix4x4& value)
2453 {
2454     Q_D(QGLShaderProgram);
2455     d->glfuncs->glUniformMatrix4fv(location, 1, GL_FALSE, value.constData());
2456 }
2457 
2458 /*!
2459     \overload
2460 
2461     Sets the uniform variable called \a name in the current context
2462     to a 4x4 matrix \a value.
2463 
2464     \sa setAttributeValue()
2465 */
setUniformValue(const char * name,const QMatrix4x4 & value)2466 void QGLShaderProgram::setUniformValue(const char *name, const QMatrix4x4& value)
2467 {
2468     setUniformValue(uniformLocation(name), value);
2469 }
2470 
2471 /*!
2472     \overload
2473 
2474     Sets the uniform variable at \a location in the current context
2475     to a 2x2 matrix \a value.  The matrix elements must be specified
2476     in column-major order.
2477 
2478     \sa setAttributeValue()
2479     \since 4.7
2480 */
setUniformValue(int location,const GLfloat value[2][2])2481 void QGLShaderProgram::setUniformValue(int location, const GLfloat value[2][2])
2482 {
2483     Q_D(QGLShaderProgram);
2484     if (location != -1)
2485         d->glfuncs->glUniformMatrix2fv(location, 1, GL_FALSE, value[0]);
2486 }
2487 
2488 /*!
2489     \overload
2490 
2491     Sets the uniform variable at \a location in the current context
2492     to a 3x3 matrix \a value.  The matrix elements must be specified
2493     in column-major order.
2494 
2495     \sa setAttributeValue()
2496     \since 4.7
2497 */
setUniformValue(int location,const GLfloat value[3][3])2498 void QGLShaderProgram::setUniformValue(int location, const GLfloat value[3][3])
2499 {
2500     Q_D(QGLShaderProgram);
2501     if (location != -1)
2502         d->glfuncs->glUniformMatrix3fv(location, 1, GL_FALSE, value[0]);
2503 }
2504 
2505 /*!
2506     \overload
2507 
2508     Sets the uniform variable at \a location in the current context
2509     to a 4x4 matrix \a value.  The matrix elements must be specified
2510     in column-major order.
2511 
2512     \sa setAttributeValue()
2513 */
setUniformValue(int location,const GLfloat value[4][4])2514 void QGLShaderProgram::setUniformValue(int location, const GLfloat value[4][4])
2515 {
2516     Q_D(QGLShaderProgram);
2517     if (location != -1)
2518         d->glfuncs->glUniformMatrix4fv(location, 1, GL_FALSE, value[0]);
2519 }
2520 
2521 
2522 /*!
2523     \overload
2524 
2525     Sets the uniform variable called \a name in the current context
2526     to a 2x2 matrix \a value.  The matrix elements must be specified
2527     in column-major order.
2528 
2529     \sa setAttributeValue()
2530     \since 4.7
2531 */
setUniformValue(const char * name,const GLfloat value[2][2])2532 void QGLShaderProgram::setUniformValue(const char *name, const GLfloat value[2][2])
2533 {
2534     setUniformValue(uniformLocation(name), value);
2535 }
2536 
2537 /*!
2538     \overload
2539 
2540     Sets the uniform variable called \a name in the current context
2541     to a 3x3 matrix \a value.  The matrix elements must be specified
2542     in column-major order.
2543 
2544     \sa setAttributeValue()
2545     \since 4.7
2546 */
setUniformValue(const char * name,const GLfloat value[3][3])2547 void QGLShaderProgram::setUniformValue(const char *name, const GLfloat value[3][3])
2548 {
2549     setUniformValue(uniformLocation(name), value);
2550 }
2551 
2552 /*!
2553     \overload
2554 
2555     Sets the uniform variable called \a name in the current context
2556     to a 4x4 matrix \a value.  The matrix elements must be specified
2557     in column-major order.
2558 
2559     \sa setAttributeValue()
2560 */
setUniformValue(const char * name,const GLfloat value[4][4])2561 void QGLShaderProgram::setUniformValue(const char *name, const GLfloat value[4][4])
2562 {
2563     setUniformValue(uniformLocation(name), value);
2564 }
2565 
2566 /*!
2567     Sets the uniform variable at \a location in the current context to a
2568     3x3 transformation matrix \a value that is specified as a QTransform value.
2569 
2570     To set a QTransform value as a 4x4 matrix in a shader, use
2571     \c{setUniformValue(location, QMatrix4x4(value))}.
2572 */
setUniformValue(int location,const QTransform & value)2573 void QGLShaderProgram::setUniformValue(int location, const QTransform& value)
2574 {
2575     Q_D(QGLShaderProgram);
2576     if (location != -1) {
2577         GLfloat mat[3][3] = {
2578             {GLfloat(value.m11()), GLfloat(value.m12()), GLfloat(value.m13())},
2579             {GLfloat(value.m21()), GLfloat(value.m22()), GLfloat(value.m23())},
2580             {GLfloat(value.m31()), GLfloat(value.m32()), GLfloat(value.m33())}
2581         };
2582         d->glfuncs->glUniformMatrix3fv(location, 1, GL_FALSE, mat[0]);
2583     }
2584 }
2585 
2586 /*!
2587     \overload
2588 
2589     Sets the uniform variable called \a name in the current context to a
2590     3x3 transformation matrix \a value that is specified as a QTransform value.
2591 
2592     To set a QTransform value as a 4x4 matrix in a shader, use
2593     \c{setUniformValue(name, QMatrix4x4(value))}.
2594 */
setUniformValue(const char * name,const QTransform & value)2595 void QGLShaderProgram::setUniformValue
2596         (const char *name, const QTransform& value)
2597 {
2598     setUniformValue(uniformLocation(name), value);
2599 }
2600 
2601 /*!
2602     Sets the uniform variable array at \a location in the current
2603     context to the \a count elements of \a values.
2604 
2605     \sa setAttributeValue()
2606 */
setUniformValueArray(int location,const GLint * values,int count)2607 void QGLShaderProgram::setUniformValueArray(int location, const GLint *values, int count)
2608 {
2609     Q_D(QGLShaderProgram);
2610     if (location != -1)
2611         d->glfuncs->glUniform1iv(location, count, values);
2612 }
2613 
2614 /*!
2615     \overload
2616 
2617     Sets the uniform variable array called \a name in the current
2618     context to the \a count elements of \a values.
2619 
2620     \sa setAttributeValue()
2621 */
setUniformValueArray(const char * name,const GLint * values,int count)2622 void QGLShaderProgram::setUniformValueArray
2623         (const char *name, const GLint *values, int count)
2624 {
2625     setUniformValueArray(uniformLocation(name), values, count);
2626 }
2627 
2628 /*!
2629     Sets the uniform variable array at \a location in the current
2630     context to the \a count elements of \a values.  This overload
2631     should be used when setting an array of sampler values.
2632 
2633     \sa setAttributeValue()
2634 */
setUniformValueArray(int location,const GLuint * values,int count)2635 void QGLShaderProgram::setUniformValueArray(int location, const GLuint *values, int count)
2636 {
2637     Q_D(QGLShaderProgram);
2638     if (location != -1)
2639         d->glfuncs->glUniform1iv(location, count, reinterpret_cast<const GLint *>(values));
2640 }
2641 
2642 /*!
2643     \overload
2644 
2645     Sets the uniform variable array called \a name in the current
2646     context to the \a count elements of \a values.  This overload
2647     should be used when setting an array of sampler values.
2648 
2649     \sa setAttributeValue()
2650 */
setUniformValueArray(const char * name,const GLuint * values,int count)2651 void QGLShaderProgram::setUniformValueArray
2652         (const char *name, const GLuint *values, int count)
2653 {
2654     setUniformValueArray(uniformLocation(name), values, count);
2655 }
2656 
2657 /*!
2658     Sets the uniform variable array at \a location in the current
2659     context to the \a count elements of \a values.  Each element
2660     has \a tupleSize components.  The \a tupleSize must be 1, 2, 3, or 4.
2661 
2662     \sa setAttributeValue()
2663 */
setUniformValueArray(int location,const GLfloat * values,int count,int tupleSize)2664 void QGLShaderProgram::setUniformValueArray(int location, const GLfloat *values, int count, int tupleSize)
2665 {
2666     Q_D(QGLShaderProgram);
2667     if (location != -1) {
2668         if (tupleSize == 1)
2669             d->glfuncs->glUniform1fv(location, count, values);
2670         else if (tupleSize == 2)
2671             d->glfuncs->glUniform2fv(location, count, values);
2672         else if (tupleSize == 3)
2673             d->glfuncs->glUniform3fv(location, count, values);
2674         else if (tupleSize == 4)
2675             d->glfuncs->glUniform4fv(location, count, values);
2676         else
2677             qWarning() << "QGLShaderProgram::setUniformValue: size" << tupleSize << "not supported";
2678     }
2679 }
2680 
2681 /*!
2682     \overload
2683 
2684     Sets the uniform variable array called \a name in the current
2685     context to the \a count elements of \a values.  Each element
2686     has \a tupleSize components.  The \a tupleSize must be 1, 2, 3, or 4.
2687 
2688     \sa setAttributeValue()
2689 */
setUniformValueArray(const char * name,const GLfloat * values,int count,int tupleSize)2690 void QGLShaderProgram::setUniformValueArray
2691         (const char *name, const GLfloat *values, int count, int tupleSize)
2692 {
2693     setUniformValueArray(uniformLocation(name), values, count, tupleSize);
2694 }
2695 
2696 /*!
2697     Sets the uniform variable array at \a location in the current
2698     context to the \a count 2D vector elements of \a values.
2699 
2700     \sa setAttributeValue()
2701 */
setUniformValueArray(int location,const QVector2D * values,int count)2702 void QGLShaderProgram::setUniformValueArray(int location, const QVector2D *values, int count)
2703 {
2704     Q_D(QGLShaderProgram);
2705     if (location != -1)
2706         d->glfuncs->glUniform2fv(location, count, reinterpret_cast<const GLfloat *>(values));
2707 }
2708 
2709 /*!
2710     \overload
2711 
2712     Sets the uniform variable array called \a name in the current
2713     context to the \a count 2D vector elements of \a values.
2714 
2715     \sa setAttributeValue()
2716 */
setUniformValueArray(const char * name,const QVector2D * values,int count)2717 void QGLShaderProgram::setUniformValueArray(const char *name, const QVector2D *values, int count)
2718 {
2719     setUniformValueArray(uniformLocation(name), values, count);
2720 }
2721 
2722 /*!
2723     Sets the uniform variable array at \a location in the current
2724     context to the \a count 3D vector elements of \a values.
2725 
2726     \sa setAttributeValue()
2727 */
setUniformValueArray(int location,const QVector3D * values,int count)2728 void QGLShaderProgram::setUniformValueArray(int location, const QVector3D *values, int count)
2729 {
2730     Q_D(QGLShaderProgram);
2731     if (location != -1)
2732         d->glfuncs->glUniform3fv(location, count, reinterpret_cast<const GLfloat *>(values));
2733 }
2734 
2735 /*!
2736     \overload
2737 
2738     Sets the uniform variable array called \a name in the current
2739     context to the \a count 3D vector elements of \a values.
2740 
2741     \sa setAttributeValue()
2742 */
setUniformValueArray(const char * name,const QVector3D * values,int count)2743 void QGLShaderProgram::setUniformValueArray(const char *name, const QVector3D *values, int count)
2744 {
2745     setUniformValueArray(uniformLocation(name), values, count);
2746 }
2747 
2748 /*!
2749     Sets the uniform variable array at \a location in the current
2750     context to the \a count 4D vector elements of \a values.
2751 
2752     \sa setAttributeValue()
2753 */
setUniformValueArray(int location,const QVector4D * values,int count)2754 void QGLShaderProgram::setUniformValueArray(int location, const QVector4D *values, int count)
2755 {
2756     Q_D(QGLShaderProgram);
2757     Q_UNUSED(d);
2758     if (location != -1)
2759         d->glfuncs->glUniform4fv(location, count, reinterpret_cast<const GLfloat *>(values));
2760 }
2761 
2762 /*!
2763     \overload
2764 
2765     Sets the uniform variable array called \a name in the current
2766     context to the \a count 4D vector elements of \a values.
2767 
2768     \sa setAttributeValue()
2769 */
setUniformValueArray(const char * name,const QVector4D * values,int count)2770 void QGLShaderProgram::setUniformValueArray(const char *name, const QVector4D *values, int count)
2771 {
2772     setUniformValueArray(uniformLocation(name), values, count);
2773 }
2774 
2775 // We have to repack matrix arrays from qreal to GLfloat.
2776 #define setUniformMatrixArray(func,location,values,count,type,cols,rows) \
2777     if (location == -1 || count <= 0) \
2778         return; \
2779     if (sizeof(type) == sizeof(GLfloat) * cols * rows) { \
2780         func(location, count, GL_FALSE, \
2781              reinterpret_cast<const GLfloat *>(values[0].constData())); \
2782     } else { \
2783         QVarLengthArray<GLfloat> temp(cols * rows * count); \
2784         for (int index = 0; index < count; ++index) { \
2785             for (int index2 = 0; index2 < (cols * rows); ++index2) { \
2786                 temp.data()[cols * rows * index + index2] = \
2787                     values[index].constData()[index2]; \
2788             } \
2789         } \
2790         func(location, count, GL_FALSE, temp.constData()); \
2791     }
2792 #define setUniformGenericMatrixArray(colfunc,location,values,count,type,cols,rows) \
2793     if (location == -1 || count <= 0) \
2794         return; \
2795     if (sizeof(type) == sizeof(GLfloat) * cols * rows) { \
2796         const GLfloat *data = reinterpret_cast<const GLfloat *> \
2797             (values[0].constData());  \
2798         colfunc(location, count * cols, data); \
2799     } else { \
2800         QVarLengthArray<GLfloat> temp(cols * rows * count); \
2801         for (int index = 0; index < count; ++index) { \
2802             for (int index2 = 0; index2 < (cols * rows); ++index2) { \
2803                 temp.data()[cols * rows * index + index2] = \
2804                     values[index].constData()[index2]; \
2805             } \
2806         } \
2807         colfunc(location, count * cols, temp.constData()); \
2808     }
2809 
2810 /*!
2811     Sets the uniform variable array at \a location in the current
2812     context to the \a count 2x2 matrix elements of \a values.
2813 
2814     \sa setAttributeValue()
2815 */
setUniformValueArray(int location,const QMatrix2x2 * values,int count)2816 void QGLShaderProgram::setUniformValueArray(int location, const QMatrix2x2 *values, int count)
2817 {
2818     Q_D(QGLShaderProgram);
2819     Q_UNUSED(d);
2820     setUniformMatrixArray
2821         (d->glfuncs->glUniformMatrix2fv, location, values, count, QMatrix2x2, 2, 2);
2822 }
2823 
2824 /*!
2825     \overload
2826 
2827     Sets the uniform variable array called \a name in the current
2828     context to the \a count 2x2 matrix elements of \a values.
2829 
2830     \sa setAttributeValue()
2831 */
setUniformValueArray(const char * name,const QMatrix2x2 * values,int count)2832 void QGLShaderProgram::setUniformValueArray(const char *name, const QMatrix2x2 *values, int count)
2833 {
2834     setUniformValueArray(uniformLocation(name), values, count);
2835 }
2836 
2837 /*!
2838     Sets the uniform variable array at \a location in the current
2839     context to the \a count 2x3 matrix elements of \a values.
2840 
2841     \sa setAttributeValue()
2842 */
setUniformValueArray(int location,const QMatrix2x3 * values,int count)2843 void QGLShaderProgram::setUniformValueArray(int location, const QMatrix2x3 *values, int count)
2844 {
2845     Q_D(QGLShaderProgram);
2846     Q_UNUSED(d);
2847     setUniformGenericMatrixArray
2848         (d->glfuncs->glUniform3fv, location, values, count,
2849          QMatrix2x3, 2, 3);
2850 }
2851 
2852 /*!
2853     \overload
2854 
2855     Sets the uniform variable array called \a name in the current
2856     context to the \a count 2x3 matrix elements of \a values.
2857 
2858     \sa setAttributeValue()
2859 */
setUniformValueArray(const char * name,const QMatrix2x3 * values,int count)2860 void QGLShaderProgram::setUniformValueArray(const char *name, const QMatrix2x3 *values, int count)
2861 {
2862     setUniformValueArray(uniformLocation(name), values, count);
2863 }
2864 
2865 /*!
2866     Sets the uniform variable array at \a location in the current
2867     context to the \a count 2x4 matrix elements of \a values.
2868 
2869     \sa setAttributeValue()
2870 */
setUniformValueArray(int location,const QMatrix2x4 * values,int count)2871 void QGLShaderProgram::setUniformValueArray(int location, const QMatrix2x4 *values, int count)
2872 {
2873     Q_D(QGLShaderProgram);
2874     Q_UNUSED(d);
2875     setUniformGenericMatrixArray
2876         (d->glfuncs->glUniform4fv, location, values, count,
2877          QMatrix2x4, 2, 4);
2878 }
2879 
2880 /*!
2881     \overload
2882 
2883     Sets the uniform variable array called \a name in the current
2884     context to the \a count 2x4 matrix elements of \a values.
2885 
2886     \sa setAttributeValue()
2887 */
setUniformValueArray(const char * name,const QMatrix2x4 * values,int count)2888 void QGLShaderProgram::setUniformValueArray(const char *name, const QMatrix2x4 *values, int count)
2889 {
2890     setUniformValueArray(uniformLocation(name), values, count);
2891 }
2892 
2893 /*!
2894     Sets the uniform variable array at \a location in the current
2895     context to the \a count 3x2 matrix elements of \a values.
2896 
2897     \sa setAttributeValue()
2898 */
setUniformValueArray(int location,const QMatrix3x2 * values,int count)2899 void QGLShaderProgram::setUniformValueArray(int location, const QMatrix3x2 *values, int count)
2900 {
2901     Q_D(QGLShaderProgram);
2902     Q_UNUSED(d);
2903     setUniformGenericMatrixArray
2904         (d->glfuncs->glUniform2fv, location, values, count,
2905          QMatrix3x2, 3, 2);
2906 }
2907 
2908 /*!
2909     \overload
2910 
2911     Sets the uniform variable array called \a name in the current
2912     context to the \a count 3x2 matrix elements of \a values.
2913 
2914     \sa setAttributeValue()
2915 */
setUniformValueArray(const char * name,const QMatrix3x2 * values,int count)2916 void QGLShaderProgram::setUniformValueArray(const char *name, const QMatrix3x2 *values, int count)
2917 {
2918     setUniformValueArray(uniformLocation(name), values, count);
2919 }
2920 
2921 /*!
2922     Sets the uniform variable array at \a location in the current
2923     context to the \a count 3x3 matrix elements of \a values.
2924 
2925     \sa setAttributeValue()
2926 */
setUniformValueArray(int location,const QMatrix3x3 * values,int count)2927 void QGLShaderProgram::setUniformValueArray(int location, const QMatrix3x3 *values, int count)
2928 {
2929     Q_D(QGLShaderProgram);
2930     Q_UNUSED(d);
2931     setUniformMatrixArray
2932         (d->glfuncs->glUniformMatrix3fv, location, values, count, QMatrix3x3, 3, 3);
2933 }
2934 
2935 /*!
2936     \overload
2937 
2938     Sets the uniform variable array called \a name in the current
2939     context to the \a count 3x3 matrix elements of \a values.
2940 
2941     \sa setAttributeValue()
2942 */
setUniformValueArray(const char * name,const QMatrix3x3 * values,int count)2943 void QGLShaderProgram::setUniformValueArray(const char *name, const QMatrix3x3 *values, int count)
2944 {
2945     setUniformValueArray(uniformLocation(name), values, count);
2946 }
2947 
2948 /*!
2949     Sets the uniform variable array at \a location in the current
2950     context to the \a count 3x4 matrix elements of \a values.
2951 
2952     \sa setAttributeValue()
2953 */
setUniformValueArray(int location,const QMatrix3x4 * values,int count)2954 void QGLShaderProgram::setUniformValueArray(int location, const QMatrix3x4 *values, int count)
2955 {
2956     Q_D(QGLShaderProgram);
2957     Q_UNUSED(d);
2958     setUniformGenericMatrixArray
2959         (d->glfuncs->glUniform4fv, location, values, count,
2960          QMatrix3x4, 3, 4);
2961 }
2962 
2963 /*!
2964     \overload
2965 
2966     Sets the uniform variable array called \a name in the current
2967     context to the \a count 3x4 matrix elements of \a values.
2968 
2969     \sa setAttributeValue()
2970 */
setUniformValueArray(const char * name,const QMatrix3x4 * values,int count)2971 void QGLShaderProgram::setUniformValueArray(const char *name, const QMatrix3x4 *values, int count)
2972 {
2973     setUniformValueArray(uniformLocation(name), values, count);
2974 }
2975 
2976 /*!
2977     Sets the uniform variable array at \a location in the current
2978     context to the \a count 4x2 matrix elements of \a values.
2979 
2980     \sa setAttributeValue()
2981 */
setUniformValueArray(int location,const QMatrix4x2 * values,int count)2982 void QGLShaderProgram::setUniformValueArray(int location, const QMatrix4x2 *values, int count)
2983 {
2984     Q_D(QGLShaderProgram);
2985     Q_UNUSED(d);
2986     setUniformGenericMatrixArray
2987         (d->glfuncs->glUniform2fv, location, values, count,
2988          QMatrix4x2, 4, 2);
2989 }
2990 
2991 /*!
2992     \overload
2993 
2994     Sets the uniform variable array called \a name in the current
2995     context to the \a count 4x2 matrix elements of \a values.
2996 
2997     \sa setAttributeValue()
2998 */
setUniformValueArray(const char * name,const QMatrix4x2 * values,int count)2999 void QGLShaderProgram::setUniformValueArray(const char *name, const QMatrix4x2 *values, int count)
3000 {
3001     setUniformValueArray(uniformLocation(name), values, count);
3002 }
3003 
3004 /*!
3005     Sets the uniform variable array at \a location in the current
3006     context to the \a count 4x3 matrix elements of \a values.
3007 
3008     \sa setAttributeValue()
3009 */
setUniformValueArray(int location,const QMatrix4x3 * values,int count)3010 void QGLShaderProgram::setUniformValueArray(int location, const QMatrix4x3 *values, int count)
3011 {
3012     Q_D(QGLShaderProgram);
3013     Q_UNUSED(d);
3014     setUniformGenericMatrixArray
3015         (d->glfuncs->glUniform3fv, location, values, count,
3016          QMatrix4x3, 4, 3);
3017 }
3018 
3019 /*!
3020     \overload
3021 
3022     Sets the uniform variable array called \a name in the current
3023     context to the \a count 4x3 matrix elements of \a values.
3024 
3025     \sa setAttributeValue()
3026 */
setUniformValueArray(const char * name,const QMatrix4x3 * values,int count)3027 void QGLShaderProgram::setUniformValueArray(const char *name, const QMatrix4x3 *values, int count)
3028 {
3029     setUniformValueArray(uniformLocation(name), values, count);
3030 }
3031 
3032 /*!
3033     Sets the uniform variable array at \a location in the current
3034     context to the \a count 4x4 matrix elements of \a values.
3035 
3036     \sa setAttributeValue()
3037 */
setUniformValueArray(int location,const QMatrix4x4 * values,int count)3038 void QGLShaderProgram::setUniformValueArray(int location, const QMatrix4x4 *values, int count)
3039 {
3040     Q_D(QGLShaderProgram);
3041     Q_UNUSED(d);
3042     setUniformMatrixArray
3043         (d->glfuncs->glUniformMatrix4fv, location, values, count, QMatrix4x4, 4, 4);
3044 }
3045 
3046 /*!
3047     \overload
3048 
3049     Sets the uniform variable array called \a name in the current
3050     context to the \a count 4x4 matrix elements of \a values.
3051 
3052     \sa setAttributeValue()
3053 */
setUniformValueArray(const char * name,const QMatrix4x4 * values,int count)3054 void QGLShaderProgram::setUniformValueArray(const char *name, const QMatrix4x4 *values, int count)
3055 {
3056     setUniformValueArray(uniformLocation(name), values, count);
3057 }
3058 
3059 #undef ctx
3060 
3061 /*!
3062     Returns the hardware limit for how many vertices a geometry shader
3063     can output.
3064 
3065     \since 4.7
3066 
3067     \sa setGeometryOutputVertexCount()
3068 */
maxGeometryOutputVertices() const3069 int QGLShaderProgram::maxGeometryOutputVertices() const
3070 {
3071     GLint n = 0;
3072 #if !defined(QT_OPENGL_ES_2)
3073     Q_D(const QGLShaderProgram);
3074     if (!QOpenGLContext::currentContext()->isOpenGLES())
3075         d->glfuncs->glGetIntegerv(GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT, &n);
3076 #endif
3077     return n;
3078 }
3079 
3080 /*!
3081     Sets the maximum number of vertices the current geometry shader
3082     program will produce, if active, to \a count.
3083 
3084     \since 4.7
3085 
3086     This parameter takes effect the next time the program is linked.
3087 */
setGeometryOutputVertexCount(int count)3088 void QGLShaderProgram::setGeometryOutputVertexCount(int count)
3089 {
3090 #ifndef QT_NO_DEBUG
3091     int max = maxGeometryOutputVertices();
3092     if (count > max) {
3093         qWarning("QGLShaderProgram::setGeometryOutputVertexCount: count: %d higher than maximum: %d",
3094                  count, max);
3095     }
3096 #endif
3097     d_func()->geometryVertexCount = count;
3098 }
3099 
3100 
3101 /*!
3102     Returns the maximum number of vertices the current geometry shader
3103     program will produce, if active.
3104 
3105     \since 4.7
3106 
3107     This parameter takes effect the ntext time the program is linked.
3108 */
geometryOutputVertexCount() const3109 int QGLShaderProgram::geometryOutputVertexCount() const
3110 {
3111     return d_func()->geometryVertexCount;
3112 }
3113 
3114 
3115 /*!
3116     Sets the input type from \a inputType.
3117 
3118     This parameter takes effect the next time the program is linked.
3119 */
setGeometryInputType(GLenum inputType)3120 void QGLShaderProgram::setGeometryInputType(GLenum inputType)
3121 {
3122     d_func()->geometryInputType = inputType;
3123 }
3124 
3125 
3126 /*!
3127     Returns the geometry shader input type, if active.
3128 
3129     This parameter takes effect the next time the program is linked.
3130 
3131     \since 4.7
3132  */
3133 
geometryInputType() const3134 GLenum QGLShaderProgram::geometryInputType() const
3135 {
3136     return d_func()->geometryInputType;
3137 }
3138 
3139 
3140 /*!
3141     Sets the output type from the geometry shader, if active, to
3142     \a outputType.
3143 
3144     This parameter takes effect the next time the program is linked.
3145 
3146     \since 4.7
3147 */
setGeometryOutputType(GLenum outputType)3148 void QGLShaderProgram::setGeometryOutputType(GLenum outputType)
3149 {
3150     d_func()->geometryOutputType = outputType;
3151 }
3152 
3153 
3154 /*!
3155     Returns the geometry shader output type, if active.
3156 
3157     This parameter takes effect the next time the program is linked.
3158 
3159     \since 4.7
3160  */
geometryOutputType() const3161 GLenum QGLShaderProgram::geometryOutputType() const
3162 {
3163     return d_func()->geometryOutputType;
3164 }
3165 
3166 
3167 /*!
3168     Returns \c true if shader programs written in the OpenGL Shading
3169     Language (GLSL) are supported on this system; false otherwise.
3170 
3171     The \a context is used to resolve the GLSL extensions.
3172     If \a context is \nullptr, then QGLContext::currentContext() is
3173     used.
3174 */
hasOpenGLShaderPrograms(const QGLContext * context)3175 bool QGLShaderProgram::hasOpenGLShaderPrograms(const QGLContext *context)
3176 {
3177 #if !defined(QT_OPENGL_ES_2)
3178     if (!context)
3179         context = QGLContext::currentContext();
3180     if (!context)
3181         return false;
3182 
3183     QOpenGLFunctions functions(context->contextHandle());
3184     return functions.hasOpenGLFeature(QOpenGLFunctions::Shaders);
3185 #else
3186     Q_UNUSED(context);
3187     return true;
3188 #endif
3189 }
3190 
3191 /*!
3192     \internal
3193 */
shaderDestroyed()3194 void QGLShaderProgram::shaderDestroyed()
3195 {
3196     Q_D(QGLShaderProgram);
3197     QGLShader *shader = qobject_cast<QGLShader *>(sender());
3198     if (shader && !d->removingShaders)
3199         removeShader(shader);
3200 }
3201 
3202 
3203 #undef ctx
3204 #undef context
3205 
3206 /*!
3207     Returns \c true if shader programs of type \a type are supported on
3208     this system; false otherwise.
3209 
3210     The \a context is used to resolve the GLSL extensions.
3211     If \a context is \nullptr, then QGLContext::currentContext() is
3212     used.
3213 
3214     \since 4.7
3215 */
hasOpenGLShaders(ShaderType type,const QGLContext * context)3216 bool QGLShader::hasOpenGLShaders(ShaderType type, const QGLContext *context)
3217 {
3218     if (!context)
3219         context = QGLContext::currentContext();
3220     if (!context)
3221         return false;
3222 
3223     if ((type & ~(Geometry | Vertex | Fragment)) || type == 0)
3224         return false;
3225 
3226     QOpenGLFunctions functions(context->contextHandle());
3227     bool resolved = functions.hasOpenGLFeature(QOpenGLFunctions::Shaders);
3228     if (!resolved)
3229         return false;
3230 
3231     if ((type & Geometry) && !QByteArray((const char *) functions.glGetString(GL_EXTENSIONS)).contains("GL_EXT_geometry_shader4"))
3232         return false;
3233 
3234     return true;
3235 }
3236 
3237 QT_END_NAMESPACE
3238