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