diff options
author | Paul Lemire <paul.lemire@kdab.com> | 2019-02-21 13:01:38 +0100 |
---|---|---|
committer | Paul Lemire <paul.lemire@kdab.com> | 2019-03-20 13:29:55 +0000 |
commit | b9ac4faf28cc27849a392019564209b319f90568 (patch) | |
tree | e36fae9592ad81dd26ab483b6d1d6a6562b7ac71 /src/render/texture | |
parent | 3c4feadc1f71d2e7cd1fa0e00d439b740bd9289d (diff) |
Make it possible to partially update a texture
- Introduce QTextureDataUpdate which contains information about the update
- QAbstractTexture::updateTexture function added
- Add manual test texture-updates-cpp
- Add unit tests for GLTexture and complete other texture tests
Change-Id: I1b792f2075830ce05cc8e04cc68110141b5571d6
Reviewed-by: Sean Harmer <sean.harmer@kdab.com>
Diffstat (limited to 'src/render/texture')
-rw-r--r-- | src/render/texture/qabstracttexture.cpp | 22 | ||||
-rw-r--r-- | src/render/texture/qabstracttexture.h | 5 | ||||
-rw-r--r-- | src/render/texture/qabstracttexture_p.h | 4 | ||||
-rw-r--r-- | src/render/texture/qtexturedataupdate.cpp | 197 | ||||
-rw-r--r-- | src/render/texture/qtexturedataupdate.h | 92 | ||||
-rw-r--r-- | src/render/texture/qtexturedataupdate_p.h | 83 | ||||
-rw-r--r-- | src/render/texture/texture.cpp | 17 | ||||
-rw-r--r-- | src/render/texture/texture.pri | 7 | ||||
-rw-r--r-- | src/render/texture/texture_p.h | 20 |
9 files changed, 436 insertions, 11 deletions
diff --git a/src/render/texture/qabstracttexture.cpp b/src/render/texture/qabstracttexture.cpp index 6ef912320..54c84799a 100644 --- a/src/render/texture/qabstracttexture.cpp +++ b/src/render/texture/qabstracttexture.cpp @@ -972,6 +972,27 @@ QVariant QAbstractTexture::handle() const return d->m_handle; } +/*! + * Allow to update a sub region of the texture without having to change the data + * generator or rely on adding or removing texture images. + * \since 5.14 + */ +void QAbstractTexture::updateData(const QTextureDataUpdate &update) +{ + Q_D(QAbstractTexture); + + // Send update to backend if we have the changeArbiter + if (d->m_changeArbiter != nullptr) { + auto e = QPropertyUpdatedChangePtr::create(id()); + e->setPropertyName("updateData"); + e->setValue(QVariant::fromValue(update)); + notifyObservers(e); + } else { + // If we have no arbiter (no backend), record the update as part of the creation changes + d->m_initialDataUpdates.push_back(update); + } +} + Qt3DCore::QNodeCreatedChangeBasePtr QAbstractTexture::createNodeCreationChange() const { auto creationChange = Qt3DCore::QNodeCreatedChangePtr<QAbstractTextureData>::create(this); @@ -996,6 +1017,7 @@ Qt3DCore::QNodeCreatedChangeBasePtr QAbstractTexture::createNodeCreationChange() data.samples = d->m_samples; data.dataFunctor = d->m_dataFunctor; data.sharedTextureId = d->m_sharedTextureId; + data.initialDataUpdates = d->m_initialDataUpdates; return creationChange; } diff --git a/src/render/texture/qabstracttexture.h b/src/render/texture/qabstracttexture.h index 40953f253..2e1127b86 100644 --- a/src/render/texture/qabstracttexture.h +++ b/src/render/texture/qabstracttexture.h @@ -52,7 +52,7 @@ class QAbstractTexturePrivate; class QTextureWrapMode; class QAbstractTextureImage; class QTextureGenerator; - +class QTextureDataUpdate; typedef QSharedPointer<QTextureGenerator> QTextureGeneratorPtr; class QT3DRENDERSHARED_EXPORT QAbstractTexture : public Qt3DCore::QNode @@ -309,6 +309,9 @@ public: HandleType handleType() const; QVariant handle() const; + Q_INVOKABLE void updateData(const QTextureDataUpdate &update); + + public Q_SLOTS: void setFormat(TextureFormat format); void setGenerateMipMaps(bool gen); diff --git a/src/render/texture/qabstracttexture_p.h b/src/render/texture/qabstracttexture_p.h index 0ad1d0737..700788787 100644 --- a/src/render/texture/qabstracttexture_p.h +++ b/src/render/texture/qabstracttexture_p.h @@ -56,6 +56,7 @@ #include <Qt3DRender/qabstracttexture.h> #include <Qt3DRender/qtexturewrapmode.h> #include <Qt3DRender/qtexturegenerator.h> +#include <Qt3DRender/qtexturedataupdate.h> #include <Qt3DRender/private/qt3drender_global_p.h> QT_BEGIN_NAMESPACE @@ -95,6 +96,8 @@ public : QTextureGeneratorPtr dataFunctor() const; void setDataFunctor(const QTextureGeneratorPtr &generator); + QVector<QTextureDataUpdate> m_initialDataUpdates; + private: QTextureGeneratorPtr m_dataFunctor; }; @@ -120,6 +123,7 @@ struct QAbstractTextureData int samples; int sharedTextureId; QTextureGeneratorPtr dataFunctor; + QVector<QTextureDataUpdate> initialDataUpdates; }; } // QT3D diff --git a/src/render/texture/qtexturedataupdate.cpp b/src/render/texture/qtexturedataupdate.cpp new file mode 100644 index 000000000..35d5682f0 --- /dev/null +++ b/src/render/texture/qtexturedataupdate.cpp @@ -0,0 +1,197 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D 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 "qtexturedataupdate.h" +#include "qtexturedataupdate_p.h" +#include <iostream> + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender +{ + +QTextureDataUpdatePrivate::QTextureDataUpdatePrivate() + : m_x(0) + , m_y(0) + , m_z(0) + , m_layer(0) + , m_mipLevel(0) + , m_face(QAbstractTexture::CubeMapPositiveX) +{ +} + +QTextureDataUpdatePrivate::QTextureDataUpdatePrivate(const QTextureDataUpdatePrivate &other) + : m_x(other.m_x) + , m_y(other.m_y) + , m_z(other.m_z) + , m_layer(other.m_layer) + , m_mipLevel(other.m_mipLevel) + , m_face(other.m_face) + , m_data(other.m_data) +{ +} + +bool QTextureDataUpdatePrivate::operator==(const QTextureDataUpdatePrivate &other) const +{ + return (m_x == other.m_x && m_y == other.m_y && m_z == other.m_z && + m_layer == other.m_layer && m_mipLevel == other.m_mipLevel && + m_face == other.m_face && m_data == other.m_data); +} + +bool QTextureDataUpdatePrivate::operator!=(const QTextureDataUpdatePrivate &other) const +{ + return !(*this == other); +} + +/*! + \class Qt3DRender::QTextureDataUpdate + \brief QTextureDataUpdate holds content and information required to perform + partial updates of a texture content. + + The actual data content is contained in a QTextureImageDataPtr member. + Additional members allow to specify the x, y, z offset of the content update + as well as the eventual layer, mipLevel and face. + + \sa QAbstractTexture + */ + +QTextureDataUpdate::QTextureDataUpdate() + : d(new QTextureDataUpdatePrivate()) +{ +} + +QTextureDataUpdate::QTextureDataUpdate(const QTextureDataUpdate &other) + : d(new QTextureDataUpdatePrivate(*other.d)) +{ +} + +QTextureDataUpdate &QTextureDataUpdate::operator=(const QTextureDataUpdate &other) +{ + QTextureDataUpdate tmp(other); + d.swap(tmp.d); + return *this; +} + +QTextureDataUpdate::~QTextureDataUpdate() +{ +} + +bool QTextureDataUpdate::operator==(const QTextureDataUpdate &other) const +{ + return *d == *other.d; +} + +bool QTextureDataUpdate::operator!=(const QTextureDataUpdate &other) const +{ + return *d != *other.d; +} + +int QTextureDataUpdate::x() const +{ + return d->m_x; +} + +int QTextureDataUpdate::y() const +{ + return d->m_y; +} + +int QTextureDataUpdate::z() const +{ + return d->m_z; +} + +int QTextureDataUpdate::layer() const +{ + return d->m_layer; +} + +int QTextureDataUpdate::mipLevel() const +{ + return d->m_mipLevel; +} + +QAbstractTexture::CubeMapFace QTextureDataUpdate::face() const +{ + return d->m_face; +} + +QTextureImageDataPtr QTextureDataUpdate::data() const +{ + return d->m_data; +} + +void QTextureDataUpdate::setX(int x) +{ + d->m_x = x; +} + +void QTextureDataUpdate::setY(int y) +{ + d->m_y = y; +} + +void QTextureDataUpdate::setZ(int z) +{ + d->m_z = z; +} + +void QTextureDataUpdate::setLayer(int layer) +{ + d->m_layer = layer; +} + +void QTextureDataUpdate::setMipLevel(int mipLevel) +{ + d->m_mipLevel = mipLevel; +} + +void QTextureDataUpdate::setFace(QAbstractTexture::CubeMapFace face) +{ + d->m_face = face; +} + +void QTextureDataUpdate::setData(const QTextureImageDataPtr &data) +{ + d->m_data = data; +} + +} // Qt3DRender + +QT_END_NAMESPACE diff --git a/src/render/texture/qtexturedataupdate.h b/src/render/texture/qtexturedataupdate.h new file mode 100644 index 000000000..4aded2369 --- /dev/null +++ b/src/render/texture/qtexturedataupdate.h @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D 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 QT3DRENDER_QTEXTUREDATAUPDATE_H +#define QT3DRENDER_QTEXTUREDATAUPDATE_H + +#include <Qt3DRender/qt3drender_global.h> +#include <Qt3DRender/qabstracttexture.h> +#include <memory> + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender +{ + +class QTextureDataUpdatePrivate; + +class QT3DRENDERSHARED_EXPORT QTextureDataUpdate +{ +public: + QTextureDataUpdate(); + QTextureDataUpdate(const QTextureDataUpdate &other); + QTextureDataUpdate &operator=(const QTextureDataUpdate &other); + ~QTextureDataUpdate(); + + bool operator==(const QTextureDataUpdate &other) const; + bool operator!=(const QTextureDataUpdate &other) const; + + int x() const; + int y() const; + int z() const; + int layer() const; + int mipLevel() const; + QAbstractTexture::CubeMapFace face() const; + QTextureImageDataPtr data() const; + + void setX(int x); + void setY(int y); + void setZ(int z); + void setLayer(int layer); + void setMipLevel(int mipLevel); + void setFace(QAbstractTexture::CubeMapFace face); + void setData(const QTextureImageDataPtr &data); + +private: + std::unique_ptr<QTextureDataUpdatePrivate> d; +}; + +} // Qt3DRender + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(Qt3DRender::QTextureDataUpdate) + + +#endif // QT3DRENDER_QTEXTUREDATAUPDATE_H diff --git a/src/render/texture/qtexturedataupdate_p.h b/src/render/texture/qtexturedataupdate_p.h new file mode 100644 index 000000000..26e707841 --- /dev/null +++ b/src/render/texture/qtexturedataupdate_p.h @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D 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 QT3DRENDER_QTEXTUREDATAUPDATE_P_H +#define QT3DRENDER_QTEXTUREDATAUPDATE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <Qt3DRender/qtextureimagedata.h> +#include <Qt3DRender/qabstracttexture.h> + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { + +class QTextureDataUpdatePrivate +{ +public: + QTextureDataUpdatePrivate(); + QTextureDataUpdatePrivate(const QTextureDataUpdatePrivate &other); + + bool operator==(const QTextureDataUpdatePrivate &other) const; + bool operator!=(const QTextureDataUpdatePrivate &other) const; + + int m_x; + int m_y; + int m_z; + int m_layer; + int m_mipLevel; + QAbstractTexture::CubeMapFace m_face; + QTextureImageDataPtr m_data; +}; + +} // Qt3DRender + +QT_END_NAMESPACE + +#endif // QT3DRENDER_QTEXTUREDATAUPDATE_P_H diff --git a/src/render/texture/texture.cpp b/src/render/texture/texture.cpp index 17fd47be3..c7a739724 100644 --- a/src/render/texture/texture.cpp +++ b/src/render/texture/texture.cpp @@ -47,7 +47,6 @@ #include <Qt3DCore/qpropertynoderemovedchange.h> #include <Qt3DRender/private/texture_p.h> -#include <Qt3DRender/private/qabstracttexture_p.h> #include <Qt3DRender/private/gltexturemanager_p.h> #include <Qt3DRender/private/managers_p.h> @@ -115,6 +114,7 @@ void Texture::cleanup() // texture is being referenced by a shared API specific texture (GLTexture) m_dataFunctor.reset(); m_textureImageIds.clear(); + m_pendingTextureDataUpdates.clear(); m_sharedTextureId = -1; // set default values @@ -185,9 +185,12 @@ void Texture::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) } else if (propertyChange->propertyName() == QByteArrayLiteral("textureId")) { m_sharedTextureId = propertyChange->value().toInt(); dirty = DirtySharedTextureId; + } else if (propertyChange->propertyName() == QByteArrayLiteral("updateData")) { + Qt3DRender::QTextureDataUpdate updateData = propertyChange->value().value<Qt3DRender::QTextureDataUpdate>(); + addTextureDataUpdate(updateData); } - } break; + } case PropertyValueAdded: { const auto change = qSharedPointerCast<QPropertyNodeAddedChange>(e); @@ -340,11 +343,21 @@ void Texture::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &chan for (const QNodeId imgId : data.textureImageIds) addTextureImage(imgId); + const QVector<QTextureDataUpdate> initialDataUpdates = data.initialDataUpdates; + for (const QTextureDataUpdate &initialUpdate : initialDataUpdates) + addTextureDataUpdate(initialUpdate); + addDirtyFlag(DirtyFlags(DirtyImageGenerators|DirtyProperties|DirtyParameters)); if (m_sharedTextureId > 0) addDirtyFlag(DirtySharedTextureId); } +void Texture::addTextureDataUpdate(const QTextureDataUpdate &update) +{ + m_pendingTextureDataUpdates.push_back(update); + addDirtyFlag(DirtyPendingDataUpdates); +} + TextureFunctor::TextureFunctor(AbstractRenderer *renderer, TextureManager *textureNodeManager) diff --git a/src/render/texture/texture.pri b/src/render/texture/texture.pri index 0115a649e..87c77a2ff 100644 --- a/src/render/texture/texture.pri +++ b/src/render/texture/texture.pri @@ -19,7 +19,9 @@ HEADERS += \ $$PWD/qtexturegenerator.h \ $$PWD/qtexture_p.h \ $$PWD/qpaintedtextureimage.h \ - $$PWD/qpaintedtextureimage_p.h + $$PWD/qpaintedtextureimage_p.h \ + $$PWD/qtexturedataupdate.h \ + $$PWD/qtexturedataupdate_p.h SOURCES += \ $$PWD/qabstracttextureimage.cpp \ @@ -32,4 +34,5 @@ SOURCES += \ $$PWD/qtextureimagedata.cpp \ $$PWD/qtexturedata.cpp \ $$PWD/qtexturegenerator.cpp \ - $$PWD/qpaintedtextureimage.cpp + $$PWD/qpaintedtextureimage.cpp \ + $$PWD/qtexturedataupdate.cpp diff --git a/src/render/texture/texture_p.h b/src/render/texture/texture_p.h index c60e90181..28580c92a 100644 --- a/src/render/texture/texture_p.h +++ b/src/render/texture/texture_p.h @@ -53,6 +53,7 @@ #include <Qt3DRender/private/backendnode_p.h> #include <Qt3DRender/private/handle_types_p.h> +#include <Qt3DRender/private/qabstracttexture_p.h> #include <Qt3DRender/qtexture.h> #include <Qt3DRender/qtexturedata.h> #include <Qt3DRender/qtexturegenerator.h> @@ -83,7 +84,7 @@ struct TextureProperties int layers = 1; int mipLevels = 1; int samples = 1; - QAbstractTexture::Target target = QAbstractTexture::Target2D; + QAbstractTexture::Target target = QAbstractTexture::TargetAutomatic; QAbstractTexture::TextureFormat format = QAbstractTexture::NoFormat; bool generateMipMaps = false; QAbstractTexture::Status status = QAbstractTexture::None; @@ -97,6 +98,7 @@ struct TextureProperties inline bool operator!=(const TextureProperties &o) const { return !(*this == o); } }; + /** * Texture parameters that are independent of texture data and that may * change without the re-uploading the texture @@ -134,11 +136,12 @@ public: enum DirtyFlag { NotDirty = 0, - DirtyProperties = 0x1, - DirtyParameters = 0x2, - DirtyImageGenerators = 0x4, - DirtyDataGenerator = 0x8, - DirtySharedTextureId = 0x16 + DirtyProperties = (1 << 0), + DirtyParameters = (1 << 1), + DirtyImageGenerators = (1 << 2), + DirtyDataGenerator = (1 << 3), + DirtySharedTextureId = (1 << 4), + DirtyPendingDataUpdates = (1 << 5), }; Q_DECLARE_FLAGS(DirtyFlags, DirtyFlag) @@ -157,6 +160,9 @@ public: void removeTextureImage(Qt3DCore::QNodeId id); void cleanup(); + void addTextureDataUpdate(const QTextureDataUpdate &update); + QVector<QTextureDataUpdate> takePendingTextureDataUpdates() { return std::move(m_pendingTextureDataUpdates); } + void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; inline const TextureProperties& properties() const { return m_properties; } @@ -180,6 +186,7 @@ private: Qt3DCore::QNodeIdVector m_textureImageIds; QMutex m_flagsMutex; + QVector<QTextureDataUpdate> m_pendingTextureDataUpdates; }; class Q_AUTOTEST_EXPORT TextureFunctor : public Qt3DCore::QBackendNodeMapper @@ -211,5 +218,6 @@ inline QDebug operator<<(QDebug dbg, const Texture &texture) QT_END_NAMESPACE Q_DECLARE_METATYPE(Qt3DRender::Render::Texture*) // LCOV_EXCL_LINE +Q_DECLARE_METATYPE(Qt3DRender::Render::TextureProperties) // LCOV_EXCL_LINE #endif // QT3DRENDER_RENDER_TEXTURE_H |