diff options
author | Sean Harmer <sean.harmer@kdab.com> | 2015-09-18 16:16:15 +0100 |
---|---|---|
committer | Paul Lemire <paul.lemire@kdab.com> | 2015-10-13 12:13:03 +0000 |
commit | 261e3ca25f09fb2095685c418b65c18b0afafc7b (patch) | |
tree | 5851c21691178a6907477e164e6a083723e4302d /src/render/texture | |
parent | c65de5cc688e09c50a470bc9d303734fd8b9858a (diff) |
Move texture classes to their own directory
Change-Id: I026cad678b06d8d785f7652f42d1dccc2fede88a
Reviewed-by: Paul Lemire <paul.lemire@kdab.com>
Diffstat (limited to 'src/render/texture')
20 files changed, 3700 insertions, 0 deletions
diff --git a/src/render/texture/qabstracttextureimage.cpp b/src/render/texture/qabstracttextureimage.cpp new file mode 100644 index 000000000..5f44090d4 --- /dev/null +++ b/src/render/texture/qabstracttextureimage.cpp @@ -0,0 +1,224 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qabstracttextureimage.h" +#include "qabstracttextureimage_p.h" +#include <Qt3DCore/qscenepropertychange.h> + +QT_BEGIN_NAMESPACE + +using namespace Qt3D; + +namespace Qt3DRender { + +/*! + \class Qt3D::QAbstractTextureImagePrivate + \internal +*/ + +/*! + \qmltype AbstractTextureImage + \instantiates Qt3D::QAbstractTextureImage + \inherits Node + \inqmlmodule Qt3D.Renderer + \qmlabstract + \since 5.5 + \brief Encapsulates the necessary information to create an OpenGL texture image. +*/ + +/*! + \class QAbstractTextureImage + \inmodule Qt3DRenderer + \since 5.5 + \brief Encapsulates the necessary information to create an OpenGL texture image. + + QAbstractTextureImage should be used as the means of providing image data to a + QAbstractTextureProvider. It contains the necessary information: mipmap + level, layer, cube face load at the proper place data into an OpenGL texture. + + The actual data is provided through a QTextureDataFunctor that will be + executed by Aspect jobs in the backend. QAbstractTextureImage should be + subclassed to provide a functor and eventual additional properties needed by + the functor to load actual data. + + \note: QAbstractTextureImage should never be shared. Expect crashes, undefined + behavior at best if this rule is not respected. + */ + +/*! + Constructs a new Qt3D::QAbstractTextureImage instance with \a parent as parent. + */ +QAbstractTextureImage::QAbstractTextureImage(QNode *parent) + : QNode(*new QAbstractTextureImagePrivate, parent) +{ +} + +/*! + The destructor. + */ +QAbstractTextureImage::~QAbstractTextureImage() +{ + Q_ASSERT_X(Qt3D::QNodePrivate::get(this)->m_wasCleanedUp, Q_FUNC_INFO, "QNode::cleanup should have been called by now. A Qt3DRender::QAbstractTextureImage subclass didn't call QNode::cleanup in its destructor"); +} + + +/*! + \qmlproperty int Qt3D.render::AbstractTextureImage::mipmapLevel + + Holds the mipmap level of the texture image. + */ + +/*! + \property Qt3D::QAbstractTextureImage::mipmapLevel + + Holds the mipmap level of the texture image. + */ +int QAbstractTextureImage::mipmapLevel() const +{ + Q_D(const QAbstractTextureImage); + return d->m_mipmapLevel; +} + +/*! + \qmlproperty int Qt3D.Renderer::AbstractTextureImage::layer + + Holds the layer of the texture image. + */ + +/*! + \property Qt3D::QAbstractTextureImage::layer + + Holds the layer of the texture image. + */ +int QAbstractTextureImage::layer() const +{ + Q_D(const QAbstractTextureImage); + return d->m_layer; +} + +/*! + \qmlproperty enumeration Qt3D.Renderer::AbstractTextureImage::cubeMapFace + + Holds the cube map face of the texture image. + + \value CubeMapPositiveX 0x8515 GL_TEXTURE_CUBE_MAP_POSITIVE_X + \value CubeMapNegativeX 0x8516 GL_TEXTURE_CUBE_MAP_NEGATIVE_X + \value CubeMapPositiveY 0x8517 GL_TEXTURE_CUBE_MAP_POSITIVE_Y + \value CubeMapNegativeY 0x8518 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y + \value CubeMapPositiveZ 0x8519 GL_TEXTURE_CUBE_MAP_POSITIVE_Z + \value CubeMapNegativeZ 0x851A GL_TEXTURE_CUBE_MAP_NEGATIVE_Z + + \note The cube map face has a meaning only for + \l {QAbstractTextureProvider::}{TargetCubeMap} and + \l {QAbstractTextureProvider::}{TargetCubeMapArray}. + */ + +/*! + \property Qt3D::QAbstractTextureImage::cubeMapFace + + Holds the cube map face of the texture image. + + \note The cube map face has a meaning only for + \l {QAbstractTextureProvider::}{TargetCubeMap} and + \l {QAbstractTextureProvider::}{TargetCubeMapArray}. + */ +QAbstractTextureProvider::CubeMapFace QAbstractTextureImage::cubeMapFace() const +{ + Q_D(const QAbstractTextureImage); + return d->m_face; +} + +void QAbstractTextureImage::setMipmapLevel(int level) +{ + Q_D(QAbstractTextureImage); + if (level != d->m_mipmapLevel) { + d->m_mipmapLevel = level; + emit mipmapLevelChanged(); + } +} + +void QAbstractTextureImage::setLayer(int layer) +{ + Q_D(QAbstractTextureImage); + if (layer != d->m_layer) { + d->m_layer = layer; + emit layerChanged(); + } +} + +void QAbstractTextureImage::setCubeMapFace(QAbstractTextureProvider::CubeMapFace face) +{ + Q_D(QAbstractTextureImage); + if (face != d->m_face) { + d->m_face = face; + emit cubeMapFaceChanged(); + } +} + +/*! + Triggers an update of the data functor that is sent to the backend. + */ +void QAbstractTextureImage::update() +{ + Q_D(QAbstractTextureImage); + if (d->m_changeArbiter != Q_NULLPTR) { + QScenePropertyChangePtr change(new QScenePropertyChange(NodeUpdated, QSceneChange::Node, id())); + change->setPropertyName("dataFunctor"); + change->setValue(QVariant::fromValue(dataFunctor())); + d->notifyObservers(change); + } +} + +/*! + Copies \a ref into this object. + */ +void QAbstractTextureImage::copy(const QNode *ref) +{ + const QAbstractTextureImage *imageRef = static_cast<const QAbstractTextureImage *>(ref); + d_func()->m_face = imageRef->cubeMapFace(); + d_func()->m_layer = imageRef->layer(); + d_func()->m_mipmapLevel = imageRef->mipmapLevel(); +} + +/*! \internal */ +QAbstractTextureImage::QAbstractTextureImage(QAbstractTextureImagePrivate &dd, QNode *parent) + : QNode(dd, parent) +{ +} + +} // namespace Qt3DRender + +QT_END_NAMESPACE diff --git a/src/render/texture/qabstracttextureimage.h b/src/render/texture/qabstracttextureimage.h new file mode 100644 index 000000000..24efd2508 --- /dev/null +++ b/src/render/texture/qabstracttextureimage.h @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT3DRENDER_QABSTRACTTEXTUREIMAGE_H +#define QT3DRENDER_QABSTRACTTEXTUREIMAGE_H + +#include <Qt3DCore/qabstractfunctor.h> +#include <Qt3DRenderer/qabstracttextureprovider.h> + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { + +// TO DO TexImageDataPtr -> QImageDataPtr + d_ptr +// We might also get rid of the layer, face, mipmap level from +// TexImageDataPtr and store that in the functor directly +// or use the QTextureImage instead +class QT3DRENDERERSHARED_EXPORT QTextureDataFunctor : public Qt3D::QAbstractFunctor +{ +public: + virtual ~QTextureDataFunctor() {} + virtual TexImageDataPtr operator()() = 0; + virtual bool operator ==(const QTextureDataFunctor &other) const = 0; +}; + +typedef QSharedPointer<QTextureDataFunctor> QTextureDataFunctorPtr; + +class QAbstractTextureImagePrivate; + +class QT3DRENDERERSHARED_EXPORT QAbstractTextureImage : public Qt3D::QNode +{ + Q_OBJECT + Q_PROPERTY(int mipmapLevel READ mipmapLevel WRITE setMipmapLevel NOTIFY mipmapLevelChanged) + Q_PROPERTY(int layer READ layer WRITE setLayer NOTIFY layerChanged) + Q_PROPERTY(Qt3DRender::QAbstractTextureProvider::CubeMapFace cubeMapFace READ cubeMapFace WRITE setCubeMapFace NOTIFY cubeMapFaceChanged) +public: + explicit QAbstractTextureImage(Qt3D::QNode *parent = 0); + virtual ~QAbstractTextureImage(); + + int mipmapLevel() const; + int layer() const; + QAbstractTextureProvider::CubeMapFace cubeMapFace() const; + + void setMipmapLevel(int level); + void setLayer(int layer); + void setCubeMapFace(QAbstractTextureProvider::CubeMapFace face); + + void update(); + virtual QTextureDataFunctorPtr dataFunctor() const = 0; + +Q_SIGNALS: + void mipmapLevelChanged(); + void layerChanged(); + void cubeMapFaceChanged(); + +protected: + void copy(const Qt3D::QNode *ref) Q_DECL_OVERRIDE; + QAbstractTextureImage(QAbstractTextureImagePrivate &dd, Qt3D::QNode *parent = 0); + +private: + Q_DECLARE_PRIVATE(QAbstractTextureImage) +}; + +} // namespace Qt3DRender + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(Qt3DRender::QTextureDataFunctorPtr) + +#endif // QT3DRENDER_QABSTRACTTEXTUREIMAGE_H diff --git a/src/render/texture/qabstracttextureimage_p.h b/src/render/texture/qabstracttextureimage_p.h new file mode 100644 index 000000000..a56cd7573 --- /dev/null +++ b/src/render/texture/qabstracttextureimage_p.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT3DRENDER_QABSTRACTTEXTUREIMAGE_P_H +#define QT3DRENDER_QABSTRACTTEXTUREIMAGE_P_H + +#include <Qt3DCore/private/qnode_p.h> +#include <Qt3DRenderer/private/qt3drenderer_global_p.h> +#include <Qt3DRenderer/qabstracttextureprovider.h> + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { + +class QAbstractTextureImage; + +class QT3DRENDERERSHARED_PRIVATE_EXPORT QAbstractTextureImagePrivate : public Qt3D::QNodePrivate +{ +public: + QAbstractTextureImagePrivate() + : QNodePrivate() + , m_mipmapLevel(0) + , m_layer(0) + , m_face(QAbstractTextureProvider::CubeMapPositiveX) + { + } + + Q_DECLARE_PUBLIC(QAbstractTextureImage) + + int m_mipmapLevel; + int m_layer; + QAbstractTextureProvider::CubeMapFace m_face; +}; + +} // namespace Qt3DRender + +QT_END_NAMESPACE + +#endif // QT3DRENDER_QABSTRACTTEXTUREIMAGE_P_H + diff --git a/src/render/texture/qabstracttextureprovider.cpp b/src/render/texture/qabstracttextureprovider.cpp new file mode 100644 index 000000000..34259b511 --- /dev/null +++ b/src/render/texture/qabstracttextureprovider.cpp @@ -0,0 +1,535 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qabstracttextureprovider.h" +#include "qabstracttextureprovider_p.h" +#include <Qt3DCore/qscenepropertychange.h> +#include <Qt3DRenderer/qabstracttextureimage.h> + +QT_BEGIN_NAMESPACE + +using namespace Qt3D; + +namespace Qt3DRender { + +/*! + \class Qt3DRender::QAbstractTextureProviderPrivate + \internal +*/ +QAbstractTextureProviderPrivate::QAbstractTextureProviderPrivate() + : QNodePrivate() + , m_target(QAbstractTextureProvider::Target2D) + , m_format(QAbstractTextureProvider::Automatic) + , m_width(1) + , m_height(1) + , m_depth(1) + , m_autoMipMap(false) + , m_minFilter(QAbstractTextureProvider::Nearest) + , m_magFilter(QAbstractTextureProvider::Nearest) + , m_status(QAbstractTextureProvider::Loading) + , m_maximumAnisotropy(1.0f) + , m_comparisonFunction(QAbstractTextureProvider::CompareLessEqual) + , m_comparisonMode(QAbstractTextureProvider::CompareNone) + , m_maximumLayers(1) + , m_unique(false) +{ +} + +void QAbstractTextureProvider::copy(const QNode *ref) +{ + QNode::copy(ref); + const QAbstractTextureProvider *t = static_cast<const QAbstractTextureProvider*>(ref); + d_func()->m_target = t->d_func()->m_target; + d_func()->m_width = t->d_func()->m_width; + d_func()->m_height = t->d_func()->m_height; + d_func()->m_depth = t->d_func()->m_depth; + d_func()->m_format = t->d_func()->m_format; + d_func()->m_wrapMode.setX(t->d_func()->m_wrapMode.x()); + d_func()->m_wrapMode.setY(t->d_func()->m_wrapMode.y()); + d_func()->m_wrapMode.setZ(t->d_func()->m_wrapMode.z()); + d_func()->m_minFilter = t->d_func()->m_minFilter; + d_func()->m_magFilter = t->d_func()->m_magFilter; + d_func()->m_autoMipMap = t->d_func()->m_autoMipMap; + d_func()->m_maximumAnisotropy = t->d_func()->m_maximumAnisotropy; + d_func()->m_comparisonFunction = t->d_func()->m_comparisonFunction; + d_func()->m_comparisonMode = t->d_func()->m_comparisonMode; + d_func()->m_maximumLayers = t->d_func()->m_maximumLayers; +} + +/*! + \class Qt3DRender::QAbstractTextureProvider + \inmodule Qt3DRender + \since 5.5 + \brief A base class to be used to provide textures. + + Qt3DRender::QAbstractTextureProvider shouldn't be used directly but rather + through one of its subclasses. Each subclass implements a given texture + target (2D, 2DArray, 3D, CubeMap ...) Each subclass provides a set of + functors for each layer, cube map face and mipmap level. In turn the + backend uses those functor to properly fill a corresponding OpenGL texture + with data. + */ + + +QAbstractTextureProvider::QAbstractTextureProvider(QNode *parent) + : QNode(*new QAbstractTextureProviderPrivate, parent) +{ +} + +QAbstractTextureProvider::QAbstractTextureProvider(Target target, QNode *parent) + : QNode(*new QAbstractTextureProviderPrivate, parent) +{ + d_func()->m_target = target; +} + +/*! \internal */ +QAbstractTextureProvider::QAbstractTextureProvider(QAbstractTextureProviderPrivate &dd, QNode *parent) + : QNode(dd, parent) +{ +} + +QAbstractTextureProvider::~QAbstractTextureProvider() +{ + // The subclasses of QAbstractTextureProvider are only there to set the type on a QTextureProvider + // QNode::cleanup needs to be handled here and not in the subclasses. + QNode::cleanup(); +} + +/*! + Sets the size of the texture provider to width \a w, height \a h and depth \a d. + */ +void QAbstractTextureProvider::setSize(int w, int h, int d) +{ + setWidth(w); + setHeight(h); + setDepth(d); +} + +/*! + \property Qt3DRender::QAbstractTextureProvider::width + + Holds the width of the texture provider. + */ +void QAbstractTextureProvider::setWidth(int width) +{ + Q_D(QAbstractTextureProvider); + if (d->m_width != width) { + d->m_width = width; + emit widthChanged(); + } +} + +/*! + \property Qt3DRender::QAbstractTextureProvider::height + + Holds the height of the texture provider. + */ +void QAbstractTextureProvider::setHeight(int height) +{ + Q_D(QAbstractTextureProvider); + if (d->m_height != height) { + d->m_height = height; + emit heightChanged(); + } +} + +/*! + \property Qt3DRender::QAbstractTextureProvider::depth + + Holds the depth of the texture provider. + */ +void QAbstractTextureProvider::setDepth(int depth) +{ + Q_D(QAbstractTextureProvider); + if (d->m_depth != depth) { + d->m_depth = depth; + emit depthChanged(); + } +} + +int QAbstractTextureProvider::width() const +{ + Q_D(const QAbstractTextureProvider); + return d->m_width; +} + +int QAbstractTextureProvider::height() const +{ + Q_D(const QAbstractTextureProvider); + return d->m_height; +} + +int QAbstractTextureProvider::depth() const +{ + Q_D(const QAbstractTextureProvider); + return d->m_depth; +} + +/*! + \property Qt3DRender::QAbstractTextureProvider::maximumLayers + + Holds the maximum layer count of the texture provider. By default, the + maximum layer count is 1. + + \note this has a meaning only for texture providers that have 3D or + array target formats. + */ +void QAbstractTextureProvider::setMaximumLayers(int maximumLayers) +{ + Q_D(QAbstractTextureProvider); + if (d->m_maximumLayers != maximumLayers) { + d->m_maximumLayers = maximumLayers; + emit maximumLayersChanged(); + } +} + +/*! + Returns the maximum number of layers for the texture provider. + + \note this has a meaning only for texture providers that have 3D or + array target formats. + */ +int QAbstractTextureProvider::maximumLayers() const +{ + Q_D(const QAbstractTextureProvider); + return d->m_maximumLayers; +} + +/*! + \property Qt3DRender::QAbstractTextureProvider::unique + + Sets whether this texture provider should be unique by reading \a unique. + By default this is false. + + By default the renderer based on the attributes of texture providers is + able to compare them and detect duplicates (same size, format and image + sources) and smartly avoid unnecessary computations. In some cases however + (texture providers used as Qt3D::RenderTarget attachments) you don't want + the renderer to perform these comparison, in which case you can set is + unique to true. + */ +void QAbstractTextureProvider::setUnique(bool unique) +{ + Q_D(QAbstractTextureProvider); + if (d->m_unique != unique) { + d->m_unique = unique; + emit uniqueChanged(); + } +} + +/*! + Returns whether the texture should be shared with other textures in the + renderer or not. Defaults to false as this allow in most cases the renderer + to be faster. + */ +bool QAbstractTextureProvider::isUnique() const +{ + Q_D(const QAbstractTextureProvider); + return d->m_unique; +} + +/*! + \property Qt3DRender::QAbstractTextureProvider::format + + Holds the format of the texture provider. + */ +void QAbstractTextureProvider::setFormat(TextureFormat format) +{ + Q_D(QAbstractTextureProvider); + if (d->m_format != format) { + d->m_format = format; + emit formatChanged(); + } +} + +/*! + Return the texture provider's format. + */ +QAbstractTextureProvider::TextureFormat QAbstractTextureProvider::format() const +{ + Q_D(const QAbstractTextureProvider); + return d->m_format; +} + +/*! + \property Qt3DRender::QAbstractTextureProvider::status readonly + + Holds the current status of the texture provider. + */ +void QAbstractTextureProvider::setStatus(Status status) +{ + Q_D(QAbstractTextureProvider); + if (status != d->m_status) { + d->m_status = status; + emit statusChanged(); + } +} + +QAbstractTextureProvider::Status QAbstractTextureProvider::status() const +{ + Q_D(const QAbstractTextureProvider); + return d->m_status; +} + +/*! + \property Qt3DRender::QAbstractTextureProvider::target readonly + + Holds the target format of the texture provider. + + \note The target format can only be set once. + */ +QAbstractTextureProvider::Target QAbstractTextureProvider::target() const +{ + Q_D(const QAbstractTextureProvider); + return d->m_target; +} + +/*! + Adds a new Qt3D::QAbstractTextureImage \a textureImage to the texture provider. + + \note Qt3D::QAbstractTextureImage should never be shared between multiple + Qt3DRender::QAbstractTextureProvider instances. + */ +void QAbstractTextureProvider::addTextureImage(QAbstractTextureImage *textureImage) +{ + Q_D(QAbstractTextureProvider); + if (!d->m_textureImages.contains(textureImage)) { + d->m_textureImages.append(textureImage); + + + if (textureImage->parent() && textureImage->parent() != this) + qWarning() << "A QAbstractTextureImage was shared, expect a crash, undefined behavior at best"; + // We need to add it as a child of the current node if it has been declared inline + // Or not previously added as a child of the current node so that + // 1) The backend gets notified about it's creation + // 2) When the current node is destroyed, it gets destroyed as well + if (!textureImage->parent()) + textureImage->setParent(this); + + if (d->m_changeArbiter != Q_NULLPTR) { + QScenePropertyChangePtr change(new QScenePropertyChange(NodeAdded, QSceneChange::Node, id())); + change->setPropertyName("textureImage"); + change->setValue(QVariant::fromValue(textureImage->id())); + d->notifyObservers(change); + } + } +} + +/*! + Removes a Qt3D::QAbstractTextureImage \a textureImage from the texture provider. + */ +void QAbstractTextureProvider::removeTextureImage(QAbstractTextureImage *textureImage) +{ + Q_D(QAbstractTextureProvider); + if (d->m_changeArbiter != Q_NULLPTR) { + QScenePropertyChangePtr change(new QScenePropertyChange(NodeRemoved, QSceneChange::Node, id())); + change->setPropertyName("textureImage"); + change->setValue(QVariant::fromValue(textureImage->id())); + d->notifyObservers(change); + } + d->m_textureImages.removeOne(textureImage); +} + +/*! + Returns a list of pointers to QAbstractTextureImage objects contained in + the texture provider. + */ +QList<QAbstractTextureImage *> QAbstractTextureProvider::textureImages() const +{ + Q_D(const QAbstractTextureProvider); + return d->m_textureImages; +} + +/*! + \property Qt3DRender::QAbstractTextureProvider::generateMipMaps + + Holds whether the texture provider should auto generate mipmaps. + */ +void QAbstractTextureProvider::setGenerateMipMaps(bool gen) +{ + Q_D(QAbstractTextureProvider); + if (d->m_autoMipMap != gen) { + d->m_autoMipMap = gen; + emit generateMipMapsChanged(); + } +} + +bool QAbstractTextureProvider::generateMipMaps() const +{ + Q_D(const QAbstractTextureProvider); + return d->m_autoMipMap; +} + +/*! + \property Qt3DRender::QAbstractTextureProvider::minificationFilter + + Holds the minification filter of the texture provider. + */ +void QAbstractTextureProvider::setMinificationFilter(Filter f) +{ + Q_D(QAbstractTextureProvider); + if (d->m_minFilter != f) { + d->m_minFilter = f; + emit minificationFilterChanged(); + } +} + +/*! + \property Qt3DRender::QAbstractTextureProvider::magnificationFilter + + Holds the magnification filter of the texture provider. + */ +void QAbstractTextureProvider::setMagnificationFilter(Filter f) +{ + Q_D(QAbstractTextureProvider); + if (d->m_magFilter != f) { + d->m_magFilter = f; + emit magnificationFilterChanged(); + } +} + +QAbstractTextureProvider::Filter QAbstractTextureProvider::minificationFilter() const +{ + Q_D(const QAbstractTextureProvider); + return d->m_minFilter; +} + +QAbstractTextureProvider::Filter QAbstractTextureProvider::magnificationFilter() const +{ + Q_D(const QAbstractTextureProvider); + return d->m_magFilter; +} + +/*! + \property Qt3DRender::QAbstractTextureProvider::wrapMode + + Holds the wrap mode of the texture provider. + */ +void QAbstractTextureProvider::setWrapMode(const QTextureWrapMode &wrapMode) +{ + Q_D(QAbstractTextureProvider); + if (d->m_wrapMode.x() != wrapMode.x()) { + d->m_wrapMode.setX(wrapMode.x()); + QScenePropertyChangePtr e(new QScenePropertyChange(NodeUpdated, QSceneChange::Node, id())); + e->setPropertyName("wrapModeX"); + e->setValue(static_cast<int>(d->m_wrapMode.x())); + d->notifyObservers(e); + } + if (d->m_wrapMode.y() != wrapMode.y()) { + d->m_wrapMode.setY(wrapMode.y()); + QScenePropertyChangePtr e(new QScenePropertyChange(NodeUpdated, QSceneChange::Node, id())); + e->setPropertyName("wrapModeY"); + e->setValue(static_cast<int>(d->m_wrapMode.y())); + d->notifyObservers(e); + } + if (d->m_wrapMode.z() != wrapMode.z()) { + d->m_wrapMode.setZ(wrapMode.z()); + QScenePropertyChangePtr e(new QScenePropertyChange(NodeUpdated, QSceneChange::Node, id())); + e->setPropertyName("wrapModeZ"); + e->setValue(static_cast<int>(d->m_wrapMode.z())); + d->notifyObservers(e); + } +} + +QTextureWrapMode *QAbstractTextureProvider::wrapMode() +{ + Q_D(QAbstractTextureProvider); + return &d->m_wrapMode; +} + +/*! + \property Qt3DRender::QAbstractTextureProvider::maximumAnisotropy + + Holds the maximum anisotropy of the texture provider. + */ +void QAbstractTextureProvider::setMaximumAnisotropy(float anisotropy) +{ + Q_D(QAbstractTextureProvider); + if (!qFuzzyCompare(d->m_maximumAnisotropy, anisotropy)) { + d->m_maximumAnisotropy = anisotropy; + emit maximumAnisotropyChanged(); + } +} + +float QAbstractTextureProvider::maximumAnisotropy() const +{ + Q_D(const QAbstractTextureProvider); + return d->m_maximumAnisotropy; +} + +/*! + \property Qt3DRender::QAbstractTextureProvider::comparisonFunction + + Holds the comparison function of the texture provider. + */ +void QAbstractTextureProvider::setComparisonFunction(QAbstractTextureProvider::ComparisonFunction function) +{ + Q_D(QAbstractTextureProvider); + if (d->m_comparisonFunction != function) { + d->m_comparisonFunction = function; + emit comparisonFunctionChanged(); + } +} + +QAbstractTextureProvider::ComparisonFunction QAbstractTextureProvider::comparisonFunction() const +{ + Q_D(const QAbstractTextureProvider); + return d->m_comparisonFunction; +} + +/*! + \property Qt3DRender::QAbstractTextureProvider::comparisonMode + + Holds the comparison mode of the texture provider. + */ +void QAbstractTextureProvider::setComparisonMode(QAbstractTextureProvider::ComparisonMode mode) +{ + Q_D(QAbstractTextureProvider); + if (d->m_comparisonMode != mode) { + d->m_comparisonMode = mode; + emit comparisonModeChanged(); + } +} + +QAbstractTextureProvider::ComparisonMode QAbstractTextureProvider::comparisonMode() const +{ + Q_D(const QAbstractTextureProvider); + return d->m_comparisonMode; +} + +} // namespace Qt3DRender + +QT_END_NAMESPACE diff --git a/src/render/texture/qabstracttextureprovider.h b/src/render/texture/qabstracttextureprovider.h new file mode 100644 index 000000000..4a8e3adde --- /dev/null +++ b/src/render/texture/qabstracttextureprovider.h @@ -0,0 +1,344 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT3DRENDER_QABSTRACTTEXTUREPROVIDER_H +#define QT3DRENDER_QABSTRACTTEXTUREPROVIDER_H + +#include <Qt3DRenderer/texturedata.h> +#include <Qt3DRenderer/qt3drenderer_global.h> +#include <Qt3DCore/qnode.h> + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { + +class QAbstractTextureProviderPrivate; +class QTextureWrapMode; +class QAbstractTextureImage; + +class QT3DRENDERERSHARED_EXPORT QAbstractTextureProvider : public Qt3D::QNode +{ + Q_OBJECT + Q_PROPERTY(Target target READ target CONSTANT) + Q_PROPERTY(TextureFormat format READ format WRITE setFormat NOTIFY formatChanged) + Q_PROPERTY(bool generateMipMaps READ generateMipMaps WRITE setGenerateMipMaps NOTIFY generateMipMapsChanged) + Q_PROPERTY(Qt3DRender::QTextureWrapMode *wrapMode READ wrapMode CONSTANT) + Q_PROPERTY(Status status READ status NOTIFY statusChanged) + Q_PROPERTY(int width READ width WRITE setWidth NOTIFY widthChanged) + Q_PROPERTY(int height READ height WRITE setHeight NOTIFY heightChanged) + Q_PROPERTY(int depth READ depth WRITE setDepth NOTIFY depthChanged) + Q_PROPERTY(Filter magnificationFilter READ magnificationFilter WRITE setMagnificationFilter NOTIFY magnificationFilterChanged) + Q_PROPERTY(Filter minificationFilter READ minificationFilter WRITE setMinificationFilter NOTIFY minificationFilterChanged) + Q_PROPERTY(float maximumAnisotropy READ maximumAnisotropy WRITE setMaximumAnisotropy NOTIFY maximumAnisotropyChanged) + Q_PROPERTY(ComparisonFunction comparisonFunction READ comparisonFunction WRITE setComparisonFunction NOTIFY comparisonFunctionChanged) + Q_PROPERTY(ComparisonMode comparisonMode READ comparisonMode WRITE setComparisonMode NOTIFY comparisonModeChanged) + Q_PROPERTY(int maximumLayers READ maximumLayers WRITE setMaximumLayers NOTIFY maximumLayersChanged) + Q_PROPERTY(bool unique READ isUnique WRITE setUnique NOTIFY uniqueChanged) + +public: + + enum Status { + Loading = 0, + Loaded, + Error + }; + Q_ENUM(Status) + + enum Target { + Target1D = 0x0DE0, // GL_TEXTURE_1D + Target1DArray = 0x8C18, // GL_TEXTURE_1D_ARRAY + Target2D = 0x0DE1, // GL_TEXTURE_2D + Target2DArray = 0x8C1A, // GL_TEXTURE_2D_ARRAY + Target3D = 0x806F, // GL_TEXTURE_3D + TargetCubeMap = 0x8513, // GL_TEXTURE_CUBE_MAP + TargetCubeMapArray = 0x9009, // GL_TEXTURE_CUBE_MAP_ARRAY + Target2DMultisample = 0x9100, // GL_TEXTURE_2D_MULTISAMPLE + Target2DMultisampleArray = 0x9102, // GL_TEXTURE_2D_MULTISAMPLE_ARRAY + TargetRectangle = 0x84F5, // GL_TEXTURE_RECTANGLE + TargetBuffer = 0x8C2A // GL_TEXTURE_BUFFER + }; + Q_ENUM(Target) + + enum TextureFormat { + NoFormat = 0, // GL_NONE + Automatic = 1, // The Qt3D engine automatically determines the best format + + // Unsigned normalized formats + R8_UNorm = 0x8229, // GL_R8 + RG8_UNorm = 0x822B, // GL_RG8 + RGB8_UNorm = 0x8051, // GL_RGB8 + RGBA8_UNorm = 0x8058, // GL_RGBA8 + + R16_UNorm = 0x822A, // GL_R16 + RG16_UNorm = 0x822C, // GL_RG16 + RGB16_UNorm = 0x8054, // GL_RGB16 + RGBA16_UNorm = 0x805B, // GL_RGBA16 + + // Signed normalized formats + R8_SNorm = 0x8F94, // GL_R8_SNORM + RG8_SNorm = 0x8F95, // GL_RG8_SNORM + RGB8_SNorm = 0x8F96, // GL_RGB8_SNORM + RGBA8_SNorm = 0x8F97, // GL_RGBA8_SNORM + + R16_SNorm = 0x8F98, // GL_R16_SNORM + RG16_SNorm = 0x8F99, // GL_RG16_SNORM + RGB16_SNorm = 0x8F9A, // GL_RGB16_SNORM + RGBA16_SNorm = 0x8F9B, // GL_RGBA16_SNORM + + // Unsigned integer formats + R8U = 0x8232, // GL_R8UI + RG8U = 0x8238, // GL_RG8UI + RGB8U = 0x8D7D, // GL_RGB8UI + RGBA8U = 0x8D7C, // GL_RGBA8UI + + R16U = 0x8234, // GL_R16UI + RG16U = 0x823A, // GL_RG16UI + RGB16U = 0x8D77, // GL_RGB16UI + RGBA16U = 0x8D76, // GL_RGBA16UI + + R32U = 0x8236, // GL_R32UI + RG32U = 0x823C, // GL_RG32UI + RGB32U = 0x8D71, // GL_RGB32UI + RGBA32U = 0x8D70, // GL_RGBA32UI + + // Signed integer formats + R8I = 0x8231, // GL_R8I + RG8I = 0x8237, // GL_RG8I + RGB8I = 0x8D8F, // GL_RGB8I + RGBA8I = 0x8D8E, // GL_RGBA8I + + R16I = 0x8233, // GL_R16I + RG16I = 0x8239, // GL_RG16I + RGB16I = 0x8D89, // GL_RGB16I + RGBA16I = 0x8D88, // GL_RGBA16I + + R32I = 0x8235, // GL_R32I + RG32I = 0x823B, // GL_RG32I + RGB32I = 0x8D83, // GL_RGB32I + RGBA32I = 0x8D82, // GL_RGBA32I + + // Floating point formats + R16F = 0x822D, // GL_R16F + RG16F = 0x822F, // GL_RG16F + RGB16F = 0x881B, // GL_RGB16F + RGBA16F = 0x881A, // GL_RGBA16F + + R32F = 0x822E, // GL_R32F + RG32F = 0x8230, // GL_RG32F + RGB32F = 0x8815, // GL_RGB32F + RGBA32F = 0x8814, // GL_RGBA32F + + // Packed formats + RGB9E5 = 0x8C3D, // GL_RGB9_E5 + RG11B10F = 0x8C3A, // GL_R11F_G11F_B10F + RG3B2 = 0x2A10, // GL_R3_G3_B2 + R5G6B5 = 0x8D62, // GL_RGB565 + RGB5A1 = 0x8057, // GL_RGB5_A1 + RGBA4 = 0x8056, // GL_RGBA4 + RGB10A2 = 0x906F, // GL_RGB10_A2UI + + // Depth formats + D16 = 0x81A5, // GL_DEPTH_COMPONENT16 + D24 = 0x81A6, // GL_DEPTH_COMPONENT24 + D24S8 = 0x88F0, // GL_DEPTH24_STENCIL8 + D32 = 0x81A7, // GL_DEPTH_COMPONENT32 + D32F = 0x8CAC, // GL_DEPTH_COMPONENT32F + D32FS8X24 = 0x8CAD, // GL_DEPTH32F_STENCIL8 + + // Compressed formats + RGB_DXT1 = 0x83F0, // GL_COMPRESSED_RGB_S3TC_DXT1_EXT + RGBA_DXT1 = 0x83F1, // GL_COMPRESSED_RGBA_S3TC_DXT1_EXT + RGBA_DXT3 = 0x83F2, // GL_COMPRESSED_RGBA_S3TC_DXT3_EXT + RGBA_DXT5 = 0x83F3, // GL_COMPRESSED_RGBA_S3TC_DXT5_EXT + R_ATI1N_UNorm = 0x8DBB, // GL_COMPRESSED_RED_RGTC1 + R_ATI1N_SNorm = 0x8DBC, // GL_COMPRESSED_SIGNED_RED_RGTC1 + RG_ATI2N_UNorm = 0x8DBD, // GL_COMPRESSED_RG_RGTC2 + RG_ATI2N_SNorm = 0x8DBE, // GL_COMPRESSED_SIGNED_RG_RGTC2 + RGB_BP_UNSIGNED_FLOAT = 0x8E8F, // GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB + RGB_BP_SIGNED_FLOAT = 0x8E8E, // GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB + RGB_BP_UNorm = 0x8E8C, // GL_COMPRESSED_RGBA_BPTC_UNORM_ARB + R11_EAC_UNorm = 0x9270, // GL_COMPRESSED_R11_EAC + R11_EAC_SNorm = 0x9271, // GL_COMPRESSED_SIGNED_R11_EAC + RG11_EAC_UNorm = 0x9272, // GL_COMPRESSED_RG11_EAC + RG11_EAC_SNorm = 0x9273, // GL_COMPRESSED_SIGNED_RG11_EAC + RGB8_ETC2 = 0x9274, // GL_COMPRESSED_RGB8_ETC2 + SRGB8_ETC2 = 0x9275, // GL_COMPRESSED_SRGB8_ETC2 + RGB8_PunchThrough_Alpha1_ETC2 = 0x9276, // GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 + SRGB8_PunchThrough_Alpha1_ETC2 = 0x9277, // GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 + RGBA8_ETC2_EAC = 0x9278, // GL_COMPRESSED_RGBA8_ETC2_EAC + SRGB8_Alpha8_ETC2_EAC = 0x9279, // GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC + RGB8_ETC1 = 0x8D64, // GL_ETC1_RGB8_OES + + // sRGB formats + SRGB8 = 0x8C41, // GL_SRGB8 + SRGB8_Alpha8 = 0x8C43, // GL_SRGB8_ALPHA8 + SRGB_DXT1 = 0x8C4C, // GL_COMPRESSED_SRGB_S3TC_DXT1_EXT + SRGB_Alpha_DXT1 = 0x8C4D, // GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT + SRGB_Alpha_DXT3 = 0x8C4E, // GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT + SRGB_Alpha_DXT5 = 0x8C4F, // GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT + SRGB_BP_UNorm = 0x8E8D, // GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB + + // ES 2 formats + DepthFormat = 0x1902, // GL_DEPTH_COMPONENT + AlphaFormat = 0x1906, // GL_ALPHA + RGBFormat = 0x1907, // GL_RGB + RGBAFormat = 0x1908, // GL_RGBA + LuminanceFormat = 0x1909, // GL_LUMINANCE + LuminanceAlphaFormat = 0x190A + }; + Q_ENUM(TextureFormat) + + enum Filter { + Nearest = 0x2600, // GL_NEAREST + Linear = 0x2601, // GL_LINEAR + NearestMipMapNearest = 0x2700, // GL_NEAREST_MIPMAP_NEAREST + NearestMipMapLinear = 0x2702, // GL_NEAREST_MIPMAP_LINEAR + LinearMipMapNearest = 0x2701, // GL_LINEAR_MIPMAP_NEAREST + LinearMipMapLinear = 0x2703 // GL_LINEAR_MIPMAP_LINEAR + }; + Q_ENUM(Filter) + + enum CubeMapFace { + CubeMapPositiveX = 0x8515, // GL_TEXTURE_CUBE_MAP_POSITIVE_X + CubeMapNegativeX = 0x8516, // GL_TEXTURE_CUBE_MAP_NEGATIVE_X + CubeMapPositiveY = 0x8517, // GL_TEXTURE_CUBE_MAP_POSITIVE_Y + CubeMapNegativeY = 0x8518, // GL_TEXTURE_CUBE_MAP_NEGATIVE_Y + CubeMapPositiveZ = 0x8519, // GL_TEXTURE_CUBE_MAP_POSITIVE_Z + CubeMapNegativeZ = 0x851A // GL_TEXTURE_CUBE_MAP_NEGATIVE_Z + }; + Q_ENUM(CubeMapFace) + + enum ComparisonFunction { + CompareLessEqual = 0x0203, // GL_LEQUAL + CompareGreaterEqual = 0x0206, // GL_GEQUAL + CompareLess = 0x0201, // GL_LESS + CompareGreater = 0x0204, // GL_GREATER + CompareEqual = 0x0202, // GL_EQUAL + CommpareNotEqual = 0x0205, // GL_NOTEQUAL + CompareAlways = 0x0207, // GL_ALWAYS + CompareNever = 0x0200 // GL_NEVER + }; + Q_ENUM(ComparisonFunction) + + enum ComparisonMode { + CompareRefToTexture = 0x884E, // GL_COMPARE_REF_TO_TEXTURE + CompareNone = 0x0000 // GL_NONE + }; + Q_ENUM(ComparisonMode) + + ~QAbstractTextureProvider(); + + Target target() const; + + void setFormat(TextureFormat format); + TextureFormat format() const; + + Status status() const; + + void addTextureImage(QAbstractTextureImage *textureImage); + void removeTextureImage(QAbstractTextureImage *textureImage); + QList<QAbstractTextureImage *> textureImages() const; + + void setGenerateMipMaps(bool gen); + bool generateMipMaps() const; + + // sampler data - in the future proxy to a Sampler helper + void setMinificationFilter(Filter f); + void setMagnificationFilter(Filter f); + + Filter minificationFilter() const; + Filter magnificationFilter() const; + + void setWrapMode(const QTextureWrapMode &wrapMode); + QTextureWrapMode *wrapMode(); + + void setMaximumAnisotropy(float anisotropy); + float maximumAnisotropy() const; + + void setComparisonFunction(ComparisonFunction function); + ComparisonFunction comparisonFunction() const; + + void setComparisonMode(ComparisonMode mode); + ComparisonMode comparisonMode() const; + + void setSize(int width, int height=1, int depth=1); + + void setWidth(int width); + void setHeight(int height); + void setDepth(int depth); + + int width() const; + int height() const; + int depth() const; + + void setMaximumLayers(int maximumLayers); + int maximumLayers() const; + + void setUnique(bool unique); + bool isUnique() const; + +Q_SIGNALS: + void formatChanged(); + void statusChanged(); + void generateMipMapsChanged(); + void widthChanged(); + void heightChanged(); + void depthChanged(); + void magnificationFilterChanged(); + void minificationFilterChanged(); + void maximumAnisotropyChanged(); + void comparisonFunctionChanged(); + void comparisonModeChanged(); + void maximumLayersChanged(); + void uniqueChanged(); + +protected: + explicit QAbstractTextureProvider(Qt3D::QNode *parent = 0); + explicit QAbstractTextureProvider(Target target, Qt3D::QNode *parent = 0); + QAbstractTextureProvider(QAbstractTextureProviderPrivate &dd, Qt3D::QNode *parent = 0); + void copy(const Qt3D::QNode *ref) Q_DECL_OVERRIDE; + void setStatus(Status status); + +private: + Q_DECLARE_PRIVATE(QAbstractTextureProvider) + QT3D_CLONEABLE(QAbstractTextureProvider) +}; + +} // namespace Qt3DRender + +QT_END_NAMESPACE + +#endif // QT3DRENDER_QABSTRACTTEXTUREPROVIDER_H diff --git a/src/render/texture/qabstracttextureprovider_p.h b/src/render/texture/qabstracttextureprovider_p.h new file mode 100644 index 000000000..c6516904c --- /dev/null +++ b/src/render/texture/qabstracttextureprovider_p.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT3DRENDER_QABSTRACTTEXTUREPROVIDER_P_H +#define QT3DRENDER_QABSTRACTTEXTUREPROVIDER_P_H + +#include <Qt3DRenderer/qt3drenderer_global.h> +#include <Qt3DCore/private/qnode_p.h> +#include <Qt3DRenderer/qabstracttextureprovider.h> +#include <Qt3DRenderer/qwrapmode.h> + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { + +class QAbstractTextureProviderPrivate : public Qt3D::QNodePrivate +{ +public : + QAbstractTextureProviderPrivate(); + + Q_DECLARE_PUBLIC(QAbstractTextureProvider) + + QAbstractTextureProvider::Target m_target; + QAbstractTextureProvider::TextureFormat m_format; + int m_width, m_height, m_depth; + bool m_autoMipMap; + + QList<TexImageDataPtr> m_data; + + QAbstractTextureProvider::Filter m_minFilter, m_magFilter; + // FIXME, store per direction + QTextureWrapMode m_wrapMode; + QAbstractTextureProvider::Status m_status; + float m_maximumAnisotropy; + QAbstractTextureProvider::ComparisonFunction m_comparisonFunction; + QAbstractTextureProvider::ComparisonMode m_comparisonMode; + QList<QAbstractTextureImage *> m_textureImages; + int m_maximumLayers; + bool m_unique; +}; + +} // QT3D + +QT_END_NAMESPACE + +#endif // QT3DRENDER_QABSTRACTTEXTUREPROVIDER_P_H + diff --git a/src/render/texture/qtexture.h b/src/render/texture/qtexture.h new file mode 100644 index 000000000..d794f5b08 --- /dev/null +++ b/src/render/texture/qtexture.h @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT3DRENDER_QTEXTURE_H +#define QT3DRENDER_QTEXTURE_H + +#include <QOpenGLTexture> +#include <Qt3DRenderer/texturedata.h> +#include <Qt3DRenderer/qwrapmode.h> +#include <Qt3DRenderer/qtextureproviders.h> +#include <Qt3DRenderer/qtextureimage.h> + +QT_BEGIN_NAMESPACE + +#if 0 +// Create a forwarding header +#pragma qt_class(QTexture) +#pragma qt_sync_stop_processing +#endif + +QT_END_NAMESPACE + +#endif // QT3DRENDER_QTEXTURE_H diff --git a/src/render/texture/qtextureimage.cpp b/src/render/texture/qtextureimage.cpp new file mode 100644 index 000000000..3d8a58b3e --- /dev/null +++ b/src/render/texture/qtextureimage.cpp @@ -0,0 +1,195 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qtextureimage.h" +#include "qabstracttextureimage_p.h" +#include <Qt3DCore/private/qurlhelper_p.h> + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { + +class QTextureImagePrivate: public QAbstractTextureImagePrivate +{ +public: + QTextureImagePrivate() + : QAbstractTextureImagePrivate() + { + } + + Q_DECLARE_PUBLIC(QTextureImage) + QUrl m_source; +}; + +class QImageTextureDataFunctor : public QTextureDataFunctor +{ +public: + QImageTextureDataFunctor(const QUrl &url) + : QTextureDataFunctor() + , m_url(url) + {} + + // Will be executed from within a QAspectJob + TexImageDataPtr operator ()() Q_DECL_FINAL + { + TexImageDataPtr dataPtr; + if (m_url.isLocalFile() || m_url.scheme() == QStringLiteral("qrc")) { + QString source = Qt3D::QUrlHelper::urlToLocalFileOrQrc(m_url); + dataPtr.reset(new TexImageData()); + if (dataPtr->setCompressedFile(source)) + return dataPtr; + QImage img; + if (img.load(source)) { + dataPtr->setImage(img); + return dataPtr; + } + dataPtr.reset(); + qWarning() << "Failed to load image : " << source; + } else { + qWarning() << "implement loading from remote URLs"; + } + return dataPtr; + } + + bool operator ==(const QTextureDataFunctor &other) const Q_DECL_FINAL + { + const QImageTextureDataFunctor *otherFunctor = functor_cast<QImageTextureDataFunctor>(&other); + return (otherFunctor != Q_NULLPTR && otherFunctor->m_url == m_url); + } + + QT3D_FUNCTOR(QImageTextureDataFunctor) + +private: + QUrl m_url; +}; + +/*! + \class QTextureImage + \inmodule Qt3DRenderer + \since 5.5 + \brief Encapsulates the necessary information to create an OpenGL texture + image from an image source. + + It contains the necessary information mipmap level, layer, cube face and + source URL to load at the proper place data into an OpenGL texture. + */ + +/*! + \qmltype TextureImage + \instantiates Qt3DRender::QTextureImage + \inherits AbstractTextureImage + \inqmlmodule Qt3D.Renderer + \since 5.5 + \brief Encapsulates the necessary information to create an OpenGL texture + image from an image source. +*/ + +/*! + Constructs a new Qt3DRender::QTextureImage instance with \a parent as parent. + */ +QTextureImage::QTextureImage(QNode *parent) + : QAbstractTextureImage(*new QTextureImagePrivate, parent) +{ +} + +/*! + The destructor. + */ +QTextureImage::~QTextureImage() +{ + QNode::cleanup(); +} + +/*! + Returns the source url from which data for the texture image will be loaded. + */ +QUrl QTextureImage::source() const +{ + Q_D(const QTextureImage); + return d->m_source; +} + +/*! + \property Qt3DRender::QTextureImage::source + + This property holdsthe source url from which data for the texture + image will be loaded. +*/ + +/*! + \qmlproperty url Qt3D.Renderer::TextureImage::source + + This property holdsthe source url from which data for the texture + image will be loaded. +*/ + +/*! + Sets the source url of the texture image to \a source. + \note This triggers a call to update() + */ +void QTextureImage::setSource(const QUrl &source) +{ + Q_D(QTextureImage); + if (source != d->m_source) { + d->m_source = source; + emit sourceChanged(); + update(); + } +} + +/*! + Returns the Qt3DRender::QTextureDataFunctorPtr functor to be used by the + backend to load the texture image data into an OpenGL texture object. + */ +QTextureDataFunctorPtr QTextureImage::dataFunctor() const +{ + return QTextureDataFunctorPtr(new QImageTextureDataFunctor(source())); +} + +/*! + Copies \ref into this texture image. + */ +void QTextureImage::copy(const QNode *ref) +{ + QAbstractTextureImage::copy(ref); + const QTextureImage *img = static_cast<const QTextureImage *>(ref); + d_func()->m_source = img->source(); +} + +} // namespace Qt3DRender + +QT_END_NAMESPACE + diff --git a/src/render/texture/qtextureimage.h b/src/render/texture/qtextureimage.h new file mode 100644 index 000000000..f77c2d47e --- /dev/null +++ b/src/render/texture/qtextureimage.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT3DRENDER_QTEXTUREIMAGE_H +#define QT3DRENDER_QTEXTUREIMAGE_H + +#include <QUrl> +#include <Qt3DRenderer/qabstracttextureimage.h> + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { + +class QTextureImagePrivate; + +class QT3DRENDERERSHARED_EXPORT QTextureImage : public QAbstractTextureImage +{ + Q_OBJECT + Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged) + +public: + explicit QTextureImage(Qt3D::QNode *parent = 0); + ~QTextureImage(); + + QUrl source() const; + void setSource(const QUrl &source); + + QTextureDataFunctorPtr dataFunctor() const Q_DECL_OVERRIDE; + +Q_SIGNALS: + void sourceChanged(); + +protected: + void copy(const Qt3D::QNode *ref) Q_DECL_OVERRIDE; + +private: + Q_DECLARE_PRIVATE(QTextureImage) + QT3D_CLONEABLE(QTextureImage) +}; + +} // namespace Qt3DRender + +QT_END_NAMESPACE + +#endif // QT3DRENDER_QTEXTUREIMAGE_H diff --git a/src/render/texture/qtextureproviders.cpp b/src/render/texture/qtextureproviders.cpp new file mode 100644 index 000000000..62c8f66c7 --- /dev/null +++ b/src/render/texture/qtextureproviders.cpp @@ -0,0 +1,258 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qtextureproviders.h" + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { + +/*! + \class Qt3DRender::QTexture1D + \inmodule Qt3DRenderer + \since 5.5 + \brief A QAbstractTextureProvider with a Target1D target format. + */ + +/*! + Constructs a new Qt3DRender::QTexture1D instance with \a parent as parent. + */ +QTexture1D::QTexture1D(QNode *parent) + : QAbstractTextureProvider(Target1D, parent) +{ +} + +QTexture1D::~QTexture1D() +{ +} + +/*! + \class Qt3DRender::QTexture1DArray + \inmodule Qt3DRenderer + \since 5.5 + \brief A QAbstractTextureProvider with a Target1DArray target format. + */ + +/*! + Constructs a new Qt3DRender::QTexture1DArray instance with \a parent as parent. + */ +QTexture1DArray::QTexture1DArray(QNode *parent) + : QAbstractTextureProvider(Target1DArray, parent) +{ +} + +QTexture1DArray::~QTexture1DArray() +{ +} + +/*! + \class Qt3DRender::QTexture2D + \inmodule Qt3DRenderer + \since 5.5 + \brief A QAbstractTextureProvider with a Target2D target format. + */ + +/*! + Constructs a new Qt3DRender::QTexture2D instance with \a parent as parent. + */ +QTexture2D::QTexture2D(QNode *parent) + : QAbstractTextureProvider(Target2D, parent) +{ +} + +QTexture2D::~QTexture2D() +{ +} + +/*! + \class Qt3DRender::QTexture2DArray + \inmodule Qt3DRenderer + \since 5.5 + \brief A QAbstractTextureProvider with a Target2DArray target format. + */ + +/*! + Constructs a new Qt3DRender::QTexture2DArray instance with \a parent as parent. + */ +QTexture2DArray::QTexture2DArray(QNode *parent) + : QAbstractTextureProvider(Target2DArray, parent) +{ +} + +QTexture2DArray::~QTexture2DArray() +{ +} + + +/*! + \class Qt3DRender::QTexture3D + \inmodule Qt3DRenderer + \since 5.5 + \brief A QAbstractTextureProvider with a Target3D target format. + */ + +/*! + Constructs a new Qt3DRender::QTexture3D instance with \a parent as parent. + */ +QTexture3D::QTexture3D(QNode *parent) + : QAbstractTextureProvider(Target2D, parent) +{ +} + +QTexture3D::~QTexture3D() +{ +} + +/*! + \class Qt3DRender::QTextureCubeMap + \inmodule Qt3DRenderer + \since 5.5 + \brief A QAbstractTextureProvider with a TargetCubeMap target format. + */ + +/*! + Constructs a new Qt3DRender::QTextureCubeMap instance with \a parent as parent. + */ +QTextureCubeMap::QTextureCubeMap(QNode *parent) + : QAbstractTextureProvider(TargetCubeMap, parent) +{ +} + +QTextureCubeMap::~QTextureCubeMap() +{ +} + +/*! + \class Qt3DRender::QTextureCubeMapArray + \inmodule Qt3DRenderer + \since 5.5 + \brief A QAbstractTextureProvider with a TargetCubeMapArray target format. + */ + +/*! + Constructs a new Qt3DRender::QTextureCubeMapArray instance with \a parent as parent. + */ +QTextureCubeMapArray::QTextureCubeMapArray(QNode *parent) + : QAbstractTextureProvider(TargetCubeMapArray, parent) +{ +} + +QTextureCubeMapArray::~QTextureCubeMapArray() +{ + QNode::cleanup(); +} + +/*! + \class Qt3DRender::QTexture2DMultisample + \inmodule Qt3DRenderer + \since 5.5 + \brief A QAbstractTextureProvider with a Target2DMultisample target format. + */ + +/*! + Constructs a new Qt3DRender::QTexture2DMultisample instance with \a parent as parent. + */ +QTexture2DMultisample::QTexture2DMultisample(QNode *parent) + : QAbstractTextureProvider(Target2DMultisample, parent) +{ +} + +QTexture2DMultisample::~QTexture2DMultisample() +{ +} + +/*! + \class Qt3DRender::QTexture2DMultisampleArray + \inmodule Qt3DRenderer + \since 5.5 + \brief A QAbstractTextureProvider with a Target2DMultisampleArray target format. + */ + +/*! + Constructs a new Qt3DRender::QTexture2DMultisampleArray instance with \a parent as parent. + */ +QTexture2DMultisampleArray::QTexture2DMultisampleArray(QNode *parent) + : QAbstractTextureProvider(Target2DMultisampleArray, parent) +{ +} + +QTexture2DMultisampleArray::~QTexture2DMultisampleArray() +{ +} + +/*! + \class Qt3DRender::QTextureRectangle + \inmodule Qt3DRenderer + \since 5.5 + \brief A QAbstractTextureProvider with a TargetRectangle target format. + */ + +/*! + Constructs a new Qt3DRender::QTextureRectangle instance with \a parent as parent. + */ +QTextureRectangle::QTextureRectangle(QNode *parent) + : QAbstractTextureProvider(TargetRectangle, parent) +{ +} + +QTextureRectangle::~QTextureRectangle() +{ +} + +/*! + \class Qt3DRender::QTextureBuffer + \inmodule Qt3DRenderer + \since 5.5 + \brief A QAbstractTextureProvider with a TargetBuffer target format. + */ + +/*! + Constructs a new Qt3DRender::QTextureBuffer instance with \a parent as parent. + */ +QTextureBuffer::QTextureBuffer(QNode *parent) + : QAbstractTextureProvider(TargetBuffer, parent) +{ +} + +QTextureBuffer::~QTextureBuffer() +{ +} + +} // namespace Qt3DRender + +QT_END_NAMESPACE + + diff --git a/src/render/texture/qtextureproviders.h b/src/render/texture/qtextureproviders.h new file mode 100644 index 000000000..dc54b7999 --- /dev/null +++ b/src/render/texture/qtextureproviders.h @@ -0,0 +1,138 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT3DRENDER_QTEXTUREPROVIDERS_H +#define QT3DRENDER_QTEXTUREPROVIDERS_H + +#include <Qt3DRenderer/qabstracttextureprovider.h> + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { + +class QT3DRENDERERSHARED_EXPORT QTexture1D : public QAbstractTextureProvider +{ + Q_OBJECT +public: + explicit QTexture1D(Qt3D::QNode *parent = 0); + ~QTexture1D(); +}; + +class QT3DRENDERERSHARED_EXPORT QTexture1DArray : public QAbstractTextureProvider +{ + Q_OBJECT +public: + explicit QTexture1DArray(Qt3D::QNode *parent = 0); + ~QTexture1DArray(); +}; + +class QT3DRENDERERSHARED_EXPORT QTexture2D : public QAbstractTextureProvider +{ + Q_OBJECT +public: + explicit QTexture2D(Qt3D::QNode *parent = 0); + ~QTexture2D(); +}; + +class QT3DRENDERERSHARED_EXPORT QTexture2DArray : public QAbstractTextureProvider +{ + Q_OBJECT +public: + explicit QTexture2DArray(Qt3D::QNode *parent = 0); + ~QTexture2DArray(); +}; + +class QT3DRENDERERSHARED_EXPORT QTexture3D : public QAbstractTextureProvider +{ + Q_OBJECT +public: + explicit QTexture3D(Qt3D::QNode *parent = 0); + ~QTexture3D(); +}; + +class QT3DRENDERERSHARED_EXPORT QTextureCubeMap : public QAbstractTextureProvider +{ + Q_OBJECT +public: + explicit QTextureCubeMap(Qt3D::QNode *parent = 0); + ~QTextureCubeMap(); +}; + +class QT3DRENDERERSHARED_EXPORT QTextureCubeMapArray : public QAbstractTextureProvider +{ + Q_OBJECT +public: + explicit QTextureCubeMapArray(Qt3D::QNode *parent = 0); + ~QTextureCubeMapArray(); +}; + +class QT3DRENDERERSHARED_EXPORT QTexture2DMultisample : public QAbstractTextureProvider +{ + Q_OBJECT +public: + explicit QTexture2DMultisample(Qt3D::QNode *parent = 0); + ~QTexture2DMultisample(); +}; + +class QT3DRENDERERSHARED_EXPORT QTexture2DMultisampleArray : public QAbstractTextureProvider +{ + Q_OBJECT +public: + explicit QTexture2DMultisampleArray(Qt3D::QNode *parent = 0); + ~QTexture2DMultisampleArray(); +}; + +class QT3DRENDERERSHARED_EXPORT QTextureRectangle : public QAbstractTextureProvider +{ + Q_OBJECT +public: + explicit QTextureRectangle(Qt3D::QNode *parent = 0); + ~QTextureRectangle(); +}; + +class QT3DRENDERERSHARED_EXPORT QTextureBuffer : public QAbstractTextureProvider +{ + Q_OBJECT +public: + explicit QTextureBuffer(Qt3D::QNode *parent = 0); + ~QTextureBuffer(); +}; + +} // namespace Qt3DRender + +QT_END_NAMESPACE + +#endif // QT3DRENDER_QTEXTUREPROVIDERS_H diff --git a/src/render/texture/qwrapmode.cpp b/src/render/texture/qwrapmode.cpp new file mode 100644 index 000000000..2e5ace4d2 --- /dev/null +++ b/src/render/texture/qwrapmode.cpp @@ -0,0 +1,157 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwrapmode.h" +#include <private/qobject_p.h> + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { + +class QTextureWrapModePrivate : public QObjectPrivate +{ +public: + QTextureWrapModePrivate() + : QObjectPrivate() + , m_x(QTextureWrapMode::ClampToEdge) + , m_y(QTextureWrapMode::ClampToEdge) + , m_z(QTextureWrapMode::ClampToEdge) + { + } + + Q_DECLARE_PUBLIC(QTextureWrapMode) + QTextureWrapMode::WrapMode m_x; + QTextureWrapMode::WrapMode m_y; + QTextureWrapMode::WrapMode m_z; +}; + +/*! + \class Qt3DRender::QTextureWrapMode + \inmodule Qt3DRenderer + \since 5.5 + + \brief Defines the wrap mode a Qt3DRender::QAbstractTextureProvider + should apply to a texture. + */ + +QTextureWrapMode::QTextureWrapMode(WrapMode wrapMode, QObject *parent) + : QObject(*new QTextureWrapModePrivate, parent) +{ + d_func()->m_x = wrapMode; + d_func()->m_y = wrapMode; + d_func()->m_z = wrapMode; +} + +/*! + Contrusts a new Qt3DRender::QTextureWrapMode instance with the wrap mode to apply to + each dimension \a x, \a y \a z of the texture and \a parent as parent. + */ +QTextureWrapMode::QTextureWrapMode(WrapMode x,WrapMode y, WrapMode z, QObject *parent) + : QObject(*new QTextureWrapModePrivate, parent) +{ + d_func()->m_x = x; + d_func()->m_y = y; + d_func()->m_z = z; +} + +/*! + Sets the wrap mode of the x dimension to \a x. + */ +void QTextureWrapMode::setX(WrapMode x) +{ + Q_D(QTextureWrapMode); + if (d->m_x != x) { + d->m_x = x; + emit xChanged(); + } +} + +/*! + Returns the wrap mode of the x dimension. + */ +QTextureWrapMode::WrapMode QTextureWrapMode::x() const +{ + Q_D(const QTextureWrapMode); + return d->m_x; +} + +/*! + Sets the wrap mode of the y dimension to \a y. + \note this is not available on 1D textures. + */ +void QTextureWrapMode::setY(WrapMode y) +{ + Q_D(QTextureWrapMode); + if (d->m_y != y) { + d->m_y = y; + emit yChanged(); + } +} + +/*! + Returns the wrap mode of the y dimension. + */ +QTextureWrapMode::WrapMode QTextureWrapMode::y() const +{ + Q_D(const QTextureWrapMode); + return d->m_y; +} + +/*! + Sets the wrap mode of the z dimension to \a z. + \note this is only available on 3D textures. + */ +void QTextureWrapMode::setZ(WrapMode z) +{ + Q_D(QTextureWrapMode); + if (d->m_z != z) { + d->m_z = z; + emit zChanged(); + } +} + +/*! + Returns the wrap mode of the y dimension. + */ +QTextureWrapMode::WrapMode QTextureWrapMode::z() const +{ + Q_D(const QTextureWrapMode); + return d->m_z; +} + +} // namespace Qt3DRender + +QT_END_NAMESPACE diff --git a/src/render/texture/qwrapmode.h b/src/render/texture/qwrapmode.h new file mode 100644 index 000000000..6254fe5bf --- /dev/null +++ b/src/render/texture/qwrapmode.h @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT3DRENDER_QWRAPMODE_H +#define QT3DRENDER_QWRAPMODE_H + +#include <Qt3DRenderer/qt3drenderer_global.h> +#include <QObject> + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { + +class QTextureWrapModePrivate; + +class QT3DRENDERERSHARED_EXPORT QTextureWrapMode : public QObject +{ + Q_OBJECT + Q_PROPERTY(WrapMode x READ x WRITE setX NOTIFY xChanged) + Q_PROPERTY(WrapMode y READ y WRITE setY NOTIFY yChanged) + Q_PROPERTY(WrapMode z READ z WRITE setZ NOTIFY zChanged) + +public: + enum WrapMode { + Repeat = 0x2901, // GL_REPEAT + MirroredRepeat = 0x8370, // GL_MIRRORED_REPEAT + ClampToEdge = 0x812F, // GL_CLAMP_TO_EDGE + ClampToBorder = 0x812D // GL_CLAMP_TO_BORDER + }; + Q_ENUM(WrapMode) + + explicit QTextureWrapMode(WrapMode wrapMode = ClampToEdge, QObject *parent = 0); + explicit QTextureWrapMode(WrapMode x, WrapMode y, WrapMode z, QObject *parent = 0); + + void setX(WrapMode x); + WrapMode x() const; + + void setY(WrapMode y); + WrapMode y() const; + + void setZ(WrapMode z); + WrapMode z() const; + +Q_SIGNALS: + void xChanged(); + void yChanged(); + void zChanged(); + +private: + Q_DECLARE_PRIVATE(QTextureWrapMode) +}; + +} // namespace Qt3DRender + +QT_END_NAMESPACE + +#endif // QT3DRENDER_QWRAPMODE_H diff --git a/src/render/texture/texture.cpp b/src/render/texture/texture.cpp new file mode 100644 index 000000000..9ac0966ce --- /dev/null +++ b/src/render/texture/texture.cpp @@ -0,0 +1,606 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtCore/qhash.h> +#include "texture_p.h" + +#include <QDebug> +#include <QOpenGLFunctions> +#include <QOpenGLTexture> +#include <QOpenGLPixelTransferOptions> +#include <Qt3DRenderer/qtexture.h> +#include <Qt3DRenderer/texturedata.h> +#include <Qt3DCore/qscenepropertychange.h> +#include <Qt3DCore/private/qaspectmanager_p.h> +#include <Qt3DRenderer/private/managers_p.h> +#include <Qt3DRenderer/private/texturedatamanager_p.h> + +QT_BEGIN_NAMESPACE + +using namespace Qt3D; + +namespace Qt3DRender { +namespace Render { + +Texture::Texture() + : QBackendNode() + , m_gl(Q_NULLPTR) + , m_width(1) + , m_height(1) + , m_depth(1) + , m_layers(1) + , m_generateMipMaps(false) + , m_target(QAbstractTextureProvider::Target2D) + , m_format(QAbstractTextureProvider::RGBA8_UNorm) + , m_magnificationFilter(QAbstractTextureProvider::Nearest) + , m_minificationFilter(QAbstractTextureProvider::Nearest) + , m_wrapModeX(QTextureWrapMode::ClampToEdge) + , m_wrapModeY(QTextureWrapMode::ClampToEdge) + , m_wrapModeZ(QTextureWrapMode::ClampToEdge) + , m_maximumAnisotropy(1.0f) + , m_comparisonFunction(QAbstractTextureProvider::CompareLessEqual) + , m_comparisonMode(QAbstractTextureProvider::CompareNone) + , m_isDirty(false) + , m_filtersAndWrapUpdated(false) + , m_dataUploadRequired(false) + , m_unique(false) + , m_lock(new QMutex()) + , m_textureDNA(0) + , m_textureManager(Q_NULLPTR) + , m_textureImageManager(Q_NULLPTR) + , m_textureDataManager(Q_NULLPTR) +{ + // We need backend -> frontend notifications to update the status of the texture +} + +Texture::~Texture() +{ + if (m_lock != Q_NULLPTR) + delete m_lock; + m_lock = Q_NULLPTR; +} + +void Texture::cleanup() +{ + m_gl = Q_NULLPTR; + m_width = 1; + m_height = 1; + m_depth = 1; + m_layers = 1; + m_generateMipMaps = false; + m_target = QAbstractTextureProvider::Target2D; + m_format = QAbstractTextureProvider::RGBA8_UNorm; + m_magnificationFilter = QAbstractTextureProvider::Nearest; + m_minificationFilter = QAbstractTextureProvider::Nearest; + m_wrapModeX = QTextureWrapMode::ClampToEdge; + m_wrapModeY = QTextureWrapMode::ClampToEdge; + m_wrapModeZ = QTextureWrapMode::ClampToEdge; + m_maximumAnisotropy = 1.0f; + m_comparisonFunction = QAbstractTextureProvider::CompareLessEqual; + m_comparisonMode = QAbstractTextureProvider::CompareNone; + m_isDirty = false; + m_filtersAndWrapUpdated = false; + m_dataUploadRequired = false; + m_unique = false; + m_textureDNA = 0; + m_textureImages.clear(); + m_textureManager = Q_NULLPTR; + m_textureImageManager = Q_NULLPTR; + m_textureDataManager = Q_NULLPTR; +} + +// AspectThread +void Texture::updateFromPeer(Qt3D::QNode *peer) +{ + QAbstractTextureProvider *texture = static_cast<QAbstractTextureProvider *>(peer); + + QMutexLocker lock(m_lock); + if (texture != Q_NULLPTR) { + m_isDirty = true; + m_width = texture->width(); + m_height = texture->height(); + m_depth = texture->depth(); + m_generateMipMaps = texture->generateMipMaps(); + m_target = texture->target(); + m_format = texture->format(); + m_magnificationFilter = texture->magnificationFilter(); + m_minificationFilter = texture->minificationFilter(); + m_wrapModeX = texture->wrapMode()->x(); + m_wrapModeY = texture->wrapMode()->y(); + m_wrapModeZ = texture->wrapMode()->z(); + m_maximumAnisotropy = texture->maximumAnisotropy(); + m_comparisonFunction = texture->comparisonFunction(); + m_comparisonMode = texture->comparisonMode(); + m_layers = texture->maximumLayers(); + m_unique = texture->isUnique(); + } +} + +// RenderTread +QOpenGLTexture *Texture::getOrCreateGLTexture() +{ + // m_gl HAS to be destroyed in the OpenGL Thread + // Will be recreated with updated values the next time + // buildGLTexture is called + + + // getOrCreateGLTexture is called by the OpenGL Render Thread + // sceneChangeEvent is called by the QAspectThread + // only the OpenGL Render Thread can set isDirty to false + // only a sceneChangeEvent in QAspectThread can set isDirty to true + // We need the lock to make sure there are no races when the OpenGL + // thread tries to read isDirty or one of the texture properties in case + // we are receiving a sceneChangeEvent that modifies isDirty or one of the properties + // at the same time + + QMutexLocker lock(m_lock); + if (m_isDirty) { + delete m_gl; + m_gl = Q_NULLPTR; + m_isDirty = false; + } + + // If the texture exists, we just update it and return + if (m_gl != Q_NULLPTR) { + + bool refreshDNA = m_filtersAndWrapUpdated || m_dataUploadRequired; + + if (m_filtersAndWrapUpdated) { + updateWrapAndFilters(); + m_filtersAndWrapUpdated = false; + } + if (m_dataUploadRequired) + updateAndLoadTextureImage(); + + if (refreshDNA) + updateDNA(); + + return m_gl; + } + + // Builds a new Texture, the texture was never created or it was destroyed + // because it was dirty + m_gl = buildGLTexture(); + + m_gl->allocateStorage(); + if (!m_gl->isStorageAllocated()) { + qWarning() << Q_FUNC_INFO << "texture storage allocation failed"; + return Q_NULLPTR; + } + + // Filters and WrapMode are set + updateWrapAndFilters(); + m_filtersAndWrapUpdated = false; + + // Upload textures data the first time + updateAndLoadTextureImage(); + + // Update DNA + updateDNA(); + + // Ideally we might want to abstract that and use the GraphicsContext as a wrapper + // around that. + if (QOpenGLContext *ctx = QOpenGLContext::currentContext()) { + int err = ctx->functions()->glGetError(); + if (err) + qWarning() << Q_FUNC_INFO << "GL error after generating mip-maps" << QString::number(err, 16); + } + + return m_gl; +} + +// RenderThread +QOpenGLTexture *Texture::buildGLTexture() +{ + QOpenGLContext *ctx = QOpenGLContext::currentContext(); + if (!ctx) { + qWarning() << Q_FUNC_INFO << "requires an OpenGL context"; + return Q_NULLPTR; + } + + QOpenGLTexture* glTex = new QOpenGLTexture(static_cast<QOpenGLTexture::Target>(m_target)); + + if (m_format == QAbstractTextureProvider::Automatic) + qWarning() << Q_FUNC_INFO << "something went wrong, format shouldn't be automatic at this point"; + + // m_format may not be ES2 compatible. Now it's time to convert it, if necessary. + QAbstractTextureProvider::TextureFormat format = m_format; + if (ctx->isOpenGLES() && ctx->format().majorVersion() < 3) { + switch (m_format) { + case QOpenGLTexture::RGBA8_UNorm: + case QOpenGLTexture::RGBAFormat: + format = QAbstractTextureProvider::RGBAFormat; + break; + case QOpenGLTexture::RGB8_UNorm: + case QOpenGLTexture::RGBFormat: + format = QAbstractTextureProvider::RGBFormat; + break; + case QOpenGLTexture::DepthFormat: + format = QAbstractTextureProvider::DepthFormat; + break; + default: + qWarning() << Q_FUNC_INFO << "could not find a matching OpenGL ES 2.0 unsized texture format"; + break; + } + } + + // Map ETC1 to ETC2 when supported. This allows using features like + // immutable storage as ETC2 is standard in GLES 3.0, while the ETC1 extension + // is written against GLES 1.0. + if (m_format == QAbstractTextureProvider::RGB8_ETC1) { + if ((ctx->isOpenGLES() && ctx->format().majorVersion() >= 3) + || ctx->hasExtension(QByteArrayLiteral("GL_OES_compressed_ETC2_RGB8_texture")) + || ctx->hasExtension(QByteArrayLiteral("GL_ARB_ES3_compatibility"))) + format = m_format = QAbstractTextureProvider::RGB8_ETC2; + } + + glTex->setFormat(format == QAbstractTextureProvider::Automatic ? + QOpenGLTexture::NoFormat : + static_cast<QOpenGLTexture::TextureFormat>(format)); + glTex->setSize(m_width, m_height, m_depth); + // Set layers count if texture array + if (m_target == QAbstractTextureProvider::Target1DArray || + m_target == QAbstractTextureProvider::Target2DArray || + m_target == QAbstractTextureProvider::Target3D || + m_target == QAbstractTextureProvider::Target2DMultisampleArray || + m_target == QAbstractTextureProvider::TargetCubeMapArray) + glTex->setLayers(m_layers); + + if (m_generateMipMaps) + glTex->setMipLevels(glTex->maximumMipLevels()); + + if (!glTex->create()) { + qWarning() << Q_FUNC_INFO << "creating QOpenGLTexture failed"; + return Q_NULLPTR; + } + + // FIXME : make this conditional on Qt version + // work-around issue in QOpenGLTexture DSA emulaation which rasies + // an Invalid Enum error + int err = ctx->functions()->glGetError(); + if (err) + qWarning() << Q_FUNC_INFO << err; + + return glTex; +} + +// RenderThread +void Texture::setToGLTexture(TextureImage *rImg, TexImageData *imgData) +{ + Q_ASSERT(m_gl && m_gl->isCreated() && m_gl->isStorageAllocated()); + // ensure we don't accidently cause a detach / copy of the raw bytes + const QByteArray &bytes(imgData->data()); + if (imgData->isCompressed()) { + m_gl->setCompressedData(rImg->mipmapLevel(), + rImg->layer(), + static_cast<QOpenGLTexture::CubeMapFace>(rImg->face()), + bytes.size(), + bytes.constData()); + } else { + QOpenGLPixelTransferOptions uploadOptions; + uploadOptions.setAlignment(1); + m_gl->setData(rImg->mipmapLevel(), + rImg->layer(), + static_cast<QOpenGLTexture::CubeMapFace>(rImg->face()), + imgData->pixelFormat(), + imgData->pixelType(), + bytes.constData(), + &uploadOptions); + } + + // FIXME : make this conditional on Qt version + // work-around issue in QOpenGLTexture DSA emulaation which rasies + // an Invalid Enum error + if (QOpenGLContext *ctx = QOpenGLContext::currentContext()) { + int err = ctx->functions()->glGetError(); + if (err) + qWarning() << Q_FUNC_INFO << err; + } +} + +// RenderThread +void Texture::updateWrapAndFilters() +{ + m_gl->setWrapMode(QOpenGLTexture::DirectionS, static_cast<QOpenGLTexture::WrapMode>(m_wrapModeX)); + if (m_target != QAbstractTextureProvider::Target1D && + m_target != QAbstractTextureProvider::Target1DArray && + m_target != QAbstractTextureProvider::TargetBuffer) + m_gl->setWrapMode(QOpenGLTexture::DirectionT, static_cast<QOpenGLTexture::WrapMode>(m_wrapModeY)); + if (m_target == QAbstractTextureProvider::Target3D) + m_gl->setWrapMode(QOpenGLTexture::DirectionR, static_cast<QOpenGLTexture::WrapMode>(m_wrapModeZ)); + m_gl->setMinMagFilters(static_cast<QOpenGLTexture::Filter>(m_minificationFilter), + static_cast<QOpenGLTexture::Filter>(m_magnificationFilter)); + if (m_gl->hasFeature(QOpenGLTexture::AnisotropicFiltering)) + m_gl->setMaximumAnisotropy(m_maximumAnisotropy); + if (m_gl->hasFeature(QOpenGLTexture::TextureComparisonOperators)) { + m_gl->setComparisonFunction(static_cast<QOpenGLTexture::ComparisonFunction>(m_comparisonFunction)); + m_gl->setComparisonMode(static_cast<QOpenGLTexture::ComparisonMode>(m_comparisonMode)); + } +} + +void Texture::updateDNA() +{ + int key = m_width + m_height + m_depth + m_layers + + (m_generateMipMaps ? 1 : 0) + + static_cast<int>(m_target) + + static_cast<int>(m_format) + + static_cast<int>(m_magnificationFilter) + + static_cast<int>(m_minificationFilter) + + static_cast<int>(m_wrapModeX) + + static_cast<int>(m_wrapModeY) + + static_cast<int>(m_wrapModeZ) + + static_cast<int>(m_comparisonFunction) + + static_cast<int>(m_comparisonMode); + m_textureDNA = ::qHash(key) + ::qHash(m_maximumAnisotropy); + Q_FOREACH (HTextureImage imgHandle, m_textureImages) { + TextureImage *img = m_textureImageManager->data(imgHandle); + if (img) + m_textureDNA += img->dna(); + } + if (m_unique) // Ensures uniqueness by adding unique QNode id to the dna + m_textureDNA += qHash(peerUuid()); +} + +// RenderThread +GLint Texture::textureId() +{ + return getOrCreateGLTexture()->textureId(); +} + +// Any Thread +bool Texture::isTextureReset() const +{ + QMutexLocker lock(m_lock); + return m_isDirty; +} + +void Texture::setSize(int width, int height, int depth) +{ + if (width != m_width) { + m_width = width; + m_isDirty |= true; + } + if (height != m_height) { + m_height = height; + m_isDirty |= true; + } + if (depth != m_depth) { + m_depth = depth; + m_isDirty |= true; + } +} + +void Texture::setFormat(QAbstractTextureProvider::TextureFormat format) +{ + if (format != m_format) { + m_format = format; + m_isDirty |= true; + } +} + +// ChangeArbiter/Aspect Thread +void Texture::sceneChangeEvent(const Qt3D::QSceneChangePtr &e) +{ + // The QOpenGLTexture has to be manipulated from the RenderThread only + QMutexLocker lock(m_lock); + // We lock here so that we're sure the texture cannot be rebuilt while we are + // modifying one of its properties + QScenePropertyChangePtr propertyChange = qSharedPointerCast<QScenePropertyChange>(e); + switch (e->type()) { + case NodeUpdated: { + if (propertyChange->propertyName() == QByteArrayLiteral("width")) { + setSize(propertyChange->value().toInt(), m_height, m_depth); + } else if (propertyChange->propertyName() == QByteArrayLiteral("height")) { + setSize(m_width, propertyChange->value().toInt(), m_depth); + } else if (propertyChange->propertyName() == QByteArrayLiteral("depth")) { + setSize(m_width, m_height, propertyChange->value().toInt()); + } else if (propertyChange->propertyName() == QByteArrayLiteral("mipmaps")) { + const bool oldMipMaps = m_generateMipMaps; + m_generateMipMaps = propertyChange->value().toBool(); + m_isDirty |= (oldMipMaps != m_generateMipMaps); + } else if (propertyChange->propertyName() == QByteArrayLiteral("minificationFilter")) { + QAbstractTextureProvider::Filter oldMinFilter = m_minificationFilter; + m_minificationFilter = static_cast<QAbstractTextureProvider::Filter>(propertyChange->value().toInt()); + m_filtersAndWrapUpdated |= (oldMinFilter != m_minificationFilter); + } else if (propertyChange->propertyName() == QByteArrayLiteral("magnificationFilter")) { + QAbstractTextureProvider::Filter oldMagFilter = m_magnificationFilter; + m_magnificationFilter = static_cast<QAbstractTextureProvider::Filter>(propertyChange->value().toInt()); + m_filtersAndWrapUpdated |= (oldMagFilter != m_magnificationFilter); + } else if (propertyChange->propertyName() == QByteArrayLiteral("wrapModeX")) { + QTextureWrapMode::WrapMode oldWrapModeX = m_wrapModeX; + m_wrapModeX = static_cast<QTextureWrapMode::WrapMode>(propertyChange->value().toInt()); + m_filtersAndWrapUpdated |= (oldWrapModeX != m_wrapModeX); + } else if (propertyChange->propertyName() == QByteArrayLiteral("wrapModeY")) { + QTextureWrapMode::WrapMode oldWrapModeY = m_wrapModeY; + m_wrapModeY = static_cast<QTextureWrapMode::WrapMode>(propertyChange->value().toInt()); + m_filtersAndWrapUpdated |= (oldWrapModeY != m_wrapModeY); + } else if (propertyChange->propertyName() == QByteArrayLiteral("wrapModeZ")) { + QTextureWrapMode::WrapMode oldWrapModeZ = m_wrapModeZ; + m_wrapModeZ =static_cast<QTextureWrapMode::WrapMode>(propertyChange->value().toInt()); + m_filtersAndWrapUpdated |= (oldWrapModeZ != m_wrapModeZ); + } else if (propertyChange->propertyName() == QByteArrayLiteral("format")) { + setFormat(static_cast<QAbstractTextureProvider::TextureFormat>(propertyChange->value().toInt())); + } else if (propertyChange->propertyName() == QByteArrayLiteral("target")) { + QAbstractTextureProvider::Target oldTarget = m_target; + m_target = static_cast<QAbstractTextureProvider::Target>(propertyChange->value().toInt()); + m_isDirty |= (oldTarget != m_target); + } else if (propertyChange->propertyName() == QByteArrayLiteral("maximumAnisotropy")) { + float oldMaximumAnisotropy = m_maximumAnisotropy; + m_maximumAnisotropy = propertyChange->value().toFloat(); + m_filtersAndWrapUpdated |= !qFuzzyCompare(oldMaximumAnisotropy, m_maximumAnisotropy); + } else if (propertyChange->propertyName() == QByteArrayLiteral("comparisonFunction")) { + QAbstractTextureProvider::ComparisonFunction oldComparisonFunction = m_comparisonFunction; + m_comparisonFunction = propertyChange->value().value<QAbstractTextureProvider::ComparisonFunction>(); + m_filtersAndWrapUpdated |= (oldComparisonFunction != m_comparisonFunction); + } else if (propertyChange->propertyName() == QByteArrayLiteral("comparisonMode")) { + QAbstractTextureProvider::ComparisonMode oldComparisonMode = m_comparisonMode; + m_comparisonMode = propertyChange->value().value<QAbstractTextureProvider::ComparisonMode>(); + m_filtersAndWrapUpdated |= (oldComparisonMode != m_comparisonMode); + } else if (propertyChange->propertyName() == QByteArrayLiteral("maximumLayers")) { + const int oldLayers = m_layers; + m_layers = propertyChange->value().toInt(); + m_isDirty |= (oldLayers != m_layers); + } else if (propertyChange->propertyName() == QByteArrayLiteral("unique")) { + const bool oldUnique = m_unique; + m_unique = propertyChange->value().toBool(); + // Will force a DNA update + m_filtersAndWrapUpdated |= (oldUnique != m_unique); + } + } + break; + + case NodeAdded: { + if (propertyChange->propertyName() == QByteArrayLiteral("textureImage")) { + m_textureImages.append(m_textureImageManager->lookupHandle(propertyChange->value().value<QNodeId>())); + } + } + break; + + case NodeRemoved: { + if (propertyChange->propertyName() == QByteArrayLiteral("textureImage")) { + m_textureImages.removeOne(m_textureImageManager->lookupHandle(propertyChange->value().value<QNodeId>())); + // If a TextureImage is removed from a Texture, the texture image data remains on GPU + } + } + break; + + default: + break; + + } +} + +TextureDNA Texture::dna() const +{ + return m_textureDNA; +} + +// AspectThread +void Texture::setTextureManager(TextureManager *manager) +{ + m_textureManager = manager; +} + +// AspectThread +void Texture::setTextureImageManager(TextureImageManager *manager) +{ + m_textureImageManager = manager; +} + +void Texture::setTextureDataManager(TextureDataManager *manager) +{ + m_textureDataManager = manager; +} + +// RenderThread +void Texture::updateAndLoadTextureImage() +{ + QVector<TextureImageDNA> dnas; + Q_FOREACH (HTextureImage t, m_textureImages) { + TextureImage *img = m_textureImageManager->data(t); + if (img != Q_NULLPTR && img->isDirty()) { + if (dnas.contains(img->dna())) { + img->unsetDirty(); + continue; + } + TexImageData *data = m_textureDataManager->data(img->textureDataHandle()); + if (data != Q_NULLPTR) { + setToGLTexture(img, data); + dnas.append(img->dna()); + img->unsetDirty(); + } + } + } + m_dataUploadRequired = false; +} + +void Texture::addTextureImageData(HTextureImage handle) +{ + m_textureImages.append(handle); +} + +void Texture::removeTextureImageData(HTextureImage handle) +{ + m_textureImages.removeOne(handle); +} + +void Texture::requestTextureDataUpdate() +{ + m_dataUploadRequired = true; +} + +// Will request a new jobs, if one of the texture data has changed +// after the job was executed, requestTextureDataUpdate will be called +// Called by RenderTextureImages +void Texture::addToPendingTextureJobs() +{ + m_textureDataManager->addToPendingTextures(peerUuid()); +} + +TextureFunctor::TextureFunctor(TextureManager *textureManager, + TextureImageManager *textureImageManager, + TextureDataManager *textureDataManager) + : m_textureManager(textureManager) + , m_textureImageManager(textureImageManager) + , m_textureDataManager(textureDataManager) +{ +} + +Qt3D::QBackendNode *TextureFunctor::create(Qt3D::QNode *frontend, const Qt3D::QBackendNodeFactory *factory) const +{ + Texture *backend = m_textureManager->getOrCreateResource(frontend->id()); + backend->setFactory(factory); + backend->setTextureManager(m_textureManager); + backend->setTextureImageManager(m_textureImageManager); + backend->setTextureDataManager(m_textureDataManager); + backend->setPeer(frontend); + return backend; +} + +Qt3D::QBackendNode *TextureFunctor::get(const Qt3D::QNodeId &id) const +{ + return m_textureManager->lookupResource(id); +} + +void TextureFunctor::destroy(const Qt3D::QNodeId &id) const +{ + m_textureManager->releaseResource(id); +} + +} // namespace Render +} // namespace Qt3DRender + +QT_END_NAMESPACE diff --git a/src/render/texture/texture.pri b/src/render/texture/texture.pri new file mode 100644 index 000000000..adc07dcd9 --- /dev/null +++ b/src/render/texture/texture.pri @@ -0,0 +1,24 @@ +INCLUDEPATH += $$PWD + +HEADERS += \ + $$PWD/qabstracttextureimage.h \ + $$PWD/qabstracttextureimage_p.h \ + $$PWD/qabstracttextureprovider.h \ + $$PWD/qabstracttextureprovider_p.h \ + $$PWD/qtexture.h \ + $$PWD/qtextureimage.h \ + $$PWD/qtextureproviders.h \ + $$PWD/qwrapmode.h \ + $$PWD/texture_p.h \ + $$PWD/texturedatamanager_p.h \ + $$PWD/textureimage_p.h + +SOURCES += \ + $$PWD/qabstracttextureimage.cpp \ + $$PWD/qabstracttextureprovider.cpp \ + $$PWD/qtextureimage.cpp \ + $$PWD/qtextureproviders.cpp \ + $$PWD/qwrapmode.cpp \ + $$PWD/texture.cpp \ + $$PWD/texturedatamanager.cpp \ + $$PWD/textureimage.cpp diff --git a/src/render/texture/texture_p.h b/src/render/texture/texture_p.h new file mode 100644 index 000000000..522343c68 --- /dev/null +++ b/src/render/texture/texture_p.h @@ -0,0 +1,161 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT3DRENDER_RENDER_TEXTURE_H +#define QT3DRENDER_RENDER_TEXTURE_H + +#include <QOpenGLContext> +#include <QMutex> +#include <Qt3DRenderer/qtexture.h> +#include <Qt3DRenderer/texturedata.h> +#include <Qt3DCore/qbackendnode.h> +#include <Qt3DRenderer/private/handle_types_p.h> + +QT_BEGIN_NAMESPACE + +class QOpenGLTexture; + +namespace Qt3DRender { + +class QAbstractTextureProvider; + +namespace Render { + +class TextureManager; +class TextureImageManager; +class TextureDataManager; + +typedef uint TextureDNA; + +class Texture : public Qt3D::QBackendNode +{ +public: + Texture(); + ~Texture(); + void cleanup(); + + void updateFromPeer(Qt3D::QNode *peer) Q_DECL_OVERRIDE; + + QOpenGLTexture* getOrCreateGLTexture() ; + + GLint textureId(); + + bool isTextureReset() const; + + void sceneChangeEvent(const Qt3D::QSceneChangePtr &e) Q_DECL_OVERRIDE; + TextureDNA dna() const; + + void setTextureManager(TextureManager *manager); + void setTextureImageManager(TextureImageManager *manager); + void setTextureDataManager(TextureDataManager *manager); + + void updateAndLoadTextureImage(); + void addTextureImageData(HTextureImage handle); + void removeTextureImageData(HTextureImage handle); + + void requestTextureDataUpdate(); + void addToPendingTextureJobs(); + void setSize(int width, int height, int depth); + void setFormat(QAbstractTextureProvider::TextureFormat format); + + inline QVector<HTextureImage> textureImages() const { return m_textureImages; } + inline QAbstractTextureProvider::TextureFormat format() const { return m_format; } + +private: + QOpenGLTexture *m_gl; + + QOpenGLTexture *buildGLTexture(); + void setToGLTexture(TextureImage *rImg, TexImageData *imgData); + void updateWrapAndFilters(); + + int m_width; + int m_height; + int m_depth; + int m_layers; + bool m_generateMipMaps; + QAbstractTextureProvider::Target m_target; + QAbstractTextureProvider::TextureFormat m_format; + QAbstractTextureProvider::Filter m_magnificationFilter; + QAbstractTextureProvider::Filter m_minificationFilter; + QTextureWrapMode::WrapMode m_wrapModeX; + QTextureWrapMode::WrapMode m_wrapModeY; + QTextureWrapMode::WrapMode m_wrapModeZ; + float m_maximumAnisotropy; + QAbstractTextureProvider::ComparisonFunction m_comparisonFunction; + QAbstractTextureProvider::ComparisonMode m_comparisonMode; + + QVector<HTextureImage> m_textureImages; + + bool m_isDirty; + bool m_filtersAndWrapUpdated; + bool m_dataUploadRequired; + bool m_formatWasSpecified; + bool m_unique; + + QMutex *m_lock; + TextureDNA m_textureDNA; + TextureManager *m_textureManager; + TextureImageManager *m_textureImageManager; + TextureDataManager *m_textureDataManager; + + void updateDNA(); +}; + +class TextureFunctor : public Qt3D::QBackendNodeFunctor +{ +public: + explicit TextureFunctor(TextureManager *textureManager, + TextureImageManager *textureImageManager, + TextureDataManager *textureDataManager); + + Qt3D::QBackendNode *create(Qt3D::QNode *frontend, const Qt3D::QBackendNodeFactory *factory) const Q_DECL_FINAL; + Qt3D::QBackendNode *get(const Qt3D::QNodeId &id) const Q_DECL_FINAL; + void destroy(const Qt3D::QNodeId &id) const Q_DECL_FINAL; + +private: + TextureManager *m_textureManager; + TextureImageManager *m_textureImageManager; + TextureDataManager *m_textureDataManager; +}; + +} // namespace Render +} // namespace Qt3DRender + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(Qt3DRender::Render::Texture*) + +#endif // QT3DRENDER_RENDER_TEXTURE_H diff --git a/src/render/texture/texturedatamanager.cpp b/src/render/texture/texturedatamanager.cpp new file mode 100644 index 000000000..3e77179f6 --- /dev/null +++ b/src/render/texture/texturedatamanager.cpp @@ -0,0 +1,170 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "texturedatamanager_p.h" + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { + +namespace Render { + + +TextureDataManager::TextureDataManager() + : m_mutex(QMutex::Recursive) +{} + +// Called from AspectThread sync +void TextureDataManager::addToPendingTextures(const Qt3D::QNodeId &textureId) +{ + // This simple check ensures that we won't be having n jobs + // for one mesh, in case n Materials are referencing the said + // texture + if (!m_texturesPending.contains(textureId)) + m_texturesPending.append(textureId); +} + +// Called from AspectThread prepare jobs +QVector<Qt3D::QNodeId> TextureDataManager::texturesPending() +{ + QVector<Qt3D::QNodeId> textureIds = m_texturesPending; + m_texturesPending.clear(); + return textureIds; +} + +// Called from LoadMeshDataJob threads +HTextureData TextureDataManager::textureDataFromFunctor(const QTextureDataFunctorPtr &functor) const +{ + QMutexLocker lock(&m_mutex); + for (int i = 0, m = m_textureDataFunctors.size(); i < m; ++i) { + if (*functor == *(m_textureDataFunctors[i].first)) + return m_textureDataFunctors[i].second; + } + return HTextureData(); +} + +// Called from LoadMeshDataJob threads +void TextureDataManager::addTextureDataForFunctor(HTextureData textureDataHandle, const QTextureDataFunctorPtr &functor) +{ + QMutexLocker lock(&m_mutex); + m_textureDataFunctors.push_back(qMakePair(functor, textureDataHandle)); +} + +// Called from LoadMeshDataJob threads +void TextureDataManager::removeTextureDataFunctor(const QTextureDataFunctorPtr &functor) +{ + QMutexLocker lock(&m_mutex); + for (int i = 0, m = m_textureDataFunctors.size(); i < m; ++i) { + if (*functor == *(m_textureDataFunctors[i].first)) { + m_textureDataFunctors.remove(i); + break; + } + } +} + +// Called from LoadMeshDataJob threads +void TextureDataManager::assignFunctorToTextureImage(const QTextureDataFunctorPtr &newFunctor, HTextureImage imageHandle) +{ + QMutexLocker lock(&m_mutex); + QVector<QPair<QTextureDataFunctorPtr, QVector<HTextureImage> > >::iterator it = m_texturesImagesPerFunctor.begin(); + + bool newFunctorAlreadyExists = false; + bool oldFunctorWasRemoved = false; + while (it != m_texturesImagesPerFunctor.end()) { + QPair<QTextureDataFunctorPtr, QVector<HTextureImage> > &entry = *it; + QTextureDataFunctorPtr functor = entry.first; + QVector<HTextureImage> &imageHandles = entry.second; + const bool functorMatchesNewFunctor = (*functor == *newFunctor); + bool removed = false; + + if (functorMatchesNewFunctor) { + // New Functor already exist, just need to append + imageHandles.push_back(imageHandle); + newFunctorAlreadyExists = true; + } else if (imageHandles.contains(imageHandle)) { + // functor in array != New Functor and contains + // <=> functor was the previous functor of imageHandle + // the image handle, we need to remove the handle + imageHandles.removeAll(imageHandle); + + // If no texture image is referencing the functor anymore + // get rid of the functor + if (imageHandles.isEmpty()) { + // We need to release the texture image data + HTextureData textureDataHandle = textureDataFromFunctor(functor); + if (!m_textureHandlesToRelease.contains(textureDataHandle)) + m_textureHandlesToRelease.push_back(textureDataHandle); + // Remove functor + removeTextureDataFunctor(functor); + // Remove the entry + it = m_texturesImagesPerFunctor.erase(it); + removed = true; + oldFunctorWasRemoved = true; + } + } + + // Early exit if we can + if (oldFunctorWasRemoved && newFunctorAlreadyExists) + break; + + if (!removed) + ++it; + } + + // Insert new imageHandle with new functor + if (!newFunctorAlreadyExists) + m_texturesImagesPerFunctor.push_back(qMakePair(newFunctor, QVector<HTextureImage>() << imageHandle)); +} + +QMutex *TextureDataManager::mutex() const +{ + return &m_mutex; +} + +// Called by cleanup job +// No need to lock +void TextureDataManager::cleanup() +{ + for (int i = 0, m = m_textureHandlesToRelease.size(); i < m; ++i) + release(m_textureHandlesToRelease[i]); + m_textureHandlesToRelease.clear(); +} + +} // namespace Render + +} // namespace Qt3DRender + +QT_END_NAMESPACE diff --git a/src/render/texture/texturedatamanager_p.h b/src/render/texture/texturedatamanager_p.h new file mode 100644 index 000000000..734e9049c --- /dev/null +++ b/src/render/texture/texturedatamanager_p.h @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT3DRENDER_RENDER_TEXTUREDATAMANAGER_H +#define QT3DRENDER_RENDER_TEXTUREDATAMANAGER_H + +#include <Qt3DCore/private/qresourcemanager_p.h> +#include <Qt3DRenderer/qtexture.h> +#include <Qt3DRenderer/texturedata.h> +#include <Qt3DRenderer/private/handle_types_p.h> + +#include <QPair> +#include <Qt3DCore/qnodeid.h> + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { + +namespace Render { + +typedef QPair<QTextureDataFunctorPtr, QVector<HTextureImage> > FunctorImageHandlesPair; +typedef QPair<QTextureDataFunctorPtr, HTextureData> FunctorTextureDataPair; + +class TextureDataManager : public Qt3D::QResourceManager<TexImageData, + Qt3D::QNodeId, + 16, + Qt3D::ArrayAllocatingPolicy, + Qt3D::ObjectLevelLockingPolicy> +{ +public: + TextureDataManager(); + void addToPendingTextures(const Qt3D::QNodeId &textureId); + + QVector<Qt3D::QNodeId> texturesPending(); + + HTextureData textureDataFromFunctor(const QTextureDataFunctorPtr &functor) const; + void addTextureDataForFunctor(HTextureData textureDataHandle, const QTextureDataFunctorPtr &functor); + void removeTextureDataFunctor(const QTextureDataFunctorPtr &functor); + + void assignFunctorToTextureImage(const QTextureDataFunctorPtr &functor, HTextureImage imageHandle); + + QMutex *mutex() const; + void cleanup(); + +private: + QVector<Qt3D::QNodeId> m_texturesPending; + QVector<FunctorTextureDataPair > m_textureDataFunctors; + QVector<FunctorImageHandlesPair > m_texturesImagesPerFunctor; + mutable QMutex m_mutex; + QVector<HTextureData> m_textureHandlesToRelease; +}; + +} // namespace Render +} // namespace Qt3DRender + +Q_DECLARE_RESOURCE_INFO(Qt3DRender::TexImageData, Q_REQUIRES_CLEANUP) + +QT_END_NAMESPACE + +#endif // TEXTUREDATAMANAGER_H diff --git a/src/render/texture/textureimage.cpp b/src/render/texture/textureimage.cpp new file mode 100644 index 000000000..4625586bf --- /dev/null +++ b/src/render/texture/textureimage.cpp @@ -0,0 +1,188 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "textureimage_p.h" +#include <Qt3DCore/qscenepropertychange.h> +#include <Qt3DRenderer/private/managers_p.h> +#include <Qt3DRenderer/private/texturedatamanager_p.h> + +QT_BEGIN_NAMESPACE + +using namespace Qt3D; + +namespace Qt3DRender { +namespace Render { + +TextureImage::TextureImage() + : QBackendNode() + , m_layer(0) + , m_mipmapLevel(0) + , m_face(QAbstractTextureProvider::CubeMapPositiveX) + , m_dirty(true) + , m_textureManager(Q_NULLPTR) + , m_textureImageManager(Q_NULLPTR) + , m_textureDataManager(Q_NULLPTR) + , m_dna(0) +{ +} + +void TextureImage::cleanup() +{ + m_layer = 0; + m_mipmapLevel = 0; + m_dirty = true; + m_face = QAbstractTextureProvider::CubeMapPositiveX; + m_functor.reset(); + m_textureManager = Q_NULLPTR; + m_textureImageManager = Q_NULLPTR; + m_textureDataManager = Q_NULLPTR; + m_referencedTextures.clear(); + m_dna = 0; +} + +void TextureImage::updateFromPeer(Qt3D::QNode *peer) +{ + QAbstractTextureImage *textureImage = static_cast<QAbstractTextureImage *>(peer); + m_layer = textureImage->layer(); + m_mipmapLevel = textureImage->mipmapLevel(); + m_face = textureImage->cubeMapFace(); + m_functor = textureImage->dataFunctor(); + // Notify the Texture that we are one of its TextureImage + if (!peer->parentNode()) { + qWarning() << "Not QAbstractTextureProvider parent found"; + } else { + m_textureProviderId = peer->parentNode()->id(); + m_textureProvider = m_textureManager->lookupHandle(m_textureProviderId); + Texture *txt = m_textureManager->data(m_textureProvider); + // Notify the Texture that it has a new TextureImage and needs an update + txt->addTextureImageData(m_textureImageManager->lookupHandle(peerUuid())); + if (txt != Q_NULLPTR) + txt->addToPendingTextureJobs(); + } +} + +void TextureImage::sceneChangeEvent(const Qt3D::QSceneChangePtr &e) +{ + QScenePropertyChangePtr propertyChange = qSharedPointerCast<QScenePropertyChange>(e); + + if (e->type() == NodeUpdated) { + if (propertyChange->propertyName() == QByteArrayLiteral("layer")) { + m_layer = propertyChange->value().toInt(); + m_dirty = true; + } else if (propertyChange->propertyName() == QByteArrayLiteral("mipmapLevel")) { + m_mipmapLevel = propertyChange->value().toInt(); + m_dirty = true; + } else if (propertyChange->propertyName() == QByteArrayLiteral("cubeMapFace")) { + m_face = static_cast<QAbstractTextureProvider::CubeMapFace>(propertyChange->value().toInt()); + m_dirty = true; + } else if (propertyChange->propertyName() == QByteArrayLiteral("dataFunctor")) { + m_functor = propertyChange->value().value<QTextureDataFunctorPtr>(); + m_dirty = true; + } + } + if (m_dirty) {// Notify the Texture that we were updated and request it to schedule an update job + Texture *txt = m_textureManager->data(m_textureProvider); + if (txt != Q_NULLPTR) + txt->addToPendingTextureJobs(); + } +} + +void TextureImage::setTextureManager(TextureManager *manager) +{ + m_textureManager = manager; +} + +void TextureImage::setTextureImageManager(TextureImageManager *manager) +{ + m_textureImageManager = manager; +} + +void TextureImage::setTextureDataManager(TextureDataManager *manager) +{ + m_textureDataManager = manager; +} + +void TextureImage::unsetDirty() +{ + m_dirty = false; +} + +// Called by LoadDataTextureJob when the texture data has been successfully load +void TextureImage::setTextureDataHandle(HTextureData handle) +{ + m_textureDataHandle = handle; + updateDNA(); +} + +void TextureImage::updateDNA() +{ + m_dna = ::qHash(m_layer + m_mipmapLevel + static_cast<int>(m_face) + m_textureDataHandle); +} + +TextureImageFunctor::TextureImageFunctor(TextureManager *textureManager, + TextureImageManager *textureImageManager, + TextureDataManager *textureDataManager) + : m_textureManager(textureManager) + , m_textureImageManager(textureImageManager) + , m_textureDataManager(textureDataManager) +{ +} + +Qt3D::QBackendNode *TextureImageFunctor::create(Qt3D::QNode *frontend, const Qt3D::QBackendNodeFactory *factory) const +{ + TextureImage *backend = m_textureImageManager->getOrCreateResource(frontend->id()); + backend->setFactory(factory); + backend->setTextureManager(m_textureManager); + backend->setTextureImageManager(m_textureImageManager); + backend->setTextureDataManager(m_textureDataManager); + backend->setPeer(frontend); + return backend; +} + +Qt3D::QBackendNode *TextureImageFunctor::get(const Qt3D::QNodeId &id) const +{ + return m_textureImageManager->lookupResource(id); +} + +void TextureImageFunctor::destroy(const Qt3D::QNodeId &id) const +{ + m_textureImageManager->releaseResource(id); +} + +} // namespace Render +} // namespace Qt3DRender + +QT_END_NAMESPACE diff --git a/src/render/texture/textureimage_p.h b/src/render/texture/textureimage_p.h new file mode 100644 index 000000000..4964eb416 --- /dev/null +++ b/src/render/texture/textureimage_p.h @@ -0,0 +1,127 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT3DRENDER_RENDER_TEXTUREIMAGE_H +#define QT3DRENDER_RENDER_TEXTUREIMAGE_H + +#include <qglobal.h> +#include <Qt3DCore/qbackendnode.h> +#include <Qt3DRenderer/qabstracttextureprovider.h> +#include <Qt3DRenderer/qabstracttextureimage.h> +#include <Qt3DRenderer/private/handle_types_p.h> + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { + +namespace Render { + +class TextureManager; +class TextureImageManager; +class TextureDataManager; + +typedef uint TextureImageDNA; + +class TextureImage : public Qt3D::QBackendNode +{ +public: + TextureImage(); + void cleanup(); + void updateFromPeer(Qt3D::QNode *peer) Q_DECL_OVERRIDE; + void sceneChangeEvent(const Qt3D::QSceneChangePtr &e) Q_DECL_OVERRIDE; + + int m_layer; + int m_mipmapLevel; + QAbstractTextureProvider::CubeMapFace m_face; + bool m_dirty; + inline TextureImageDNA dna() const { return m_dna; } + + inline int layer() const { return m_layer; } + inline int mipmapLevel() const { return m_mipmapLevel; } + inline QAbstractTextureProvider::CubeMapFace face() const { return m_face; } + + void setTextureManager(TextureManager *manager); + void setTextureImageManager(TextureImageManager *manager); + void setTextureDataManager(TextureDataManager *manager); + void unsetDirty(); + + inline bool isDirty() const { return m_dirty; } + inline QTextureDataFunctorPtr textureDataFunctor() const { return m_functor; } + + void setTextureDataHandle(HTextureData handle); + + inline HTextureData textureDataHandle() const { return m_textureDataHandle; } + inline QTextureDataFunctorPtr dataFunctor() const { return m_functor; } + +private: + void updateDNA(); + + QTextureDataFunctorPtr m_functor; + HTextureData m_textureDataHandle; + TextureManager *m_textureManager; + TextureImageManager *m_textureImageManager; + TextureDataManager *m_textureDataManager; + QList<Qt3D::QNodeId> m_referencedTextures; + HTexture m_textureProvider; + Qt3D::QNodeId m_textureProviderId; + TextureImageDNA m_dna; +}; + +class TextureImageFunctor : public Qt3D::QBackendNodeFunctor +{ +public: + explicit TextureImageFunctor(TextureManager *textureManager, + TextureImageManager *textureImageManager, + TextureDataManager *textureDataManager); + + Qt3D::QBackendNode *create(Qt3D::QNode *frontend, const Qt3D::QBackendNodeFactory *factory) const Q_DECL_FINAL; + Qt3D::QBackendNode *get(const Qt3D::QNodeId &id) const Q_DECL_FINAL; + void destroy(const Qt3D::QNodeId &id) const Q_DECL_FINAL; + +private: + TextureManager *m_textureManager; + TextureImageManager *m_textureImageManager; + TextureDataManager *m_textureDataManager; +}; + + +} // namespace Render + +} // namespace Qt3DRender + +QT_END_NAMESPACE + +#endif // QT3DRENDER_RENDER_TEXTUREIMAGE_H |