summaryrefslogtreecommitdiffstats
path: root/tests/auto/render/opengl/textures/tst_textures.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/render/opengl/textures/tst_textures.cpp')
-rw-r--r--tests/auto/render/opengl/textures/tst_textures.cpp821
1 files changed, 821 insertions, 0 deletions
diff --git a/tests/auto/render/opengl/textures/tst_textures.cpp b/tests/auto/render/opengl/textures/tst_textures.cpp
new file mode 100644
index 000000000..5343a6fde
--- /dev/null
+++ b/tests/auto/render/opengl/textures/tst_textures.cpp
@@ -0,0 +1,821 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// TODO Remove in Qt6
+#include <QtCore/qcompilerdetection.h>
+QT_WARNING_DISABLE_DEPRECATED
+
+#include <QtTest/QTest>
+#include <qbackendnodetester.h>
+#include <qtextureimagedatagenerator.h>
+#include <Qt3DRender/qtexture.h>
+#include <Qt3DRender/qtextureimage.h>
+#include <Qt3DRender/qtexturedata.h>
+
+#include <renderer_p.h>
+#include <glresourcemanagers_p.h>
+#include <gltexture_p.h>
+#include <Qt3DRender/private/texture_p.h>
+#include <Qt3DRender/private/textureimage_p.h>
+#include <Qt3DRender/private/nodemanagers_p.h>
+#include <Qt3DRender/private/managers_p.h>
+#include <Qt3DRender/private/qtexture_p.h>
+
+#include <testrenderer.h>
+
+/**
+ * @brief Dummy QTextureImageDataGenerator
+ */
+class TestImageDataGenerator : public Qt3DRender::QTextureImageDataGenerator
+{
+ int m_id;
+public:
+ TestImageDataGenerator(int id) : m_id(id) {}
+
+ Qt3DRender::QTextureImageDataPtr operator ()() override {
+ return Qt3DRender::QTextureImageDataPtr::create();
+ }
+
+ bool operator ==(const Qt3DRender::QTextureImageDataGenerator &other) const override {
+ const TestImageDataGenerator *otherFunctor = Qt3DRender::functor_cast<TestImageDataGenerator>(&other);
+ return (otherFunctor != nullptr && otherFunctor->m_id == m_id);
+ }
+
+ QT3D_FUNCTOR(TestImageDataGenerator)
+};
+
+/**
+ * @brief Dummy QTextureGenerator
+ */
+class TestTextureGenerator : public Qt3DRender::QTextureGenerator
+{
+ int m_id;
+public:
+ TestTextureGenerator(int id) : m_id(id) {}
+
+ Qt3DRender::QTextureDataPtr operator ()() override {
+ return Qt3DRender::QTextureDataPtr::create();
+ }
+
+ bool operator ==(const Qt3DRender::QTextureGenerator &other) const override {
+ const TestTextureGenerator *otherFunctor = Qt3DRender::functor_cast<TestTextureGenerator>(&other);
+ return (otherFunctor != nullptr && otherFunctor->m_id == m_id);
+ }
+
+ QT3D_FUNCTOR(TestTextureGenerator)
+};
+
+typedef QSharedPointer<TestTextureGenerator> TestTextureGeneratorPtr;
+
+class TestTexturePrivate : public Qt3DRender::QAbstractTexturePrivate
+{
+public:
+ int genId;
+};
+
+/**
+ * @brief Test QTexture. Assign texture data functor if genId > 0.
+ */
+class TestTexture : public Qt3DRender::QAbstractTexture
+{
+public:
+ TestTexture(int genId, Qt3DCore::QNode *p = nullptr)
+ : QAbstractTexture(*new TestTexturePrivate(), p)
+ {
+ d_func()->genId = genId;
+ if (genId > 0)
+ d_func()->setDataFunctor(TestTextureGeneratorPtr::create(genId));
+ }
+private:
+ Q_DECLARE_PRIVATE(TestTexture)
+};
+
+class TestSharedGLTexturePrivate : public Qt3DRender::QAbstractTexturePrivate
+{
+};
+
+class TestSharedGLTexture : public Qt3DRender::QAbstractTexture
+{
+public:
+ TestSharedGLTexture(int textureId, Qt3DCore::QNode *p = nullptr)
+ : QAbstractTexture(*new TestSharedGLTexturePrivate(), p)
+ {
+ d_func()->m_sharedTextureId = textureId;
+ }
+
+private:
+ Q_DECLARE_PRIVATE(TestSharedGLTexture)
+};
+
+
+/**
+ * @brief Test QTextureImage
+ */
+class TestTextureImage : public Qt3DRender::QAbstractTextureImage
+{
+public:
+ TestTextureImage(int genId, Qt3DCore::QNode *p = nullptr)
+ : QAbstractTextureImage(p)
+ , m_genId(genId)
+ {
+ }
+
+ void updateGenerator()
+ {
+ Qt3DRender::QAbstractTextureImage::notifyDataGeneratorChanged();
+ }
+
+ Qt3DRender::QTextureImageDataGeneratorPtr dataGenerator() const
+ {
+ return Qt3DRender::QTextureImageDataGeneratorPtr(new TestImageDataGenerator(m_genId));
+ }
+protected:
+ int m_genId;
+};
+
+class EmptyTextureImage : public Qt3DRender::QAbstractTextureImage
+{
+public:
+ EmptyTextureImage(Qt3DCore::QNode *p = nullptr)
+ : QAbstractTextureImage(p)
+ {
+ }
+
+ Qt3DRender::QTextureImageDataGeneratorPtr dataGenerator() const
+ {
+ return {};
+ }
+};
+
+class tst_RenderTextures : public Qt3DCore::QBackendNodeTester
+{
+ Q_OBJECT
+
+ Qt3DRender::QAbstractTexture *createQTexture(int genId,
+ const QVector<int> &imgGenIds,
+ bool genMipMaps)
+ {
+ TestTexture *tex = new TestTexture(genId);
+
+ for (int imgGen : imgGenIds)
+ tex->addTextureImage(new TestTextureImage(imgGen));
+ tex->setGenerateMipMaps(genMipMaps);
+
+ return tex;
+ }
+
+ Qt3DRender::QAbstractTexture *createQTextureWithTextureId(int textureId)
+ {
+ return new TestSharedGLTexture(textureId);
+ }
+
+ Qt3DRender::Render::Texture *createBackendTexture(Qt3DRender::QAbstractTexture *frontend,
+ Qt3DRender::Render::TextureManager *texMgr,
+ Qt3DRender::Render::TextureImageManager *texImgMgr,
+ Qt3DRender::Render::AbstractRenderer *renderer)
+ {
+ Qt3DRender::Render::Texture *backend = texMgr->getOrCreateResource(frontend->id());
+ backend->setRenderer(renderer);
+ simulateInitializationSync(frontend, backend);
+
+ // create texture images
+ for (const auto texImgFrontend : frontend->textureImages()) {
+ // make sure TextureImageManager has backend node for this QTextureImage
+ if (!texImgMgr->contains(texImgFrontend->id())) {
+ Qt3DRender::Render::TextureImage *texImgBackend = texImgMgr->getOrCreateResource(texImgFrontend->id());
+ texImgBackend->setRenderer(renderer);
+ simulateInitializationSync(texImgFrontend, texImgBackend);
+ }
+ }
+
+ return backend;
+ }
+
+private Q_SLOTS:
+
+ void shouldCreateSameGLTextures()
+ {
+ QSKIP("Texture Sharing is now disabled");
+ QScopedPointer<Qt3DRender::Render::NodeManagers> mgrs(new Qt3DRender::Render::NodeManagers());
+ Qt3DRender::Render::OpenGL::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous);
+ renderer.setNodeManagers(mgrs.data());
+
+ // GIVEN
+ Qt3DRender::QAbstractTexture *tex1a = createQTexture(-1, {1,2}, true);
+ Qt3DRender::QAbstractTexture *tex1b = createQTexture(-1, {1,2}, true);
+
+ // WHEN
+ Qt3DRender::Render::Texture *bt1a = createBackendTexture(tex1a,
+ mgrs->textureManager(),
+ mgrs->textureImageManager(),
+ &renderer);
+ Qt3DRender::Render::Texture *bt1b = createBackendTexture(tex1b,
+ mgrs->textureManager(),
+ mgrs->textureImageManager(),
+ &renderer);
+ renderer.updateTexture(bt1a);
+ renderer.updateTexture(bt1b);
+
+ // THEN
+ QCOMPARE(renderer.glResourceManagers()->glTextureManager()->lookupResource(bt1a->peerId()),
+ renderer.glResourceManagers()->glTextureManager()->lookupResource(bt1b->peerId()));
+ renderer.shutdown();
+ }
+
+ void shouldCreateDifferentGLTexturess()
+ {
+ QScopedPointer<Qt3DRender::Render::NodeManagers> mgrs(new Qt3DRender::Render::NodeManagers());
+ Qt3DRender::Render::OpenGL::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous);
+ renderer.setNodeManagers(mgrs.data());
+
+ // GIVEN
+ QVector<Qt3DRender::QAbstractTexture*> textures;
+ textures << createQTexture(-1, {1,2}, true);
+ textures << createQTexture(-1, {1,2}, false);
+ textures << createQTexture(1, {1,2}, true);
+ textures << createQTexture(1, {1,2}, false);
+ textures << createQTexture(1, {1,2,3}, true);
+ textures << createQTexture(1, {1,2,3}, false);
+
+ // WHEN
+ QVector<Qt3DRender::Render::Texture*> backend;
+ for (auto *t : textures) {
+ Qt3DRender::Render::Texture *backendTexture = createBackendTexture(t,
+ mgrs->textureManager(),
+ mgrs->textureImageManager(),
+ &renderer);
+ backend.push_back(backendTexture);
+ renderer.updateTexture(backendTexture);
+ }
+
+ // THEN
+
+ // no 2 textures must be the same
+ for (int i = 0; i < backend.size(); i++)
+ for (int k = i+1; k < backend.size(); k++)
+ QVERIFY(renderer.glResourceManagers()->glTextureManager()->lookupResource(backend[i]->peerId()) !=
+ renderer.glResourceManagers()->glTextureManager()->lookupResource(backend[k]->peerId()));
+
+ QVector<Qt3DRender::Render::OpenGL::GLTexture *> glTextures;
+ for (Qt3DRender::Render::Texture *t : backend)
+ glTextures.push_back(renderer.glResourceManagers()->glTextureManager()->lookupResource(t->peerId()));
+
+ // some texture generators must be the same
+ QVERIFY(glTextures[0]->textureGenerator().data() == nullptr);
+ QVERIFY(glTextures[1]->textureGenerator().data() == nullptr);
+ QCOMPARE(*(glTextures[2]->textureGenerator()), *(glTextures[3]->textureGenerator()));
+
+ // some images must be the same
+ QCOMPARE(glTextures[0]->images(), glTextures[1]->images());
+ QCOMPARE(glTextures[0]->images(), glTextures[2]->images());
+ QCOMPARE(glTextures[0]->images(), glTextures[3]->images());
+ QCOMPARE(glTextures[4]->images(), glTextures[5]->images());
+
+ QCOMPARE(glTextures[0]->properties(), glTextures[2]->properties());
+ QCOMPARE(glTextures[1]->properties(), glTextures[3]->properties());
+ QVERIFY(glTextures[0]->properties() != glTextures[1]->properties());
+
+ renderer.shutdown();
+ }
+
+ void shouldCreateDifferentGLTexturesWhenUsingSharedTextureIds()
+ {
+ QScopedPointer<Qt3DRender::Render::NodeManagers> mgrs(new Qt3DRender::Render::NodeManagers());
+ Qt3DRender::Render::OpenGL::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous);
+ renderer.setNodeManagers(mgrs.data());
+
+ Qt3DRender::Render::OpenGL::GLResourceManagers *glMgrs = renderer.glResourceManagers();
+
+ // both texture having the same sharedTextureId
+ {
+ // GIVEN
+ Qt3DRender::QAbstractTexture *tex1a = createQTextureWithTextureId(1);
+ Qt3DRender::QAbstractTexture *tex1b = createQTextureWithTextureId(1);
+
+ // WHEN
+ Qt3DRender::Render::Texture *bt1 = createBackendTexture(tex1a,
+ mgrs->textureManager(),
+ mgrs->textureImageManager(),
+ &renderer);
+ Qt3DRender::Render::Texture *bt2 = createBackendTexture(tex1b,
+ mgrs->textureManager(),
+ mgrs->textureImageManager(),
+ &renderer);
+ // THEN
+ QCOMPARE(bt1->sharedTextureId(), 1);
+ QCOMPARE(bt2->sharedTextureId(), 1);
+
+ // WHEN
+ renderer.updateTexture(bt1);
+ renderer.updateTexture(bt2);
+
+ // THEN
+ Qt3DRender::Render::OpenGL::GLTexture *glt1 = glMgrs->glTextureManager()->lookupResource(bt1->peerId());
+ Qt3DRender::Render::OpenGL::GLTexture *glt2 = glMgrs->glTextureManager()->lookupResource(bt2->peerId());
+ QVERIFY(glt1 != glt2);
+ QCOMPARE(glt1->sharedTextureId(), bt1->sharedTextureId());
+ QCOMPARE(glt2->sharedTextureId(), bt2->sharedTextureId());
+ }
+
+ // textures having a different sharedTextureId
+ {
+ // GIVEN
+ Qt3DRender::QAbstractTexture *tex1a = createQTextureWithTextureId(1);
+ Qt3DRender::QAbstractTexture *tex1b = createQTextureWithTextureId(2);
+
+ // WHEN
+ Qt3DRender::Render::Texture *bt1 = createBackendTexture(tex1a,
+ mgrs->textureManager(),
+ mgrs->textureImageManager(),
+ &renderer);
+ Qt3DRender::Render::Texture *bt2 = createBackendTexture(tex1b,
+ mgrs->textureManager(),
+ mgrs->textureImageManager(),
+ &renderer);
+ // THEN
+ QCOMPARE(bt1->sharedTextureId(), 1);
+ QCOMPARE(bt2->sharedTextureId(), 2);
+
+ // WHEN
+ renderer.updateTexture(bt1);
+ renderer.updateTexture(bt2);
+
+ // THEN
+ Qt3DRender::Render::OpenGL::GLTexture *glt1 = glMgrs->glTextureManager()->lookupResource(bt1->peerId());
+ Qt3DRender::Render::OpenGL::GLTexture *glt2 = glMgrs->glTextureManager()->lookupResource(bt2->peerId());
+ QVERIFY(glt1 != glt2);
+ QCOMPARE(glt1->sharedTextureId(), bt1->sharedTextureId());
+ QCOMPARE(glt2->sharedTextureId(), bt2->sharedTextureId());
+ }
+
+ renderer.shutdown();
+ }
+
+ void generatorsShouldCreateSameData()
+ {
+ QScopedPointer<Qt3DRender::Render::NodeManagers> mgrs(new Qt3DRender::Render::NodeManagers());
+ Qt3DRender::Render::OpenGL::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous);
+ renderer.setNodeManagers(mgrs.data());
+
+ // GIVEN
+ QVector<Qt3DRender::QAbstractTexture*> textures;
+ textures << createQTexture(1, {1}, true);
+ textures << createQTexture(2, {1,2}, true);
+ textures << createQTexture(1, {1,2}, true);
+
+ // WHEN
+ QVector<Qt3DRender::Render::Texture*> backend;
+ for (auto *t : textures) {
+ Qt3DRender::Render::Texture *backendTexture = createBackendTexture(t,
+ mgrs->textureManager(),
+ mgrs->textureImageManager(),
+ &renderer);
+ backend.push_back(backendTexture);
+ renderer.updateTexture(backendTexture);
+ }
+
+ Qt3DRender::QTextureImageDataGeneratorPtr idg1a = renderer.glResourceManagers()->glTextureManager()->lookupResource(backend[0]->peerId())->images()[0].generator;
+ Qt3DRender::QTextureImageDataGeneratorPtr idg1b = renderer.glResourceManagers()->glTextureManager()->lookupResource(backend[1]->peerId())->images()[0].generator;
+ Qt3DRender::QTextureImageDataGeneratorPtr idg2 = renderer.glResourceManagers()->glTextureManager()->lookupResource(backend[1]->peerId())->images()[1].generator;
+ Qt3DRender::QTextureGeneratorPtr tg1a = renderer.glResourceManagers()->glTextureManager()->lookupResource(backend[0]->peerId())->textureGenerator();
+ Qt3DRender::QTextureGeneratorPtr tg1b = renderer.glResourceManagers()->glTextureManager()->lookupResource(backend[2]->peerId())->textureGenerator();
+ Qt3DRender::QTextureGeneratorPtr tg2 = renderer.glResourceManagers()->glTextureManager()->lookupResource(backend[1]->peerId())->textureGenerator();
+
+ // THEN
+ QVERIFY(idg1a);
+ QVERIFY(idg1b);
+ QVERIFY(idg2);
+ QVERIFY(tg1a);
+ QVERIFY(tg1b);
+ QVERIFY(tg2);
+
+ QCOMPARE(*idg1a, *idg1b);
+ QVERIFY(!(*idg1a == *idg2));
+ QCOMPARE(*tg1a, *tg1b);
+ QVERIFY(!(*tg1a == *tg2));
+
+ renderer.shutdown();
+ }
+
+ void checkTextureImageInitialState()
+ {
+ // GIVEN
+ Qt3DRender::Render::TextureImage img;
+
+ // THEN
+ QCOMPARE(img.layer(), 0);
+ QCOMPARE(img.mipLevel(), 0);
+ QCOMPARE(img.isDirty(), false);
+ QCOMPARE(img.face(), Qt3DRender::QAbstractTexture::CubeMapPositiveX);
+ QVERIFY(img.dataGenerator().isNull());
+ }
+
+ void checkTextureImageCleanupState()
+ {
+ // GIVEN
+ Qt3DRender::Render::OpenGL::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous);
+ TestTextureImage img(1);
+ img.setLayer(2);
+ img.setMipLevel(3);
+
+ // WHEN
+ Qt3DRender::Render::TextureImage texImgBackend;
+ texImgBackend.setRenderer(&renderer);
+ simulateInitializationSync(&img, &texImgBackend);
+ texImgBackend.cleanup();
+
+ // THEN
+ QCOMPARE(texImgBackend.isDirty(), false);
+ QCOMPARE(texImgBackend.layer(), 0);
+ QCOMPARE(texImgBackend.mipLevel(), 0);
+ QCOMPARE(texImgBackend.face(), Qt3DRender::QAbstractTexture::CubeMapPositiveX);
+ QVERIFY(texImgBackend.dataGenerator().isNull());
+
+ renderer.shutdown();
+ }
+
+ void checkTextureImageInitializeFromPeer()
+ {
+ // GIVEN
+ Qt3DRender::Render::OpenGL::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous);
+ TestTextureImage img(1);
+
+ {
+ // WHEN
+ img.setLayer(2);
+ img.setMipLevel(3);
+
+ Qt3DRender::Render::TextureImage texImgBackend;
+ texImgBackend.setRenderer(&renderer);
+ simulateInitializationSync(&img, &texImgBackend);
+
+ // THEN
+ QCOMPARE(texImgBackend.isEnabled(), true);
+ QCOMPARE(texImgBackend.isDirty(), true);
+ QCOMPARE(texImgBackend.peerId(), img.id());
+ QCOMPARE(texImgBackend.layer(), 2);
+ QCOMPARE(texImgBackend.mipLevel(), 3);
+ QCOMPARE(texImgBackend.face(), Qt3DRender::QAbstractTexture::CubeMapPositiveX);
+ QVERIFY(!texImgBackend.dataGenerator().isNull());
+ }
+
+ {
+ // WHEN
+ img.setEnabled(false);
+
+ Qt3DRender::Render::TextureImage texImgBackend;
+ texImgBackend.setRenderer(&renderer);
+ simulateInitializationSync(&img, &texImgBackend);
+
+ // THEN
+ QCOMPARE(texImgBackend.isEnabled(), false);
+ QCOMPARE(texImgBackend.peerId(), img.id());
+ }
+
+ renderer.shutdown();
+ }
+
+ void checkTextureImageSceneChangeEvents()
+ {
+ // GIVEN
+ Qt3DRender::Render::TextureImage backendImage;
+ TestTextureImage textureImage(1);
+ TestRenderer renderer;
+ backendImage.setRenderer(&renderer);
+ simulateInitializationSync(&textureImage, &backendImage);
+
+ {
+ // WHEN
+ const bool newValue = false;
+ textureImage.setEnabled(newValue);
+ backendImage.syncFromFrontEnd(&textureImage, false);
+
+ // THEN
+ QCOMPARE(backendImage.isEnabled(), newValue);
+ QVERIFY(backendImage.isDirty());
+ QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::AllDirty);
+ renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
+ backendImage.unsetDirty();
+ }
+
+ {
+ // WHEN
+ const int newValue = 7;
+ textureImage.setLayer(newValue);
+ backendImage.syncFromFrontEnd(&textureImage, false);
+
+ // THEN
+ QCOMPARE(backendImage.layer(), newValue);
+ QVERIFY(backendImage.isDirty());
+ QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::AllDirty);
+ renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
+ backendImage.unsetDirty();
+ }
+
+ {
+ // WHEN
+ const int newValue = 3;
+ textureImage.setMipLevel(newValue);
+ backendImage.syncFromFrontEnd(&textureImage, false);
+
+
+ // THEN
+ QCOMPARE(backendImage.mipLevel(), newValue);
+ QVERIFY(backendImage.isDirty());
+ QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::AllDirty);
+ renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
+ backendImage.unsetDirty();
+ }
+
+ {
+ // WHEN
+ const Qt3DRender::QAbstractTexture::CubeMapFace newValue = Qt3DRender::QAbstractTexture::CubeMapNegativeX;
+ textureImage.setFace(newValue);
+ backendImage.syncFromFrontEnd(&textureImage, false);
+
+ // THEN
+ QCOMPARE(backendImage.face(), newValue);
+ QVERIFY(backendImage.isDirty());
+ QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::AllDirty);
+ renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
+ backendImage.unsetDirty();
+ }
+
+ {
+ // WHEN
+ textureImage.updateGenerator();
+ backendImage.syncFromFrontEnd(&textureImage, false);
+
+ // THEN
+ QVERIFY(backendImage.isDirty());
+ QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::AllDirty);
+ renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
+ backendImage.unsetDirty();
+
+ // WHEN
+ textureImage.updateGenerator();
+ backendImage.syncFromFrontEnd(&textureImage, false);
+
+ // THEN
+ QVERIFY(backendImage.isDirty());
+ QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::AllDirty);
+ renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
+ backendImage.unsetDirty();
+ }
+
+ renderer.shutdown();
+ }
+
+ void checkTextureImageProperlyReleaseGenerator()
+ {
+ QScopedPointer<Qt3DRender::Render::NodeManagers> mgrs(new Qt3DRender::Render::NodeManagers());
+ Qt3DRender::Render::OpenGL::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous);
+ Qt3DRender::Render::TextureManager *texMgr = mgrs->textureManager();
+ Qt3DRender::Render::TextureImageManager *texImgMgr = mgrs->textureImageManager();
+ renderer.setNodeManagers(mgrs.data());
+
+ // GIVEN
+ Qt3DRender::QAbstractTexture* frontendTexture = createQTexture(1, {1}, true);
+
+ Qt3DRender::Render::Texture *backendTexture = texMgr->getOrCreateResource(frontendTexture->id());
+ backendTexture->setRenderer(&renderer);
+ simulateInitializationSync(frontendTexture, backendTexture);
+
+ // THEN
+ QCOMPARE(backendTexture->textureImageIds().size(), 1);
+ QCOMPARE(frontendTexture->textureImages().size(), 1);
+
+ // WHEN
+ TestTextureImage *texImgFrontend = static_cast<TestTextureImage *>(frontendTexture->textureImages().first());
+ const Qt3DRender::QTextureImageDataGeneratorPtr frontendGenerator = texImgFrontend->dataGenerator();
+
+ // THEN
+ QVERIFY(!frontendGenerator.isNull());
+
+ // WHEN
+ Qt3DRender::Render::TextureImage *texImgBackend = texImgMgr->getOrCreateResource(texImgFrontend->id());
+ texImgBackend->setRenderer(&renderer);
+ simulateInitializationSync(texImgFrontend, texImgBackend);
+
+ // THEN
+ qDebug() << frontendGenerator << texImgBackend->dataGenerator();
+ const Qt3DRender::QTextureImageDataGeneratorPtr backendGenerator = texImgFrontend->dataGenerator();
+ QVERIFY(frontendGenerator != backendGenerator);
+ QVERIFY(*frontendGenerator == *backendGenerator);
+
+ renderer.shutdown();
+ }
+
+ void checkTextureIsMarkedForDeletion()
+ {
+ QScopedPointer<Qt3DRender::Render::NodeManagers> mgrs(new Qt3DRender::Render::NodeManagers());
+ Qt3DRender::Render::OpenGL::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous);
+ Qt3DRender::Render::TextureManager *texMgr = mgrs->textureManager();
+ renderer.setNodeManagers(mgrs.data());
+
+ Qt3DRender::Render::TextureFunctor textureBackendNodeMapper(&renderer,
+ texMgr);
+
+ // GIVEN
+ Qt3DRender::QAbstractTexture* frontendTexture = createQTexture(1, {1}, true);
+
+ Qt3DRender::Render::Texture *backendTexture = static_cast<Qt3DRender::Render::Texture *>(textureBackendNodeMapper.create(creationChange(frontendTexture)));
+ backendTexture->setRenderer(&renderer);
+ simulateInitializationSync(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);
+
+ renderer.shutdown();
+ }
+
+ void checkTextureDestructionReconstructionWithinSameLoop()
+ {
+ QScopedPointer<Qt3DRender::Render::NodeManagers> mgrs(new Qt3DRender::Render::NodeManagers());
+ Qt3DRender::Render::OpenGL::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous);
+ Qt3DRender::Render::TextureManager *texMgr = mgrs->textureManager();
+ renderer.setNodeManagers(mgrs.data());
+
+ Qt3DRender::Render::TextureFunctor textureBackendNodeMapper(&renderer,
+ texMgr);
+
+ // GIVEN
+ Qt3DRender::QAbstractTexture* frontendTexture = createQTexture(1, {1}, true);
+
+ Qt3DRender::Render::Texture *backendTexture = static_cast<Qt3DRender::Render::Texture *>(textureBackendNodeMapper.create(creationChange(frontendTexture)));
+ backendTexture->setRenderer(&renderer);
+ simulateInitializationSync(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)));
+ backendTexture->setRenderer(&renderer);
+ simulateInitializationSync(frontendTexture, backendTexture);
+
+ // THEN
+ QVERIFY(backendTexture != nullptr);
+ QCOMPARE(texMgr->textureIdsToCleanup().size(), 0);
+ QCOMPARE(texMgr->lookupResource(frontendTexture->id()), backendTexture);
+
+ renderer.shutdown();
+ }
+
+ void checkTextureImageDirtinessPropagatesToTextures()
+ {
+ // GIVEN
+ QScopedPointer<Qt3DRender::Render::NodeManagers> mgrs(new Qt3DRender::Render::NodeManagers());
+ Qt3DRender::Render::OpenGL::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous);
+ Qt3DRender::Render::TextureManager *texMgr = mgrs->textureManager();
+ Qt3DRender::Render::TextureImageManager *texImgMgr = mgrs->textureImageManager();
+ renderer.setNodeManagers(mgrs.data());
+
+ Qt3DRender::QTexture2D *texture1 = new Qt3DRender::QTexture2D();
+ TestTextureImage *image1 = new TestTextureImage(1);
+
+ Qt3DRender::QTexture2D *texture2 = new Qt3DRender::QTexture2D();
+ TestTextureImage *image2 = new TestTextureImage(2);
+
+ Qt3DRender::QTexture2D *texture3 = new Qt3DRender::QTexture2D();
+
+ texture1->addTextureImage(image1);
+ texture2->addTextureImage(image2);
+ texture3->addTextureImage(image1);
+ texture3->addTextureImage(image2);
+
+ Qt3DRender::Render::Texture *backendTexture1 = texMgr->getOrCreateResource(texture1->id());
+ Qt3DRender::Render::Texture *backendTexture2 = texMgr->getOrCreateResource(texture2->id());
+ Qt3DRender::Render::Texture *backendTexture3 = texMgr->getOrCreateResource(texture3->id());
+ Qt3DRender::Render::TextureImage *backendImage1 = texImgMgr->getOrCreateResource(image1->id());
+ Qt3DRender::Render::TextureImage *backendImage2 = texImgMgr->getOrCreateResource(image2->id());
+
+ backendTexture1->setRenderer(&renderer);
+ backendTexture2->setRenderer(&renderer);
+ backendTexture3->setRenderer(&renderer);
+ backendImage1->setRenderer(&renderer);
+ backendImage2->setRenderer(&renderer);
+
+ simulateInitializationSync(texture1, backendTexture1);
+ simulateInitializationSync(texture2, backendTexture2);
+ simulateInitializationSync(texture3, backendTexture3);
+ simulateInitializationSync(image1, backendImage1);
+ simulateInitializationSync(image2, backendImage2);
+
+ // THEN
+ QCOMPARE(backendTexture1->textureImageIds().size(), 1);
+ QCOMPARE(backendTexture1->textureImageIds().first(), image1->id());
+ QCOMPARE(backendTexture2->textureImageIds().size(), 1);
+ QCOMPARE(backendTexture2->textureImageIds().first(), image2->id());
+ QCOMPARE(backendTexture3->textureImageIds().size(), 2);
+ QCOMPARE(backendTexture3->textureImageIds().first(), image1->id());
+ QCOMPARE(backendTexture3->textureImageIds().last(), image2->id());
+
+ // WHEN
+ backendTexture1->unsetDirty();
+ backendTexture2->unsetDirty();
+ backendTexture3->unsetDirty();
+ backendImage1->unsetDirty();
+ backendImage2->unsetDirty();
+
+ // THEN
+ QVERIFY(backendTexture1->dirtyFlags() == Qt3DRender::Render::Texture::NotDirty);
+ QVERIFY(backendTexture2->dirtyFlags() == Qt3DRender::Render::Texture::NotDirty);
+ QVERIFY(backendTexture3->dirtyFlags() == Qt3DRender::Render::Texture::NotDirty);
+
+ // WHEN
+ renderer.textureGathererJob()->run();
+
+ // THEN
+ QVERIFY(backendTexture1->dirtyFlags() == Qt3DRender::Render::Texture::NotDirty);
+ QVERIFY(backendTexture2->dirtyFlags() == Qt3DRender::Render::Texture::NotDirty);
+ QVERIFY(backendTexture3->dirtyFlags() == Qt3DRender::Render::Texture::NotDirty);
+
+ // WHEN
+ // Make Image1 dirty
+ image1->updateGenerator();
+ backendImage1->syncFromFrontEnd(image1, false);
+
+ // THEN
+ QVERIFY(backendImage1->isDirty());
+ QVERIFY(backendTexture1->dirtyFlags() == Qt3DRender::Render::Texture::NotDirty);
+ QVERIFY(backendTexture2->dirtyFlags() == Qt3DRender::Render::Texture::NotDirty);
+ QVERIFY(backendTexture3->dirtyFlags() == Qt3DRender::Render::Texture::NotDirty);
+
+ // WHEN
+ renderer.textureGathererJob()->run();
+
+ // THEN
+ QVERIFY(backendTexture1->dirtyFlags() & Qt3DRender::Render::Texture::DirtyImageGenerators);
+ QVERIFY(backendTexture2->dirtyFlags() == Qt3DRender::Render::Texture::NotDirty);
+ QVERIFY(backendTexture3->dirtyFlags() & Qt3DRender::Render::Texture::DirtyImageGenerators);
+
+ backendImage1->unsetDirty();
+ backendTexture1->unsetDirty();
+ backendTexture3->unsetDirty();
+
+ // WHEN
+ image2->updateGenerator();
+ backendImage2->syncFromFrontEnd(image2, false);
+
+ // THEN
+ QVERIFY(backendImage2->isDirty());
+ QVERIFY(backendTexture1->dirtyFlags() == Qt3DRender::Render::Texture::NotDirty);
+ QVERIFY(backendTexture2->dirtyFlags() == Qt3DRender::Render::Texture::NotDirty);
+ QVERIFY(backendTexture3->dirtyFlags() == Qt3DRender::Render::Texture::NotDirty);
+
+ // WHEN
+ renderer.textureGathererJob()->run();
+
+ QVERIFY(backendTexture1->dirtyFlags() == Qt3DRender::Render::Texture::NotDirty);
+ QVERIFY(backendTexture2->dirtyFlags() & Qt3DRender::Render::Texture::DirtyImageGenerators);
+ QVERIFY(backendTexture3->dirtyFlags() & Qt3DRender::Render::Texture::DirtyImageGenerators);
+
+ renderer.shutdown();
+ }
+};
+
+QTEST_MAIN(tst_RenderTextures)
+
+#include "tst_textures.moc"