diff options
author | Juan Casafranca <juan.casafranca@kdab.com> | 2021-01-05 11:47:26 +0100 |
---|---|---|
committer | Paul Lemire <paul.lemire@kdab.com> | 2021-10-05 17:49:51 +0200 |
commit | 0263cfdfa0162162df07d4a15f896c20a6aac9d2 (patch) | |
tree | 1dcf5c70f879f50dea067c3d03f98a217c6195fe | |
parent | f2040b89396b1f8feff85a24329688c81e17d1d8 (diff) |
Remove qshadergraph files
- Those files were moved as part of Qt3D as its the sole
user of these
- Also removed associated unit tests
Pick-to: 6.2 5.15
Change-Id: I302bc219218a58071c86d2447cb4449601fca32c
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Mike Krus <mike.krus@kdab.com>
28 files changed, 0 insertions, 6667 deletions
diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index ef0bdfee0b..dc7837aa63 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -250,13 +250,6 @@ qt_internal_add_module(Gui util/qktxhandler.cpp util/qktxhandler_p.h util/qlayoutpolicy.cpp util/qlayoutpolicy_p.h util/qpkmhandler.cpp util/qpkmhandler_p.h - util/qshaderformat.cpp util/qshaderformat_p.h - util/qshadergraph.cpp util/qshadergraph_p.h - util/qshadergraphloader.cpp util/qshadergraphloader_p.h - util/qshaderlanguage.cpp util/qshaderlanguage_p.h - util/qshadernode.cpp util/qshadernode_p.h - util/qshadernodeport.cpp util/qshadernodeport_p.h - util/qshadernodesloader.cpp util/qshadernodesloader_p.h util/qtexturefiledata.cpp util/qtexturefiledata_p.h util/qtexturefilehandler_p.h util/qtexturefilereader.cpp util/qtexturefilereader_p.h @@ -812,11 +805,6 @@ qt_internal_extend_target(Gui CONDITION NOT QT_FEATURE_system_zlib AND NOT no_co Qt::Core ) -qt_internal_extend_target(Gui CONDITION QT_FEATURE_regularexpression - SOURCES - util/qshadergenerator.cpp util/qshadergenerator_p.h -) - qt_internal_extend_target(Gui CONDITION QT_FEATURE_undocommand SOURCES util/qundostack.cpp util/qundostack.h util/qundostack_p.h diff --git a/src/gui/util/qshaderformat.cpp b/src/gui/util/qshaderformat.cpp deleted file mode 100644 index d56dfc413e..0000000000 --- a/src/gui/util/qshaderformat.cpp +++ /dev/null @@ -1,145 +0,0 @@ -/**************************************************************************** -** -** 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() noexcept - : m_api(NoApi) - , m_shaderType(Fragment) -{ -} - -QShaderFormat::Api QShaderFormat::api() const noexcept -{ - return m_api; -} - -void QShaderFormat::setApi(QShaderFormat::Api api) noexcept -{ - m_api = api; -} - -QVersionNumber QShaderFormat::version() const noexcept -{ - return m_version; -} - -void QShaderFormat::setVersion(const QVersionNumber &version) noexcept -{ - m_version = version; -} - -QStringList QShaderFormat::extensions() const noexcept -{ - return m_extensions; -} - -void QShaderFormat::setExtensions(const QStringList &extensions) noexcept -{ - m_extensions = extensions; - m_extensions.sort(); -} - -QString QShaderFormat::vendor() const noexcept -{ - return m_vendor; -} - -void QShaderFormat::setVendor(const QString &vendor) noexcept -{ - m_vendor = vendor; -} - -bool QShaderFormat::isValid() const noexcept -{ - return m_api != NoApi && m_version.majorVersion() > 0; -} - -bool QShaderFormat::supports(const QShaderFormat &other) const noexcept -{ - 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; - - if (m_shaderType != other.m_shaderType) - 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; -} - -QShaderFormat::ShaderType QShaderFormat::shaderType() const noexcept -{ - return m_shaderType; -} - -void QShaderFormat::setShaderType(QShaderFormat::ShaderType shaderType) noexcept -{ - m_shaderType = shaderType; -} - -bool operator==(const QShaderFormat &lhs, const QShaderFormat &rhs) noexcept -{ - return lhs.api() == rhs.api() - && lhs.version() == rhs.version() - && lhs.extensions() == rhs.extensions() - && lhs.vendor() == rhs.vendor() - && lhs.shaderType() == rhs.shaderType(); -} - -QT_END_NAMESPACE diff --git a/src/gui/util/qshaderformat_p.h b/src/gui/util/qshaderformat_p.h deleted file mode 100644 index e47fbb8a03..0000000000 --- a/src/gui/util/qshaderformat_p.h +++ /dev/null @@ -1,123 +0,0 @@ -/**************************************************************************** -** -** 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, - VulkanFlavoredGLSL - }; - - enum ShaderType : int { - Vertex = 0, - TessellationControl, - TessellationEvaluation, - Geometry, - Fragment, - Compute - }; - - Q_GUI_EXPORT QShaderFormat() noexcept; - - Q_GUI_EXPORT Api api() const noexcept; - Q_GUI_EXPORT void setApi(Api api) noexcept; - - Q_GUI_EXPORT QVersionNumber version() const noexcept; - Q_GUI_EXPORT void setVersion(const QVersionNumber &version) noexcept; - - Q_GUI_EXPORT QStringList extensions() const noexcept; - Q_GUI_EXPORT void setExtensions(const QStringList &extensions) noexcept; - - Q_GUI_EXPORT QString vendor() const noexcept; - Q_GUI_EXPORT void setVendor(const QString &vendor) noexcept; - - Q_GUI_EXPORT bool isValid() const noexcept; - Q_GUI_EXPORT bool supports(const QShaderFormat &other) const noexcept; - - Q_GUI_EXPORT ShaderType shaderType() const noexcept; - Q_GUI_EXPORT void setShaderType(ShaderType shaderType) noexcept; - -private: - Api m_api; - QVersionNumber m_version; - QStringList m_extensions; - QString m_vendor; - ShaderType m_shaderType; -}; - -Q_GUI_EXPORT bool operator==(const QShaderFormat &lhs, const QShaderFormat &rhs) noexcept; - -inline bool operator!=(const QShaderFormat &lhs, const QShaderFormat &rhs) noexcept -{ - return !(lhs == rhs); -} - -Q_DECLARE_TYPEINFO(QShaderFormat, Q_RELOCATABLE_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 deleted file mode 100644 index 4933e913a3..0000000000 --- a/src/gui/util/qshadergenerator.cpp +++ /dev/null @@ -1,638 +0,0 @@ -/**************************************************************************** -** -** 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" -#include <QRegularExpression> - -#include <cctype> - -QT_BEGIN_NAMESPACE - -Q_LOGGING_CATEGORY(ShaderGenerator, "ShaderGenerator", QtWarningMsg) - -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: - if (format.shaderType() == QShaderFormat::Vertex) - return "attribute"; - else - return "varying"; - case QShaderLanguage::Output: - return ""; // Although fragment shaders for <=2 only have fixed outputs - case QShaderLanguage::Uniform: - return "uniform"; - case QShaderLanguage::BuiltIn: - return "//"; - } - } else { - switch (qualifier) { - case QShaderLanguage::Const: - return "const"; - case QShaderLanguage::Input: - return "in"; - case QShaderLanguage::Output: - return "out"; - case QShaderLanguage::Uniform: - return "uniform"; - case QShaderLanguage::BuiltIn: - return "//"; - } - } - - 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) - { - QByteArray result = original; - - const QStringList parameterNames = node.parameterNames(); - for (const QString ¶meterName : parameterNames) { - const QByteArray placeholder = QByteArray(QByteArrayLiteral("$") + parameterName.toUtf8()); - const QVariant parameter = node.parameter(parameterName); - if (parameter.userType() == qMetaTypeId<QShaderLanguage::StorageQualifier>()) { - const QShaderLanguage::StorageQualifier qualifier = qvariant_cast<QShaderLanguage::StorageQualifier>(parameter); - const QByteArray value = toGlsl(qualifier, format); - result.replace(placeholder, value); - } else if (parameter.userType() == qMetaTypeId<QShaderLanguage::VariableType>()) { - const QShaderLanguage::VariableType type = qvariant_cast<QShaderLanguage::VariableType>(parameter); - const QByteArray value = toGlsl(type); - result.replace(placeholder, value); - } else { - const QByteArray value = parameter.toString().toUtf8(); - result.replace(placeholder, value); - } - } - - return result; - } -} - -QByteArray QShaderGenerator::createShaderCode(const QStringList &enabledLayers) const -{ - auto code = QByteArrayList(); - - if (format.isValid()) { - const bool isGLES = format.api() == QShaderFormat::OpenGLES; - const int major = format.version().majorVersion(); - const int minor = format.version().minorVersion(); - - const int 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 QByteArray 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); }); - }; - - QList<QString> globalInputVariables; - const QRegularExpression globalInputExtractRegExp(QStringLiteral("^.*\\s+(\\w+).*;$")); - - const QList<QShaderNode> nodes = graph.nodes(); - for (const QShaderNode &node : nodes) { - if (intersectsEnabledLayers(node.layers())) { - const QByteArrayList headerSnippets = node.rule(format).headerSnippets; - for (const QByteArray &snippet : headerSnippets) { - code << replaceParameters(snippet, node, format); - - // If node is an input, record the variable name into the globalInputVariables list - if (node.type() == QShaderNode::Input) { - const QRegularExpressionMatch match = globalInputExtractRegExp.match(QString::fromUtf8(code.last())); - if (match.hasMatch()) - globalInputVariables.push_back(match.captured(1)); - } - } - } - } - - code << QByteArray(); - code << QByteArrayLiteral("void main()"); - code << QByteArrayLiteral("{"); - - const QRegularExpression temporaryVariableToAssignmentRegExp(QStringLiteral("([^;]*\\s+(v\\d+))\\s*=\\s*([^;]*);")); - const QRegularExpression temporaryVariableInAssignmentRegExp(QStringLiteral("\\W*(v\\d+)\\W*")); - const QRegularExpression statementRegExp(QStringLiteral("\\s*(\\w+)\\s*=\\s*([^;]*);")); - - struct Variable; - - struct Assignment - { - QString expression; - QList<Variable *> referencedVariables; - }; - - struct Variable - { - enum Type { - GlobalInput, - TemporaryAssignment, - Output - }; - - QString name; - QString declaration; - int referenceCount = 0; - Assignment assignment; - Type type = TemporaryAssignment; - bool substituted = false; - - static void substitute(Variable *v) - { - if (v->substituted) - return; - - qCDebug(ShaderGenerator) << "Begin Substituting " << v->name << " = " << v->assignment.expression; - for (Variable *ref : qAsConst(v->assignment.referencedVariables)) { - // Recursively substitute - Variable::substitute(ref); - - // Replace all variables referenced only once in the assignment - // by their actual expression - if (ref->referenceCount == 1 || ref->type == Variable::GlobalInput) { - const QRegularExpression r(QStringLiteral("(.*\\b)(%1)(\\b.*)").arg(ref->name)); - if (v->assignment.referencedVariables.size() == 1) - v->assignment.expression.replace(r, - QStringLiteral("\\1%2\\3").arg(ref->assignment.expression)); - else - v->assignment.expression.replace(r, - QStringLiteral("(\\1%2\\3)").arg(ref->assignment.expression)); - } - } - qCDebug(ShaderGenerator) << "Done Substituting " << v->name << " = " << v->assignment.expression; - v->substituted = true; - } - }; - - struct LineContent - { - QByteArray rawContent; - Variable *var = nullptr; - }; - - // Table to store temporary variables that should be replaced: - // - If variable references a a global variables - // -> we will use the global variable directly - // - If variable references a function results - // -> will be kept only if variable is referenced more than once. - // This avoids having vec3 v56 = vertexPosition; when we could - // just use vertexPosition directly. - // The added benefit is when having arrays, we don't try to create - // mat4 v38 = skinningPalelette[100] which would be invalid - QList<Variable> temporaryVariables; - // Reserve more than enough space to ensure no reallocation will take place - temporaryVariables.reserve(nodes.size() * 8); - - QList<LineContent> lines; - - auto createVariable = [&] () -> Variable * { - Q_ASSERT(temporaryVariables.capacity() > 0); - temporaryVariables.resize(temporaryVariables.size() + 1); - return &temporaryVariables.last(); - }; - - auto findVariable = [&] (const QString &name) -> Variable * { - const auto end = temporaryVariables.end(); - auto it = std::find_if(temporaryVariables.begin(), end, - [=] (const Variable &a) { return a.name == name; }); - if (it != end) - return &(*it); - return nullptr; - }; - - auto gatherTemporaryVariablesFromAssignment = [&] (Variable *v, const QString &assignmentContent) { - QRegularExpressionMatchIterator subMatchIt = temporaryVariableInAssignmentRegExp.globalMatch(assignmentContent); - while (subMatchIt.hasNext()) { - const QRegularExpressionMatch subMatch = subMatchIt.next(); - const QString variableName = subMatch.captured(1); - - // Variable we care about should already exists -> an expression cannot reference a variable that hasn't been defined - Variable *u = findVariable(variableName); - Q_ASSERT(u); - - // Increase reference count for u - ++u->referenceCount; - // Insert u as reference for variable v - v->assignment.referencedVariables.push_back(u); - } - }; - - for (const QShaderGraph::Statement &statement : graph.createStatements(enabledLayers)) { - const QShaderNode node = statement.node; - QByteArray line = node.rule(format).substitution; - const QList<QShaderNodePort> ports = node.ports(); - - struct VariableReplacement { - QByteArray placeholder; - QByteArray variable; - }; - - QList<VariableReplacement> variableReplacements; - - // Generate temporary variable names vN - for (const QShaderNodePort &port : ports) { - const QString portName = port.name; - const QShaderNodePort::Direction portDirection = port.direction; - const bool isInput = port.direction == QShaderNodePort::Input; - - const int portIndex = statement.portIndex(portDirection, portName); - - Q_ASSERT(portIndex >= 0); - - const int variableIndex = isInput ? statement.inputs.at(portIndex) - : statement.outputs.at(portIndex); - if (variableIndex < 0) - continue; - - VariableReplacement replacement; - replacement.placeholder = QByteArrayLiteral("$") + portName.toUtf8(); - replacement.variable = QByteArrayLiteral("v") + QByteArray::number(variableIndex); - - variableReplacements.append(std::move(replacement)); - } - - int begin = 0; - while ((begin = line.indexOf('$', begin)) != -1) { - int end = begin + 1; - char endChar = line.at(end); - const int size = line.size(); - while (end < size && (std::isalnum(endChar) || endChar == '_')) { - ++end; - endChar = line.at(end); - } - - const int placeholderLength = end - begin; - - const QByteArray variableName = line.mid(begin, placeholderLength); - const auto replacementIt = std::find_if(variableReplacements.cbegin(), variableReplacements.cend(), - [&variableName](const VariableReplacement &replacement) { - return variableName == replacement.placeholder; - }); - - if (replacementIt != variableReplacements.cend()) { - line.replace(begin, placeholderLength, replacementIt->variable); - begin += replacementIt->variable.length(); - } else { - begin = end; - } - } - - // Substitute variable names by generated vN variable names - const QByteArray substitutionedLine = replaceParameters(line, node, format); - - QRegularExpressionMatchIterator matches; - - switch (node.type()) { - case QShaderNode::Input: - case QShaderNode::Output: - matches = statementRegExp.globalMatch(QString::fromUtf8(substitutionedLine)); - break; - case QShaderNode::Function: - matches = temporaryVariableToAssignmentRegExp.globalMatch(QString::fromUtf8(substitutionedLine)); - break; - case QShaderNode::Invalid: - break; - } - - while (matches.hasNext()) { - QRegularExpressionMatch match = matches.next(); - - Variable *v = nullptr; - - switch (node.type()) { - // Record name of temporary variable that possibly references a global input - // We will replace the temporary variables by the matching global variables later - case QShaderNode::Input: { - const QString localVariable = match.captured(1); - const QString globalVariable = match.captured(2); - - v = createVariable(); - v->name = localVariable; - v->type = Variable::GlobalInput; - - Assignment assignment; - assignment.expression = globalVariable; - v->assignment = assignment; - break; - } - - case QShaderNode::Function: { - const QString localVariableDeclaration = match.captured(1); - const QString localVariableName = match.captured(2); - const QString assignmentContent = match.captured(3); - - // Add new variable -> it cannot exist already - v = createVariable(); - v->name = localVariableName; - v->declaration = localVariableDeclaration; - v->assignment.expression = assignmentContent; - - // Find variables that may be referenced in the assignment - gatherTemporaryVariablesFromAssignment(v, assignmentContent); - break; - } - - case QShaderNode::Output: { - const QString outputDeclaration = match.captured(1); - const QString assignmentContent = match.captured(2); - - v = createVariable(); - v->name = outputDeclaration; - v->declaration = outputDeclaration; - v->type = Variable::Output; - - Assignment assignment; - assignment.expression = assignmentContent; - v->assignment = assignment; - - // Find variables that may be referenced in the assignment - gatherTemporaryVariablesFromAssignment(v, assignmentContent); - break; - } - case QShaderNode::Invalid: - break; - } - - LineContent lineContent; - lineContent.rawContent = QByteArray(QByteArrayLiteral(" ") + substitutionedLine); - lineContent.var = v; - lines << lineContent; - } - } - - // Go through all lines - // Perform substitution of line with temporary variables substitution - for (LineContent &lineContent : lines) { - Variable *v = lineContent.var; - qCDebug(ShaderGenerator) << lineContent.rawContent; - if (v != nullptr) { - Variable::substitute(v); - - qCDebug(ShaderGenerator) << "Line " << lineContent.rawContent << "is assigned to temporary" << v->name; - - // Check number of occurrences a temporary variable is referenced - if (v->referenceCount == 1 || v->type == Variable::GlobalInput) { - // If it is referenced only once, no point in creating a temporary - // Clear content for current line - lineContent.rawContent.clear(); - // We assume expression that were referencing vN will have vN properly substituted - } else { - lineContent.rawContent = QStringLiteral(" %1 = %2;").arg(v->declaration) - .arg(v->assignment.expression) - .toUtf8(); - } - - qCDebug(ShaderGenerator) << "Updated Line is " << lineContent.rawContent; - } - } - - // Go throug all lines and insert content - for (const LineContent &lineContent : qAsConst(lines)) { - if (!lineContent.rawContent.isEmpty()) { - code << lineContent.rawContent; - } - } - - 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 deleted file mode 100644 index 4d3a09c92f..0000000000 --- a/src/gui/util/qshadergenerator_p.h +++ /dev/null @@ -1,79 +0,0 @@ -/**************************************************************************** -** -** 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> -#include <QtCore/QLoggingCategory> - - -QT_BEGIN_NAMESPACE - -Q_DECLARE_LOGGING_CATEGORY(ShaderGenerator) - -class QShaderGenerator -{ -public: - Q_GUI_EXPORT QByteArray createShaderCode(const QStringList &enabledLayers = QStringList()) const; - - QShaderGraph graph; - QShaderFormat format; -}; - -Q_DECLARE_TYPEINFO(QShaderGenerator, Q_RELOCATABLE_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 deleted file mode 100644 index 5d2d7f3627..0000000000 --- a/src/gui/util/qshadergraph.cpp +++ /dev/null @@ -1,316 +0,0 @@ -/**************************************************************************** -** -** 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 -{ - QList<QShaderNode> copyOutputNodes(const QList<QShaderNode> &nodes, const QList<QShaderGraph::Edge> &edges) - { - auto res = QList<QShaderNode>(); - std::copy_if(nodes.cbegin(), nodes.cend(), - std::back_inserter(res), - [&edges] (const QShaderNode &node) { - return node.type() == QShaderNode::Output || - (node.type() == QShaderNode::Function && - !std::any_of(edges.cbegin(), - edges.cend(), - [&node] (const QShaderGraph::Edge &edge) { - return edge.sourceNodeUuid == - node.uuid(); - })); - }); - return res; - } - - QList<QShaderGraph::Edge> incomingEdges(const QList<QShaderGraph::Edge> &edges, const QUuid &uuid) - { - auto res = QList<QShaderGraph::Edge>(); - std::copy_if(edges.cbegin(), edges.cend(), - std::back_inserter(res), - [uuid] (const QShaderGraph::Edge &edge) { - return edge.sourceNodeUuid == uuid; - }); - return res; - } - - QList<QShaderGraph::Edge> outgoingEdges(const QList<QShaderGraph::Edge> &edges, const QUuid &uuid) - { - auto res = QList<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 QList<QShaderNodePort> ports = node.ports(); - for (const QShaderNodePort &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 QList<QShaderGraph::Edge> edges, - const QUuid &uuid) - { - auto targetStatement = idHash.value(uuid); - for (const QShaderGraph::Edge &edge : edges) { - if (edge.targetNodeUuid != uuid) - continue; - - const QShaderGraph::Statement sourceStatement = idHash.value(edge.sourceNodeUuid); - const int sourcePortIndex = sourceStatement.portIndex(QShaderNodePort::Output, edge.sourcePortName); - const int targetPortIndex = targetStatement.portIndex(QShaderNodePort::Input, edge.targetPortName); - - if (sourcePortIndex < 0 || targetPortIndex < 0) - continue; - - const QList<int> sourceOutputs = sourceStatement.outputs; - QList<int> &targetInputs = targetStatement.inputs; - targetInputs[targetPortIndex] = sourceOutputs[sourcePortIndex]; - } - return targetStatement; - } - - void removeNodesWithUnboundInputs(QList<QShaderGraph::Statement> &statements, - const QList<QShaderGraph::Edge> &allEdges) - { - // A node is invalid if any of its input ports is disconected - // or connected to the output port of another invalid node. - - // Keeps track of the edges from the nodes we know to be valid - // to unvisited nodes - auto currentEdges = QList<QShaderGraph::Edge>(); - - statements.erase(std::remove_if(statements.begin(), - statements.end(), - [¤tEdges, &allEdges] (const QShaderGraph::Statement &statement) { - const QShaderNode &node = statement.node; - const QList<QShaderGraph::Edge> outgoing = outgoingEdges(currentEdges, node.uuid()); - const QList<QShaderNodePort> ports = node.ports(); - - bool allInputsConnected = true; - for (const QShaderNodePort &port : node.ports()) { - if (port.direction == QShaderNodePort::Output) - continue; - - const auto edgeIt = std::find_if(outgoing.cbegin(), - outgoing.cend(), - [&port] (const QShaderGraph::Edge &edge) { - return edge.targetPortName == port.name; - }); - - if (edgeIt != outgoing.cend()) - currentEdges.removeAll(*edgeIt); - else - allInputsConnected = false; - } - - if (allInputsConnected) { - const QList<QShaderGraph::Edge> incoming = incomingEdges(allEdges, node.uuid()); - currentEdges.append(incoming); - } - - return !allInputsConnected; - }), - statements.end()); - } -} - -QUuid QShaderGraph::Statement::uuid() const noexcept -{ - return node.uuid(); -} - -int QShaderGraph::Statement::portIndex(QShaderNodePort::Direction direction, const QString &portName) const noexcept -{ - const QList<QShaderNodePort> ports = node.ports(); - int index = 0; - for (const QShaderNodePort &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); -} - -QList<QShaderNode> QShaderGraph::nodes() const noexcept -{ - 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); -} - -QList<QShaderGraph::Edge> QShaderGraph::edges() const noexcept -{ - return m_edges; -} - -QList<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 QList<QShaderNode> enabledNodes = [this, intersectsEnabledLayers] { - auto res = QList<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 QList<Edge> enabledEdges = [this, intersectsEnabledLayers] { - auto res = QList<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 QHash<QUuid, Statement> idHash = [enabledNodes] { - auto nextVarId = 0; - auto res = QHash<QUuid, Statement>(); - for (const QShaderNode &node : enabledNodes) - res.insert(node.uuid(), nodeToStatement(node, nextVarId)); - return res; - }(); - - auto result = QList<Statement>(); - QList<Edge> currentEdges = enabledEdges; - QList<QUuid> currentUuids = [enabledNodes, enabledEdges] { - const QList<QShaderNode> inputs = copyOutputNodes(enabledNodes, enabledEdges); - auto res = QList<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 QUuid uuid = currentUuids.takeFirst(); - result.append(completeStatement(idHash, enabledEdges, uuid)); - - const QList<QShaderGraph::Edge> outgoing = outgoingEdges(currentEdges, uuid); - for (const QShaderGraph::Edge &outgoingEdge : outgoing) { - currentEdges.removeAll(outgoingEdge); - const QUuid nextUuid = outgoingEdge.sourceNodeUuid; - const QList<QShaderGraph::Edge> incoming = incomingEdges(currentEdges, nextUuid); - if (incoming.isEmpty()) { - currentUuids.append(nextUuid); - } - } - } - - std::reverse(result.begin(), result.end()); - - removeNodesWithUnboundInputs(result, enabledEdges); - - return result; -} - -bool operator==(const QShaderGraph::Edge &lhs, const QShaderGraph::Edge &rhs) noexcept -{ - 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) noexcept -{ - 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 deleted file mode 100644 index dbc5f3fab7..0000000000 --- a/src/gui/util/qshadergraph_p.h +++ /dev/null @@ -1,124 +0,0 @@ -/**************************************************************************** -** -** 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 noexcept; - Q_GUI_EXPORT int portIndex(QShaderNodePort::Direction direction, const QString &portName) const noexcept; - - QShaderNode node; - QList<int> inputs; - QList<int> outputs; - }; - - Q_GUI_EXPORT void addNode(const QShaderNode &node); - Q_GUI_EXPORT void removeNode(const QShaderNode &node); - Q_GUI_EXPORT QList<QShaderNode> nodes() const noexcept; - - Q_GUI_EXPORT void addEdge(const Edge &edge); - Q_GUI_EXPORT void removeEdge(const Edge &edge); - Q_GUI_EXPORT QList<Edge> edges() const noexcept; - - Q_GUI_EXPORT QList<Statement> - createStatements(const QStringList &enabledLayers = QStringList()) const; - -private: - QList<QShaderNode> m_nodes; - QList<Edge> m_edges; -}; - -Q_GUI_EXPORT bool operator==(const QShaderGraph::Edge &lhs, const QShaderGraph::Edge &rhs) noexcept; - -inline bool operator!=(const QShaderGraph::Edge &lhs, const QShaderGraph::Edge &rhs) noexcept -{ - return !(lhs == rhs); -} - -Q_GUI_EXPORT bool operator==(const QShaderGraph::Statement &lhs, const QShaderGraph::Statement &rhs) noexcept; - -inline bool operator!=(const QShaderGraph::Statement &lhs, const QShaderGraph::Statement &rhs) noexcept -{ - return !(lhs == rhs); -} - -Q_DECLARE_TYPEINFO(QShaderGraph, Q_RELOCATABLE_TYPE); -Q_DECLARE_TYPEINFO(QShaderGraph::Edge, Q_RELOCATABLE_TYPE); -Q_DECLARE_TYPEINFO(QShaderGraph::Statement, Q_RELOCATABLE_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 deleted file mode 100644 index defa88b9d3..0000000000 --- a/src/gui/util/qshadergraphloader.cpp +++ /dev/null @@ -1,269 +0,0 @@ -/**************************************************************************** -** -** 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 "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 - -void qt_register_ShaderLanguage_enums(); - -QShaderGraphLoader::QShaderGraphLoader() noexcept - : m_status(Null), - m_device(nullptr) -{ - qt_register_ShaderLanguage_enums(); -} - -QShaderGraphLoader::Status QShaderGraphLoader::status() const noexcept -{ - return m_status; -} - -QShaderGraph QShaderGraphLoader::graph() const noexcept -{ - return m_graph; -} - -QIODevice *QShaderGraphLoader::device() const noexcept -{ - return m_device; -} - -void QShaderGraphLoader::setDevice(QIODevice *device) noexcept -{ - m_device = device; - m_graph = QShaderGraph(); - m_status = !m_device ? Null - : (m_device->openMode() & QIODevice::ReadOnly) ? Waiting - : Error; -} - -QHash<QString, QShaderNode> QShaderGraphLoader::prototypes() const noexcept -{ - return m_prototypes; -} - -void QShaderGraphLoader::setPrototypes(const QHash<QString, QShaderNode> &prototypes) noexcept -{ - m_prototypes = prototypes; -} - -void QShaderGraphLoader::load() -{ - if (m_status == Error) - return; - - auto error = QJsonParseError(); - const QJsonDocument 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 QJsonObject root = document.object(); - - const QJsonValue nodesValue = root.value(QStringLiteral("nodes")); - if (!nodesValue.isArray()) { - qWarning() << "Invalid nodes property, should be an array"; - m_status = Error; - return; - } - - const QJsonValue edgesValue = root.value(QStringLiteral("edges")); - if (!edgesValue.isArray()) { - qWarning() << "Invalid edges property, should be an array"; - m_status = Error; - return; - } - - bool hasError = false; - - const QJsonValue prototypesValue = root.value(QStringLiteral("prototypes")); - if (!prototypesValue.isUndefined()) { - if (prototypesValue.isObject()) { - QShaderNodesLoader loader; - loader.load(prototypesValue.toObject()); - m_prototypes.insert(loader.nodes()); - } else { - qWarning() << "Invalid prototypes property, should be an object"; - m_status = Error; - return; - } - } - - const QJsonArray nodes = nodesValue.toArray(); - for (const QJsonValue nodeValue : nodes) { - if (!nodeValue.isObject()) { - qWarning() << "Invalid node found"; - hasError = true; - continue; - } - - const QJsonObject nodeObject = nodeValue.toObject(); - - const QString uuidString = nodeObject.value(QStringLiteral("uuid")).toString(); - const QUuid uuid = QUuid(uuidString); - if (uuid.isNull()) { - qWarning() << "Invalid UUID found in node:" << uuidString; - hasError = true; - continue; - } - - const QString type = nodeObject.value(QStringLiteral("type")).toString(); - if (!m_prototypes.contains(type)) { - qWarning() << "Unsupported node type found:" << type; - hasError = true; - continue; - } - - const QJsonArray layersArray = nodeObject.value(QStringLiteral("layers")).toArray(); - auto layers = QStringList(); - for (const QJsonValue layerValue : layersArray) { - layers.append(layerValue.toString()); - } - - QShaderNode node = m_prototypes.value(type); - node.setUuid(uuid); - node.setLayers(layers); - - const QJsonValue parametersValue = nodeObject.value(QStringLiteral("parameters")); - if (parametersValue.isObject()) { - const QJsonObject parametersObject = parametersValue.toObject(); - for (const QString ¶meterName : parametersObject.keys()) { - const QJsonValue parameterValue = parametersObject.value(parameterName); - if (parameterValue.isObject()) { - const QJsonObject parameterObject = parameterValue.toObject(); - const QString type = parameterObject.value(QStringLiteral("type")).toString(); - const auto metaType = QMetaType::fromName(type.toUtf8()); - - const QString value = parameterObject.value(QStringLiteral("value")).toString(); - auto variant = QVariant(value); - - if (metaType.flags() & QMetaType::IsEnumeration) { - const QMetaObject *metaObject = metaType.metaObject(); - const char *className = metaObject->className(); - const QByteArray enumName = type.mid(static_cast<int>(qstrlen(className)) + 2).toUtf8(); - const QMetaEnum metaEnum = metaObject->enumerator(metaObject->indexOfEnumerator(enumName)); - const int enumValue = metaEnum.keyToValue(value.toUtf8()); - variant = QVariant(enumValue); - variant.convert(metaType); - } else { - variant.convert(metaType); - } - node.setParameter(parameterName, variant); - } else { - node.setParameter(parameterName, parameterValue.toVariant()); - } - } - } - - m_graph.addNode(node); - } - - const QJsonArray edges = edgesValue.toArray(); - for (const QJsonValue edgeValue : edges) { - if (!edgeValue.isObject()) { - qWarning() << "Invalid edge found"; - hasError = true; - continue; - } - - const QJsonObject edgeObject = edgeValue.toObject(); - - const QString sourceUuidString = edgeObject.value(QStringLiteral("sourceUuid")).toString(); - const QUuid sourceUuid = QUuid(sourceUuidString); - if (sourceUuid.isNull()) { - qWarning() << "Invalid source UUID found in edge:" << sourceUuidString; - hasError = true; - continue; - } - - const QString sourcePort = edgeObject.value(QStringLiteral("sourcePort")).toString(); - - const QString targetUuidString = edgeObject.value(QStringLiteral("targetUuid")).toString(); - const QUuid targetUuid = QUuid(targetUuidString); - if (targetUuid.isNull()) { - qWarning() << "Invalid target UUID found in edge:" << targetUuidString; - hasError = true; - continue; - } - - const QString targetPort = edgeObject.value(QStringLiteral("targetPort")).toString(); - - const QJsonArray layersArray = edgeObject.value(QStringLiteral("layers")).toArray(); - auto layers = QStringList(); - for (const QJsonValue 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 deleted file mode 100644 index bdd02799f7..0000000000 --- a/src/gui/util/qshadergraphloader_p.h +++ /dev/null @@ -1,99 +0,0 @@ -/**************************************************************************** -** -** 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() noexcept; - - Q_GUI_EXPORT Status status() const noexcept; - Q_GUI_EXPORT QShaderGraph graph() const noexcept; - - Q_GUI_EXPORT QIODevice *device() const noexcept; - Q_GUI_EXPORT void setDevice(QIODevice *device) noexcept; - - Q_GUI_EXPORT QHash<QString, QShaderNode> prototypes() const noexcept; - Q_GUI_EXPORT void setPrototypes(const QHash<QString, QShaderNode> &prototypes) noexcept; - - 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_RELOCATABLE_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 deleted file mode 100644 index efd607ba60..0000000000 --- a/src/gui/util/qshaderlanguage.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/**************************************************************************** -** -** 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 "qshaderlanguage_p.h" - -#include <QtCore/qcoreapplication.h> - -QT_BEGIN_NAMESPACE - -// Note: to be invoked explicitly. Relying for example on -// Q_COREAPP_STARTUP_FUNCTION would not be acceptable in static builds. -void qt_register_ShaderLanguage_enums() -{ - qRegisterMetaType<QShaderLanguage::StorageQualifier>(); - qRegisterMetaType<QShaderLanguage::VariableType>(); -} - -QT_END_NAMESPACE diff --git a/src/gui/util/qshaderlanguage_p.h b/src/gui/util/qshaderlanguage_p.h deleted file mode 100644 index 193f797cc3..0000000000 --- a/src/gui/util/qshaderlanguage_p.h +++ /dev/null @@ -1,164 +0,0 @@ -/**************************************************************************** -** -** 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 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_NAMESPACE_EXPORT(Q_GUI_EXPORT) - - enum StorageQualifier : char { - Const = 1, - Input, - BuiltIn, - 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 deleted file mode 100644 index 3e53c35037..0000000000 --- a/src/gui/util/qshadernode.cpp +++ /dev/null @@ -1,172 +0,0 @@ -/**************************************************************************** -** -** 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 "qshadernode_p.h" - -QT_BEGIN_NAMESPACE - -QShaderNode::Type QShaderNode::type() const noexcept -{ - 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 noexcept -{ - return m_uuid; -} - -void QShaderNode::setUuid(const QUuid &uuid) noexcept -{ - m_uuid = uuid; -} - -QStringList QShaderNode::layers() const noexcept -{ - return m_layers; -} - -void QShaderNode::setLayers(const QStringList &layers) noexcept -{ - m_layers = layers; -} - -QList<QShaderNodePort> QShaderNode::ports() const noexcept -{ - 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); -} - -QList<QShaderFormat> QShaderNode::availableFormats() const -{ - auto res = QList<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) noexcept - : substitution(subs), - headerSnippets(snippets) -{ -} - -bool operator==(const QShaderNode::Rule &lhs, const QShaderNode::Rule &rhs) noexcept -{ - 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 deleted file mode 100644 index 303a404165..0000000000 --- a/src/gui/util/qshadernode_p.h +++ /dev/null @@ -1,128 +0,0 @@ -/**************************************************************************** -** -** 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 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()) noexcept; - - QByteArray substitution; - QByteArrayList headerSnippets; - }; - - Q_GUI_EXPORT Type type() const noexcept; - - Q_GUI_EXPORT QUuid uuid() const noexcept; - Q_GUI_EXPORT void setUuid(const QUuid &uuid) noexcept; - - Q_GUI_EXPORT QStringList layers() const noexcept; - Q_GUI_EXPORT void setLayers(const QStringList &layers) noexcept; - - Q_GUI_EXPORT QList<QShaderNodePort> ports() const noexcept; - 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 QList<QShaderFormat> availableFormats() const; - Q_GUI_EXPORT Rule rule(const QShaderFormat &format) const; - -private: - QUuid m_uuid; - QStringList m_layers; - QList<QShaderNodePort> m_ports; - QHash<QString, QVariant> m_parameters; - QList<QPair<QShaderFormat, QShaderNode::Rule>> m_rules; -}; - -Q_GUI_EXPORT bool operator==(const QShaderNode::Rule &lhs, const QShaderNode::Rule &rhs) noexcept; - -inline bool operator!=(const QShaderNode::Rule &lhs, const QShaderNode::Rule &rhs) noexcept -{ - return !(lhs == rhs); -} - -Q_DECLARE_TYPEINFO(QShaderNode, Q_RELOCATABLE_TYPE); -Q_DECLARE_TYPEINFO(QShaderNode::Rule, Q_RELOCATABLE_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 deleted file mode 100644 index 15dbc4160e..0000000000 --- a/src/gui/util/qshadernodeport.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/**************************************************************************** -** -** 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() noexcept - : direction(Output) -{ -} - -bool operator==(const QShaderNodePort &lhs, const QShaderNodePort &rhs) noexcept -{ - 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 deleted file mode 100644 index e4e11f6826..0000000000 --- a/src/gui/util/qshadernodeport_p.h +++ /dev/null @@ -1,88 +0,0 @@ -/**************************************************************************** -** -** 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() noexcept; - - QShaderNodePort::Direction direction; - QString name; -}; - -Q_GUI_EXPORT bool operator==(const QShaderNodePort &lhs, const QShaderNodePort &rhs) noexcept; - -inline bool operator!=(const QShaderNodePort &lhs, const QShaderNodePort &rhs) noexcept -{ - return !(lhs == rhs); -} - -Q_DECLARE_TYPEINFO(QShaderNodePort, Q_RELOCATABLE_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 deleted file mode 100644 index db1755e33a..0000000000 --- a/src/gui/util/qshadernodesloader.cpp +++ /dev/null @@ -1,290 +0,0 @@ -/**************************************************************************** -** -** 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() noexcept - : m_status(Null), - m_device(nullptr) -{ -} - -QShaderNodesLoader::Status QShaderNodesLoader::status() const noexcept -{ - return m_status; -} - -QHash<QString, QShaderNode> QShaderNodesLoader::nodes() const noexcept -{ - return m_nodes; -} - -QIODevice *QShaderNodesLoader::device() const noexcept -{ - return m_device; -} - -void QShaderNodesLoader::setDevice(QIODevice *device) noexcept -{ - 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 QJsonDocument 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 QJsonObject root = document.object(); - load(root); -} - -void QShaderNodesLoader::load(const QJsonObject &prototypesObject) -{ - bool hasError = false; - - for (const QString &property : prototypesObject.keys()) { - const QJsonValue nodeValue = prototypesObject.value(property); - if (!nodeValue.isObject()) { - qWarning() << "Invalid node found"; - hasError = true; - break; - } - - const QJsonObject nodeObject = nodeValue.toObject(); - - auto node = QShaderNode(); - - const QJsonValue inputsValue = nodeObject.value(QStringLiteral("inputs")); - if (inputsValue.isArray()) { - const QJsonArray inputsArray = inputsValue.toArray(); - for (const QJsonValue 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 QJsonValue outputsValue = nodeObject.value(QStringLiteral("outputs")); - if (outputsValue.isArray()) { - const QJsonArray outputsArray = outputsValue.toArray(); - for (const QJsonValue 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 QJsonValue parametersValue = nodeObject.value(QStringLiteral("parameters")); - if (parametersValue.isObject()) { - const QJsonObject parametersObject = parametersValue.toObject(); - for (const QString ¶meterName : parametersObject.keys()) { - const QJsonValue parameterValue = parametersObject.value(parameterName); - if (parameterValue.isObject()) { - const QJsonObject parameterObject = parameterValue.toObject(); - const QString type = parameterObject.value(QStringLiteral("type")).toString(); - const auto metaType = QMetaType::fromName(type.toUtf8()); - - const QString value = parameterObject.value(QStringLiteral("value")).toString(); - auto variant = QVariant(value); - - if (metaType.flags() & QMetaType::IsEnumeration) { - const QMetaObject *metaObject = metaType.metaObject(); - const char *className = metaObject->className(); - const QByteArray enumName = type.mid(static_cast<int>(qstrlen(className)) + 2).toUtf8(); - const QMetaEnum metaEnum = metaObject->enumerator(metaObject->indexOfEnumerator(enumName)); - const int enumValue = metaEnum.keyToValue(value.toUtf8()); - variant = QVariant(enumValue); - variant.convert(metaType); - } else { - variant.convert(metaType); - } - node.setParameter(parameterName, variant); - } else { - node.setParameter(parameterName, parameterValue.toVariant()); - } - } - } - - const QJsonValue rulesValue = nodeObject.value(QStringLiteral("rules")); - if (rulesValue.isArray()) { - const QJsonArray rulesArray = rulesValue.toArray(); - for (const QJsonValue ruleValue : rulesArray) { - if (!ruleValue.isObject()) { - qWarning() << "Rules should be objects"; - hasError = true; - break; - } - - const QJsonObject ruleObject = ruleValue.toObject(); - - const QJsonValue formatValue = ruleObject.value(QStringLiteral("format")); - if (!formatValue.isObject()) { - qWarning() << "Format is mandatory in rules and should be an object"; - hasError = true; - break; - } - - const QJsonObject formatObject = formatValue.toObject(); - auto format = QShaderFormat(); - - const QJsonValue apiValue = formatObject.value(QStringLiteral("api")); - if (!apiValue.isString()) { - qWarning() << "Format API must be a string"; - hasError = true; - break; - } - - const QString 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 - : api == QStringLiteral("VulkanFlavoredGLSL") ? QShaderFormat::VulkanFlavoredGLSL - : QShaderFormat::NoApi); - if (format.api() == QShaderFormat::NoApi) { - qWarning() << "Format API must be one of: OpenGLES, OpenGLNoProfile, OpenGLCoreProfile or OpenGLCompatibilityProfile, VulkanFlavoredGLSL"; - hasError = true; - break; - } - - const QJsonValue majorValue = formatObject.value(QStringLiteral("major")); - const QJsonValue 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 QJsonValue extensionsValue = formatObject.value(QStringLiteral("extensions")); - const QJsonArray 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 QString vendor = formatObject.value(QStringLiteral("vendor")).toString(); - format.setVendor(vendor); - - const QJsonValue substitutionValue = ruleObject.value(QStringLiteral("substitution")); - if (!substitutionValue.isString()) { - qWarning() << "Substitution needs to be a string"; - hasError = true; - break; - } - - // We default out to a Fragment ShaderType if nothing is specified - // as that was the initial behavior we introduced - const QString shaderType = formatObject.value(QStringLiteral("shaderType")).toString(); - format.setShaderType(shaderType == QStringLiteral("Fragment") ? QShaderFormat::Fragment - : shaderType == QStringLiteral("Vertex") ? QShaderFormat::Vertex - : shaderType == QStringLiteral("TessellationControl") ? QShaderFormat::TessellationControl - : shaderType == QStringLiteral("TessellationEvaluation") ? QShaderFormat::TessellationEvaluation - : shaderType == QStringLiteral("Geometry") ? QShaderFormat::Geometry - : shaderType == QStringLiteral("Compute") ? QShaderFormat::Compute - : QShaderFormat::Fragment); - - const QByteArray substitution = substitutionValue.toString().toUtf8(); - - const QJsonValue snippetsValue = ruleObject.value(QStringLiteral("headerSnippets")); - const QJsonArray 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 deleted file mode 100644 index 8afdd294ca..0000000000 --- a/src/gui/util/qshadernodesloader_p.h +++ /dev/null @@ -1,96 +0,0 @@ -/**************************************************************************** -** -** 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() noexcept; - - Q_GUI_EXPORT Status status() const noexcept; - Q_GUI_EXPORT QHash<QString, QShaderNode> nodes() const noexcept; - - Q_GUI_EXPORT QIODevice *device() const noexcept; - Q_GUI_EXPORT void setDevice(QIODevice *device) noexcept; - - Q_GUI_EXPORT void load(); - Q_GUI_EXPORT void load(const QJsonObject &prototypesObject); - -private: - Status m_status; - QIODevice *m_device; - QHash<QString, QShaderNode> m_nodes; -}; - -Q_DECLARE_TYPEINFO(QShaderNodesLoader, Q_RELOCATABLE_TYPE); - -QT_END_NAMESPACE - -Q_DECLARE_METATYPE(QShaderNodesLoader) -Q_DECLARE_METATYPE(QShaderNodesLoader::Status) - -#endif // QSHADERNODESLOADER_P_H diff --git a/tests/auto/gui/util/CMakeLists.txt b/tests/auto/gui/util/CMakeLists.txt index 4feae26818..048e18360c 100644 --- a/tests/auto/gui/util/CMakeLists.txt +++ b/tests/auto/gui/util/CMakeLists.txt @@ -4,11 +4,6 @@ add_subdirectory(qdesktopservices) add_subdirectory(qdoublevalidator) add_subdirectory(qintvalidator) add_subdirectory(qregularexpressionvalidator) -add_subdirectory(qshadergenerator) -add_subdirectory(qshadergraph) -add_subdirectory(qshadergraphloader) -add_subdirectory(qshadernodes) -add_subdirectory(qshadernodesloader) add_subdirectory(qtexturefilereader) add_subdirectory(qundogroup) add_subdirectory(qundostack) diff --git a/tests/auto/gui/util/qshadergenerator/CMakeLists.txt b/tests/auto/gui/util/qshadergenerator/CMakeLists.txt deleted file mode 100644 index 77cefcbd06..0000000000 --- a/tests/auto/gui/util/qshadergenerator/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -# Generated from qshadergenerator.pro. - -##################################################################### -## tst_qshadergenerator Test: -##################################################################### - -qt_internal_add_test(tst_qshadergenerator - SOURCES - tst_qshadergenerator.cpp - PUBLIC_LIBRARIES - Qt::Gui - Qt::GuiPrivate -) diff --git a/tests/auto/gui/util/qshadergenerator/tst_qshadergenerator.cpp b/tests/auto/gui/util/qshadergenerator/tst_qshadergenerator.cpp deleted file mode 100644 index 408460132b..0000000000 --- a/tests/auto/gui/util/qshadergenerator/tst_qshadergenerator.cpp +++ /dev/null @@ -1,1428 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** 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 General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** 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-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include <QTest> - -#include <QtCore/qmetaobject.h> -#include <QtGui/private/qshadergenerator_p.h> -#include <QtGui/private/qshaderlanguage_p.h> - -namespace -{ - QShaderFormat createFormat(QShaderFormat::Api api, int majorVersion, int minorVersion, - QShaderFormat::ShaderType shaderType= QShaderFormat::Fragment) - { - auto format = QShaderFormat(); - format.setApi(api); - format.setVersion(QVersionNumber(majorVersion, minorVersion)); - format.setShaderType(shaderType); - return format; - } - - QShaderNodePort createPort(QShaderNodePort::Direction portDirection, const QString &portName) - { - auto port = QShaderNodePort(); - port.direction = portDirection; - port.name = portName; - return port; - } - - QShaderNode createNode(const QList<QShaderNodePort> &ports, - const QStringList &layers = QStringList()) - { - auto node = QShaderNode(); - node.setUuid(QUuid::createUuid()); - node.setLayers(layers); - for (const auto &port : ports) - node.addPort(port); - return node; - } - - QShaderGraph::Edge createEdge(const QUuid &sourceUuid, const QString &sourceName, - const QUuid &targetUuid, const QString &targetName, - const QStringList &layers = QStringList()) - { - auto edge = QShaderGraph::Edge(); - edge.sourceNodeUuid = sourceUuid; - edge.sourcePortName = sourceName; - edge.targetNodeUuid = targetUuid; - edge.targetPortName = targetName; - edge.layers = layers; - return edge; - } - - QShaderGraph createFragmentShaderGraph() - { - const auto openGLES2 = createFormat(QShaderFormat::OpenGLES, 2, 0); - const auto openGL3 = createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0); - - auto graph = QShaderGraph(); - - auto worldPosition = createNode({ - createPort(QShaderNodePort::Output, "value") - }); - worldPosition.setParameter("name", "worldPosition"); - worldPosition.addRule(openGLES2, QShaderNode::Rule("highp vec3 $value = $name;", - QByteArrayList() << "varying highp vec3 $name;")); - worldPosition.addRule(openGL3, QShaderNode::Rule("vec3 $value = $name;", - QByteArrayList() << "in vec3 $name;")); - - auto texture = createNode({ - createPort(QShaderNodePort::Output, "texture") - }); - texture.addRule(openGLES2, QShaderNode::Rule("sampler2D $texture = texture;", - QByteArrayList() << "uniform sampler2D texture;")); - texture.addRule(openGL3, QShaderNode::Rule("sampler2D $texture = texture;", - QByteArrayList() << "uniform sampler2D texture;")); - - auto texCoord = createNode({ - createPort(QShaderNodePort::Output, "texCoord") - }); - texCoord.addRule(openGLES2, QShaderNode::Rule("highp vec2 $texCoord = texCoord;", - QByteArrayList() << "varying highp vec2 texCoord;")); - texCoord.addRule(openGL3, QShaderNode::Rule("vec2 $texCoord = texCoord;", - QByteArrayList() << "in vec2 texCoord;")); - - auto lightIntensity = createNode({ - createPort(QShaderNodePort::Output, "lightIntensity") - }); - lightIntensity.addRule(openGLES2, QShaderNode::Rule("highp float $lightIntensity = lightIntensity;", - QByteArrayList() << "uniform highp float lightIntensity;")); - lightIntensity.addRule(openGL3, QShaderNode::Rule("float $lightIntensity = lightIntensity;", - QByteArrayList() << "uniform float lightIntensity;")); - - auto exposure = createNode({ - createPort(QShaderNodePort::Output, "exposure") - }); - exposure.addRule(openGLES2, QShaderNode::Rule("highp float $exposure = exposure;", - QByteArrayList() << "uniform highp float exposure;")); - exposure.addRule(openGL3, QShaderNode::Rule("float $exposure = exposure;", - QByteArrayList() << "uniform float exposure;")); - - auto fragColor = createNode({ - createPort(QShaderNodePort::Input, "fragColor") - }); - fragColor.addRule(openGLES2, QShaderNode::Rule("gl_fragColor = $fragColor;")); - fragColor.addRule(openGL3, QShaderNode::Rule("fragColor = $fragColor;", - QByteArrayList() << "out vec4 fragColor;")); - - auto sampleTexture = createNode({ - createPort(QShaderNodePort::Input, "sampler"), - createPort(QShaderNodePort::Input, "coord"), - createPort(QShaderNodePort::Output, "color") - }); - sampleTexture.addRule(openGLES2, QShaderNode::Rule("highp vec4 $color = texture2D($sampler, $coord);")); - sampleTexture.addRule(openGL3, QShaderNode::Rule("vec4 $color = texture($sampler, $coord);")); - - auto lightFunction = createNode({ - createPort(QShaderNodePort::Input, "baseColor"), - createPort(QShaderNodePort::Input, "position"), - createPort(QShaderNodePort::Input, "lightIntensity"), - createPort(QShaderNodePort::Output, "outputColor") - }); - lightFunction.addRule(openGLES2, QShaderNode::Rule("highp vec4 $outputColor = lightModel($baseColor, $position, $lightIntensity);", - QByteArrayList() << "#pragma include es2/lightmodel.frag.inc")); - lightFunction.addRule(openGL3, QShaderNode::Rule("vec4 $outputColor = lightModel($baseColor, $position, $lightIntensity);", - QByteArrayList() << "#pragma include gl3/lightmodel.frag.inc")); - - auto exposureFunction = createNode({ - createPort(QShaderNodePort::Input, "inputColor"), - createPort(QShaderNodePort::Input, "exposure"), - createPort(QShaderNodePort::Output, "outputColor") - }); - exposureFunction.addRule(openGLES2, QShaderNode::Rule("highp vec4 $outputColor = $inputColor * pow(2.0, $exposure);")); - exposureFunction.addRule(openGL3, QShaderNode::Rule("vec4 $outputColor = $inputColor * pow(2.0, $exposure);")); - - graph.addNode(worldPosition); - graph.addNode(texture); - graph.addNode(texCoord); - graph.addNode(lightIntensity); - graph.addNode(exposure); - graph.addNode(fragColor); - graph.addNode(sampleTexture); - graph.addNode(lightFunction); - graph.addNode(exposureFunction); - - graph.addEdge(createEdge(texture.uuid(), "texture", sampleTexture.uuid(), "sampler")); - graph.addEdge(createEdge(texCoord.uuid(), "texCoord", sampleTexture.uuid(), "coord")); - - graph.addEdge(createEdge(worldPosition.uuid(), "value", lightFunction.uuid(), "position")); - graph.addEdge(createEdge(sampleTexture.uuid(), "color", lightFunction.uuid(), "baseColor")); - graph.addEdge(createEdge(lightIntensity.uuid(), "lightIntensity", lightFunction.uuid(), "lightIntensity")); - - graph.addEdge(createEdge(lightFunction.uuid(), "outputColor", exposureFunction.uuid(), "inputColor")); - graph.addEdge(createEdge(exposure.uuid(), "exposure", exposureFunction.uuid(), "exposure")); - - graph.addEdge(createEdge(exposureFunction.uuid(), "outputColor", fragColor.uuid(), "fragColor")); - - return graph; - } -} - -class tst_QShaderGenerator : public QObject -{ - Q_OBJECT -private slots: - void shouldHaveDefaultState(); - void shouldGenerateShaderCode_data(); - void shouldGenerateShaderCode(); - void shouldGenerateVersionCommands_data(); - void shouldGenerateVersionCommands(); - void shouldProcessLanguageQualifierAndTypeEnums_data(); - void shouldProcessLanguageQualifierAndTypeEnums(); - void shouldGenerateDifferentCodeDependingOnActiveLayers(); - void shouldUseGlobalVariableRatherThanTemporaries(); - void shouldGenerateTemporariesWisely(); - void shouldHandlePortNamesPrefixingOneAnother(); - void shouldHandleNodesWithMultipleOutputPorts(); - void shouldHandleExpressionsInInputNodes(); -}; - -void tst_QShaderGenerator::shouldHaveDefaultState() -{ - // GIVEN - auto generator = QShaderGenerator(); - - // THEN - QVERIFY(generator.graph.nodes().isEmpty()); - QVERIFY(generator.graph.edges().isEmpty()); - QVERIFY(!generator.format.isValid()); -} - -void tst_QShaderGenerator::shouldGenerateShaderCode_data() -{ - QTest::addColumn<QShaderGraph>("graph"); - QTest::addColumn<QShaderFormat>("format"); - QTest::addColumn<QByteArray>("expectedCode"); - - const auto graph = createFragmentShaderGraph(); - - const auto openGLES2 = createFormat(QShaderFormat::OpenGLES, 2, 0); - const auto openGL3 = createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0); - const auto openGL32 = createFormat(QShaderFormat::OpenGLCoreProfile, 3, 2); - const auto openGL4 = createFormat(QShaderFormat::OpenGLCoreProfile, 4, 0); - - const auto versionGLES2 = QByteArrayList() << "#version 100" << ""; - const auto versionGL3 = QByteArrayList() << "#version 130" << ""; - const auto versionGL32 = QByteArrayList() << "#version 150 core" << ""; - const auto versionGL4 = QByteArrayList() << "#version 400 core" << ""; - - const auto es2Code = QByteArrayList() << "varying highp vec3 worldPosition;" - << "uniform sampler2D texture;" - << "varying highp vec2 texCoord;" - << "uniform highp float lightIntensity;" - << "uniform highp float exposure;" - << "#pragma include es2/lightmodel.frag.inc" - << "" - << "void main()" - << "{" - << " gl_fragColor = (((((lightModel(((texture2D(texture, texCoord))), worldPosition, lightIntensity)))) * pow(2.0, exposure)));" - << "}" - << ""; - - const auto gl3Code = QByteArrayList() << "in vec3 worldPosition;" - << "uniform sampler2D texture;" - << "in vec2 texCoord;" - << "uniform float lightIntensity;" - << "uniform float exposure;" - << "out vec4 fragColor;" - << "#pragma include gl3/lightmodel.frag.inc" - << "" - << "void main()" - << "{" - << " fragColor = (((((lightModel(((texture(texture, texCoord))), worldPosition, lightIntensity)))) * pow(2.0, exposure)));" - << "}" - << ""; - - QTest::newRow("EmptyGraphAndFormat") << QShaderGraph() << QShaderFormat() << QByteArrayLiteral("\nvoid main()\n{\n}\n"); - QTest::newRow("LightExposureGraphAndES2") << graph << openGLES2 << (versionGLES2 + es2Code).join('\n'); - QTest::newRow("LightExposureGraphAndGL3") << graph << openGL3 << (versionGL3 + gl3Code).join('\n'); - QTest::newRow("LightExposureGraphAndGL32") << graph << openGL32 << (versionGL32 + gl3Code).join('\n'); - QTest::newRow("LightExposureGraphAndGL4") << graph << openGL4 << (versionGL4 + gl3Code).join('\n'); -} - -void tst_QShaderGenerator::shouldGenerateShaderCode() -{ - // GIVEN - QFETCH(QShaderGraph, graph); - QFETCH(QShaderFormat, format); - - auto generator = QShaderGenerator(); - generator.graph = graph; - generator.format = format; - - // WHEN - const auto code = generator.createShaderCode(); - - // THEN - QFETCH(QByteArray, expectedCode); - QCOMPARE(code, expectedCode); -} - -void tst_QShaderGenerator::shouldGenerateVersionCommands_data() -{ - QTest::addColumn<QShaderFormat>("format"); - QTest::addColumn<QByteArray>("version"); - - QTest::newRow("GLES2") << createFormat(QShaderFormat::OpenGLES, 2, 0) << QByteArrayLiteral("#version 100"); - QTest::newRow("GLES3") << createFormat(QShaderFormat::OpenGLES, 3, 0) << QByteArrayLiteral("#version 300 es"); - - QTest::newRow("GL20") << createFormat(QShaderFormat::OpenGLNoProfile, 2, 0) << QByteArrayLiteral("#version 110"); - QTest::newRow("GL21") << createFormat(QShaderFormat::OpenGLNoProfile, 2, 1) << QByteArrayLiteral("#version 120"); - QTest::newRow("GL30") << createFormat(QShaderFormat::OpenGLNoProfile, 3, 0) << QByteArrayLiteral("#version 130"); - QTest::newRow("GL31") << createFormat(QShaderFormat::OpenGLNoProfile, 3, 1) << QByteArrayLiteral("#version 140"); - QTest::newRow("GL32") << createFormat(QShaderFormat::OpenGLNoProfile, 3, 2) << QByteArrayLiteral("#version 150"); - QTest::newRow("GL33") << createFormat(QShaderFormat::OpenGLNoProfile, 3, 3) << QByteArrayLiteral("#version 330"); - QTest::newRow("GL40") << createFormat(QShaderFormat::OpenGLNoProfile, 4, 0) << QByteArrayLiteral("#version 400"); - QTest::newRow("GL41") << createFormat(QShaderFormat::OpenGLNoProfile, 4, 1) << QByteArrayLiteral("#version 410"); - QTest::newRow("GL42") << createFormat(QShaderFormat::OpenGLNoProfile, 4, 2) << QByteArrayLiteral("#version 420"); - QTest::newRow("GL43") << createFormat(QShaderFormat::OpenGLNoProfile, 4, 3) << QByteArrayLiteral("#version 430"); - - QTest::newRow("GL20core") << createFormat(QShaderFormat::OpenGLCoreProfile, 2, 0) << QByteArrayLiteral("#version 110"); - QTest::newRow("GL21core") << createFormat(QShaderFormat::OpenGLCoreProfile, 2, 1) << QByteArrayLiteral("#version 120"); - QTest::newRow("GL30core") << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0) << QByteArrayLiteral("#version 130"); - QTest::newRow("GL31core") << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 1) << QByteArrayLiteral("#version 140"); - QTest::newRow("GL32core") << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 2) << QByteArrayLiteral("#version 150 core"); - QTest::newRow("GL33core") << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 3) << QByteArrayLiteral("#version 330 core"); - QTest::newRow("GL40core") << createFormat(QShaderFormat::OpenGLCoreProfile, 4, 0) << QByteArrayLiteral("#version 400 core"); - QTest::newRow("GL41core") << createFormat(QShaderFormat::OpenGLCoreProfile, 4, 1) << QByteArrayLiteral("#version 410 core"); - QTest::newRow("GL42core") << createFormat(QShaderFormat::OpenGLCoreProfile, 4, 2) << QByteArrayLiteral("#version 420 core"); - QTest::newRow("GL43core") << createFormat(QShaderFormat::OpenGLCoreProfile, 4, 3) << QByteArrayLiteral("#version 430 core"); - - QTest::newRow("GL20compatibility") << createFormat(QShaderFormat::OpenGLCompatibilityProfile, 2, 0) << QByteArrayLiteral("#version 110"); - QTest::newRow("GL21compatibility") << createFormat(QShaderFormat::OpenGLCompatibilityProfile, 2, 1) << QByteArrayLiteral("#version 120"); - QTest::newRow("GL30compatibility") << createFormat(QShaderFormat::OpenGLCompatibilityProfile, 3, 0) << QByteArrayLiteral("#version 130"); - QTest::newRow("GL31compatibility") << createFormat(QShaderFormat::OpenGLCompatibilityProfile, 3, 1) << QByteArrayLiteral("#version 140"); - QTest::newRow("GL32compatibility") << createFormat(QShaderFormat::OpenGLCompatibilityProfile, 3, 2) << QByteArrayLiteral("#version 150 compatibility"); - QTest::newRow("GL33compatibility") << createFormat(QShaderFormat::OpenGLCompatibilityProfile, 3, 3) << QByteArrayLiteral("#version 330 compatibility"); - QTest::newRow("GL40compatibility") << createFormat(QShaderFormat::OpenGLCompatibilityProfile, 4, 0) << QByteArrayLiteral("#version 400 compatibility"); - QTest::newRow("GL41compatibility") << createFormat(QShaderFormat::OpenGLCompatibilityProfile, 4, 1) << QByteArrayLiteral("#version 410 compatibility"); - QTest::newRow("GL42compatibility") << createFormat(QShaderFormat::OpenGLCompatibilityProfile, 4, 2) << QByteArrayLiteral("#version 420 compatibility"); - QTest::newRow("GL43compatibility") << createFormat(QShaderFormat::OpenGLCompatibilityProfile, 4, 3) << QByteArrayLiteral("#version 430 compatibility"); -} - -void tst_QShaderGenerator::shouldGenerateVersionCommands() -{ - // GIVEN - QFETCH(QShaderFormat, format); - - auto generator = QShaderGenerator(); - generator.format = format; - - // WHEN - const auto code = generator.createShaderCode(); - - // THEN - QFETCH(QByteArray, version); - const auto expectedCode = (QByteArrayList() << version - << "" - << "" - << "void main()" - << "{" - << "}" - << "").join('\n'); - QCOMPARE(code, expectedCode); -} - - -namespace { - QString 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::BuiltIn: - return "//"; - 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::BuiltIn: - return "//"; - case QShaderLanguage::Output: - return "out"; - case QShaderLanguage::Uniform: - return "uniform"; - } - } - - Q_UNREACHABLE(); - } - - QString 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(); - } -} - -void tst_QShaderGenerator::shouldProcessLanguageQualifierAndTypeEnums_data() -{ - QTest::addColumn<QShaderGraph>("graph"); - QTest::addColumn<QShaderFormat>("format"); - QTest::addColumn<QByteArray>("expectedCode"); - - { - const auto es2 = createFormat(QShaderFormat::OpenGLES, 2, 0); - const auto es3 = createFormat(QShaderFormat::OpenGLES, 3, 0); - const auto gl2 = createFormat(QShaderFormat::OpenGLNoProfile, 2, 0); - const auto gl3 = createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0); - const auto gl4 = createFormat(QShaderFormat::OpenGLCoreProfile, 4, 0); - - const auto qualifierEnum = QMetaEnum::fromType<QShaderLanguage::StorageQualifier>(); - const auto typeEnum = QMetaEnum::fromType<QShaderLanguage::VariableType>(); - - for (int qualifierIndex = 0; qualifierIndex < qualifierEnum.keyCount(); qualifierIndex++) { - const auto qualifierName = qualifierEnum.key(qualifierIndex); - const auto qualifierValue = static_cast<QShaderLanguage::StorageQualifier>(qualifierEnum.value(qualifierIndex)); - - for (int typeIndex = 0; typeIndex < typeEnum.keyCount(); typeIndex++) { - const auto typeName = typeEnum.key(typeIndex); - const auto typeValue = static_cast<QShaderLanguage::VariableType>(typeEnum.value(typeIndex)); - - auto graph = QShaderGraph(); - - auto worldPosition = createNode({ - createPort(QShaderNodePort::Output, "value") - }); - worldPosition.setParameter("name", "worldPosition"); - worldPosition.setParameter("qualifier", QVariant::fromValue<QShaderLanguage::StorageQualifier>(qualifierValue)); - worldPosition.setParameter("type", QVariant::fromValue<QShaderLanguage::VariableType>(typeValue)); - worldPosition.addRule(es2, QShaderNode::Rule("highp $type $value = $name;", - QByteArrayList() << "$qualifier highp $type $name;")); - worldPosition.addRule(gl2, QShaderNode::Rule("$type $value = $name;", - QByteArrayList() << "$qualifier $type $name;")); - worldPosition.addRule(gl3, QShaderNode::Rule("$type $value = $name;", - QByteArrayList() << "$qualifier $type $name;")); - - auto fragColor = createNode({ - createPort(QShaderNodePort::Input, "fragColor") - }); - fragColor.addRule(es2, QShaderNode::Rule("gl_fragColor = $fragColor;")); - fragColor.addRule(gl2, QShaderNode::Rule("gl_fragColor = $fragColor;")); - fragColor.addRule(gl3, QShaderNode::Rule("fragColor = $fragColor;", - QByteArrayList() << "out vec4 fragColor;")); - - graph.addNode(worldPosition); - graph.addNode(fragColor); - - graph.addEdge(createEdge(worldPosition.uuid(), "value", fragColor.uuid(), "fragColor")); - - const auto gl2Code = (QByteArrayList() << "#version 110" - << "" - << QStringLiteral("%1 %2 worldPosition;").arg(toGlsl(qualifierValue, gl2)) - .arg(toGlsl(typeValue)) - .toUtf8() - << "" - << "void main()" - << "{" - << " gl_fragColor = worldPosition;" - << "}" - << "").join("\n"); - const auto gl3Code = (QByteArrayList() << "#version 130" - << "" - << QStringLiteral("%1 %2 worldPosition;").arg(toGlsl(qualifierValue, gl3)) - .arg(toGlsl(typeValue)) - .toUtf8() - << "out vec4 fragColor;" - << "" - << "void main()" - << "{" - << " fragColor = worldPosition;" - << "}" - << "").join("\n"); - const auto gl4Code = (QByteArrayList() << "#version 400 core" - << "" - << QStringLiteral("%1 %2 worldPosition;").arg(toGlsl(qualifierValue, gl4)) - .arg(toGlsl(typeValue)) - .toUtf8() - << "out vec4 fragColor;" - << "" - << "void main()" - << "{" - << " fragColor = worldPosition;" - << "}" - << "").join("\n"); - const auto es2Code = (QByteArrayList() << "#version 100" - << "" - << QStringLiteral("%1 highp %2 worldPosition;").arg(toGlsl(qualifierValue, es2)) - .arg(toGlsl(typeValue)) - .toUtf8() - << "" - << "void main()" - << "{" - << " gl_fragColor = worldPosition;" - << "}" - << "").join("\n"); - const auto es3Code = (QByteArrayList() << "#version 300 es" - << "" - << QStringLiteral("%1 highp %2 worldPosition;").arg(toGlsl(qualifierValue, es3)) - .arg(toGlsl(typeValue)) - .toUtf8() - << "" - << "void main()" - << "{" - << " gl_fragColor = worldPosition;" - << "}" - << "").join("\n"); - - QTest::addRow("%s %s ES2", qualifierName, typeName) << graph << es2 << es2Code; - QTest::addRow("%s %s ES3", qualifierName, typeName) << graph << es3 << es3Code; - QTest::addRow("%s %s GL2", qualifierName, typeName) << graph << gl2 << gl2Code; - QTest::addRow("%s %s GL3", qualifierName, typeName) << graph << gl3 << gl3Code; - QTest::addRow("%s %s GL4", qualifierName, typeName) << graph << gl4 << gl4Code; - } - } - } - - { - const auto es2 = createFormat(QShaderFormat::OpenGLES, 2, 0, QShaderFormat::Vertex); - const auto es3 = createFormat(QShaderFormat::OpenGLES, 3, 0, QShaderFormat::Vertex); - const auto gl2 = createFormat(QShaderFormat::OpenGLNoProfile, 2, 0, QShaderFormat::Vertex); - const auto gl3 = createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0, QShaderFormat::Vertex); - const auto gl4 = createFormat(QShaderFormat::OpenGLCoreProfile, 4, 0, QShaderFormat::Vertex); - - auto graph = QShaderGraph(); - - auto vertexPosition = createNode({ - createPort(QShaderNodePort::Output, "value") - }); - vertexPosition.setParameter("name", "vertexPosition"); - vertexPosition.setParameter("qualifier", QVariant::fromValue<QShaderLanguage::StorageQualifier>(QShaderLanguage::Input)); - vertexPosition.setParameter("type", QVariant::fromValue<QShaderLanguage::VariableType>(QShaderLanguage::Vec4)); - - vertexPosition.addRule(es2, QShaderNode::Rule("", - QByteArrayList() << "$qualifier highp $type $name;")); - vertexPosition.addRule(gl2, QShaderNode::Rule("", - QByteArrayList() << "$qualifier $type $name;")); - vertexPosition.addRule(gl3, QShaderNode::Rule("", - QByteArrayList() << "$qualifier $type $name;")); - - graph.addNode(vertexPosition); - - const auto gl2Code = (QByteArrayList() << "#version 110" - << "" - << "attribute vec4 vertexPosition;" - << "" - << "void main()" - << "{" - << "}" - << "").join("\n"); - const auto gl3Code = (QByteArrayList() << "#version 130" - << "" - << "in vec4 vertexPosition;" - << "" - << "void main()" - << "{" - << "}" - << "").join("\n"); - const auto gl4Code = (QByteArrayList() << "#version 400 core" - << "" - << "in vec4 vertexPosition;" - << "" - << "void main()" - << "{" - << "}" - << "").join("\n"); - const auto es2Code = (QByteArrayList() << "#version 100" - << "" - << "attribute highp vec4 vertexPosition;" - << "" - << "void main()" - << "{" - << "}" - << "").join("\n"); - const auto es3Code = (QByteArrayList() << "#version 300 es" - << "" - << "in highp vec4 vertexPosition;" - << "" - << "void main()" - << "{" - << "}" - << "").join("\n"); - - QTest::addRow("Attribute header substitution ES2") << graph << es2 << es2Code; - QTest::addRow("Attribute header substitution ES3") << graph << es3 << es3Code; - QTest::addRow("Attribute header substitution GL2") << graph << gl2 << gl2Code; - QTest::addRow("Attribute header substitution GL3") << graph << gl3 << gl3Code; - QTest::addRow("Attribute header substitution GL4") << graph << gl4 << gl4Code; - } -} - -void tst_QShaderGenerator::shouldProcessLanguageQualifierAndTypeEnums() -{ - // GIVEN - QFETCH(QShaderGraph, graph); - QFETCH(QShaderFormat, format); - - auto generator = QShaderGenerator(); - generator.graph = graph; - generator.format = format; - - // WHEN - const auto code = generator.createShaderCode(); - - // THEN - QFETCH(QByteArray, expectedCode); - QCOMPARE(code, expectedCode); -} - -void tst_QShaderGenerator::shouldGenerateDifferentCodeDependingOnActiveLayers() -{ - // GIVEN - const auto gl4 = createFormat(QShaderFormat::OpenGLCoreProfile, 4, 0); - - auto texCoord = createNode({ - createPort(QShaderNodePort::Output, "texCoord") - }, { - "diffuseTexture", - "normalTexture" - }); - texCoord.addRule(gl4, QShaderNode::Rule("vec2 $texCoord = texCoord;", - QByteArrayList() << "in vec2 texCoord;")); - auto diffuseUniform = createNode({ - createPort(QShaderNodePort::Output, "color") - }, {"diffuseUniform"}); - diffuseUniform.addRule(gl4, QShaderNode::Rule("vec4 $color = diffuseUniform;", - QByteArrayList() << "uniform vec4 diffuseUniform;")); - auto diffuseTexture = createNode({ - createPort(QShaderNodePort::Input, "coord"), - createPort(QShaderNodePort::Output, "color") - }, {"diffuseTexture"}); - diffuseTexture.addRule(gl4, QShaderNode::Rule("vec4 $color = texture2D(diffuseTexture, $coord);", - QByteArrayList() << "uniform sampler2D diffuseTexture;")); - auto normalUniform = createNode({ - createPort(QShaderNodePort::Output, "normal") - }, {"normalUniform"}); - normalUniform.addRule(gl4, QShaderNode::Rule("vec3 $normal = normalUniform;", - QByteArrayList() << "uniform vec3 normalUniform;")); - auto normalTexture = createNode({ - createPort(QShaderNodePort::Input, "coord"), - createPort(QShaderNodePort::Output, "normal") - }, {"normalTexture"}); - normalTexture.addRule(gl4, QShaderNode::Rule("vec3 $normal = texture2D(normalTexture, $coord).rgb;", - QByteArrayList() << "uniform sampler2D normalTexture;")); - auto lightFunction = createNode({ - createPort(QShaderNodePort::Input, "color"), - createPort(QShaderNodePort::Input, "normal"), - createPort(QShaderNodePort::Output, "output") - }); - lightFunction.addRule(gl4, QShaderNode::Rule("vec4 $output = lightModel($color, $normal);", - QByteArrayList() << "#pragma include gl4/lightmodel.frag.inc")); - auto fragColor = createNode({ - createPort(QShaderNodePort::Input, "fragColor") - }); - fragColor.addRule(gl4, QShaderNode::Rule("fragColor = $fragColor;", - QByteArrayList() << "out vec4 fragColor;")); - - const auto graph = [=] { - auto res = QShaderGraph(); - - res.addNode(texCoord); - res.addNode(diffuseUniform); - res.addNode(diffuseTexture); - res.addNode(normalUniform); - res.addNode(normalTexture); - res.addNode(lightFunction); - res.addNode(fragColor); - - res.addEdge(createEdge(diffuseUniform.uuid(), "color", lightFunction.uuid(), "color", {"diffuseUniform"})); - res.addEdge(createEdge(texCoord.uuid(), "texCoord", diffuseTexture.uuid(), "coord", {"diffuseTexture"})); - res.addEdge(createEdge(diffuseTexture.uuid(), "color", lightFunction.uuid(), "color", {"diffuseTexture"})); - - res.addEdge(createEdge(normalUniform.uuid(), "normal", lightFunction.uuid(), "normal", {"normalUniform"})); - res.addEdge(createEdge(texCoord.uuid(), "texCoord", normalTexture.uuid(), "coord", {"normalTexture"})); - res.addEdge(createEdge(normalTexture.uuid(), "normal", lightFunction.uuid(), "normal", {"normalTexture"})); - - res.addEdge(createEdge(lightFunction.uuid(), "output", fragColor.uuid(), "fragColor")); - - return res; - }(); - - auto generator = QShaderGenerator(); - generator.graph = graph; - generator.format = gl4; - - { - // WHEN - const auto code = generator.createShaderCode({"diffuseUniform", "normalUniform"}); - - // THEN - const auto expected = QByteArrayList() - << "#version 400 core" - << "" - << "uniform vec4 diffuseUniform;" - << "uniform vec3 normalUniform;" - << "#pragma include gl4/lightmodel.frag.inc" - << "out vec4 fragColor;" - << "" - << "void main()" - << "{" - << " fragColor = ((lightModel(diffuseUniform, normalUniform)));" - << "}" - << ""; - QCOMPARE(code, expected.join("\n")); - } - - { - // WHEN - const auto code = generator.createShaderCode({"diffuseUniform", "normalTexture"}); - - // THEN - const auto expected = QByteArrayList() - << "#version 400 core" - << "" - << "in vec2 texCoord;" - << "uniform vec4 diffuseUniform;" - << "uniform sampler2D normalTexture;" - << "#pragma include gl4/lightmodel.frag.inc" - << "out vec4 fragColor;" - << "" - << "void main()" - << "{" - << " fragColor = ((lightModel(diffuseUniform, texture2D(normalTexture, texCoord).rgb)));" - << "}" - << ""; - QCOMPARE(code, expected.join("\n")); - } - - { - // WHEN - const auto code = generator.createShaderCode({"diffuseTexture", "normalUniform"}); - - // THEN - const auto expected = QByteArrayList() - << "#version 400 core" - << "" - << "in vec2 texCoord;" - << "uniform sampler2D diffuseTexture;" - << "uniform vec3 normalUniform;" - << "#pragma include gl4/lightmodel.frag.inc" - << "out vec4 fragColor;" - << "" - << "void main()" - << "{" - << " fragColor = ((lightModel(texture2D(diffuseTexture, texCoord), normalUniform)));" - << "}" - << ""; - QCOMPARE(code, expected.join("\n")); - } - - { - // WHEN - const auto code = generator.createShaderCode({"diffuseTexture", "normalTexture"}); - - // THEN - const auto expected = QByteArrayList() - << "#version 400 core" - << "" - << "in vec2 texCoord;" - << "uniform sampler2D diffuseTexture;" - << "uniform sampler2D normalTexture;" - << "#pragma include gl4/lightmodel.frag.inc" - << "out vec4 fragColor;" - << "" - << "void main()" - << "{" - << " fragColor = ((lightModel(texture2D(diffuseTexture, texCoord), texture2D(normalTexture, texCoord).rgb)));" - << "}" - << ""; - QCOMPARE(code, expected.join("\n")); - } -} - -void tst_QShaderGenerator::shouldUseGlobalVariableRatherThanTemporaries() -{ - // GIVEN - const auto gl4 = createFormat(QShaderFormat::OpenGLCoreProfile, 4, 0); - - { - // WHEN - auto vertexPosition = createNode({ - createPort(QShaderNodePort::Output, "vertexPosition") - }); - vertexPosition.addRule(gl4, QShaderNode::Rule("vec4 $vertexPosition = vertexPosition;", - QByteArrayList() << "in vec4 vertexPosition;")); - - auto fakeMultiPlyNoSpace = createNode({ - createPort(QShaderNodePort::Input, "varName"), - createPort(QShaderNodePort::Output, "out") - }); - fakeMultiPlyNoSpace.addRule(gl4, QShaderNode::Rule("vec4 $out = $varName*speed;")); - - auto fakeMultiPlySpace = createNode({ - createPort(QShaderNodePort::Input, "varName"), - createPort(QShaderNodePort::Output, "out") - }); - fakeMultiPlySpace.addRule(gl4, QShaderNode::Rule("vec4 $out = $varName * speed;")); - - auto fakeJoinNoSpace = createNode({ - createPort(QShaderNodePort::Input, "varName"), - createPort(QShaderNodePort::Output, "out") - }); - fakeJoinNoSpace.addRule(gl4, QShaderNode::Rule("vec4 $out = vec4($varName.xyz,$varName.w);")); - - auto fakeJoinSpace = createNode({ - createPort(QShaderNodePort::Input, "varName"), - createPort(QShaderNodePort::Output, "out") - }); - fakeJoinSpace.addRule(gl4, QShaderNode::Rule("vec4 $out = vec4($varName.xyz, $varName.w);")); - - auto fakeAdd = createNode({ - createPort(QShaderNodePort::Input, "varName"), - createPort(QShaderNodePort::Output, "out") - }); - fakeAdd.addRule(gl4, QShaderNode::Rule("vec4 $out = $varName.xyzw + $varName;")); - - auto fakeSub = createNode({ - createPort(QShaderNodePort::Input, "varName"), - createPort(QShaderNodePort::Output, "out") - }); - fakeSub.addRule(gl4, QShaderNode::Rule("vec4 $out = $varName.xyzw - $varName;")); - - auto fakeDiv = createNode({ - createPort(QShaderNodePort::Input, "varName"), - createPort(QShaderNodePort::Output, "out") - }); - fakeDiv.addRule(gl4, QShaderNode::Rule("vec4 $out = $varName / v0;")); - - auto fragColor = createNode({ - createPort(QShaderNodePort::Input, "input1"), - createPort(QShaderNodePort::Input, "input2"), - createPort(QShaderNodePort::Input, "input3"), - createPort(QShaderNodePort::Input, "input4"), - createPort(QShaderNodePort::Input, "input5"), - createPort(QShaderNodePort::Input, "input6"), - createPort(QShaderNodePort::Input, "input7") - }); - fragColor.addRule(gl4, QShaderNode::Rule("fragColor = $input1 + $input2 + $input3 + $input4 + $input5 + $input6 + $input7;", - QByteArrayList() << "out vec4 fragColor;")); - - const auto graph = [=] { - auto res = QShaderGraph(); - - res.addNode(vertexPosition); - res.addNode(fakeMultiPlyNoSpace); - res.addNode(fakeMultiPlySpace); - res.addNode(fakeJoinNoSpace); - res.addNode(fakeJoinSpace); - res.addNode(fakeAdd); - res.addNode(fakeSub); - res.addNode(fakeDiv); - res.addNode(fragColor); - - res.addEdge(createEdge(vertexPosition.uuid(), "vertexPosition", fakeMultiPlyNoSpace.uuid(), "varName")); - res.addEdge(createEdge(vertexPosition.uuid(), "vertexPosition", fakeMultiPlySpace.uuid(), "varName")); - res.addEdge(createEdge(vertexPosition.uuid(), "vertexPosition", fakeJoinNoSpace.uuid(), "varName")); - res.addEdge(createEdge(vertexPosition.uuid(), "vertexPosition", fakeJoinSpace.uuid(), "varName")); - res.addEdge(createEdge(vertexPosition.uuid(), "vertexPosition", fakeAdd.uuid(), "varName")); - res.addEdge(createEdge(vertexPosition.uuid(), "vertexPosition", fakeSub.uuid(), "varName")); - res.addEdge(createEdge(vertexPosition.uuid(), "vertexPosition", fakeDiv.uuid(), "varName")); - res.addEdge(createEdge(fakeMultiPlyNoSpace.uuid(), "out", fragColor.uuid(), "input1")); - res.addEdge(createEdge(fakeMultiPlySpace.uuid(), "out", fragColor.uuid(), "input2")); - res.addEdge(createEdge(fakeJoinNoSpace.uuid(), "out", fragColor.uuid(), "input3")); - res.addEdge(createEdge(fakeJoinSpace.uuid(), "out", fragColor.uuid(), "input4")); - res.addEdge(createEdge(fakeAdd.uuid(), "out", fragColor.uuid(), "input5")); - res.addEdge(createEdge(fakeSub.uuid(), "out", fragColor.uuid(), "input6")); - res.addEdge(createEdge(fakeDiv.uuid(), "out", fragColor.uuid(), "input7")); - - return res; - }(); - - auto generator = QShaderGenerator(); - generator.graph = graph; - generator.format = gl4; - - const auto code = generator.createShaderCode({"diffuseUniform", "normalUniform"}); - - // THEN - const auto expected = QByteArrayList() - << "#version 400 core" - << "" - << "in vec4 vertexPosition;" - << "out vec4 fragColor;" - << "" - << "void main()" - << "{" - << " fragColor = (((((((vertexPosition*speed + vertexPosition * speed + ((vec4(vertexPosition.xyz,vertexPosition.w))) + ((vec4(vertexPosition.xyz, vertexPosition.w))) + ((vertexPosition.xyzw + vertexPosition)) + ((vertexPosition.xyzw - vertexPosition)) + ((vertexPosition / vertexPosition)))))))));" - << "}" - << ""; - QCOMPARE(code, expected.join("\n")); - } -} - -void tst_QShaderGenerator::shouldGenerateTemporariesWisely() -{ - // GIVEN - const auto gl4 = createFormat(QShaderFormat::OpenGLCoreProfile, 4, 0); - - { - auto attribute = createNode({ - createPort(QShaderNodePort::Output, "vertexPosition") - }); - attribute.addRule(gl4, QShaderNode::Rule("vec4 $vertexPosition = vertexPosition;", - QByteArrayList() << "in vec4 vertexPosition;")); - - auto complexFunction = createNode({ - createPort(QShaderNodePort::Input, "inputVarName"), - createPort(QShaderNodePort::Output, "out") - }); - complexFunction.addRule(gl4, QShaderNode::Rule("vec4 $out = $inputVarName * 2.0;")); - - auto complexFunction2 = createNode({ - createPort(QShaderNodePort::Input, "inputVarName"), - createPort(QShaderNodePort::Output, "out") - }); - complexFunction2.addRule(gl4, QShaderNode::Rule("vec4 $out = $inputVarName * 4.0;")); - - auto complexFunction3 = createNode({ - createPort(QShaderNodePort::Input, "a"), - createPort(QShaderNodePort::Input, "b"), - createPort(QShaderNodePort::Output, "out") - }); - complexFunction3.addRule(gl4, QShaderNode::Rule("vec4 $out = $a + $b;")); - - auto shaderOutput1 = createNode({ - createPort(QShaderNodePort::Input, "input") - }); - - shaderOutput1.addRule(gl4, QShaderNode::Rule("shaderOutput1 = $input;", - QByteArrayList() << "out vec4 shaderOutput1;")); - - auto shaderOutput2 = createNode({ - createPort(QShaderNodePort::Input, "input") - }); - - shaderOutput2.addRule(gl4, QShaderNode::Rule("shaderOutput2 = $input;", - QByteArrayList() << "out vec4 shaderOutput2;")); - - { - // WHEN - const auto graph = [=] { - auto res = QShaderGraph(); - - res.addNode(attribute); - res.addNode(complexFunction); - res.addNode(shaderOutput1); - - res.addEdge(createEdge(attribute.uuid(), "vertexPosition", complexFunction.uuid(), "inputVarName")); - res.addEdge(createEdge(complexFunction.uuid(), "out", shaderOutput1.uuid(), "input")); - - return res; - }(); - - auto generator = QShaderGenerator(); - generator.graph = graph; - generator.format = gl4; - - const auto code = generator.createShaderCode(); - - // THEN - const auto expected = QByteArrayList() - << "#version 400 core" - << "" - << "in vec4 vertexPosition;" - << "out vec4 shaderOutput1;" - << "" - << "void main()" - << "{" - << " shaderOutput1 = vertexPosition * 2.0;" - << "}" - << ""; - QCOMPARE(code, expected.join("\n")); - } - - { - // WHEN - const auto graph = [=] { - auto res = QShaderGraph(); - - res.addNode(attribute); - res.addNode(complexFunction); - res.addNode(shaderOutput1); - res.addNode(shaderOutput2); - - res.addEdge(createEdge(attribute.uuid(), "vertexPosition", complexFunction.uuid(), "inputVarName")); - res.addEdge(createEdge(complexFunction.uuid(), "out", shaderOutput1.uuid(), "input")); - res.addEdge(createEdge(complexFunction.uuid(), "out", shaderOutput2.uuid(), "input")); - - return res; - }(); - - auto generator = QShaderGenerator(); - generator.graph = graph; - generator.format = gl4; - - const auto code = generator.createShaderCode(); - - // THEN - const auto expected = QByteArrayList() - << "#version 400 core" - << "" - << "in vec4 vertexPosition;" - << "out vec4 shaderOutput1;" - << "out vec4 shaderOutput2;" - << "" - << "void main()" - << "{" - << " vec4 v1 = vertexPosition * 2.0;" - << " shaderOutput2 = v1;" - << " shaderOutput1 = v1;" - << "}" - << ""; - QCOMPARE(code, expected.join("\n")); - } - - { - // WHEN - const auto graph = [=] { - auto res = QShaderGraph(); - - res.addNode(attribute); - res.addNode(complexFunction); - res.addNode(complexFunction2); - res.addNode(complexFunction3); - res.addNode(shaderOutput1); - res.addNode(shaderOutput2); - - res.addEdge(createEdge(attribute.uuid(), "vertexPosition", complexFunction.uuid(), "inputVarName")); - res.addEdge(createEdge(attribute.uuid(), "vertexPosition", complexFunction2.uuid(), "inputVarName")); - - res.addEdge(createEdge(complexFunction.uuid(), "out", complexFunction3.uuid(), "a")); - res.addEdge(createEdge(complexFunction2.uuid(), "out", complexFunction3.uuid(), "b")); - - res.addEdge(createEdge(complexFunction3.uuid(), "out", shaderOutput1.uuid(), "input")); - res.addEdge(createEdge(complexFunction2.uuid(), "out", shaderOutput2.uuid(), "input")); - - return res; - }(); - - auto generator = QShaderGenerator(); - generator.graph = graph; - generator.format = gl4; - - const auto code = generator.createShaderCode(); - - // THEN - const auto expected = QByteArrayList() - << "#version 400 core" - << "" - << "in vec4 vertexPosition;" - << "out vec4 shaderOutput1;" - << "out vec4 shaderOutput2;" - << "" - << "void main()" - << "{" - << " vec4 v2 = vertexPosition * 4.0;" - << " shaderOutput2 = v2;" - << " shaderOutput1 = (vertexPosition * 2.0 + v2);" - << "}" - << ""; - QCOMPARE(code, expected.join("\n")); - } - } -} - -void tst_QShaderGenerator::shouldHandlePortNamesPrefixingOneAnother() -{ - // GIVEN - const auto gl4 = createFormat(QShaderFormat::OpenGLCoreProfile, 4, 0); - - auto color1 = createNode({ - createPort(QShaderNodePort::Output, "output") - }); - color1.addRule(gl4, QShaderNode::Rule("vec4 $output = color1;", - QByteArrayList() << "in vec4 color1;")); - - auto color2 = createNode({ - createPort(QShaderNodePort::Output, "output") - }); - color2.addRule(gl4, QShaderNode::Rule("vec4 $output = color2;", - QByteArrayList() << "in vec4 color2;")); - - auto addColor = createNode({ - createPort(QShaderNodePort::Output, "color"), - createPort(QShaderNodePort::Input, "color1"), - createPort(QShaderNodePort::Input, "color2"), - }); - addColor.addRule(gl4, QShaderNode::Rule("vec4 $color = $color1 + $color2;")); - - auto shaderOutput = createNode({ - createPort(QShaderNodePort::Input, "input") - }); - - shaderOutput.addRule(gl4, QShaderNode::Rule("shaderOutput = $input;", - QByteArrayList() << "out vec4 shaderOutput;")); - - // WHEN - const auto graph = [=] { - auto res = QShaderGraph(); - - res.addNode(color1); - res.addNode(color2); - res.addNode(addColor); - res.addNode(shaderOutput); - - res.addEdge(createEdge(color1.uuid(), "output", addColor.uuid(), "color1")); - res.addEdge(createEdge(color2.uuid(), "output", addColor.uuid(), "color2")); - res.addEdge(createEdge(addColor.uuid(), "color", shaderOutput.uuid(), "input")); - - return res; - }(); - - auto generator = QShaderGenerator(); - generator.graph = graph; - generator.format = gl4; - - const auto code = generator.createShaderCode(); - - // THEN - const auto expected = QByteArrayList() - << "#version 400 core" - << "" - << "in vec4 color1;" - << "in vec4 color2;" - << "out vec4 shaderOutput;" - << "" - << "void main()" - << "{" - << " shaderOutput = ((color1 + color2));" - << "}" - << ""; - QCOMPARE(code, expected.join("\n")); -} - -void tst_QShaderGenerator::shouldHandleNodesWithMultipleOutputPorts() -{ - // GIVEN - const auto gl4 = createFormat(QShaderFormat::OpenGLCoreProfile, 4, 0); - - auto input = createNode({ - createPort(QShaderNodePort::Output, "output0"), - createPort(QShaderNodePort::Output, "output1") - }); - input.addRule(gl4, QShaderNode::Rule("vec4 $output0 = globalIn0;" - "float $output1 = globalIn1;", - QByteArrayList() << "in vec4 globalIn0;" << "in float globalIn1;")); - - auto function = createNode({ - createPort(QShaderNodePort::Input, "input0"), - createPort(QShaderNodePort::Input, "input1"), - createPort(QShaderNodePort::Output, "output0"), - createPort(QShaderNodePort::Output, "output1") - }); - function.addRule(gl4, QShaderNode::Rule("vec4 $output0 = $input0;" - "float $output1 = $input1;")); - - auto output = createNode({ - createPort(QShaderNodePort::Input, "input0"), - createPort(QShaderNodePort::Input, "input1") - }); - - output.addRule(gl4, QShaderNode::Rule("globalOut0 = $input0;" - "globalOut1 = $input1;", - QByteArrayList() << "out vec4 globalOut0;" << "out float globalOut1;")); - - // WHEN - const auto graph = [=] { - auto res = QShaderGraph(); - - res.addNode(input); - res.addNode(function); - res.addNode(output); - - res.addEdge(createEdge(input.uuid(), "output0", function.uuid(), "input0")); - res.addEdge(createEdge(input.uuid(), "output1", function.uuid(), "input1")); - - res.addEdge(createEdge(function.uuid(), "output0", output.uuid(), "input0")); - res.addEdge(createEdge(function.uuid(), "output1", output.uuid(), "input1")); - - return res; - }(); - - auto generator = QShaderGenerator(); - generator.graph = graph; - generator.format = gl4; - - const auto code = generator.createShaderCode(); - - // THEN - const auto expected = QByteArrayList() - << "#version 400 core" - << "" - << "in vec4 globalIn0;" - << "in float globalIn1;" - << "out vec4 globalOut0;" - << "out float globalOut1;" - << "" - << "void main()" - << "{" - << " globalOut0 = globalIn0;" - << " globalOut1 = globalIn1;" - << "}" - << ""; - QCOMPARE(code, expected.join("\n")); -} - -void tst_QShaderGenerator::shouldHandleExpressionsInInputNodes() -{ - // GIVEN - const auto gl4 = createFormat(QShaderFormat::OpenGLCoreProfile, 4, 0); - - auto input = createNode({ - createPort(QShaderNodePort::Output, "output") - }); - input.addRule(gl4, QShaderNode::Rule("float $output = 3 + 4;")); - - auto output = createNode({ - createPort(QShaderNodePort::Input, "input") - }); - - output.addRule(gl4, QShaderNode::Rule("globalOut = $input;", - QByteArrayList() << "out float globalOut;")); - - // WHEN - const auto graph = [=] { - auto res = QShaderGraph(); - - res.addNode(input); - res.addNode(output); - - res.addEdge(createEdge(input.uuid(), "output", output.uuid(), "input")); - - return res; - }(); - - auto generator = QShaderGenerator(); - generator.graph = graph; - generator.format = gl4; - - const auto code = generator.createShaderCode(); - - // THEN - const auto expected = QByteArrayList() - << "#version 400 core" - << "" - << "out float globalOut;" - << "" - << "void main()" - << "{" - << " globalOut = 3 + 4;" - << "}" - << ""; - QCOMPARE(code, expected.join("\n")); -} - -QTEST_MAIN(tst_QShaderGenerator) - -#include "tst_qshadergenerator.moc" diff --git a/tests/auto/gui/util/qshadergraph/CMakeLists.txt b/tests/auto/gui/util/qshadergraph/CMakeLists.txt deleted file mode 100644 index e510fffb03..0000000000 --- a/tests/auto/gui/util/qshadergraph/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -# Generated from qshadergraph.pro. - -##################################################################### -## tst_qshadergraph Test: -##################################################################### - -qt_internal_add_test(tst_qshadergraph - SOURCES - tst_qshadergraph.cpp - PUBLIC_LIBRARIES - Qt::Gui - Qt::GuiPrivate -) diff --git a/tests/auto/gui/util/qshadergraph/tst_qshadergraph.cpp b/tests/auto/gui/util/qshadergraph/tst_qshadergraph.cpp deleted file mode 100644 index 8cf62eb387..0000000000 --- a/tests/auto/gui/util/qshadergraph/tst_qshadergraph.cpp +++ /dev/null @@ -1,815 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** 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 General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** 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-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include <QTest> - -#include <QtGui/private/qshadergraph_p.h> - -namespace -{ - QShaderNodePort createPort(QShaderNodePort::Direction portDirection, const QString &portName) - { - auto port = QShaderNodePort(); - port.direction = portDirection; - port.name = portName; - return port; - } - - QShaderNode createNode(const QList<QShaderNodePort> &ports, - const QStringList &layers = QStringList()) - { - auto node = QShaderNode(); - node.setUuid(QUuid::createUuid()); - node.setLayers(layers); - for (const auto &port : ports) - node.addPort(port); - return node; - } - - QShaderGraph::Edge createEdge(const QUuid &sourceUuid, const QString &sourceName, - const QUuid &targetUuid, const QString &targetName, - const QStringList &layers = QStringList()) - { - auto edge = QShaderGraph::Edge(); - edge.sourceNodeUuid = sourceUuid; - edge.sourcePortName = sourceName; - edge.targetNodeUuid = targetUuid; - edge.targetPortName = targetName; - edge.layers = layers; - return edge; - } - - QShaderGraph::Statement createStatement(const QShaderNode &node, - const QList<int> &inputs = QList<int>(), - const QList<int> &outputs = QList<int>()) - { - auto statement = QShaderGraph::Statement(); - statement.node = node; - statement.inputs = inputs; - statement.outputs = outputs; - return statement; - } - - void debugStatement(const QString &prefix, const QShaderGraph::Statement &statement) - { - qDebug() << prefix << statement.inputs << statement.uuid().toString() << statement.outputs; - } - - void dumpStatementsIfNeeded(const QList<QShaderGraph::Statement> &statements, - const QList<QShaderGraph::Statement> &expected) - { - if (statements != expected) { - for (int i = 0; i < qMax(statements.size(), expected.size()); i++) { - qDebug() << "----" << i << "----"; - if (i < statements.size()) - debugStatement("A:", statements.at(i)); - if (i < expected.size()) - debugStatement("E:", expected.at(i)); - qDebug() << "-----------"; - } - } - } -} - -class tst_QShaderGraph : public QObject -{ - Q_OBJECT -private slots: - void shouldHaveEdgeDefaultState(); - void shouldTestEdgesEquality_data(); - void shouldTestEdgesEquality(); - void shouldManipulateStatementMembers(); - void shouldTestStatementsEquality_data(); - void shouldTestStatementsEquality(); - void shouldFindIndexFromPortNameInStatements_data(); - void shouldFindIndexFromPortNameInStatements(); - void shouldManageNodeList(); - void shouldManageEdgeList(); - void shouldSerializeGraphForCodeGeneration(); - void shouldHandleUnboundPortsDuringGraphSerialization(); - void shouldSurviveCyclesDuringGraphSerialization(); - void shouldDealWithEdgesJumpingOverLayers(); - void shouldGenerateDifferentStatementsDependingOnActiveLayers(); - void shouldDealWithBranchesWithoutOutput(); -}; - -void tst_QShaderGraph::shouldHaveEdgeDefaultState() -{ - // GIVEN - auto edge = QShaderGraph::Edge(); - - // THEN - QVERIFY(edge.sourceNodeUuid.isNull()); - QVERIFY(edge.sourcePortName.isEmpty()); - QVERIFY(edge.targetNodeUuid.isNull()); - QVERIFY(edge.targetPortName.isEmpty()); -} - -void tst_QShaderGraph::shouldTestEdgesEquality_data() -{ - QTest::addColumn<QShaderGraph::Edge>("left"); - QTest::addColumn<QShaderGraph::Edge>("right"); - QTest::addColumn<bool>("expected"); - - const auto sourceUuid1 = QUuid::createUuid(); - const auto sourceUuid2 = QUuid::createUuid(); - const auto targetUuid1 = QUuid::createUuid(); - const auto targetUuid2 = QUuid::createUuid(); - - QTest::newRow("Equals") << createEdge(sourceUuid1, "foo", targetUuid1, "bar") - << createEdge(sourceUuid1, "foo", targetUuid1, "bar") - << true; - QTest::newRow("SourceUuid") << createEdge(sourceUuid1, "foo", targetUuid1, "bar") - << createEdge(sourceUuid2, "foo", targetUuid1, "bar") - << false; - QTest::newRow("SourceName") << createEdge(sourceUuid1, "foo", targetUuid1, "bar") - << createEdge(sourceUuid1, "bleh", targetUuid1, "bar") - << false; - QTest::newRow("TargetUuid") << createEdge(sourceUuid1, "foo", targetUuid1, "bar") - << createEdge(sourceUuid1, "foo", targetUuid2, "bar") - << false; - QTest::newRow("TargetName") << createEdge(sourceUuid1, "foo", targetUuid1, "bar") - << createEdge(sourceUuid1, "foo", targetUuid1, "bleh") - << false; -} - -void tst_QShaderGraph::shouldTestEdgesEquality() -{ - // GIVEN - QFETCH(QShaderGraph::Edge, left); - QFETCH(QShaderGraph::Edge, right); - - // WHEN - const auto equal = (left == right); - const auto notEqual = (left != right); - - // THEN - QFETCH(bool, expected); - QCOMPARE(equal, expected); - QCOMPARE(notEqual, !expected); -} - -void tst_QShaderGraph::shouldManipulateStatementMembers() -{ - // GIVEN - auto statement = QShaderGraph::Statement(); - - // THEN (default state) - QVERIFY(statement.inputs.isEmpty()); - QVERIFY(statement.outputs.isEmpty()); - QVERIFY(statement.node.uuid().isNull()); - QVERIFY(statement.uuid().isNull()); - - // WHEN - const auto node = createNode({}); - statement.node = node; - - // THEN - QCOMPARE(statement.uuid(), node.uuid()); - - // WHEN - statement.node = QShaderNode(); - - // THEN - QVERIFY(statement.uuid().isNull()); -} - -void tst_QShaderGraph::shouldTestStatementsEquality_data() -{ - QTest::addColumn<QShaderGraph::Statement>("left"); - QTest::addColumn<QShaderGraph::Statement>("right"); - QTest::addColumn<bool>("expected"); - - const auto node1 = createNode({}); - const auto node2 = createNode({}); - - QTest::newRow("EqualNodes") << createStatement(node1, {1, 2}, {3, 4}) - << createStatement(node1, {1, 2}, {3, 4}) - << true; - QTest::newRow("EqualInvalids") << createStatement(QShaderNode(), {1, 2}, {3, 4}) - << createStatement(QShaderNode(), {1, 2}, {3, 4}) - << true; - QTest::newRow("Nodes") << createStatement(node1, {1, 2}, {3, 4}) - << createStatement(node2, {1, 2}, {3, 4}) - << false; - QTest::newRow("Inputs") << createStatement(node1, {1, 2}, {3, 4}) - << createStatement(node1, {1, 2, 0}, {3, 4}) - << false; - QTest::newRow("Outputs") << createStatement(node1, {1, 2}, {3, 4}) - << createStatement(node1, {1, 2}, {3, 0, 4}) - << false; -} - -void tst_QShaderGraph::shouldTestStatementsEquality() -{ - // GIVEN - QFETCH(QShaderGraph::Statement, left); - QFETCH(QShaderGraph::Statement, right); - - // WHEN - const auto equal = (left == right); - const auto notEqual = (left != right); - - // THEN - QFETCH(bool, expected); - QCOMPARE(equal, expected); - QCOMPARE(notEqual, !expected); -} - -void tst_QShaderGraph::shouldFindIndexFromPortNameInStatements_data() -{ - QTest::addColumn<QShaderGraph::Statement>("statement"); - QTest::addColumn<QString>("portName"); - QTest::addColumn<int>("expectedInputIndex"); - QTest::addColumn<int>("expectedOutputIndex"); - - const auto inputNodeStatement = createStatement(createNode({ - createPort(QShaderNodePort::Output, "input") - })); - const auto outputNodeStatement = createStatement(createNode({ - createPort(QShaderNodePort::Input, "output") - })); - const auto functionNodeStatement = createStatement(createNode({ - createPort(QShaderNodePort::Input, "input1"), - createPort(QShaderNodePort::Output, "output1"), - createPort(QShaderNodePort::Input, "input2"), - createPort(QShaderNodePort::Output, "output2"), - createPort(QShaderNodePort::Output, "output3"), - createPort(QShaderNodePort::Input, "input3") - })); - - QTest::newRow("Invalid") << QShaderGraph::Statement() << "foo" << -1 << -1; - QTest::newRow("InputNodeWrongName") << inputNodeStatement << "foo" << -1 << -1; - QTest::newRow("InputNodeExistingName") << inputNodeStatement << "input" << -1 << 0; - QTest::newRow("OutputNodeWrongName") << outputNodeStatement << "foo" << -1 << -1; - QTest::newRow("OutputNodeExistingName") << outputNodeStatement << "output" << 0 << -1; - QTest::newRow("FunctionNodeWrongName") << functionNodeStatement << "foo" << -1 << -1; - QTest::newRow("FunctionNodeInput1") << functionNodeStatement << "input1" << 0 << -1; - QTest::newRow("FunctionNodeOutput1") << functionNodeStatement << "output1" << -1 << 0; - QTest::newRow("FunctionNodeInput2") << functionNodeStatement << "input2" << 1 << -1; - QTest::newRow("FunctionNodeOutput2") << functionNodeStatement << "output2" << -1 << 1; - QTest::newRow("FunctionNodeInput3") << functionNodeStatement << "input3" << 2 << -1; - QTest::newRow("FunctionNodeOutput3") << functionNodeStatement << "output3" << -1 << 2; -} - -void tst_QShaderGraph::shouldFindIndexFromPortNameInStatements() -{ - // GIVEN - QFETCH(QShaderGraph::Statement, statement); - QFETCH(QString, portName); - QFETCH(int, expectedInputIndex); - QFETCH(int, expectedOutputIndex); - - // WHEN - const auto inputIndex = statement.portIndex(QShaderNodePort::Input, portName); - const auto outputIndex = statement.portIndex(QShaderNodePort::Output, portName); - - // THEN - QCOMPARE(inputIndex, expectedInputIndex); - QCOMPARE(outputIndex, expectedOutputIndex); -} - -void tst_QShaderGraph::shouldManageNodeList() -{ - // GIVEN - const auto node1 = createNode({createPort(QShaderNodePort::Output, "node1")}); - const auto node2 = createNode({createPort(QShaderNodePort::Output, "node2")}); - - auto graph = QShaderGraph(); - - // THEN (default state) - QVERIFY(graph.nodes().isEmpty()); - - // WHEN - graph.addNode(node1); - - // THEN - QCOMPARE(graph.nodes().size(), 1); - QCOMPARE(graph.nodes().at(0).uuid(), node1.uuid()); - QCOMPARE(graph.nodes().at(0).ports().at(0).name, node1.ports().at(0).name); - - // WHEN - graph.addNode(node2); - - // THEN - QCOMPARE(graph.nodes().size(), 2); - QCOMPARE(graph.nodes().at(0).uuid(), node1.uuid()); - QCOMPARE(graph.nodes().at(0).ports().at(0).name, node1.ports().at(0).name); - QCOMPARE(graph.nodes().at(1).uuid(), node2.uuid()); - QCOMPARE(graph.nodes().at(1).ports().at(0).name, node2.ports().at(0).name); - - - // WHEN - graph.removeNode(node2); - - // THEN - QCOMPARE(graph.nodes().size(), 1); - QCOMPARE(graph.nodes().at(0).uuid(), node1.uuid()); - QCOMPARE(graph.nodes().at(0).ports().at(0).name, node1.ports().at(0).name); - - // WHEN - graph.addNode(node2); - - // THEN - QCOMPARE(graph.nodes().size(), 2); - QCOMPARE(graph.nodes().at(0).uuid(), node1.uuid()); - QCOMPARE(graph.nodes().at(0).ports().at(0).name, node1.ports().at(0).name); - QCOMPARE(graph.nodes().at(1).uuid(), node2.uuid()); - QCOMPARE(graph.nodes().at(1).ports().at(0).name, node2.ports().at(0).name); - - // WHEN - const auto node1bis = [node1] { - auto res = node1; - auto port = res.ports().at(0); - port.name = QStringLiteral("node1bis"); - res.addPort(port); - return res; - }(); - graph.addNode(node1bis); - - // THEN - QCOMPARE(graph.nodes().size(), 2); - QCOMPARE(graph.nodes().at(0).uuid(), node2.uuid()); - QCOMPARE(graph.nodes().at(0).ports().at(0).name, node2.ports().at(0).name); - QCOMPARE(graph.nodes().at(1).uuid(), node1bis.uuid()); - QCOMPARE(graph.nodes().at(1).ports().at(0).name, node1bis.ports().at(0).name); -} - -void tst_QShaderGraph::shouldManageEdgeList() -{ - // GIVEN - const auto edge1 = createEdge(QUuid::createUuid(), "foo", QUuid::createUuid(), "bar"); - const auto edge2 = createEdge(QUuid::createUuid(), "baz", QUuid::createUuid(), "boo"); - - auto graph = QShaderGraph(); - - // THEN (default state) - QVERIFY(graph.edges().isEmpty()); - - // WHEN - graph.addEdge(edge1); - - // THEN - QCOMPARE(graph.edges().size(), 1); - QCOMPARE(graph.edges().at(0), edge1); - - // WHEN - graph.addEdge(edge2); - - // THEN - QCOMPARE(graph.edges().size(), 2); - QCOMPARE(graph.edges().at(0), edge1); - QCOMPARE(graph.edges().at(1), edge2); - - - // WHEN - graph.removeEdge(edge2); - - // THEN - QCOMPARE(graph.edges().size(), 1); - QCOMPARE(graph.edges().at(0), edge1); - - // WHEN - graph.addEdge(edge2); - - // THEN - QCOMPARE(graph.edges().size(), 2); - QCOMPARE(graph.edges().at(0), edge1); - QCOMPARE(graph.edges().at(1), edge2); - - // WHEN - graph.addEdge(edge1); - - // THEN - QCOMPARE(graph.edges().size(), 2); - QCOMPARE(graph.edges().at(0), edge1); - QCOMPARE(graph.edges().at(1), edge2); -} - -void tst_QShaderGraph::shouldSerializeGraphForCodeGeneration() -{ - // GIVEN - const auto input1 = createNode({ - createPort(QShaderNodePort::Output, "input1Value") - }); - const auto input2 = createNode({ - createPort(QShaderNodePort::Output, "input2Value") - }); - const auto output1 = createNode({ - createPort(QShaderNodePort::Input, "output1Value") - }); - const auto output2 = createNode({ - createPort(QShaderNodePort::Input, "output2Value") - }); - const auto function1 = createNode({ - createPort(QShaderNodePort::Input, "function1Input"), - createPort(QShaderNodePort::Output, "function1Output") - }); - const auto function2 = createNode({ - createPort(QShaderNodePort::Input, "function2Input1"), - createPort(QShaderNodePort::Input, "function2Input2"), - createPort(QShaderNodePort::Output, "function2Output") - }); - const auto function3 = createNode({ - createPort(QShaderNodePort::Input, "function3Input1"), - createPort(QShaderNodePort::Input, "function3Input2"), - createPort(QShaderNodePort::Output, "function3Output1"), - createPort(QShaderNodePort::Output, "function3Output2") - }); - - const auto graph = [=] { - auto res = QShaderGraph(); - res.addNode(input1); - res.addNode(input2); - res.addNode(output1); - res.addNode(output2); - res.addNode(function1); - res.addNode(function2); - res.addNode(function3); - res.addEdge(createEdge(input1.uuid(), "input1Value", function1.uuid(), "function1Input")); - res.addEdge(createEdge(input1.uuid(), "input1Value", function2.uuid(), "function2Input1")); - res.addEdge(createEdge(input2.uuid(), "input2Value", function2.uuid(), "function2Input2")); - res.addEdge(createEdge(function1.uuid(), "function1Output", function3.uuid(), "function3Input1")); - res.addEdge(createEdge(function2.uuid(), "function2Output", function3.uuid(), "function3Input2")); - res.addEdge(createEdge(function3.uuid(), "function3Output1", output1.uuid(), "output1Value")); - res.addEdge(createEdge(function3.uuid(), "function3Output2", output2.uuid(), "output2Value")); - return res; - }(); - - // WHEN - const auto statements = graph.createStatements(); - - // THEN - const auto expected = QList<QShaderGraph::Statement>() - << createStatement(input2, {}, { 1 }) << createStatement(input1, {}, { 0 }) - << createStatement(function2, { 0, 1 }, { 3 }) - << createStatement(function1, { 0 }, { 2 }) - << createStatement(function3, { 2, 3 }, { 4, 5 }) << createStatement(output2, { 5 }, {}) - << createStatement(output1, { 4 }, {}); - dumpStatementsIfNeeded(statements, expected); - QCOMPARE(statements, expected); -} - -void tst_QShaderGraph::shouldHandleUnboundPortsDuringGraphSerialization() -{ - // GIVEN - const auto input = createNode({ - createPort(QShaderNodePort::Output, "input") - }); - const auto unboundInput = createNode({ - createPort(QShaderNodePort::Output, "unbound") - }); - const auto output = createNode({ - createPort(QShaderNodePort::Input, "output") - }); - const auto unboundOutput = createNode({ - createPort(QShaderNodePort::Input, "unbound") - }); - const auto function = createNode({ - createPort(QShaderNodePort::Input, "functionInput1"), - createPort(QShaderNodePort::Input, "functionInput2"), - createPort(QShaderNodePort::Input, "functionInput3"), - createPort(QShaderNodePort::Output, "functionOutput1"), - createPort(QShaderNodePort::Output, "functionOutput2"), - createPort(QShaderNodePort::Output, "functionOutput3") - }); - - const auto graph = [=] { - auto res = QShaderGraph(); - res.addNode(input); - res.addNode(unboundInput); - res.addNode(output); - res.addNode(unboundOutput); - res.addNode(function); - res.addEdge(createEdge(input.uuid(), "input", function.uuid(), "functionInput2")); - res.addEdge(createEdge(function.uuid(), "functionOutput2", output.uuid(), "output")); - return res; - }(); - - // WHEN - const auto statements = graph.createStatements(); - - // THEN - // Note that no statement has any unbound input - const auto expected = QList<QShaderGraph::Statement>() << createStatement(input, {}, { 0 }); - dumpStatementsIfNeeded(statements, expected); - QCOMPARE(statements, expected); -} - -void tst_QShaderGraph::shouldSurviveCyclesDuringGraphSerialization() -{ - // GIVEN - const auto input = createNode({ - createPort(QShaderNodePort::Output, "input") - }); - const auto output = createNode({ - createPort(QShaderNodePort::Input, "output") - }); - const auto function1 = createNode({ - createPort(QShaderNodePort::Input, "function1Input1"), - createPort(QShaderNodePort::Input, "function1Input2"), - createPort(QShaderNodePort::Output, "function1Output") - }); - const auto function2 = createNode({ - createPort(QShaderNodePort::Input, "function2Input"), - createPort(QShaderNodePort::Output, "function2Output") - }); - const auto function3 = createNode({ - createPort(QShaderNodePort::Input, "function3Input"), - createPort(QShaderNodePort::Output, "function3Output") - }); - - const auto graph = [=] { - auto res = QShaderGraph(); - res.addNode(input); - res.addNode(output); - res.addNode(function1); - res.addNode(function2); - res.addNode(function3); - res.addEdge(createEdge(input.uuid(), "input", function1.uuid(), "function1Input1")); - res.addEdge(createEdge(function1.uuid(), "function1Output", function2.uuid(), "function2Input")); - res.addEdge(createEdge(function2.uuid(), "function2Output", function3.uuid(), "function3Input")); - res.addEdge(createEdge(function3.uuid(), "function3Output", function1.uuid(), "function1Input2")); - res.addEdge(createEdge(function2.uuid(), "function2Output", output.uuid(), "output")); - return res; - }(); - - // WHEN - const auto statements = graph.createStatements(); - - // THEN - // The cycle is ignored - const auto expected = QList<QShaderGraph::Statement>(); - dumpStatementsIfNeeded(statements, expected); - QCOMPARE(statements, expected); -} - -void tst_QShaderGraph::shouldDealWithEdgesJumpingOverLayers() -{ - // GIVEN - const auto worldPosition = createNode({ - createPort(QShaderNodePort::Output, "worldPosition") - }); - const auto texture = createNode({ - createPort(QShaderNodePort::Output, "texture") - }); - const auto texCoord = createNode({ - createPort(QShaderNodePort::Output, "texCoord") - }); - const auto lightIntensity = createNode({ - createPort(QShaderNodePort::Output, "lightIntensity") - }); - const auto exposure = createNode({ - createPort(QShaderNodePort::Output, "exposure") - }); - const auto fragColor = createNode({ - createPort(QShaderNodePort::Input, "fragColor") - }); - const auto sampleTexture = createNode({ - createPort(QShaderNodePort::Input, "sampler"), - createPort(QShaderNodePort::Input, "coord"), - createPort(QShaderNodePort::Output, "color") - }); - const auto lightFunction = createNode({ - createPort(QShaderNodePort::Input, "baseColor"), - createPort(QShaderNodePort::Input, "position"), - createPort(QShaderNodePort::Input, "lightIntensity"), - createPort(QShaderNodePort::Output, "outputColor") - }); - const auto exposureFunction = createNode({ - createPort(QShaderNodePort::Input, "inputColor"), - createPort(QShaderNodePort::Input, "exposure"), - createPort(QShaderNodePort::Output, "outputColor") - }); - - const auto graph = [=] { - auto res = QShaderGraph(); - - res.addNode(worldPosition); - res.addNode(texture); - res.addNode(texCoord); - res.addNode(lightIntensity); - res.addNode(exposure); - res.addNode(fragColor); - res.addNode(sampleTexture); - res.addNode(lightFunction); - res.addNode(exposureFunction); - - res.addEdge(createEdge(texture.uuid(), "texture", sampleTexture.uuid(), "sampler")); - res.addEdge(createEdge(texCoord.uuid(), "texCoord", sampleTexture.uuid(), "coord")); - - res.addEdge(createEdge(worldPosition.uuid(), "worldPosition", lightFunction.uuid(), "position")); - res.addEdge(createEdge(sampleTexture.uuid(), "color", lightFunction.uuid(), "baseColor")); - res.addEdge(createEdge(lightIntensity.uuid(), "lightIntensity", lightFunction.uuid(), "lightIntensity")); - - res.addEdge(createEdge(lightFunction.uuid(), "outputColor", exposureFunction.uuid(), "inputColor")); - res.addEdge(createEdge(exposure.uuid(), "exposure", exposureFunction.uuid(), "exposure")); - - res.addEdge(createEdge(exposureFunction.uuid(), "outputColor", fragColor.uuid(), "fragColor")); - - return res; - }(); - - // WHEN - const auto statements = graph.createStatements(); - - // THEN - const auto expected = QList<QShaderGraph::Statement>() - << createStatement(texCoord, {}, { 2 }) << createStatement(texture, {}, { 1 }) - << createStatement(lightIntensity, {}, { 3 }) - << createStatement(sampleTexture, { 1, 2 }, { 5 }) - << createStatement(worldPosition, {}, { 0 }) << createStatement(exposure, {}, { 4 }) - << createStatement(lightFunction, { 5, 0, 3 }, { 6 }) - << createStatement(exposureFunction, { 6, 4 }, { 7 }) - << createStatement(fragColor, { 7 }, {}); - dumpStatementsIfNeeded(statements, expected); - QCOMPARE(statements, expected); -} - -void tst_QShaderGraph::shouldGenerateDifferentStatementsDependingOnActiveLayers() -{ - // GIVEN - const auto texCoord = createNode({ - createPort(QShaderNodePort::Output, "texCoord") - }, { - "diffuseTexture", - "normalTexture" - }); - const auto diffuseUniform = createNode({ - createPort(QShaderNodePort::Output, "color") - }, {"diffuseUniform"}); - const auto diffuseTexture = createNode({ - createPort(QShaderNodePort::Input, "coord"), - createPort(QShaderNodePort::Output, "color") - }, {"diffuseTexture"}); - const auto normalUniform = createNode({ - createPort(QShaderNodePort::Output, "normal") - }, {"normalUniform"}); - const auto normalTexture = createNode({ - createPort(QShaderNodePort::Input, "coord"), - createPort(QShaderNodePort::Output, "normal") - }, {"normalTexture"}); - const auto lightFunction = createNode({ - createPort(QShaderNodePort::Input, "color"), - createPort(QShaderNodePort::Input, "normal"), - createPort(QShaderNodePort::Output, "output") - }); - const auto fragColor = createNode({ - createPort(QShaderNodePort::Input, "fragColor") - }); - - const auto graph = [=] { - auto res = QShaderGraph(); - - res.addNode(texCoord); - res.addNode(diffuseUniform); - res.addNode(diffuseTexture); - res.addNode(normalUniform); - res.addNode(normalTexture); - res.addNode(lightFunction); - res.addNode(fragColor); - - res.addEdge(createEdge(diffuseUniform.uuid(), "color", lightFunction.uuid(), "color", {"diffuseUniform"})); - res.addEdge(createEdge(texCoord.uuid(), "texCoord", diffuseTexture.uuid(), "coord", {"diffuseTexture"})); - res.addEdge(createEdge(diffuseTexture.uuid(), "color", lightFunction.uuid(), "color", {"diffuseTexture"})); - - res.addEdge(createEdge(normalUniform.uuid(), "normal", lightFunction.uuid(), "normal", {"normalUniform"})); - res.addEdge(createEdge(texCoord.uuid(), "texCoord", normalTexture.uuid(), "coord", {"normalTexture"})); - res.addEdge(createEdge(normalTexture.uuid(), "normal", lightFunction.uuid(), "normal", {"normalTexture"})); - - res.addEdge(createEdge(lightFunction.uuid(), "output", fragColor.uuid(), "fragColor")); - - return res; - }(); - - { - // WHEN - const auto statements = graph.createStatements({"diffuseUniform", "normalUniform"}); - - // THEN - const auto expected = QList<QShaderGraph::Statement>() - << createStatement(normalUniform, {}, { 1 }) - << createStatement(diffuseUniform, {}, { 0 }) - << createStatement(lightFunction, { 0, 1 }, { 2 }) - << createStatement(fragColor, { 2 }, {}); - dumpStatementsIfNeeded(statements, expected); - QCOMPARE(statements, expected); - } - - { - // WHEN - const auto statements = graph.createStatements({"diffuseUniform", "normalTexture"}); - - // THEN - const auto expected = QList<QShaderGraph::Statement>() - << createStatement(texCoord, {}, { 0 }) - << createStatement(normalTexture, { 0 }, { 2 }) - << createStatement(diffuseUniform, {}, { 1 }) - << createStatement(lightFunction, { 1, 2 }, { 3 }) - << createStatement(fragColor, { 3 }, {}); - dumpStatementsIfNeeded(statements, expected); - QCOMPARE(statements, expected); - } - - { - // WHEN - const auto statements = graph.createStatements({"diffuseTexture", "normalUniform"}); - - // THEN - const auto expected = QList<QShaderGraph::Statement>() - << createStatement(texCoord, {}, { 0 }) << createStatement(normalUniform, {}, { 2 }) - << createStatement(diffuseTexture, { 0 }, { 1 }) - << createStatement(lightFunction, { 1, 2 }, { 3 }) - << createStatement(fragColor, { 3 }, {}); - dumpStatementsIfNeeded(statements, expected); - QCOMPARE(statements, expected); - } - - { - // WHEN - const auto statements = graph.createStatements({"diffuseTexture", "normalTexture"}); - - // THEN - const auto expected = QList<QShaderGraph::Statement>() - << createStatement(texCoord, {}, { 0 }) - << createStatement(normalTexture, { 0 }, { 2 }) - << createStatement(diffuseTexture, { 0 }, { 1 }) - << createStatement(lightFunction, { 1, 2 }, { 3 }) - << createStatement(fragColor, { 3 }, {}); - dumpStatementsIfNeeded(statements, expected); - QCOMPARE(statements, expected); - } -} - -void tst_QShaderGraph::shouldDealWithBranchesWithoutOutput() -{ - // GIVEN - const auto input = createNode({ - createPort(QShaderNodePort::Output, "input") - }); - const auto output = createNode({ - createPort(QShaderNodePort::Input, "output") - }); - const auto danglingFunction = createNode({ - createPort(QShaderNodePort::Input, "functionInput"), - createPort(QShaderNodePort::Output, "unbound") - }); - const auto function = createNode({ - createPort(QShaderNodePort::Input, "functionInput"), - createPort(QShaderNodePort::Output, "functionOutput") - }); - - const auto graph = [=] { - auto res = QShaderGraph(); - res.addNode(input); - res.addNode(function); - res.addNode(danglingFunction); - res.addNode(output); - res.addEdge(createEdge(input.uuid(), "input", function.uuid(), "functionInput")); - res.addEdge(createEdge(input.uuid(), "input", danglingFunction.uuid(), "functionInput")); - res.addEdge(createEdge(function.uuid(), "functionOutput", output.uuid(), "output")); - return res; - }(); - - // WHEN - const auto statements = graph.createStatements(); - - // THEN - // Note that no edge leads to the unbound input - const auto expected = QList<QShaderGraph::Statement>() - << createStatement(input, {}, { 0 }) << createStatement(function, { 0 }, { 1 }) - << createStatement(output, { 1 }, {}) - << createStatement(danglingFunction, { 0 }, { 2 }); - dumpStatementsIfNeeded(statements, expected); - QCOMPARE(statements, expected); -} - -QTEST_MAIN(tst_QShaderGraph) - -#include "tst_qshadergraph.moc" diff --git a/tests/auto/gui/util/qshadergraphloader/CMakeLists.txt b/tests/auto/gui/util/qshadergraphloader/CMakeLists.txt deleted file mode 100644 index 70f99d9266..0000000000 --- a/tests/auto/gui/util/qshadergraphloader/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -# Generated from qshadergraphloader.pro. - -##################################################################### -## tst_qshadergraphloader Test: -##################################################################### - -qt_internal_add_test(tst_qshadergraphloader - SOURCES - tst_qshadergraphloader.cpp - PUBLIC_LIBRARIES - Qt::Gui - Qt::GuiPrivate -) diff --git a/tests/auto/gui/util/qshadergraphloader/tst_qshadergraphloader.cpp b/tests/auto/gui/util/qshadergraphloader/tst_qshadergraphloader.cpp deleted file mode 100644 index 86db9edbea..0000000000 --- a/tests/auto/gui/util/qshadergraphloader/tst_qshadergraphloader.cpp +++ /dev/null @@ -1,627 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** 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 General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** 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-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include <QTest> - -#include <QtCore/qbuffer.h> - -#include <QtGui/private/qshadergraphloader_p.h> -#include <QtGui/private/qshaderlanguage_p.h> - -using QBufferPointer = QSharedPointer<QBuffer>; -Q_DECLARE_METATYPE(QBufferPointer); - -using PrototypeHash = QHash<QString, QShaderNode>; -Q_DECLARE_METATYPE(PrototypeHash); - -namespace -{ - QBufferPointer createBuffer(const QByteArray &data, QIODevice::OpenMode openMode = QIODevice::ReadOnly) - { - auto buffer = QBufferPointer::create(); - buffer->setData(data); - if (openMode != QIODevice::NotOpen) - buffer->open(openMode); - return buffer; - } - - QShaderFormat createFormat(QShaderFormat::Api api, int majorVersion, int minorVersion) - { - auto format = QShaderFormat(); - format.setApi(api); - format.setVersion(QVersionNumber(majorVersion, minorVersion)); - return format; - } - - QShaderNodePort createPort(QShaderNodePort::Direction portDirection, const QString &portName) - { - auto port = QShaderNodePort(); - port.direction = portDirection; - port.name = portName; - return port; - } - - QShaderNode createNode(const QList<QShaderNodePort> &ports, - const QStringList &layers = QStringList()) - { - auto node = QShaderNode(); - node.setUuid(QUuid::createUuid()); - node.setLayers(layers); - for (const auto &port : ports) - node.addPort(port); - return node; - } - - QShaderGraph::Edge createEdge(const QUuid &sourceUuid, const QString &sourceName, - const QUuid &targetUuid, const QString &targetName, - const QStringList &layers = QStringList()) - { - auto edge = QShaderGraph::Edge(); - edge.sourceNodeUuid = sourceUuid; - edge.sourcePortName = sourceName; - edge.targetNodeUuid = targetUuid; - edge.targetPortName = targetName; - edge.layers = layers; - return edge; - } - - QShaderGraph createGraph() - { - const auto openGLES2 = createFormat(QShaderFormat::OpenGLES, 2, 0); - const auto openGL3 = createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0); - - auto graph = QShaderGraph(); - - auto worldPosition = createNode({ - createPort(QShaderNodePort::Output, "value") - }); - worldPosition.setUuid(QUuid("{00000000-0000-0000-0000-000000000001}")); - worldPosition.setParameter("name", "worldPosition"); - worldPosition.setParameter("qualifier", QVariant::fromValue<QShaderLanguage::StorageQualifier>(QShaderLanguage::Input)); - worldPosition.setParameter("type", QVariant::fromValue<QShaderLanguage::VariableType>(QShaderLanguage::Vec3)); - worldPosition.addRule(openGLES2, QShaderNode::Rule("highp $type $value = $name;", - QByteArrayList() << "$qualifier highp $type $name;")); - worldPosition.addRule(openGL3, QShaderNode::Rule("$type $value = $name;", - QByteArrayList() << "$qualifier $type $name;")); - - auto texture = createNode({ - createPort(QShaderNodePort::Output, "texture") - }); - texture.setUuid(QUuid("{00000000-0000-0000-0000-000000000002}")); - texture.addRule(openGLES2, QShaderNode::Rule("sampler2D $texture = texture;", - QByteArrayList() << "uniform sampler2D texture;")); - texture.addRule(openGL3, QShaderNode::Rule("sampler2D $texture = texture;", - QByteArrayList() << "uniform sampler2D texture;")); - - auto texCoord = createNode({ - createPort(QShaderNodePort::Output, "texCoord") - }); - texCoord.setUuid(QUuid("{00000000-0000-0000-0000-000000000003}")); - texCoord.addRule(openGLES2, QShaderNode::Rule("highp vec2 $texCoord = texCoord;", - QByteArrayList() << "varying highp vec2 texCoord;")); - texCoord.addRule(openGL3, QShaderNode::Rule("vec2 $texCoord = texCoord;", - QByteArrayList() << "in vec2 texCoord;")); - - auto lightIntensity = createNode({ - createPort(QShaderNodePort::Output, "value") - }); - lightIntensity.setUuid(QUuid("{00000000-0000-0000-0000-000000000004}")); - lightIntensity.setParameter("name", "defaultName"); - lightIntensity.setParameter("qualifier", QVariant::fromValue<QShaderLanguage::StorageQualifier>(QShaderLanguage::Uniform)); - lightIntensity.setParameter("type", QVariant::fromValue<QShaderLanguage::VariableType>(QShaderLanguage::Float)); - lightIntensity.addRule(openGLES2, QShaderNode::Rule("highp $type $value = $name;", - QByteArrayList() << "$qualifier highp $type $name;")); - lightIntensity.addRule(openGL3, QShaderNode::Rule("$type $value = $name;", - QByteArrayList() << "$qualifier $type $name;")); - - auto exposure = createNode({ - createPort(QShaderNodePort::Output, "exposure") - }); - exposure.setUuid(QUuid("{00000000-0000-0000-0000-000000000005}")); - exposure.addRule(openGLES2, QShaderNode::Rule("highp float $exposure = exposure;", - QByteArrayList() << "uniform highp float exposure;")); - exposure.addRule(openGL3, QShaderNode::Rule("float $exposure = exposure;", - QByteArrayList() << "uniform float exposure;")); - - auto fragColor = createNode({ - createPort(QShaderNodePort::Input, "fragColor") - }); - fragColor.setUuid(QUuid("{00000000-0000-0000-0000-000000000006}")); - fragColor.addRule(openGLES2, QShaderNode::Rule("gl_fragColor = $fragColor;")); - fragColor.addRule(openGL3, QShaderNode::Rule("fragColor = $fragColor;", - QByteArrayList() << "out vec4 fragColor;")); - - auto sampleTexture = createNode({ - createPort(QShaderNodePort::Input, "sampler"), - createPort(QShaderNodePort::Input, "coord"), - createPort(QShaderNodePort::Output, "color") - }); - sampleTexture.setUuid(QUuid("{00000000-0000-0000-0000-000000000007}")); - sampleTexture.addRule(openGLES2, QShaderNode::Rule("highp vec4 $color = texture2D($sampler, $coord);")); - sampleTexture.addRule(openGL3, QShaderNode::Rule("vec4 $color = texture2D($sampler, $coord);")); - - auto lightFunction = createNode({ - createPort(QShaderNodePort::Input, "baseColor"), - createPort(QShaderNodePort::Input, "position"), - createPort(QShaderNodePort::Input, "lightIntensity"), - createPort(QShaderNodePort::Output, "outputColor") - }); - lightFunction.setUuid(QUuid("{00000000-0000-0000-0000-000000000008}")); - lightFunction.addRule(openGLES2, QShaderNode::Rule("highp vec4 $outputColor = lightModel($baseColor, $position, $lightIntensity);", - QByteArrayList() << "#pragma include es2/lightmodel.frag.inc")); - lightFunction.addRule(openGL3, QShaderNode::Rule("vec4 $outputColor = lightModel($baseColor, $position, $lightIntensity);", - QByteArrayList() << "#pragma include gl3/lightmodel.frag.inc")); - - auto exposureFunction = createNode({ - createPort(QShaderNodePort::Input, "inputColor"), - createPort(QShaderNodePort::Input, "exposure"), - createPort(QShaderNodePort::Output, "outputColor") - }); - exposureFunction.setUuid(QUuid("{00000000-0000-0000-0000-000000000009}")); - exposureFunction.addRule(openGLES2, QShaderNode::Rule("highp vec4 $outputColor = $inputColor * pow(2.0, $exposure);")); - exposureFunction.addRule(openGL3, QShaderNode::Rule("vec4 $outputColor = $inputColor * pow(2.0, $exposure);")); - - graph.addNode(worldPosition); - graph.addNode(texture); - graph.addNode(texCoord); - graph.addNode(lightIntensity); - graph.addNode(exposure); - graph.addNode(fragColor); - graph.addNode(sampleTexture); - graph.addNode(lightFunction); - graph.addNode(exposureFunction); - - graph.addEdge(createEdge(texture.uuid(), "texture", sampleTexture.uuid(), "sampler")); - graph.addEdge(createEdge(texCoord.uuid(), "texCoord", sampleTexture.uuid(), "coord")); - - graph.addEdge(createEdge(worldPosition.uuid(), "value", lightFunction.uuid(), "position")); - graph.addEdge(createEdge(sampleTexture.uuid(), "color", lightFunction.uuid(), "baseColor")); - graph.addEdge(createEdge(lightIntensity.uuid(), "value", lightFunction.uuid(), "lightIntensity")); - - graph.addEdge(createEdge(lightFunction.uuid(), "outputColor", exposureFunction.uuid(), "inputColor")); - graph.addEdge(createEdge(exposure.uuid(), "exposure", exposureFunction.uuid(), "exposure")); - - graph.addEdge(createEdge(exposureFunction.uuid(), "outputColor", fragColor.uuid(), "fragColor")); - - return graph; - } - - void debugStatement(const QString &prefix, const QShaderGraph::Statement &statement) - { - qDebug() << prefix << statement.inputs << statement.uuid().toString() << statement.outputs; - } - - void dumpStatementsIfNeeded(const QList<QShaderGraph::Statement> &statements, - const QList<QShaderGraph::Statement> &expected) - { - if (statements != expected) { - for (int i = 0; i < qMax(statements.size(), expected.size()); i++) { - qDebug() << "----" << i << "----"; - if (i < statements.size()) - debugStatement("A:", statements.at(i)); - if (i < expected.size()) - debugStatement("E:", expected.at(i)); - qDebug() << "-----------"; - } - } - } -} - -class tst_QShaderGraphLoader : public QObject -{ - Q_OBJECT -private slots: - void shouldManipulateLoaderMembers(); - void shouldLoadFromJsonStream_data(); - void shouldLoadFromJsonStream(); -}; - -void tst_QShaderGraphLoader::shouldManipulateLoaderMembers() -{ - // GIVEN - auto loader = QShaderGraphLoader(); - - // THEN (default state) - QCOMPARE(loader.status(), QShaderGraphLoader::Null); - QVERIFY(!loader.device()); - QVERIFY(loader.graph().nodes().isEmpty()); - QVERIFY(loader.graph().edges().isEmpty()); - QVERIFY(loader.prototypes().isEmpty()); - - // WHEN - auto device1 = createBuffer(QByteArray("..........."), QIODevice::NotOpen); - loader.setDevice(device1.data()); - - // THEN - QCOMPARE(loader.status(), QShaderGraphLoader::Error); - QCOMPARE(loader.device(), device1.data()); - QVERIFY(loader.graph().nodes().isEmpty()); - QVERIFY(loader.graph().edges().isEmpty()); - - // WHEN - auto device2 = createBuffer(QByteArray("..........."), QIODevice::ReadOnly); - loader.setDevice(device2.data()); - - // THEN - QCOMPARE(loader.status(), QShaderGraphLoader::Waiting); - QCOMPARE(loader.device(), device2.data()); - QVERIFY(loader.graph().nodes().isEmpty()); - QVERIFY(loader.graph().edges().isEmpty()); - - - // WHEN - const auto prototypes = [&]{ - auto res = QHash<QString, QShaderNode>(); - res.insert("foo", createNode({})); - return res; - }(); - loader.setPrototypes(prototypes); - - // THEN - QCOMPARE(loader.prototypes().size(), prototypes.size()); - QVERIFY(loader.prototypes().contains("foo")); - QCOMPARE(loader.prototypes().value("foo").uuid(), prototypes.value("foo").uuid()); -} - -void tst_QShaderGraphLoader::shouldLoadFromJsonStream_data() -{ - QTest::addColumn<QBufferPointer>("device"); - QTest::addColumn<PrototypeHash>("prototypes"); - QTest::addColumn<QShaderGraph>("graph"); - QTest::addColumn<QShaderGraphLoader::Status>("status"); - - QTest::newRow("empty") << createBuffer("", QIODevice::ReadOnly) << PrototypeHash() - << QShaderGraph() << QShaderGraphLoader::Error; - - const auto smallJson = "{" - " \"nodes\": [" - " {" - " \"uuid\": \"{00000000-0000-0000-0000-000000000001}\"," - " \"type\": \"MyInput\"," - " \"layers\": [\"foo\", \"bar\"]" - " }," - " {" - " \"uuid\": \"{00000000-0000-0000-0000-000000000002}\"," - " \"type\": \"MyOutput\"" - " }," - " {" - " \"uuid\": \"{00000000-0000-0000-0000-000000000003}\"," - " \"type\": \"MyFunction\"" - " }" - " ]," - " \"edges\": [" - " {" - " \"sourceUuid\": \"{00000000-0000-0000-0000-000000000001}\"," - " \"sourcePort\": \"input\"," - " \"targetUuid\": \"{00000000-0000-0000-0000-000000000003}\"," - " \"targetPort\": \"functionInput\"," - " \"layers\": [\"bar\", \"baz\"]" - " }," - " {" - " \"sourceUuid\": \"{00000000-0000-0000-0000-000000000003}\"," - " \"sourcePort\": \"functionOutput\"," - " \"targetUuid\": \"{00000000-0000-0000-0000-000000000002}\"," - " \"targetPort\": \"output\"" - " }" - " ]" - "}"; - - const auto smallProtos = [&]{ - auto protos = PrototypeHash(); - - auto input = createNode({ - createPort(QShaderNodePort::Output, "input") - }); - protos.insert("MyInput", input); - - auto output = createNode({ - createPort(QShaderNodePort::Input, "output") - }); - protos.insert("MyOutput", output); - - auto function = createNode({ - createPort(QShaderNodePort::Input, "functionInput"), - createPort(QShaderNodePort::Output, "functionOutput") - }); - protos.insert("MyFunction", function); - return protos; - }(); - - const auto smallGraph = [&]{ - auto graph = QShaderGraph(); - - auto input = createNode({ - createPort(QShaderNodePort::Output, "input") - }, {"foo", "bar"}); - input.setUuid(QUuid("{00000000-0000-0000-0000-000000000001}")); - auto output = createNode({ - createPort(QShaderNodePort::Input, "output") - }); - output.setUuid(QUuid("{00000000-0000-0000-0000-000000000002}")); - auto function = createNode({ - createPort(QShaderNodePort::Input, "functionInput"), - createPort(QShaderNodePort::Output, "functionOutput") - }); - function.setUuid(QUuid("{00000000-0000-0000-0000-000000000003}")); - - graph.addNode(input); - graph.addNode(output); - graph.addNode(function); - graph.addEdge(createEdge(input.uuid(), "input", function.uuid(), "functionInput", {"bar", "baz"})); - graph.addEdge(createEdge(function.uuid(), "functionOutput", output.uuid(), "output")); - - return graph; - }(); - - QTest::newRow("TwoNodesOneEdge") << createBuffer(smallJson) << smallProtos << smallGraph << QShaderGraphLoader::Ready; - QTest::newRow("NotOpen") << createBuffer(smallJson, QIODevice::NotOpen) << smallProtos << QShaderGraph() << QShaderGraphLoader::Error; - QTest::newRow("NoPrototype") << createBuffer(smallJson) << PrototypeHash() << QShaderGraph() << QShaderGraphLoader::Error; - - const auto complexJson = "{" - " \"nodes\": [" - " {" - " \"uuid\": \"{00000000-0000-0000-0000-000000000001}\"," - " \"type\": \"inputValue\"," - " \"parameters\": {" - " \"name\": \"worldPosition\"," - " \"qualifier\": {" - " \"type\": \"QShaderLanguage::StorageQualifier\"," - " \"value\": \"QShaderLanguage::Input\"" - " }," - " \"type\": {" - " \"type\": \"QShaderLanguage::VariableType\"," - " \"value\": \"QShaderLanguage::Vec3\"" - " }" - " }" - " }," - " {" - " \"uuid\": \"{00000000-0000-0000-0000-000000000002}\"," - " \"type\": \"texture\"" - " }," - " {" - " \"uuid\": \"{00000000-0000-0000-0000-000000000003}\"," - " \"type\": \"texCoord\"" - " }," - " {" - " \"uuid\": \"{00000000-0000-0000-0000-000000000004}\"," - " \"type\": \"inputValue\"" - " }," - " {" - " \"uuid\": \"{00000000-0000-0000-0000-000000000005}\"," - " \"type\": \"exposure\"" - " }," - " {" - " \"uuid\": \"{00000000-0000-0000-0000-000000000006}\"," - " \"type\": \"fragColor\"" - " }," - " {" - " \"uuid\": \"{00000000-0000-0000-0000-000000000007}\"," - " \"type\": \"sampleTexture\"" - " }," - " {" - " \"uuid\": \"{00000000-0000-0000-0000-000000000008}\"," - " \"type\": \"lightModel\"" - " }," - " {" - " \"uuid\": \"{00000000-0000-0000-0000-000000000009}\"," - " \"type\": \"exposureFunction\"" - " }" - " ]," - " \"edges\": [" - " {" - " \"sourceUuid\": \"{00000000-0000-0000-0000-000000000002}\"," - " \"sourcePort\": \"texture\"," - " \"targetUuid\": \"{00000000-0000-0000-0000-000000000007}\"," - " \"targetPort\": \"sampler\"" - " }," - " {" - " \"sourceUuid\": \"{00000000-0000-0000-0000-000000000003}\"," - " \"sourcePort\": \"texCoord\"," - " \"targetUuid\": \"{00000000-0000-0000-0000-000000000007}\"," - " \"targetPort\": \"coord\"" - " }," - " {" - " \"sourceUuid\": \"{00000000-0000-0000-0000-000000000001}\"," - " \"sourcePort\": \"value\"," - " \"targetUuid\": \"{00000000-0000-0000-0000-000000000008}\"," - " \"targetPort\": \"position\"" - " }," - " {" - " \"sourceUuid\": \"{00000000-0000-0000-0000-000000000007}\"," - " \"sourcePort\": \"color\"," - " \"targetUuid\": \"{00000000-0000-0000-0000-000000000008}\"," - " \"targetPort\": \"baseColor\"" - " }," - " {" - " \"sourceUuid\": \"{00000000-0000-0000-0000-000000000004}\"," - " \"sourcePort\": \"value\"," - " \"targetUuid\": \"{00000000-0000-0000-0000-000000000008}\"," - " \"targetPort\": \"lightIntensity\"" - " }," - " {" - " \"sourceUuid\": \"{00000000-0000-0000-0000-000000000008}\"," - " \"sourcePort\": \"outputColor\"," - " \"targetUuid\": \"{00000000-0000-0000-0000-000000000009}\"," - " \"targetPort\": \"inputColor\"" - " }," - " {" - " \"sourceUuid\": \"{00000000-0000-0000-0000-000000000005}\"," - " \"sourcePort\": \"exposure\"," - " \"targetUuid\": \"{00000000-0000-0000-0000-000000000009}\"," - " \"targetPort\": \"exposure\"" - " }," - " {" - " \"sourceUuid\": \"{00000000-0000-0000-0000-000000000009}\"," - " \"sourcePort\": \"outputColor\"," - " \"targetUuid\": \"{00000000-0000-0000-0000-000000000006}\"," - " \"targetPort\": \"fragColor\"" - " }" - " ]" - "}"; - - const auto complexProtos = [&]{ - const auto openGLES2 = createFormat(QShaderFormat::OpenGLES, 2, 0); - const auto openGL3 = createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0); - - auto protos = PrototypeHash(); - - auto inputValue = createNode({ - createPort(QShaderNodePort::Output, "value") - }); - inputValue.setParameter("name", "defaultName"); - inputValue.setParameter("qualifier", QVariant::fromValue<QShaderLanguage::StorageQualifier>(QShaderLanguage::Uniform)); - inputValue.setParameter("type", QVariant::fromValue<QShaderLanguage::VariableType>(QShaderLanguage::Float)); - inputValue.addRule(openGLES2, QShaderNode::Rule("highp $type $value = $name;", - QByteArrayList() << "$qualifier highp $type $name;")); - inputValue.addRule(openGL3, QShaderNode::Rule("$type $value = $name;", - QByteArrayList() << "$qualifier $type $name;")); - protos.insert("inputValue", inputValue); - - auto texture = createNode({ - createPort(QShaderNodePort::Output, "texture") - }); - texture.addRule(openGLES2, QShaderNode::Rule("sampler2D $texture = texture;", - QByteArrayList() << "uniform sampler2D texture;")); - texture.addRule(openGL3, QShaderNode::Rule("sampler2D $texture = texture;", - QByteArrayList() << "uniform sampler2D texture;")); - protos.insert("texture", texture); - - auto texCoord = createNode({ - createPort(QShaderNodePort::Output, "texCoord") - }); - texCoord.addRule(openGLES2, QShaderNode::Rule("highp vec2 $texCoord = texCoord;", - QByteArrayList() << "varying highp vec2 texCoord;")); - texCoord.addRule(openGL3, QShaderNode::Rule("vec2 $texCoord = texCoord;", - QByteArrayList() << "in vec2 texCoord;")); - protos.insert("texCoord", texCoord); - - auto exposure = createNode({ - createPort(QShaderNodePort::Output, "exposure") - }); - exposure.addRule(openGLES2, QShaderNode::Rule("highp float $exposure = exposure;", - QByteArrayList() << "uniform highp float exposure;")); - exposure.addRule(openGL3, QShaderNode::Rule("float $exposure = exposure;", - QByteArrayList() << "uniform float exposure;")); - protos.insert("exposure", exposure); - - auto fragColor = createNode({ - createPort(QShaderNodePort::Input, "fragColor") - }); - fragColor.addRule(openGLES2, QShaderNode::Rule("gl_fragColor = $fragColor;")); - fragColor.addRule(openGL3, QShaderNode::Rule("fragColor = $fragColor;", - QByteArrayList() << "out vec4 fragColor;")); - protos.insert("fragColor", fragColor); - - auto sampleTexture = createNode({ - createPort(QShaderNodePort::Input, "sampler"), - createPort(QShaderNodePort::Input, "coord"), - createPort(QShaderNodePort::Output, "color") - }); - sampleTexture.addRule(openGLES2, QShaderNode::Rule("highp vec4 $color = texture2D($sampler, $coord);")); - sampleTexture.addRule(openGL3, QShaderNode::Rule("vec4 $color = texture2D($sampler, $coord);")); - protos.insert("sampleTexture", sampleTexture); - - auto lightModel = createNode({ - createPort(QShaderNodePort::Input, "baseColor"), - createPort(QShaderNodePort::Input, "position"), - createPort(QShaderNodePort::Input, "lightIntensity"), - createPort(QShaderNodePort::Output, "outputColor") - }); - lightModel.addRule(openGLES2, QShaderNode::Rule("highp vec4 $outputColor = lightModel($baseColor, $position, $lightIntensity);", - QByteArrayList() << "#pragma include es2/lightmodel.frag.inc")); - lightModel.addRule(openGL3, QShaderNode::Rule("vec4 $outputColor = lightModel($baseColor, $position, $lightIntensity);", - QByteArrayList() << "#pragma include gl3/lightmodel.frag.inc")); - protos.insert("lightModel", lightModel); - - auto exposureFunction = createNode({ - createPort(QShaderNodePort::Input, "inputColor"), - createPort(QShaderNodePort::Input, "exposure"), - createPort(QShaderNodePort::Output, "outputColor") - }); - exposureFunction.addRule(openGLES2, QShaderNode::Rule("highp vec4 $outputColor = $inputColor * pow(2.0, $exposure);")); - exposureFunction.addRule(openGL3, QShaderNode::Rule("vec4 $outputColor = $inputColor * pow(2.0, $exposure);")); - protos.insert("exposureFunction", exposureFunction); - - return protos; - }(); - - const auto complexGraph = createGraph(); - - QTest::newRow("ComplexGraph") << createBuffer(complexJson) << complexProtos << complexGraph << QShaderGraphLoader::Ready; -} - -void tst_QShaderGraphLoader::shouldLoadFromJsonStream() -{ - // GIVEN - QFETCH(QBufferPointer, device); - QFETCH(PrototypeHash, prototypes); - - auto loader = QShaderGraphLoader(); - - // WHEN - loader.setPrototypes(prototypes); - loader.setDevice(device.data()); - loader.load(); - - // THEN - QFETCH(QShaderGraphLoader::Status, status); - QCOMPARE(loader.status(), status); - - QFETCH(QShaderGraph, graph); - const auto statements = loader.graph().createStatements({"foo", "bar", "baz"}); - const auto expected = graph.createStatements({"foo", "bar", "baz"}); - dumpStatementsIfNeeded(statements, expected); - QCOMPARE(statements, expected); - - const auto sortedParameters = [](const QShaderNode &node) { - auto res = node.parameterNames(); - res.sort(); - return res; - }; - - for (int i = 0; i < statements.size(); i++) { - const auto actualNode = statements.at(i).node; - const auto expectedNode = expected.at(i).node; - - QCOMPARE(actualNode.layers(), expectedNode.layers()); - QCOMPARE(actualNode.ports(), expectedNode.ports()); - QCOMPARE(sortedParameters(actualNode), sortedParameters(expectedNode)); - for (const auto &name : expectedNode.parameterNames()) { - QCOMPARE(actualNode.parameter(name), expectedNode.parameter(name)); - } - QCOMPARE(actualNode.availableFormats(), expectedNode.availableFormats()); - for (const auto &format : expectedNode.availableFormats()) { - QCOMPARE(actualNode.rule(format), expectedNode.rule(format)); - } - } -} - -QTEST_MAIN(tst_QShaderGraphLoader) - -#include "tst_qshadergraphloader.moc" diff --git a/tests/auto/gui/util/qshadernodes/CMakeLists.txt b/tests/auto/gui/util/qshadernodes/CMakeLists.txt deleted file mode 100644 index 471a203ffc..0000000000 --- a/tests/auto/gui/util/qshadernodes/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -# Generated from qshadernodes.pro. - -##################################################################### -## tst_qshadernodes Test: -##################################################################### - -qt_internal_add_test(tst_qshadernodes - SOURCES - tst_qshadernodes.cpp - PUBLIC_LIBRARIES - Qt::Gui - Qt::GuiPrivate -) diff --git a/tests/auto/gui/util/qshadernodes/tst_qshadernodes.cpp b/tests/auto/gui/util/qshadernodes/tst_qshadernodes.cpp deleted file mode 100644 index be6239a4fd..0000000000 --- a/tests/auto/gui/util/qshadernodes/tst_qshadernodes.cpp +++ /dev/null @@ -1,548 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** 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 General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** 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-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include <QTest> - -#include <QtGui/private/qshaderformat_p.h> -#include <QtGui/private/qshadernode_p.h> -#include <QtGui/private/qshadernodeport_p.h> - -namespace -{ - QShaderFormat createFormat(QShaderFormat::Api api, int majorVersion, int minorVersion, - const QStringList &extensions = QStringList(), - const QString &vendor = QString()) - { - auto format = QShaderFormat(); - format.setApi(api); - format.setVersion(QVersionNumber(majorVersion, minorVersion)); - format.setExtensions(extensions); - format.setVendor(vendor); - return format; - } - - QShaderNodePort createPort(QShaderNodePort::Direction direction, const QString &name) - { - auto port = QShaderNodePort(); - port.direction = direction; - port.name = name; - return port; - } -} - -class tst_QShaderNodes : public QObject -{ - Q_OBJECT -private slots: - void shouldManipulateFormatMembers(); - void shouldVerifyFormatsEquality_data(); - void shouldVerifyFormatsEquality(); - void shouldVerifyFormatsCompatibilities_data(); - void shouldVerifyFormatsCompatibilities(); - - void shouldHaveDefaultPortState(); - void shouldVerifyPortsEquality_data(); - void shouldVerifyPortsEquality(); - - void shouldManipulateNodeMembers(); - void shouldHandleNodeRulesSupportAndOrder(); -}; - -void tst_QShaderNodes::shouldManipulateFormatMembers() -{ - // GIVEN - auto format = QShaderFormat(); - - // THEN (default state) - QCOMPARE(format.api(), QShaderFormat::NoApi); - QCOMPARE(format.version().majorVersion(), 0); - QCOMPARE(format.version().minorVersion(), 0); - QCOMPARE(format.extensions(), QStringList()); - QCOMPARE(format.vendor(), QString()); - QVERIFY(!format.isValid()); - - // WHEN - format.setApi(QShaderFormat::OpenGLES); - - // THEN - QCOMPARE(format.api(), QShaderFormat::OpenGLES); - QCOMPARE(format.version().majorVersion(), 0); - QCOMPARE(format.version().minorVersion(), 0); - QCOMPARE(format.extensions(), QStringList()); - QCOMPARE(format.vendor(), QString()); - QVERIFY(!format.isValid()); - - // WHEN - format.setVersion(QVersionNumber(3)); - - // THEN - QCOMPARE(format.api(), QShaderFormat::OpenGLES); - QCOMPARE(format.version().majorVersion(), 3); - QCOMPARE(format.version().minorVersion(), 0); - QCOMPARE(format.extensions(), QStringList()); - QCOMPARE(format.vendor(), QString()); - QVERIFY(format.isValid()); - - // WHEN - format.setVersion(QVersionNumber(3, 2)); - - // THEN - QCOMPARE(format.api(), QShaderFormat::OpenGLES); - QCOMPARE(format.version().majorVersion(), 3); - QCOMPARE(format.version().minorVersion(), 2); - QCOMPARE(format.extensions(), QStringList()); - QCOMPARE(format.vendor(), QString()); - QVERIFY(format.isValid()); - - // WHEN - format.setExtensions({"foo", "bar"}); - - // THEN - QCOMPARE(format.api(), QShaderFormat::OpenGLES); - QCOMPARE(format.version().majorVersion(), 3); - QCOMPARE(format.version().minorVersion(), 2); - QCOMPARE(format.extensions(), QStringList({"bar", "foo"})); - QCOMPARE(format.vendor(), QString()); - QVERIFY(format.isValid()); - - // WHEN - format.setVendor(QStringLiteral("KDAB")); - - // THEN - QCOMPARE(format.api(), QShaderFormat::OpenGLES); - QCOMPARE(format.version().majorVersion(), 3); - QCOMPARE(format.version().minorVersion(), 2); - QCOMPARE(format.extensions(), QStringList({"bar", "foo"})); - QCOMPARE(format.vendor(), QStringLiteral("KDAB")); - QVERIFY(format.isValid()); -} - -void tst_QShaderNodes::shouldVerifyFormatsEquality_data() -{ - QTest::addColumn<QShaderFormat>("left"); - QTest::addColumn<QShaderFormat>("right"); - QTest::addColumn<bool>("expected"); - - QTest::newRow("Equals") << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0, {"foo", "bar"}, "KDAB") - << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0, {"foo", "bar"}, "KDAB") - << true; - QTest::newRow("Apis") << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0, {"foo", "bar"}, "KDAB") - << createFormat(QShaderFormat::OpenGLNoProfile, 3, 0, {"foo", "bar"}, "KDAB") - << false; - QTest::newRow("Major") << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0, {"foo", "bar"}, "KDAB") - << createFormat(QShaderFormat::OpenGLCoreProfile, 2, 0, {"foo", "bar"}, "KDAB") - << false; - QTest::newRow("Minor") << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0, {"foo", "bar"}, "KDAB") - << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 1, {"foo", "bar"}, "KDAB") - << false; - QTest::newRow("Extensions") << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0, {"foo", "bar"}, "KDAB") - << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0, {"foo"}, "KDAB") - << false; - QTest::newRow("Vendor") << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0, {"foo", "bar"}, "KDAB") - << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0, {"foo", "bar"}) - << false; -} - -void tst_QShaderNodes::shouldVerifyFormatsEquality() -{ - // GIVEN - QFETCH(QShaderFormat, left); - QFETCH(QShaderFormat, right); - - // WHEN - const auto equal = (left == right); - const auto notEqual = (left != right); - - // THEN - QFETCH(bool, expected); - QCOMPARE(equal, expected); - QCOMPARE(notEqual, !expected); -} - -void tst_QShaderNodes::shouldVerifyFormatsCompatibilities_data() -{ - QTest::addColumn<QShaderFormat>("reference"); - QTest::addColumn<QShaderFormat>("tested"); - QTest::addColumn<bool>("expected"); - - QTest::newRow("NoProfileVsES") << createFormat(QShaderFormat::OpenGLNoProfile, 2, 0) - << createFormat(QShaderFormat::OpenGLES, 2, 0) - << true; - QTest::newRow("CoreProfileVsES") << createFormat(QShaderFormat::OpenGLCoreProfile, 2, 0) - << createFormat(QShaderFormat::OpenGLES, 2, 0) - << false; - QTest::newRow("CompatProfileVsES") << createFormat(QShaderFormat::OpenGLCompatibilityProfile, 2, 0) - << createFormat(QShaderFormat::OpenGLES, 2, 0) - << true; - - QTest::newRow("ESVsNoProfile") << createFormat(QShaderFormat::OpenGLES, 2, 0) - << createFormat(QShaderFormat::OpenGLNoProfile, 2, 0) - << false; - QTest::newRow("ESVsCoreProfile") << createFormat(QShaderFormat::OpenGLES, 2, 0) - << createFormat(QShaderFormat::OpenGLCoreProfile, 2, 0) - << false; - QTest::newRow("ESVsCompatProfile") << createFormat(QShaderFormat::OpenGLES, 2, 0) - << createFormat(QShaderFormat::OpenGLCompatibilityProfile, 2, 0) - << false; - - QTest::newRow("CoreVsNoProfile") << createFormat(QShaderFormat::OpenGLCoreProfile, 2, 0) - << createFormat(QShaderFormat::OpenGLNoProfile, 2, 0) - << false; - QTest::newRow("CoreVsCompat") << createFormat(QShaderFormat::OpenGLCoreProfile, 2, 0) - << createFormat(QShaderFormat::OpenGLCompatibilityProfile, 2, 0) - << false; - QTest::newRow("CoreVsCore") << createFormat(QShaderFormat::OpenGLCoreProfile, 2, 0) - << createFormat(QShaderFormat::OpenGLCoreProfile, 2, 0) - << true; - - QTest::newRow("NoProfileVsCore") << createFormat(QShaderFormat::OpenGLNoProfile, 2, 0) - << createFormat(QShaderFormat::OpenGLCoreProfile, 2, 0) - << true; - QTest::newRow("NoProvileVsCompat") << createFormat(QShaderFormat::OpenGLNoProfile, 2, 0) - << createFormat(QShaderFormat::OpenGLCompatibilityProfile, 2, 0) - << true; - QTest::newRow("NoProfileVsNoProfile") << createFormat(QShaderFormat::OpenGLNoProfile, 2, 0) - << createFormat(QShaderFormat::OpenGLNoProfile, 2, 0) - << true; - - QTest::newRow("CompatVsCore") << createFormat(QShaderFormat::OpenGLCompatibilityProfile, 2, 0) - << createFormat(QShaderFormat::OpenGLCoreProfile, 2, 0) - << true; - QTest::newRow("CompatVsCompat") << createFormat(QShaderFormat::OpenGLCompatibilityProfile, 2, 0) - << createFormat(QShaderFormat::OpenGLCompatibilityProfile, 2, 0) - << true; - QTest::newRow("CompatVsNoProfile") << createFormat(QShaderFormat::OpenGLCompatibilityProfile, 2, 0) - << createFormat(QShaderFormat::OpenGLNoProfile, 2, 0) - << true; - - QTest::newRow("MajorForwardCompat_1") << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0) - << createFormat(QShaderFormat::OpenGLCoreProfile, 2, 0) - << true; - QTest::newRow("MajorForwardCompat_2") << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0) - << createFormat(QShaderFormat::OpenGLCoreProfile, 2, 4) - << true; - QTest::newRow("MajorForwardCompat_3") << createFormat(QShaderFormat::OpenGLCoreProfile, 2, 0) - << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0) - << false; - QTest::newRow("MajorForwardCompat_4") << createFormat(QShaderFormat::OpenGLCoreProfile, 2, 4) - << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0) - << false; - - QTest::newRow("MinorForwardCompat_1") << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 1) - << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0) - << true; - QTest::newRow("MinorForwardCompat_2") << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0) - << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 1) - << false; - - QTest::newRow("Extensions_1") << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0, {"foo", "bar"}) - << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0, {"foo"}) - << true; - QTest::newRow("Extensions_2") << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0, {"foo"}) - << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0, {"foo", "bar"}) - << false; - - QTest::newRow("Vendor_1") << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0, {}, "KDAB") - << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0, {}) - << true; - QTest::newRow("Vendor_2") << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0, {}) - << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0, {}, "KDAB") - << false; - QTest::newRow("Vendor_2") << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0, {}, "KDAB") - << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0, {}, "KDAB") - << true; -} - -void tst_QShaderNodes::shouldVerifyFormatsCompatibilities() -{ - // GIVEN - QFETCH(QShaderFormat, reference); - QFETCH(QShaderFormat, tested); - - // WHEN - const auto supported = reference.supports(tested); - - // THEN - QFETCH(bool, expected); - QCOMPARE(supported, expected); -} - -void tst_QShaderNodes::shouldHaveDefaultPortState() -{ - // GIVEN - auto port = QShaderNodePort(); - - // THEN - QCOMPARE(port.direction, QShaderNodePort::Output); - QVERIFY(port.name.isEmpty()); -} - -void tst_QShaderNodes::shouldVerifyPortsEquality_data() -{ - QTest::addColumn<QShaderNodePort>("left"); - QTest::addColumn<QShaderNodePort>("right"); - QTest::addColumn<bool>("expected"); - - QTest::newRow("Equals") << createPort(QShaderNodePort::Input, "foo") - << createPort(QShaderNodePort::Input, "foo") - << true; - QTest::newRow("Direction") << createPort(QShaderNodePort::Input, "foo") - << createPort(QShaderNodePort::Output, "foo") - << false; - QTest::newRow("Name") << createPort(QShaderNodePort::Input, "foo") - << createPort(QShaderNodePort::Input, "bar") - << false; -} - -void tst_QShaderNodes::shouldVerifyPortsEquality() -{ - // GIVEN - QFETCH(QShaderNodePort, left); - QFETCH(QShaderNodePort, right); - - // WHEN - const auto equal = (left == right); - const auto notEqual = (left != right); - - // THEN - QFETCH(bool, expected); - QCOMPARE(equal, expected); - QCOMPARE(notEqual, !expected); -} - -void tst_QShaderNodes::shouldManipulateNodeMembers() -{ - // GIVEN - const auto openGLES2 = createFormat(QShaderFormat::OpenGLES, 2, 0); - const auto openGL3 = createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0); - - const auto es2Rule = QShaderNode::Rule(QByteArrayLiteral("gles2"), {"#pragma include es2/foo.inc", "#pragma include es2/bar.inc"}); - const auto gl3Rule = QShaderNode::Rule(QByteArrayLiteral("gl3"), {"#pragma include gl3/foo.inc", "#pragma include gl3/bar.inc"}); - const auto gl3bisRule = QShaderNode::Rule(QByteArrayLiteral("gl3bis"), {"#pragma include gl3/foo.inc", "#pragma include gl3/bar.inc"}); - - auto node = QShaderNode(); - - // THEN (default state) - QCOMPARE(node.type(), QShaderNode::Invalid); - QVERIFY(node.uuid().isNull()); - QVERIFY(node.layers().isEmpty()); - QVERIFY(node.ports().isEmpty()); - QVERIFY(node.parameterNames().isEmpty()); - QVERIFY(node.availableFormats().isEmpty()); - - // WHEN - const auto uuid = QUuid::createUuid(); - node.setUuid(uuid); - - // THEN - QCOMPARE(node.uuid(), uuid); - - // WHEN - node.setLayers({"foo", "bar"}); - - // THEN - QCOMPARE(node.layers(), QStringList({"foo", "bar"})); - - // WHEN - auto firstPort = QShaderNodePort(); - firstPort.direction = QShaderNodePort::Input; - firstPort.name = QStringLiteral("foo"); - node.addPort(firstPort); - - // THEN - QCOMPARE(node.type(), QShaderNode::Output); - QCOMPARE(node.ports().size(), 1); - QCOMPARE(node.ports().at(0), firstPort); - QVERIFY(node.availableFormats().isEmpty()); - - // WHEN - auto secondPort = QShaderNodePort(); - secondPort.direction = QShaderNodePort::Output; - secondPort.name = QStringLiteral("bar"); - node.addPort(secondPort); - - // THEN - QCOMPARE(node.type(), QShaderNode::Function); - QCOMPARE(node.ports().size(), 2); - QCOMPARE(node.ports().at(0), firstPort); - QCOMPARE(node.ports().at(1), secondPort); - QVERIFY(node.availableFormats().isEmpty()); - - // WHEN - node.removePort(firstPort); - - // THEN - QCOMPARE(node.type(), QShaderNode::Input); - QCOMPARE(node.ports().size(), 1); - QCOMPARE(node.ports().at(0), secondPort); - QVERIFY(node.availableFormats().isEmpty()); - - // WHEN - node.setParameter(QStringLiteral("baz"), 42); - - // THEN - QCOMPARE(node.type(), QShaderNode::Input); - QCOMPARE(node.ports().size(), 1); - QCOMPARE(node.ports().at(0), secondPort); - auto parameterNames = node.parameterNames(); - parameterNames.sort(); - QCOMPARE(parameterNames.size(), 1); - QCOMPARE(parameterNames.at(0), QStringLiteral("baz")); - QCOMPARE(node.parameter(QStringLiteral("baz")), QVariant(42)); - QVERIFY(node.availableFormats().isEmpty()); - - // WHEN - node.setParameter(QStringLiteral("bleh"), QStringLiteral("value")); - - // THEN - QCOMPARE(node.type(), QShaderNode::Input); - QCOMPARE(node.ports().size(), 1); - QCOMPARE(node.ports().at(0), secondPort); - parameterNames = node.parameterNames(); - parameterNames.sort(); - QCOMPARE(parameterNames.size(), 2); - QCOMPARE(parameterNames.at(0), QStringLiteral("baz")); - QCOMPARE(parameterNames.at(1), QStringLiteral("bleh")); - QCOMPARE(node.parameter(QStringLiteral("baz")), QVariant(42)); - QCOMPARE(node.parameter(QStringLiteral("bleh")), QVariant(QStringLiteral("value"))); - QVERIFY(node.availableFormats().isEmpty()); - - // WHEN - node.clearParameter(QStringLiteral("baz")); - - // THEN - QCOMPARE(node.type(), QShaderNode::Input); - QCOMPARE(node.ports().size(), 1); - QCOMPARE(node.ports().at(0), secondPort); - parameterNames = node.parameterNames(); - parameterNames.sort(); - QCOMPARE(parameterNames.size(), 1); - QCOMPARE(parameterNames.at(0), QStringLiteral("bleh")); - QCOMPARE(node.parameter(QStringLiteral("baz")), QVariant()); - QCOMPARE(node.parameter(QStringLiteral("bleh")), QVariant(QStringLiteral("value"))); - QVERIFY(node.availableFormats().isEmpty()); - - // WHEN - node.addRule(openGLES2, es2Rule); - node.addRule(openGL3, gl3Rule); - - // THEN - QCOMPARE(node.availableFormats().size(), 2); - QCOMPARE(node.availableFormats().at(0), openGLES2); - QCOMPARE(node.availableFormats().at(1), openGL3); - QCOMPARE(node.rule(openGLES2), es2Rule); - QCOMPARE(node.rule(openGL3), gl3Rule); - - // WHEN - node.removeRule(openGLES2); - - // THEN - QCOMPARE(node.availableFormats().size(), 1); - QCOMPARE(node.availableFormats().at(0), openGL3); - QCOMPARE(node.rule(openGL3), gl3Rule); - - // WHEN - node.addRule(openGLES2, es2Rule); - - // THEN - QCOMPARE(node.availableFormats().size(), 2); - QCOMPARE(node.availableFormats().at(0), openGL3); - QCOMPARE(node.availableFormats().at(1), openGLES2); - QCOMPARE(node.rule(openGLES2), es2Rule); - QCOMPARE(node.rule(openGL3), gl3Rule); - - // WHEN - node.addRule(openGL3, gl3bisRule); - - // THEN - QCOMPARE(node.availableFormats().size(), 2); - QCOMPARE(node.availableFormats().at(0), openGLES2); - QCOMPARE(node.availableFormats().at(1), openGL3); - QCOMPARE(node.rule(openGLES2), es2Rule); - QCOMPARE(node.rule(openGL3), gl3bisRule); -} - -void tst_QShaderNodes::shouldHandleNodeRulesSupportAndOrder() -{ - // GIVEN - const auto openGLES2 = createFormat(QShaderFormat::OpenGLES, 2, 0); - const auto openGL3 = createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0); - const auto openGL32 = createFormat(QShaderFormat::OpenGLCoreProfile, 3, 2); - const auto openGL4 = createFormat(QShaderFormat::OpenGLCoreProfile, 4, 0); - - const auto es2Rule = QShaderNode::Rule(QByteArrayLiteral("gles2"), {"#pragma include es2/foo.inc", "#pragma include es2/bar.inc"}); - const auto gl3Rule = QShaderNode::Rule(QByteArrayLiteral("gl3"), {"#pragma include gl3/foo.inc", "#pragma include gl3/bar.inc"}); - const auto gl32Rule = QShaderNode::Rule(QByteArrayLiteral("gl32"), {"#pragma include gl32/foo.inc", "#pragma include gl32/bar.inc"}); - const auto gl3bisRule = QShaderNode::Rule(QByteArrayLiteral("gl3bis"), {"#pragma include gl3/foo.inc", "#pragma include gl3/bar.inc"}); - - auto node = QShaderNode(); - - // WHEN - node.addRule(openGLES2, es2Rule); - node.addRule(openGL3, gl3Rule); - - // THEN - QCOMPARE(node.availableFormats().size(), 2); - QCOMPARE(node.availableFormats().at(0), openGLES2); - QCOMPARE(node.availableFormats().at(1), openGL3); - QCOMPARE(node.rule(openGLES2), es2Rule); - QCOMPARE(node.rule(openGL3), gl3Rule); - QCOMPARE(node.rule(openGL32), gl3Rule); - QCOMPARE(node.rule(openGL4), gl3Rule); - - // WHEN - node.addRule(openGL32, gl32Rule); - - // THEN - QCOMPARE(node.availableFormats().size(), 3); - QCOMPARE(node.availableFormats().at(0), openGLES2); - QCOMPARE(node.availableFormats().at(1), openGL3); - QCOMPARE(node.availableFormats().at(2), openGL32); - QCOMPARE(node.rule(openGLES2), es2Rule); - QCOMPARE(node.rule(openGL3), gl3Rule); - QCOMPARE(node.rule(openGL32), gl32Rule); - QCOMPARE(node.rule(openGL4), gl32Rule); - - // WHEN - node.addRule(openGL3, gl3bisRule); - - // THEN - QCOMPARE(node.availableFormats().size(), 3); - QCOMPARE(node.availableFormats().at(0), openGLES2); - QCOMPARE(node.availableFormats().at(1), openGL32); - QCOMPARE(node.availableFormats().at(2), openGL3); - QCOMPARE(node.rule(openGLES2), es2Rule); - QCOMPARE(node.rule(openGL3), gl3bisRule); - QCOMPARE(node.rule(openGL32), gl3bisRule); - QCOMPARE(node.rule(openGL4), gl3bisRule); -} - -QTEST_MAIN(tst_QShaderNodes) - -#include "tst_qshadernodes.moc" diff --git a/tests/auto/gui/util/qshadernodesloader/CMakeLists.txt b/tests/auto/gui/util/qshadernodesloader/CMakeLists.txt deleted file mode 100644 index 0491e4d149..0000000000 --- a/tests/auto/gui/util/qshadernodesloader/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -# Generated from qshadernodesloader.pro. - -##################################################################### -## tst_qshadernodesloader Test: -##################################################################### - -qt_internal_add_test(tst_qshadernodesloader - SOURCES - tst_qshadernodesloader.cpp - PUBLIC_LIBRARIES - Qt::Gui - Qt::GuiPrivate -) diff --git a/tests/auto/gui/util/qshadernodesloader/tst_qshadernodesloader.cpp b/tests/auto/gui/util/qshadernodesloader/tst_qshadernodesloader.cpp deleted file mode 100644 index fd022ba83f..0000000000 --- a/tests/auto/gui/util/qshadernodesloader/tst_qshadernodesloader.cpp +++ /dev/null @@ -1,327 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** 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 General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** 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-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include <QTest> - -#include <QtCore/qbuffer.h> - -#include <QtGui/private/qshadernodesloader_p.h> -#include <QtGui/private/qshaderlanguage_p.h> - -using QBufferPointer = QSharedPointer<QBuffer>; -Q_DECLARE_METATYPE(QBufferPointer); - -using NodeHash = QHash<QString, QShaderNode>; -Q_DECLARE_METATYPE(NodeHash); - -namespace -{ - QBufferPointer createBuffer(const QByteArray &data, QIODevice::OpenMode openMode = QIODevice::ReadOnly) - { - auto buffer = QBufferPointer::create(); - buffer->setData(data); - if (openMode != QIODevice::NotOpen) - buffer->open(openMode); - return buffer; - } - - QShaderFormat createFormat(QShaderFormat::Api api, int majorVersion, int minorVersion, - const QStringList &extensions = QStringList(), - const QString &vendor = QString()) - { - auto format = QShaderFormat(); - format.setApi(api); - format.setVersion(QVersionNumber(majorVersion, minorVersion)); - format.setExtensions(extensions); - format.setVendor(vendor); - return format; - } - - QShaderNodePort createPort(QShaderNodePort::Direction portDirection, const QString &portName) - { - auto port = QShaderNodePort(); - port.direction = portDirection; - port.name = portName; - return port; - } - - QShaderNode createNode(const QList<QShaderNodePort> &ports) - { - auto node = QShaderNode(); - for (const auto &port : ports) - node.addPort(port); - return node; - } -} - -class tst_QShaderNodesLoader : public QObject -{ - Q_OBJECT -private slots: - void shouldManipulateLoaderMembers(); - void shouldLoadFromJsonStream_data(); - void shouldLoadFromJsonStream(); -}; - -void tst_QShaderNodesLoader::shouldManipulateLoaderMembers() -{ - // GIVEN - auto loader = QShaderNodesLoader(); - - // THEN (default state) - QCOMPARE(loader.status(), QShaderNodesLoader::Null); - QVERIFY(!loader.device()); - QVERIFY(loader.nodes().isEmpty()); - - // WHEN - auto device1 = createBuffer(QByteArray("..........."), QIODevice::NotOpen); - loader.setDevice(device1.data()); - - // THEN - QCOMPARE(loader.status(), QShaderNodesLoader::Error); - QCOMPARE(loader.device(), device1.data()); - QVERIFY(loader.nodes().isEmpty()); - - // WHEN - auto device2 = createBuffer(QByteArray("..........."), QIODevice::ReadOnly); - loader.setDevice(device2.data()); - - // THEN - QCOMPARE(loader.status(), QShaderNodesLoader::Waiting); - QCOMPARE(loader.device(), device2.data()); - QVERIFY(loader.nodes().isEmpty()); -} - -void tst_QShaderNodesLoader::shouldLoadFromJsonStream_data() -{ - QTest::addColumn<QBufferPointer>("device"); - QTest::addColumn<NodeHash>("nodes"); - QTest::addColumn<QShaderNodesLoader::Status>("status"); - - QTest::newRow("empty") << createBuffer("", QIODevice::ReadOnly) << NodeHash() << QShaderNodesLoader::Error; - - const auto smallJson = "{" - " \"inputValue\": {" - " \"outputs\": [" - " \"value\"" - " ]," - " \"parameters\": {" - " \"name\": \"defaultName\"," - " \"qualifier\": {" - " \"type\": \"QShaderLanguage::StorageQualifier\"," - " \"value\": \"QShaderLanguage::Uniform\"" - " }," - " \"type\": {" - " \"type\": \"QShaderLanguage::VariableType\"," - " \"value\": \"QShaderLanguage::Vec3\"" - " }," - " \"defaultValue\": {" - " \"type\": \"float\"," - " \"value\": \"1.25\"" - " }" - " }," - " \"rules\": [" - " {" - " \"format\": {" - " \"api\": \"OpenGLES\"," - " \"major\": 2," - " \"minor\": 0" - " }," - " \"substitution\": \"highp vec3 $value = $name;\"," - " \"headerSnippets\": [ \"varying highp vec3 $name;\" ]" - " }," - " {" - " \"format\": {" - " \"api\": \"OpenGLCompatibilityProfile\"," - " \"major\": 2," - " \"minor\": 1" - " }," - " \"substitution\": \"vec3 $value = $name;\"," - " \"headerSnippets\": [ \"in vec3 $name;\" ]" - " }" - " ]" - " }," - " \"fragColor\": {" - " \"inputs\": [" - " \"fragColor\"" - " ]," - " \"rules\": [" - " {" - " \"format\": {" - " \"api\": \"OpenGLES\"," - " \"major\": 2," - " \"minor\": 0" - " }," - " \"substitution\": \"gl_fragColor = $fragColor;\"" - " }," - " {" - " \"format\": {" - " \"api\": \"OpenGLNoProfile\"," - " \"major\": 4," - " \"minor\": 0" - " }," - " \"substitution\": \"fragColor = $fragColor;\"," - " \"headerSnippets\": [ \"out vec4 fragColor;\" ]" - " }" - " ]" - " }," - " \"lightModel\": {" - " \"inputs\": [" - " \"baseColor\"," - " \"position\"," - " \"lightIntensity\"" - " ]," - " \"outputs\": [" - " \"outputColor\"" - " ]," - " \"rules\": [" - " {" - " \"format\": {" - " \"api\": \"OpenGLES\"," - " \"major\": 2," - " \"minor\": 0," - " \"extensions\": [ \"ext1\", \"ext2\" ]," - " \"vendor\": \"kdab\"" - " }," - " \"substitution\": \"highp vec4 $outputColor = lightModel($baseColor, $position, $lightIntensity);\"," - " \"headerSnippets\": [ \"#pragma include es2/lightmodel.frag.inc\" ]" - " }," - " {" - " \"format\": {" - " \"api\": \"OpenGLCoreProfile\"," - " \"major\": 3," - " \"minor\": 3" - " }," - " \"substitution\": \"vec4 $outputColor = lightModel($baseColor, $position, $lightIntensity);\"," - " \"headerSnippets\": [ \"#pragma include gl3/lightmodel.frag.inc\" ]" - " }" - " ]" - " }" - "}"; - - const auto smallProtos = [&]{ - const auto openGLES2 = createFormat(QShaderFormat::OpenGLES, 2, 0); - const auto openGLES2Extended = createFormat(QShaderFormat::OpenGLES, 2, 0, {"ext1", "ext2"}, "kdab"); - const auto openGL2 = createFormat(QShaderFormat::OpenGLCompatibilityProfile, 2, 1); - const auto openGL3 = createFormat(QShaderFormat::OpenGLCoreProfile, 3, 3); - const auto openGL4 = createFormat(QShaderFormat::OpenGLNoProfile, 4, 0); - - auto protos = NodeHash(); - - auto inputValue = createNode({ - createPort(QShaderNodePort::Output, "value") - }); - inputValue.setParameter("name", "defaultName"); - inputValue.setParameter("qualifier", QVariant::fromValue<QShaderLanguage::StorageQualifier>(QShaderLanguage::Uniform)); - inputValue.setParameter("type", QVariant::fromValue<QShaderLanguage::VariableType>(QShaderLanguage::Vec3)); - inputValue.setParameter("defaultValue", QVariant(1.25f)); - inputValue.addRule(openGLES2, QShaderNode::Rule("highp vec3 $value = $name;", - QByteArrayList() << "varying highp vec3 $name;")); - inputValue.addRule(openGL2, QShaderNode::Rule("vec3 $value = $name;", - QByteArrayList() << "in vec3 $name;")); - protos.insert("inputValue", inputValue); - - auto fragColor = createNode({ - createPort(QShaderNodePort::Input, "fragColor") - }); - fragColor.addRule(openGLES2, QShaderNode::Rule("gl_fragColor = $fragColor;")); - fragColor.addRule(openGL4, QShaderNode::Rule("fragColor = $fragColor;", - QByteArrayList() << "out vec4 fragColor;")); - protos.insert(QStringLiteral("fragColor"), fragColor); - - auto lightModel = createNode({ - createPort(QShaderNodePort::Input, "baseColor"), - createPort(QShaderNodePort::Input, "position"), - createPort(QShaderNodePort::Input, "lightIntensity"), - createPort(QShaderNodePort::Output, "outputColor") - }); - lightModel.addRule(openGLES2Extended, QShaderNode::Rule("highp vec4 $outputColor = lightModel($baseColor, $position, $lightIntensity);", - QByteArrayList() << "#pragma include es2/lightmodel.frag.inc")); - lightModel.addRule(openGL3, QShaderNode::Rule("vec4 $outputColor = lightModel($baseColor, $position, $lightIntensity);", - QByteArrayList() << "#pragma include gl3/lightmodel.frag.inc")); - protos.insert("lightModel", lightModel); - - return protos; - }(); - - QTest::newRow("NotOpen") << createBuffer(smallJson, QIODevice::NotOpen) << NodeHash() << QShaderNodesLoader::Error; - QTest::newRow("CorrectJSON") << createBuffer(smallJson) << smallProtos << QShaderNodesLoader::Ready; - - // These types are normaly registered by QShaderGraphLoader - qRegisterMetaType<QShaderLanguage::StorageQualifier>(); - qRegisterMetaType<QShaderLanguage::VariableType>(); -} - -void tst_QShaderNodesLoader::shouldLoadFromJsonStream() -{ - // GIVEN - QFETCH(QBufferPointer, device); - - auto loader = QShaderNodesLoader(); - - // WHEN - loader.setDevice(device.data()); - loader.load(); - - // THEN - QFETCH(QShaderNodesLoader::Status, status); - QCOMPARE(loader.status(), status); - - QFETCH(NodeHash, nodes); - const auto sortedKeys = [](const NodeHash &nodes) { - auto res = nodes.keys(); - res.sort(); - return res; - }; - const auto sortedParameters = [](const QShaderNode &node) { - auto res = node.parameterNames(); - res.sort(); - return res; - }; - QCOMPARE(sortedKeys(loader.nodes()), sortedKeys(nodes)); - for (const auto &key : nodes.keys()) { - const auto actual = loader.nodes().value(key); - const auto expected = nodes.value(key); - - QVERIFY(actual.uuid().isNull()); - QCOMPARE(actual.ports(), expected.ports()); - QCOMPARE(sortedParameters(actual), sortedParameters(expected)); - for (const auto &name : expected.parameterNames()) { - QCOMPARE(actual.parameter(name), expected.parameter(name)); - } - QCOMPARE(actual.availableFormats(), expected.availableFormats()); - for (const auto &format : expected.availableFormats()) { - QCOMPARE(actual.rule(format), expected.rule(format)); - } - } -} - -QTEST_MAIN(tst_QShaderNodesLoader) - -#include "tst_qshadernodesloader.moc" |