summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/render/backend/managers_p.h15
-rw-r--r--src/render/renderers/opengl/renderer/renderer.cpp13
-rw-r--r--src/render/texture/texture.cpp10
-rw-r--r--src/render/texture/texture_p.h2
-rw-r--r--tests/auto/core/common/qbackendnodetester.cpp5
-rw-r--r--tests/auto/core/common/qbackendnodetester.h2
-rw-r--r--tests/auto/render/textures/tst_textures.cpp69
7 files changed, 104 insertions, 12 deletions
diff --git a/src/render/backend/managers_p.h b/src/render/backend/managers_p.h
index c9bcb799e..6af34fa6d 100644
--- a/src/render/backend/managers_p.h
+++ b/src/render/backend/managers_p.h
@@ -230,12 +230,27 @@ public:
m_textureIdsToCleanup.push_back(id);
}
+ // Called in AspectThread by Texture node functor create
+ void removeTextureIdToCleanup(Qt3DCore::QNodeId id)
+ {
+ m_textureIdsToCleanup.removeAll(id);
+ }
+
// Called by RenderThread in updateGLResources (locked)
QVector<Qt3DCore::QNodeId> takeTexturesIdsToCleanup()
{
return std::move(m_textureIdsToCleanup);
}
+#ifdef QT_BUILD_INTERNAL
+ // For unit testing purposes only
+ QVector<Qt3DCore::QNodeId> textureIdsToCleanup() const
+ {
+ return m_textureIdsToCleanup;
+ }
+
+#endif
+
private:
QVector<Qt3DCore::QNodeId> m_textureIdsToCleanup;
};
diff --git a/src/render/renderers/opengl/renderer/renderer.cpp b/src/render/renderers/opengl/renderer/renderer.cpp
index f04b864a3..27d46cc81 100644
--- a/src/render/renderers/opengl/renderer/renderer.cpp
+++ b/src/render/renderers/opengl/renderer/renderer.cpp
@@ -1191,16 +1191,13 @@ void Renderer::updateGLResources()
glTexture->getOrCreateGLTexture();
}
}
- // When Textures are cleaned up, their id is saved
- // so that they can be cleaned up in the render thread
- // Note: we perform this step in second so that the previous updateTexture call
- // has a chance to find a shared texture
+ // When Textures are cleaned up, their id is saved so that they can be
+ // cleaned up in the render thread Note: we perform this step in second so
+ // that the previous updateTexture call has a chance to find a shared
+ // texture and avoid possible destroying recreating a new texture
const QVector<Qt3DCore::QNodeId> cleanedUpTextureIds = m_nodesManager->textureManager()->takeTexturesIdsToCleanup();
- for (const Qt3DCore::QNodeId textureCleanedUpId: cleanedUpTextureIds) {
+ for (const Qt3DCore::QNodeId textureCleanedUpId: cleanedUpTextureIds)
cleanupTexture(m_nodesManager->textureManager()->lookupResource(textureCleanedUpId));
- // We can really release the texture at this point
- m_nodesManager->textureManager()->releaseResource(textureCleanedUpId);
- }
}
// Render Thread
diff --git a/src/render/texture/texture.cpp b/src/render/texture/texture.cpp
index 2585165e7..914a4d9d8 100644
--- a/src/render/texture/texture.cpp
+++ b/src/render/texture/texture.cpp
@@ -372,6 +372,10 @@ Qt3DCore::QBackendNode *TextureFunctor::create(const Qt3DCore::QNodeCreatedChang
Texture *backend = m_textureNodeManager->getOrCreateResource(change->subjectId());
backend->setTextureImageManager(m_textureImageManager);
backend->setRenderer(m_renderer);
+ // Remove id from cleanupList if for some reason we were in the dirty list of texture
+ // (Can happen when a node destroyed is followed by a node created change
+ // in the same loop, when changing parent for instance)
+ m_textureNodeManager->removeTextureIdToCleanup(change->subjectId());
return backend;
}
@@ -383,9 +387,9 @@ Qt3DCore::QBackendNode *TextureFunctor::get(Qt3DCore::QNodeId id) const
void TextureFunctor::destroy(Qt3DCore::QNodeId id) const
{
m_textureNodeManager->addTextureIdToCleanup(id);
- // We only add ourselves to the dirty list
- // The actual removal needs to be performed after we have
- // destroyed the associated APITexture in the RenderThread
+ // We add ourselves to the dirty list to tell the shared texture managers
+ // in the renderer that this texture has been destroyed
+ m_textureNodeManager->releaseResource(id);
}
diff --git a/src/render/texture/texture_p.h b/src/render/texture/texture_p.h
index 2c71eb10a..7e23f124c 100644
--- a/src/render/texture/texture_p.h
+++ b/src/render/texture/texture_p.h
@@ -175,7 +175,7 @@ private:
QMutex m_flagsMutex;
};
-class TextureFunctor : public Qt3DCore::QBackendNodeMapper
+class Q_AUTOTEST_EXPORT TextureFunctor : public Qt3DCore::QBackendNodeMapper
{
public:
explicit TextureFunctor(AbstractRenderer *renderer,
diff --git a/tests/auto/core/common/qbackendnodetester.cpp b/tests/auto/core/common/qbackendnodetester.cpp
index 6f87e10d9..5d4a10b81 100644
--- a/tests/auto/core/common/qbackendnodetester.cpp
+++ b/tests/auto/core/common/qbackendnodetester.cpp
@@ -68,6 +68,11 @@ void QBackendNodeTester::sceneChangeEvent(QBackendNode *backend, const Qt3DCore:
backend->sceneChangeEvent(e);
}
+QNodeCreatedChangeBasePtr QBackendNodeTester::creationChange(QNode *frontend) const
+{
+ return frontend->createNodeCreationChange();
+}
+
} // namespace Qt3DCore
QT_END_NAMESPACE
diff --git a/tests/auto/core/common/qbackendnodetester.h b/tests/auto/core/common/qbackendnodetester.h
index 9f266e40d..a9738dff0 100644
--- a/tests/auto/core/common/qbackendnodetester.h
+++ b/tests/auto/core/common/qbackendnodetester.h
@@ -40,6 +40,7 @@
#include <QObject>
#include <Qt3DCore/qnodeid.h>
#include <Qt3DCore/qscenechange.h>
+#include <Qt3DCore/qnodecreatedchange.h>
QT_BEGIN_NAMESPACE
@@ -58,6 +59,7 @@ public:
void setPeerId(QBackendNode *backend, QNodeId id);
void simulateInitialization(QNode *frontend, QBackendNode *backend);
void sceneChangeEvent(QBackendNode *backend, const Qt3DCore::QSceneChangePtr &e);
+ Qt3DCore::QNodeCreatedChangeBasePtr creationChange(QNode *frontend) const;
};
} // namespace Qt3DCore
diff --git a/tests/auto/render/textures/tst_textures.cpp b/tests/auto/render/textures/tst_textures.cpp
index f50131e12..364bfd7a9 100644
--- a/tests/auto/render/textures/tst_textures.cpp
+++ b/tests/auto/render/textures/tst_textures.cpp
@@ -583,6 +583,75 @@ private Q_SLOTS:
QVERIFY(texImgDataMgr->getData(frontendGenerator).isNull());
QVERIFY(texImgDataMgr->getData(backendGenerator).isNull());
}
+
+ void checkTextureIsMarkedForDeletion()
+ {
+ QScopedPointer<Qt3DRender::Render::NodeManagers> mgrs(new Qt3DRender::Render::NodeManagers());
+ Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous);
+ Qt3DRender::Render::TextureManager *texMgr = mgrs->textureManager();
+ Qt3DRender::Render::TextureImageManager *texImgMgr = mgrs->textureImageManager();
+ renderer.setNodeManagers(mgrs.data());
+
+ Qt3DRender::Render::TextureFunctor textureBackendNodeMapper(&renderer,
+ texMgr,
+ texImgMgr);
+
+ // GIVEN
+ Qt3DRender::QAbstractTexture* frontendTexture = createQTexture(1, {1}, true);
+
+ Qt3DRender::Render::Texture *backendTexture = static_cast<Qt3DRender::Render::Texture *>(textureBackendNodeMapper.create(creationChange(frontendTexture)));
+ simulateInitialization(frontendTexture, backendTexture);
+
+ // THEN
+ QVERIFY(backendTexture != nullptr);
+ QCOMPARE(texMgr->textureIdsToCleanup().size(), 0);
+
+ QCOMPARE(texMgr->lookupResource(frontendTexture->id()), backendTexture);
+
+ // WHEN
+ textureBackendNodeMapper.destroy(frontendTexture->id());
+
+ // THEN
+ QCOMPARE(texMgr->textureIdsToCleanup().size(), 1);
+ QCOMPARE(texMgr->textureIdsToCleanup().first(), frontendTexture->id());
+ QVERIFY(texMgr->lookupResource(frontendTexture->id()) == nullptr);
+ }
+
+ void checkTextureDestructionReconstructionWithinSameLoop()
+ {
+ QScopedPointer<Qt3DRender::Render::NodeManagers> mgrs(new Qt3DRender::Render::NodeManagers());
+ Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous);
+ Qt3DRender::Render::TextureManager *texMgr = mgrs->textureManager();
+ Qt3DRender::Render::TextureImageManager *texImgMgr = mgrs->textureImageManager();
+ renderer.setNodeManagers(mgrs.data());
+
+ Qt3DRender::Render::TextureFunctor textureBackendNodeMapper(&renderer,
+ texMgr,
+ texImgMgr);
+
+ // GIVEN
+ Qt3DRender::QAbstractTexture* frontendTexture = createQTexture(1, {1}, true);
+
+ Qt3DRender::Render::Texture *backendTexture = static_cast<Qt3DRender::Render::Texture *>(textureBackendNodeMapper.create(creationChange(frontendTexture)));
+ simulateInitialization(frontendTexture, backendTexture);
+
+ // WHEN
+ textureBackendNodeMapper.destroy(frontendTexture->id());
+
+ // THEN
+ QCOMPARE(texMgr->textureIdsToCleanup().size(), 1);
+ QCOMPARE(texMgr->textureIdsToCleanup().first(), frontendTexture->id());
+ QVERIFY(texMgr->lookupResource(frontendTexture->id()) == nullptr);
+
+ // WHEN
+ backendTexture = static_cast<Qt3DRender::Render::Texture *>(textureBackendNodeMapper.create(creationChange(frontendTexture)));
+ simulateInitialization(frontendTexture, backendTexture);
+
+ // THEN
+ QVERIFY(backendTexture != nullptr);
+ QCOMPARE(texMgr->textureIdsToCleanup().size(), 0);
+ QCOMPARE(texMgr->lookupResource(frontendTexture->id()), backendTexture);
+ }
};
QTEST_MAIN(tst_RenderTextures)