summaryrefslogtreecommitdiffstats
path: root/src/gui/util
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/util')
-rw-r--r--src/gui/util/qshaderformat.cpp130
-rw-r--r--src/gui/util/qshaderformat_p.h109
-rw-r--r--src/gui/util/qshadergenerator.cpp351
-rw-r--r--src/gui/util/qshadergenerator_p.h75
-rw-r--r--src/gui/util/qshadergraph.cpp262
-rw-r--r--src/gui/util/qshadergraph_p.h123
-rw-r--r--src/gui/util/qshadergraphloader.cpp251
-rw-r--r--src/gui/util/qshadergraphloader_p.h99
-rw-r--r--src/gui/util/qshaderlanguage.cpp56
-rw-r--r--src/gui/util/qshaderlanguage_p.h163
-rw-r--r--src/gui/util/qshadernode.cpp172
-rw-r--r--src/gui/util/qshadernode_p.h128
-rw-r--r--src/gui/util/qshadernodeport.cpp55
-rw-r--r--src/gui/util/qshadernodeport_p.h88
-rw-r--r--src/gui/util/qshadernodesloader.cpp274
-rw-r--r--src/gui/util/qshadernodesloader_p.h95
-rw-r--r--src/gui/util/qvalidator.cpp12
-rw-r--r--src/gui/util/util.pri20
18 files changed, 2455 insertions, 8 deletions
diff --git a/src/gui/util/qshaderformat.cpp b/src/gui/util/qshaderformat.cpp
new file mode 100644
index 0000000000..373bfb9e7e
--- /dev/null
+++ b/src/gui/util/qshaderformat.cpp
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** 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 "qshaderformat_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QShaderFormat::QShaderFormat() Q_DECL_NOTHROW
+ : m_api(NoApi)
+{
+}
+
+QShaderFormat::Api QShaderFormat::api() const Q_DECL_NOTHROW
+{
+ return m_api;
+}
+
+void QShaderFormat::setApi(QShaderFormat::Api api) Q_DECL_NOTHROW
+{
+ m_api = api;
+}
+
+QVersionNumber QShaderFormat::version() const Q_DECL_NOTHROW
+{
+ return m_version;
+}
+
+void QShaderFormat::setVersion(const QVersionNumber &version) Q_DECL_NOTHROW
+{
+ m_version = version;
+}
+
+QStringList QShaderFormat::extensions() const Q_DECL_NOTHROW
+{
+ return m_extensions;
+}
+
+void QShaderFormat::setExtensions(const QStringList &extensions) Q_DECL_NOTHROW
+{
+ m_extensions = extensions;
+ m_extensions.sort();
+}
+
+QString QShaderFormat::vendor() const Q_DECL_NOTHROW
+{
+ return m_vendor;
+}
+
+void QShaderFormat::setVendor(const QString &vendor) Q_DECL_NOTHROW
+{
+ m_vendor = vendor;
+}
+
+bool QShaderFormat::isValid() const Q_DECL_NOTHROW
+{
+ return m_api != NoApi && m_version.majorVersion() > 0;
+}
+
+bool QShaderFormat::supports(const QShaderFormat &other) const Q_DECL_NOTHROW
+{
+ if (!isValid() || !other.isValid())
+ return false;
+
+ if (m_api == OpenGLES && m_api != other.m_api)
+ return false;
+
+ if (m_api == OpenGLCoreProfile && m_api != other.m_api)
+ return false;
+
+ if (m_version < other.m_version)
+ return false;
+
+ const auto containsAllExtensionsFromOther = std::includes(m_extensions.constBegin(),
+ m_extensions.constEnd(),
+ other.m_extensions.constBegin(),
+ other.m_extensions.constEnd());
+ if (!containsAllExtensionsFromOther)
+ return false;
+
+ if (!other.m_vendor.isEmpty() && m_vendor != other.m_vendor)
+ return false;
+
+ return true;
+}
+
+bool operator==(const QShaderFormat &lhs, const QShaderFormat &rhs) Q_DECL_NOTHROW
+{
+ return lhs.api() == rhs.api()
+ && lhs.version() == rhs.version()
+ && lhs.extensions() == rhs.extensions()
+ && lhs.vendor() == rhs.vendor();
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/util/qshaderformat_p.h b/src/gui/util/qshaderformat_p.h
new file mode 100644
index 0000000000..064c2364a7
--- /dev/null
+++ b/src/gui/util/qshaderformat_p.h
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** 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 QSHADERFORMAT_P_H
+#define QSHADERFORMAT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtGui/private/qtguiglobal_p.h>
+
+#include <QtCore/qstringlist.h>
+#include <QtCore/qversionnumber.h>
+
+QT_BEGIN_NAMESPACE
+
+class QShaderFormat
+{
+public:
+ enum Api : int {
+ NoApi,
+ OpenGLNoProfile,
+ OpenGLCoreProfile,
+ OpenGLCompatibilityProfile,
+ OpenGLES
+ };
+
+ Q_GUI_EXPORT QShaderFormat() Q_DECL_NOTHROW;
+
+ Q_GUI_EXPORT Api api() const Q_DECL_NOTHROW;
+ Q_GUI_EXPORT void setApi(Api api) Q_DECL_NOTHROW;
+
+ Q_GUI_EXPORT QVersionNumber version() const Q_DECL_NOTHROW;
+ Q_GUI_EXPORT void setVersion(const QVersionNumber &version) Q_DECL_NOTHROW;
+
+ Q_GUI_EXPORT QStringList extensions() const Q_DECL_NOTHROW;
+ Q_GUI_EXPORT void setExtensions(const QStringList &extensions) Q_DECL_NOTHROW;
+
+ Q_GUI_EXPORT QString vendor() const Q_DECL_NOTHROW;
+ Q_GUI_EXPORT void setVendor(const QString &vendor) Q_DECL_NOTHROW;
+
+ Q_GUI_EXPORT bool isValid() const Q_DECL_NOTHROW;
+ Q_GUI_EXPORT bool supports(const QShaderFormat &other) const Q_DECL_NOTHROW;
+
+private:
+ Api m_api;
+ QVersionNumber m_version;
+ QStringList m_extensions;
+ QString m_vendor;
+};
+
+Q_GUI_EXPORT bool operator==(const QShaderFormat &lhs, const QShaderFormat &rhs) Q_DECL_NOTHROW;
+
+inline bool operator!=(const QShaderFormat &lhs, const QShaderFormat &rhs) Q_DECL_NOTHROW
+{
+ return !(lhs == rhs);
+}
+
+Q_DECLARE_TYPEINFO(QShaderFormat, Q_MOVABLE_TYPE);
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QShaderFormat)
+
+#endif // QSHADERFORMAT_P_H
diff --git a/src/gui/util/qshadergenerator.cpp b/src/gui/util/qshadergenerator.cpp
new file mode 100644
index 0000000000..31c2f74746
--- /dev/null
+++ b/src/gui/util/qshadergenerator.cpp
@@ -0,0 +1,351 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** 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 "qshadergenerator_p.h"
+
+#include "qshaderlanguage_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace
+{
+ QByteArray toGlsl(QShaderLanguage::StorageQualifier qualifier, const QShaderFormat &format)
+ {
+ if (format.version().majorVersion() <= 2) {
+ // Note we're assuming fragment shader only here, it'd be different
+ // values for vertex shader, will need to be fixed properly at some
+ // point but isn't necessary yet (this problem already exists in past
+ // commits anyway)
+ switch (qualifier) {
+ case QShaderLanguage::Const:
+ return "const";
+ case QShaderLanguage::Input:
+ return "varying";
+ case QShaderLanguage::Output:
+ return ""; // Although fragment shaders for <=2 only have fixed outputs
+ case QShaderLanguage::Uniform:
+ return "uniform";
+ }
+ } else {
+ switch (qualifier) {
+ case QShaderLanguage::Const:
+ return "const";
+ case QShaderLanguage::Input:
+ return "in";
+ case QShaderLanguage::Output:
+ return "out";
+ case QShaderLanguage::Uniform:
+ return "uniform";
+ }
+ }
+
+ Q_UNREACHABLE();
+ }
+
+ QByteArray toGlsl(QShaderLanguage::VariableType type)
+ {
+ switch (type) {
+ case QShaderLanguage::Bool:
+ return "bool";
+ case QShaderLanguage::Int:
+ return "int";
+ case QShaderLanguage::Uint:
+ return "uint";
+ case QShaderLanguage::Float:
+ return "float";
+ case QShaderLanguage::Double:
+ return "double";
+ case QShaderLanguage::Vec2:
+ return "vec2";
+ case QShaderLanguage::Vec3:
+ return "vec3";
+ case QShaderLanguage::Vec4:
+ return "vec4";
+ case QShaderLanguage::DVec2:
+ return "dvec2";
+ case QShaderLanguage::DVec3:
+ return "dvec3";
+ case QShaderLanguage::DVec4:
+ return "dvec4";
+ case QShaderLanguage::BVec2:
+ return "bvec2";
+ case QShaderLanguage::BVec3:
+ return "bvec3";
+ case QShaderLanguage::BVec4:
+ return "bvec4";
+ case QShaderLanguage::IVec2:
+ return "ivec2";
+ case QShaderLanguage::IVec3:
+ return "ivec3";
+ case QShaderLanguage::IVec4:
+ return "ivec4";
+ case QShaderLanguage::UVec2:
+ return "uvec2";
+ case QShaderLanguage::UVec3:
+ return "uvec3";
+ case QShaderLanguage::UVec4:
+ return "uvec4";
+ case QShaderLanguage::Mat2:
+ return "mat2";
+ case QShaderLanguage::Mat3:
+ return "mat3";
+ case QShaderLanguage::Mat4:
+ return "mat4";
+ case QShaderLanguage::Mat2x2:
+ return "mat2x2";
+ case QShaderLanguage::Mat2x3:
+ return "mat2x3";
+ case QShaderLanguage::Mat2x4:
+ return "mat2x4";
+ case QShaderLanguage::Mat3x2:
+ return "mat3x2";
+ case QShaderLanguage::Mat3x3:
+ return "mat3x3";
+ case QShaderLanguage::Mat3x4:
+ return "mat3x4";
+ case QShaderLanguage::Mat4x2:
+ return "mat4x2";
+ case QShaderLanguage::Mat4x3:
+ return "mat4x3";
+ case QShaderLanguage::Mat4x4:
+ return "mat4x4";
+ case QShaderLanguage::DMat2:
+ return "dmat2";
+ case QShaderLanguage::DMat3:
+ return "dmat3";
+ case QShaderLanguage::DMat4:
+ return "dmat4";
+ case QShaderLanguage::DMat2x2:
+ return "dmat2x2";
+ case QShaderLanguage::DMat2x3:
+ return "dmat2x3";
+ case QShaderLanguage::DMat2x4:
+ return "dmat2x4";
+ case QShaderLanguage::DMat3x2:
+ return "dmat3x2";
+ case QShaderLanguage::DMat3x3:
+ return "dmat3x3";
+ case QShaderLanguage::DMat3x4:
+ return "dmat3x4";
+ case QShaderLanguage::DMat4x2:
+ return "dmat4x2";
+ case QShaderLanguage::DMat4x3:
+ return "dmat4x3";
+ case QShaderLanguage::DMat4x4:
+ return "dmat4x4";
+ case QShaderLanguage::Sampler1D:
+ return "sampler1D";
+ case QShaderLanguage::Sampler2D:
+ return "sampler2D";
+ case QShaderLanguage::Sampler3D:
+ return "sampler3D";
+ case QShaderLanguage::SamplerCube:
+ return "samplerCube";
+ case QShaderLanguage::Sampler2DRect:
+ return "sampler2DRect";
+ case QShaderLanguage::Sampler2DMs:
+ return "sampler2DMS";
+ case QShaderLanguage::SamplerBuffer:
+ return "samplerBuffer";
+ case QShaderLanguage::Sampler1DArray:
+ return "sampler1DArray";
+ case QShaderLanguage::Sampler2DArray:
+ return "sampler2DArray";
+ case QShaderLanguage::Sampler2DMsArray:
+ return "sampler2DMSArray";
+ case QShaderLanguage::SamplerCubeArray:
+ return "samplerCubeArray";
+ case QShaderLanguage::Sampler1DShadow:
+ return "sampler1DShadow";
+ case QShaderLanguage::Sampler2DShadow:
+ return "sampler2DShadow";
+ case QShaderLanguage::Sampler2DRectShadow:
+ return "sampler2DRectShadow";
+ case QShaderLanguage::Sampler1DArrayShadow:
+ return "sampler1DArrayShadow";
+ case QShaderLanguage::Sampler2DArrayShadow:
+ return "sample2DArrayShadow";
+ case QShaderLanguage::SamplerCubeShadow:
+ return "samplerCubeShadow";
+ case QShaderLanguage::SamplerCubeArrayShadow:
+ return "samplerCubeArrayShadow";
+ case QShaderLanguage::ISampler1D:
+ return "isampler1D";
+ case QShaderLanguage::ISampler2D:
+ return "isampler2D";
+ case QShaderLanguage::ISampler3D:
+ return "isampler3D";
+ case QShaderLanguage::ISamplerCube:
+ return "isamplerCube";
+ case QShaderLanguage::ISampler2DRect:
+ return "isampler2DRect";
+ case QShaderLanguage::ISampler2DMs:
+ return "isampler2DMS";
+ case QShaderLanguage::ISamplerBuffer:
+ return "isamplerBuffer";
+ case QShaderLanguage::ISampler1DArray:
+ return "isampler1DArray";
+ case QShaderLanguage::ISampler2DArray:
+ return "isampler2DArray";
+ case QShaderLanguage::ISampler2DMsArray:
+ return "isampler2DMSArray";
+ case QShaderLanguage::ISamplerCubeArray:
+ return "isamplerCubeArray";
+ case QShaderLanguage::USampler1D:
+ return "usampler1D";
+ case QShaderLanguage::USampler2D:
+ return "usampler2D";
+ case QShaderLanguage::USampler3D:
+ return "usampler3D";
+ case QShaderLanguage::USamplerCube:
+ return "usamplerCube";
+ case QShaderLanguage::USampler2DRect:
+ return "usampler2DRect";
+ case QShaderLanguage::USampler2DMs:
+ return "usampler2DMS";
+ case QShaderLanguage::USamplerBuffer:
+ return "usamplerBuffer";
+ case QShaderLanguage::USampler1DArray:
+ return "usampler1DArray";
+ case QShaderLanguage::USampler2DArray:
+ return "usampler2DArray";
+ case QShaderLanguage::USampler2DMsArray:
+ return "usampler2DMSArray";
+ case QShaderLanguage::USamplerCubeArray:
+ return "usamplerCubeArray";
+ }
+
+ Q_UNREACHABLE();
+ }
+
+ QByteArray replaceParameters(const QByteArray &original, const QShaderNode &node, const QShaderFormat &format)
+ {
+ auto result = original;
+
+ for (const auto &parameterName : node.parameterNames()) {
+ const auto placeholder = QByteArray(QByteArrayLiteral("$") + parameterName.toUtf8());
+ const auto parameter = node.parameter(parameterName);
+ if (parameter.userType() == qMetaTypeId<QShaderLanguage::StorageQualifier>()) {
+ const auto qualifier = parameter.value<QShaderLanguage::StorageQualifier>();
+ const auto value = toGlsl(qualifier, format);
+ result.replace(placeholder, value);
+ } else if (parameter.userType() == qMetaTypeId<QShaderLanguage::VariableType>()) {
+ const auto type = parameter.value<QShaderLanguage::VariableType>();
+ const auto value = toGlsl(type);
+ result.replace(placeholder, value);
+ } else {
+ const auto value = parameter.toString().toUtf8();
+ result.replace(placeholder, value);
+ }
+ }
+
+ return result;
+ }
+}
+
+QByteArray QShaderGenerator::createShaderCode(const QStringList &enabledLayers) const
+{
+ auto code = QByteArrayList();
+
+ if (format.isValid()) {
+ const auto isGLES = format.api() == QShaderFormat::OpenGLES;
+ const auto major = format.version().majorVersion();
+ const auto minor = format.version().minorVersion();
+
+ const auto version = major == 2 && isGLES ? 100
+ : major == 3 && isGLES ? 300
+ : major == 2 ? 100 + 10 * (minor + 1)
+ : major == 3 && minor <= 2 ? 100 + 10 * (minor + 3)
+ : major * 100 + minor * 10;
+
+ const auto profile = isGLES && version > 100 ? QByteArrayLiteral(" es")
+ : version >= 150 && format.api() == QShaderFormat::OpenGLCoreProfile ? QByteArrayLiteral(" core")
+ : version >= 150 && format.api() == QShaderFormat::OpenGLCompatibilityProfile ? QByteArrayLiteral(" compatibility")
+ : QByteArray();
+
+ code << (QByteArrayLiteral("#version ") + QByteArray::number(version) + profile);
+ code << QByteArray();
+ }
+
+ const auto intersectsEnabledLayers = [enabledLayers] (const QStringList &layers) {
+ return layers.isEmpty()
+ || std::any_of(layers.cbegin(), layers.cend(),
+ [enabledLayers] (const QString &s) { return enabledLayers.contains(s); });
+ };
+
+ for (const auto &node : graph.nodes()) {
+ if (intersectsEnabledLayers(node.layers())) {
+ for (const auto &snippet : node.rule(format).headerSnippets) {
+ code << replaceParameters(snippet, node, format);
+ }
+ }
+ }
+
+ code << QByteArray();
+ code << QByteArrayLiteral("void main()");
+ code << QByteArrayLiteral("{");
+
+ for (const auto &statement : graph.createStatements(enabledLayers)) {
+ const auto node = statement.node;
+ auto line = node.rule(format).substitution;
+ for (const auto &port : node.ports()) {
+ const auto portName = port.name;
+ const auto portDirection = port.direction;
+ const auto isInput = port.direction == QShaderNodePort::Input;
+
+ const auto portIndex = statement.portIndex(portDirection, portName);
+ const auto variableIndex = isInput ? statement.inputs.at(portIndex)
+ : statement.outputs.at(portIndex);
+ if (variableIndex < 0)
+ continue;
+
+ const auto placeholder = QByteArray(QByteArrayLiteral("$") + portName.toUtf8());
+ const auto variable = QByteArray(QByteArrayLiteral("v") + QByteArray::number(variableIndex));
+ line.replace(placeholder, variable);
+ }
+
+ code << QByteArrayLiteral(" ") + replaceParameters(line, node, format);
+ }
+
+ code << QByteArrayLiteral("}");
+ code << QByteArray();
+ return code.join('\n');
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/util/qshadergenerator_p.h b/src/gui/util/qshadergenerator_p.h
new file mode 100644
index 0000000000..7bc8838b52
--- /dev/null
+++ b/src/gui/util/qshadergenerator_p.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** 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 QSHADERGENERATOR_P_H
+#define QSHADERGENERATOR_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtGui/private/qtguiglobal_p.h>
+
+#include <QtGui/private/qshadergraph_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QShaderGenerator
+{
+public:
+ Q_GUI_EXPORT QByteArray createShaderCode(const QStringList &enabledLayers = QStringList()) const;
+
+ QShaderGraph graph;
+ QShaderFormat format;
+};
+
+Q_DECLARE_TYPEINFO(QShaderGenerator, Q_MOVABLE_TYPE);
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QShaderGenerator)
+
+#endif // QSHADERGENERATOR_P_H
diff --git a/src/gui/util/qshadergraph.cpp b/src/gui/util/qshadergraph.cpp
new file mode 100644
index 0000000000..828c709a12
--- /dev/null
+++ b/src/gui/util/qshadergraph.cpp
@@ -0,0 +1,262 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** 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 "qshadergraph_p.h"
+
+QT_BEGIN_NAMESPACE
+
+
+namespace
+{
+ QVector<QShaderNode> copyOutputNodes(const QVector<QShaderNode> &nodes)
+ {
+ auto res = QVector<QShaderNode>();
+ std::copy_if(nodes.cbegin(), nodes.cend(),
+ std::back_inserter(res),
+ [] (const QShaderNode &node) {
+ return node.type() == QShaderNode::Output;
+ });
+ return res;
+ }
+
+ QVector<QShaderGraph::Edge> incomingEdges(const QVector<QShaderGraph::Edge> &edges, const QUuid &uuid)
+ {
+ auto res = QVector<QShaderGraph::Edge>();
+ std::copy_if(edges.cbegin(), edges.cend(),
+ std::back_inserter(res),
+ [uuid] (const QShaderGraph::Edge &edge) {
+ return edge.sourceNodeUuid == uuid;
+ });
+ return res;
+ }
+
+ QVector<QShaderGraph::Edge> outgoingEdges(const QVector<QShaderGraph::Edge> &edges, const QUuid &uuid)
+ {
+ auto res = QVector<QShaderGraph::Edge>();
+ std::copy_if(edges.cbegin(), edges.cend(),
+ std::back_inserter(res),
+ [uuid] (const QShaderGraph::Edge &edge) {
+ return edge.targetNodeUuid == uuid;
+ });
+ return res;
+ }
+
+ QShaderGraph::Statement nodeToStatement(const QShaderNode &node, int &nextVarId)
+ {
+ auto statement = QShaderGraph::Statement();
+ statement.node = node;
+
+ const auto ports = node.ports();
+ for (const auto &port : ports) {
+ if (port.direction == QShaderNodePort::Input) {
+ statement.inputs.append(-1);
+ } else {
+ statement.outputs.append(nextVarId);
+ nextVarId++;
+ }
+ }
+ return statement;
+ }
+
+ QShaderGraph::Statement completeStatement(const QHash<QUuid, QShaderGraph::Statement> &idHash,
+ const QVector<QShaderGraph::Edge> edges,
+ const QUuid &uuid)
+ {
+ auto targetStatement = idHash.value(uuid);
+ for (const auto &edge : edges) {
+ if (edge.targetNodeUuid != uuid)
+ continue;
+
+ const auto sourceStatement = idHash.value(edge.sourceNodeUuid);
+ const auto sourcePortIndex = sourceStatement.portIndex(QShaderNodePort::Output, edge.sourcePortName);
+ const auto targetPortIndex = targetStatement.portIndex(QShaderNodePort::Input, edge.targetPortName);
+
+ if (sourcePortIndex < 0 || targetPortIndex < 0)
+ continue;
+
+ const auto &sourceOutputs = sourceStatement.outputs;
+ auto &targetInputs = targetStatement.inputs;
+ targetInputs[targetPortIndex] = sourceOutputs[sourcePortIndex];
+ }
+ return targetStatement;
+ }
+}
+
+QUuid QShaderGraph::Statement::uuid() const Q_DECL_NOTHROW
+{
+ return node.uuid();
+}
+
+int QShaderGraph::Statement::portIndex(QShaderNodePort::Direction direction, const QString &portName) const Q_DECL_NOTHROW
+{
+ const auto ports = node.ports();
+ int index = 0;
+ for (const auto &port : ports) {
+ if (port.name == portName && port.direction == direction)
+ return index;
+ else if (port.direction == direction)
+ index++;
+ }
+ return -1;
+}
+
+void QShaderGraph::addNode(const QShaderNode &node)
+{
+ removeNode(node);
+ m_nodes.append(node);
+}
+
+void QShaderGraph::removeNode(const QShaderNode &node)
+{
+ const auto it = std::find_if(m_nodes.begin(), m_nodes.end(),
+ [node] (const QShaderNode &n) { return n.uuid() == node.uuid(); });
+ if (it != m_nodes.end())
+ m_nodes.erase(it);
+}
+
+QVector<QShaderNode> QShaderGraph::nodes() const Q_DECL_NOTHROW
+{
+ return m_nodes;
+}
+
+void QShaderGraph::addEdge(const QShaderGraph::Edge &edge)
+{
+ if (m_edges.contains(edge))
+ return;
+ m_edges.append(edge);
+}
+
+void QShaderGraph::removeEdge(const QShaderGraph::Edge &edge)
+{
+ m_edges.removeAll(edge);
+}
+
+QVector<QShaderGraph::Edge> QShaderGraph::edges() const Q_DECL_NOTHROW
+{
+ return m_edges;
+}
+
+QVector<QShaderGraph::Statement> QShaderGraph::createStatements(const QStringList &enabledLayers) const
+{
+ const auto intersectsEnabledLayers = [enabledLayers] (const QStringList &layers) {
+ return layers.isEmpty()
+ || std::any_of(layers.cbegin(), layers.cend(),
+ [enabledLayers] (const QString &s) { return enabledLayers.contains(s); });
+ };
+
+ const auto enabledNodes = [this, intersectsEnabledLayers] {
+ auto res = QVector<QShaderNode>();
+ std::copy_if(m_nodes.cbegin(), m_nodes.cend(),
+ std::back_inserter(res),
+ [intersectsEnabledLayers] (const QShaderNode &node) {
+ return intersectsEnabledLayers(node.layers());
+ });
+ return res;
+ }();
+
+ const auto enabledEdges = [this, intersectsEnabledLayers] {
+ auto res = QVector<Edge>();
+ std::copy_if(m_edges.cbegin(), m_edges.cend(),
+ std::back_inserter(res),
+ [intersectsEnabledLayers] (const Edge &edge) {
+ return intersectsEnabledLayers(edge.layers);
+ });
+ return res;
+ }();
+
+ const auto idHash = [enabledNodes] {
+ auto nextVarId = 0;
+ auto res = QHash<QUuid, Statement>();
+ for (const auto &node : enabledNodes)
+ res.insert(node.uuid(), nodeToStatement(node, nextVarId));
+ return res;
+ }();
+
+ auto result = QVector<Statement>();
+ auto currentEdges = enabledEdges;
+ auto currentUuids = [enabledNodes] {
+ const auto inputs = copyOutputNodes(enabledNodes);
+ auto res = QVector<QUuid>();
+ std::transform(inputs.cbegin(), inputs.cend(),
+ std::back_inserter(res),
+ [](const QShaderNode &node) { return node.uuid(); });
+ return res;
+ }();
+
+ // Implements Kahn's algorithm to flatten the graph
+ // https://en.wikipedia.org/wiki/Topological_sorting#Kahn.27s_algorithm
+ //
+ // We implement it with a small twist though, we follow the edges backward
+ // because we want to track the dependencies from the output nodes and not the
+ // input nodes
+ while (!currentUuids.isEmpty()) {
+ const auto uuid = currentUuids.takeFirst();
+ result.append(completeStatement(idHash, enabledEdges, uuid));
+
+ const auto outgoing = outgoingEdges(currentEdges, uuid);
+ for (const auto &outgoingEdge : outgoing) {
+ currentEdges.removeAll(outgoingEdge);
+ const QUuid nextUuid = outgoingEdge.sourceNodeUuid;
+ const auto incoming = incomingEdges(currentEdges, nextUuid);
+ if (incoming.isEmpty()) {
+ currentUuids.append(nextUuid);
+ }
+ }
+ }
+
+ std::reverse(result.begin(), result.end());
+ return result;
+}
+
+bool operator==(const QShaderGraph::Edge &lhs, const QShaderGraph::Edge &rhs) Q_DECL_NOTHROW
+{
+ return lhs.sourceNodeUuid == rhs.sourceNodeUuid
+ && lhs.sourcePortName == rhs.sourcePortName
+ && lhs.targetNodeUuid == rhs.targetNodeUuid
+ && lhs.targetPortName == rhs.targetPortName;
+}
+
+bool operator==(const QShaderGraph::Statement &lhs, const QShaderGraph::Statement &rhs) Q_DECL_NOTHROW
+{
+ return lhs.inputs == rhs.inputs
+ && lhs.outputs == rhs.outputs
+ && lhs.node.uuid() == rhs.node.uuid();
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/util/qshadergraph_p.h b/src/gui/util/qshadergraph_p.h
new file mode 100644
index 0000000000..756e1b2da2
--- /dev/null
+++ b/src/gui/util/qshadergraph_p.h
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** 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 QSHADERGRAPH_P_H
+#define QSHADERGRAPH_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtGui/private/qtguiglobal_p.h>
+
+#include <QtGui/private/qshadernode_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QShaderGraph
+{
+public:
+ class Edge
+ {
+ public:
+ QStringList layers;
+ QUuid sourceNodeUuid;
+ QString sourcePortName;
+ QUuid targetNodeUuid;
+ QString targetPortName;
+ };
+
+ class Statement
+ {
+ public:
+ Q_GUI_EXPORT QUuid uuid() const Q_DECL_NOTHROW;
+ Q_GUI_EXPORT int portIndex(QShaderNodePort::Direction direction, const QString &portName) const Q_DECL_NOTHROW;
+
+ QShaderNode node;
+ QVector<int> inputs;
+ QVector<int> outputs;
+ };
+
+ Q_GUI_EXPORT void addNode(const QShaderNode &node);
+ Q_GUI_EXPORT void removeNode(const QShaderNode &node);
+ Q_GUI_EXPORT QVector<QShaderNode> nodes() const Q_DECL_NOTHROW;
+
+ Q_GUI_EXPORT void addEdge(const Edge &edge);
+ Q_GUI_EXPORT void removeEdge(const Edge &edge);
+ Q_GUI_EXPORT QVector<Edge> edges() const Q_DECL_NOTHROW;
+
+ Q_GUI_EXPORT QVector<Statement> createStatements(const QStringList &enabledLayers = QStringList()) const;
+
+private:
+ QVector<QShaderNode> m_nodes;
+ QVector<Edge> m_edges;
+};
+
+Q_GUI_EXPORT bool operator==(const QShaderGraph::Edge &lhs, const QShaderGraph::Edge &rhs) Q_DECL_NOTHROW;
+
+inline bool operator!=(const QShaderGraph::Edge &lhs, const QShaderGraph::Edge &rhs) Q_DECL_NOTHROW
+{
+ return !(lhs == rhs);
+}
+
+Q_GUI_EXPORT bool operator==(const QShaderGraph::Statement &lhs, const QShaderGraph::Statement &rhs) Q_DECL_NOTHROW;
+
+inline bool operator!=(const QShaderGraph::Statement &lhs, const QShaderGraph::Statement &rhs) Q_DECL_NOTHROW
+{
+ return !(lhs == rhs);
+}
+
+Q_DECLARE_TYPEINFO(QShaderGraph, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QShaderGraph::Edge, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QShaderGraph::Statement, Q_MOVABLE_TYPE);
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QShaderGraph)
+Q_DECLARE_METATYPE(QShaderGraph::Edge)
+Q_DECLARE_METATYPE(QShaderGraph::Statement)
+
+#endif // QSHADERGRAPH_P_H
diff --git a/src/gui/util/qshadergraphloader.cpp b/src/gui/util/qshadergraphloader.cpp
new file mode 100644
index 0000000000..c7560d9105
--- /dev/null
+++ b/src/gui/util/qshadergraphloader.cpp
@@ -0,0 +1,251 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** 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 "qshadergraphloader_p.h"
+
+#include <QtCore/qdebug.h>
+#include <QtCore/qiodevice.h>
+#include <QtCore/qjsonarray.h>
+#include <QtCore/qjsondocument.h>
+#include <QtCore/qjsonobject.h>
+#include <QtCore/qmetaobject.h>
+
+QT_BEGIN_NAMESPACE
+
+QShaderGraphLoader::QShaderGraphLoader() Q_DECL_NOTHROW
+ : m_status(Null),
+ m_device(nullptr)
+{
+}
+
+QShaderGraphLoader::Status QShaderGraphLoader::status() const Q_DECL_NOTHROW
+{
+ return m_status;
+}
+
+QShaderGraph QShaderGraphLoader::graph() const Q_DECL_NOTHROW
+{
+ return m_graph;
+}
+
+QIODevice *QShaderGraphLoader::device() const Q_DECL_NOTHROW
+{
+ return m_device;
+}
+
+void QShaderGraphLoader::setDevice(QIODevice *device) Q_DECL_NOTHROW
+{
+ m_device = device;
+ m_graph = QShaderGraph();
+ m_status = !m_device ? Null
+ : (m_device->openMode() & QIODevice::ReadOnly) ? Waiting
+ : Error;
+}
+
+QHash<QString, QShaderNode> QShaderGraphLoader::prototypes() const Q_DECL_NOTHROW
+{
+ return m_prototypes;
+}
+
+void QShaderGraphLoader::setPrototypes(const QHash<QString, QShaderNode> &prototypes) Q_DECL_NOTHROW
+{
+ m_prototypes = prototypes;
+}
+
+void QShaderGraphLoader::load()
+{
+ if (m_status == Error)
+ return;
+
+ auto error = QJsonParseError();
+ const auto document = QJsonDocument::fromJson(m_device->readAll(), &error);
+
+ if (error.error != QJsonParseError::NoError) {
+ qWarning() << "Invalid JSON document:" << error.errorString();
+ m_status = Error;
+ return;
+ }
+
+ if (document.isEmpty() || !document.isObject()) {
+ qWarning() << "Invalid JSON document, root should be an object";
+ m_status = Error;
+ return;
+ }
+
+ const auto root = document.object();
+
+ const auto nodesValue = root.value(QStringLiteral("nodes"));
+ if (!nodesValue.isArray()) {
+ qWarning() << "Invalid nodes property, should be an array";
+ m_status = Error;
+ return;
+ }
+
+ const auto edgesValue = root.value(QStringLiteral("edges"));
+ if (!edgesValue.isArray()) {
+ qWarning() << "Invalid edges property, should be an array";
+ m_status = Error;
+ return;
+ }
+
+ bool hasError = false;
+
+ const auto nodes = nodesValue.toArray();
+ for (const auto &nodeValue : nodes) {
+ if (!nodeValue.isObject()) {
+ qWarning() << "Invalid node found";
+ hasError = true;
+ continue;
+ }
+
+ const auto nodeObject = nodeValue.toObject();
+
+ const auto uuidString = nodeObject.value(QStringLiteral("uuid")).toString();
+ const auto uuid = QUuid(uuidString);
+ if (uuid.isNull()) {
+ qWarning() << "Invalid UUID found in node:" << uuidString;
+ hasError = true;
+ continue;
+ }
+
+ const auto type = nodeObject.value(QStringLiteral("type")).toString();
+ if (!m_prototypes.contains(type)) {
+ qWarning() << "Unsupported node type found:" << type;
+ hasError = true;
+ continue;
+ }
+
+ const auto layersArray = nodeObject.value(QStringLiteral("layers")).toArray();
+ auto layers = QStringList();
+ for (const auto &layerValue : layersArray) {
+ layers.append(layerValue.toString());
+ }
+
+ auto node = m_prototypes.value(type);
+ node.setUuid(uuid);
+ node.setLayers(layers);
+
+ const auto parametersValue = nodeObject.value(QStringLiteral("parameters"));
+ if (parametersValue.isObject()) {
+ const auto parametersObject = parametersValue.toObject();
+ for (const auto &parameterName : parametersObject.keys()) {
+ const auto parameterValue = parametersObject.value(parameterName);
+ if (parameterValue.isObject()) {
+ const auto parameterObject = parameterValue.toObject();
+ const auto type = parameterObject.value(QStringLiteral("type")).toString();
+ const auto typeId = QMetaType::type(type.toUtf8());
+
+ const auto value = parameterObject.value(QStringLiteral("value")).toString();
+ auto variant = QVariant(value);
+
+ if (QMetaType::typeFlags(typeId) & QMetaType::IsEnumeration) {
+ const auto metaObject = QMetaType::metaObjectForType(typeId);
+ const auto className = metaObject->className();
+ const auto enumName = type.mid(static_cast<int>(qstrlen(className)) + 2).toUtf8();
+ const auto metaEnum = metaObject->enumerator(metaObject->indexOfEnumerator(enumName));
+ const auto enumValue = metaEnum.keyToValue(value.toUtf8());
+ variant = QVariant(enumValue);
+ variant.convert(typeId);
+ } else {
+ variant.convert(typeId);
+ }
+ node.setParameter(parameterName, variant);
+ } else {
+ node.setParameter(parameterName, parameterValue.toVariant());
+ }
+ }
+ }
+
+ m_graph.addNode(node);
+ }
+
+ const auto edges = edgesValue.toArray();
+ for (const auto &edgeValue : edges) {
+ if (!edgeValue.isObject()) {
+ qWarning() << "Invalid edge found";
+ hasError = true;
+ continue;
+ }
+
+ const auto edgeObject = edgeValue.toObject();
+
+ const auto sourceUuidString = edgeObject.value(QStringLiteral("sourceUuid")).toString();
+ const auto sourceUuid = QUuid(sourceUuidString);
+ if (sourceUuid.isNull()) {
+ qWarning() << "Invalid source UUID found in edge:" << sourceUuidString;
+ hasError = true;
+ continue;
+ }
+
+ const auto sourcePort = edgeObject.value(QStringLiteral("sourcePort")).toString();
+
+ const auto targetUuidString = edgeObject.value(QStringLiteral("targetUuid")).toString();
+ const auto targetUuid = QUuid(targetUuidString);
+ if (targetUuid.isNull()) {
+ qWarning() << "Invalid target UUID found in edge:" << targetUuidString;
+ hasError = true;
+ continue;
+ }
+
+ const auto targetPort = edgeObject.value(QStringLiteral("targetPort")).toString();
+
+ const auto layersArray = edgeObject.value(QStringLiteral("layers")).toArray();
+ auto layers = QStringList();
+ for (const auto &layerValue : layersArray) {
+ layers.append(layerValue.toString());
+ }
+
+ auto edge = QShaderGraph::Edge();
+ edge.sourceNodeUuid = sourceUuid;
+ edge.sourcePortName = sourcePort;
+ edge.targetNodeUuid = targetUuid;
+ edge.targetPortName = targetPort;
+ edge.layers = layers;
+ m_graph.addEdge(edge);
+ }
+
+ if (hasError) {
+ m_status = Error;
+ m_graph = QShaderGraph();
+ } else {
+ m_status = Ready;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/util/qshadergraphloader_p.h b/src/gui/util/qshadergraphloader_p.h
new file mode 100644
index 0000000000..97cbd8d18c
--- /dev/null
+++ b/src/gui/util/qshadergraphloader_p.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** 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 QSHADERGRAPHLOADER_P_H
+#define QSHADERGRAPHLOADER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtGui/private/qtguiglobal_p.h>
+
+#include <QtGui/private/qshadergraph_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QIODevice;
+
+class QShaderGraphLoader
+{
+public:
+ enum Status : char {
+ Null,
+ Waiting,
+ Ready,
+ Error
+ };
+
+ Q_GUI_EXPORT QShaderGraphLoader() Q_DECL_NOTHROW;
+
+ Q_GUI_EXPORT Status status() const Q_DECL_NOTHROW;
+ Q_GUI_EXPORT QShaderGraph graph() const Q_DECL_NOTHROW;
+
+ Q_GUI_EXPORT QIODevice *device() const Q_DECL_NOTHROW;
+ Q_GUI_EXPORT void setDevice(QIODevice *device) Q_DECL_NOTHROW;
+
+ Q_GUI_EXPORT QHash<QString, QShaderNode> prototypes() const Q_DECL_NOTHROW;
+ Q_GUI_EXPORT void setPrototypes(const QHash<QString, QShaderNode> &prototypes) Q_DECL_NOTHROW;
+
+ Q_GUI_EXPORT void load();
+
+private:
+ Status m_status;
+ QIODevice *m_device;
+ QHash<QString, QShaderNode> m_prototypes;
+ QShaderGraph m_graph;
+};
+
+Q_DECLARE_TYPEINFO(QShaderGraphLoader, Q_MOVABLE_TYPE);
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QShaderGraphLoader)
+Q_DECLARE_METATYPE(QShaderGraphLoader::Status)
+
+#endif // QSHADERGRAPHLOADER_P_H
diff --git a/src/gui/util/qshaderlanguage.cpp b/src/gui/util/qshaderlanguage.cpp
new file mode 100644
index 0000000000..4a0da5bfb5
--- /dev/null
+++ b/src/gui/util/qshaderlanguage.cpp
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Layouts 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 "qshaderlanguage_p.h"
+
+#include <QtCore/qcoreapplication.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace {
+ void registerEnums()
+ {
+ qRegisterMetaType<QShaderLanguage::StorageQualifier>();
+ qRegisterMetaType<QShaderLanguage::VariableType>();
+ }
+}
+
+Q_COREAPP_STARTUP_FUNCTION(registerEnums)
+
+QT_END_NAMESPACE
diff --git a/src/gui/util/qshaderlanguage_p.h b/src/gui/util/qshaderlanguage_p.h
new file mode 100644
index 0000000000..5c7819a3b8
--- /dev/null
+++ b/src/gui/util/qshaderlanguage_p.h
@@ -0,0 +1,163 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Layouts 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 QSHADERLANGUAGE_P_H
+#define QSHADERLANGUAGE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtGui/private/qtguiglobal_p.h>
+
+#include <QtCore/qmetatype.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QShaderLanguage
+{
+ Q_GUI_EXPORT Q_NAMESPACE
+
+ enum StorageQualifier : char {
+ Const = 1,
+ Input,
+ Output,
+ Uniform
+ };
+ Q_ENUM_NS(StorageQualifier)
+
+ enum VariableType : int {
+ Bool = 1,
+ Int,
+ Uint,
+ Float,
+ Double,
+ Vec2,
+ Vec3,
+ Vec4,
+ DVec2,
+ DVec3,
+ DVec4,
+ BVec2,
+ BVec3,
+ BVec4,
+ IVec2,
+ IVec3,
+ IVec4,
+ UVec2,
+ UVec3,
+ UVec4,
+ Mat2,
+ Mat3,
+ Mat4,
+ Mat2x2,
+ Mat2x3,
+ Mat2x4,
+ Mat3x2,
+ Mat3x3,
+ Mat3x4,
+ Mat4x2,
+ Mat4x3,
+ Mat4x4,
+ DMat2,
+ DMat3,
+ DMat4,
+ DMat2x2,
+ DMat2x3,
+ DMat2x4,
+ DMat3x2,
+ DMat3x3,
+ DMat3x4,
+ DMat4x2,
+ DMat4x3,
+ DMat4x4,
+ Sampler1D,
+ Sampler2D,
+ Sampler3D,
+ SamplerCube,
+ Sampler2DRect,
+ Sampler2DMs,
+ SamplerBuffer,
+ Sampler1DArray,
+ Sampler2DArray,
+ Sampler2DMsArray,
+ SamplerCubeArray,
+ Sampler1DShadow,
+ Sampler2DShadow,
+ Sampler2DRectShadow,
+ Sampler1DArrayShadow,
+ Sampler2DArrayShadow,
+ SamplerCubeShadow,
+ SamplerCubeArrayShadow,
+ ISampler1D,
+ ISampler2D,
+ ISampler3D,
+ ISamplerCube,
+ ISampler2DRect,
+ ISampler2DMs,
+ ISamplerBuffer,
+ ISampler1DArray,
+ ISampler2DArray,
+ ISampler2DMsArray,
+ ISamplerCubeArray,
+ USampler1D,
+ USampler2D,
+ USampler3D,
+ USamplerCube,
+ USampler2DRect,
+ USampler2DMs,
+ USamplerBuffer,
+ USampler1DArray,
+ USampler2DArray,
+ USampler2DMsArray,
+ USamplerCubeArray
+ };
+ Q_ENUM_NS(VariableType)
+}
+
+QT_END_NAMESPACE
+
+#endif // QSHADERLANGUAGE_P_H
diff --git a/src/gui/util/qshadernode.cpp b/src/gui/util/qshadernode.cpp
new file mode 100644
index 0000000000..676667ddcf
--- /dev/null
+++ b/src/gui/util/qshadernode.cpp
@@ -0,0 +1,172 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Layouts 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 "qshadernode_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QShaderNode::Type QShaderNode::type() const Q_DECL_NOTHROW
+{
+ int inputCount = 0;
+ int outputCount = 0;
+ for (const auto &port : qAsConst(m_ports)) {
+ switch (port.direction) {
+ case QShaderNodePort::Input:
+ inputCount++;
+ break;
+ case QShaderNodePort::Output:
+ outputCount++;
+ break;
+ }
+ }
+
+ return (inputCount == 0 && outputCount == 0) ? Invalid
+ : (inputCount > 0 && outputCount == 0) ? Output
+ : (inputCount == 0 && outputCount > 0) ? Input
+ : Function;
+}
+
+QUuid QShaderNode::uuid() const Q_DECL_NOTHROW
+{
+ return m_uuid;
+}
+
+void QShaderNode::setUuid(const QUuid &uuid) Q_DECL_NOTHROW
+{
+ m_uuid = uuid;
+}
+
+QStringList QShaderNode::layers() const Q_DECL_NOTHROW
+{
+ return m_layers;
+}
+
+void QShaderNode::setLayers(const QStringList &layers) Q_DECL_NOTHROW
+{
+ m_layers = layers;
+}
+
+QVector<QShaderNodePort> QShaderNode::ports() const Q_DECL_NOTHROW
+{
+ return m_ports;
+}
+
+void QShaderNode::addPort(const QShaderNodePort &port)
+{
+ removePort(port);
+ m_ports.append(port);
+}
+
+void QShaderNode::removePort(const QShaderNodePort &port)
+{
+ const auto it = std::find_if(m_ports.begin(), m_ports.end(),
+ [port](const QShaderNodePort &p) {
+ return p.name == port.name;
+ });
+ if (it != m_ports.end())
+ m_ports.erase(it);
+}
+
+QStringList QShaderNode::parameterNames() const
+{
+ return m_parameters.keys();
+}
+
+QVariant QShaderNode::parameter(const QString &name) const
+{
+ return m_parameters.value(name);
+}
+
+void QShaderNode::setParameter(const QString &name, const QVariant &value)
+{
+ m_parameters.insert(name, value);
+}
+
+void QShaderNode::clearParameter(const QString &name)
+{
+ m_parameters.remove(name);
+}
+
+void QShaderNode::addRule(const QShaderFormat &format, const QShaderNode::Rule &rule)
+{
+ removeRule(format);
+ m_rules << qMakePair(format, rule);
+}
+
+void QShaderNode::removeRule(const QShaderFormat &format)
+{
+ const auto it = std::find_if(m_rules.begin(), m_rules.end(),
+ [format](const QPair<QShaderFormat, Rule> &entry) {
+ return entry.first == format;
+ });
+ if (it != m_rules.end())
+ m_rules.erase(it);
+}
+
+QVector<QShaderFormat> QShaderNode::availableFormats() const
+{
+ auto res = QVector<QShaderFormat>();
+ std::transform(m_rules.cbegin(), m_rules.cend(),
+ std::back_inserter(res),
+ [](const QPair<QShaderFormat, Rule> &entry) { return entry.first; });
+ return res;
+}
+
+QShaderNode::Rule QShaderNode::rule(const QShaderFormat &format) const
+{
+ const auto it = std::find_if(m_rules.crbegin(), m_rules.crend(),
+ [format](const QPair<QShaderFormat, Rule> &entry) {
+ return format.supports(entry.first);
+ });
+ return it != m_rules.crend() ? it->second : Rule();
+}
+
+QShaderNode::Rule::Rule(const QByteArray &subs, const QByteArrayList &snippets) Q_DECL_NOTHROW
+ : substitution(subs),
+ headerSnippets(snippets)
+{
+}
+
+bool operator==(const QShaderNode::Rule &lhs, const QShaderNode::Rule &rhs) Q_DECL_NOTHROW
+{
+ return lhs.substitution == rhs.substitution
+ && lhs.headerSnippets == rhs.headerSnippets;
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/util/qshadernode_p.h b/src/gui/util/qshadernode_p.h
new file mode 100644
index 0000000000..494c87bc18
--- /dev/null
+++ b/src/gui/util/qshadernode_p.h
@@ -0,0 +1,128 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Layouts 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 QSHADERNODE_P_H
+#define QSHADERNODE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtGui/private/qtguiglobal_p.h>
+
+#include <QtGui/private/qshaderformat_p.h>
+#include <QtGui/private/qshadernodeport_p.h>
+
+#include <QtCore/quuid.h>
+
+QT_BEGIN_NAMESPACE
+
+class QShaderNode
+{
+public:
+ enum Type : char {
+ Invalid,
+ Input,
+ Output,
+ Function
+ };
+
+ class Rule
+ {
+ public:
+ Q_GUI_EXPORT Rule(const QByteArray &substitution = QByteArray(), const QByteArrayList &headerSnippets = QByteArrayList()) Q_DECL_NOTHROW;
+
+ QByteArray substitution;
+ QByteArrayList headerSnippets;
+ };
+
+ Q_GUI_EXPORT Type type() const Q_DECL_NOTHROW;
+
+ Q_GUI_EXPORT QUuid uuid() const Q_DECL_NOTHROW;
+ Q_GUI_EXPORT void setUuid(const QUuid &uuid) Q_DECL_NOTHROW;
+
+ Q_GUI_EXPORT QStringList layers() const Q_DECL_NOTHROW;
+ Q_GUI_EXPORT void setLayers(const QStringList &layers) Q_DECL_NOTHROW;
+
+ Q_GUI_EXPORT QVector<QShaderNodePort> ports() const Q_DECL_NOTHROW;
+ Q_GUI_EXPORT void addPort(const QShaderNodePort &port);
+ Q_GUI_EXPORT void removePort(const QShaderNodePort &port);
+
+ Q_GUI_EXPORT QStringList parameterNames() const;
+ Q_GUI_EXPORT QVariant parameter(const QString &name) const;
+ Q_GUI_EXPORT void setParameter(const QString &name, const QVariant &value);
+ Q_GUI_EXPORT void clearParameter(const QString &name);
+
+ Q_GUI_EXPORT void addRule(const QShaderFormat &format, const Rule &rule);
+ Q_GUI_EXPORT void removeRule(const QShaderFormat &format);
+
+ Q_GUI_EXPORT QVector<QShaderFormat> availableFormats() const;
+ Q_GUI_EXPORT Rule rule(const QShaderFormat &format) const;
+
+private:
+ QUuid m_uuid;
+ QStringList m_layers;
+ QVector<QShaderNodePort> m_ports;
+ QHash<QString, QVariant> m_parameters;
+ QVector<QPair<QShaderFormat, QShaderNode::Rule>> m_rules;
+};
+
+Q_GUI_EXPORT bool operator==(const QShaderNode::Rule &lhs, const QShaderNode::Rule &rhs) Q_DECL_NOTHROW;
+
+inline bool operator!=(const QShaderNode::Rule &lhs, const QShaderNode::Rule &rhs) Q_DECL_NOTHROW
+{
+ return !(lhs == rhs);
+}
+
+Q_DECLARE_TYPEINFO(QShaderNode, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QShaderNode::Rule, Q_MOVABLE_TYPE);
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QShaderNode)
+Q_DECLARE_METATYPE(QShaderNode::Rule)
+
+#endif // QSHADERNODE_P_H
diff --git a/src/gui/util/qshadernodeport.cpp b/src/gui/util/qshadernodeport.cpp
new file mode 100644
index 0000000000..03646a9467
--- /dev/null
+++ b/src/gui/util/qshadernodeport.cpp
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** 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 "qshadernodeport_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QShaderNodePort::QShaderNodePort() Q_DECL_NOTHROW
+ : direction(Output)
+{
+}
+
+bool operator==(const QShaderNodePort &lhs, const QShaderNodePort &rhs) Q_DECL_NOTHROW
+{
+ return lhs.direction == rhs.direction
+ && lhs.name == rhs.name;
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/util/qshadernodeport_p.h b/src/gui/util/qshadernodeport_p.h
new file mode 100644
index 0000000000..cfdaf05017
--- /dev/null
+++ b/src/gui/util/qshadernodeport_p.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** 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 QSHADERNODEPORT_P_H
+#define QSHADERNODEPORT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtGui/private/qtguiglobal_p.h>
+
+#include <QtCore/qstring.h>
+#include <QtCore/qvariant.h>
+
+QT_BEGIN_NAMESPACE
+
+class QShaderNodePort
+{
+public:
+ enum Direction : char {
+ Input,
+ Output
+ };
+
+ Q_GUI_EXPORT QShaderNodePort() Q_DECL_NOTHROW;
+
+ QShaderNodePort::Direction direction;
+ QString name;
+};
+
+Q_GUI_EXPORT bool operator==(const QShaderNodePort &lhs, const QShaderNodePort &rhs) Q_DECL_NOTHROW;
+
+inline bool operator!=(const QShaderNodePort &lhs, const QShaderNodePort &rhs) Q_DECL_NOTHROW
+{
+ return !(lhs == rhs);
+}
+
+Q_DECLARE_TYPEINFO(QShaderNodePort, Q_MOVABLE_TYPE);
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QShaderNodePort)
+
+#endif // QSHADERNODEPORT_P_H
diff --git a/src/gui/util/qshadernodesloader.cpp b/src/gui/util/qshadernodesloader.cpp
new file mode 100644
index 0000000000..db34b6d44d
--- /dev/null
+++ b/src/gui/util/qshadernodesloader.cpp
@@ -0,0 +1,274 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** 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 "qshadernodesloader_p.h"
+
+#include <QtCore/qdebug.h>
+#include <QtCore/qiodevice.h>
+#include <QtCore/qjsonarray.h>
+#include <QtCore/qjsondocument.h>
+#include <QtCore/qjsonobject.h>
+#include <QtCore/qmetaobject.h>
+
+QT_BEGIN_NAMESPACE
+
+QShaderNodesLoader::QShaderNodesLoader() Q_DECL_NOTHROW
+ : m_status(Null),
+ m_device(nullptr)
+{
+}
+
+QShaderNodesLoader::Status QShaderNodesLoader::status() const Q_DECL_NOTHROW
+{
+ return m_status;
+}
+
+QHash<QString, QShaderNode> QShaderNodesLoader::nodes() const Q_DECL_NOTHROW
+{
+ return m_nodes;
+}
+
+QIODevice *QShaderNodesLoader::device() const Q_DECL_NOTHROW
+{
+ return m_device;
+}
+
+void QShaderNodesLoader::setDevice(QIODevice *device) Q_DECL_NOTHROW
+{
+ m_device = device;
+ m_nodes.clear();
+ m_status = !m_device ? Null
+ : (m_device->openMode() & QIODevice::ReadOnly) ? Waiting
+ : Error;
+}
+
+void QShaderNodesLoader::load()
+{
+ if (m_status == Error)
+ return;
+
+ auto error = QJsonParseError();
+ const auto document = QJsonDocument::fromJson(m_device->readAll(), &error);
+
+ if (error.error != QJsonParseError::NoError) {
+ qWarning() << "Invalid JSON document:" << error.errorString();
+ m_status = Error;
+ return;
+ }
+
+ if (document.isEmpty() || !document.isObject()) {
+ qWarning() << "Invalid JSON document, root should be an object";
+ m_status = Error;
+ return;
+ }
+
+ const auto root = document.object();
+
+ bool hasError = false;
+
+ for (const auto &property : root.keys()) {
+ const auto nodeValue = root.value(property);
+ if (!nodeValue.isObject()) {
+ qWarning() << "Invalid node found";
+ hasError = true;
+ break;
+ }
+
+ const auto nodeObject = nodeValue.toObject();
+
+ auto node = QShaderNode();
+
+ const auto inputsValue = nodeObject.value(QStringLiteral("inputs"));
+ if (inputsValue.isArray()) {
+ const auto inputsArray = inputsValue.toArray();
+ for (const auto &inputValue : inputsArray) {
+ if (!inputValue.isString()) {
+ qWarning() << "Non-string value in inputs";
+ hasError = true;
+ break;
+ }
+
+ auto input = QShaderNodePort();
+ input.direction = QShaderNodePort::Input;
+ input.name = inputValue.toString();
+ node.addPort(input);
+ }
+ }
+
+ const auto outputsValue = nodeObject.value(QStringLiteral("outputs"));
+ if (outputsValue.isArray()) {
+ const auto outputsArray = outputsValue.toArray();
+ for (const auto &outputValue : outputsArray) {
+ if (!outputValue.isString()) {
+ qWarning() << "Non-string value in outputs";
+ hasError = true;
+ break;
+ }
+
+ auto output = QShaderNodePort();
+ output.direction = QShaderNodePort::Output;
+ output.name = outputValue.toString();
+ node.addPort(output);
+ }
+ }
+
+ const auto parametersValue = nodeObject.value(QStringLiteral("parameters"));
+ if (parametersValue.isObject()) {
+ const auto parametersObject = parametersValue.toObject();
+ for (const auto &parameterName : parametersObject.keys()) {
+ const auto parameterValue = parametersObject.value(parameterName);
+ if (parameterValue.isObject()) {
+ const auto parameterObject = parameterValue.toObject();
+ const auto type = parameterObject.value(QStringLiteral("type")).toString();
+ const auto typeId = QMetaType::type(type.toUtf8());
+
+ const auto value = parameterObject.value(QStringLiteral("value")).toString();
+ auto variant = QVariant(value);
+
+ if (QMetaType::typeFlags(typeId) & QMetaType::IsEnumeration) {
+ const auto metaObject = QMetaType::metaObjectForType(typeId);
+ const auto className = metaObject->className();
+ const auto enumName = type.mid(static_cast<int>(qstrlen(className)) + 2).toUtf8();
+ const auto metaEnum = metaObject->enumerator(metaObject->indexOfEnumerator(enumName));
+ const auto enumValue = metaEnum.keyToValue(value.toUtf8());
+ variant = QVariant(enumValue);
+ variant.convert(typeId);
+ } else {
+ variant.convert(typeId);
+ }
+ node.setParameter(parameterName, variant);
+ } else {
+ node.setParameter(parameterName, parameterValue.toVariant());
+ }
+ }
+ }
+
+ const auto rulesValue = nodeObject.value(QStringLiteral("rules"));
+ if (rulesValue.isArray()) {
+ const auto rulesArray = rulesValue.toArray();
+ for (const auto &ruleValue : rulesArray) {
+ if (!ruleValue.isObject()) {
+ qWarning() << "Rules should be objects";
+ hasError = true;
+ break;
+ }
+
+ const auto ruleObject = ruleValue.toObject();
+
+ const auto formatValue = ruleObject.value(QStringLiteral("format"));
+ if (!formatValue.isObject()) {
+ qWarning() << "Format is mandatory in rules and should be an object";
+ hasError = true;
+ break;
+ }
+
+ const auto formatObject = formatValue.toObject();
+ auto format = QShaderFormat();
+
+ const auto apiValue = formatObject.value(QStringLiteral("api"));
+ if (!apiValue.isString()) {
+ qWarning() << "Format API must be a string";
+ hasError = true;
+ break;
+ }
+
+ const auto api = apiValue.toString();
+ format.setApi(api == QStringLiteral("OpenGLES") ? QShaderFormat::OpenGLES
+ : api == QStringLiteral("OpenGLNoProfile") ? QShaderFormat::OpenGLNoProfile
+ : api == QStringLiteral("OpenGLCoreProfile") ? QShaderFormat::OpenGLCoreProfile
+ : api == QStringLiteral("OpenGLCompatibilityProfile") ? QShaderFormat::OpenGLCompatibilityProfile
+ : QShaderFormat::NoApi);
+ if (format.api() == QShaderFormat::NoApi) {
+ qWarning() << "Format API must be one of: OpenGLES, OpenGLNoProfile, OpenGLCoreProfile or OpenGLCompatibilityProfile";
+ hasError = true;
+ break;
+ }
+
+ const auto majorValue = formatObject.value(QStringLiteral("major"));
+ const auto minorValue = formatObject.value(QStringLiteral("minor"));
+ if (!majorValue.isDouble() || !minorValue.isDouble()) {
+ qWarning() << "Format major and minor version must be values";
+ hasError = true;
+ break;
+ }
+ format.setVersion(QVersionNumber(majorValue.toInt(), minorValue.toInt()));
+
+ const auto extensionsValue = formatObject.value(QStringLiteral("extensions"));
+ const auto extensionsArray = extensionsValue.toArray();
+ auto extensions = QStringList();
+ std::transform(extensionsArray.constBegin(), extensionsArray.constEnd(),
+ std::back_inserter(extensions),
+ [] (const QJsonValue &extensionValue) { return extensionValue.toString(); });
+ format.setExtensions(extensions);
+
+ const auto vendor = formatObject.value(QStringLiteral("vendor")).toString();
+ format.setVendor(vendor);
+
+ const auto substitutionValue = ruleObject.value(QStringLiteral("substitution"));
+ if (!substitutionValue.isString()) {
+ qWarning() << "Substitution needs to be a string";
+ hasError = true;
+ break;
+ }
+
+ const auto substitution = substitutionValue.toString().toUtf8();
+
+ const auto snippetsValue = ruleObject.value(QStringLiteral("headerSnippets"));
+ const auto snippetsArray = snippetsValue.toArray();
+ auto snippets = QByteArrayList();
+ std::transform(snippetsArray.constBegin(), snippetsArray.constEnd(),
+ std::back_inserter(snippets),
+ [] (const QJsonValue &snippetValue) { return snippetValue.toString().toUtf8(); });
+
+ node.addRule(format, QShaderNode::Rule(substitution, snippets));
+ }
+ }
+
+ m_nodes.insert(property, node);
+ }
+
+ if (hasError) {
+ m_status = Error;
+ m_nodes.clear();
+ } else {
+ m_status = Ready;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/util/qshadernodesloader_p.h b/src/gui/util/qshadernodesloader_p.h
new file mode 100644
index 0000000000..2696e958b6
--- /dev/null
+++ b/src/gui/util/qshadernodesloader_p.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** 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 QSHADERNODESLOADER_P_H
+#define QSHADERNODESLOADER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtGui/private/qtguiglobal_p.h>
+
+#include <QtGui/private/qshadergraph_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QIODevice;
+
+class QShaderNodesLoader
+{
+public:
+ enum Status : char {
+ Null,
+ Waiting,
+ Ready,
+ Error
+ };
+
+ Q_GUI_EXPORT QShaderNodesLoader() Q_DECL_NOTHROW;
+
+ Q_GUI_EXPORT Status status() const Q_DECL_NOTHROW;
+ Q_GUI_EXPORT QHash<QString, QShaderNode> nodes() const Q_DECL_NOTHROW;
+
+ Q_GUI_EXPORT QIODevice *device() const Q_DECL_NOTHROW;
+ Q_GUI_EXPORT void setDevice(QIODevice *device) Q_DECL_NOTHROW;
+
+ Q_GUI_EXPORT void load();
+
+private:
+ Status m_status;
+ QIODevice *m_device;
+ QHash<QString, QShaderNode> m_nodes;
+};
+
+Q_DECLARE_TYPEINFO(QShaderNodesLoader, Q_MOVABLE_TYPE);
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QShaderNodesLoader)
+Q_DECLARE_METATYPE(QShaderNodesLoader::Status)
+
+#endif // QSHADERNODESLOADER_P_H
diff --git a/src/gui/util/qvalidator.cpp b/src/gui/util/qvalidator.cpp
index fb9dfc9f69..1709012291 100644
--- a/src/gui/util/qvalidator.cpp
+++ b/src/gui/util/qvalidator.cpp
@@ -420,9 +420,9 @@ QValidator::State QIntValidator::validate(QString & input, int&) const
if (buff.size() == 1 && (buff.at(0) == '+' || buff.at(0) == '-'))
return Intermediate;
- bool ok, overflow;
- qlonglong entered = QLocaleData::bytearrayToLongLong(buff.constData(), 10, &ok, &overflow);
- if (overflow || !ok)
+ bool ok;
+ qlonglong entered = QLocaleData::bytearrayToLongLong(buff.constData(), 10, &ok);
+ if (!ok)
return Invalid;
if (entered >= b && entered <= t) {
@@ -447,9 +447,9 @@ void QIntValidator::fixup(QString &input) const
locale().numberOptions())) {
return;
}
- bool ok, overflow;
- qlonglong entered = QLocaleData::bytearrayToLongLong(buff.constData(), 10, &ok, &overflow);
- if (ok && !overflow)
+ bool ok;
+ qlonglong entered = QLocaleData::bytearrayToLongLong(buff.constData(), 10, &ok);
+ if (ok)
input = locale().toString(entered);
}
diff --git a/src/gui/util/util.pri b/src/gui/util/util.pri
index 79c83599b9..cf3cbee48e 100644
--- a/src/gui/util/util.pri
+++ b/src/gui/util/util.pri
@@ -6,11 +6,27 @@ HEADERS += \
util/qvalidator.h \
util/qgridlayoutengine_p.h \
util/qabstractlayoutstyleinfo_p.h \
- util/qlayoutpolicy_p.h
+ util/qlayoutpolicy_p.h \
+ util/qshaderformat_p.h \
+ util/qshadergenerator_p.h \
+ util/qshadergraph_p.h \
+ util/qshadergraphloader_p.h \
+ util/qshaderlanguage_p.h \
+ util/qshadernode_p.h \
+ util/qshadernodeport_p.h \
+ util/qshadernodesloader_p.h
SOURCES += \
util/qdesktopservices.cpp \
util/qvalidator.cpp \
util/qgridlayoutengine.cpp \
util/qabstractlayoutstyleinfo.cpp \
- util/qlayoutpolicy.cpp
+ util/qlayoutpolicy.cpp \
+ util/qshaderformat.cpp \
+ util/qshadergenerator.cpp \
+ util/qshadergraph.cpp \
+ util/qshadergraphloader.cpp \
+ util/qshaderlanguage.cpp \
+ util/qshadernode.cpp \
+ util/qshadernodeport.cpp \
+ util/qshadernodesloader.cpp