From 4b611d649ede3bd1e56a73abcbd16aa60db38e3b Mon Sep 17 00:00:00 2001 From: Johan Klokkhammer Helsing Date: Fri, 17 Jan 2020 14:40:36 +0100 Subject: Move QOpenGLShaderProgram from QtGui to QtOpenGL Task-number: QTBUG-74409 Change-Id: I20dfafc0c9bf8e2b68b03e171d70c2cb4ad2bfaf Reviewed-by: Laszlo Agocs --- src/gui/opengl/opengl.pri | 2 - src/gui/opengl/qopenglprogrambinarycache.cpp | 1 - src/gui/opengl/qopenglprogrambinarycache_p.h | 11 +- src/gui/opengl/qopenglshaderprogram.cpp | 3812 -------------------------- src/gui/opengl/qopenglshaderprogram.h | 318 --- 5 files changed, 7 insertions(+), 4137 deletions(-) delete mode 100644 src/gui/opengl/qopenglshaderprogram.cpp delete mode 100644 src/gui/opengl/qopenglshaderprogram.h (limited to 'src/gui/opengl') diff --git a/src/gui/opengl/opengl.pri b/src/gui/opengl/opengl.pri index 00ac48fa75..c606e9ec02 100644 --- a/src/gui/opengl/opengl.pri +++ b/src/gui/opengl/opengl.pri @@ -9,7 +9,6 @@ qtConfig(opengl) { opengl/qopengl_p.h \ opengl/qopenglfunctions.h \ opengl/qopenglbuffer.h \ - opengl/qopenglshaderprogram.h \ opengl/qopenglextensions_p.h \ opengl/qopenglversionfunctions.h \ opengl/qopenglversionfunctionsfactory_p.h \ @@ -20,7 +19,6 @@ qtConfig(opengl) { SOURCES += opengl/qopengl.cpp \ opengl/qopenglfunctions.cpp \ opengl/qopenglbuffer.cpp \ - opengl/qopenglshaderprogram.cpp \ opengl/qopenglversionfunctions.cpp \ opengl/qopenglversionfunctionsfactory.cpp \ opengl/qopenglvertexarrayobject.cpp \ diff --git a/src/gui/opengl/qopenglprogrambinarycache.cpp b/src/gui/opengl/qopenglprogrambinarycache.cpp index 72bdacf43f..89c44e72c0 100644 --- a/src/gui/opengl/qopenglprogrambinarycache.cpp +++ b/src/gui/opengl/qopenglprogrambinarycache.cpp @@ -45,7 +45,6 @@ #include #include #include -#include #include #ifdef Q_OS_UNIX diff --git a/src/gui/opengl/qopenglprogrambinarycache_p.h b/src/gui/opengl/qopenglprogrambinarycache_p.h index f1cf24cd87..873e9d7c00 100644 --- a/src/gui/opengl/qopenglprogrambinarycache_p.h +++ b/src/gui/opengl/qopenglprogrambinarycache_p.h @@ -54,6 +54,7 @@ #include #include #include +#include #include #include @@ -63,10 +64,12 @@ QT_BEGIN_NAMESPACE // therefore stay independent from QOpenGLShader(Program). Must rely only on // QOpenGLContext/Functions. -class QOpenGLProgramBinaryCache +Q_GUI_EXPORT Q_DECLARE_LOGGING_CATEGORY(lcOpenGLProgramDiskCache) + +class Q_GUI_EXPORT QOpenGLProgramBinaryCache { public: - struct ShaderDesc { + struct Q_GUI_EXPORT ShaderDesc { ShaderDesc() { } ShaderDesc(QShader::Stage stage, const QByteArray &source = QByteArray()) : stage(stage), source(source) @@ -74,7 +77,7 @@ public: QShader::Stage stage; QByteArray source; }; - struct ProgramDesc { + struct Q_GUI_EXPORT ProgramDesc { QVector shaders; QByteArray cacheKey() const; }; @@ -114,7 +117,7 @@ private: // per-context basis, not just once per process. QOpenGLSharedResource enables this, // although it's once-per-sharing-context-group, not per-context. Still, this should // be good enough in practice. -class QOpenGLProgramBinarySupportCheck : public QOpenGLSharedResource +class Q_GUI_EXPORT QOpenGLProgramBinarySupportCheck : public QOpenGLSharedResource { public: QOpenGLProgramBinarySupportCheck(QOpenGLContext *context); diff --git a/src/gui/opengl/qopenglshaderprogram.cpp b/src/gui/opengl/qopenglshaderprogram.cpp deleted file mode 100644 index 7e89d9c8d4..0000000000 --- a/src/gui/opengl/qopenglshaderprogram.cpp +++ /dev/null @@ -1,3812 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qopenglshaderprogram.h" -#include "qopenglprogrambinarycache_p.h" -#include "qopenglextrafunctions.h" -#include "private/qopenglcontext_p.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if !defined(QT_OPENGL_ES_2) -#include -#endif - -#include - -QT_BEGIN_NAMESPACE - -/*! - \class QOpenGLShaderProgram - \brief The QOpenGLShaderProgram class allows OpenGL shader programs to be linked and used. - \since 5.0 - \ingroup painting-3D - \inmodule QtGui - - \section1 Introduction - - This class supports shader programs written in the OpenGL Shading - Language (GLSL) and in the OpenGL/ES Shading Language (GLSL/ES). - - QOpenGLShader and QOpenGLShaderProgram shelter the programmer from the details of - compiling and linking vertex and fragment shaders. - - The following example creates a vertex shader program using the - supplied source \c{code}. Once compiled and linked, the shader - program is activated in the current QOpenGLContext by calling - QOpenGLShaderProgram::bind(): - - \snippet code/src_gui_qopenglshaderprogram.cpp 0 - - \section1 Writing Portable Shaders - - Shader programs can be difficult to reuse across OpenGL implementations - because of varying levels of support for standard vertex attributes and - uniform variables. In particular, GLSL/ES lacks all of the - standard variables that are present on desktop OpenGL systems: - \c{gl_Vertex}, \c{gl_Normal}, \c{gl_Color}, and so on. Desktop OpenGL - lacks the variable qualifiers \c{highp}, \c{mediump}, and \c{lowp}. - - The QOpenGLShaderProgram class makes the process of writing portable shaders - easier by prefixing all shader programs with the following lines on - desktop OpenGL: - - \code - #define highp - #define mediump - #define lowp - \endcode - - This makes it possible to run most GLSL/ES shader programs - on desktop systems. The programmer should restrict themselves - to just features that are present in GLSL/ES, and avoid - standard variable names that only work on the desktop. - - \section1 Simple Shader Example - - \snippet code/src_gui_qopenglshaderprogram.cpp 1 - - With the above shader program active, we can draw a green triangle - as follows: - - \snippet code/src_gui_qopenglshaderprogram.cpp 2 - - \section1 Binary Shaders and Programs - - Binary shaders may be specified using \c{glShaderBinary()} on - the return value from QOpenGLShader::shaderId(). The QOpenGLShader instance - containing the binary can then be added to the shader program with - addShader() and linked in the usual fashion with link(). - - Binary programs may be specified using \c{glProgramBinaryOES()} - on the return value from programId(). Then the application should - call link(), which will notice that the program has already been - specified and linked, allowing other operations to be performed - on the shader program. The shader program's id can be explicitly - created using the create() function. - - \section2 Caching Program Binaries - - As of Qt 5.9, support for caching program binaries on disk is built in. To - enable this, switch to using addCacheableShaderFromSourceCode() and - addCacheableShaderFromSourceFile(). With an OpenGL ES 3.x context or support - for \c{GL_ARB_get_program_binary}, this will transparently cache program - binaries under QStandardPaths::GenericCacheLocation or - QStandardPaths::CacheLocation. When support is not available, calling the - cacheable function variants is equivalent to the normal ones. - - \note Some drivers do not have any binary formats available, even though - they advertise the extension or offer OpenGL ES 3.0. In this case program - binary support will be disabled. - - \sa QOpenGLShader -*/ - -/*! - \class QOpenGLShader - \brief The QOpenGLShader class allows OpenGL shaders to be compiled. - \since 5.0 - \ingroup painting-3D - \inmodule QtGui - - This class supports shaders written in the OpenGL Shading Language (GLSL) - and in the OpenGL/ES Shading Language (GLSL/ES). - - QOpenGLShader and QOpenGLShaderProgram shelter the programmer from the details of - compiling and linking vertex and fragment shaders. - - \sa QOpenGLShaderProgram -*/ - -/*! - \enum QOpenGLShader::ShaderTypeBit - This enum specifies the type of QOpenGLShader that is being created. - - \value Vertex Vertex shader written in the OpenGL Shading Language (GLSL). - \value Fragment Fragment shader written in the OpenGL Shading Language (GLSL). - \value Geometry Geometry shaders written in the OpenGL Shading Language (GLSL) - (requires OpenGL >= 3.2 or OpenGL ES >= 3.2). - \value TessellationControl Tessellation control shaders written in the OpenGL - shading language (GLSL) (requires OpenGL >= 4.0 or OpenGL ES >= 3.2). - \value TessellationEvaluation Tessellation evaluation shaders written in the OpenGL - shading language (GLSL) (requires OpenGL >= 4.0 or OpenGL ES >= 3.2). - \value Compute Compute shaders written in the OpenGL shading language (GLSL) - (requires OpenGL >= 4.3 or OpenGL ES >= 3.1). -*/ - -Q_DECLARE_LOGGING_CATEGORY(lcOpenGLProgramDiskCache) - -// For GLES 3.1/3.2 -#ifndef GL_GEOMETRY_SHADER -#define GL_GEOMETRY_SHADER 0x8DD9 -#endif -#ifndef GL_TESS_CONTROL_SHADER -#define GL_TESS_CONTROL_SHADER 0x8E88 -#endif -#ifndef GL_TESS_EVALUATION_SHADER -#define GL_TESS_EVALUATION_SHADER 0x8E87 -#endif -#ifndef GL_COMPUTE_SHADER -#define GL_COMPUTE_SHADER 0x91B9 -#endif -#ifndef GL_MAX_GEOMETRY_OUTPUT_VERTICES -#define GL_MAX_GEOMETRY_OUTPUT_VERTICES 0x8DE0 -#endif -#ifndef GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS -#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS 0x8DE1 -#endif -#ifndef GL_PATCH_VERTICES -#define GL_PATCH_VERTICES 0x8E72 -#endif -#ifndef GL_PATCH_DEFAULT_OUTER_LEVEL -#define GL_PATCH_DEFAULT_OUTER_LEVEL 0x8E74 -#endif -#ifndef GL_PATCH_DEFAULT_INNER_LEVEL -#define GL_PATCH_DEFAULT_INNER_LEVEL 0x8E73 -#endif - -#ifndef QT_OPENGL_ES_2 -static inline bool isFormatGLES(const QSurfaceFormat &f) -{ - return (f.renderableType() == QSurfaceFormat::OpenGLES); -} -#endif - -static inline bool supportsGeometry(const QSurfaceFormat &f) -{ - return f.version() >= qMakePair(3, 2); -} - -static inline bool supportsCompute(const QSurfaceFormat &f) -{ -#ifndef QT_OPENGL_ES_2 - if (!isFormatGLES(f)) - return f.version() >= qMakePair(4, 3); - else - return f.version() >= qMakePair(3, 1); -#else - return f.version() >= qMakePair(3, 1); -#endif -} - -static inline bool supportsTessellation(const QSurfaceFormat &f) -{ -#ifndef QT_OPENGL_ES_2 - if (!isFormatGLES(f)) - return f.version() >= qMakePair(4, 0); - else - return f.version() >= qMakePair(3, 2); -#else - return f.version() >= qMakePair(3, 2); -#endif -} - -class QOpenGLShaderPrivate : public QObjectPrivate -{ - Q_DECLARE_PUBLIC(QOpenGLShader) -public: - QOpenGLShaderPrivate(QOpenGLContext *ctx, QOpenGLShader::ShaderType type) - : shaderGuard(nullptr) - , shaderType(type) - , compiled(false) - , glfuncs(new QOpenGLExtraFunctions(ctx)) - , supportsGeometryShaders(false) - , supportsTessellationShaders(false) - , supportsComputeShaders(false) - { - if (shaderType & QOpenGLShader::Geometry) - supportsGeometryShaders = supportsGeometry(ctx->format()); - else if (shaderType & (QOpenGLShader::TessellationControl | QOpenGLShader::TessellationEvaluation)) - supportsTessellationShaders = supportsTessellation(ctx->format()); - else if (shaderType & QOpenGLShader::Compute) - supportsComputeShaders = supportsCompute(ctx->format()); - } - ~QOpenGLShaderPrivate(); - - QOpenGLSharedResourceGuard *shaderGuard; - QOpenGLShader::ShaderType shaderType; - bool compiled; - QString log; - - QOpenGLExtraFunctions *glfuncs; - - // Support for geometry shaders - bool supportsGeometryShaders; - // Support for tessellation shaders - bool supportsTessellationShaders; - // Support for compute shaders - bool supportsComputeShaders; - - - bool create(); - bool compile(QOpenGLShader *q); - void deleteShader(); -}; - -namespace { - void freeShaderFunc(QOpenGLFunctions *funcs, GLuint id) - { - funcs->glDeleteShader(id); - } -} - -QOpenGLShaderPrivate::~QOpenGLShaderPrivate() -{ - delete glfuncs; - if (shaderGuard) - shaderGuard->free(); -} - -bool QOpenGLShaderPrivate::create() -{ - QOpenGLContext *context = const_cast(QOpenGLContext::currentContext()); - if (!context) - return false; - GLuint shader = 0; - if (shaderType == QOpenGLShader::Vertex) { - shader = glfuncs->glCreateShader(GL_VERTEX_SHADER); - } else if (shaderType == QOpenGLShader::Geometry && supportsGeometryShaders) { - shader = glfuncs->glCreateShader(GL_GEOMETRY_SHADER); - } else if (shaderType == QOpenGLShader::TessellationControl && supportsTessellationShaders) { - shader = glfuncs->glCreateShader(GL_TESS_CONTROL_SHADER); - } else if (shaderType == QOpenGLShader::TessellationEvaluation && supportsTessellationShaders) { - shader = glfuncs->glCreateShader(GL_TESS_EVALUATION_SHADER); - } else if (shaderType == QOpenGLShader::Compute && supportsComputeShaders) { - shader = glfuncs->glCreateShader(GL_COMPUTE_SHADER); - } else if (shaderType == QOpenGLShader::Fragment) { - shader = glfuncs->glCreateShader(GL_FRAGMENT_SHADER); - } - if (!shader) { - qWarning("QOpenGLShader: could not create shader"); - return false; - } - shaderGuard = new QOpenGLSharedResourceGuard(context, shader, freeShaderFunc); - return true; -} - -bool QOpenGLShaderPrivate::compile(QOpenGLShader *q) -{ - GLuint shader = shaderGuard ? shaderGuard->id() : 0; - if (!shader) - return false; - - // Try to compile shader - glfuncs->glCompileShader(shader); - GLint value = 0; - - // Get compilation status - glfuncs->glGetShaderiv(shader, GL_COMPILE_STATUS, &value); - compiled = (value != 0); - - if (!compiled) { - // Compilation failed, try to provide some information about the failure - QString name = q->objectName(); - - const char *types[] = { - "Fragment", - "Vertex", - "Geometry", - "Tessellation Control", - "Tessellation Evaluation", - "Compute", - "" - }; - - const char *type = types[6]; - switch (shaderType) { - case QOpenGLShader::Fragment: - type = types[0]; break; - case QOpenGLShader::Vertex: - type = types[1]; break; - case QOpenGLShader::Geometry: - type = types[2]; break; - case QOpenGLShader::TessellationControl: - type = types[3]; break; - case QOpenGLShader::TessellationEvaluation: - type = types[4]; break; - case QOpenGLShader::Compute: - type = types[5]; break; - } - - // Get info and source code lengths - GLint infoLogLength = 0; - GLint sourceCodeLength = 0; - char *logBuffer = nullptr; - char *sourceCodeBuffer = nullptr; - - // Get the compilation info log - glfuncs->glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength); - - if (infoLogLength > 1) { - GLint temp; - logBuffer = new char [infoLogLength]; - glfuncs->glGetShaderInfoLog(shader, infoLogLength, &temp, logBuffer); - } - - // Get the source code - glfuncs->glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &sourceCodeLength); - - if (sourceCodeLength > 1) { - GLint temp; - sourceCodeBuffer = new char [sourceCodeLength]; - glfuncs->glGetShaderSource(shader, sourceCodeLength, &temp, sourceCodeBuffer); - } - - if (logBuffer) - log = QString::fromLatin1(logBuffer); - else - log = QLatin1String("failed"); - - if (name.isEmpty()) - qWarning("QOpenGLShader::compile(%s): %s", type, qPrintable(log)); - else - qWarning("QOpenGLShader::compile(%s)[%s]: %s", type, qPrintable(name), qPrintable(log)); - - // Dump the source code if we got it - if (sourceCodeBuffer) { - qWarning("*** Problematic %s shader source code ***\n" - "%ls\n" - "***", - type, qUtf16Printable(QString::fromLatin1(sourceCodeBuffer))); - } - - // Cleanup - delete [] logBuffer; - delete [] sourceCodeBuffer; - } - - return compiled; -} - -void QOpenGLShaderPrivate::deleteShader() -{ - if (shaderGuard) { - shaderGuard->free(); - shaderGuard = nullptr; - } -} - -/*! - Constructs a new QOpenGLShader object of the specified \a type - and attaches it to \a parent. If shader programs are not supported, - QOpenGLShaderProgram::hasOpenGLShaderPrograms() will return false. - - This constructor is normally followed by a call to compileSourceCode() - or compileSourceFile(). - - The shader will be associated with the current QOpenGLContext. - - \sa compileSourceCode(), compileSourceFile() -*/ -QOpenGLShader::QOpenGLShader(QOpenGLShader::ShaderType type, QObject *parent) - : QObject(*new QOpenGLShaderPrivate(QOpenGLContext::currentContext(), type), parent) -{ - Q_D(QOpenGLShader); - d->create(); -} - -/*! - Deletes this shader. If the shader has been attached to a - QOpenGLShaderProgram object, then the actual shader will stay around - until the QOpenGLShaderProgram is destroyed. -*/ -QOpenGLShader::~QOpenGLShader() -{ -} - -/*! - Returns the type of this shader. -*/ -QOpenGLShader::ShaderType QOpenGLShader::shaderType() const -{ - Q_D(const QOpenGLShader); - return d->shaderType; -} - -static const char qualifierDefines[] = - "#define lowp\n" - "#define mediump\n" - "#define highp\n"; - -#if defined(QT_OPENGL_ES) && !defined(QT_OPENGL_FORCE_SHADER_DEFINES) -// The "highp" qualifier doesn't exist in fragment shaders -// on all ES platforms. When it doesn't exist, use "mediump". -#define QOpenGL_REDEFINE_HIGHP 1 -static const char redefineHighp[] = - "#ifndef GL_FRAGMENT_PRECISION_HIGH\n" - "#define highp mediump\n" - "#endif\n"; -#endif - -// Boiler-plate header to have the layout attributes available we need later -static const char blendEquationAdvancedHeader[] = - "#ifdef GL_KHR_blend_equation_advanced\n" - "#extension GL_ARB_fragment_coord_conventions : enable\n" - "#extension GL_KHR_blend_equation_advanced : enable\n" - "#endif\n"; - -struct QVersionDirectivePosition -{ - Q_DECL_CONSTEXPR QVersionDirectivePosition(int position = 0, int line = -1) - : position(position) - , line(line) - { - } - - Q_DECL_CONSTEXPR bool hasPosition() const - { - return position > 0; - } - - const int position; - const int line; -}; - -static QVersionDirectivePosition findVersionDirectivePosition(const char *source) -{ - Q_ASSERT(source); - - // According to the GLSL spec the #version directive must not be - // preceded by anything but whitespace and comments. - // In order to not get confused by #version directives within a - // multiline comment, we need to do some minimal comment parsing - // while searching for the directive. - enum { - Normal, - StartOfLine, - PreprocessorDirective, - CommentStarting, - MultiLineComment, - SingleLineComment, - CommentEnding - } state = StartOfLine; - - const char *c = source; - while (*c) { - switch (state) { - case PreprocessorDirective: - if (*c == ' ' || *c == '\t') - break; - if (!strncmp(c, "version", strlen("version"))) { - // Found version directive - c += strlen("version"); - while (*c && *c != '\n') - ++c; - int splitPosition = c - source + 1; - int linePosition = int(std::count(source, c, '\n')) + 1; - return QVersionDirectivePosition(splitPosition, linePosition); - } else if (*c == '/') - state = CommentStarting; - else if (*c == '\n') - state = StartOfLine; - else - state = Normal; - break; - case StartOfLine: - if (*c == ' ' || *c == '\t') - break; - else if (*c == '#') { - state = PreprocessorDirective; - break; - } - state = Normal; - Q_FALLTHROUGH(); - case Normal: - if (*c == '/') - state = CommentStarting; - else if (*c == '\n') - state = StartOfLine; - break; - case CommentStarting: - if (*c == '*') - state = MultiLineComment; - else if (*c == '/') - state = SingleLineComment; - else - state = Normal; - break; - case MultiLineComment: - if (*c == '*') - state = CommentEnding; - break; - case SingleLineComment: - if (*c == '\n') - state = Normal; - break; - case CommentEnding: - if (*c == '/') - state = Normal; - else if (*c != QLatin1Char('*')) - state = MultiLineComment; - break; - } - ++c; - } - - return QVersionDirectivePosition(0, 1); -} - -/*! - Sets the \a source code for this shader and compiles it. - Returns \c true if the source was successfully compiled, false otherwise. - - \sa compileSourceFile() -*/ -bool QOpenGLShader::compileSourceCode(const char *source) -{ - Q_D(QOpenGLShader); - // This method breaks the shader code into two parts: - // 1. Up to and including an optional #version directive. - // 2. The rest. - // If a #version directive exists, qualifierDefines and redefineHighp - // are inserted after. Otherwise they are inserted right at the start. - // In both cases a #line directive is appended in order to compensate - // for line number changes in case of compiler errors. - - if (d->shaderGuard && d->shaderGuard->id() && source) { - const QVersionDirectivePosition versionDirectivePosition = findVersionDirectivePosition(source); - - QVarLengthArray sourceChunks; - QVarLengthArray sourceChunkLengths; - QOpenGLContext *ctx = QOpenGLContext::currentContext(); - - if (versionDirectivePosition.hasPosition()) { - // Append source up to and including the #version directive - sourceChunks.append(source); - sourceChunkLengths.append(GLint(versionDirectivePosition.position)); - } else { - // QTBUG-55733: Intel on Windows with Compatibility profile requires a #version always - if (ctx->format().profile() == QSurfaceFormat::CompatibilityProfile) { - const char *vendor = reinterpret_cast(ctx->functions()->glGetString(GL_VENDOR)); - if (vendor && !strcmp(vendor, "Intel")) { - static const char version110[] = "#version 110\n"; - sourceChunks.append(version110); - sourceChunkLengths.append(GLint(sizeof(version110)) - 1); - } - } - } - if (d->shaderType == Fragment) { - sourceChunks.append(blendEquationAdvancedHeader); - sourceChunkLengths.append(GLint(sizeof(blendEquationAdvancedHeader) - 1)); - } - - // The precision qualifiers are useful on OpenGL/ES systems, - // but usually not present on desktop systems. - const QSurfaceFormat currentSurfaceFormat = ctx->format(); - QOpenGLContextPrivate *ctx_d = QOpenGLContextPrivate::get(QOpenGLContext::currentContext()); - if (currentSurfaceFormat.renderableType() == QSurfaceFormat::OpenGL - || ctx_d->workaround_missingPrecisionQualifiers -#ifdef QT_OPENGL_FORCE_SHADER_DEFINES - || true -#endif - ) { - sourceChunks.append(qualifierDefines); - sourceChunkLengths.append(GLint(sizeof(qualifierDefines) - 1)); - } - -#ifdef QOpenGL_REDEFINE_HIGHP - if (d->shaderType == Fragment && !ctx_d->workaround_missingPrecisionQualifiers - && QOpenGLContext::currentContext()->isOpenGLES()) { - sourceChunks.append(redefineHighp); - sourceChunkLengths.append(GLint(sizeof(redefineHighp) - 1)); - } -#endif - - QByteArray lineDirective; - // #line is rejected by some drivers: - // "2.1 Mesa 8.1-devel (git-48a3d4e)" or "MESA 2.1 Mesa 8.1-devel" - const char *version = reinterpret_cast(ctx->functions()->glGetString(GL_VERSION)); - if (!version || !strstr(version, "2.1 Mesa 8")) { - // Append #line directive in order to compensate for text insertion - lineDirective = QStringLiteral("#line %1\n").arg(versionDirectivePosition.line).toUtf8(); - sourceChunks.append(lineDirective.constData()); - sourceChunkLengths.append(GLint(lineDirective.length())); - } - - // Append rest of shader code - sourceChunks.append(source + versionDirectivePosition.position); - sourceChunkLengths.append(GLint(qstrlen(source + versionDirectivePosition.position))); - - d->glfuncs->glShaderSource(d->shaderGuard->id(), sourceChunks.size(), sourceChunks.data(), sourceChunkLengths.data()); - return d->compile(this); - } else { - return false; - } -} - -/*! - \overload - - Sets the \a source code for this shader and compiles it. - Returns \c true if the source was successfully compiled, false otherwise. - - \sa compileSourceFile() -*/ -bool QOpenGLShader::compileSourceCode(const QByteArray& source) -{ - return compileSourceCode(source.constData()); -} - -/*! - \overload - - Sets the \a source code for this shader and compiles it. - Returns \c true if the source was successfully compiled, false otherwise. - - \sa compileSourceFile() -*/ -bool QOpenGLShader::compileSourceCode(const QString& source) -{ - return compileSourceCode(source.toLatin1().constData()); -} - -/*! - Sets the source code for this shader to the contents of \a fileName - and compiles it. Returns \c true if the file could be opened and the - source compiled, false otherwise. - - \sa compileSourceCode() -*/ -bool QOpenGLShader::compileSourceFile(const QString& fileName) -{ - QFile file(fileName); - if (!file.open(QFile::ReadOnly)) { - qWarning() << "QOpenGLShader: Unable to open file" << fileName; - return false; - } - - QByteArray contents = file.readAll(); - return compileSourceCode(contents.constData()); -} - -/*! - Returns the source code for this shader. - - \sa compileSourceCode() -*/ -QByteArray QOpenGLShader::sourceCode() const -{ - Q_D(const QOpenGLShader); - GLuint shader = d->shaderGuard ? d->shaderGuard->id() : 0; - if (!shader) - return QByteArray(); - GLint size = 0; - d->glfuncs->glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &size); - if (size <= 0) - return QByteArray(); - GLint len = 0; - char *source = new char [size]; - d->glfuncs->glGetShaderSource(shader, size, &len, source); - QByteArray src(source); - delete [] source; - return src; -} - -/*! - Returns \c true if this shader has been compiled; false otherwise. - - \sa compileSourceCode(), compileSourceFile() -*/ -bool QOpenGLShader::isCompiled() const -{ - Q_D(const QOpenGLShader); - return d->compiled; -} - -/*! - Returns the errors and warnings that occurred during the last compile. - - \sa compileSourceCode(), compileSourceFile() -*/ -QString QOpenGLShader::log() const -{ - Q_D(const QOpenGLShader); - return d->log; -} - -/*! - Returns the OpenGL identifier associated with this shader. - - \sa QOpenGLShaderProgram::programId() -*/ -GLuint QOpenGLShader::shaderId() const -{ - Q_D(const QOpenGLShader); - return d->shaderGuard ? d->shaderGuard->id() : 0; -} - -class QOpenGLShaderProgramPrivate : public QObjectPrivate -{ - Q_DECLARE_PUBLIC(QOpenGLShaderProgram) -public: - QOpenGLShaderProgramPrivate() - : programGuard(nullptr) - , linked(false) - , inited(false) - , removingShaders(false) - , glfuncs(new QOpenGLExtraFunctions) -#ifndef QT_OPENGL_ES_2 - , tessellationFuncs(nullptr) -#endif - , linkBinaryRecursion(false) - { - } - ~QOpenGLShaderProgramPrivate(); - - QOpenGLSharedResourceGuard *programGuard; - bool linked; - bool inited; - bool removingShaders; - - QString log; - QList shaders; - QList anonShaders; - - QOpenGLExtraFunctions *glfuncs; -#ifndef QT_OPENGL_ES_2 - // for tessellation features not in GLES 3.2 - QOpenGLFunctions_4_0_Core *tessellationFuncs; -#endif - - bool hasShader(QOpenGLShader::ShaderType type) const; - - QOpenGLProgramBinaryCache::ProgramDesc binaryProgram; - bool isCacheDisabled() const; - bool compileCacheable(); - bool linkBinary(); - - bool linkBinaryRecursion; -}; - -namespace { - void freeProgramFunc(QOpenGLFunctions *funcs, GLuint id) - { - funcs->glDeleteProgram(id); - } -} - - -QOpenGLShaderProgramPrivate::~QOpenGLShaderProgramPrivate() -{ - delete glfuncs; - if (programGuard) - programGuard->free(); -} - -bool QOpenGLShaderProgramPrivate::hasShader(QOpenGLShader::ShaderType type) const -{ - for (QOpenGLShader *shader : shaders) { - if (shader->shaderType() == type) - return true; - } - return false; -} - -/*! - Constructs a new shader program and attaches it to \a parent. - The program will be invalid until addShader() is called. - - The shader program will be associated with the current QOpenGLContext. - - \sa addShader() -*/ -QOpenGLShaderProgram::QOpenGLShaderProgram(QObject *parent) - : QObject(*new QOpenGLShaderProgramPrivate, parent) -{ -} - -/*! - Deletes this shader program. -*/ -QOpenGLShaderProgram::~QOpenGLShaderProgram() -{ -} - -/*! - Requests the shader program's id to be created immediately. Returns \c true - if successful; \c false otherwise. - - This function is primarily useful when combining QOpenGLShaderProgram - with other OpenGL functions that operate directly on the shader - program id, like \c {GL_OES_get_program_binary}. - - When the shader program is used normally, the shader program's id will - be created on demand. - - \sa programId() - - \since 5.3 - */ -bool QOpenGLShaderProgram::create() -{ - return init(); -} - -bool QOpenGLShaderProgram::init() -{ - Q_D(QOpenGLShaderProgram); - if ((d->programGuard && d->programGuard->id()) || d->inited) - return true; - d->inited = true; - QOpenGLContext *context = const_cast(QOpenGLContext::currentContext()); - if (!context) - return false; - d->glfuncs->initializeOpenGLFunctions(); - -#ifndef QT_OPENGL_ES_2 - if (!context->isOpenGLES() && context->format().version() >= qMakePair(4, 0)) { - d->tessellationFuncs = context->versionFunctions(); - d->tessellationFuncs->initializeOpenGLFunctions(); - } -#endif - - GLuint program = d->glfuncs->glCreateProgram(); - if (!program) { - qWarning("QOpenGLShaderProgram: could not create shader program"); - return false; - } - if (d->programGuard) - delete d->programGuard; - d->programGuard = new QOpenGLSharedResourceGuard(context, program, freeProgramFunc); - return true; -} - -/*! - Adds a compiled \a shader to this shader program. Returns \c true - if the shader could be added, or false otherwise. - - Ownership of the \a shader object remains with the caller. - It will not be deleted when this QOpenGLShaderProgram instance - is deleted. This allows the caller to add the same shader - to multiple shader programs. - - \sa addShaderFromSourceCode(), addShaderFromSourceFile() - \sa removeShader(), link(), removeAllShaders() -*/ -bool QOpenGLShaderProgram::addShader(QOpenGLShader *shader) -{ - Q_D(QOpenGLShaderProgram); - if (!init()) - return false; - if (d->shaders.contains(shader)) - return true; // Already added to this shader program. - if (d->programGuard && d->programGuard->id() && shader) { - if (!shader->d_func()->shaderGuard || !shader->d_func()->shaderGuard->id()) - return false; - if (d->programGuard->group() != shader->d_func()->shaderGuard->group()) { - qWarning("QOpenGLShaderProgram::addShader: Program and shader are not associated with same context."); - return false; - } - d->glfuncs->glAttachShader(d->programGuard->id(), shader->d_func()->shaderGuard->id()); - d->linked = false; // Program needs to be relinked. - d->shaders.append(shader); - connect(shader, SIGNAL(destroyed()), this, SLOT(shaderDestroyed())); - return true; - } else { - return false; - } -} - -/*! - Compiles \a source as a shader of the specified \a type and - adds it to this shader program. Returns \c true if compilation - was successful, false otherwise. The compilation errors - and warnings will be made available via log(). - - This function is intended to be a short-cut for quickly - adding vertex and fragment shaders to a shader program without - creating an instance of QOpenGLShader first. - - \sa addShader(), addShaderFromSourceFile() - \sa removeShader(), link(), log(), removeAllShaders() -*/ -bool QOpenGLShaderProgram::addShaderFromSourceCode(QOpenGLShader::ShaderType type, const char *source) -{ - Q_D(QOpenGLShaderProgram); - if (!init()) - return false; - QOpenGLShader *shader = new QOpenGLShader(type, this); - if (!shader->compileSourceCode(source)) { - d->log = shader->log(); - delete shader; - return false; - } - d->anonShaders.append(shader); - return addShader(shader); -} - -/*! - \overload - - Compiles \a source as a shader of the specified \a type and - adds it to this shader program. Returns \c true if compilation - was successful, false otherwise. The compilation errors - and warnings will be made available via log(). - - This function is intended to be a short-cut for quickly - adding vertex and fragment shaders to a shader program without - creating an instance of QOpenGLShader first. - - \sa addShader(), addShaderFromSourceFile() - \sa removeShader(), link(), log(), removeAllShaders() -*/ -bool QOpenGLShaderProgram::addShaderFromSourceCode(QOpenGLShader::ShaderType type, const QByteArray& source) -{ - return addShaderFromSourceCode(type, source.constData()); -} - -/*! - \overload - - Compiles \a source as a shader of the specified \a type and - adds it to this shader program. Returns \c true if compilation - was successful, false otherwise. The compilation errors - and warnings will be made available via log(). - - This function is intended to be a short-cut for quickly - adding vertex and fragment shaders to a shader program without - creating an instance of QOpenGLShader first. - - \sa addShader(), addShaderFromSourceFile() - \sa removeShader(), link(), log(), removeAllShaders() -*/ -bool QOpenGLShaderProgram::addShaderFromSourceCode(QOpenGLShader::ShaderType type, const QString& source) -{ - return addShaderFromSourceCode(type, source.toLatin1().constData()); -} - -/*! - Compiles the contents of \a fileName as a shader of the specified - \a type and adds it to this shader program. Returns \c true if - compilation was successful, false otherwise. The compilation errors - and warnings will be made available via log(). - - This function is intended to be a short-cut for quickly - adding vertex and fragment shaders to a shader program without - creating an instance of QOpenGLShader first. - - \sa addShader(), addShaderFromSourceCode() -*/ -bool QOpenGLShaderProgram::addShaderFromSourceFile - (QOpenGLShader::ShaderType type, const QString& fileName) -{ - Q_D(QOpenGLShaderProgram); - if (!init()) - return false; - QOpenGLShader *shader = new QOpenGLShader(type, this); - if (!shader->compileSourceFile(fileName)) { - d->log = shader->log(); - delete shader; - return false; - } - d->anonShaders.append(shader); - return addShader(shader); -} - -/*! - Registers the shader of the specified \a type and \a source to this - program. Unlike addShaderFromSourceCode(), this function does not perform - compilation. Compilation is deferred to link(), and may not happen at all, - because link() may potentially use a program binary from Qt's shader disk - cache. This will typically lead to a significant increase in performance. - - \return true if the shader has been registered or, in the non-cached case, - compiled successfully; false if there was an error. The compilation error - messages can be retrieved via log(). - - When the disk cache is disabled, via Qt::AA_DisableShaderDiskCache for - example, or the OpenGL context has no support for context binaries, calling - this function is equivalent to addShaderFromSourceCode(). - - \since 5.9 - \sa addShaderFromSourceCode(), addCacheableShaderFromSourceFile() - */ -bool QOpenGLShaderProgram::addCacheableShaderFromSourceCode(QOpenGLShader::ShaderType type, const char *source) -{ - Q_D(QOpenGLShaderProgram); - if (!init()) - return false; - if (d->isCacheDisabled()) - return addShaderFromSourceCode(type, source); - - return addCacheableShaderFromSourceCode(type, QByteArray(source)); -} - -static inline QShader::Stage qt_shaderTypeToStage(QOpenGLShader::ShaderType type) -{ - switch (type) { - case QOpenGLShader::Vertex: - return QShader::VertexStage; - case QOpenGLShader::Fragment: - return QShader::FragmentStage; - case QOpenGLShader::Geometry: - return QShader::GeometryStage; - case QOpenGLShader::TessellationControl: - return QShader::TessellationControlStage; - case QOpenGLShader::TessellationEvaluation: - return QShader::TessellationEvaluationStage; - case QOpenGLShader::Compute: - return QShader::ComputeStage; - } - return QShader::VertexStage; -} - -static inline QOpenGLShader::ShaderType qt_shaderStageToType(QShader::Stage stage) -{ - switch (stage) { - case QShader::VertexStage: - return QOpenGLShader::Vertex; - case QShader::TessellationControlStage: - return QOpenGLShader::TessellationControl; - case QShader::TessellationEvaluationStage: - return QOpenGLShader::TessellationEvaluation; - case QShader::GeometryStage: - return QOpenGLShader::Geometry; - case QShader::FragmentStage: - return QOpenGLShader::Fragment; - case QShader::ComputeStage: - return QOpenGLShader::Compute; - } - return QOpenGLShader::Vertex; -} - -/*! - \overload - - Registers the shader of the specified \a type and \a source to this - program. Unlike addShaderFromSourceCode(), this function does not perform - compilation. Compilation is deferred to link(), and may not happen at all, - because link() may potentially use a program binary from Qt's shader disk - cache. This will typically lead to a significant increase in performance. - - \return true if the shader has been registered or, in the non-cached case, - compiled successfully; false if there was an error. The compilation error - messages can be retrieved via log(). - - When the disk cache is disabled, via Qt::AA_DisableShaderDiskCache for - example, or the OpenGL context has no support for context binaries, calling - this function is equivalent to addShaderFromSourceCode(). - - \since 5.9 - \sa addShaderFromSourceCode(), addCacheableShaderFromSourceFile() - */ -bool QOpenGLShaderProgram::addCacheableShaderFromSourceCode(QOpenGLShader::ShaderType type, const QByteArray &source) -{ - Q_D(QOpenGLShaderProgram); - if (!init()) - return false; - if (d->isCacheDisabled()) - return addShaderFromSourceCode(type, source); - - d->binaryProgram.shaders.append(QOpenGLProgramBinaryCache::ShaderDesc(qt_shaderTypeToStage(type), source)); - return true; -} - -/*! - \overload - - Registers the shader of the specified \a type and \a source to this - program. Unlike addShaderFromSourceCode(), this function does not perform - compilation. Compilation is deferred to link(), and may not happen at all, - because link() may potentially use a program binary from Qt's shader disk - cache. This will typically lead to a significant increase in performance. - - When the disk cache is disabled, via Qt::AA_DisableShaderDiskCache for - example, or the OpenGL context has no support for context binaries, calling - this function is equivalent to addShaderFromSourceCode(). - - \since 5.9 - \sa addShaderFromSourceCode(), addCacheableShaderFromSourceFile() - */ -bool QOpenGLShaderProgram::addCacheableShaderFromSourceCode(QOpenGLShader::ShaderType type, const QString &source) -{ - Q_D(QOpenGLShaderProgram); - if (!init()) - return false; - if (d->isCacheDisabled()) - return addShaderFromSourceCode(type, source); - - return addCacheableShaderFromSourceCode(type, source.toUtf8().constData()); -} - -/*! - Registers the shader of the specified \a type and \a fileName to this - program. Unlike addShaderFromSourceFile(), this function does not perform - compilation. Compilation is deferred to link(), and may not happen at all, - because link() may potentially use a program binary from Qt's shader disk - cache. This will typically lead to a significant increase in performance. - - \return true if the file has been read successfully, false if the file could - not be opened or the normal, non-cached compilation of the shader has - failed. The compilation error messages can be retrieved via log(). - - When the disk cache is disabled, via Qt::AA_DisableShaderDiskCache for - example, or the OpenGL context has no support for context binaries, calling - this function is equivalent to addShaderFromSourceFile(). - - \since 5.9 - \sa addShaderFromSourceFile(), addCacheableShaderFromSourceCode() - */ -bool QOpenGLShaderProgram::addCacheableShaderFromSourceFile(QOpenGLShader::ShaderType type, const QString &fileName) -{ - Q_D(QOpenGLShaderProgram); - if (!init()) - return false; - if (d->isCacheDisabled()) - return addShaderFromSourceFile(type, fileName); - - QOpenGLProgramBinaryCache::ShaderDesc shader(qt_shaderTypeToStage(type)); - // NB! It could be tempting to defer reading the file contents and just - // hash the filename as the cache key, perhaps combined with last-modified - // timestamp checks. However, this would raise a number of issues (no - // timestamps for files in the resource system; preference for global, not - // per-application cache items (where filenames may clash); resource-based - // shaders from libraries like Qt Quick; etc.), so just avoid it. - QFile f(fileName); - if (f.open(QIODevice::ReadOnly | QIODevice::Text)) { - shader.source = f.readAll(); - f.close(); - } else { - qWarning("QOpenGLShaderProgram: Unable to open file %s", qPrintable(fileName)); - return false; - } - d->binaryProgram.shaders.append(shader); - return true; -} - -/*! - Removes \a shader from this shader program. The object is not deleted. - - The shader program must be valid in the current QOpenGLContext. - - \sa addShader(), link(), removeAllShaders() -*/ -void QOpenGLShaderProgram::removeShader(QOpenGLShader *shader) -{ - Q_D(QOpenGLShaderProgram); - if (d->programGuard && d->programGuard->id() - && shader && shader->d_func()->shaderGuard) - { - d->glfuncs->glDetachShader(d->programGuard->id(), shader->d_func()->shaderGuard->id()); - } - d->linked = false; // Program needs to be relinked. - if (shader) { - d->shaders.removeAll(shader); - d->anonShaders.removeAll(shader); - disconnect(shader, SIGNAL(destroyed()), this, SLOT(shaderDestroyed())); - } -} - -/*! - Returns a list of all shaders that have been added to this shader - program using addShader(). - - \sa addShader(), removeShader() -*/ -QList QOpenGLShaderProgram::shaders() const -{ - Q_D(const QOpenGLShaderProgram); - return d->shaders; -} - -/*! - Removes all of the shaders that were added to this program previously. - The QOpenGLShader objects for the shaders will not be deleted if they - were constructed externally. QOpenGLShader objects that are constructed - internally by QOpenGLShaderProgram will be deleted. - - \sa addShader(), removeShader() -*/ -void QOpenGLShaderProgram::removeAllShaders() -{ - Q_D(QOpenGLShaderProgram); - d->removingShaders = true; - for (QOpenGLShader *shader : qAsConst(d->shaders)) { - if (d->programGuard && d->programGuard->id() - && shader && shader->d_func()->shaderGuard) - { - d->glfuncs->glDetachShader(d->programGuard->id(), shader->d_func()->shaderGuard->id()); - } - } - // Delete shader objects that were created anonymously. - qDeleteAll(d->anonShaders); - d->shaders.clear(); - d->anonShaders.clear(); - d->binaryProgram = QOpenGLProgramBinaryCache::ProgramDesc(); - d->linked = false; // Program needs to be relinked. - d->removingShaders = false; -} - -/*! - Links together the shaders that were added to this program with - addShader(). Returns \c true if the link was successful or - false otherwise. If the link failed, the error messages can - be retrieved with log(). - - Subclasses can override this function to initialize attributes - and uniform variables for use in specific shader programs. - - If the shader program was already linked, calling this - function again will force it to be re-linked. - - When shaders were added to this program via - addCacheableShaderFromSourceCode() or addCacheableShaderFromSourceFile(), - program binaries are supported, and a cached binary is available on disk, - actual compilation and linking are skipped. Instead, link() will initialize - the program with the binary blob via glProgramBinary(). If there is no - cached version of the program or it was generated with a different driver - version, the shaders will be compiled from source and the program will get - linked normally. This allows seamless upgrading of the graphics drivers, - without having to worry about potentially incompatible binary formats. - - \sa addShader(), log() -*/ -bool QOpenGLShaderProgram::link() -{ - Q_D(QOpenGLShaderProgram); - GLuint program = d->programGuard ? d->programGuard->id() : 0; - if (!program) - return false; - - if (!d->linkBinaryRecursion && d->shaders.isEmpty() && !d->binaryProgram.shaders.isEmpty()) - return d->linkBinary(); - - GLint value; - if (d->shaders.isEmpty()) { - // If there are no explicit shaders, then it is possible that the - // application added a program binary with glProgramBinaryOES(), or - // otherwise populated the shaders itself. This is also the case when - // we are recursively called back from linkBinary() after a successful - // glProgramBinary(). Check to see if the program is already linked and - // bail out if so. - value = 0; - d->glfuncs->glGetProgramiv(program, GL_LINK_STATUS, &value); - d->linked = (value != 0); - if (d->linked) - return true; - } - - d->glfuncs->glLinkProgram(program); - value = 0; - d->glfuncs->glGetProgramiv(program, GL_LINK_STATUS, &value); - d->linked = (value != 0); - value = 0; - d->glfuncs->glGetProgramiv(program, GL_INFO_LOG_LENGTH, &value); - d->log = QString(); - if (value > 1) { - char *logbuf = new char [value]; - GLint len; - d->glfuncs->glGetProgramInfoLog(program, value, &len, logbuf); - d->log = QString::fromLatin1(logbuf); - if (!d->linked && !d->linkBinaryRecursion) { - QString name = objectName(); - if (name.isEmpty()) - qWarning("QOpenGLShader::link: %ls", qUtf16Printable(d->log)); - else - qWarning("QOpenGLShader::link[%ls]: %ls", qUtf16Printable(name), qUtf16Printable(d->log)); - } - delete [] logbuf; - } - return d->linked; -} - -/*! - Returns \c true if this shader program has been linked; false otherwise. - - \sa link() -*/ -bool QOpenGLShaderProgram::isLinked() const -{ - Q_D(const QOpenGLShaderProgram); - return d->linked; -} - -/*! - Returns the errors and warnings that occurred during the last link() - or addShader() with explicitly specified source code. - - \sa link() -*/ -QString QOpenGLShaderProgram::log() const -{ - Q_D(const QOpenGLShaderProgram); - return d->log; -} - -/*! - Binds this shader program to the active QOpenGLContext and makes - it the current shader program. Any previously bound shader program - is released. This is equivalent to calling \c{glUseProgram()} on - programId(). Returns \c true if the program was successfully bound; - false otherwise. If the shader program has not yet been linked, - or it needs to be re-linked, this function will call link(). - - \sa link(), release() -*/ -bool QOpenGLShaderProgram::bind() -{ - Q_D(QOpenGLShaderProgram); - GLuint program = d->programGuard ? d->programGuard->id() : 0; - if (!program) - return false; - if (!d->linked && !link()) - return false; -#ifndef QT_NO_DEBUG - if (d->programGuard->group() != QOpenGLContextGroup::currentContextGroup()) { - qWarning("QOpenGLShaderProgram::bind: program is not valid in the current context."); - return false; - } -#endif - d->glfuncs->glUseProgram(program); - return true; -} - -/*! - Releases the active shader program from the current QOpenGLContext. - This is equivalent to calling \c{glUseProgram(0)}. - - \sa bind() -*/ -void QOpenGLShaderProgram::release() -{ - Q_D(QOpenGLShaderProgram); -#ifndef QT_NO_DEBUG - if (d->programGuard && d->programGuard->group() != QOpenGLContextGroup::currentContextGroup()) - qWarning("QOpenGLShaderProgram::release: program is not valid in the current context."); -#endif - d->glfuncs->glUseProgram(0); -} - -/*! - Returns the OpenGL identifier associated with this shader program. - - \sa QOpenGLShader::shaderId() -*/ -GLuint QOpenGLShaderProgram::programId() const -{ - Q_D(const QOpenGLShaderProgram); - GLuint id = d->programGuard ? d->programGuard->id() : 0; - if (id) - return id; - - // Create the identifier if we don't have one yet. This is for - // applications that want to create the attached shader configuration - // themselves, particularly those using program binaries. - if (!const_cast(this)->init()) - return 0; - return d->programGuard ? d->programGuard->id() : 0; -} - -/*! - Binds the attribute \a name to the specified \a location. This - function can be called before or after the program has been linked. - Any attributes that have not been explicitly bound when the program - is linked will be assigned locations automatically. - - When this function is called after the program has been linked, - the program will need to be relinked for the change to take effect. - - \sa attributeLocation() -*/ -void QOpenGLShaderProgram::bindAttributeLocation(const char *name, int location) -{ - Q_D(QOpenGLShaderProgram); - if (!init() || !d->programGuard || !d->programGuard->id()) - return; - d->glfuncs->glBindAttribLocation(d->programGuard->id(), location, name); - d->linked = false; // Program needs to be relinked. -} - -/*! - \overload - - Binds the attribute \a name to the specified \a location. This - function can be called before or after the program has been linked. - Any attributes that have not been explicitly bound when the program - is linked will be assigned locations automatically. - - When this function is called after the program has been linked, - the program will need to be relinked for the change to take effect. - - \sa attributeLocation() -*/ -void QOpenGLShaderProgram::bindAttributeLocation(const QByteArray& name, int location) -{ - bindAttributeLocation(name.constData(), location); -} - -/*! - \overload - - Binds the attribute \a name to the specified \a location. This - function can be called before or after the program has been linked. - Any attributes that have not been explicitly bound when the program - is linked will be assigned locations automatically. - - When this function is called after the program has been linked, - the program will need to be relinked for the change to take effect. - - \sa attributeLocation() -*/ -void QOpenGLShaderProgram::bindAttributeLocation(const QString& name, int location) -{ - bindAttributeLocation(name.toLatin1().constData(), location); -} - -/*! - Returns the location of the attribute \a name within this shader - program's parameter list. Returns -1 if \a name is not a valid - attribute for this shader program. - - \sa uniformLocation(), bindAttributeLocation() -*/ -int QOpenGLShaderProgram::attributeLocation(const char *name) const -{ - Q_D(const QOpenGLShaderProgram); - if (d->linked && d->programGuard && d->programGuard->id()) { - return d->glfuncs->glGetAttribLocation(d->programGuard->id(), name); - } else { - qWarning("QOpenGLShaderProgram::attributeLocation(%s): shader program is not linked", name); - return -1; - } -} - -/*! - \overload - - Returns the location of the attribute \a name within this shader - program's parameter list. Returns -1 if \a name is not a valid - attribute for this shader program. - - \sa uniformLocation(), bindAttributeLocation() -*/ -int QOpenGLShaderProgram::attributeLocation(const QByteArray& name) const -{ - return attributeLocation(name.constData()); -} - -/*! - \overload - - Returns the location of the attribute \a name within this shader - program's parameter list. Returns -1 if \a name is not a valid - attribute for this shader program. - - \sa uniformLocation(), bindAttributeLocation() -*/ -int QOpenGLShaderProgram::attributeLocation(const QString& name) const -{ - return attributeLocation(name.toLatin1().constData()); -} - -/*! - Sets the attribute at \a location in the current context to \a value. - - \sa setUniformValue() -*/ -void QOpenGLShaderProgram::setAttributeValue(int location, GLfloat value) -{ - Q_D(QOpenGLShaderProgram); - if (location != -1) - d->glfuncs->glVertexAttrib1fv(location, &value); -} - -/*! - \overload - - Sets the attribute called \a name in the current context to \a value. - - \sa setUniformValue() -*/ -void QOpenGLShaderProgram::setAttributeValue(const char *name, GLfloat value) -{ - setAttributeValue(attributeLocation(name), value); -} - -/*! - Sets the attribute at \a location in the current context to - the 2D vector (\a x, \a y). - - \sa setUniformValue() -*/ -void QOpenGLShaderProgram::setAttributeValue(int location, GLfloat x, GLfloat y) -{ - Q_D(QOpenGLShaderProgram); - if (location != -1) { - GLfloat values[2] = {x, y}; - d->glfuncs->glVertexAttrib2fv(location, values); - } -} - -/*! - \overload - - Sets the attribute called \a name in the current context to - the 2D vector (\a x, \a y). - - \sa setUniformValue() -*/ -void QOpenGLShaderProgram::setAttributeValue(const char *name, GLfloat x, GLfloat y) -{ - setAttributeValue(attributeLocation(name), x, y); -} - -/*! - Sets the attribute at \a location in the current context to - the 3D vector (\a x, \a y, \a z). - - \sa setUniformValue() -*/ -void QOpenGLShaderProgram::setAttributeValue - (int location, GLfloat x, GLfloat y, GLfloat z) -{ - Q_D(QOpenGLShaderProgram); - Q_UNUSED(d); - if (location != -1) { - GLfloat values[3] = {x, y, z}; - d->glfuncs->glVertexAttrib3fv(location, values); - } -} - -/*! - \overload - - Sets the attribute called \a name in the current context to - the 3D vector (\a x, \a y, \a z). - - \sa setUniformValue() -*/ -void QOpenGLShaderProgram::setAttributeValue - (const char *name, GLfloat x, GLfloat y, GLfloat z) -{ - setAttributeValue(attributeLocation(name), x, y, z); -} - -/*! - Sets the attribute at \a location in the current context to - the 4D vector (\a x, \a y, \a z, \a w). - - \sa setUniformValue() -*/ -void QOpenGLShaderProgram::setAttributeValue - (int location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) -{ - Q_D(QOpenGLShaderProgram); - if (location != -1) { - GLfloat values[4] = {x, y, z, w}; - d->glfuncs->glVertexAttrib4fv(location, values); - } -} - -/*! - \overload - - Sets the attribute called \a name in the current context to - the 4D vector (\a x, \a y, \a z, \a w). - - \sa setUniformValue() -*/ -void QOpenGLShaderProgram::setAttributeValue - (const char *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w) -{ - setAttributeValue(attributeLocation(name), x, y, z, w); -} - -/*! - Sets the attribute at \a location in the current context to \a value. - - \sa setUniformValue() -*/ -void QOpenGLShaderProgram::setAttributeValue(int location, const QVector2D& value) -{ - Q_D(QOpenGLShaderProgram); - if (location != -1) - d->glfuncs->glVertexAttrib2fv(location, reinterpret_cast(&value)); -} - -/*! - \overload - - Sets the attribute called \a name in the current context to \a value. - - \sa setUniformValue() -*/ -void QOpenGLShaderProgram::setAttributeValue(const char *name, const QVector2D& value) -{ - setAttributeValue(attributeLocation(name), value); -} - -/*! - Sets the attribute at \a location in the current context to \a value. - - \sa setUniformValue() -*/ -void QOpenGLShaderProgram::setAttributeValue(int location, const QVector3D& value) -{ - Q_D(QOpenGLShaderProgram); - Q_UNUSED(d); - if (location != -1) - d->glfuncs->glVertexAttrib3fv(location, reinterpret_cast(&value)); -} - -/*! - \overload - - Sets the attribute called \a name in the current context to \a value. - - \sa setUniformValue() -*/ -void QOpenGLShaderProgram::setAttributeValue(const char *name, const QVector3D& value) -{ - setAttributeValue(attributeLocation(name), value); -} - -/*! - Sets the attribute at \a location in the current context to \a value. - - \sa setUniformValue() -*/ -void QOpenGLShaderProgram::setAttributeValue(int location, const QVector4D& value) -{ - Q_D(QOpenGLShaderProgram); - Q_UNUSED(d); - if (location != -1) - d->glfuncs->glVertexAttrib4fv(location, reinterpret_cast(&value)); -} - -/*! - \overload - - Sets the attribute called \a name in the current context to \a value. - - \sa setUniformValue() -*/ -void QOpenGLShaderProgram::setAttributeValue(const char *name, const QVector4D& value) -{ - setAttributeValue(attributeLocation(name), value); -} - -/*! - Sets the attribute at \a location in the current context to \a value. - - \sa setUniformValue() -*/ -void QOpenGLShaderProgram::setAttributeValue(int location, const QColor& value) -{ - Q_D(QOpenGLShaderProgram); - Q_UNUSED(d); - if (location != -1) { - GLfloat values[4] = {GLfloat(value.redF()), GLfloat(value.greenF()), - GLfloat(value.blueF()), GLfloat(value.alphaF())}; - d->glfuncs->glVertexAttrib4fv(location, values); - } -} - -/*! - \overload - - Sets the attribute called \a name in the current context to \a value. - - \sa setUniformValue() -*/ -void QOpenGLShaderProgram::setAttributeValue(const char *name, const QColor& value) -{ - setAttributeValue(attributeLocation(name), value); -} - -/*! - Sets the attribute at \a location in the current context to the - contents of \a values, which contains \a columns elements, each - consisting of \a rows elements. The \a rows value should be - 1, 2, 3, or 4. This function is typically used to set matrix - values and column vectors. - - \sa setUniformValue() -*/ -void QOpenGLShaderProgram::setAttributeValue - (int location, const GLfloat *values, int columns, int rows) -{ - Q_D(QOpenGLShaderProgram); - Q_UNUSED(d); - if (rows < 1 || rows > 4) { - qWarning("QOpenGLShaderProgram::setAttributeValue: rows %d not supported", rows); - return; - } - if (location != -1) { - while (columns-- > 0) { - if (rows == 1) - d->glfuncs->glVertexAttrib1fv(location, values); - else if (rows == 2) - d->glfuncs->glVertexAttrib2fv(location, values); - else if (rows == 3) - d->glfuncs->glVertexAttrib3fv(location, values); - else - d->glfuncs->glVertexAttrib4fv(location, values); - values += rows; - ++location; - } - } -} - -/*! - \overload - - Sets the attribute called \a name in the current context to the - contents of \a values, which contains \a columns elements, each - consisting of \a rows elements. The \a rows value should be - 1, 2, 3, or 4. This function is typically used to set matrix - values and column vectors. - - \sa setUniformValue() -*/ -void QOpenGLShaderProgram::setAttributeValue - (const char *name, const GLfloat *values, int columns, int rows) -{ - setAttributeValue(attributeLocation(name), values, columns, rows); -} - -/*! - Sets an array of vertex \a values on the attribute at \a location - in this shader program. The \a tupleSize indicates the number of - components per vertex (1, 2, 3, or 4), and the \a stride indicates - the number of bytes between vertices. A default \a stride value - of zero indicates that the vertices are densely packed in \a values. - - The array will become active when enableAttributeArray() is called - on the \a location. Otherwise the value specified with - setAttributeValue() for \a location will be used. - - \sa setAttributeValue(), setUniformValue(), enableAttributeArray() - \sa disableAttributeArray() -*/ -void QOpenGLShaderProgram::setAttributeArray - (int location, const GLfloat *values, int tupleSize, int stride) -{ - Q_D(QOpenGLShaderProgram); - Q_UNUSED(d); - if (location != -1) { - d->glfuncs->glVertexAttribPointer(location, tupleSize, GL_FLOAT, GL_FALSE, - stride, values); - } -} - -/*! - Sets an array of 2D vertex \a values on the attribute at \a location - in this shader program. The \a stride indicates the number of bytes - between vertices. A default \a stride value of zero indicates that - the vertices are densely packed in \a values. - - The array will become active when enableAttributeArray() is called - on the \a location. Otherwise the value specified with - setAttributeValue() for \a location will be used. - - \sa setAttributeValue(), setUniformValue(), enableAttributeArray() - \sa disableAttributeArray() -*/ -void QOpenGLShaderProgram::setAttributeArray - (int location, const QVector2D *values, int stride) -{ - Q_D(QOpenGLShaderProgram); - Q_UNUSED(d); - if (location != -1) { - d->glfuncs->glVertexAttribPointer(location, 2, GL_FLOAT, GL_FALSE, - stride, values); - } -} - -/*! - Sets an array of 3D vertex \a values on the attribute at \a location - in this shader program. The \a stride indicates the number of bytes - between vertices. A default \a stride value of zero indicates that - the vertices are densely packed in \a values. - - The array will become active when enableAttributeArray() is called - on the \a location. Otherwise the value specified with - setAttributeValue() for \a location will be used. - - \sa setAttributeValue(), setUniformValue(), enableAttributeArray() - \sa disableAttributeArray() -*/ -void QOpenGLShaderProgram::setAttributeArray - (int location, const QVector3D *values, int stride) -{ - Q_D(QOpenGLShaderProgram); - Q_UNUSED(d); - if (location != -1) { - d->glfuncs->glVertexAttribPointer(location, 3, GL_FLOAT, GL_FALSE, - stride, values); - } -} - -/*! - Sets an array of 4D vertex \a values on the attribute at \a location - in this shader program. The \a stride indicates the number of bytes - between vertices. A default \a stride value of zero indicates that - the vertices are densely packed in \a values. - - The array will become active when enableAttributeArray() is called - on the \a location. Otherwise the value specified with - setAttributeValue() for \a location will be used. - - \sa setAttributeValue(), setUniformValue(), enableAttributeArray() - \sa disableAttributeArray() -*/ -void QOpenGLShaderProgram::setAttributeArray - (int location, const QVector4D *values, int stride) -{ - Q_D(QOpenGLShaderProgram); - Q_UNUSED(d); - if (location != -1) { - d->glfuncs->glVertexAttribPointer(location, 4, GL_FLOAT, GL_FALSE, - stride, values); - } -} - -/*! - Sets an array of vertex \a values on the attribute at \a location - in this shader program. The \a stride indicates the number of bytes - between vertices. A default \a stride value of zero indicates that - the vertices are densely packed in \a values. - - The \a type indicates the type of elements in the \a values array, - usually \c{GL_FLOAT}, \c{GL_UNSIGNED_BYTE}, etc. The \a tupleSize - indicates the number of components per vertex: 1, 2, 3, or 4. - - The array will become active when enableAttributeArray() is called - on the \a location. Otherwise the value specified with - setAttributeValue() for \a location will be used. - - The setAttributeBuffer() function can be used to set the attribute - array to an offset within a vertex buffer. - - \note Normalization will be enabled. If this is not desired, call - glVertexAttribPointer directly through QOpenGLFunctions. - - \sa setAttributeValue(), setUniformValue(), enableAttributeArray() - \sa disableAttributeArray(), setAttributeBuffer() -*/ -void QOpenGLShaderProgram::setAttributeArray - (int location, GLenum type, const void *values, int tupleSize, int stride) -{ - Q_D(QOpenGLShaderProgram); - Q_UNUSED(d); - if (location != -1) { - d->glfuncs->glVertexAttribPointer(location, tupleSize, type, GL_TRUE, - stride, values); - } -} - -/*! - \overload - - Sets an array of vertex \a values on the attribute called \a name - in this shader program. The \a tupleSize indicates the number of - components per vertex (1, 2, 3, or 4), and the \a stride indicates - the number of bytes between vertices. A default \a stride value - of zero indicates that the vertices are densely packed in \a values. - - The array will become active when enableAttributeArray() is called - on \a name. Otherwise the value specified with setAttributeValue() - for \a name will be used. - - \sa setAttributeValue(), setUniformValue(), enableAttributeArray() - \sa disableAttributeArray() -*/ -void QOpenGLShaderProgram::setAttributeArray - (const char *name, const GLfloat *values, int tupleSize, int stride) -{ - setAttributeArray(attributeLocation(name), values, tupleSize, stride); -} - -/*! - \overload - - Sets an array of 2D vertex \a values on the attribute called \a name - in this shader program. The \a stride indicates the number of bytes - between vertices. A default \a stride value of zero indicates that - the vertices are densely packed in \a values. - - The array will become active when enableAttributeArray() is called - on \a name. Otherwise the value specified with setAttributeValue() - for \a name will be used. - - \sa setAttributeValue(), setUniformValue(), enableAttributeArray() - \sa disableAttributeArray() -*/ -void QOpenGLShaderProgram::setAttributeArray - (const char *name, const QVector2D *values, int stride) -{ - setAttributeArray(attributeLocation(name), values, stride); -} - -/*! - \overload - - Sets an array of 3D vertex \a values on the attribute called \a name - in this shader program. The \a stride indicates the number of bytes - between vertices. A default \a stride value of zero indicates that - the vertices are densely packed in \a values. - - The array will become active when enableAttributeArray() is called - on \a name. Otherwise the value specified with setAttributeValue() - for \a name will be used. - - \sa setAttributeValue(), setUniformValue(), enableAttributeArray() - \sa disableAttributeArray() -*/ -void QOpenGLShaderProgram::setAttributeArray - (const char *name, const QVector3D *values, int stride) -{ - setAttributeArray(attributeLocation(name), values, stride); -} - -/*! - \overload - - Sets an array of 4D vertex \a values on the attribute called \a name - in this shader program. The \a stride indicates the number of bytes - between vertices. A default \a stride value of zero indicates that - the vertices are densely packed in \a values. - - The array will become active when enableAttributeArray() is called - on \a name. Otherwise the value specified with setAttributeValue() - for \a name will be used. - - \sa setAttributeValue(), setUniformValue(), enableAttributeArray() - \sa disableAttributeArray() -*/ -void QOpenGLShaderProgram::setAttributeArray - (const char *name, const QVector4D *values, int stride) -{ - setAttributeArray(attributeLocation(name), values, stride); -} - -/*! - \overload - - Sets an array of vertex \a values on the attribute called \a name - in this shader program. The \a stride indicates the number of bytes - between vertices. A default \a stride value of zero indicates that - the vertices are densely packed in \a values. - - The \a type indicates the type of elements in the \a values array, - usually \c{GL_FLOAT}, \c{GL_UNSIGNED_BYTE}, etc. The \a tupleSize - indicates the number of components per vertex: 1, 2, 3, or 4. - - The array will become active when enableAttributeArray() is called - on the \a name. Otherwise the value specified with - setAttributeValue() for \a name will be used. - - The setAttributeBuffer() function can be used to set the attribute - array to an offset within a vertex buffer. - - \sa setAttributeValue(), setUniformValue(), enableAttributeArray() - \sa disableAttributeArray(), setAttributeBuffer() -*/ -void QOpenGLShaderProgram::setAttributeArray - (const char *name, GLenum type, const void *values, int tupleSize, int stride) -{ - setAttributeArray(attributeLocation(name), type, values, tupleSize, stride); -} - -/*! - Sets an array of vertex values on the attribute at \a location in - this shader program, starting at a specific \a offset in the - currently bound vertex buffer. The \a stride indicates the number - of bytes between vertices. A default \a stride value of zero - indicates that the vertices are densely packed in the value array. - - The \a type indicates the type of elements in the vertex value - array, usually \c{GL_FLOAT}, \c{GL_UNSIGNED_BYTE}, etc. The \a - tupleSize indicates the number of components per vertex: 1, 2, 3, - or 4. - - The array will become active when enableAttributeArray() is called - on the \a location. Otherwise the value specified with - setAttributeValue() for \a location will be used. - - \note Normalization will be enabled. If this is not desired, call - glVertexAttribPointer directly through QOpenGLFunctions. - - \sa setAttributeArray() -*/ -void QOpenGLShaderProgram::setAttributeBuffer - (int location, GLenum type, int offset, int tupleSize, int stride) -{ - Q_D(QOpenGLShaderProgram); - Q_UNUSED(d); - if (location != -1) { - d->glfuncs->glVertexAttribPointer(location, tupleSize, type, GL_TRUE, stride, - reinterpret_cast(qintptr(offset))); - } -} - -/*! - \overload - - Sets an array of vertex values on the attribute called \a name - in this shader program, starting at a specific \a offset in the - currently bound vertex buffer. The \a stride indicates the number - of bytes between vertices. A default \a stride value of zero - indicates that the vertices are densely packed in the value array. - - The \a type indicates the type of elements in the vertex value - array, usually \c{GL_FLOAT}, \c{GL_UNSIGNED_BYTE}, etc. The \a - tupleSize indicates the number of components per vertex: 1, 2, 3, - or 4. - - The array will become active when enableAttributeArray() is called - on the \a name. Otherwise the value specified with - setAttributeValue() for \a name will be used. - - \sa setAttributeArray() -*/ -void QOpenGLShaderProgram::setAttributeBuffer - (const char *name, GLenum type, int offset, int tupleSize, int stride) -{ - setAttributeBuffer(attributeLocation(name), type, offset, tupleSize, stride); -} - -/*! - Enables the vertex array at \a location in this shader program - so that the value set by setAttributeArray() on \a location - will be used by the shader program. - - \sa disableAttributeArray(), setAttributeArray(), setAttributeValue() - \sa setUniformValue() -*/ -void QOpenGLShaderProgram::enableAttributeArray(int location) -{ - Q_D(QOpenGLShaderProgram); - Q_UNUSED(d); - if (location != -1) - d->glfuncs->glEnableVertexAttribArray(location); -} - -/*! - \overload - - Enables the vertex array called \a name in this shader program - so that the value set by setAttributeArray() on \a name - will be used by the shader program. - - \sa disableAttributeArray(), setAttributeArray(), setAttributeValue() - \sa setUniformValue() -*/ -void QOpenGLShaderProgram::enableAttributeArray(const char *name) -{ - enableAttributeArray(attributeLocation(name)); -} - -/*! - Disables the vertex array at \a location in this shader program - that was enabled by a previous call to enableAttributeArray(). - - \sa enableAttributeArray(), setAttributeArray(), setAttributeValue() - \sa setUniformValue() -*/ -void QOpenGLShaderProgram::disableAttributeArray(int location) -{ - Q_D(QOpenGLShaderProgram); - Q_UNUSED(d); - if (location != -1) - d->glfuncs->glDisableVertexAttribArray(location); -} - -/*! - \overload - - Disables the vertex array called \a name in this shader program - that was enabled by a previous call to enableAttributeArray(). - - \sa enableAttributeArray(), setAttributeArray(), setAttributeValue() - \sa setUniformValue() -*/ -void QOpenGLShaderProgram::disableAttributeArray(const char *name) -{ - disableAttributeArray(attributeLocation(name)); -} - -/*! - Returns the location of the uniform variable \a name within this shader - program's parameter list. Returns -1 if \a name is not a valid - uniform variable for this shader program. - - \sa attributeLocation() -*/ -int QOpenGLShaderProgram::uniformLocation(const char *name) const -{ - Q_D(const QOpenGLShaderProgram); - Q_UNUSED(d); - if (d->linked && d->programGuard && d->programGuard->id()) { - return d->glfuncs->glGetUniformLocation(d->programGuard->id(), name); - } else { - qWarning("QOpenGLShaderProgram::uniformLocation(%s): shader program is not linked", name); - return -1; - } -} - -/*! - \overload - - Returns the location of the uniform variable \a name within this shader - program's parameter list. Returns -1 if \a name is not a valid - uniform variable for this shader program. - - \sa attributeLocation() -*/ -int QOpenGLShaderProgram::uniformLocation(const QByteArray& name) const -{ - return uniformLocation(name.constData()); -} - -/*! - \overload - - Returns the location of the uniform variable \a name within this shader - program's parameter list. Returns -1 if \a name is not a valid - uniform variable for this shader program. - - \sa attributeLocation() -*/ -int QOpenGLShaderProgram::uniformLocation(const QString& name) const -{ - return uniformLocation(name.toLatin1().constData()); -} - -/*! - Sets the uniform variable at \a location in the current context to \a value. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValue(int location, GLfloat value) -{ - Q_D(QOpenGLShaderProgram); - Q_UNUSED(d); - if (location != -1) - d->glfuncs->glUniform1fv(location, 1, &value); -} - -/*! - \overload - - Sets the uniform variable called \a name in the current context - to \a value. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValue(const char *name, GLfloat value) -{ - setUniformValue(uniformLocation(name), value); -} - -/*! - Sets the uniform variable at \a location in the current context to \a value. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValue(int location, GLint value) -{ - Q_D(QOpenGLShaderProgram); - Q_UNUSED(d); - if (location != -1) - d->glfuncs->glUniform1i(location, value); -} - -/*! - \overload - - Sets the uniform variable called \a name in the current context - to \a value. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValue(const char *name, GLint value) -{ - setUniformValue(uniformLocation(name), value); -} - -/*! - Sets the uniform variable at \a location in the current context to \a value. - This function should be used when setting sampler values. - - \note This function is not aware of unsigned int support in modern OpenGL - versions and therefore treats \a value as a GLint and calls glUniform1i. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValue(int location, GLuint value) -{ - Q_D(QOpenGLShaderProgram); - Q_UNUSED(d); - if (location != -1) - d->glfuncs->glUniform1i(location, value); -} - -/*! - \overload - - Sets the uniform variable called \a name in the current context - to \a value. This function should be used when setting sampler values. - - \note This function is not aware of unsigned int support in modern OpenGL - versions and therefore treats \a value as a GLint and calls glUniform1i. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValue(const char *name, GLuint value) -{ - setUniformValue(uniformLocation(name), value); -} - -/*! - Sets the uniform variable at \a location in the current context to - the 2D vector (\a x, \a y). - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValue(int location, GLfloat x, GLfloat y) -{ - Q_D(QOpenGLShaderProgram); - Q_UNUSED(d); - if (location != -1) { - GLfloat values[2] = {x, y}; - d->glfuncs->glUniform2fv(location, 1, values); - } -} - -/*! - \overload - - Sets the uniform variable called \a name in the current context to - the 2D vector (\a x, \a y). - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValue(const char *name, GLfloat x, GLfloat y) -{ - setUniformValue(uniformLocation(name), x, y); -} - -/*! - Sets the uniform variable at \a location in the current context to - the 3D vector (\a x, \a y, \a z). - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValue - (int location, GLfloat x, GLfloat y, GLfloat z) -{ - Q_D(QOpenGLShaderProgram); - Q_UNUSED(d); - if (location != -1) { - GLfloat values[3] = {x, y, z}; - d->glfuncs->glUniform3fv(location, 1, values); - } -} - -/*! - \overload - - Sets the uniform variable called \a name in the current context to - the 3D vector (\a x, \a y, \a z). - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValue - (const char *name, GLfloat x, GLfloat y, GLfloat z) -{ - setUniformValue(uniformLocation(name), x, y, z); -} - -/*! - Sets the uniform variable at \a location in the current context to - the 4D vector (\a x, \a y, \a z, \a w). - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValue - (int location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) -{ - Q_D(QOpenGLShaderProgram); - Q_UNUSED(d); - if (location != -1) { - GLfloat values[4] = {x, y, z, w}; - d->glfuncs->glUniform4fv(location, 1, values); - } -} - -/*! - \overload - - Sets the uniform variable called \a name in the current context to - the 4D vector (\a x, \a y, \a z, \a w). - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValue - (const char *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w) -{ - setUniformValue(uniformLocation(name), x, y, z, w); -} - -/*! - Sets the uniform variable at \a location in the current context to \a value. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValue(int location, const QVector2D& value) -{ - Q_D(QOpenGLShaderProgram); - Q_UNUSED(d); - if (location != -1) - d->glfuncs->glUniform2fv(location, 1, reinterpret_cast(&value)); -} - -/*! - \overload - - Sets the uniform variable called \a name in the current context - to \a value. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValue(const char *name, const QVector2D& value) -{ - setUniformValue(uniformLocation(name), value); -} - -/*! - Sets the uniform variable at \a location in the current context to \a value. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValue(int location, const QVector3D& value) -{ - Q_D(QOpenGLShaderProgram); - Q_UNUSED(d); - if (location != -1) - d->glfuncs->glUniform3fv(location, 1, reinterpret_cast(&value)); -} - -/*! - \overload - - Sets the uniform variable called \a name in the current context - to \a value. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValue(const char *name, const QVector3D& value) -{ - setUniformValue(uniformLocation(name), value); -} - -/*! - Sets the uniform variable at \a location in the current context to \a value. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValue(int location, const QVector4D& value) -{ - Q_D(QOpenGLShaderProgram); - Q_UNUSED(d); - if (location != -1) - d->glfuncs->glUniform4fv(location, 1, reinterpret_cast(&value)); -} - -/*! - \overload - - Sets the uniform variable called \a name in the current context - to \a value. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValue(const char *name, const QVector4D& value) -{ - setUniformValue(uniformLocation(name), value); -} - -/*! - Sets the uniform variable at \a location in the current context to - the red, green, blue, and alpha components of \a color. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValue(int location, const QColor& color) -{ - Q_D(QOpenGLShaderProgram); - Q_UNUSED(d); - if (location != -1) { - GLfloat values[4] = {GLfloat(color.redF()), GLfloat(color.greenF()), - GLfloat(color.blueF()), GLfloat(color.alphaF())}; - d->glfuncs->glUniform4fv(location, 1, values); - } -} - -/*! - \overload - - Sets the uniform variable called \a name in the current context to - the red, green, blue, and alpha components of \a color. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValue(const char *name, const QColor& color) -{ - setUniformValue(uniformLocation(name), color); -} - -/*! - Sets the uniform variable at \a location in the current context to - the x and y coordinates of \a point. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValue(int location, const QPoint& point) -{ - Q_D(QOpenGLShaderProgram); - Q_UNUSED(d); - if (location != -1) { - GLfloat values[4] = {GLfloat(point.x()), GLfloat(point.y())}; - d->glfuncs->glUniform2fv(location, 1, values); - } -} - -/*! - \overload - - Sets the uniform variable associated with \a name in the current - context to the x and y coordinates of \a point. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValue(const char *name, const QPoint& point) -{ - setUniformValue(uniformLocation(name), point); -} - -/*! - Sets the uniform variable at \a location in the current context to - the x and y coordinates of \a point. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValue(int location, const QPointF& point) -{ - Q_D(QOpenGLShaderProgram); - Q_UNUSED(d); - if (location != -1) { - GLfloat values[4] = {GLfloat(point.x()), GLfloat(point.y())}; - d->glfuncs->glUniform2fv(location, 1, values); - } -} - -/*! - \overload - - Sets the uniform variable associated with \a name in the current - context to the x and y coordinates of \a point. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValue(const char *name, const QPointF& point) -{ - setUniformValue(uniformLocation(name), point); -} - -/*! - Sets the uniform variable at \a location in the current context to - the width and height of the given \a size. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValue(int location, const QSize& size) -{ - Q_D(QOpenGLShaderProgram); - Q_UNUSED(d); - if (location != -1) { - GLfloat values[4] = {GLfloat(size.width()), GLfloat(size.height())}; - d->glfuncs->glUniform2fv(location, 1, values); - } -} - -/*! - \overload - - Sets the uniform variable associated with \a name in the current - context to the width and height of the given \a size. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValue(const char *name, const QSize& size) -{ - setUniformValue(uniformLocation(name), size); -} - -/*! - Sets the uniform variable at \a location in the current context to - the width and height of the given \a size. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValue(int location, const QSizeF& size) -{ - Q_D(QOpenGLShaderProgram); - Q_UNUSED(d); - if (location != -1) { - GLfloat values[4] = {GLfloat(size.width()), GLfloat(size.height())}; - d->glfuncs->glUniform2fv(location, 1, values); - } -} - -/*! - \overload - - Sets the uniform variable associated with \a name in the current - context to the width and height of the given \a size. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValue(const char *name, const QSizeF& size) -{ - setUniformValue(uniformLocation(name), size); -} - -/*! - Sets the uniform variable at \a location in the current context - to a 2x2 matrix \a value. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValue(int location, const QMatrix2x2& value) -{ - Q_D(QOpenGLShaderProgram); - Q_UNUSED(d); - d->glfuncs->glUniformMatrix2fv(location, 1, GL_FALSE, value.constData()); -} - -/*! - \overload - - Sets the uniform variable called \a name in the current context - to a 2x2 matrix \a value. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValue(const char *name, const QMatrix2x2& value) -{ - setUniformValue(uniformLocation(name), value); -} - -/*! - Sets the uniform variable at \a location in the current context - to a 2x3 matrix \a value. - - \note This function is not aware of non square matrix support, - that is, GLSL types like mat2x3, that is present in modern OpenGL - versions. Instead, it treats the uniform as an array of vec3. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValue(int location, const QMatrix2x3& value) -{ - Q_D(QOpenGLShaderProgram); - Q_UNUSED(d); - d->glfuncs->glUniform3fv(location, 2, value.constData()); -} - -/*! - \overload - - Sets the uniform variable called \a name in the current context - to a 2x3 matrix \a value. - - \note This function is not aware of non square matrix support, - that is, GLSL types like mat2x3, that is present in modern OpenGL - versions. Instead, it treats the uniform as an array of vec3. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValue(const char *name, const QMatrix2x3& value) -{ - setUniformValue(uniformLocation(name), value); -} - -/*! - Sets the uniform variable at \a location in the current context - to a 2x4 matrix \a value. - - \note This function is not aware of non square matrix support, - that is, GLSL types like mat2x4, that is present in modern OpenGL - versions. Instead, it treats the uniform as an array of vec4. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValue(int location, const QMatrix2x4& value) -{ - Q_D(QOpenGLShaderProgram); - Q_UNUSED(d); - d->glfuncs->glUniform4fv(location, 2, value.constData()); -} - -/*! - \overload - - Sets the uniform variable called \a name in the current context - to a 2x4 matrix \a value. - - \note This function is not aware of non square matrix support, - that is, GLSL types like mat2x4, that is present in modern OpenGL - versions. Instead, it treats the uniform as an array of vec4. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValue(const char *name, const QMatrix2x4& value) -{ - setUniformValue(uniformLocation(name), value); -} - -/*! - Sets the uniform variable at \a location in the current context - to a 3x2 matrix \a value. - - \note This function is not aware of non square matrix support, - that is, GLSL types like mat3x2, that is present in modern OpenGL - versions. Instead, it treats the uniform as an array of vec2. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValue(int location, const QMatrix3x2& value) -{ - Q_D(QOpenGLShaderProgram); - Q_UNUSED(d); - d->glfuncs->glUniform2fv(location, 3, value.constData()); -} - -/*! - \overload - - Sets the uniform variable called \a name in the current context - to a 3x2 matrix \a value. - - \note This function is not aware of non square matrix support, - that is, GLSL types like mat3x2, that is present in modern OpenGL - versions. Instead, it treats the uniform as an array of vec2. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValue(const char *name, const QMatrix3x2& value) -{ - setUniformValue(uniformLocation(name), value); -} - -/*! - Sets the uniform variable at \a location in the current context - to a 3x3 matrix \a value. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValue(int location, const QMatrix3x3& value) -{ - Q_D(QOpenGLShaderProgram); - Q_UNUSED(d); - d->glfuncs->glUniformMatrix3fv(location, 1, GL_FALSE, value.constData()); -} - -/*! - \overload - - Sets the uniform variable called \a name in the current context - to a 3x3 matrix \a value. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValue(const char *name, const QMatrix3x3& value) -{ - setUniformValue(uniformLocation(name), value); -} - -/*! - Sets the uniform variable at \a location in the current context - to a 3x4 matrix \a value. - - \note This function is not aware of non square matrix support, - that is, GLSL types like mat3x4, that is present in modern OpenGL - versions. Instead, it treats the uniform as an array of vec4. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValue(int location, const QMatrix3x4& value) -{ - Q_D(QOpenGLShaderProgram); - Q_UNUSED(d); - d->glfuncs->glUniform4fv(location, 3, value.constData()); -} - -/*! - \overload - - Sets the uniform variable called \a name in the current context - to a 3x4 matrix \a value. - - \note This function is not aware of non square matrix support, - that is, GLSL types like mat3x4, that is present in modern OpenGL - versions. Instead, it treats the uniform as an array of vec4. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValue(const char *name, const QMatrix3x4& value) -{ - setUniformValue(uniformLocation(name), value); -} - -/*! - Sets the uniform variable at \a location in the current context - to a 4x2 matrix \a value. - - \note This function is not aware of non square matrix support, - that is, GLSL types like mat4x2, that is present in modern OpenGL - versions. Instead, it treats the uniform as an array of vec2. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValue(int location, const QMatrix4x2& value) -{ - Q_D(QOpenGLShaderProgram); - Q_UNUSED(d); - d->glfuncs->glUniform2fv(location, 4, value.constData()); -} - -/*! - \overload - - Sets the uniform variable called \a name in the current context - to a 4x2 matrix \a value. - - \note This function is not aware of non square matrix support, - that is, GLSL types like mat4x2, that is present in modern OpenGL - versions. Instead, it treats the uniform as an array of vec2. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValue(const char *name, const QMatrix4x2& value) -{ - setUniformValue(uniformLocation(name), value); -} - -/*! - Sets the uniform variable at \a location in the current context - to a 4x3 matrix \a value. - - \note This function is not aware of non square matrix support, - that is, GLSL types like mat4x3, that is present in modern OpenGL - versions. Instead, it treats the uniform as an array of vec3. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValue(int location, const QMatrix4x3& value) -{ - Q_D(QOpenGLShaderProgram); - Q_UNUSED(d); - d->glfuncs->glUniform3fv(location, 4, value.constData()); -} - -/*! - \overload - - Sets the uniform variable called \a name in the current context - to a 4x3 matrix \a value. - - \note This function is not aware of non square matrix support, - that is, GLSL types like mat4x3, that is present in modern OpenGL - versions. Instead, it treats the uniform as an array of vec3. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValue(const char *name, const QMatrix4x3& value) -{ - setUniformValue(uniformLocation(name), value); -} - -/*! - Sets the uniform variable at \a location in the current context - to a 4x4 matrix \a value. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValue(int location, const QMatrix4x4& value) -{ - Q_D(QOpenGLShaderProgram); - Q_UNUSED(d); - d->glfuncs->glUniformMatrix4fv(location, 1, GL_FALSE, value.constData()); -} - -/*! - \overload - - Sets the uniform variable called \a name in the current context - to a 4x4 matrix \a value. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValue(const char *name, const QMatrix4x4& value) -{ - setUniformValue(uniformLocation(name), value); -} - -/*! - \overload - - Sets the uniform variable at \a location in the current context - to a 2x2 matrix \a value. The matrix elements must be specified - in column-major order. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValue(int location, const GLfloat value[2][2]) -{ - Q_D(QOpenGLShaderProgram); - Q_UNUSED(d); - if (location != -1) - d->glfuncs->glUniformMatrix2fv(location, 1, GL_FALSE, value[0]); -} - -/*! - \overload - - Sets the uniform variable at \a location in the current context - to a 3x3 matrix \a value. The matrix elements must be specified - in column-major order. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValue(int location, const GLfloat value[3][3]) -{ - Q_D(QOpenGLShaderProgram); - Q_UNUSED(d); - if (location != -1) - d->glfuncs->glUniformMatrix3fv(location, 1, GL_FALSE, value[0]); -} - -/*! - \overload - - Sets the uniform variable at \a location in the current context - to a 4x4 matrix \a value. The matrix elements must be specified - in column-major order. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValue(int location, const GLfloat value[4][4]) -{ - Q_D(QOpenGLShaderProgram); - Q_UNUSED(d); - if (location != -1) - d->glfuncs->glUniformMatrix4fv(location, 1, GL_FALSE, value[0]); -} - - -/*! - \overload - - Sets the uniform variable called \a name in the current context - to a 2x2 matrix \a value. The matrix elements must be specified - in column-major order. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValue(const char *name, const GLfloat value[2][2]) -{ - setUniformValue(uniformLocation(name), value); -} - -/*! - \overload - - Sets the uniform variable called \a name in the current context - to a 3x3 matrix \a value. The matrix elements must be specified - in column-major order. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValue(const char *name, const GLfloat value[3][3]) -{ - setUniformValue(uniformLocation(name), value); -} - -/*! - \overload - - Sets the uniform variable called \a name in the current context - to a 4x4 matrix \a value. The matrix elements must be specified - in column-major order. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValue(const char *name, const GLfloat value[4][4]) -{ - setUniformValue(uniformLocation(name), value); -} - -/*! - Sets the uniform variable at \a location in the current context to a - 3x3 transformation matrix \a value that is specified as a QTransform value. - - To set a QTransform value as a 4x4 matrix in a shader, use - \c{setUniformValue(location, QMatrix4x4(value))}. -*/ -void QOpenGLShaderProgram::setUniformValue(int location, const QTransform& value) -{ - Q_D(QOpenGLShaderProgram); - Q_UNUSED(d); - if (location != -1) { - GLfloat mat[3][3] = { - {GLfloat(value.m11()), GLfloat(value.m12()), GLfloat(value.m13())}, - {GLfloat(value.m21()), GLfloat(value.m22()), GLfloat(value.m23())}, - {GLfloat(value.m31()), GLfloat(value.m32()), GLfloat(value.m33())} - }; - d->glfuncs->glUniformMatrix3fv(location, 1, GL_FALSE, mat[0]); - } -} - -/*! - \overload - - Sets the uniform variable called \a name in the current context to a - 3x3 transformation matrix \a value that is specified as a QTransform value. - - To set a QTransform value as a 4x4 matrix in a shader, use - \c{setUniformValue(name, QMatrix4x4(value))}. -*/ -void QOpenGLShaderProgram::setUniformValue - (const char *name, const QTransform& value) -{ - setUniformValue(uniformLocation(name), value); -} - -/*! - Sets the uniform variable array at \a location in the current - context to the \a count elements of \a values. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValueArray(int location, const GLint *values, int count) -{ - Q_D(QOpenGLShaderProgram); - Q_UNUSED(d); - if (location != -1) - d->glfuncs->glUniform1iv(location, count, values); -} - -/*! - \overload - - Sets the uniform variable array called \a name in the current - context to the \a count elements of \a values. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValueArray - (const char *name, const GLint *values, int count) -{ - setUniformValueArray(uniformLocation(name), values, count); -} - -/*! - Sets the uniform variable array at \a location in the current - context to the \a count elements of \a values. This overload - should be used when setting an array of sampler values. - - \note This function is not aware of unsigned int support in modern OpenGL - versions and therefore treats \a values as a GLint and calls glUniform1iv. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValueArray(int location, const GLuint *values, int count) -{ - Q_D(QOpenGLShaderProgram); - Q_UNUSED(d); - if (location != -1) - d->glfuncs->glUniform1iv(location, count, reinterpret_cast(values)); -} - -/*! - \overload - - Sets the uniform variable array called \a name in the current - context to the \a count elements of \a values. This overload - should be used when setting an array of sampler values. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValueArray - (const char *name, const GLuint *values, int count) -{ - setUniformValueArray(uniformLocation(name), values, count); -} - -/*! - Sets the uniform variable array at \a location in the current - context to the \a count elements of \a values. Each element - has \a tupleSize components. The \a tupleSize must be 1, 2, 3, or 4. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValueArray(int location, const GLfloat *values, int count, int tupleSize) -{ - Q_D(QOpenGLShaderProgram); - Q_UNUSED(d); - if (location != -1) { - if (tupleSize == 1) - d->glfuncs->glUniform1fv(location, count, values); - else if (tupleSize == 2) - d->glfuncs->glUniform2fv(location, count, values); - else if (tupleSize == 3) - d->glfuncs->glUniform3fv(location, count, values); - else if (tupleSize == 4) - d->glfuncs->glUniform4fv(location, count, values); - else - qWarning("QOpenGLShaderProgram::setUniformValue: size %d not supported", tupleSize); - } -} - -/*! - \overload - - Sets the uniform variable array called \a name in the current - context to the \a count elements of \a values. Each element - has \a tupleSize components. The \a tupleSize must be 1, 2, 3, or 4. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValueArray - (const char *name, const GLfloat *values, int count, int tupleSize) -{ - setUniformValueArray(uniformLocation(name), values, count, tupleSize); -} - -/*! - Sets the uniform variable array at \a location in the current - context to the \a count 2D vector elements of \a values. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValueArray(int location, const QVector2D *values, int count) -{ - Q_D(QOpenGLShaderProgram); - Q_UNUSED(d); - if (location != -1) - d->glfuncs->glUniform2fv(location, count, reinterpret_cast(values)); -} - -/*! - \overload - - Sets the uniform variable array called \a name in the current - context to the \a count 2D vector elements of \a values. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValueArray(const char *name, const QVector2D *values, int count) -{ - setUniformValueArray(uniformLocation(name), values, count); -} - -/*! - Sets the uniform variable array at \a location in the current - context to the \a count 3D vector elements of \a values. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValueArray(int location, const QVector3D *values, int count) -{ - Q_D(QOpenGLShaderProgram); - Q_UNUSED(d); - if (location != -1) - d->glfuncs->glUniform3fv(location, count, reinterpret_cast(values)); -} - -/*! - \overload - - Sets the uniform variable array called \a name in the current - context to the \a count 3D vector elements of \a values. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValueArray(const char *name, const QVector3D *values, int count) -{ - setUniformValueArray(uniformLocation(name), values, count); -} - -/*! - Sets the uniform variable array at \a location in the current - context to the \a count 4D vector elements of \a values. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValueArray(int location, const QVector4D *values, int count) -{ - Q_D(QOpenGLShaderProgram); - Q_UNUSED(d); - if (location != -1) - d->glfuncs->glUniform4fv(location, count, reinterpret_cast(values)); -} - -/*! - \overload - - Sets the uniform variable array called \a name in the current - context to the \a count 4D vector elements of \a values. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValueArray(const char *name, const QVector4D *values, int count) -{ - setUniformValueArray(uniformLocation(name), values, count); -} - -// We have to repack matrix arrays from qreal to GLfloat. -#define setUniformMatrixArray(func,location,values,count,type,cols,rows) \ - if (location == -1 || count <= 0) \ - return; \ - if (sizeof(type) == sizeof(GLfloat) * cols * rows) { \ - func(location, count, GL_FALSE, \ - reinterpret_cast(values[0].constData())); \ - } else { \ - QVarLengthArray temp(cols * rows * count); \ - for (int index = 0; index < count; ++index) { \ - for (int index2 = 0; index2 < (cols * rows); ++index2) { \ - temp.data()[cols * rows * index + index2] = \ - values[index].constData()[index2]; \ - } \ - } \ - func(location, count, GL_FALSE, temp.constData()); \ - } -#define setUniformGenericMatrixArray(colfunc,location,values,count,type,cols,rows) \ - if (location == -1 || count <= 0) \ - return; \ - if (sizeof(type) == sizeof(GLfloat) * cols * rows) { \ - const GLfloat *data = reinterpret_cast \ - (values[0].constData()); \ - colfunc(location, count * cols, data); \ - } else { \ - QVarLengthArray temp(cols * rows * count); \ - for (int index = 0; index < count; ++index) { \ - for (int index2 = 0; index2 < (cols * rows); ++index2) { \ - temp.data()[cols * rows * index + index2] = \ - values[index].constData()[index2]; \ - } \ - } \ - colfunc(location, count * cols, temp.constData()); \ - } - -/*! - Sets the uniform variable array at \a location in the current - context to the \a count 2x2 matrix elements of \a values. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValueArray(int location, const QMatrix2x2 *values, int count) -{ - Q_D(QOpenGLShaderProgram); - Q_UNUSED(d); - setUniformMatrixArray - (d->glfuncs->glUniformMatrix2fv, location, values, count, QMatrix2x2, 2, 2); -} - -/*! - \overload - - Sets the uniform variable array called \a name in the current - context to the \a count 2x2 matrix elements of \a values. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValueArray(const char *name, const QMatrix2x2 *values, int count) -{ - setUniformValueArray(uniformLocation(name), values, count); -} - -/*! - Sets the uniform variable array at \a location in the current - context to the \a count 2x3 matrix elements of \a values. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValueArray(int location, const QMatrix2x3 *values, int count) -{ - Q_D(QOpenGLShaderProgram); - Q_UNUSED(d); - setUniformGenericMatrixArray - (d->glfuncs->glUniform3fv, location, values, count, - QMatrix2x3, 2, 3); -} - -/*! - \overload - - Sets the uniform variable array called \a name in the current - context to the \a count 2x3 matrix elements of \a values. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValueArray(const char *name, const QMatrix2x3 *values, int count) -{ - setUniformValueArray(uniformLocation(name), values, count); -} - -/*! - Sets the uniform variable array at \a location in the current - context to the \a count 2x4 matrix elements of \a values. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValueArray(int location, const QMatrix2x4 *values, int count) -{ - Q_D(QOpenGLShaderProgram); - Q_UNUSED(d); - setUniformGenericMatrixArray - (d->glfuncs->glUniform4fv, location, values, count, - QMatrix2x4, 2, 4); -} - -/*! - \overload - - Sets the uniform variable array called \a name in the current - context to the \a count 2x4 matrix elements of \a values. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValueArray(const char *name, const QMatrix2x4 *values, int count) -{ - setUniformValueArray(uniformLocation(name), values, count); -} - -/*! - Sets the uniform variable array at \a location in the current - context to the \a count 3x2 matrix elements of \a values. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValueArray(int location, const QMatrix3x2 *values, int count) -{ - Q_D(QOpenGLShaderProgram); - Q_UNUSED(d); - setUniformGenericMatrixArray - (d->glfuncs->glUniform2fv, location, values, count, - QMatrix3x2, 3, 2); -} - -/*! - \overload - - Sets the uniform variable array called \a name in the current - context to the \a count 3x2 matrix elements of \a values. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValueArray(const char *name, const QMatrix3x2 *values, int count) -{ - setUniformValueArray(uniformLocation(name), values, count); -} - -/*! - Sets the uniform variable array at \a location in the current - context to the \a count 3x3 matrix elements of \a values. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValueArray(int location, const QMatrix3x3 *values, int count) -{ - Q_D(QOpenGLShaderProgram); - Q_UNUSED(d); - setUniformMatrixArray - (d->glfuncs->glUniformMatrix3fv, location, values, count, QMatrix3x3, 3, 3); -} - -/*! - \overload - - Sets the uniform variable array called \a name in the current - context to the \a count 3x3 matrix elements of \a values. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValueArray(const char *name, const QMatrix3x3 *values, int count) -{ - setUniformValueArray(uniformLocation(name), values, count); -} - -/*! - Sets the uniform variable array at \a location in the current - context to the \a count 3x4 matrix elements of \a values. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValueArray(int location, const QMatrix3x4 *values, int count) -{ - Q_D(QOpenGLShaderProgram); - Q_UNUSED(d); - setUniformGenericMatrixArray - (d->glfuncs->glUniform4fv, location, values, count, - QMatrix3x4, 3, 4); -} - -/*! - \overload - - Sets the uniform variable array called \a name in the current - context to the \a count 3x4 matrix elements of \a values. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValueArray(const char *name, const QMatrix3x4 *values, int count) -{ - setUniformValueArray(uniformLocation(name), values, count); -} - -/*! - Sets the uniform variable array at \a location in the current - context to the \a count 4x2 matrix elements of \a values. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValueArray(int location, const QMatrix4x2 *values, int count) -{ - Q_D(QOpenGLShaderProgram); - Q_UNUSED(d); - setUniformGenericMatrixArray - (d->glfuncs->glUniform2fv, location, values, count, - QMatrix4x2, 4, 2); -} - -/*! - \overload - - Sets the uniform variable array called \a name in the current - context to the \a count 4x2 matrix elements of \a values. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValueArray(const char *name, const QMatrix4x2 *values, int count) -{ - setUniformValueArray(uniformLocation(name), values, count); -} - -/*! - Sets the uniform variable array at \a location in the current - context to the \a count 4x3 matrix elements of \a values. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValueArray(int location, const QMatrix4x3 *values, int count) -{ - Q_D(QOpenGLShaderProgram); - Q_UNUSED(d); - setUniformGenericMatrixArray - (d->glfuncs->glUniform3fv, location, values, count, - QMatrix4x3, 4, 3); -} - -/*! - \overload - - Sets the uniform variable array called \a name in the current - context to the \a count 4x3 matrix elements of \a values. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValueArray(const char *name, const QMatrix4x3 *values, int count) -{ - setUniformValueArray(uniformLocation(name), values, count); -} - -/*! - Sets the uniform variable array at \a location in the current - context to the \a count 4x4 matrix elements of \a values. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValueArray(int location, const QMatrix4x4 *values, int count) -{ - Q_D(QOpenGLShaderProgram); - Q_UNUSED(d); - setUniformMatrixArray - (d->glfuncs->glUniformMatrix4fv, location, values, count, QMatrix4x4, 4, 4); -} - -/*! - \overload - - Sets the uniform variable array called \a name in the current - context to the \a count 4x4 matrix elements of \a values. - - \sa setAttributeValue() -*/ -void QOpenGLShaderProgram::setUniformValueArray(const char *name, const QMatrix4x4 *values, int count) -{ - setUniformValueArray(uniformLocation(name), values, count); -} - -/*! - Returns the hardware limit for how many vertices a geometry shader - can output. -*/ -int QOpenGLShaderProgram::maxGeometryOutputVertices() const -{ - GLint n = 0; - Q_D(const QOpenGLShaderProgram); - d->glfuncs->glGetIntegerv(GL_MAX_GEOMETRY_OUTPUT_VERTICES, &n); - return n; -} - -/*! - Use this function to specify to OpenGL the number of vertices in - a patch to \a count. A patch is a custom OpenGL primitive whose interpretation - is entirely defined by the tessellation shader stages. Therefore, calling - this function only makes sense when using a QOpenGLShaderProgram - containing tessellation stage shaders. When using OpenGL tessellation, - the only primitive that can be rendered with \c{glDraw*()} functions is - \c{GL_PATCHES}. - - This is equivalent to calling glPatchParameteri(GL_PATCH_VERTICES, count). - - \note This modifies global OpenGL state and is not specific to this - QOpenGLShaderProgram instance. You should call this in your render - function when needed, as QOpenGLShaderProgram will not apply this for - you. This is purely a convenience function. - - \sa patchVertexCount() -*/ -void QOpenGLShaderProgram::setPatchVertexCount(int count) -{ - Q_D(QOpenGLShaderProgram); - d->glfuncs->glPatchParameteri(GL_PATCH_VERTICES, count); -} - -/*! - Returns the number of vertices per-patch to be used when rendering. - - \note This returns the global OpenGL state value. It is not specific to - this QOpenGLShaderProgram instance. - - \sa setPatchVertexCount() -*/ -int QOpenGLShaderProgram::patchVertexCount() const -{ - int patchVertices = 0; - Q_D(const QOpenGLShaderProgram); - d->glfuncs->glGetIntegerv(GL_PATCH_VERTICES, &patchVertices); - return patchVertices; -} - -/*! - Sets the default outer tessellation levels to be used by the tessellation - primitive generator in the event that the tessellation control shader - does not output them to \a levels. For more details on OpenGL and Tessellation - shaders see \l{OpenGL Tessellation Shaders}. - - The \a levels argument should be a QVector consisting of 4 floats. Not all - of the values make sense for all tessellation modes. If you specify a vector with - fewer than 4 elements, the remaining elements will be given a default value of 1. - - \note This modifies global OpenGL state and is not specific to this - QOpenGLShaderProgram instance. You should call this in your render - function when needed, as QOpenGLShaderProgram will not apply this for - you. This is purely a convenience function. - - \note This function is only available with OpenGL >= 4.0 and is not supported - with OpenGL ES 3.2. - - \sa defaultOuterTessellationLevels(), setDefaultInnerTessellationLevels() -*/ -void QOpenGLShaderProgram::setDefaultOuterTessellationLevels(const QVector &levels) -{ -#ifndef QT_OPENGL_ES_2 - Q_D(QOpenGLShaderProgram); - if (d->tessellationFuncs) { - QVector tessLevels = levels; - - // Ensure we have the required 4 outer tessellation levels - // Use default of 1 for missing entries (same as spec) - const int argCount = 4; - if (tessLevels.size() < argCount) { - tessLevels.reserve(argCount); - for (int i = tessLevels.size(); i < argCount; ++i) - tessLevels.append(1.0f); - } - d->tessellationFuncs->glPatchParameterfv(GL_PATCH_DEFAULT_OUTER_LEVEL, tessLevels.data()); - } -#else - Q_UNUSED(levels); -#endif -} - -/*! - Returns the default outer tessellation levels to be used by the tessellation - primitive generator in the event that the tessellation control shader - does not output them. For more details on OpenGL and Tessellation shaders see - \l{OpenGL Tessellation Shaders}. - - Returns a QVector of floats describing the outer tessellation levels. The vector - will always have four elements but not all of them make sense for every mode - of tessellation. - - \note This returns the global OpenGL state value. It is not specific to - this QOpenGLShaderProgram instance. - - \note This function is only supported with OpenGL >= 4.0 and will not - return valid results with OpenGL ES 3.2. - - \sa setDefaultOuterTessellationLevels(), defaultInnerTessellationLevels() -*/ -QVector QOpenGLShaderProgram::defaultOuterTessellationLevels() const -{ -#ifndef QT_OPENGL_ES_2 - QVector tessLevels(4, 1.0f); - Q_D(const QOpenGLShaderProgram); - if (d->tessellationFuncs) - d->tessellationFuncs->glGetFloatv(GL_PATCH_DEFAULT_OUTER_LEVEL, tessLevels.data()); - return tessLevels; -#else - return QVector(); -#endif -} - -/*! - Sets the default outer tessellation levels to be used by the tessellation - primitive generator in the event that the tessellation control shader - does not output them to \a levels. For more details on OpenGL and Tessellation shaders see - \l{OpenGL Tessellation Shaders}. - - The \a levels argument should be a QVector consisting of 2 floats. Not all - of the values make sense for all tessellation modes. If you specify a vector with - fewer than 2 elements, the remaining elements will be given a default value of 1. - - \note This modifies global OpenGL state and is not specific to this - QOpenGLShaderProgram instance. You should call this in your render - function when needed, as QOpenGLShaderProgram will not apply this for - you. This is purely a convenience function. - - \note This function is only available with OpenGL >= 4.0 and is not supported - with OpenGL ES 3.2. - - \sa defaultInnerTessellationLevels(), setDefaultOuterTessellationLevels() -*/ -void QOpenGLShaderProgram::setDefaultInnerTessellationLevels(const QVector &levels) -{ -#ifndef QT_OPENGL_ES_2 - Q_D(QOpenGLShaderProgram); - if (d->tessellationFuncs) { - QVector tessLevels = levels; - - // Ensure we have the required 2 inner tessellation levels - // Use default of 1 for missing entries (same as spec) - const int argCount = 2; - if (tessLevels.size() < argCount) { - tessLevels.reserve(argCount); - for (int i = tessLevels.size(); i < argCount; ++i) - tessLevels.append(1.0f); - } - d->tessellationFuncs->glPatchParameterfv(GL_PATCH_DEFAULT_INNER_LEVEL, tessLevels.data()); - } -#else - Q_UNUSED(levels); -#endif -} - -/*! - Returns the default inner tessellation levels to be used by the tessellation - primitive generator in the event that the tessellation control shader - does not output them. For more details on OpenGL and Tessellation shaders see - \l{OpenGL Tessellation Shaders}. - - Returns a QVector of floats describing the inner tessellation levels. The vector - will always have two elements but not all of them make sense for every mode - of tessellation. - - \note This returns the global OpenGL state value. It is not specific to - this QOpenGLShaderProgram instance. - - \note This function is only supported with OpenGL >= 4.0 and will not - return valid results with OpenGL ES 3.2. - - \sa setDefaultInnerTessellationLevels(), defaultOuterTessellationLevels() -*/ -QVector QOpenGLShaderProgram::defaultInnerTessellationLevels() const -{ -#ifndef QT_OPENGL_ES_2 - QVector tessLevels(2, 1.0f); - Q_D(const QOpenGLShaderProgram); - if (d->tessellationFuncs) - d->tessellationFuncs->glGetFloatv(GL_PATCH_DEFAULT_INNER_LEVEL, tessLevels.data()); - return tessLevels; -#else - return QVector(); -#endif -} - - -/*! - Returns \c true if shader programs written in the OpenGL Shading - Language (GLSL) are supported on this system; false otherwise. - - The \a context is used to resolve the GLSL extensions. - If \a context is \nullptr, then QOpenGLContext::currentContext() - is used. -*/ -bool QOpenGLShaderProgram::hasOpenGLShaderPrograms(QOpenGLContext *context) -{ - if (!context) - context = QOpenGLContext::currentContext(); - if (!context) - return false; - return QOpenGLFunctions(context).hasOpenGLFeature(QOpenGLFunctions::Shaders); -} - -/*! - \internal -*/ -void QOpenGLShaderProgram::shaderDestroyed() -{ - Q_D(QOpenGLShaderProgram); - QOpenGLShader *shader = qobject_cast(sender()); - if (shader && !d->removingShaders) - removeShader(shader); -} - -/*! - Returns \c true if shader programs of type \a type are supported on - this system; false otherwise. - - The \a context is used to resolve the GLSL extensions. - If \a context is \nullptr, then QOpenGLContext::currentContext() - is used. -*/ -bool QOpenGLShader::hasOpenGLShaders(ShaderType type, QOpenGLContext *context) -{ - if (!context) - context = QOpenGLContext::currentContext(); - if (!context) - return false; - - if ((type & ~(Geometry | Vertex | Fragment | TessellationControl | TessellationEvaluation | Compute)) || type == 0) - return false; - - if (type & QOpenGLShader::Geometry) - return supportsGeometry(context->format()); - else if (type & (QOpenGLShader::TessellationControl | QOpenGLShader::TessellationEvaluation)) - return supportsTessellation(context->format()); - else if (type & QOpenGLShader::Compute) - return supportsCompute(context->format()); - - // Unconditional support of vertex and fragment shaders implicitly assumes - // a minimum OpenGL version of 2.0 - return true; -} - -bool QOpenGLShaderProgramPrivate::isCacheDisabled() const -{ - static QOpenGLProgramBinarySupportCheckWrapper binSupportCheck; - return !binSupportCheck.get(QOpenGLContext::currentContext())->isSupported(); -} - -bool QOpenGLShaderProgramPrivate::compileCacheable() -{ - Q_Q(QOpenGLShaderProgram); - for (const QOpenGLProgramBinaryCache::ShaderDesc &shader : qAsConst(binaryProgram.shaders)) { - QScopedPointer s(new QOpenGLShader(qt_shaderStageToType(shader.stage), q)); - if (!s->compileSourceCode(shader.source)) { - log = s->log(); - return false; - } - anonShaders.append(s.take()); - if (!q->addShader(anonShaders.last())) - return false; - } - return true; -} - -bool QOpenGLShaderProgramPrivate::linkBinary() -{ - static QOpenGLProgramBinaryCache binCache; - - Q_Q(QOpenGLShaderProgram); - - const QByteArray cacheKey = binaryProgram.cacheKey(); - if (lcOpenGLProgramDiskCache().isEnabled(QtDebugMsg)) - qCDebug(lcOpenGLProgramDiskCache, "program with %d shaders, cache key %s", - binaryProgram.shaders.count(), cacheKey.constData()); - - bool needsCompile = true; - if (binCache.load(cacheKey, q->programId())) { - qCDebug(lcOpenGLProgramDiskCache, "Program binary received from cache"); - needsCompile = false; - } - - bool needsSave = false; - if (needsCompile) { - qCDebug(lcOpenGLProgramDiskCache, "Program binary not in cache, compiling"); - if (compileCacheable()) - needsSave = true; - else - return false; - } - - linkBinaryRecursion = true; - bool ok = q->link(); - linkBinaryRecursion = false; - if (ok && needsSave) - binCache.save(cacheKey, q->programId()); - - return ok; -} - -QT_END_NAMESPACE diff --git a/src/gui/opengl/qopenglshaderprogram.h b/src/gui/opengl/qopenglshaderprogram.h deleted file mode 100644 index c79101fd4d..0000000000 --- a/src/gui/opengl/qopenglshaderprogram.h +++ /dev/null @@ -1,318 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QOPENGLSHADERPROGRAM_H -#define QOPENGLSHADERPROGRAM_H - -#include - -#ifndef QT_NO_OPENGL - -#include -#include -#include -#include -#include - -QT_BEGIN_NAMESPACE - - -class QOpenGLContext; -class QOpenGLShaderProgram; -class QOpenGLShaderPrivate; - -class Q_GUI_EXPORT QOpenGLShader : public QObject -{ - Q_OBJECT -public: - enum ShaderTypeBit - { - Vertex = 0x0001, - Fragment = 0x0002, - Geometry = 0x0004, - TessellationControl = 0x0008, - TessellationEvaluation = 0x0010, - Compute = 0x0020 - }; - Q_DECLARE_FLAGS(ShaderType, ShaderTypeBit) - - explicit QOpenGLShader(QOpenGLShader::ShaderType type, QObject *parent = nullptr); - ~QOpenGLShader(); - - QOpenGLShader::ShaderType shaderType() const; - - bool compileSourceCode(const char *source); - bool compileSourceCode(const QByteArray& source); - bool compileSourceCode(const QString& source); - bool compileSourceFile(const QString& fileName); - - QByteArray sourceCode() const; - - bool isCompiled() const; - QString log() const; - - GLuint shaderId() const; - - static bool hasOpenGLShaders(ShaderType type, QOpenGLContext *context = nullptr); - -private: - friend class QOpenGLShaderProgram; - - Q_DISABLE_COPY(QOpenGLShader) - Q_DECLARE_PRIVATE(QOpenGLShader) -}; - -Q_DECLARE_OPERATORS_FOR_FLAGS(QOpenGLShader::ShaderType) - - -class QOpenGLShaderProgramPrivate; - -class Q_GUI_EXPORT QOpenGLShaderProgram : public QObject -{ - Q_OBJECT -public: - explicit QOpenGLShaderProgram(QObject *parent = nullptr); - ~QOpenGLShaderProgram(); - - bool addShader(QOpenGLShader *shader); - void removeShader(QOpenGLShader *shader); - QList shaders() const; - - bool addShaderFromSourceCode(QOpenGLShader::ShaderType type, const char *source); - bool addShaderFromSourceCode(QOpenGLShader::ShaderType type, const QByteArray& source); - bool addShaderFromSourceCode(QOpenGLShader::ShaderType type, const QString& source); - bool addShaderFromSourceFile(QOpenGLShader::ShaderType type, const QString& fileName); - - bool addCacheableShaderFromSourceCode(QOpenGLShader::ShaderType type, const char *source); - bool addCacheableShaderFromSourceCode(QOpenGLShader::ShaderType type, const QByteArray &source); - bool addCacheableShaderFromSourceCode(QOpenGLShader::ShaderType type, const QString &source); - bool addCacheableShaderFromSourceFile(QOpenGLShader::ShaderType type, const QString &fileName); - - void removeAllShaders(); - - virtual bool link(); - bool isLinked() const; - QString log() const; - - bool bind(); - void release(); - - bool create(); - - GLuint programId() const; - - int maxGeometryOutputVertices() const; - - void setPatchVertexCount(int count); - int patchVertexCount() const; - - void setDefaultOuterTessellationLevels(const QVector &levels); - QVector defaultOuterTessellationLevels() const; - - void setDefaultInnerTessellationLevels(const QVector &levels); - QVector defaultInnerTessellationLevels() const; - - void bindAttributeLocation(const char *name, int location); - void bindAttributeLocation(const QByteArray& name, int location); - void bindAttributeLocation(const QString& name, int location); - - int attributeLocation(const char *name) const; - int attributeLocation(const QByteArray& name) const; - int attributeLocation(const QString& name) const; - - void setAttributeValue(int location, GLfloat value); - void setAttributeValue(int location, GLfloat x, GLfloat y); - void setAttributeValue(int location, GLfloat x, GLfloat y, GLfloat z); - void setAttributeValue(int location, GLfloat x, GLfloat y, GLfloat z, GLfloat w); - void setAttributeValue(int location, const QVector2D& value); - void setAttributeValue(int location, const QVector3D& value); - void setAttributeValue(int location, const QVector4D& value); - void setAttributeValue(int location, const QColor& value); - void setAttributeValue(int location, const GLfloat *values, int columns, int rows); - - void setAttributeValue(const char *name, GLfloat value); - void setAttributeValue(const char *name, GLfloat x, GLfloat y); - void setAttributeValue(const char *name, GLfloat x, GLfloat y, GLfloat z); - void setAttributeValue(const char *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w); - void setAttributeValue(const char *name, const QVector2D& value); - void setAttributeValue(const char *name, const QVector3D& value); - void setAttributeValue(const char *name, const QVector4D& value); - void setAttributeValue(const char *name, const QColor& value); - void setAttributeValue(const char *name, const GLfloat *values, int columns, int rows); - - void setAttributeArray - (int location, const GLfloat *values, int tupleSize, int stride = 0); - void setAttributeArray - (int location, const QVector2D *values, int stride = 0); - void setAttributeArray - (int location, const QVector3D *values, int stride = 0); - void setAttributeArray - (int location, const QVector4D *values, int stride = 0); - void setAttributeArray - (int location, GLenum type, const void *values, int tupleSize, int stride = 0); - void setAttributeArray - (const char *name, const GLfloat *values, int tupleSize, int stride = 0); - void setAttributeArray - (const char *name, const QVector2D *values, int stride = 0); - void setAttributeArray - (const char *name, const QVector3D *values, int stride = 0); - void setAttributeArray - (const char *name, const QVector4D *values, int stride = 0); - void setAttributeArray - (const char *name, GLenum type, const void *values, int tupleSize, int stride = 0); - - void setAttributeBuffer - (int location, GLenum type, int offset, int tupleSize, int stride = 0); - void setAttributeBuffer - (const char *name, GLenum type, int offset, int tupleSize, int stride = 0); - - void enableAttributeArray(int location); - void enableAttributeArray(const char *name); - void disableAttributeArray(int location); - void disableAttributeArray(const char *name); - - int uniformLocation(const char *name) const; - int uniformLocation(const QByteArray& name) const; - int uniformLocation(const QString& name) const; - - void setUniformValue(int location, GLfloat value); - void setUniformValue(int location, GLint value); - void setUniformValue(int location, GLuint value); - void setUniformValue(int location, GLfloat x, GLfloat y); - void setUniformValue(int location, GLfloat x, GLfloat y, GLfloat z); - void setUniformValue(int location, GLfloat x, GLfloat y, GLfloat z, GLfloat w); - void setUniformValue(int location, const QVector2D& value); - void setUniformValue(int location, const QVector3D& value); - void setUniformValue(int location, const QVector4D& value); - void setUniformValue(int location, const QColor& color); - void setUniformValue(int location, const QPoint& point); - void setUniformValue(int location, const QPointF& point); - void setUniformValue(int location, const QSize& size); - void setUniformValue(int location, const QSizeF& size); - void setUniformValue(int location, const QMatrix2x2& value); - void setUniformValue(int location, const QMatrix2x3& value); - void setUniformValue(int location, const QMatrix2x4& value); - void setUniformValue(int location, const QMatrix3x2& value); - void setUniformValue(int location, const QMatrix3x3& value); - void setUniformValue(int location, const QMatrix3x4& value); - void setUniformValue(int location, const QMatrix4x2& value); - void setUniformValue(int location, const QMatrix4x3& value); - void setUniformValue(int location, const QMatrix4x4& value); - void setUniformValue(int location, const GLfloat value[2][2]); - void setUniformValue(int location, const GLfloat value[3][3]); - void setUniformValue(int location, const GLfloat value[4][4]); - void setUniformValue(int location, const QTransform& value); - - void setUniformValue(const char *name, GLfloat value); - void setUniformValue(const char *name, GLint value); - void setUniformValue(const char *name, GLuint value); - void setUniformValue(const char *name, GLfloat x, GLfloat y); - void setUniformValue(const char *name, GLfloat x, GLfloat y, GLfloat z); - void setUniformValue(const char *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w); - void setUniformValue(const char *name, const QVector2D& value); - void setUniformValue(const char *name, const QVector3D& value); - void setUniformValue(const char *name, const QVector4D& value); - void setUniformValue(const char *name, const QColor& color); - void setUniformValue(const char *name, const QPoint& point); - void setUniformValue(const char *name, const QPointF& point); - void setUniformValue(const char *name, const QSize& size); - void setUniformValue(const char *name, const QSizeF& size); - void setUniformValue(const char *name, const QMatrix2x2& value); - void setUniformValue(const char *name, const QMatrix2x3& value); - void setUniformValue(const char *name, const QMatrix2x4& value); - void setUniformValue(const char *name, const QMatrix3x2& value); - void setUniformValue(const char *name, const QMatrix3x3& value); - void setUniformValue(const char *name, const QMatrix3x4& value); - void setUniformValue(const char *name, const QMatrix4x2& value); - void setUniformValue(const char *name, const QMatrix4x3& value); - void setUniformValue(const char *name, const QMatrix4x4& value); - void setUniformValue(const char *name, const GLfloat value[2][2]); - void setUniformValue(const char *name, const GLfloat value[3][3]); - void setUniformValue(const char *name, const GLfloat value[4][4]); - void setUniformValue(const char *name, const QTransform& value); - - void setUniformValueArray(int location, const GLfloat *values, int count, int tupleSize); - void setUniformValueArray(int location, const GLint *values, int count); - void setUniformValueArray(int location, const GLuint *values, int count); - void setUniformValueArray(int location, const QVector2D *values, int count); - void setUniformValueArray(int location, const QVector3D *values, int count); - void setUniformValueArray(int location, const QVector4D *values, int count); - void setUniformValueArray(int location, const QMatrix2x2 *values, int count); - void setUniformValueArray(int location, const QMatrix2x3 *values, int count); - void setUniformValueArray(int location, const QMatrix2x4 *values, int count); - void setUniformValueArray(int location, const QMatrix3x2 *values, int count); - void setUniformValueArray(int location, const QMatrix3x3 *values, int count); - void setUniformValueArray(int location, const QMatrix3x4 *values, int count); - void setUniformValueArray(int location, const QMatrix4x2 *values, int count); - void setUniformValueArray(int location, const QMatrix4x3 *values, int count); - void setUniformValueArray(int location, const QMatrix4x4 *values, int count); - - void setUniformValueArray(const char *name, const GLfloat *values, int count, int tupleSize); - void setUniformValueArray(const char *name, const GLint *values, int count); - void setUniformValueArray(const char *name, const GLuint *values, int count); - void setUniformValueArray(const char *name, const QVector2D *values, int count); - void setUniformValueArray(const char *name, const QVector3D *values, int count); - void setUniformValueArray(const char *name, const QVector4D *values, int count); - void setUniformValueArray(const char *name, const QMatrix2x2 *values, int count); - void setUniformValueArray(const char *name, const QMatrix2x3 *values, int count); - void setUniformValueArray(const char *name, const QMatrix2x4 *values, int count); - void setUniformValueArray(const char *name, const QMatrix3x2 *values, int count); - void setUniformValueArray(const char *name, const QMatrix3x3 *values, int count); - void setUniformValueArray(const char *name, const QMatrix3x4 *values, int count); - void setUniformValueArray(const char *name, const QMatrix4x2 *values, int count); - void setUniformValueArray(const char *name, const QMatrix4x3 *values, int count); - void setUniformValueArray(const char *name, const QMatrix4x4 *values, int count); - - static bool hasOpenGLShaderPrograms(QOpenGLContext *context = nullptr); - -private Q_SLOTS: - void shaderDestroyed(); - -private: - Q_DISABLE_COPY(QOpenGLShaderProgram) - Q_DECLARE_PRIVATE(QOpenGLShaderProgram) - - bool init(); -}; - -QT_END_NAMESPACE - -#endif // QT_NO_OPENGL - -#endif -- cgit v1.2.3