summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Lemire <paul.lemire@kdab.com>2015-01-30 11:28:20 +0100
committerSean Harmer <sean.harmer@kdab.com>2015-02-08 15:02:28 +0000
commit4b22aa1904337e595cca0b6f46b445d555db7d6b (patch)
treea8c9f26628c41dae1ae48ba6853b07d50f96a3f8 /src
parent782907f3f15def5f050bb69f95575d5e3f40b61d (diff)
Texture API refactoring
* Added LoadTextureDataJob * QAbstractTextureProvider: maximum layers property * Automatic QAbstractTextureProvider::TextureFormat added * material-qml should work perfectly with that patch. Change-Id: I3f92f13b783155798772086304a30126a4fc687d Reviewed-by: Sean Harmer <sean.harmer@kdab.com>
Diffstat (limited to 'src')
-rw-r--r--src/plugins/sceneparsers/assimp/assimpparser.cpp2
-rw-r--r--src/quick3d/quick3drenderer/items/quick3dtexture.cpp6
-rw-r--r--src/render/backend/jobs/loadtexturedatajob.cpp131
-rw-r--r--src/render/backend/jobs/loadtexturedatajob_p.h80
-rw-r--r--src/render/backend/jobs/render-jobs.pri6
-rw-r--r--src/render/backend/meshdatamanager.cpp10
-rw-r--r--src/render/backend/meshdatamanager_p.h2
-rw-r--r--src/render/backend/qgraphicscontext.cpp1
-rw-r--r--src/render/backend/qrenderaspect.cpp12
-rw-r--r--src/render/backend/rendertexture.cpp209
-rw-r--r--src/render/backend/rendertexture_p.h29
-rw-r--r--src/render/backend/rendertextureimage.cpp94
-rw-r--r--src/render/backend/rendertextureimage_p.h48
-rw-r--r--src/render/backend/texturedatamanager.cpp30
-rw-r--r--src/render/backend/texturedatamanager_p.h13
-rw-r--r--src/render/frontend/qabstracttextureimage.cpp3
-rw-r--r--src/render/frontend/qabstracttextureprovider.cpp37
-rw-r--r--src/render/frontend/qabstracttextureprovider.h6
-rw-r--r--src/render/frontend/qabstracttextureprovider_p.h1
-rw-r--r--src/render/frontend/qtextureimage.cpp15
-rw-r--r--src/render/io/texturedata.cpp22
-rw-r--r--src/render/io/texturedata.h22
22 files changed, 663 insertions, 116 deletions
diff --git a/src/plugins/sceneparsers/assimp/assimpparser.cpp b/src/plugins/sceneparsers/assimp/assimpparser.cpp
index c29226fad..aeb27a3ab 100644
--- a/src/plugins/sceneparsers/assimp/assimpparser.cpp
+++ b/src/plugins/sceneparsers/assimp/assimpparser.cpp
@@ -594,7 +594,7 @@ void AssimpParser::loadEmbeddedTexture(uint textureIndex)
{
aiTexture *assimpTexture = m_scene->m_aiScene->mTextures[textureIndex];
QAbstractTextureProvider *texture = new QTexture2D();
- TexImageDataPtr textureData(new TexImageData(0, 0));
+ TexImageDataPtr textureData(new TexImageData());
bool isCompressed = assimpTexture->mHeight == 0;
uint textureSize = assimpTexture->mWidth *
diff --git a/src/quick3d/quick3drenderer/items/quick3dtexture.cpp b/src/quick3d/quick3drenderer/items/quick3dtexture.cpp
index 01689b432..172da793d 100644
--- a/src/quick3d/quick3drenderer/items/quick3dtexture.cpp
+++ b/src/quick3d/quick3drenderer/items/quick3dtexture.cpp
@@ -211,9 +211,9 @@ void Quick3DTextureCubeMapExtension::loadFace(const QUrl &faceUrl, QAbstractText
// parentTexture()->setStatus(QAbstractTextureProvider::Loading);
if (img.load(source)) {
- TexImageDataPtr dataPtr(new TexImageData(0, 0));
+ TexImageDataPtr dataPtr(new TexImageData());
- dataPtr->setCubeFace(static_cast<QOpenGLTexture::CubeMapFace>(face));
+// dataPtr->setCubeFace(static_cast<QOpenGLTexture::CubeMapFace>(face));
if (parentTexture()->height() != img.height())
parentTexture()->setHeight(img.height());
if (parentTexture()->width() != img.width())
@@ -224,7 +224,7 @@ void Quick3DTextureCubeMapExtension::loadFace(const QUrl &faceUrl, QAbstractText
if (format != parentTexture()->format())
parentTexture()->setFormat(format);
dataPtr->setImage(img);
- parentTexture()->addImageData(dataPtr);
+// parentTexture()->addImageData(dataPtr);
// parentTexture()->setStatus(QAbstractTextureProvider::Loaded);
}
else {
diff --git a/src/render/backend/jobs/loadtexturedatajob.cpp b/src/render/backend/jobs/loadtexturedatajob.cpp
new file mode 100644
index 000000000..fde19a678
--- /dev/null
+++ b/src/render/backend/jobs/loadtexturedatajob.cpp
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** 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:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 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 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "loadtexturedatajob_p.h"
+#include <Qt3DRenderer/private/renderer_p.h>
+#include <Qt3DRenderer/private/managers_p.h>
+#include <Qt3DRenderer/private/texturedatamanager_p.h>
+#include <QThread>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3D {
+
+namespace Render {
+
+LoadTextureDataJob::LoadTextureDataJob(const QNodeId &textureId)
+ : m_textureId(textureId)
+{
+}
+
+LoadTextureDataJob::~LoadTextureDataJob()
+{
+}
+
+void LoadTextureDataJob::run()
+{
+ qCDebug(Jobs) << "Entering" << Q_FUNC_INFO << QThread::currentThread();
+
+ RenderTexture *txt = m_renderer->textureManager()->lookupResource(m_textureId);
+
+ if (txt != Q_NULLPTR) {
+ // Load update each TextureImage
+ Q_FOREACH (HTextureImage texImgHandle, txt->textureImages()) {
+ RenderTextureImage *texImg = m_renderer->textureImageManager()->data(texImgHandle);
+ if (texImg != Q_NULLPTR && texImg->isDirty() && !texImg->dataFunctor().isNull()) {
+ QTextureDataFunctorPtr functor = texImg->dataFunctor();
+ TextureDataManager::Locker locker(m_renderer->textureDataManager());
+ HTextureData textureDataHandle = m_renderer->textureDataManager()->textureDataFromFunctor(functor);
+ locker.unlock();
+
+ TexImageData *data = Q_NULLPTR;
+ // Texture data handle isn't null == there's already a matching TextureData
+ if (!textureDataHandle.isNull()) {
+ data = m_renderer->textureDataManager()->data(textureDataHandle);
+ } else {
+ TexImageDataPtr dataPtr = functor->operator ()();
+ if (dataPtr.isNull()) {
+ qCDebug(Jobs) << Q_FUNC_INFO << "Texture has no raw data";
+ } else {
+ // Save the TexImageDataPtr with it's functor as a key
+ textureDataHandle = m_renderer->textureDataManager()->acquire();
+ data = m_renderer->textureDataManager()->data(textureDataHandle);
+ locker.relock();
+ *data = *(dataPtr.data());
+ m_renderer->textureDataManager()->addTextureDataForFunctor(textureDataHandle, functor);
+ }
+ }
+
+ // Set texture size of texture if the first layer / level / face has a valid size
+ // otherwise assume the size was set on the texture itself
+ if (texImg->layer() == 0 && texImg->mipmapLevel() == 0 &&
+ texImg->face() == QAbstractTextureProvider::CubeMapPositiveX) {
+
+ if (data == Q_NULLPTR) {
+ qWarning() << "Texture data is null, texture data failed to load";
+ } else {
+ // Set the size of the texture based on the layer 0 / level 0
+ // if the functor provides something valid. Otherwise we assume the texture
+ // already has the correct size
+ if (data->width() != -1 && data->height() != -1 && data->depth() != -1) {
+ txt->setSize(data->width(), data->height(), data->depth());
+ }
+ // Set the format of the texture if the texture format is set to Automatic
+ if (txt->format() == QAbstractTextureProvider::Automatic) {
+ txt->setFormat(static_cast<QAbstractTextureProvider::TextureFormat>(data->format()));
+ }
+ }
+ }
+ // Set the textureDataHandle on the texture image
+ texImg->setTextureDataHandle(textureDataHandle);
+ }
+ }
+ // Tell the renderer to reload the TextureImage for the Texture
+ // next frame
+ txt->requestTextureDataUpdate();
+ }
+}
+
+} // Render
+
+} // Qt3D
+
+QT_END_NAMESPACE
diff --git a/src/render/backend/jobs/loadtexturedatajob_p.h b/src/render/backend/jobs/loadtexturedatajob_p.h
new file mode 100644
index 000000000..5506d2efd
--- /dev/null
+++ b/src/render/backend/jobs/loadtexturedatajob_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:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 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 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3D_RENDER_LOADTEXTUREDATAJOB_H
+#define QT3D_RENDER_LOADTEXTUREDATAJOB_H
+
+#include <Qt3DCore/qnodeid.h>
+#include <Qt3DCore/qaspectjob.h>
+#include <Qt3DRenderer/qtextureimage.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3D {
+
+namespace Render {
+
+class Renderer;
+
+class LoadTextureDataJob : public QAspectJob
+{
+public:
+ LoadTextureDataJob(const QNodeId &textureId);
+ ~LoadTextureDataJob();
+ inline void setRenderer(Renderer *renderer) { m_renderer = renderer; }
+
+protected:
+ void run() Q_DECL_FINAL;
+
+private:
+ QNodeId m_textureId;
+ Renderer *m_renderer;
+};
+
+typedef QSharedPointer<LoadTextureDataJob> LoadTextureDataJobPtr;
+
+} // Render
+
+} // Qt3D
+
+QT_END_NAMESPACE
+
+#endif // QT3D_RENDER_LOADTEXTUREDATAJOB_H
diff --git a/src/render/backend/jobs/render-jobs.pri b/src/render/backend/jobs/render-jobs.pri
index 4b1b750fc..fefc18001 100644
--- a/src/render/backend/jobs/render-jobs.pri
+++ b/src/render/backend/jobs/render-jobs.pri
@@ -8,7 +8,8 @@ HEADERS += \
$$PWD/renderviewjobutils_p.h \
$$PWD/loadscenejob_p.h \
$$PWD/framecleanupjob_p.h \
- $$PWD/framepreparationjob_p.h
+ $$PWD/framepreparationjob_p.h \
+ $$PWD/loadtexturedatajob_p.h
SOURCES += \
$$PWD/updateworldtransformjob.cpp \
@@ -18,4 +19,5 @@ SOURCES += \
$$PWD/renderviewjobutils.cpp \
$$PWD/loadscenejob.cpp \
$$PWD/framecleanupjob.cpp \
- $$PWD/framepreparationjob.cpp
+ $$PWD/framepreparationjob.cpp \
+ $$PWD/loadtexturedatajob.cpp
diff --git a/src/render/backend/meshdatamanager.cpp b/src/render/backend/meshdatamanager.cpp
index 13266e5a5..02a00d31a 100644
--- a/src/render/backend/meshdatamanager.cpp
+++ b/src/render/backend/meshdatamanager.cpp
@@ -63,9 +63,13 @@ QHash<QNodeId, QAbstractMeshFunctorPtr> MeshDataManager::meshesPending()
HMeshData MeshDataManager::meshDataFromFunctor(QAbstractMeshFunctorPtr functor) const
{
- Q_FOREACH (const QAbstractMeshFunctorPtr &ptr, m_meshFunctors.keys()) {
- if (*ptr == *functor)
- return m_meshFunctors.value(ptr);
+ QHash<QAbstractMeshFunctorPtr, HMeshData>::const_iterator it = m_meshFunctors.begin();
+ const QHash<QAbstractMeshFunctorPtr, HMeshData>::const_iterator end = m_meshFunctors.end();
+
+ while (it != end) {
+ if (*it.key() == *functor)
+ return it.value();
+ ++it;
}
return HMeshData();
}
diff --git a/src/render/backend/meshdatamanager_p.h b/src/render/backend/meshdatamanager_p.h
index e7251cca7..4df9f39b5 100644
--- a/src/render/backend/meshdatamanager_p.h
+++ b/src/render/backend/meshdatamanager_p.h
@@ -62,7 +62,7 @@ namespace Render {
class MeshDataManager : public QResourceManager<QMeshData,
QNodeId,
16,
- Qt3D::ListAllocatingPolicy,
+ Qt3D::ArrayAllocatingPolicy,
Qt3D::ObjectLevelLockingPolicy>
{
public:
diff --git a/src/render/backend/qgraphicscontext.cpp b/src/render/backend/qgraphicscontext.cpp
index 9376b9e07..0ff0ad556 100644
--- a/src/render/backend/qgraphicscontext.cpp
+++ b/src/render/backend/qgraphicscontext.cpp
@@ -373,6 +373,7 @@ int QGraphicsContext::activateTexture(TextureScope scope, RenderTexture *tex, in
if (m_activeTextures[onUnit] != tex) {
QOpenGLTexture* glTex = tex->getOrCreateGLTexture();
glTex->bind(onUnit);
+ m_activeTextures[onUnit] = tex;
}
int err = m_gl->functions()->glGetError();
diff --git a/src/render/backend/qrenderaspect.cpp b/src/render/backend/qrenderaspect.cpp
index 7e1ce5e53..f61d3e2b7 100644
--- a/src/render/backend/qrenderaspect.cpp
+++ b/src/render/backend/qrenderaspect.cpp
@@ -44,6 +44,7 @@
#include <Qt3DRenderer/private/rendermesh_p.h>
#include <Qt3DRenderer/private/meshdatamanager_p.h>
+#include <Qt3DRenderer/private/texturedatamanager_p.h>
#include <Qt3DRenderer/private/renderer_p.h>
#include <Qt3DRenderer/private/scenemanager_p.h>
@@ -88,6 +89,7 @@
#include <Qt3DRenderer/private/rendernodefunctor_p.h>
#include <Qt3DRenderer/private/framegraphnode_p.h>
#include <Qt3DRenderer/private/loadmeshdatajob_p.h>
+#include <Qt3DRenderer/private/loadtexturedatajob_p.h>
#include <Qt3DRenderer/private/updateboundingvolumejob_p.h>
#include <Qt3DRenderer/private/updateworldtransformjob_p.h>
#include <Qt3DRenderer/private/framecleanupjob_p.h>
@@ -191,7 +193,7 @@ void QRenderAspect::registerBackendTypes()
registerBackendType<QTransform>(QBackendNodeFunctorPtr(new Render::RenderNodeFunctor<Render::RenderTransform, Render::TransformManager>(d->m_renderer->transformManager())));
registerBackendType<QMaterial>(QBackendNodeFunctorPtr(new Render::RenderNodeFunctor<Render::RenderMaterial, Render::MaterialManager>(d->m_renderer->materialManager())));
registerBackendType<QTechnique>(QBackendNodeFunctorPtr(new Render::RenderNodeFunctor<Render::RenderTechnique, Render::TechniqueManager>(d->m_renderer->techniqueManager())));
- registerBackendType<QAbstractTextureProvider>(QBackendNodeFunctorPtr(new Render::RenderTextureFunctor(d->m_renderer->textureManager(), d->m_renderer->textureImageManager())));
+ registerBackendType<QAbstractTextureProvider>(QBackendNodeFunctorPtr(new Render::RenderTextureFunctor(d->m_renderer->textureManager(), d->m_renderer->textureImageManager(), d->m_renderer->textureDataManager())));
registerBackendType<QShaderProgram>(QBackendNodeFunctorPtr(new Render::RenderNodeFunctor<Render::RenderShader, Render::ShaderManager>(d->m_renderer->shaderManager())));
registerBackendType<QEffect>(QBackendNodeFunctorPtr(new Render::RenderNodeFunctor<Render::RenderEffect, Render::EffectManager>(d->m_renderer->effectManager())));
registerBackendType<QAnnotation>(QBackendNodeFunctorPtr(new Render::RenderNodeFunctor<Render::RenderAnnotation, Render::CriterionManager>(d->m_renderer->criterionManager())));
@@ -215,7 +217,7 @@ void QRenderAspect::registerBackendTypes()
registerBackendType<QFrameGraph>(QBackendNodeFunctorPtr(new Render::FrameGraphComponentFunctor(d->m_renderer)));
registerBackendType<QParameter>(QBackendNodeFunctorPtr(new Render::RenderNodeFunctor<Render::RenderParameter, Render::ParameterManager>(d->m_renderer->parameterManager())));
registerBackendType<QShaderData>(QBackendNodeFunctorPtr(new Render::RenderShaderDataFunctor(d->m_renderer->shaderDataManager())));
- registerBackendType<QAbstractTextureImage>(QBackendNodeFunctorPtr(new Render::RenderNodeFunctor<Render::RenderTextureImage, Render::TextureImageManager>(d->m_renderer->textureImageManager())));
+ registerBackendType<QAbstractTextureImage>(QBackendNodeFunctorPtr(new Render::RenderTextureImageFunctor(d->m_renderer->textureManager(), d->m_renderer->textureImageManager(), d->m_renderer->textureDataManager())));
}
void QRenderAspect::renderInitialize(QOpenGLContext *context)
@@ -259,6 +261,12 @@ QVector<QAspectJobPtr> QRenderAspect::jobsToExecute(qint64 time)
jobs.append(loadMeshJob);
}
+ QVector<QNodeId> texturesPending = d->m_renderer->textureDataManager()->texturesPending();
+ Q_FOREACH (const QNodeId &textureId, texturesPending) {
+ Render::LoadTextureDataJobPtr loadTextureJob(new Render::LoadTextureDataJob(textureId));
+ loadTextureJob->setRenderer(d->m_renderer);
+ jobs.append(loadTextureJob);
+ }
// TO DO: Have 2 jobs queue
// One for urgent jobs that are mandatory for the rendering of a frame
// Another for jobs that can span across multiple frames (Scene/Mesh loading)
diff --git a/src/render/backend/rendertexture.cpp b/src/render/backend/rendertexture.cpp
index b34ceb454..737bccdda 100644
--- a/src/render/backend/rendertexture.cpp
+++ b/src/render/backend/rendertexture.cpp
@@ -51,6 +51,7 @@
#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
@@ -63,9 +64,10 @@ RenderTexture::RenderTexture()
, m_width(1)
, m_height(1)
, m_depth(1)
+ , m_layers(1)
, m_generateMipMaps(false)
, m_target(QAbstractTextureProvider::Target2D)
- , m_format(QAbstractTextureProvider::RGBA8U)
+ , m_format(QAbstractTextureProvider::RGBA8_UNorm)
, m_magnificationFilter(QAbstractTextureProvider::Nearest)
, m_minificationFilter(QAbstractTextureProvider::Nearest)
, m_wrapModeX(QTextureWrapMode::ClampToEdge)
@@ -76,10 +78,12 @@ RenderTexture::RenderTexture()
, m_comparisonMode(QAbstractTextureProvider::CompareNone)
, m_isDirty(false)
, m_filtersAndWrapUpdated(false)
+ , m_dataUploadRequired(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
}
@@ -97,9 +101,10 @@ void RenderTexture::cleanup()
m_width = 1;
m_height = 1;
m_depth = 1;
+ m_layers = 1;
m_generateMipMaps = false;
m_target = QAbstractTextureProvider::Target2D;
- m_format = QAbstractTextureProvider::RGBA8U;
+ m_format = QAbstractTextureProvider::RGBA8_UNorm;
m_magnificationFilter = QAbstractTextureProvider::Nearest;
m_minificationFilter = QAbstractTextureProvider::Nearest;
m_wrapModeX = QTextureWrapMode::ClampToEdge;
@@ -110,12 +115,15 @@ void RenderTexture::cleanup()
m_comparisonMode = QAbstractTextureProvider::CompareNone;
m_isDirty = false;
m_filtersAndWrapUpdated = false;
+ m_dataUploadRequired = false;
+ m_textureDNA = 0;
m_textureImages.clear();
- m_imageData.clear();
m_textureManager = Q_NULLPTR;
m_textureImageManager = Q_NULLPTR;
+ m_textureDataManager = Q_NULLPTR;
}
+// AspectThread
void RenderTexture::updateFromPeer(QNode *peer)
{
QAbstractTextureProvider *texture = static_cast<QAbstractTextureProvider *>(peer);
@@ -137,17 +145,11 @@ void RenderTexture::updateFromPeer(QNode *peer)
m_maximumAnisotropy = texture->maximumAnisotropy();
m_comparisonFunction = texture->comparisonFunction();
m_comparisonMode = texture->comparisonMode();
-
- // TO DO: This list should be filled by executing the functor of
- // each TextureImage instead of reading those from the frontend directly
- Q_FOREACH (TexImageDataPtr imgData, texture->imageData())
- m_imageData.append(imgData);
-
- Q_FOREACH (QAbstractTextureImage *textureImage, texture->textureImages())
- m_textureImages.append(m_textureImageManager->getOrAcquireHandle(textureImage->id()));
+ m_layers = texture->maximumLayers();
}
}
+// RenderTread
QOpenGLTexture *RenderTexture::getOrCreateGLTexture()
{
// m_gl HAS to be destroyed in the OpenGL Thread
@@ -176,6 +178,8 @@ QOpenGLTexture *RenderTexture::getOrCreateGLTexture()
updateWrapAndFilters();
m_filtersAndWrapUpdated = false;
}
+ if (m_dataUploadRequired)
+ updateAndLoadTextureImage();
return m_gl;
}
@@ -187,14 +191,13 @@ QOpenGLTexture *RenderTexture::getOrCreateGLTexture()
return Q_NULLPTR;
}
- foreach (TexImageDataPtr imgData, m_imageData) {
- setToGLTexture(imgData);
- } // of image data in texture iteration
-
// Filters and WrapMode are set
updateWrapAndFilters();
m_filtersAndWrapUpdated = false;
+ // Upload textures data the first time
+ updateAndLoadTextureImage();
+
// Ideally we might want to abstract that and use the QGraphicsContext as a wrapper
// around that.
if (QOpenGLContext *ctx = QOpenGLContext::currentContext()) {
@@ -206,11 +209,25 @@ QOpenGLTexture *RenderTexture::getOrCreateGLTexture()
return m_gl;
}
+// RenderThread
QOpenGLTexture *RenderTexture::buildGLTexture()
{
QOpenGLTexture* glTex = new QOpenGLTexture(static_cast<QOpenGLTexture::Target>(m_target));
- glTex->setFormat(static_cast<QOpenGLTexture::TextureFormat>(m_format));
+
+ if (m_format == QAbstractTextureProvider::Automatic)
+ qWarning() << Q_FUNC_INFO << "something went wrong, format shouldn't be automatic at this point";
+
+ glTex->setFormat(m_format == QAbstractTextureProvider::Automatic ?
+ QOpenGLTexture::NoFormat :
+ static_cast<QOpenGLTexture::TextureFormat>(m_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());
@@ -223,29 +240,33 @@ QOpenGLTexture *RenderTexture::buildGLTexture()
// 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())
- ctx->functions()->glGetError();
+ if (QOpenGLContext *ctx = QOpenGLContext::currentContext()) {
+ int err = ctx->functions()->glGetError();
+ if (err)
+ qWarning() << Q_FUNC_INFO << err;
+ }
return glTex;
}
-void RenderTexture::setToGLTexture(TexImageDataPtr imgData)
+// RenderThread
+void RenderTexture::setToGLTexture(RenderTextureImage *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(imgData->mipMapLevel(),
- imgData->layer(),
- imgData->cubeFace(),
+ 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(imgData->mipMapLevel(),
- imgData->layer(),
- imgData->cubeFace(),
+ m_gl->setData(rImg->mipmapLevel(),
+ rImg->layer(),
+ static_cast<QOpenGLTexture::CubeMapFace>(rImg->face()),
imgData->pixelFormat(),
imgData->pixelType(),
bytes.constData(),
@@ -255,10 +276,14 @@ void RenderTexture::setToGLTexture(TexImageDataPtr imgData)
// 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())
- ctx->functions()->glGetError();
+ if (QOpenGLContext *ctx = QOpenGLContext::currentContext()) {
+ int err = ctx->functions()->glGetError();
+ if (err)
+ qWarning() << Q_FUNC_INFO << err;
+ }
}
+// RenderThread
void RenderTexture::updateWrapAndFilters()
{
m_gl->setWrapMode(QOpenGLTexture::DirectionS, static_cast<QOpenGLTexture::WrapMode>(m_wrapModeX));
@@ -280,18 +305,44 @@ void RenderTexture::updateWrapAndFilters()
}
}
-
+// RenderThread
GLint RenderTexture::textureId()
{
return getOrCreateGLTexture()->textureId();
}
+// Any Thread
bool RenderTexture::isTextureReset() const
{
QMutexLocker lock(m_lock);
return m_isDirty;
}
+void RenderTexture::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 RenderTexture::setFormat(QAbstractTextureProvider::TextureFormat format)
+{
+ if (format != m_format) {
+ m_format = format;
+ m_isDirty |= true;
+ }
+}
+
+// ChangeArbiter/Aspect Thread
void RenderTexture::sceneChangeEvent(const QSceneChangePtr &e)
{
// The QOpenGLTexture has to be manipulated from the RenderThread only
@@ -302,74 +353,73 @@ void RenderTexture::sceneChangeEvent(const QSceneChangePtr &e)
switch (e->type()) {
case NodeUpdated: {
if (propertyChange->propertyName() == QByteArrayLiteral("width")) {
- int oldWidth = m_width;
- m_width = propertyChange->value().toInt();
- m_isDirty = (oldWidth != m_width);
+ setSize(propertyChange->value().toInt(), m_height, m_depth);
} else if (propertyChange->propertyName() == QByteArrayLiteral("height")) {
- int oldHeight = m_height;
- m_height = propertyChange->value().toInt();
- m_isDirty = (oldHeight != m_height);
+ setSize(m_width, propertyChange->value().toInt(), m_depth);
} else if (propertyChange->propertyName() == QByteArrayLiteral("depth")) {
- int oldDepth = m_depth;
- m_depth = propertyChange->value().toInt();
- m_isDirty = (oldDepth != m_depth);
+ setSize(m_width, m_height, propertyChange->value().toInt());
} else if (propertyChange->propertyName() == QByteArrayLiteral("mipmaps")) {
bool oldMipMaps = m_generateMipMaps;
m_generateMipMaps = propertyChange->value().toBool();
- m_isDirty = (oldMipMaps != m_generateMipMaps);
+ 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);
+ 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);
+ 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);
+ m_filtersAndWrapUpdated |= (oldWrapModeX != m_wrapModeX);
} else if (propertyChange->propertyName() == QByteArrayLiteral("wrapModeX")) {
QTextureWrapMode::WrapMode oldWrapModeY = m_wrapModeY;
m_wrapModeY = static_cast<QTextureWrapMode::WrapMode>(propertyChange->value().toInt());
- m_filtersAndWrapUpdated = (oldWrapModeY != m_wrapModeY);
+ m_filtersAndWrapUpdated |= (oldWrapModeY != m_wrapModeY);
} else if (propertyChange->propertyName() == QByteArrayLiteral("wrapModeX")) {
QTextureWrapMode::WrapMode oldWrapModeZ = m_wrapModeZ;
m_wrapModeZ =static_cast<QTextureWrapMode::WrapMode>(propertyChange->value().toInt());
- m_filtersAndWrapUpdated = (oldWrapModeZ != m_wrapModeZ);
+ m_filtersAndWrapUpdated |= (oldWrapModeZ != m_wrapModeZ);
} else if (propertyChange->propertyName() == QByteArrayLiteral("format")) {
- QAbstractTextureProvider::TextureFormat oldFormat = m_format;
- m_format = static_cast<QAbstractTextureProvider::TextureFormat>(propertyChange->value().toInt());
- m_isDirty = (oldFormat != m_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);
+ 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);
+ 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);
+ 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);
+ m_filtersAndWrapUpdated |= (oldComparisonMode != m_comparisonMode);
+ } else if (propertyChange->propertyName() == QByteArrayLiteral("maximumLayers")) {
+ int oldLayers = m_layers;
+ m_layers = propertyChange->value().toInt();
+ m_isDirty |= (oldLayers != m_layers);
}
}
break;
case NodeAdded: {
- if (propertyChange->propertyName() == QByteArrayLiteral("textureImage"))
- m_textureImages.append(m_textureImageManager->getOrAcquireHandle(propertyChange->value().value<QNodeId>()));
+ 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->getOrAcquireHandle(propertyChange->value().value<QNodeId>()));
+ 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;
@@ -384,20 +434,68 @@ TextureDNA RenderTexture::dna() const
return m_textureDNA;
}
+// AspectThread
void RenderTexture::setTextureManager(TextureManager *manager)
{
m_textureManager = manager;
}
+// AspectThread
void RenderTexture::setTextureImageManager(TextureImageManager *manager)
{
m_textureImageManager = manager;
}
+void RenderTexture::setTextureDataManager(TextureDataManager *manager)
+{
+ m_textureDataManager = manager;
+}
+
+// RenderThread
+void RenderTexture::updateAndLoadTextureImage()
+{
+ Q_FOREACH (HTextureImage t, m_textureImages) {
+ RenderTextureImage *img = m_textureImageManager->data(t);
+ if (img != Q_NULLPTR && img->isDirty()) {
+ TexImageData *data = m_textureDataManager->data(img->textureDataHandle());
+ if (data != Q_NULLPTR) {
+ setToGLTexture(img, data);
+ img->unsetDirty();
+ }
+ }
+ }
+ m_dataUploadRequired = false;
+}
+
+void RenderTexture::addTextureImageData(HTextureImage handle)
+{
+ m_textureImages.append(handle);
+}
+
+void RenderTexture::removeTextureImageData(HTextureImage handle)
+{
+ m_textureImages.removeOne(handle);
+}
+
+void RenderTexture::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 RenderTexture::addToPendingTextureJobs()
+{
+ m_textureDataManager->addToPendingTextures(peerUuid());
+}
+
RenderTextureFunctor::RenderTextureFunctor(TextureManager *textureManager,
- TextureImageManager *textureImageManager)
+ TextureImageManager *textureImageManager,
+ TextureDataManager *textureDataManager)
: m_textureManager(textureManager)
, m_textureImageManager(textureImageManager)
+ , m_textureDataManager(textureDataManager)
{
}
@@ -407,6 +505,7 @@ QBackendNode *RenderTextureFunctor::create(QNode *frontend, const QBackendNodeFa
backend->setFactory(factory);
backend->setTextureManager(m_textureManager);
backend->setTextureImageManager(m_textureImageManager);
+ backend->setTextureDataManager(m_textureDataManager);
backend->setPeer(frontend);
return backend;
}
diff --git a/src/render/backend/rendertexture_p.h b/src/render/backend/rendertexture_p.h
index 4386be4f1..fb86ef10f 100644
--- a/src/render/backend/rendertexture_p.h
+++ b/src/render/backend/rendertexture_p.h
@@ -61,6 +61,7 @@ namespace Render {
class TextureManager;
class TextureImageManager;
+class TextureDataManager;
typedef uint TextureDNA;
@@ -84,17 +85,31 @@ public:
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(TexImageDataPtr imgData);
+ void setToGLTexture(RenderTextureImage *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;
@@ -107,14 +122,18 @@ private:
QAbstractTextureProvider::ComparisonFunction m_comparisonFunction;
QAbstractTextureProvider::ComparisonMode m_comparisonMode;
- QList<TexImageDataPtr> m_imageData;
- QList<HTextureImage> m_textureImages;
+ QVector<HTextureImage> m_textureImages;
+
bool m_isDirty;
bool m_filtersAndWrapUpdated;
+ bool m_dataUploadRequired;
+ bool m_formatWasSpecified;
+
QMutex *m_lock;
TextureDNA m_textureDNA;
TextureManager *m_textureManager;
TextureImageManager *m_textureImageManager;
+ TextureDataManager *m_textureDataManager;
void updateDNA();
};
@@ -123,7 +142,8 @@ class RenderTextureFunctor : public QBackendNodeFunctor
{
public:
explicit RenderTextureFunctor(TextureManager *textureManager,
- TextureImageManager *textureImageManager);
+ TextureImageManager *textureImageManager,
+ TextureDataManager *textureDataManager);
QBackendNode *create(QNode *frontend, const QBackendNodeFactory *factory) const Q_DECL_FINAL;
QBackendNode *get(QNode *frontend) const Q_DECL_FINAL;
@@ -132,6 +152,7 @@ public:
private:
TextureManager *m_textureManager;
TextureImageManager *m_textureImageManager;
+ TextureDataManager *m_textureDataManager;
};
} // namespace Render
diff --git a/src/render/backend/rendertextureimage.cpp b/src/render/backend/rendertextureimage.cpp
index e3011e189..f113533fb 100644
--- a/src/render/backend/rendertextureimage.cpp
+++ b/src/render/backend/rendertextureimage.cpp
@@ -41,6 +41,8 @@
#include "rendertextureimage_p.h"
#include <Qt3DCore/qscenepropertychange.h>
+#include <Qt3DRenderer/private/managers_p.h>
+#include <Qt3DRenderer/private/texturedatamanager_p.h>
QT_BEGIN_NAMESPACE
@@ -53,7 +55,10 @@ RenderTextureImage::RenderTextureImage()
, m_layer(0)
, m_mipmapLevel(0)
, m_face(QAbstractTextureProvider::CubeMapPositiveX)
- , m_isDirty(true)
+ , m_dirty(true)
+ , m_textureManager(Q_NULLPTR)
+ , m_textureImageManager(Q_NULLPTR)
+ , m_textureDataManager(Q_NULLPTR)
{
}
@@ -61,9 +66,13 @@ void RenderTextureImage::cleanup()
{
m_layer = 0;
m_mipmapLevel = 0;
- m_isDirty = true;
+ 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();
}
void RenderTextureImage::updateFromPeer(QNode *peer)
@@ -73,6 +82,18 @@ void RenderTextureImage::updateFromPeer(QNode *peer)
m_mipmapLevel = textureImage->mipmapLevel();
m_face = textureImage->cubeMapFace();
m_functor = textureImage->dataFunctor();
+ // Notify the RenderTexture 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);
+ RenderTexture *txt = m_textureManager->data(m_textureProvider);
+ // Notify the RenderTexture that it has a new RenderTextureImage and needs an update
+ txt->addTextureImageData(m_textureImageManager->lookupHandle(peerUuid()));
+ if (txt != Q_NULLPTR)
+ txt->addToPendingTextureJobs();
+ }
}
void RenderTextureImage::sceneChangeEvent(const QSceneChangePtr &e)
@@ -82,18 +103,79 @@ void RenderTextureImage::sceneChangeEvent(const QSceneChangePtr &e)
if (e->type() == NodeUpdated) {
if (propertyChange->propertyName() == QByteArrayLiteral("layer")) {
m_layer = propertyChange->value().toInt();
- m_isDirty = true;
+ m_dirty = true;
} else if (propertyChange->propertyName() == QByteArrayLiteral("mipmapLevel")) {
m_mipmapLevel = propertyChange->value().toInt();
- m_isDirty = true;
+ m_dirty = true;
} else if (propertyChange->propertyName() == QByteArrayLiteral("cubeMapFace")) {
m_face = static_cast<QAbstractTextureProvider::CubeMapFace>(propertyChange->value().toInt());
- m_isDirty = true;
+ m_dirty = true;
} else if (propertyChange->propertyName() == QByteArrayLiteral("dataFunctor")) {
m_functor = propertyChange->value().value<QTextureDataFunctorPtr>();
- m_isDirty = true;
+ m_dirty = true;
}
}
+ if (m_dirty) {// Notify the RenderTexture that we were updated and request it to schedule an update job
+ RenderTexture *txt = m_textureManager->data(m_textureProvider);
+ if (txt != Q_NULLPTR)
+ txt->addToPendingTextureJobs();
+ }
+}
+
+void RenderTextureImage::setTextureManager(TextureManager *manager)
+{
+ m_textureManager = manager;
+}
+
+void RenderTextureImage::setTextureImageManager(TextureImageManager *manager)
+{
+ m_textureImageManager = manager;
+}
+
+void RenderTextureImage::setTextureDataManager(TextureDataManager *manager)
+{
+ m_textureDataManager = manager;
+}
+
+void RenderTextureImage::unsetDirty()
+{
+ m_dirty = false;
+}
+
+// Called by LoadDataTextureJob when the texture data has been successfully load
+void RenderTextureImage::setTextureDataHandle(HTextureData handle)
+{
+ m_textureDataHandle = handle;
+}
+
+RenderTextureImageFunctor::RenderTextureImageFunctor(TextureManager *textureManager,
+ TextureImageManager *textureImageManager,
+ TextureDataManager *textureDataManager)
+ : m_textureManager(textureManager)
+ , m_textureImageManager(textureImageManager)
+ , m_textureDataManager(textureDataManager)
+{
+}
+
+QBackendNode *RenderTextureImageFunctor::create(QNode *frontend, const QBackendNodeFactory *factory) const
+{
+ RenderTextureImage *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;
+}
+
+QBackendNode *RenderTextureImageFunctor::get(QNode *frontend) const
+{
+ return m_textureImageManager->lookupResource(frontend->id());
+}
+
+void RenderTextureImageFunctor::destroy(QNode *frontend) const
+{
+ m_textureImageManager->releaseResource(frontend->id());
}
} // Render
diff --git a/src/render/backend/rendertextureimage_p.h b/src/render/backend/rendertextureimage_p.h
index 9b1a77086..cda5216b7 100644
--- a/src/render/backend/rendertextureimage_p.h
+++ b/src/render/backend/rendertextureimage_p.h
@@ -46,6 +46,7 @@
#include <Qt3DCore/qbackendnode.h>
#include <Qt3DRenderer/qabstracttextureprovider.h>
#include <Qt3DRenderer/qabstracttextureimage.h>
+#include <Qt3DRenderer/private/handle_types_p.h>
QT_BEGIN_NAMESPACE
@@ -53,6 +54,10 @@ namespace Qt3D {
namespace Render {
+class TextureManager;
+class TextureImageManager;
+class TextureDataManager;
+
class RenderTextureImage : public QBackendNode
{
public:
@@ -64,15 +69,54 @@ public:
int m_layer;
int m_mipmapLevel;
QAbstractTextureProvider::CubeMapFace m_face;
- bool m_isDirty;
+ bool m_dirty;
+
+ inline int layer() const { return m_layer; }
+ inline int mipmapLevel() const { return m_mipmapLevel; }
+ inline QAbstractTextureProvider::CubeMapFace face() const { return m_face; }
- inline bool isDirty() const { return m_isDirty; }
+ 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:
QTextureDataFunctorPtr m_functor;
+ HTextureData m_textureDataHandle;
+ TextureManager *m_textureManager;
+ TextureImageManager *m_textureImageManager;
+ TextureDataManager *m_textureDataManager;
+ QList<QNodeId> m_referencedTextures;
+ HTexture m_textureProvider;
+ QNodeId m_textureProviderId;
};
+class RenderTextureImageFunctor : public QBackendNodeFunctor
+{
+public:
+ explicit RenderTextureImageFunctor(TextureManager *textureManager,
+ TextureImageManager *textureImageManager,
+ TextureDataManager *textureDataManager);
+
+ QBackendNode *create(QNode *frontend, const QBackendNodeFactory *factory) const Q_DECL_FINAL;
+ QBackendNode *get(QNode *frontend) const Q_DECL_FINAL;
+ void destroy(QNode *frontend) const Q_DECL_FINAL;
+
+private:
+ TextureManager *m_textureManager;
+ TextureImageManager *m_textureImageManager;
+ TextureDataManager *m_textureDataManager;
+};
+
+
} // Render
} // Qt3D
diff --git a/src/render/backend/texturedatamanager.cpp b/src/render/backend/texturedatamanager.cpp
index 528ade8e3..30c8cf370 100644
--- a/src/render/backend/texturedatamanager.cpp
+++ b/src/render/backend/texturedatamanager.cpp
@@ -47,10 +47,34 @@ namespace Qt3D {
namespace Render {
-void Qt3D::Render::TextureDataManager::addTextureData(Qt3D::QAbstractTextureProvider *texture)
+
+void TextureDataManager::addToPendingTextures(const QNodeId &textureId)
+{
+ m_texturesPending.append(textureId);
+}
+
+QVector<QNodeId> TextureDataManager::texturesPending()
+{
+ QVector<QNodeId> textureIds = m_texturesPending;
+ m_texturesPending.clear();
+ return textureIds;
+}
+
+HTextureData TextureDataManager::textureDataFromFunctor(QTextureDataFunctorPtr functor) const
+{
+ QHash<QTextureDataFunctorPtr, HTextureData>::const_iterator it = m_textureDataFunctors.begin();
+ const QHash<QTextureDataFunctorPtr, HTextureData>::const_iterator end = m_textureDataFunctors.end();
+ while (it != end) {
+ if (*it.key() == *functor)
+ return it.value();
+ ++it;
+ }
+ return HTextureData();
+}
+
+void TextureDataManager::addTextureDataForFunctor(HTextureData textureDataHandle, QTextureDataFunctorPtr functor)
{
- if (!contains(texture->id()) && !m_texturesPending.contains(texture))
- m_texturesPending.append(texture);
+ m_textureDataFunctors.insert(functor, textureDataHandle);
}
} // Render
diff --git a/src/render/backend/texturedatamanager_p.h b/src/render/backend/texturedatamanager_p.h
index d920e5e59..3c5411068 100644
--- a/src/render/backend/texturedatamanager_p.h
+++ b/src/render/backend/texturedatamanager_p.h
@@ -58,19 +58,20 @@ namespace Render {
class TextureDataManager : public QResourceManager<TexImageData,
QNodeId,
16,
- Qt3D::ListAllocatingPolicy,
+ Qt3D::ArrayAllocatingPolicy,
Qt3D::ObjectLevelLockingPolicy>
{
public:
TextureDataManager() {}
+ void addToPendingTextures(const QNodeId &textureId);
- void addTextureData(QAbstractTextureProvider *texture);
-
- QList<QAbstractTextureProvider *> texturesPending() const { return m_texturesPending; }
- void clearTexturesPending() { m_texturesPending.clear(); }
+ QVector<QNodeId> texturesPending();
+ HTextureData textureDataFromFunctor(QTextureDataFunctorPtr functor) const;
+ void addTextureDataForFunctor(HTextureData textureDataHandle, QTextureDataFunctorPtr functor);
private:
- QList<QAbstractTextureProvider *> m_texturesPending;
+ QVector<QNodeId> m_texturesPending;
+ QHash<QTextureDataFunctorPtr, HTextureData> m_textureDataFunctors;
};
} // Render
diff --git a/src/render/frontend/qabstracttextureimage.cpp b/src/render/frontend/qabstracttextureimage.cpp
index bbb437056..5c749eb2e 100644
--- a/src/render/frontend/qabstracttextureimage.cpp
+++ b/src/render/frontend/qabstracttextureimage.cpp
@@ -60,6 +60,9 @@ namespace Qt3D {
executed by Aspect jobs in the backend. Qt3D::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.
*/
/*!
diff --git a/src/render/frontend/qabstracttextureprovider.cpp b/src/render/frontend/qabstracttextureprovider.cpp
index 6d720906a..5547d73f4 100644
--- a/src/render/frontend/qabstracttextureprovider.cpp
+++ b/src/render/frontend/qabstracttextureprovider.cpp
@@ -51,7 +51,7 @@ namespace Qt3D {
QAbstractTextureProviderPrivate::QAbstractTextureProviderPrivate(QAbstractTextureProvider *qq)
: QNodePrivate(qq)
, m_target(QAbstractTextureProvider::Target2D)
- , m_format(QAbstractTextureProvider::RGBA8U)
+ , m_format(QAbstractTextureProvider::Automatic)
, m_width(1)
, m_height(1)
, m_depth(1)
@@ -62,6 +62,7 @@ QAbstractTextureProviderPrivate::QAbstractTextureProviderPrivate(QAbstractTextur
, m_maximumAnisotropy(1.0f)
, m_comparisonFunction(QAbstractTextureProvider::CompareLessEqual)
, m_comparisonMode(QAbstractTextureProvider::CompareNone)
+ , m_maximumLayers(1)
{
}
@@ -83,7 +84,7 @@ void QAbstractTextureProvider::copy(const QNode *ref)
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;
- // TO DO: Copy TexImageDataPtr
+ d_func()->m_maximumLayers = t->d_func()->m_maximumLayers;
}
/*!
@@ -194,6 +195,32 @@ int QAbstractTextureProvider::depth() const
}
/*!
+ Sets the maximum layers count to \a maximumLayers, by defaults, 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();
+ }
+}
+
+/*!
+ \return return the maximum layers count of 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;
+}
+
+/*!
Sets the format of the texture provider to \a format.
*/
void QAbstractTextureProvider::setFormat(TextureFormat format)
@@ -258,7 +285,7 @@ bool QAbstractTextureProvider::setFromQImage(QImage img, int layer)
return false;
}
- TexImageDataPtr dataPtr(new TexImageData(0, layer));
+ TexImageDataPtr dataPtr(new TexImageData());
dataPtr->setImage(img);
addImageData(dataPtr);
setStatus(Loaded);
@@ -279,6 +306,7 @@ QList<TexImageDataPtr> QAbstractTextureProvider::imageData() const
/*!
Adds a new Qt3D::QAbstractTextureImage \a texture image to the texture provider.
+ \note: Qt3D::QAbstractTextureImage should never be shared by several Qt3D::QAbstractTextureProvider
*/
void QAbstractTextureProvider::addTextureImage(QAbstractTextureImage *textureImage)
{
@@ -286,6 +314,9 @@ void QAbstractTextureProvider::addTextureImage(QAbstractTextureImage *textureIma
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
diff --git a/src/render/frontend/qabstracttextureprovider.h b/src/render/frontend/qabstracttextureprovider.h
index ed60b20c3..e0021298f 100644
--- a/src/render/frontend/qabstracttextureprovider.h
+++ b/src/render/frontend/qabstracttextureprovider.h
@@ -76,6 +76,7 @@ class QT3DRENDERERSHARED_EXPORT QAbstractTextureProvider : public QNode
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)
public:
@@ -101,6 +102,7 @@ public:
enum TextureFormat {
NoFormat = 0, // GL_NONE
+ Automatic = 1, // The Qt3D engine automatically determines the best format
// Unsigned normalized formats
R8_UNorm = 0x8229, // GL_R8
@@ -301,6 +303,9 @@ public:
int height() const;
int depth() const;
+ void setMaximumLayers(int maximumLayers);
+ int maximumLayers() const;
+
Q_SIGNALS:
void formatChanged();
void statusChanged();
@@ -313,6 +318,7 @@ Q_SIGNALS:
void maximumAnisotropyChanged();
void comparisonFunctionChanged();
void comparisonModeChanged();
+ void maximumLayersChanged();
protected:
explicit QAbstractTextureProvider(QNode *parent = 0);
diff --git a/src/render/frontend/qabstracttextureprovider_p.h b/src/render/frontend/qabstracttextureprovider_p.h
index e40e1c106..b5e906aa8 100644
--- a/src/render/frontend/qabstracttextureprovider_p.h
+++ b/src/render/frontend/qabstracttextureprovider_p.h
@@ -73,6 +73,7 @@ public :
QAbstractTextureProvider::ComparisonFunction m_comparisonFunction;
QAbstractTextureProvider::ComparisonMode m_comparisonMode;
QList<QAbstractTextureImage *> m_textureImages;
+ int m_maximumLayers;
};
} // QT3D
diff --git a/src/render/frontend/qtextureimage.cpp b/src/render/frontend/qtextureimage.cpp
index c3fc92098..4ff15d70e 100644
--- a/src/render/frontend/qtextureimage.cpp
+++ b/src/render/frontend/qtextureimage.cpp
@@ -69,7 +69,20 @@ public:
// Will be executed from within a QAspectJob
TexImageDataPtr operator ()() Q_DECL_FINAL
{
- return TexImageDataPtr();
+ TexImageDataPtr dataPtr;
+ if (m_url.isLocalFile() || m_url.scheme() == QStringLiteral("qrc")) {
+ QString source = m_url.toString().replace(QStringLiteral("qrc"), QStringLiteral(""));
+ QImage img;
+ if (img.load(source)) {
+ dataPtr.reset(new TexImageData());
+ dataPtr->setImage(img);
+ } else {
+ qWarning() << "Failed to load image : " << source;
+ }
+ } else {
+ qWarning() << "implement loading from remote URLs";
+ }
+ return dataPtr;
}
bool operator ==(const QTextureDataFunctor &other) const Q_DECL_FINAL
diff --git a/src/render/io/texturedata.cpp b/src/render/io/texturedata.cpp
index 9331e865e..582e0259d 100644
--- a/src/render/io/texturedata.cpp
+++ b/src/render/io/texturedata.cpp
@@ -48,25 +48,25 @@ QT_BEGIN_NAMESPACE
namespace Qt3D {
-TexImageData::TexImageData(int level, int layer) :
- m_layer(layer),
- m_mipMapLevel(level),
- m_cubeFace(QOpenGLTexture::CubeMapPositiveX),
- m_isCompressed(false)
+TexImageData::TexImageData()
+ : m_width(-1)
+ , m_height(-1)
+ , m_depth(-1)
+ , m_isCompressed(false)
+ , m_format(QOpenGLTexture::RGBA8_UNorm)
{
}
-void TexImageData::setCubeFace(QOpenGLTexture::CubeMapFace face)
-{
- m_cubeFace = face;
-}
-
void TexImageData::setImage(const QImage &image)
{
QImage glImage = image.convertToFormat(QImage::Format_RGBA8888);
-
+ m_width = image.width();
+ m_height = image.height();
+ m_depth = 1;
QByteArray imageBytes((const char*) glImage.constBits(), glImage.byteCount());
setData(imageBytes, QOpenGLTexture::RGBA, QOpenGLTexture::UInt8);
+ m_format = image.hasAlphaChannel() ? QOpenGLTexture::RGBA8_UNorm :
+ QOpenGLTexture::RGB8_UNorm;
}
void TexImageData::setData(const QByteArray &data, QOpenGLTexture::PixelFormat fmt, QOpenGLTexture::PixelType ptype)
diff --git a/src/render/io/texturedata.h b/src/render/io/texturedata.h
index 530faeecc..b69d62d89 100644
--- a/src/render/io/texturedata.h
+++ b/src/render/io/texturedata.h
@@ -54,22 +54,18 @@ namespace Qt3D {
class QT3DRENDERERSHARED_EXPORT TexImageData
{
public:
- TexImageData(int level, int layer);
+ TexImageData();
- QOpenGLTexture::CubeMapFace cubeFace() const
- { return m_cubeFace; }
-
- void setCubeFace(QOpenGLTexture::CubeMapFace face);
-
- int layer() const
- { return m_layer; }
-
- int mipMapLevel() const
- { return m_mipMapLevel; }
+ ~TexImageData() {}
bool isCompressed() const
{ return m_isCompressed; }
+ inline int width() const { return m_width; }
+ inline int height() const { return m_height; }
+ inline int depth() const { return m_depth; }
+ inline QOpenGLTexture::TextureFormat format() const { return m_format; }
+
void setImage(const QImage &);
void setData(const QByteArray &data,
@@ -87,13 +83,13 @@ public:
{ return m_pixelType; }
private:
- int m_layer, m_mipMapLevel;
- QOpenGLTexture::CubeMapFace m_cubeFace;
+ int m_width, m_height, m_depth;
QOpenGLTexture::PixelFormat m_pixelFormat;
QOpenGLTexture::PixelType m_pixelType;
bool m_isCompressed;
QByteArray m_data;
+ QOpenGLTexture::TextureFormat m_format;
};
typedef QSharedPointer<TexImageData> TexImageDataPtr;