diff options
Diffstat (limited to 'tests/auto/render')
67 files changed, 6586 insertions, 273 deletions
diff --git a/tests/auto/render/armature/armature.pro b/tests/auto/render/armature/armature.pro new file mode 100644 index 000000000..fc8d69eaa --- /dev/null +++ b/tests/auto/render/armature/armature.pro @@ -0,0 +1,12 @@ +TEMPLATE = app + +TARGET = tst_armature + +QT += core-private 3dcore 3dcore-private 3drender 3drender-private testlib + +CONFIG += testcase + +SOURCES += \ + tst_armature.cpp + +include(../../core/common/common.pri) diff --git a/tests/auto/render/armature/tst_armature.cpp b/tests/auto/render/armature/tst_armature.cpp new file mode 100644 index 000000000..2c481db7a --- /dev/null +++ b/tests/auto/render/armature/tst_armature.cpp @@ -0,0 +1,120 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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$ +** +****************************************************************************/ + +#include <QtTest/QTest> +#include <Qt3DRender/private/armature_p.h> +#include <Qt3DCore/qarmature.h> +#include <Qt3DCore/qskeleton.h> +#include <Qt3DCore/private/qnode_p.h> +#include <Qt3DCore/private/qscene_p.h> +#include <Qt3DCore/qpropertyupdatedchange.h> +#include <Qt3DCore/private/qbackendnode_p.h> +#include <qbackendnodetester.h> +#include <testpostmanarbiter.h> + +using namespace Qt3DCore; +using namespace Qt3DRender; +using namespace Qt3DRender::Render; + +class tst_Armature: public Qt3DCore::QBackendNodeTester +{ + Q_OBJECT + +private Q_SLOTS: + void checkPeerPropertyMirroring() + { + // GIVEN + Armature backendArmature; + QArmature armature; + auto skeleton = new QSkeleton; + + armature.setSkeleton(skeleton); + + // WHEN + simulateInitialization(&armature, &backendArmature); + + // THEN + QCOMPARE(backendArmature.peerId(), armature.id()); + QCOMPARE(backendArmature.isEnabled(), armature.isEnabled()); + QCOMPARE(backendArmature.skeletonId(), skeleton->id()); + } + + void checkInitialAndCleanedUpState() + { + // GIVEN + Armature backendArmature; + + // THEN + QVERIFY(backendArmature.peerId().isNull()); + QCOMPARE(backendArmature.isEnabled(), false); + QCOMPARE(backendArmature.skeletonId(), Qt3DCore::QNodeId()); + + // GIVEN + QArmature armature; + auto skeleton = new QSkeleton(); + armature.setSkeleton(skeleton); + + // WHEN + simulateInitialization(&armature, &backendArmature); + backendArmature.cleanup(); + + // THEN + QCOMPARE(backendArmature.skeletonId(), Qt3DCore::QNodeId()); + QCOMPARE(backendArmature.isEnabled(), false); + } + + void checkPropertyChanges() + { + // GIVEN + Armature backendArmature; + Qt3DCore::QPropertyUpdatedChangePtr updateChange; + + // WHEN + updateChange.reset(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId())); + updateChange->setPropertyName("enabled"); + updateChange->setValue(true); + backendArmature.sceneChangeEvent(updateChange); + + // THEN + QCOMPARE(backendArmature.isEnabled(), true); + + // WHEN + auto newSkeleton = new QSkeleton(); + updateChange.reset(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId())); + updateChange->setPropertyName("skeleton"); + updateChange->setValue(QVariant::fromValue(newSkeleton->id())); + backendArmature.sceneChangeEvent(updateChange); + + // THEN + QCOMPARE(backendArmature.skeletonId(), newSkeleton->id()); + } +}; + +QTEST_APPLESS_MAIN(tst_Armature) + +#include "tst_armature.moc" diff --git a/tests/auto/render/blitframebuffer/blitframebuffer.pro b/tests/auto/render/blitframebuffer/blitframebuffer.pro new file mode 100644 index 000000000..39531ae9a --- /dev/null +++ b/tests/auto/render/blitframebuffer/blitframebuffer.pro @@ -0,0 +1,12 @@ +TEMPLATE = app + +TARGET = tst_blitframebuffer + +QT += 3dcore 3dcore-private 3drender 3drender-private testlib + +CONFIG += testcase + +SOURCES += tst_blitframebuffer.cpp + +include(../../core/common/common.pri) +include(../commons/commons.pri) diff --git a/tests/auto/render/blitframebuffer/tst_blitframebuffer.cpp b/tests/auto/render/blitframebuffer/tst_blitframebuffer.cpp new file mode 100644 index 000000000..6c70b0e95 --- /dev/null +++ b/tests/auto/render/blitframebuffer/tst_blitframebuffer.cpp @@ -0,0 +1,196 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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$ +** +****************************************************************************/ + + +#include <QtTest/QTest> +#include <Qt3DRender/qblitframebuffer.h> +#include <Qt3DRender/private/qblitframebuffer_p.h> +#include <Qt3DRender/private/blitframebuffer_p.h> +#include <Qt3DCore/qpropertyupdatedchange.h> +#include "qbackendnodetester.h" +#include "testrenderer.h" + +class tst_BlitFramebuffer : public Qt3DCore::QBackendNodeTester +{ + Q_OBJECT + +private Q_SLOTS: + + void checkInitialState() + { + // GIVEN + Qt3DRender::Render::BlitFramebuffer backendBlitFramebuffer; + + // THEN + QCOMPARE(backendBlitFramebuffer.nodeType(), Qt3DRender::Render::FrameGraphNode::BlitFramebuffer); + QCOMPARE(backendBlitFramebuffer.isEnabled(), false); + QVERIFY(backendBlitFramebuffer.peerId().isNull()); + QVERIFY(backendBlitFramebuffer.sourceRenderTargetId().isNull()); + QVERIFY(backendBlitFramebuffer.destinationRenderTargetId().isNull()); + QCOMPARE(backendBlitFramebuffer.sourceRect(), QRect()); + QCOMPARE(backendBlitFramebuffer.destinationRect(), QRect()); + QCOMPARE(backendBlitFramebuffer.sourceAttachmentPoint(), Qt3DRender::QRenderTargetOutput::Color0); + QCOMPARE(backendBlitFramebuffer.destinationAttachmentPoint(), Qt3DRender::QRenderTargetOutput::Color0); + QCOMPARE(backendBlitFramebuffer.interpolationMethod(), Qt3DRender::QBlitFramebuffer::Linear); + } + + void checkInitializeFromPeer() + { + // GIVEN + Qt3DRender::QRenderTarget sourceTarget; + Qt3DRender::QRenderTarget destinationTarget; + Qt3DRender::QBlitFramebuffer blitFramebuffer; + blitFramebuffer.setSource(&sourceTarget); + blitFramebuffer.setDestination(&destinationTarget); + blitFramebuffer.setSourceRect(QRect(0,0,1,1)); + blitFramebuffer.setDestinationRect(QRect(0,0,1,1)); + blitFramebuffer.setSourceAttachmentPoint(Qt3DRender::QRenderTargetOutput::Color1); + blitFramebuffer.setDestinationAttachmentPoint(Qt3DRender::QRenderTargetOutput::Color1); + blitFramebuffer.setInterpolationMethod(Qt3DRender::QBlitFramebuffer::Nearest); + + { + // WHEN + Qt3DRender::Render::BlitFramebuffer backendBlitFramebuffer; + simulateInitialization(&blitFramebuffer, &backendBlitFramebuffer); + + // THEN + QCOMPARE(backendBlitFramebuffer.isEnabled(), true); + QCOMPARE(backendBlitFramebuffer.peerId(), blitFramebuffer.id()); + QCOMPARE(backendBlitFramebuffer.sourceRenderTargetId(), sourceTarget.id()); + QCOMPARE(backendBlitFramebuffer.destinationRenderTargetId(), destinationTarget.id()); + QCOMPARE(backendBlitFramebuffer.sourceRect(), QRect(0,0,1,1)); + QCOMPARE(backendBlitFramebuffer.destinationRect(), QRect(0,0,1,1)); + QCOMPARE(backendBlitFramebuffer.sourceAttachmentPoint(), Qt3DRender::QRenderTargetOutput::Color1); + QCOMPARE(backendBlitFramebuffer.destinationAttachmentPoint(), Qt3DRender::QRenderTargetOutput::Color1); + QCOMPARE(backendBlitFramebuffer.interpolationMethod(), Qt3DRender::QBlitFramebuffer::Nearest); + } + { + // WHEN + Qt3DRender::Render::BlitFramebuffer backendBlitFramebuffer; + blitFramebuffer.setEnabled(false); + simulateInitialization(&blitFramebuffer, &backendBlitFramebuffer); + + // THEN + QCOMPARE(backendBlitFramebuffer.peerId(), blitFramebuffer.id()); + QCOMPARE(backendBlitFramebuffer.isEnabled(), false); + } + } + + void checkSceneChangeEvents() + { + // GIVEN + Qt3DRender::Render::BlitFramebuffer backendBlitFramebuffer; + TestRenderer renderer; + backendBlitFramebuffer.setRenderer(&renderer); + + { + // WHEN + const bool newValue = false; + const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + change->setPropertyName("enabled"); + change->setValue(newValue); + backendBlitFramebuffer.sceneChangeEvent(change); + + // THEN + QCOMPARE(backendBlitFramebuffer.isEnabled(), newValue); + } + { + // WHEN + const Qt3DRender::QRenderTarget sourceRenderTarget; + const Qt3DCore::QNodeId newValue = sourceRenderTarget.id(); + const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + change->setPropertyName("sourceRenderTarget"); + change->setValue(QVariant::fromValue(newValue)); + backendBlitFramebuffer.sceneChangeEvent(change); + + // THEN + QCOMPARE(backendBlitFramebuffer.sourceRenderTargetId(), newValue); + } + { + // WHEN + const Qt3DRender::QRenderTarget destinationRenderTarget; + const Qt3DCore::QNodeId newValue = destinationRenderTarget.id(); + const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + change->setPropertyName("destinationRenderTarget"); + change->setValue(QVariant::fromValue(newValue)); + backendBlitFramebuffer.sceneChangeEvent(change); + + // THEN + QCOMPARE(backendBlitFramebuffer.destinationRenderTargetId(), newValue); + } + { + // WHEN + const auto newValue = QRect(0,0,1,1); + const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + change->setPropertyName("sourceRect"); + change->setValue(QVariant::fromValue(newValue)); + backendBlitFramebuffer.sceneChangeEvent(change); + + // THEN + QCOMPARE(backendBlitFramebuffer.sourceRect(), newValue); + } + { + // WHEN + const auto newValue = QRect(0,0,1,1); + const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + change->setPropertyName("destinationRect"); + change->setValue(QVariant::fromValue(newValue)); + backendBlitFramebuffer.sceneChangeEvent(change); + + // THEN + QCOMPARE(backendBlitFramebuffer.destinationRect(), newValue); + } + { + // WHEN + const auto newValue = Qt3DRender::QRenderTargetOutput::Color1; + const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + change->setPropertyName("sourceAttachmentPoint"); + change->setValue(QVariant::fromValue(newValue)); + backendBlitFramebuffer.sceneChangeEvent(change); + + // THEN + QCOMPARE(backendBlitFramebuffer.sourceAttachmentPoint(), newValue); + } + { + // WHEN + const auto newValue = Qt3DRender::QRenderTargetOutput::Color1; + const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + change->setPropertyName("destinationAttachmentPoint"); + change->setValue(QVariant::fromValue(newValue)); + backendBlitFramebuffer.sceneChangeEvent(change); + + // THEN + QCOMPARE(backendBlitFramebuffer.destinationAttachmentPoint(), newValue); + } + } + +}; + +QTEST_MAIN(tst_BlitFramebuffer) + +#include "tst_blitframebuffer.moc" diff --git a/tests/auto/render/buffer/tst_buffer.cpp b/tests/auto/render/buffer/tst_buffer.cpp index 6fa7960fe..f9a54c8bf 100644 --- a/tests/auto/render/buffer/tst_buffer.cpp +++ b/tests/auto/render/buffer/tst_buffer.cpp @@ -73,18 +73,20 @@ private Q_SLOTS: Qt3DRender::Render::Buffer renderBuffer; Qt3DRender::QBuffer buffer(Qt3DRender::QBuffer::IndexBuffer); Qt3DRender::Render::BufferManager bufferManager; + TestRenderer renderer; + buffer.setUsage(Qt3DRender::QBuffer::DynamicCopy); buffer.setData(QByteArrayLiteral("Corvette")); buffer.setDataGenerator(Qt3DRender::QBufferDataGeneratorPtr(new TestFunctor(883))); // WHEN + renderBuffer.setRenderer(&renderer); renderBuffer.setManager(&bufferManager); simulateInitialization(&buffer, &renderBuffer); // THEN QCOMPARE(renderBuffer.peerId(), buffer.id()); QCOMPARE(renderBuffer.isDirty(), true); - QCOMPARE(renderBuffer.type(), buffer.type()); QCOMPARE(renderBuffer.usage(), buffer.usage()); QCOMPARE(renderBuffer.data(), buffer.data()); QCOMPARE(renderBuffer.dataGenerator(), buffer.dataGenerator()); @@ -102,7 +104,6 @@ private Q_SLOTS: // THEN QCOMPARE(renderBuffer.isDirty(), false); - QCOMPARE(renderBuffer.type(), Qt3DRender::QBuffer::VertexBuffer); QCOMPARE(renderBuffer.usage(), Qt3DRender::QBuffer::StaticDraw); QVERIFY(renderBuffer.data().isEmpty()); QVERIFY(renderBuffer.peerId().isNull()); @@ -110,7 +111,7 @@ private Q_SLOTS: QVERIFY(renderBuffer.pendingBufferUpdates().empty()); // GIVEN - Qt3DRender::QBuffer buffer(Qt3DRender::QBuffer::IndexBuffer); + Qt3DRender::QBuffer buffer; buffer.setUsage(Qt3DRender::QBuffer::DynamicCopy); buffer.setData(QByteArrayLiteral("C7")); buffer.setDataGenerator(Qt3DRender::QBufferDataGeneratorPtr(new TestFunctor(73))); @@ -129,7 +130,6 @@ private Q_SLOTS: renderBuffer.sceneChangeEvent(updateChange); // THEN - QCOMPARE(renderBuffer.type(), Qt3DRender::QBuffer::IndexBuffer); QCOMPARE(renderBuffer.usage(), Qt3DRender::QBuffer::DynamicCopy); QCOMPARE(renderBuffer.isDirty(), true); QCOMPARE(renderBuffer.data(), QByteArrayLiteral("C7")); @@ -141,7 +141,6 @@ private Q_SLOTS: // THEN QCOMPARE(renderBuffer.isDirty(), false); - QCOMPARE(renderBuffer.type(), Qt3DRender::QBuffer::VertexBuffer); QCOMPARE(renderBuffer.usage(), Qt3DRender::QBuffer::StaticDraw); QVERIFY(renderBuffer.data().isEmpty()); QVERIFY(renderBuffer.dataGenerator().isNull()); @@ -156,27 +155,14 @@ private Q_SLOTS: renderBuffer.setRenderer(&renderer); // THEN - QVERIFY(renderBuffer.type() != Qt3DRender::QBuffer::IndexBuffer); QVERIFY(renderBuffer.data().isEmpty()); QVERIFY(renderBuffer.usage() != Qt3DRender::QBuffer::DynamicRead); QVERIFY(!renderBuffer.isDirty()); + QVERIFY(!(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::BuffersDirty)); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); // WHEN Qt3DCore::QPropertyUpdatedChangePtr updateChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId())); - updateChange->setValue(static_cast<int>(Qt3DRender::QBuffer::IndexBuffer)); - updateChange->setPropertyName("type"); - renderBuffer.sceneChangeEvent(updateChange); - - // THEN - QCOMPARE(renderBuffer.type(), Qt3DRender::QBuffer::IndexBuffer); - QVERIFY(renderer.dirtyBits() != 0); - QVERIFY(renderBuffer.isDirty()); - - renderBuffer.unsetDirty(); - QVERIFY(!renderBuffer.isDirty()); - - // WHEN - updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId()); updateChange->setValue(static_cast<int>(Qt3DRender::QBuffer::DynamicRead)); updateChange->setPropertyName("usage"); renderBuffer.sceneChangeEvent(updateChange); @@ -185,6 +171,9 @@ private Q_SLOTS: QCOMPARE(renderBuffer.usage(), Qt3DRender::QBuffer::DynamicRead); QVERIFY(renderBuffer.isDirty()); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::BuffersDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + renderBuffer.unsetDirty(); QVERIFY(!renderBuffer.isDirty()); @@ -201,6 +190,10 @@ private Q_SLOTS: QCOMPARE(renderBuffer.pendingBufferUpdates().first().offset, -1); renderBuffer.pendingBufferUpdates().clear(); + + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::BuffersDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + renderBuffer.unsetDirty(); QVERIFY(!renderBuffer.isDirty()); @@ -215,6 +208,9 @@ private Q_SLOTS: QCOMPARE(renderBuffer.dataGenerator(), functor); QVERIFY(renderBuffer.isDirty()); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::BuffersDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + renderBuffer.unsetDirty(); QVERIFY(!renderBuffer.isDirty()); @@ -228,6 +224,9 @@ private Q_SLOTS: QCOMPARE(renderBuffer.isSyncData(), true); QVERIFY(!renderBuffer.isDirty()); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::BuffersDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + // WHEN TestArbiter arbiter; Qt3DCore::QBackendNodePrivate::get(&renderBuffer)->setArbiter(&arbiter); @@ -258,6 +257,9 @@ private Q_SLOTS: QCOMPARE(renderBuffer.pendingBufferUpdates().first().offset, 2); QVERIFY(renderBuffer.isDirty()); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::BuffersDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + renderBuffer.unsetDirty(); QVERIFY(!renderBuffer.isDirty()); } @@ -268,8 +270,10 @@ private Q_SLOTS: Qt3DRender::Render::Buffer renderBuffer; Qt3DRender::QBuffer buffer(Qt3DRender::QBuffer::IndexBuffer); Qt3DRender::Render::BufferManager bufferManager; + TestRenderer renderer; // WHEN + renderBuffer.setRenderer(&renderer); renderBuffer.setManager(&bufferManager); simulateInitialization(&buffer, &renderBuffer); @@ -285,6 +289,27 @@ private Q_SLOTS: QVERIFY(buffers.first() == renderBuffer.peerId()); QVERIFY(bufferManager.takeBuffersToRelease().empty()); } + + void checkSetRendererDirtyOnInitialization() + { + // GIVEN + Qt3DRender::Render::Buffer renderBuffer; + Qt3DRender::QBuffer buffer(Qt3DRender::QBuffer::IndexBuffer); + Qt3DRender::Render::BufferManager bufferManager; + TestRenderer renderer; + + renderBuffer.setRenderer(&renderer); + renderBuffer.setManager(&bufferManager); + + // THEN + QCOMPARE(renderer.dirtyBits(), 0); + + // WHEN + simulateInitialization(&buffer, &renderBuffer); + + // THEN + QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::BuffersDirty); + } }; diff --git a/tests/auto/render/commons/testrenderer.h b/tests/auto/render/commons/testrenderer.h index 74f529fa0..031ca214b 100644 --- a/tests/auto/render/commons/testrenderer.h +++ b/tests/auto/render/commons/testrenderer.h @@ -60,6 +60,7 @@ public: QVector<Qt3DCore::QAspectJobPtr> renderBinJobs() Q_DECL_OVERRIDE { return QVector<Qt3DCore::QAspectJobPtr>(); } Qt3DCore::QAspectJobPtr pickBoundingVolumeJob() Q_DECL_OVERRIDE { return Qt3DCore::QAspectJobPtr(); } Qt3DCore::QAspectJobPtr syncTextureLoadingJob() Q_DECL_OVERRIDE { return Qt3DCore::QAspectJobPtr(); } + Qt3DCore::QAspectJobPtr expandBoundingVolumeJob() Q_DECL_OVERRIDE { return Qt3DCore::QAspectJobPtr(); } void setSceneRoot(Qt3DCore::QBackendNodeFactory *factory, Qt3DRender::Render::Entity *root) Q_DECL_OVERRIDE { Q_UNUSED(factory); Q_UNUSED(root); } Qt3DRender::Render::Entity *sceneRoot() const Q_DECL_OVERRIDE { return nullptr; } Qt3DRender::Render::FrameGraphNode *frameGraphRoot() const Q_DECL_OVERRIDE { return nullptr; } diff --git a/tests/auto/render/ddstextures/data/16x16-etc1.pkm b/tests/auto/render/ddstextures/data/16x16-etc1.pkm Binary files differnew file mode 100644 index 000000000..62ae2a11f --- /dev/null +++ b/tests/auto/render/ddstextures/data/16x16-etc1.pkm diff --git a/tests/auto/render/ddstextures/data/16x16-etc2.pkm b/tests/auto/render/ddstextures/data/16x16-etc2.pkm Binary files differnew file mode 100644 index 000000000..be391113e --- /dev/null +++ b/tests/auto/render/ddstextures/data/16x16-etc2.pkm diff --git a/tests/auto/render/ddstextures/ddstextures.pro b/tests/auto/render/ddstextures/ddstextures.pro index e81fd80d8..62456561f 100644 --- a/tests/auto/render/ddstextures/ddstextures.pro +++ b/tests/auto/render/ddstextures/ddstextures.pro @@ -30,7 +30,9 @@ OTHER_FILES = \ data/16x16x1-6-lumi.dds \ data/16x16x1-6-lumi-nomips.dds \ data/16x16x1-6-rgb.dds \ - data/16x16x1-6-rgb-nomips.dds + data/16x16x1-6-rgb-nomips.dds \ + data/16x16-etc1.pkm \ + data/16x16-etc2.pkm TESTDATA = data/* diff --git a/tests/auto/render/ddstextures/tst_ddstextures.cpp b/tests/auto/render/ddstextures/tst_ddstextures.cpp index 4d9a1fb32..1f33f20e2 100644 --- a/tests/auto/render/ddstextures/tst_ddstextures.cpp +++ b/tests/auto/render/ddstextures/tst_ddstextures.cpp @@ -73,6 +73,8 @@ void tst_DdsTextures::ddsImageData() { "data/16x16x1-6-bc1-dx10.dds", 16, 16, 1, 6, 5, QOpenGLTexture::RGBA_DXT1 }, { "data/16x16x1-6-bc3-nomips-dx10.dds", 16, 16, 1, 6, 1, QOpenGLTexture::RGBA_DXT5 }, { "data/16x16x1-6-bc3-dx10.dds", 16, 16, 1, 6, 5, QOpenGLTexture::RGBA_DXT5 }, + { "data/16x16-etc1.pkm", 16, 16, 1, 1, 1, QOpenGLTexture::RGB8_ETC1 }, + { "data/16x16-etc2.pkm", 16, 16, 1, 1, 1, QOpenGLTexture::RGB8_ETC2 }, }; for (unsigned i = 0; i < sizeof(textures)/sizeof(*textures); i++) { diff --git a/tests/auto/render/entity/tst_entity.cpp b/tests/auto/render/entity/tst_entity.cpp index d1a222c92..6ad958451 100644 --- a/tests/auto/render/entity/tst_entity.cpp +++ b/tests/auto/render/entity/tst_entity.cpp @@ -46,6 +46,7 @@ #include <Qt3DRender/QGeometryRenderer> #include <Qt3DRender/QObjectPicker> #include <Qt3DRender/QComputeCommand> +#include <Qt3DCore/QArmature> #include "testrenderer.h" @@ -62,6 +63,7 @@ QNodeId materialUuid(Entity *entity) { return entity->componentUuid<Material>(); QNodeId geometryRendererUuid(Entity *entity) { return entity->componentUuid<GeometryRenderer>(); } QNodeId objectPickerUuid(Entity *entity) { return entity->componentUuid<ObjectPicker>(); } QNodeId computeJobUuid(Entity *entity) { return entity->componentUuid<ComputeCommand>(); } +QNodeId armatureUuid(Entity *entity) { return entity->componentUuid<Armature>(); } QVector<QNodeId> layersUuid(Entity *entity) { return entity->componentsUuid<Layer>(); } QVector<QNodeId> shadersUuid(Entity *entity) { return entity->componentsUuid<ShaderData>(); } @@ -89,7 +91,8 @@ private slots: << new QLayer << new QShaderData << new QComputeCommand - << new QEnvironmentLight; + << new QEnvironmentLight + << new QArmature; QTest::newRow("all components") << components; } @@ -116,8 +119,10 @@ private slots: QVERIFY(entity.componentsUuid<Layer>().isEmpty()); QVERIFY(entity.componentsUuid<ShaderData>().isEmpty()); QVERIFY(entity.componentsUuid<EnvironmentLight>().isEmpty()); + QVERIFY(entity.componentUuid<Armature>().isNull()); QVERIFY(!entity.isBoundingVolumeDirty()); QVERIFY(entity.childrenHandles().isEmpty()); + QVERIFY(entity.layerIds().isEmpty()); // WHEN Q_FOREACH (QComponent *component, components) { @@ -144,10 +149,13 @@ private slots: QVERIFY(!entity.componentsUuid<Layer>().isEmpty()); QVERIFY(!entity.componentsUuid<ShaderData>().isEmpty()); QVERIFY(!entity.componentsUuid<EnvironmentLight>().isEmpty()); + QVERIFY(!entity.componentUuid<Armature>().isNull()); QVERIFY(entity.isBoundingVolumeDirty()); QVERIFY(!entity.childrenHandles().isEmpty()); + QVERIFY(!entity.layerIds().isEmpty()); QVERIFY(renderer.dirtyBits() != 0); - bool containsAll = entity.containsComponentsOfType<Transform, CameraLens, Material, GeometryRenderer, ObjectPicker, ComputeCommand>(); + bool containsAll = entity.containsComponentsOfType<Transform, + CameraLens, Material, GeometryRenderer, ObjectPicker, ComputeCommand, Armature>(); QVERIFY(containsAll); // WHEN @@ -163,9 +171,12 @@ private slots: QVERIFY(entity.componentsUuid<Layer>().isEmpty()); QVERIFY(entity.componentsUuid<ShaderData>().isEmpty()); QVERIFY(entity.componentsUuid<EnvironmentLight>().isEmpty()); + QVERIFY(entity.componentUuid<Armature>().isNull()); QVERIFY(!entity.isBoundingVolumeDirty()); QVERIFY(entity.childrenHandles().isEmpty()); - containsAll = entity.containsComponentsOfType<Transform, CameraLens, Material, GeometryRenderer, ObjectPicker, ComputeCommand>(); + QVERIFY(entity.layerIds().isEmpty()); + containsAll = entity.containsComponentsOfType<Transform, + CameraLens, Material, GeometryRenderer, ObjectPicker, ComputeCommand, Armature>(); QVERIFY(!containsAll); } @@ -191,6 +202,9 @@ private slots: component = new QComputeCommand; QTest::newRow("computeJob") << component << reinterpret_cast<void*>(computeJobUuid); + + component = new QArmature; + QTest::newRow("armature") << component << reinterpret_cast<void*>(armatureUuid); } void shouldHandleSingleComponentEvents() diff --git a/tests/auto/render/filtercompatibletechniquejob/BLACKLIST b/tests/auto/render/filtercompatibletechniquejob/BLACKLIST index c9313fd62..22cb59fab 100644 --- a/tests/auto/render/filtercompatibletechniquejob/BLACKLIST +++ b/tests/auto/render/filtercompatibletechniquejob/BLACKLIST @@ -1,4 +1,5 @@ -[checkRunRendererNotRunning] -windows -[checkRunRendererRunning] +#[checkRunRendererNotRunning] +#windows +#[checkRunRendererRunning] +#QTBUG-64271 windows diff --git a/tests/auto/render/geometry/tst_geometry.cpp b/tests/auto/render/geometry/tst_geometry.cpp index 6a8746f47..958edfd09 100644 --- a/tests/auto/render/geometry/tst_geometry.cpp +++ b/tests/auto/render/geometry/tst_geometry.cpp @@ -54,6 +54,7 @@ private Q_SLOTS: { // GIVEN Qt3DRender::Render::Geometry renderGeometry; + TestRenderer renderer; Qt3DRender::QGeometry geometry; Qt3DRender::QAttribute attr1; @@ -66,6 +67,7 @@ private Q_SLOTS: geometry.addAttribute(&attr3); geometry.addAttribute(&attr4); geometry.setBoundingVolumePositionAttribute(&attr1); + renderGeometry.setRenderer(&renderer); // WHEN simulateInitialization(&geometry, &renderGeometry); @@ -80,10 +82,31 @@ private Q_SLOTS: QCOMPARE(geometry.attributes().at(i)->id(), renderGeometry.attributes().at(i)); } + void checkSetRendererDirtyOnInitialization() + { + // GIVEN + Qt3DRender::Render::Geometry renderGeometry; + Qt3DRender::QGeometry geometry; + TestRenderer renderer; + + renderGeometry.setRenderer(&renderer); + + // THEN + QCOMPARE(renderer.dirtyBits(), 0); + + // WHEN + simulateInitialization(&geometry, &renderGeometry); + + // THEN + QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::GeometryDirty); + } + void checkInitialAndCleanedUpState() { // GIVEN + TestRenderer renderer; Qt3DRender::Render::Geometry renderGeometry; + renderGeometry.setRenderer(&renderer); // THEN QCOMPARE(renderGeometry.isDirty(), false); @@ -131,6 +154,8 @@ private Q_SLOTS: // THEN QCOMPARE(renderGeometry.attributes().count(), 1); QVERIFY(renderGeometry.isDirty()); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::GeometryDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); renderGeometry.unsetDirty(); QVERIFY(!renderGeometry.isDirty()); @@ -143,6 +168,8 @@ private Q_SLOTS: // THEN QCOMPARE(renderGeometry.attributes().count(), 0); QVERIFY(renderGeometry.isDirty()); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::GeometryDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); renderGeometry.unsetDirty(); QVERIFY(!renderGeometry.isDirty()); @@ -157,6 +184,8 @@ private Q_SLOTS: // THEN QCOMPARE(renderGeometry.boundingPositionAttribute(), boundingAttrId); QVERIFY(!renderGeometry.isDirty()); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::GeometryDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); } }; diff --git a/tests/auto/render/geometryrenderer/tst_geometryrenderer.cpp b/tests/auto/render/geometryrenderer/tst_geometryrenderer.cpp index d9ed000ab..af074def0 100644 --- a/tests/auto/render/geometryrenderer/tst_geometryrenderer.cpp +++ b/tests/auto/render/geometryrenderer/tst_geometryrenderer.cpp @@ -85,11 +85,13 @@ private Q_SLOTS: Qt3DRender::QGeometry geometry; Qt3DRender::QGeometryFactoryPtr factory(new TestFactory(1200)); Qt3DRender::Render::GeometryRendererManager geometryRendererManager; + TestRenderer renderer; geometryRenderer.setInstanceCount(1584); geometryRenderer.setVertexCount(1609); geometryRenderer.setIndexOffset(750); geometryRenderer.setFirstInstance(883); + geometryRenderer.setIndexBufferByteOffset(96); geometryRenderer.setRestartIndexValue(65536); geometryRenderer.setPrimitiveRestartEnabled(true); geometryRenderer.setPrimitiveType(Qt3DRender::QGeometryRenderer::Patches); @@ -98,6 +100,7 @@ private Q_SLOTS: geometryRenderer.setEnabled(false); // WHEN + renderGeometryRenderer.setRenderer(&renderer); renderGeometryRenderer.setManager(&geometryRendererManager); simulateInitialization(&geometryRenderer, &renderGeometryRenderer); @@ -108,6 +111,7 @@ private Q_SLOTS: QCOMPARE(renderGeometryRenderer.vertexCount(), geometryRenderer.vertexCount()); QCOMPARE(renderGeometryRenderer.indexOffset(), geometryRenderer.indexOffset()); QCOMPARE(renderGeometryRenderer.firstInstance(), geometryRenderer.firstInstance()); + QCOMPARE(renderGeometryRenderer.indexBufferByteOffset(), geometryRenderer.indexBufferByteOffset()); QCOMPARE(renderGeometryRenderer.restartIndexValue(), geometryRenderer.restartIndexValue()); QCOMPARE(renderGeometryRenderer.primitiveRestartEnabled(), geometryRenderer.primitiveRestartEnabled()); QCOMPARE(renderGeometryRenderer.primitiveType(), geometryRenderer.primitiveType()); @@ -131,6 +135,7 @@ private Q_SLOTS: QCOMPARE(renderGeometryRenderer.vertexCount(), 0); QCOMPARE(renderGeometryRenderer.indexOffset(), 0); QCOMPARE(renderGeometryRenderer.firstInstance(), 0); + QCOMPARE(renderGeometryRenderer.indexBufferByteOffset(), 0); QCOMPARE(renderGeometryRenderer.restartIndexValue(), -1); QCOMPARE(renderGeometryRenderer.primitiveRestartEnabled(), false); QCOMPARE(renderGeometryRenderer.primitiveType(), Qt3DRender::QGeometryRenderer::Triangles); @@ -141,12 +146,13 @@ private Q_SLOTS: Qt3DRender::QGeometryRenderer geometryRenderer; Qt3DRender::QGeometry geometry; Qt3DRender::QGeometryFactoryPtr factory(new TestFactory(1200)); - + TestRenderer renderer; geometryRenderer.setInstanceCount(454); geometryRenderer.setVertexCount(350); geometryRenderer.setIndexOffset(427); geometryRenderer.setFirstInstance(383); + geometryRenderer.setIndexBufferByteOffset(96); geometryRenderer.setRestartIndexValue(555); geometryRenderer.setPrimitiveRestartEnabled(true); geometryRenderer.setPrimitiveType(Qt3DRender::QGeometryRenderer::Patches); @@ -155,6 +161,7 @@ private Q_SLOTS: geometryRenderer.setEnabled(true); // WHEN + renderGeometryRenderer.setRenderer(&renderer); renderGeometryRenderer.setManager(&geometryRendererManager); simulateInitialization(&geometryRenderer, &renderGeometryRenderer); renderGeometryRenderer.cleanup(); @@ -166,6 +173,7 @@ private Q_SLOTS: QCOMPARE(renderGeometryRenderer.vertexCount(), 0); QCOMPARE(renderGeometryRenderer.indexOffset(), 0); QCOMPARE(renderGeometryRenderer.firstInstance(), 0); + QCOMPARE(renderGeometryRenderer.indexBufferByteOffset(), 0); QCOMPARE(renderGeometryRenderer.restartIndexValue(), -1); QCOMPARE(renderGeometryRenderer.primitiveRestartEnabled(), false); QCOMPARE(renderGeometryRenderer.primitiveType(), Qt3DRender::QGeometryRenderer::Triangles); @@ -191,7 +199,8 @@ private Q_SLOTS: // THEN QCOMPARE(renderGeometryRenderer.instanceCount(), 2); QVERIFY(renderGeometryRenderer.isDirty()); - QVERIFY(renderer.dirtyBits() != 0); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::GeometryDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); renderGeometryRenderer.unsetDirty(); QVERIFY(!renderGeometryRenderer.isDirty()); @@ -206,6 +215,9 @@ private Q_SLOTS: QCOMPARE(renderGeometryRenderer.vertexCount(), 56); QVERIFY(renderGeometryRenderer.isDirty()); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::GeometryDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + renderGeometryRenderer.unsetDirty(); QVERIFY(!renderGeometryRenderer.isDirty()); @@ -219,6 +231,9 @@ private Q_SLOTS: QCOMPARE(renderGeometryRenderer.indexOffset(), 65); QVERIFY(renderGeometryRenderer.isDirty()); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::GeometryDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + renderGeometryRenderer.unsetDirty(); QVERIFY(!renderGeometryRenderer.isDirty()); @@ -232,6 +247,25 @@ private Q_SLOTS: QCOMPARE(renderGeometryRenderer.firstInstance(), 82); QVERIFY(renderGeometryRenderer.isDirty()); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::GeometryDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + + renderGeometryRenderer.unsetDirty(); + QVERIFY(!renderGeometryRenderer.isDirty()); + + // WHEN + updateChange.reset(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId())); + updateChange->setPropertyName("indexBufferByteOffset"); + updateChange->setValue(96); + renderGeometryRenderer.sceneChangeEvent(updateChange); + + // THEN + QCOMPARE(renderGeometryRenderer.indexBufferByteOffset(), 96); + QVERIFY(renderGeometryRenderer.isDirty()); + + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::GeometryDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + renderGeometryRenderer.unsetDirty(); QVERIFY(!renderGeometryRenderer.isDirty()); @@ -245,6 +279,9 @@ private Q_SLOTS: QCOMPARE(renderGeometryRenderer.restartIndexValue(), 46); QVERIFY(renderGeometryRenderer.isDirty()); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::GeometryDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + renderGeometryRenderer.unsetDirty(); QVERIFY(!renderGeometryRenderer.isDirty()); @@ -258,6 +295,9 @@ private Q_SLOTS: QCOMPARE(renderGeometryRenderer.primitiveRestartEnabled(), true); QVERIFY(renderGeometryRenderer.isDirty()); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::GeometryDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + renderGeometryRenderer.unsetDirty(); QVERIFY(!renderGeometryRenderer.isDirty()); @@ -271,6 +311,9 @@ private Q_SLOTS: QCOMPARE(renderGeometryRenderer.primitiveType(), Qt3DRender::QGeometryRenderer::LineLoop); QVERIFY(renderGeometryRenderer.isDirty()); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::GeometryDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + renderGeometryRenderer.unsetDirty(); QVERIFY(!renderGeometryRenderer.isDirty()); @@ -285,9 +328,23 @@ private Q_SLOTS: QCOMPARE(renderGeometryRenderer.geometryFactory(), factory); QVERIFY(renderGeometryRenderer.isDirty()); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::GeometryDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + renderGeometryRenderer.unsetDirty(); QVERIFY(!renderGeometryRenderer.isDirty()); + // WHEN we set an identical factory again + updateChange.reset(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId())); + updateChange->setPropertyName("geometryFactory"); + Qt3DRender::QGeometryFactoryPtr factory2(new TestFactory(1450)); + updateChange->setValue(QVariant::fromValue(factory2)); + renderGeometryRenderer.sceneChangeEvent(updateChange); + + // THEN not dirty and still uses original factory + QCOMPARE(renderGeometryRenderer.geometryFactory(), factory); + QVERIFY(!renderGeometryRenderer.isDirty()); + // WHEN DummyGeometry geometry; const Qt3DCore::QNodeId geometryId = geometry.id(); @@ -300,6 +357,9 @@ private Q_SLOTS: QCOMPARE(renderGeometryRenderer.geometryId(), geometryId); QVERIFY(renderGeometryRenderer.isDirty()); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::GeometryDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + renderGeometryRenderer.unsetDirty(); QVERIFY(!renderGeometryRenderer.isDirty()); @@ -313,6 +373,9 @@ private Q_SLOTS: QCOMPARE(renderGeometryRenderer.geometryId(), Qt3DCore::QNodeId()); QVERIFY(renderGeometryRenderer.isDirty()); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::GeometryDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + renderGeometryRenderer.unsetDirty(); QVERIFY(!renderGeometryRenderer.isDirty()); @@ -326,6 +389,27 @@ private Q_SLOTS: QCOMPARE(renderGeometryRenderer.isEnabled(), true); QVERIFY(!renderGeometryRenderer.isDirty()); } + + void checkSetRendererDirtyOnInitialization() + { + // GIVEN + Qt3DRender::Render::GeometryRendererManager geometryRendererManager; + Qt3DRender::Render::GeometryRenderer renderGeometryRenderer; + Qt3DRender::QGeometryRenderer geometryRenderer; + TestRenderer renderer; + + renderGeometryRenderer.setRenderer(&renderer); + renderGeometryRenderer.setManager(&geometryRendererManager); + + // THEN + QCOMPARE(renderer.dirtyBits(), 0); + + // WHEN + simulateInitialization(&geometryRenderer, &renderGeometryRenderer); + + // THEN + QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::GeometryDirty); + } }; QTEST_APPLESS_MAIN(tst_RenderGeometryRenderer) diff --git a/tests/auto/render/graphicshelpergl2/tst_graphicshelpergl2.cpp b/tests/auto/render/graphicshelpergl2/tst_graphicshelpergl2.cpp index afd56e9bd..584b675ee 100644 --- a/tests/auto/render/graphicshelpergl2/tst_graphicshelpergl2.cpp +++ b/tests/auto/render/graphicshelpergl2/tst_graphicshelpergl2.cpp @@ -33,8 +33,10 @@ #include <Qt3DRender/private/attachmentpack_p.h> #include <QtOpenGLExtensions/QOpenGLExtensions> #include <QOpenGLContext> +#include <QOpenGLBuffer> #include <QOpenGLFunctions_2_0> #include <QOpenGLShaderProgram> +#include <QOpenGLVertexArrayObject> #include <QSurfaceFormat> #ifndef QT_OPENGL_ES_2 @@ -612,6 +614,33 @@ private Q_SLOTS: // Not supported by GL2 } + void enableVertexAttribute() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + + // GIVEN + QOpenGLVertexArrayObject vao; + vao.create(); + QOpenGLVertexArrayObject::Binder binder(&vao); + + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeSamplers); + QVERIFY(shaderProgram.link()); + shaderProgram.bind(); + + // WHEN + GLint positionLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexPosition"); + GLint texCoordLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexTexCoord"); + m_glHelper.enableVertexAttributeArray(positionLocation); + m_glHelper.enableVertexAttributeArray(texCoordLocation); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + } + void frontFace() { if (!m_initializationSuccessful) @@ -1019,6 +1048,51 @@ private Q_SLOTS: // Not available in 3.2 } + void vertexAttributePointer() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + QOpenGLVertexArrayObject vao; + vao.create(); + QOpenGLVertexArrayObject::Binder binder(&vao); + + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeSamplers); + QVERIFY(shaderProgram.link()); + + GLint positionLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexPosition"); + GLint texCoordLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexTexCoord"); + + const int vertexCount = 99; + QOpenGLBuffer positionBuffer(QOpenGLBuffer::VertexBuffer); + positionBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); + positionBuffer.create(); + positionBuffer.bind(); + positionBuffer.allocate(vertexCount * sizeof(QVector3D)); + + QOpenGLBuffer texCoordBuffer(QOpenGLBuffer::VertexBuffer); + texCoordBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); + texCoordBuffer.create(); + texCoordBuffer.allocate(vertexCount * sizeof(QVector2D)); + + // WHEN + shaderProgram.bind(); + positionBuffer.bind(); + m_glHelper.enableVertexAttributeArray(positionLocation); + m_glHelper.vertexAttributePointer(GL_FLOAT_VEC3, positionLocation, 3, GL_FLOAT, GL_TRUE, 0, 0); + + texCoordBuffer.bind(); + m_glHelper.enableVertexAttributeArray(texCoordLocation); + m_glHelper.vertexAttributePointer(GL_FLOAT_VEC2, texCoordLocation, 2, GL_FLOAT, GL_TRUE, 0, 0); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + } + void glUniform1fv() { if (!m_initializationSuccessful) @@ -1438,6 +1512,18 @@ private Q_SLOTS: QCOMPARE(computed, expected); } + void drawBuffer() + { + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + // Not supported by GL2 + } + + void readBuffer() + { + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + // Not supported by GL2 + } + private: QScopedPointer<QWindow> m_window; QOpenGLContext m_glContext; diff --git a/tests/auto/render/graphicshelpergl3_2/tst_graphicshelpergl3_2.cpp b/tests/auto/render/graphicshelpergl3_2/tst_graphicshelpergl3_2.cpp index 1414d13b0..648eaaddb 100644 --- a/tests/auto/render/graphicshelpergl3_2/tst_graphicshelpergl3_2.cpp +++ b/tests/auto/render/graphicshelpergl3_2/tst_graphicshelpergl3_2.cpp @@ -31,8 +31,10 @@ #include <Qt3DRender/private/uniform_p.h> #include <Qt3DRender/private/graphicshelpergl3_2_p.h> #include <Qt3DRender/private/attachmentpack_p.h> +#include <QOpenGLBuffer> #include <QOpenGLFunctions_3_2_Core> #include <QOpenGLShaderProgram> +#include <QOpenGLVertexArrayObject> #include <QSurfaceFormat> #if !defined(QT_OPENGL_ES_2) && defined(QT_OPENGL_3_2) @@ -139,6 +141,7 @@ const QByteArray fragCodeUniformsFloatMatrices = QByteArrayLiteral( const QByteArray fragCodeUniformBuffer = QByteArrayLiteral( "#version 150 core\n" \ "out vec4 color;\n" \ + "in vec2 texCoord;\n" \ "flat in int colorIndex;\n" \ "uniform ColorArray\n" \ "{\n" \ @@ -146,7 +149,7 @@ const QByteArray fragCodeUniformBuffer = QByteArrayLiteral( "};\n" \ "void main()\n" \ "{\n" \ - " color = colors[colorIndex];\n" \ + " color = colors[colorIndex] + vec4(texCoord.s, texCoord.t, 0.0, 1.0);\n" \ "}\n"); const QByteArray fragCodeSamplers = QByteArrayLiteral( @@ -823,6 +826,35 @@ private Q_SLOTS: m_func->glDisable(GL_PRIMITIVE_RESTART); } + void enableVertexAttribute() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + // GIVEN + QOpenGLVertexArrayObject vao; + vao.create(); + QOpenGLVertexArrayObject::Binder binder(&vao); + + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCodeUniformBuffer); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformBuffer); + QVERIFY(shaderProgram.link()); + shaderProgram.bind(); + + // WHEN + GLint positionLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexPosition"); + GLint texCoordLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexTexCoord"); + GLint colorIndexLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexColorIndex"); + m_glHelper.enableVertexAttributeArray(positionLocation); + m_glHelper.enableVertexAttributeArray(texCoordLocation); + m_glHelper.enableVertexAttributeArray(colorIndexLocation); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + } + void frontFace() { if (!m_initializationSuccessful) @@ -1318,6 +1350,61 @@ private Q_SLOTS: // Not available in 3.2 } + void vertexAttributePointer() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + QOpenGLVertexArrayObject vao; + vao.create(); + QOpenGLVertexArrayObject::Binder binder(&vao); + + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCodeUniformBuffer); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformBuffer); + QVERIFY(shaderProgram.link()); + + GLint positionLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexPosition"); + GLint texCoordLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexTexCoord"); + GLint colorIndexLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexColorIndex"); + + const int vertexCount = 99; + QOpenGLBuffer positionBuffer(QOpenGLBuffer::VertexBuffer); + positionBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); + positionBuffer.create(); + positionBuffer.bind(); + positionBuffer.allocate(vertexCount * sizeof(QVector3D)); + + QOpenGLBuffer texCoordBuffer(QOpenGLBuffer::VertexBuffer); + texCoordBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); + texCoordBuffer.create(); + texCoordBuffer.allocate(vertexCount * sizeof(QVector2D)); + + QOpenGLBuffer colorIndexBuffer(QOpenGLBuffer::VertexBuffer); + colorIndexBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); + colorIndexBuffer.create(); + colorIndexBuffer.allocate(vertexCount * sizeof(int)); + + // WHEN + shaderProgram.bind(); + positionBuffer.bind(); + m_glHelper.enableVertexAttributeArray(positionLocation); + m_glHelper.vertexAttributePointer(GL_FLOAT_VEC3, positionLocation, 3, GL_FLOAT, GL_TRUE, 0, 0); + + texCoordBuffer.bind(); + m_glHelper.enableVertexAttributeArray(texCoordLocation); + m_glHelper.vertexAttributePointer(GL_FLOAT_VEC2, texCoordLocation, 2, GL_FLOAT, GL_TRUE, 0, 0); + + colorIndexBuffer.bind(); + m_glHelper.enableVertexAttributeArray(colorIndexLocation); + m_glHelper.vertexAttributePointer(GL_INT, colorIndexLocation, 1, GL_INT, GL_TRUE, 0, 0); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + } + void glUniform1fv() { if (!m_initializationSuccessful) @@ -2028,6 +2115,42 @@ private Q_SLOTS: QCOMPARE(computed, expected); } + void drawBuffer() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + m_func->glGetError(); + + // WHEN + m_glHelper.drawBuffer(GL_FRONT); + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + + // THEN + GLint p; + m_func->glGetIntegerv(GL_DRAW_BUFFER, &p); + QCOMPARE(p, GL_FRONT); + } + + void readBuffer() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + m_func->glGetError(); + + // WHEN + m_glHelper.readBuffer(GL_FRONT); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + GLint p; + m_func->glGetIntegerv(GL_READ_BUFFER, &p); + QCOMPARE(p, GL_FRONT); + } + private: QScopedPointer<QWindow> m_window; QOpenGLContext m_glContext; diff --git a/tests/auto/render/graphicshelpergl3_3/tst_graphicshelpergl3_3.cpp b/tests/auto/render/graphicshelpergl3_3/tst_graphicshelpergl3_3.cpp index eea0e9f14..06a3c41cd 100644 --- a/tests/auto/render/graphicshelpergl3_3/tst_graphicshelpergl3_3.cpp +++ b/tests/auto/render/graphicshelpergl3_3/tst_graphicshelpergl3_3.cpp @@ -31,8 +31,10 @@ #include <Qt3DRender/private/uniform_p.h> #include <Qt3DRender/private/graphicshelpergl3_3_p.h> #include <Qt3DRender/private/attachmentpack_p.h> +#include <QOpenGLBuffer> #include <QOpenGLFunctions_3_3_Core> #include <QOpenGLShaderProgram> +#include <QOpenGLVertexArrayObject> #if !defined(QT_OPENGL_ES_2) && defined(QT_OPENGL_3_2) @@ -138,6 +140,7 @@ const QByteArray fragCodeUniformsFloatMatrices = QByteArrayLiteral( const QByteArray fragCodeUniformBuffer = QByteArrayLiteral( "#version 330 core\n" \ "out vec4 color;\n" \ + "in vec2 texCoord;\n" \ "flat in int colorIndex;\n" \ "uniform ColorArray\n" \ "{\n" \ @@ -145,7 +148,7 @@ const QByteArray fragCodeUniformBuffer = QByteArrayLiteral( "};\n" \ "void main()\n" \ "{\n" \ - " color = colors[colorIndex];\n" \ + " color = colors[colorIndex] + vec4(texCoord.s, texCoord.t, 0.0, 1.0);\n" \ "}\n"); const QByteArray fragCodeSamplers = QByteArrayLiteral( @@ -922,6 +925,35 @@ private Q_SLOTS: m_func->glDisable(GL_PRIMITIVE_RESTART); } + void enableVertexAttribute() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QOpenGLVertexArrayObject vao; + vao.create(); + QOpenGLVertexArrayObject::Binder binder(&vao); + + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCodeUniformBuffer); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformBuffer); + QVERIFY(shaderProgram.link()); + shaderProgram.bind(); + + // WHEN + GLint positionLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexPosition"); + GLint texCoordLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexTexCoord"); + GLint colorIndexLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexColorIndex"); + m_glHelper.enableVertexAttributeArray(positionLocation); + m_glHelper.enableVertexAttributeArray(texCoordLocation); + m_glHelper.enableVertexAttributeArray(colorIndexLocation); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + } + void frontFace() { if (!m_initializationSuccessful) @@ -1417,6 +1449,61 @@ private Q_SLOTS: QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); } + void vertexAttributePointer() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + QOpenGLVertexArrayObject vao; + vao.create(); + QOpenGLVertexArrayObject::Binder binder(&vao); + + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCodeUniformBuffer); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformBuffer); + QVERIFY(shaderProgram.link()); + + GLint positionLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexPosition"); + GLint texCoordLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexTexCoord"); + GLint colorIndexLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexColorIndex"); + + const int vertexCount = 99; + QOpenGLBuffer positionBuffer(QOpenGLBuffer::VertexBuffer); + positionBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); + positionBuffer.create(); + positionBuffer.bind(); + positionBuffer.allocate(vertexCount * sizeof(QVector3D)); + + QOpenGLBuffer texCoordBuffer(QOpenGLBuffer::VertexBuffer); + texCoordBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); + texCoordBuffer.create(); + texCoordBuffer.allocate(vertexCount * sizeof(QVector2D)); + + QOpenGLBuffer colorIndexBuffer(QOpenGLBuffer::VertexBuffer); + colorIndexBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); + colorIndexBuffer.create(); + colorIndexBuffer.allocate(vertexCount * sizeof(int)); + + // WHEN + shaderProgram.bind(); + positionBuffer.bind(); + m_glHelper.enableVertexAttributeArray(positionLocation); + m_glHelper.vertexAttributePointer(GL_FLOAT_VEC3, positionLocation, 3, GL_FLOAT, GL_TRUE, 0, 0); + + texCoordBuffer.bind(); + m_glHelper.enableVertexAttributeArray(texCoordLocation); + m_glHelper.vertexAttributePointer(GL_FLOAT_VEC2, texCoordLocation, 2, GL_FLOAT, GL_TRUE, 0, 0); + + colorIndexBuffer.bind(); + m_glHelper.enableVertexAttributeArray(colorIndexLocation); + m_glHelper.vertexAttributePointer(GL_INT, colorIndexLocation, 1, GL_INT, GL_TRUE, 0, 0); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + } + void glUniform1fv() { if (!m_initializationSuccessful) @@ -2128,6 +2215,42 @@ private Q_SLOTS: QCOMPARE(computed, expected); } + void drawBuffer() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + m_func->glGetError(); + + // WHEN + m_glHelper.drawBuffer(GL_FRONT); + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + + // THEN + GLint p; + m_func->glGetIntegerv(GL_DRAW_BUFFER, &p); + QCOMPARE(p, GL_FRONT); + } + + void readBuffer() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + m_func->glGetError(); + + // WHEN + m_glHelper.readBuffer(GL_FRONT); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + GLint p; + m_func->glGetIntegerv(GL_READ_BUFFER, &p); + QCOMPARE(p, GL_FRONT); + } + private: QScopedPointer<QWindow> m_window; QOpenGLContext m_glContext; diff --git a/tests/auto/render/graphicshelpergl4/tst_graphicshelpergl4.cpp b/tests/auto/render/graphicshelpergl4/tst_graphicshelpergl4.cpp index 84d261659..5a96cf116 100644 --- a/tests/auto/render/graphicshelpergl4/tst_graphicshelpergl4.cpp +++ b/tests/auto/render/graphicshelpergl4/tst_graphicshelpergl4.cpp @@ -31,8 +31,10 @@ #include <Qt3DRender/private/uniform_p.h> #include <Qt3DRender/private/graphicshelpergl4_p.h> #include <Qt3DRender/private/attachmentpack_p.h> +#include <QOpenGLBuffer> #include <QOpenGLFunctions_4_3_Core> #include <QOpenGLShaderProgram> +#include <QOpenGLVertexArrayObject> #include <QSurfaceFormat> #if !defined(QT_OPENGL_ES_2) && defined(QT_OPENGL_4_3) @@ -60,11 +62,12 @@ const QByteArray vertCodeUniformBuffer = QByteArrayLiteral( "layout(location = 1) in vec3 vertexPosition;\n" \ "layout(location = 2) in vec2 vertexTexCoord;\n" \ "layout(location = 3) in int vertexColorIndex;\n" \ + "layout(location = 4) in double vertexTexCoordScale;\n" \ "out vec2 texCoord;\n" \ "flat out int colorIndex;\n" \ "void main()\n" \ "{\n" \ - " texCoord = vertexTexCoord;\n" \ + " texCoord = vec2(vertexTexCoordScale * vertexTexCoord);\n" \ " colorIndex = vertexColorIndex;\n" \ " gl_Position = vec4(vertexPosition, 1.0);\n" \ "}\n"); @@ -139,6 +142,7 @@ const QByteArray fragCodeUniformsFloatMatrices = QByteArrayLiteral( const QByteArray fragCodeUniformBuffer = QByteArrayLiteral( "#version 430 core\n" \ "out vec4 color;\n" \ + "in vec2 texCoord;\n" \ "flat in int colorIndex;\n" \ "layout(binding = 2, std140) uniform ColorArray\n" \ "{\n" \ @@ -146,7 +150,7 @@ const QByteArray fragCodeUniformBuffer = QByteArrayLiteral( "};\n" \ "void main()\n" \ "{\n" \ - " color = colors[colorIndex];\n" \ + " color = colors[colorIndex] + vec4(texCoord.s, texCoord.t, 0.0, 1.0);\n" \ "}\n"); const QByteArray fragCodeSamplers = QByteArrayLiteral( @@ -1020,6 +1024,35 @@ private Q_SLOTS: m_func->glDisable(GL_PRIMITIVE_RESTART); } + void enableVertexAttribute() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + QOpenGLVertexArrayObject vao; + vao.create(); + QOpenGLVertexArrayObject::Binder binder(&vao); + + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCodeUniformBuffer); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformBuffer); + QVERIFY(shaderProgram.link()); + shaderProgram.bind(); + + // WHEN + GLint positionLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexPosition"); + GLint texCoordLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexTexCoord"); + GLint colorIndexLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexColorIndex"); + m_glHelper.enableVertexAttributeArray(positionLocation); + m_glHelper.enableVertexAttributeArray(texCoordLocation); + m_glHelper.enableVertexAttributeArray(colorIndexLocation); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + } + void frontFace() { if (!m_initializationSuccessful) @@ -1507,6 +1540,71 @@ private Q_SLOTS: QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); } + void vertexAttributePointer() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + QOpenGLVertexArrayObject vao; + vao.create(); + QOpenGLVertexArrayObject::Binder binder(&vao); + + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCodeUniformBuffer); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformBuffer); + QVERIFY(shaderProgram.link()); + + GLint positionLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexPosition"); + GLint texCoordLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexTexCoord"); + GLint colorIndexLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexColorIndex"); + GLint texCoordScaleLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexTexCoordScale"); + + const int vertexCount = 99; + QOpenGLBuffer positionBuffer(QOpenGLBuffer::VertexBuffer); + positionBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); + positionBuffer.create(); + positionBuffer.bind(); + positionBuffer.allocate(vertexCount * sizeof(QVector3D)); + + QOpenGLBuffer texCoordBuffer(QOpenGLBuffer::VertexBuffer); + texCoordBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); + texCoordBuffer.create(); + texCoordBuffer.allocate(vertexCount * sizeof(QVector2D)); + + QOpenGLBuffer colorIndexBuffer(QOpenGLBuffer::VertexBuffer); + colorIndexBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); + colorIndexBuffer.create(); + colorIndexBuffer.allocate(vertexCount * sizeof(int)); + + QOpenGLBuffer scaleBuffer(QOpenGLBuffer::VertexBuffer); + scaleBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); + scaleBuffer.create(); + scaleBuffer.allocate(vertexCount * sizeof(double)); + + // WHEN + shaderProgram.bind(); + positionBuffer.bind(); + m_glHelper.enableVertexAttributeArray(positionLocation); + m_glHelper.vertexAttributePointer(GL_FLOAT_VEC3, positionLocation, 3, GL_FLOAT, GL_TRUE, 0, 0); + + texCoordBuffer.bind(); + m_glHelper.enableVertexAttributeArray(texCoordLocation); + m_glHelper.vertexAttributePointer(GL_FLOAT_VEC2, texCoordLocation, 2, GL_FLOAT, GL_TRUE, 0, 0); + + colorIndexBuffer.bind(); + m_glHelper.enableVertexAttributeArray(colorIndexLocation); + m_glHelper.vertexAttributePointer(GL_INT, colorIndexLocation, 1, GL_INT, GL_TRUE, 0, 0); + + scaleBuffer.bind(); + m_glHelper.enableVertexAttributeArray(colorIndexLocation); + m_glHelper.vertexAttributePointer(GL_DOUBLE, texCoordScaleLocation, 1, GL_DOUBLE, GL_TRUE, 0, 0); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + } + void glUniform1fv() { if (!m_initializationSuccessful) @@ -2196,6 +2294,42 @@ private Q_SLOTS: QCOMPARE(computed, expected); } + void drawBuffer() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + m_func->glGetError(); + + // WHEN + m_glHelper.drawBuffer(GL_FRONT); + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + + // THEN + GLint p; + m_func->glGetIntegerv(GL_DRAW_BUFFER, &p); + QCOMPARE(p, GL_FRONT); + } + + void readBuffer() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + m_func->glGetError(); + + // WHEN + m_glHelper.readBuffer(GL_FRONT); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + GLint p; + m_func->glGetIntegerv(GL_READ_BUFFER, &p); + QCOMPARE(p, GL_FRONT); + } + private: QScopedPointer<QWindow> m_window; QOpenGLContext m_glContext; diff --git a/tests/auto/render/joint/joint.pro b/tests/auto/render/joint/joint.pro new file mode 100644 index 000000000..9428ab5fd --- /dev/null +++ b/tests/auto/render/joint/joint.pro @@ -0,0 +1,13 @@ +TEMPLATE = app + +TARGET = tst_joint + +QT += core-private 3dcore 3dcore-private 3drender 3drender-private testlib + +CONFIG += testcase + +SOURCES += \ + tst_joint.cpp + +include(../../core/common/common.pri) +include(../commons/commons.pri) diff --git a/tests/auto/render/joint/tst_joint.cpp b/tests/auto/render/joint/tst_joint.cpp new file mode 100644 index 000000000..13aa915d2 --- /dev/null +++ b/tests/auto/render/joint/tst_joint.cpp @@ -0,0 +1,242 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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$ +** +****************************************************************************/ + +#include <QtTest/QTest> +#include <Qt3DRender/private/joint_p.h> +#include <Qt3DRender/private/nodemanagers_p.h> +#include <Qt3DCore/qjoint.h> +#include <Qt3DCore/private/qnode_p.h> +#include <Qt3DCore/private/qscene_p.h> +#include <Qt3DCore/qpropertyupdatedchange.h> +#include <Qt3DCore/private/qpropertyupdatedchangebase_p.h> +#include <Qt3DCore/qpropertynodeaddedchange.h> +#include <Qt3DCore/qpropertynoderemovedchange.h> +#include <QtGui/qmatrix4x4.h> +#include <QtGui/qvector3d.h> +#include <qbackendnodetester.h> +#include <testpostmanarbiter.h> +#include <testrenderer.h> + +using namespace Qt3DCore; +using namespace Qt3DRender; +using namespace Qt3DRender::Render; + +class tst_Joint : public Qt3DCore::QBackendNodeTester +{ + Q_OBJECT + +private Q_SLOTS: + void checkPeerPropertyMirroring() + { + // GIVEN + TestRenderer renderer; + NodeManagers nodeManagers; + renderer.setNodeManagers(&nodeManagers); + Joint backendJoint; + backendJoint.setRenderer(&renderer); + backendJoint.setJointManager(nodeManagers.jointManager()); + QJoint joint; + + joint.setTranslation(QVector3D(1.0f, 2.0f, 3.0f)); + joint.setScale(QVector3D(1.5f, 2.5f, 3.5)); + joint.setRotation(QQuaternion::fromAxisAndAngle(1.0f, 0.0f, 0.0f, 45.0f)); + QMatrix4x4 inverseBind; + inverseBind.rotate(-45.0f, 1.0f, 0.0, 0.0f); + joint.setInverseBindMatrix(inverseBind); + + QVector<QJoint *> childJoints; + for (int i = 0; i < 10; ++i) { + const auto childJoint = new QJoint(); + joint.addChildJoint(childJoint); + childJoints.push_back(childJoint); + } + + // WHEN + simulateInitialization(&joint, &backendJoint); + + // THEN + QCOMPARE(backendJoint.peerId(), joint.id()); + QCOMPARE(backendJoint.isEnabled(), joint.isEnabled()); + QCOMPARE(backendJoint.translation(), joint.translation()); + QCOMPARE(backendJoint.rotation(), joint.rotation()); + QCOMPARE(backendJoint.scale(), joint.scale()); + QCOMPARE(backendJoint.inverseBindMatrix(), joint.inverseBindMatrix()); + for (int i = 0; i < childJoints.size(); ++i) { + QCOMPARE(backendJoint.childJointIds()[i], childJoints[i]->id()); + } + } + + void checkInitialAndCleanedUpState() + { + // GIVEN + TestRenderer renderer; + NodeManagers nodeManagers; + renderer.setNodeManagers(&nodeManagers); + Joint backendJoint; + backendJoint.setRenderer(&renderer); + backendJoint.setJointManager(nodeManagers.jointManager()); + + // THEN + QVERIFY(backendJoint.peerId().isNull()); + QCOMPARE(backendJoint.isEnabled(), false); + QCOMPARE(backendJoint.translation(), QVector3D()); + QCOMPARE(backendJoint.rotation(), QQuaternion()); + QCOMPARE(backendJoint.scale(), QVector3D(1.0f, 1.0f, 1.0f)); + QCOMPARE(backendJoint.inverseBindMatrix(), QMatrix4x4()); + QCOMPARE(backendJoint.childJointIds(), QNodeIdVector()); + QCOMPARE(backendJoint.owningSkeleton(), HSkeleton()); + + // GIVEN + QJoint joint; + joint.setTranslation(QVector3D(1.0f, 2.0f, 3.0f)); + joint.setScale(QVector3D(1.5f, 2.5f, 3.5)); + joint.setRotation(QQuaternion::fromAxisAndAngle(1.0f, 0.0f, 0.0f, 45.0f)); + QMatrix4x4 inverseBind; + inverseBind.rotate(-45.0f, 1.0f, 0.0, 0.0f); + joint.setInverseBindMatrix(inverseBind); + + QVector<QJoint *> childJoints; + for (int i = 0; i < 10; ++i) { + const auto childJoint = new QJoint(); + joint.addChildJoint(childJoint); + childJoints.push_back(childJoint); + } + + // WHEN + simulateInitialization(&joint, &backendJoint); + backendJoint.cleanup(); + + // THEN + QCOMPARE(backendJoint.isEnabled(), false); + QCOMPARE(backendJoint.translation(), QVector3D()); + QCOMPARE(backendJoint.rotation(), QQuaternion()); + QCOMPARE(backendJoint.scale(), QVector3D(1.0f, 1.0f, 1.0f)); + QCOMPARE(backendJoint.inverseBindMatrix(), QMatrix4x4()); + QCOMPARE(backendJoint.childJointIds(), QNodeIdVector()); + QCOMPARE(backendJoint.owningSkeleton(), HSkeleton()); + } + + void checkPropertyChanges() + { + // GIVEN + TestRenderer renderer; + NodeManagers nodeManagers; + renderer.setNodeManagers(&nodeManagers); + Joint backendJoint; + backendJoint.setRenderer(&renderer); + backendJoint.setJointManager(nodeManagers.jointManager()); + backendJoint.setSkeletonManager(nodeManagers.skeletonManager()); + Qt3DCore::QPropertyUpdatedChangePtr updateChange; + + // WHEN + updateChange.reset(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId())); + updateChange->setPropertyName("enabled"); + updateChange->setValue(true); + backendJoint.sceneChangeEvent(updateChange); + + // THEN + QCOMPARE(backendJoint.isEnabled(), true); + + // WHEN + const QVector3D newTranslation = QVector3D(1.0f, 2.0f, 3.0f); + updateChange.reset(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId())); + updateChange->setPropertyName("translation"); + updateChange->setValue(newTranslation); + backendJoint.sceneChangeEvent(updateChange); + + // THEN + QCOMPARE(backendJoint.translation(), newTranslation); + + // WHEN + const QQuaternion newRotation = QQuaternion::fromAxisAndAngle(1.0f, 0.0f, 0.0f, 45.0f); + updateChange.reset(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId())); + updateChange->setPropertyName("rotation"); + updateChange->setValue(newRotation); + backendJoint.sceneChangeEvent(updateChange); + + // THEN + QCOMPARE(backendJoint.rotation(), newRotation); + + // WHEN + const QVector3D newScale = QVector3D(1.5f, 2.5f, 3.5f); + updateChange.reset(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId())); + updateChange->setPropertyName("scale"); + updateChange->setValue(newScale); + backendJoint.sceneChangeEvent(updateChange); + + // THEN + QCOMPARE(backendJoint.scale(), newScale); + + // WHEN + QMatrix4x4 newInverseBind; + newInverseBind.scale(5.4f); + updateChange.reset(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId())); + updateChange->setPropertyName("inverseBindMatrix"); + updateChange->setValue(newInverseBind); + backendJoint.sceneChangeEvent(updateChange); + + // THEN + QCOMPARE(backendJoint.inverseBindMatrix(), newInverseBind); + + // WHEN + QVector<QJoint *> childJoints; + QPropertyNodeAddedChangePtr nodeAddedChange; + for (int i = 0; i < 10; ++i) { + const auto childJoint = new QJoint(); + childJoints.push_back(childJoint); + + nodeAddedChange.reset(new QPropertyNodeAddedChange(QNodeId(), childJoint)); + nodeAddedChange->setPropertyName("childJoint"); + backendJoint.sceneChangeEvent(nodeAddedChange); + } + + // THEN + for (int i = 0; i < childJoints.size(); ++i) { + QCOMPARE(backendJoint.childJointIds()[i], childJoints[i]->id()); + } + + QPropertyNodeRemovedChangePtr nodeRemovedChange; + for (int i = 0; i < 10; ++i) { + // WHEN + const auto childJoint = childJoints.takeLast(); + + nodeRemovedChange.reset(new QPropertyNodeRemovedChange(QNodeId(), childJoint)); + nodeRemovedChange->setPropertyName("childJoint"); + backendJoint.sceneChangeEvent(nodeAddedChange); + + // THEN + for (int i = 0; i < childJoints.size(); ++i) { + QCOMPARE(backendJoint.childJointIds()[i], childJoints[i]->id()); + } + } + } +}; + +QTEST_APPLESS_MAIN(tst_Joint) + +#include "tst_joint.moc" diff --git a/tests/auto/render/layerfiltering/tst_layerfiltering.cpp b/tests/auto/render/layerfiltering/tst_layerfiltering.cpp index c66b85c8c..c2651c477 100644 --- a/tests/auto/render/layerfiltering/tst_layerfiltering.cpp +++ b/tests/auto/render/layerfiltering/tst_layerfiltering.cpp @@ -34,6 +34,7 @@ #include <Qt3DRender/private/filterlayerentityjob_p.h> #include <Qt3DRender/private/updatetreeenabledjob_p.h> #include <Qt3DRender/qlayer.h> +#include <Qt3DRender/qlayerfilter.h> #include "testaspect.h" class tst_LayerFiltering : public QObject @@ -45,18 +46,19 @@ private Q_SLOTS: { // GIVEN Qt3DRender::Render::FilterLayerEntityJob filterJob; + Qt3DRender::QLayer frontendLayer; // THEN QCOMPARE(filterJob.hasLayerFilter(), false); QCOMPARE(filterJob.filteredEntities().size(), 0); - QCOMPARE(filterJob.layers().size(), 0); + QCOMPARE(filterJob.layerFilters().size(), 0); + QCOMPARE(frontendLayer.recursive(), false); } void filterEntities_data() { QTest::addColumn<Qt3DCore::QEntity *>("entitySubtree"); - QTest::addColumn<Qt3DCore::QNodeIdVector>("layerIds"); - QTest::addColumn<bool>("hasLayerFilter"); + QTest::addColumn<Qt3DCore::QNodeIdVector>("layerFilterIds"); QTest::addColumn<Qt3DCore::QNodeIdVector>("expectedSelectedEntities"); @@ -70,15 +72,14 @@ private Q_SLOTS: Q_UNUSED(childEntity2); Q_UNUSED(childEntity3); - QTest::newRow("EntitiesNoLayerNoLayerFilter-ShouldSelectAll") << rootEntity - << Qt3DCore::QNodeIdVector() - << false - << (Qt3DCore::QNodeIdVector() - << rootEntity->id() - << childEntity1->id() - << childEntity2->id() - << childEntity3->id() - ); + QTest::newRow("EntitiesNoLayerNoLayerFilterNoDiscardNoRecursive-ShouldSelectAll") << rootEntity + << Qt3DCore::QNodeIdVector() + << (Qt3DCore::QNodeIdVector() + << rootEntity->id() + << childEntity1->id() + << childEntity2->id() + << childEntity3->id() + ); } { @@ -87,14 +88,14 @@ private Q_SLOTS: Qt3DCore::QEntity *childEntity2 = new Qt3DCore::QEntity(rootEntity); Qt3DCore::QEntity *childEntity3 = new Qt3DCore::QEntity(rootEntity); + Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(rootEntity); Q_UNUSED(childEntity1); Q_UNUSED(childEntity2); Q_UNUSED(childEntity3); QTest::newRow("EntityNoLayerWithLayerFilterWithNoFilter-ShouldSelectNone") << rootEntity - << Qt3DCore::QNodeIdVector() - << true + << (Qt3DCore::QNodeIdVector() << layerFilter->id()) << Qt3DCore::QNodeIdVector(); } @@ -109,12 +110,13 @@ private Q_SLOTS: Q_UNUSED(childEntity3); Qt3DRender::QLayer *layer = new Qt3DRender::QLayer(rootEntity); + Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(rootEntity); + layerFilter->addLayer(layer); - QTest::newRow("NoLayerWithLayerFilterWithFilter-ShouldSelectNone") << rootEntity - << (Qt3DCore::QNodeIdVector() << layer->id()) - << true - << Qt3DCore::QNodeIdVector(); + QTest::newRow("AcceptAny-NoLayerWithLayerFilterWithFilter-ShouldSelectNone") << rootEntity + << (Qt3DCore::QNodeIdVector() << layerFilter->id()) + << Qt3DCore::QNodeIdVector(); } { @@ -129,10 +131,12 @@ private Q_SLOTS: childEntity2->addComponent(layer); childEntity3->addComponent(layer); - QTest::newRow("LayerWithLayerFilterWithFilter-ShouldSelectAllButRoot") << rootEntity - << (Qt3DCore::QNodeIdVector() << layer->id()) - << true - << (Qt3DCore::QNodeIdVector() << childEntity1->id() << childEntity2->id() << childEntity3->id()); + Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(rootEntity); + layerFilter->addLayer(layer); + + QTest::newRow("AcceptAny-LayerWithLayerFilterWithFilter-ShouldSelectAllButRoot") << rootEntity + << (Qt3DCore::QNodeIdVector() << layerFilter->id()) + << (Qt3DCore::QNodeIdVector() << childEntity1->id() << childEntity2->id() << childEntity3->id()); } { @@ -148,10 +152,13 @@ private Q_SLOTS: childEntity2->addComponent(layer2); childEntity3->addComponent(layer); - QTest::newRow("LayerWithLayerFilterWithFilter-ShouldSelectChild2And3") << rootEntity - << (Qt3DCore::QNodeIdVector() << layer->id() << layer2->id()) - << true - << (Qt3DCore::QNodeIdVector() << childEntity2->id() << childEntity3->id()); + Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(rootEntity); + layerFilter->addLayer(layer); + layerFilter->addLayer(layer2); + + QTest::newRow("AcceptAny-LayerWithLayerFilterWithFilter-ShouldSelectChild2And3") << rootEntity + << (Qt3DCore::QNodeIdVector() << layerFilter->id()) + << (Qt3DCore::QNodeIdVector() << childEntity2->id() << childEntity3->id()); } { @@ -167,10 +174,12 @@ private Q_SLOTS: childEntity2->addComponent(layer); childEntity3->addComponent(layer); - QTest::newRow("LayerWithLayerFilterWithFilter-ShouldSelectNone") << rootEntity - << (Qt3DCore::QNodeIdVector() << layer2->id()) - << true - << Qt3DCore::QNodeIdVector(); + Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(rootEntity); + layerFilter->addLayer(layer2); + + QTest::newRow("AcceptAny-LayerWithLayerFilterWithFilter-ShouldSelectNone") << rootEntity + << (Qt3DCore::QNodeIdVector() << layerFilter->id()) + << Qt3DCore::QNodeIdVector(); } { @@ -186,22 +195,436 @@ private Q_SLOTS: childEntity2->addComponent(layer); childEntity3->addComponent(layer); - QTest::newRow("LayerWithEntityDisabled-ShouldSelectOnlyEntityEnabled") << rootEntity - << (Qt3DCore::QNodeIdVector() << layer->id()) - << true - << (Qt3DCore::QNodeIdVector() << childEntity2->id() << childEntity3->id()); + Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(rootEntity); + layerFilter->addLayer(layer); + + QTest::newRow("AcceptAny-LayerWithEntityDisabled-ShouldSelectOnlyEntityEnabled") << rootEntity + << (Qt3DCore::QNodeIdVector() << layerFilter->id()) + << (Qt3DCore::QNodeIdVector() << childEntity2->id() << childEntity3->id()); + } + + { + Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity(); + Qt3DCore::QEntity *childEntity1 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity2 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity3 = new Qt3DCore::QEntity(rootEntity); + + Qt3DRender::QLayer *layer = new Qt3DRender::QLayer(rootEntity); + layer->setRecursive(true); + rootEntity->addComponent(layer); + + Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(rootEntity); + layerFilter->addLayer(layer); + + QTest::newRow("AcceptAny-RecursiveLayerOnRoot-ShouldSelectAll") << rootEntity + << (Qt3DCore::QNodeIdVector() << layerFilter->id()) + << (Qt3DCore::QNodeIdVector() + << rootEntity->id() + << childEntity1->id() + << childEntity2->id() + << childEntity3->id()); + } + + { + Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity(); + Qt3DCore::QEntity *childEntity1 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity2 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity3 = new Qt3DCore::QEntity(rootEntity); + + Q_UNUSED(childEntity1); + Q_UNUSED(childEntity2); + Q_UNUSED(childEntity3); + + Qt3DRender::QLayer *layer = new Qt3DRender::QLayer(rootEntity); + layer->setRecursive(true); + rootEntity->addComponent(layer); + + Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(rootEntity); + layerFilter->setFilterMode(Qt3DRender::QLayerFilter::DiscardAnyMatchingLayers); + layerFilter->addLayer(layer); + + QTest::newRow("DiscardAny-RecursiveLayerLayerFilterDiscardOnRoot-ShouldSelectNone") << rootEntity + << (Qt3DCore::QNodeIdVector() << layerFilter->id()) + << (Qt3DCore::QNodeIdVector()); + } + + { + Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity(); + Qt3DCore::QEntity *childEntity1 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity2 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity3 = new Qt3DCore::QEntity(rootEntity); + + Qt3DRender::QLayer *layer = new Qt3DRender::QLayer(rootEntity); + rootEntity->addComponent(layer); + + Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(rootEntity); + layerFilter->setFilterMode(Qt3DRender::QLayerFilter::DiscardAnyMatchingLayers); + layerFilter->addLayer(layer); + + QTest::newRow("DiscardAny-LayerLayerFilterDiscardOnRoot-ShouldSelectAllButRoot") << rootEntity + << (Qt3DCore::QNodeIdVector() << layerFilter->id()) + << (Qt3DCore::QNodeIdVector() + << childEntity1->id() + << childEntity2->id() + << childEntity3->id()); + } + + { + Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity(); + Qt3DCore::QEntity *childEntity1 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity2 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity3 = new Qt3DCore::QEntity(rootEntity); + + Qt3DRender::QLayer *layer = new Qt3DRender::QLayer(rootEntity); + Qt3DRender::QLayer *layer2 = new Qt3DRender::QLayer(rootEntity); + Qt3DRender::QLayer *layer3 = new Qt3DRender::QLayer(rootEntity); + rootEntity->addComponent(layer); + + childEntity1->addComponent(layer2); + + childEntity2->addComponent(layer3); + + childEntity3->addComponent(layer2); + childEntity3->addComponent(layer3); + childEntity3->addComponent(layer); + + Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(rootEntity); + layerFilter->setFilterMode(Qt3DRender::QLayerFilter::DiscardAnyMatchingLayers); + layerFilter->addLayer(layer2); + layerFilter->addLayer(layer3); + + QTest::newRow("DiscardAny-LayerLayerFilterDiscardOnRoot-ShouldSelectRoot") << rootEntity + << (Qt3DCore::QNodeIdVector() << layerFilter->id()) + << (Qt3DCore::QNodeIdVector() + << rootEntity->id()); + } + + { + Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity(); + Qt3DCore::QEntity *childEntity1 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity2 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity3 = new Qt3DCore::QEntity(rootEntity); + + Qt3DRender::QLayer *layer = new Qt3DRender::QLayer(rootEntity); + Qt3DRender::QLayer *layer2 = new Qt3DRender::QLayer(rootEntity); + Qt3DRender::QLayer *layer3 = new Qt3DRender::QLayer(rootEntity); + + rootEntity->addComponent(layer); + + childEntity1->addComponent(layer3); + childEntity1->addComponent(layer2); + + childEntity2->addComponent(layer); + childEntity2->addComponent(layer3); + + childEntity3->addComponent(layer); + childEntity3->addComponent(layer2); + + Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(rootEntity); + layerFilter->setFilterMode(Qt3DRender::QLayerFilter::AcceptAllMatchingLayers); + layerFilter->addLayer(layer2); + layerFilter->addLayer(layer3); + + QTest::newRow("AcceptAll-LayerFilterWith2LayersNonRecursive-ShouldSelectChild1") << rootEntity + << (Qt3DCore::QNodeIdVector() << layerFilter->id()) + << (Qt3DCore::QNodeIdVector() + << childEntity1->id()); } + { + Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity(); + Qt3DCore::QEntity *childEntity1 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity2 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity3 = new Qt3DCore::QEntity(rootEntity); + + Qt3DRender::QLayer *layer = new Qt3DRender::QLayer(rootEntity); + layer->setRecursive(true); + + Qt3DRender::QLayer *layer2 = new Qt3DRender::QLayer(rootEntity); + Qt3DRender::QLayer *layer3 = new Qt3DRender::QLayer(rootEntity); + + rootEntity->addComponent(layer); + + childEntity1->addComponent(layer3); + childEntity1->addComponent(layer2); + + childEntity2->addComponent(layer3); + + childEntity3->addComponent(layer2); + + Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(rootEntity); + layerFilter->setFilterMode(Qt3DRender::QLayerFilter::AcceptAllMatchingLayers); + layerFilter->addLayer(layer); + layerFilter->addLayer(layer3); + + QTest::newRow("AcceptAll-LayerFilterWith2LayersRecursive-ShouldSelectChild12") << rootEntity + << (Qt3DCore::QNodeIdVector() << layerFilter->id()) + << (Qt3DCore::QNodeIdVector() + << childEntity1->id() + << childEntity2->id()); + } + + { + Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity(); + Qt3DCore::QEntity *childEntity1 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity2 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity3 = new Qt3DCore::QEntity(rootEntity); + + Qt3DRender::QLayer *layer = new Qt3DRender::QLayer(rootEntity); + layer->setRecursive(true); + + Qt3DRender::QLayer *layer2 = new Qt3DRender::QLayer(rootEntity); + Qt3DRender::QLayer *layer3 = new Qt3DRender::QLayer(rootEntity); + + rootEntity->addComponent(layer); + + childEntity1->addComponent(layer3); + childEntity1->addComponent(layer2); + + childEntity2->addComponent(layer); + childEntity2->addComponent(layer3); + + childEntity3->addComponent(layer2); + + Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(rootEntity); + layerFilter->setFilterMode(Qt3DRender::QLayerFilter::AcceptAllMatchingLayers); + layerFilter->addLayer(layer); + layerFilter->addLayer(layer3); + + QTest::newRow("AcceptAll-LayerFilterWith2LayersRecursiveAndDirectReferenceToRecursiveLayer-ShouldSelectChild12") << rootEntity + << (Qt3DCore::QNodeIdVector() << layerFilter->id()) + << (Qt3DCore::QNodeIdVector() + << childEntity1->id() + << childEntity2->id()); + } + + { + Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity(); + Qt3DCore::QEntity *childEntity1 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity2 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity3 = new Qt3DCore::QEntity(rootEntity); + + Qt3DRender::QLayer *layer = new Qt3DRender::QLayer(rootEntity); + Qt3DRender::QLayer *layer2 = new Qt3DRender::QLayer(rootEntity); + Qt3DRender::QLayer *layer3 = new Qt3DRender::QLayer(rootEntity); + + rootEntity->addComponent(layer); + + childEntity1->addComponent(layer); + childEntity1->addComponent(layer2); + + childEntity2->addComponent(layer); + childEntity2->addComponent(layer3); + + childEntity3->addComponent(layer2); + childEntity3->addComponent(layer3); + + Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(rootEntity); + layerFilter->setFilterMode(Qt3DRender::QLayerFilter::DiscardAllMatchingLayers); + layerFilter->addLayer(layer2); + layerFilter->addLayer(layer3); + + QTest::newRow("DiscardAll-LayerFilterWith2Layers-ShouldSelectRootAndChild12") << rootEntity + << (Qt3DCore::QNodeIdVector() << layerFilter->id()) + << (Qt3DCore::QNodeIdVector() + << rootEntity->id() + << childEntity1->id() + << childEntity2->id()); + } + + { + Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity(); + Qt3DCore::QEntity *childEntity1 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity2 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity3 = new Qt3DCore::QEntity(rootEntity); + + Qt3DRender::QLayer *layer = new Qt3DRender::QLayer(rootEntity); + layer->setRecursive(true); + + Qt3DRender::QLayer *layer2 = new Qt3DRender::QLayer(rootEntity); + Qt3DRender::QLayer *layer3 = new Qt3DRender::QLayer(rootEntity); + + rootEntity->addComponent(layer); + + childEntity1->addComponent(layer2); + + childEntity2->addComponent(layer3); + + childEntity3->addComponent(layer3); + + Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(rootEntity); + layerFilter->setFilterMode(Qt3DRender::QLayerFilter::DiscardAllMatchingLayers); + layerFilter->addLayer(layer); + layerFilter->addLayer(layer3); + + QTest::newRow("DiscardAll-LayerFilterWith2LayersRecursive-ShouldSelectRootAndChild1") << rootEntity + << (Qt3DCore::QNodeIdVector() << layerFilter->id()) + << (Qt3DCore::QNodeIdVector() + << rootEntity->id() + << childEntity1->id()); + } + + { + Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity(); + Qt3DCore::QEntity *childEntity1 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity2 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity3 = new Qt3DCore::QEntity(rootEntity); + + Qt3DRender::QLayer *layer = new Qt3DRender::QLayer(rootEntity); + layer->setRecursive(true); + + Qt3DRender::QLayer *layer2 = new Qt3DRender::QLayer(rootEntity); + Qt3DRender::QLayer *layer3 = new Qt3DRender::QLayer(rootEntity); + + rootEntity->addComponent(layer); + + childEntity1->addComponent(layer2); + childEntity1->addComponent(layer); + + childEntity2->addComponent(layer3); + + childEntity3->addComponent(layer3); + + Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(rootEntity); + layerFilter->setFilterMode(Qt3DRender::QLayerFilter::DiscardAllMatchingLayers); + layerFilter->addLayer(layer); + layerFilter->addLayer(layer3); + + QTest::newRow("DiscardAll-LayerFilterWith2LayersRecursiveAndDirectReference-ShouldSelectRootAndChild1") << rootEntity + << (Qt3DCore::QNodeIdVector() << layerFilter->id()) + << (Qt3DCore::QNodeIdVector() + << rootEntity->id() + << childEntity1->id()); + } + + { + Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity(); + Qt3DCore::QEntity *childEntity1 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity2 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity3 = new Qt3DCore::QEntity(rootEntity); + + Qt3DRender::QLayer *layer = new Qt3DRender::QLayer(rootEntity); + layer->setRecursive(true); + + Qt3DRender::QLayer *layer2 = new Qt3DRender::QLayer(rootEntity); + Qt3DRender::QLayer *layer3 = new Qt3DRender::QLayer(rootEntity); + Qt3DRender::QLayer *layer4 = new Qt3DRender::QLayer(rootEntity); + Qt3DRender::QLayer *layer5 = new Qt3DRender::QLayer(rootEntity); + + rootEntity->addComponent(layer); + + childEntity1->addComponent(layer2); + childEntity1->addComponent(layer3); + + childEntity2->addComponent(layer2); + childEntity2->addComponent(layer3); + childEntity2->addComponent(layer4); + childEntity2->addComponent(layer5); + + childEntity3->addComponent(layer2); + childEntity3->addComponent(layer3); + childEntity3->addComponent(layer5); + + Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(rootEntity); + layerFilter->setFilterMode(Qt3DRender::QLayerFilter::AcceptAllMatchingLayers); + layerFilter->addLayer(layer); + layerFilter->addLayer(layer2); + layerFilter->addLayer(layer3); + + Qt3DRender::QLayerFilter *layerFilter2 = new Qt3DRender::QLayerFilter(rootEntity); + layerFilter2->setFilterMode(Qt3DRender::QLayerFilter::DiscardAnyMatchingLayers); + layerFilter2->addLayer(layer4); + layerFilter2->addLayer(layer5); + + QTest::newRow("NestedFiltering-SelectAllOfLayer123AndNoneOf45-ShouldChild1") << rootEntity + << (Qt3DCore::QNodeIdVector() << layerFilter->id() << layerFilter2->id()) + << (Qt3DCore::QNodeIdVector() + << childEntity1->id()); + } + + { + Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity(); + Qt3DCore::QEntity *childEntity1 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity2 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity3 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity4 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity5 = new Qt3DCore::QEntity(rootEntity); + + Qt3DRender::QLayer *layer = new Qt3DRender::QLayer(rootEntity); + layer->setRecursive(true); + + Qt3DRender::QLayer *layer2 = new Qt3DRender::QLayer(rootEntity); + Qt3DRender::QLayer *layer3 = new Qt3DRender::QLayer(rootEntity); + Qt3DRender::QLayer *layer4 = new Qt3DRender::QLayer(rootEntity); + Qt3DRender::QLayer *layer5 = new Qt3DRender::QLayer(rootEntity); + Qt3DRender::QLayer *layer6 = new Qt3DRender::QLayer(rootEntity); + + rootEntity->addComponent(layer); + + childEntity1->addComponent(layer2); + childEntity1->addComponent(layer3); + + childEntity2->addComponent(layer2); + childEntity2->addComponent(layer3); + childEntity2->addComponent(layer4); + childEntity2->addComponent(layer5); + + childEntity3->addComponent(layer2); + childEntity3->addComponent(layer5); + + childEntity4->addComponent(layer2); + childEntity4->addComponent(layer); + childEntity4->addComponent(layer3); + childEntity4->addComponent(layer6); + + childEntity5->addComponent(layer3); + childEntity5->addComponent(layer4); + childEntity5->addComponent(layer6); + + Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(rootEntity); + layerFilter->setFilterMode(Qt3DRender::QLayerFilter::DiscardAnyMatchingLayers); + layerFilter->addLayer(layer5); + layerFilter->addLayer(layer4); + + Qt3DRender::QLayerFilter *layerFilter2 = new Qt3DRender::QLayerFilter(rootEntity); + layerFilter2->setFilterMode(Qt3DRender::QLayerFilter::AcceptAnyMatchingLayers); + layerFilter2->addLayer(layer2); + layerFilter2->addLayer(layer3); + + Qt3DRender::QLayerFilter *layerFilter3 = new Qt3DRender::QLayerFilter(rootEntity); + layerFilter3->setFilterMode(Qt3DRender::QLayerFilter::AcceptAllMatchingLayers); + layerFilter3->addLayer(layer); + layerFilter3->addLayer(layer6); + + QTest::newRow("NestedFiltering-SelectAllNoneOfAnyLayer45AndAnyOf23AndAllOf16-ShouldSelectChild4-Step1") << rootEntity + << (Qt3DCore::QNodeIdVector() << layerFilter->id()) + << (Qt3DCore::QNodeIdVector() + << rootEntity->id() + << childEntity1->id() + << childEntity4->id() + ); + + QTest::newRow("NestedFiltering-SelectAllNoneOfAnyLayer45AndAnyOf23AndAllOf16-ShouldSelectChild4-Step2") << rootEntity + << (Qt3DCore::QNodeIdVector() << layerFilter->id() << layerFilter2->id()) + << (Qt3DCore::QNodeIdVector() + << childEntity1->id() + << childEntity4->id()); + + QTest::newRow("NestedFiltering-SelectAllNoneOfAnyLayer45AndAnyOf23AndAllOf16-ShouldSelectChild4-Step3") << rootEntity + << (Qt3DCore::QNodeIdVector() << layerFilter->id() << layerFilter2->id() << layerFilter3->id()) + << (Qt3DCore::QNodeIdVector() + << childEntity4->id()); + } } void filterEntities() { //QSKIP("Skipping until TestAspect can be registered"); QFETCH(Qt3DCore::QEntity *, entitySubtree); - QFETCH(Qt3DCore::QNodeIdVector, layerIds); - QFETCH(bool, hasLayerFilter); + QFETCH(Qt3DCore::QNodeIdVector, layerFilterIds); QFETCH(Qt3DCore::QNodeIdVector, expectedSelectedEntities); + // GIVEN QScopedPointer<Qt3DRender::TestAspect> aspect(new Qt3DRender::TestAspect(entitySubtree)); @@ -213,16 +636,15 @@ private Q_SLOTS: // WHEN Qt3DRender::Render::FilterLayerEntityJob filterJob; - filterJob.setHasLayerFilter(hasLayerFilter); - filterJob.setLayers(layerIds); + filterJob.setLayerFilters(layerFilterIds); filterJob.setManager(aspect->nodeManagers()); filterJob.run(); // THEN const QVector<Qt3DRender::Render::Entity *> filterEntities = filterJob.filteredEntities(); - QCOMPARE(expectedSelectedEntities.size(), filterEntities.size()); + QCOMPARE(filterEntities.size(), expectedSelectedEntities.size()); for (auto i = 0, m = expectedSelectedEntities.size(); i < m; ++i) - QCOMPARE(expectedSelectedEntities.at(i), filterEntities.at(i)->peerId()); + QCOMPARE(filterEntities.at(i)->peerId(), expectedSelectedEntities.at(i)); } }; diff --git a/tests/auto/render/loadscenejob/tst_loadscenejob.cpp b/tests/auto/render/loadscenejob/tst_loadscenejob.cpp index 08d1caace..bd9848928 100644 --- a/tests/auto/render/loadscenejob/tst_loadscenejob.cpp +++ b/tests/auto/render/loadscenejob/tst_loadscenejob.cpp @@ -50,8 +50,15 @@ public: m_source = source; } - bool isFileTypeSupported(const QUrl &) const Q_DECL_OVERRIDE + void setData(const QByteArray& data, const QString &basePath) Q_DECL_OVERRIDE { + Q_UNUSED(data); + Q_UNUSED(basePath); + } + + bool areFileTypesSupported(const QStringList &extensions) const Q_DECL_OVERRIDE + { + Q_UNUSED(extensions); return m_supportsFormat; } @@ -99,7 +106,7 @@ private Q_SLOTS: void checkInitialize() { // GIVEN - const QUrl url(QStringLiteral("URL")); + const QUrl url(QStringLiteral("file:///URL")); const Qt3DCore::QNodeId sceneId = Qt3DCore::QNodeId::createId(); Qt3DRender::Render::NodeManagers nodeManagers; TestSceneImporter fakeImporter(true, true); @@ -120,8 +127,10 @@ private Q_SLOTS: void checkRunValidSourceSupportedFormat() { + QSKIP("Can't test successful loading"); + // GIVEN - const QUrl url(QStringLiteral("URL")); + const QUrl url(QStringLiteral("file:///URL")); TestArbiter arbiter; Qt3DRender::Render::NodeManagers nodeManagers; TestSceneImporter fakeImporter(true, false); @@ -202,8 +211,11 @@ private Q_SLOTS: void checkRunValidSourceUnsupportedFormat() { + // no data is loaded so... + QSKIP("Can't differentiate between no data and unsupported data"); + // GIVEN - const QUrl url(QStringLiteral("URL")); + const QUrl url(QStringLiteral("file:///URL")); TestArbiter arbiter; Qt3DRender::Render::NodeManagers nodeManagers; TestSceneImporter fakeImporter(false, false); @@ -241,7 +253,7 @@ private Q_SLOTS: void checkRunErrorAtLoading() { // GIVEN - const QUrl url(QStringLiteral("URL")); + const QUrl url(QStringLiteral("file:///URL")); TestArbiter arbiter; Qt3DRender::Render::NodeManagers nodeManagers; TestSceneImporter fakeImporter(true, true); @@ -259,7 +271,7 @@ private Q_SLOTS: loadSceneJob.run(); // THEN - QCOMPARE(arbiter.events.count(), 4); + QCOMPARE(arbiter.events.count(), 3); auto change = arbiter.events.at(0).staticCast<Qt3DCore::QPropertyUpdatedChange>(); QCOMPARE(change->subjectId(), scene->peerId()); QCOMPARE(change->propertyName(), "status"); @@ -267,16 +279,11 @@ private Q_SLOTS: change = arbiter.events.at(1).staticCast<Qt3DCore::QPropertyUpdatedChange>(); QCOMPARE(change->subjectId(), scene->peerId()); - QCOMPARE(change->propertyName(), "status"); - QCOMPARE(change->value().value<Qt3DRender::QSceneLoader::Status>(), Qt3DRender::QSceneLoader::Loading); - - change = arbiter.events.at(2).staticCast<Qt3DCore::QPropertyUpdatedChange>(); - QCOMPARE(change->subjectId(), scene->peerId()); QCOMPARE(change->propertyName(), "scene"); QVERIFY(change->value().value<Qt3DCore::QEntity *>() == nullptr); delete change->value().value<Qt3DCore::QEntity *>(); - change = arbiter.events.at(3).staticCast<Qt3DCore::QPropertyUpdatedChange>(); + change = arbiter.events.at(2).staticCast<Qt3DCore::QPropertyUpdatedChange>(); QCOMPARE(change->subjectId(), scene->peerId()); QCOMPARE(change->propertyName(), "status"); QCOMPARE(change->value().value<Qt3DRender::QSceneLoader::Status>(), Qt3DRender::QSceneLoader::Error); diff --git a/tests/auto/render/meshfunctors/tst_meshfunctors.cpp b/tests/auto/render/meshfunctors/tst_meshfunctors.cpp index e2877b24b..fd430c5d8 100644 --- a/tests/auto/render/meshfunctors/tst_meshfunctors.cpp +++ b/tests/auto/render/meshfunctors/tst_meshfunctors.cpp @@ -32,6 +32,7 @@ #include <Qt3DRender/qgeometry.h> #include <Qt3DRender/qmesh.h> #include <Qt3DRender/private/qmesh_p.h> +#include <Qt3DCore/qaspectengine.h> class MeshFunctorA : public Qt3DRender::QGeometryFactory { @@ -124,14 +125,27 @@ private Q_SLOTS: void checkMeshFunctorEquality() { // GIVEN - const Qt3DRender::MeshFunctor functorA(QUrl::fromLocalFile(QLatin1String("/foo")), - QLatin1String("bar")); - const Qt3DRender::MeshFunctor functorB(QUrl::fromLocalFile(QLatin1String("/foo")), - QLatin1String("baz")); - const Qt3DRender::MeshFunctor functorC(QUrl::fromLocalFile(QLatin1String("/baz")), - QLatin1String("bar")); - const Qt3DRender::MeshFunctor functorD(QUrl::fromLocalFile(QLatin1String("/foo")), - QLatin1String("bar")); + Qt3DCore::QAspectEngine engine; + auto meshA = new Qt3DRender::QMesh(); + meshA->setSource(QUrl::fromLocalFile(QLatin1String("/foo"))); + meshA->setMeshName(QLatin1String("bar")); + + auto meshB = new Qt3DRender::QMesh(); + meshB->setSource(QUrl::fromLocalFile(QLatin1String("/foo"))); + meshB->setMeshName(QLatin1String("baz")); + + auto meshC = new Qt3DRender::QMesh(); + meshC->setSource(QUrl::fromLocalFile(QLatin1String("/baz"))); + meshC->setMeshName(QLatin1String("bar")); + + auto meshD = new Qt3DRender::QMesh(); + meshD->setSource(QUrl::fromLocalFile(QLatin1String("/foo"))); + meshD->setMeshName(QLatin1String("bar")); + + const Qt3DRender::MeshLoaderFunctor functorA(meshA, &engine); + const Qt3DRender::MeshLoaderFunctor functorB(meshB, &engine); + const Qt3DRender::MeshLoaderFunctor functorC(meshC, &engine); + const Qt3DRender::MeshLoaderFunctor functorD(meshD, &engine); // WHEN const bool selfEquality = (functorA == functorA); @@ -147,6 +161,6 @@ private Q_SLOTS: } }; -QTEST_APPLESS_MAIN(tst_MeshFunctors) +QTEST_MAIN(tst_MeshFunctors) #include "tst_meshfunctors.moc" diff --git a/tests/auto/render/pickboundingvolumejob/tst_pickboundingvolumejob.cpp b/tests/auto/render/pickboundingvolumejob/tst_pickboundingvolumejob.cpp index c60ddda27..d9d90a03d 100644 --- a/tests/auto/render/pickboundingvolumejob/tst_pickboundingvolumejob.cpp +++ b/tests/auto/render/pickboundingvolumejob/tst_pickboundingvolumejob.cpp @@ -46,6 +46,7 @@ #include <Qt3DRender/qrenderaspect.h> #include <Qt3DRender/private/qrenderaspect_p.h> #include <Qt3DRender/private/pickboundingvolumejob_p.h> +#include <Qt3DRender/private/pickboundingvolumeutils_p.h> #include <Qt3DRender/private/updatemeshtrianglelistjob_p.h> #include <Qt3DRender/private/updateworldboundingvolumejob_p.h> #include <Qt3DRender/private/updateworldtransformjob_p.h> diff --git a/tests/auto/render/proximityfilter/proximityfilter.pro b/tests/auto/render/proximityfilter/proximityfilter.pro new file mode 100644 index 000000000..74599e4f0 --- /dev/null +++ b/tests/auto/render/proximityfilter/proximityfilter.pro @@ -0,0 +1,12 @@ +TEMPLATE = app + +TARGET = tst_proximityfilter + +QT += 3dcore 3dcore-private 3drender 3drender-private testlib + +CONFIG += testcase + +SOURCES += tst_proximityfilter.cpp + +include(../../core/common/common.pri) +include(../commons/commons.pri) diff --git a/tests/auto/render/proximityfilter/tst_proximityfilter.cpp b/tests/auto/render/proximityfilter/tst_proximityfilter.cpp new file mode 100644 index 000000000..774e2dd1f --- /dev/null +++ b/tests/auto/render/proximityfilter/tst_proximityfilter.cpp @@ -0,0 +1,133 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Paul Lemire <paul.lemire350@gmail.com> +** 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$ +** +****************************************************************************/ + + +#include <QtTest/QTest> +#include <Qt3DRender/qproximityfilter.h> +#include <Qt3DRender/private/qproximityfilter_p.h> +#include <Qt3DRender/private/proximityfilter_p.h> +#include <Qt3DCore/qpropertyupdatedchange.h> +#include "qbackendnodetester.h" +#include "testrenderer.h" + +class tst_ProximityFilter : public Qt3DCore::QBackendNodeTester +{ + Q_OBJECT + +private Q_SLOTS: + + void checkInitialState() + { + // GIVEN + Qt3DRender::Render::ProximityFilter backendProximityFilter; + + // THEN + QCOMPARE(backendProximityFilter.isEnabled(), false); + QVERIFY(backendProximityFilter.peerId().isNull()); + QCOMPARE(backendProximityFilter.distanceThreshold(), 0.0f); + QCOMPARE(backendProximityFilter.entityId(), Qt3DCore::QNodeId()); + } + + void checkInitializeFromPeer() + { + // GIVEN + Qt3DRender::QProximityFilter proximityFilter; + Qt3DCore::QEntity entity; + proximityFilter.setDistanceThreshold(1340.0f); + proximityFilter.setEntity(&entity); + + { + // WHEN + Qt3DRender::Render::ProximityFilter backendProximityFilter; + simulateInitialization(&proximityFilter, &backendProximityFilter); + + // THEN + QCOMPARE(backendProximityFilter.isEnabled(), true); + QCOMPARE(backendProximityFilter.peerId(), proximityFilter.id()); + QCOMPARE(backendProximityFilter.distanceThreshold(), 1340.f); + QCOMPARE(backendProximityFilter.entityId(), entity.id()); + } + { + // WHEN + Qt3DRender::Render::ProximityFilter backendProximityFilter; + proximityFilter.setEnabled(false); + simulateInitialization(&proximityFilter, &backendProximityFilter); + + // THEN + QCOMPARE(backendProximityFilter.peerId(), proximityFilter.id()); + QCOMPARE(backendProximityFilter.isEnabled(), false); + } + } + + void checkSceneChangeEvents() + { + // GIVEN + Qt3DRender::Render::ProximityFilter backendProximityFilter; + TestRenderer renderer; + backendProximityFilter.setRenderer(&renderer); + + { + // WHEN + const bool newValue = false; + const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + change->setPropertyName("enabled"); + change->setValue(newValue); + backendProximityFilter.sceneChangeEvent(change); + + // THEN + QCOMPARE(backendProximityFilter.isEnabled(), newValue); + } + { + // WHEN + const float newValue = 383.0f; + const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + change->setPropertyName("distanceThreshold"); + change->setValue(QVariant::fromValue(newValue)); + backendProximityFilter.sceneChangeEvent(change); + + // THEN + QCOMPARE(backendProximityFilter.distanceThreshold(), newValue); + } + { + // WHEN + const Qt3DCore::QNodeId newValue = Qt3DCore::QNodeId::createId(); + const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + change->setPropertyName("entity"); + change->setValue(QVariant::fromValue(newValue)); + backendProximityFilter.sceneChangeEvent(change); + + // THEN + QCOMPARE(backendProximityFilter.entityId(), newValue); + } + } + +}; + +QTEST_MAIN(tst_ProximityFilter) + +#include "tst_proximityfilter.moc" diff --git a/tests/auto/render/proximityfiltering/proximityfiltering.pro b/tests/auto/render/proximityfiltering/proximityfiltering.pro new file mode 100644 index 000000000..68b709ec5 --- /dev/null +++ b/tests/auto/render/proximityfiltering/proximityfiltering.pro @@ -0,0 +1,13 @@ +TEMPLATE = app + +TARGET = tst_proximityfiltering + +QT += core-private 3dcore 3dcore-private 3drender 3drender-private testlib + +CONFIG += testcase + +SOURCES += tst_proximityfiltering.cpp + +CONFIG += useCommonTestAspect + +include(../commons/commons.pri) diff --git a/tests/auto/render/proximityfiltering/tst_proximityfiltering.cpp b/tests/auto/render/proximityfiltering/tst_proximityfiltering.cpp new file mode 100644 index 000000000..7a5648271 --- /dev/null +++ b/tests/auto/render/proximityfiltering/tst_proximityfiltering.cpp @@ -0,0 +1,287 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Paul Lemire +** 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$ +** +****************************************************************************/ + +#include <QtTest/QTest> +#include <Qt3DCore/qentity.h> +#include <Qt3DCore/qtransform.h> +#include <Qt3DRender/private/nodemanagers_p.h> +#include <Qt3DRender/private/managers_p.h> +#include <Qt3DRender/private/entity_p.h> +#include <Qt3DRender/private/filterproximitydistancejob_p.h> +#include <Qt3DRender/private/updatetreeenabledjob_p.h> +#include <Qt3DRender/qproximityfilter.h> + +#include "testaspect.h" + +namespace { + +Qt3DCore::QEntity *buildEntityAtDistance(float distance, Qt3DCore::QEntity *parent) +{ + Qt3DCore::QEntity *entity = new Qt3DCore::QEntity(parent); + Qt3DCore::QTransform *transform = new Qt3DCore::QTransform(parent); + const QVector3D t = QVector3D(1.0f, 0.0f, 0.0f) * distance; + + transform->setTranslation(t); + entity->addComponent(transform); + + return entity; +} + +} // anonymous + +class tst_ProximityFiltering : public QObject +{ + Q_OBJECT +private Q_SLOTS: + + void checkInitialState() + { + // GIVEN + Qt3DRender::Render::FilterProximityDistanceJob filterJob; + + // THEN + QCOMPARE(filterJob.hasProximityFilter(), false); + QCOMPARE(filterJob.filteredEntities().size(), 0); + QCOMPARE(filterJob.proximityFilterIds().size(), 0); + QVERIFY(filterJob.manager() == nullptr); + } + + void filterEntities_data() + { + QTest::addColumn<Qt3DCore::QEntity *>("entitySubtree"); + QTest::addColumn<Qt3DCore::QNodeIdVector>("proximityFilterIds"); + QTest::addColumn<Qt3DCore::QNodeIdVector>("expectedSelectedEntities"); + + { + Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity(); + Qt3DCore::QEntity *childEntity1 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity2 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity3 = new Qt3DCore::QEntity(rootEntity); + + QTest::newRow("ShouldSelectAll") << rootEntity + << Qt3DCore::QNodeIdVector() + << (Qt3DCore::QNodeIdVector() + << rootEntity->id() + << childEntity1->id() + << childEntity2->id() + << childEntity3->id() + ); + } + + { + Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity(); + Qt3DCore::QEntity *childEntity1 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity2 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity3 = new Qt3DCore::QEntity(rootEntity); + Q_UNUSED(childEntity1); + Q_UNUSED(childEntity2); + Q_UNUSED(childEntity3); + + Qt3DRender::QProximityFilter *proximityFilter = new Qt3DRender::QProximityFilter(rootEntity); + + QTest::newRow("ShouldSelectNone") << rootEntity + << (Qt3DCore::QNodeIdVector() << proximityFilter->id()) + << (Qt3DCore::QNodeIdVector()); + } + + { + Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity(); + Qt3DCore::QEntity *targetEntity = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity1 = buildEntityAtDistance(50.0f, rootEntity); + Qt3DCore::QEntity *childEntity2 = buildEntityAtDistance(25.0f, rootEntity); + Qt3DCore::QEntity *childEntity3 = buildEntityAtDistance(75.0f, rootEntity); + Qt3DRender::QProximityFilter *proximityFilter = new Qt3DRender::QProximityFilter(rootEntity); + proximityFilter->setDistanceThreshold(30.0f); + + // Note: rootEntity BoundingSphere will be centered in vec3(75.0f / 2.0, 0.0f 0.0f); + + // Note: we cannot set rootEntity here as that would mean + // that the parent of the root would then be the proximity filter + // (since rootEntity has no parent) but this isn't valid in the way + // we have build the test + // Also rootEntity is centered based on the size of the child it contains + proximityFilter->setEntity(targetEntity); + + Q_UNUSED(childEntity1); + Q_UNUSED(childEntity3); + + QTest::newRow("ShouldSelectChild2") << rootEntity + << (Qt3DCore::QNodeIdVector() << proximityFilter->id()) + << (Qt3DCore::QNodeIdVector() + << targetEntity->id() + << childEntity2->id() + ); + } + + { + Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity(); + Qt3DCore::QEntity *targetEntity = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity1 = buildEntityAtDistance(50.0f, rootEntity); + Qt3DCore::QEntity *childEntity2 = buildEntityAtDistance(25.0f, rootEntity); + Qt3DCore::QEntity *childEntity3 = buildEntityAtDistance(49.9f, rootEntity); + Qt3DRender::QProximityFilter *proximityFilter = new Qt3DRender::QProximityFilter(rootEntity); + proximityFilter->setDistanceThreshold(50.0f); + + // Note: rootEntity BoundingSphere will be centered in vec3(50.0f / 2.0, 0.0f 0.0f); + + // Note: we cannot set rootEntity here as that would mean + // that the parent of the root would then be the proximity filter + // (since rootEntity has no parent) but this isn't valid in the way + // we have build the test + // Also rootEntity is centered based on the size of the child it contains + proximityFilter->setEntity(targetEntity); + + QTest::newRow("ShouldSelectRootChild123") << rootEntity + << (Qt3DCore::QNodeIdVector() << proximityFilter->id()) + << (Qt3DCore::QNodeIdVector() + << rootEntity->id() + << targetEntity->id() + << childEntity1->id() + << childEntity2->id() + << childEntity3->id() + ); + } + + { + Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity(); + Qt3DCore::QEntity *targetEntity = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity1 = buildEntityAtDistance(51.0f, rootEntity); + Qt3DCore::QEntity *childEntity2 = buildEntityAtDistance(75.0f, rootEntity); + Qt3DCore::QEntity *childEntity3 = buildEntityAtDistance(883.0f, rootEntity); + Qt3DRender::QProximityFilter *proximityFilter = new Qt3DRender::QProximityFilter(rootEntity); + proximityFilter->setDistanceThreshold(50.0f); + + // Note: rootEntity BoundingSphere will be centered in vec3(883.0f / 2.0, 0.0f 0.0f); + + // Note: we cannot set rootEntity here as that would mean + // that the parent of the root would then be the proximity filter + // (since rootEntity has no parent) but this isn't valid in the way + // we have build the test + // Also rootEntity is centered based on the size of the child it contains + proximityFilter->setEntity(targetEntity); + + Q_UNUSED(childEntity1); + Q_UNUSED(childEntity2); + Q_UNUSED(childEntity3); + + QTest::newRow("ShouldSelectNoneButTarget") << rootEntity + << (Qt3DCore::QNodeIdVector() << proximityFilter->id()) + << (Qt3DCore::QNodeIdVector() << targetEntity->id()); + } + + { + Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity(); + Qt3DCore::QEntity *targetEntity = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity1 = buildEntityAtDistance(50.0f, rootEntity); + Qt3DCore::QEntity *childEntity2 = buildEntityAtDistance(150.0f, rootEntity); + Qt3DCore::QEntity *childEntity3 = buildEntityAtDistance(25.0f, rootEntity); + + Qt3DRender::QProximityFilter *proximityFilter = new Qt3DRender::QProximityFilter(rootEntity); + proximityFilter->setDistanceThreshold(50.0f); + + Qt3DRender::QProximityFilter *proximityFilter2 = new Qt3DRender::QProximityFilter(rootEntity); + proximityFilter2->setDistanceThreshold(30.0f); + + // Note: rootEntity BoundingSphere will be centered in vec3(150.0f / 2.0, 0.0f 0.0f); + + // Note: we cannot set rootEntity here as that would mean + // that the parent of the root would then be the proximity filter + // (since rootEntity has no parent) but this isn't valid in the way + // we have build the test + // Also rootEntity is centered based on the size of the child it contains + proximityFilter->setEntity(targetEntity); + proximityFilter2->setEntity(targetEntity); + + Q_UNUSED(childEntity2); + + QTest::newRow("Nested-Step1") << rootEntity + << (Qt3DCore::QNodeIdVector() << proximityFilter->id()) + << (Qt3DCore::QNodeIdVector() + << targetEntity->id() + << childEntity1->id() + << childEntity3->id() + ); + QTest::newRow("Nested-Step2") << rootEntity + << (Qt3DCore::QNodeIdVector() << proximityFilter->id() << proximityFilter2->id()) + << (Qt3DCore::QNodeIdVector() + << targetEntity->id() + << childEntity3->id() + ); + } + } + + void filterEntities() + { + QFETCH(Qt3DCore::QEntity *, entitySubtree); + QFETCH(Qt3DCore::QNodeIdVector, proximityFilterIds); + QFETCH(Qt3DCore::QNodeIdVector, expectedSelectedEntities); + + // GIVEN + QScopedPointer<Qt3DRender::TestAspect> aspect(new Qt3DRender::TestAspect(entitySubtree)); + + // WHEN + Qt3DRender::Render::Entity *backendRoot = aspect->nodeManagers()->renderNodesManager()->getOrCreateResource(entitySubtree->id()); + Qt3DRender::Render::UpdateTreeEnabledJob updateTreeEnabledJob; + updateTreeEnabledJob.setRoot(backendRoot); + updateTreeEnabledJob.run(); + + Qt3DRender::Render::UpdateWorldTransformJob updateWorldTransform; + updateWorldTransform.setRoot(backendRoot); + updateWorldTransform.run(); + + Qt3DRender::Render::CalculateBoundingVolumeJob calcBVolume; + calcBVolume.setManagers(aspect->nodeManagers()); + calcBVolume.setRoot(backendRoot); + calcBVolume.run(); + + Qt3DRender::Render::UpdateWorldBoundingVolumeJob updateWorldBVolume; + updateWorldBVolume.setManager(aspect->nodeManagers()->renderNodesManager()); + updateWorldBVolume.run(); + + Qt3DRender::Render::ExpandBoundingVolumeJob expandBVolume; + expandBVolume.setRoot(backendRoot); + expandBVolume.run(); + + // WHEN + Qt3DRender::Render::FilterProximityDistanceJob filterJob; + filterJob.setProximityFilterIds(proximityFilterIds); + filterJob.setManager(aspect->nodeManagers()); + filterJob.run(); + + // THEN + const QVector<Qt3DRender::Render::Entity *> filterEntities = filterJob.filteredEntities(); + QCOMPARE(filterEntities.size(), expectedSelectedEntities.size()); + + for (auto i = 0, m = expectedSelectedEntities.size(); i < m; ++i) + QCOMPARE(filterEntities.at(i)->peerId(), expectedSelectedEntities.at(i)); + } +}; + +QTEST_MAIN(tst_ProximityFiltering) + +#include "tst_proximityfiltering.moc" diff --git a/tests/auto/render/qattribute/tst_qattribute.cpp b/tests/auto/render/qattribute/tst_qattribute.cpp index 66854acdd..23532c435 100644 --- a/tests/auto/render/qattribute/tst_qattribute.cpp +++ b/tests/auto/render/qattribute/tst_qattribute.cpp @@ -58,6 +58,8 @@ private Q_SLOTS: QCOMPARE(Qt3DRender::QAttribute::defaultColorAttributeName(), QStringLiteral("vertexColor")); QCOMPARE(Qt3DRender::QAttribute::defaultTextureCoordinateAttributeName(), QStringLiteral("vertexTexCoord")); QCOMPARE(Qt3DRender::QAttribute::defaultTangentAttributeName(), QStringLiteral("vertexTangent")); + QCOMPARE(Qt3DRender::QAttribute::defaultJointIndicesAttributeName(), QStringLiteral("vertexJointIndices")); + QCOMPARE(Qt3DRender::QAttribute::defaultJointWeightsAttributeName(), QStringLiteral("vertexJointWeights")); QCOMPARE(attribute.property("defaultPositionAttributeName").toString(), Qt3DRender::QAttribute::defaultPositionAttributeName()); @@ -69,6 +71,10 @@ private Q_SLOTS: Qt3DRender::QAttribute::defaultTextureCoordinateAttributeName()); QCOMPARE(attribute.property("defaultTangentAttributeName").toString(), Qt3DRender::QAttribute::defaultTangentAttributeName()); + QCOMPARE(attribute.property("defaultJointIndicesAttributeName").toString(), + Qt3DRender::QAttribute::defaultJointIndicesAttributeName()); + QCOMPARE(attribute.property("defaultJointWeightsAttributeName").toString(), + Qt3DRender::QAttribute::defaultJointWeightsAttributeName()); } void checkCloning_data() diff --git a/tests/auto/render/qblitframebuffer/qblitframebuffer.pro b/tests/auto/render/qblitframebuffer/qblitframebuffer.pro new file mode 100644 index 000000000..219bad3d2 --- /dev/null +++ b/tests/auto/render/qblitframebuffer/qblitframebuffer.pro @@ -0,0 +1,11 @@ +TEMPLATE = app + +TARGET = tst_qblitframebuffer + +QT += core-private 3dcore 3dcore-private 3drender 3drender-private testlib + +CONFIG += testcase + +SOURCES += tst_qblitframebuffer.cpp + +include(../../core/common/common.pri) diff --git a/tests/auto/render/qblitframebuffer/tst_qblitframebuffer.cpp b/tests/auto/render/qblitframebuffer/tst_qblitframebuffer.cpp new file mode 100644 index 000000000..26ef936f6 --- /dev/null +++ b/tests/auto/render/qblitframebuffer/tst_qblitframebuffer.cpp @@ -0,0 +1,338 @@ +/**************************************************************************** +** +** Copyright (C) 2015 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$ +** +****************************************************************************/ + +#include <QtTest/QTest> +#include <Qt3DCore/private/qnode_p.h> +#include <Qt3DCore/private/qscene_p.h> +#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h> + +#include <Qt3DRender/QBlitFramebuffer> +#include <Qt3DRender/private/qblitframebuffer_p.h> + +#include "testpostmanarbiter.h" + +class tst_QBlitFrameBuffer: public QObject +{ + Q_OBJECT + +public: + tst_QBlitFrameBuffer() : QObject() + { + qRegisterMetaType<Qt3DRender::QRenderTarget*>(); + } + +private Q_SLOTS: + + void checkCreationData_data() + { + QTest::addColumn<Qt3DRender::QBlitFramebuffer *>("blitFramebuffer"); + + Qt3DRender::QBlitFramebuffer *defaultConstructed = new Qt3DRender::QBlitFramebuffer(); + Qt3DRender::QRenderTarget *sourceRenderTarget = new Qt3DRender::QRenderTarget(); + Qt3DRender::QRenderTarget *destinationRenderTarget = new Qt3DRender::QRenderTarget(); + defaultConstructed->setSource(sourceRenderTarget); + defaultConstructed->setDestination(destinationRenderTarget); + QTest::newRow("defaultConstructed") << defaultConstructed; + } + + void checkInitialState() + { + // GIVEN + Qt3DRender::QBlitFramebuffer blitFramebuffer; + + // THEN + QCOMPARE(blitFramebuffer.source(), nullptr); + QCOMPARE(blitFramebuffer.destination(), nullptr); + QCOMPARE(blitFramebuffer.sourceRect(), QRect()); + QCOMPARE(blitFramebuffer.destinationRect(), QRect()); + QCOMPARE(blitFramebuffer.sourceAttachmentPoint(), Qt3DRender::QRenderTargetOutput::AttachmentPoint::Color0); + QCOMPARE(blitFramebuffer.destinationAttachmentPoint(), Qt3DRender::QRenderTargetOutput::AttachmentPoint::Color0); + QCOMPARE(blitFramebuffer.interpolationMethod(), Qt3DRender::QBlitFramebuffer::Linear); + } + + void checkCreationData() + { + // GIVEN + QFETCH(Qt3DRender::QBlitFramebuffer *, blitFramebuffer); + + // WHEN + Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(blitFramebuffer); + QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges = creationChangeGenerator.creationChanges(); + + // THEN + QCOMPARE(creationChanges.size(), 1); + + const Qt3DCore::QNodeCreatedChangePtr<Qt3DRender::QBlitFramebufferData> creationChangeData = + qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DRender::QBlitFramebufferData>>(creationChanges.first()); + const Qt3DRender::QBlitFramebufferData &cloneData = creationChangeData->data; + + // THEN + QCOMPARE(blitFramebuffer->id(), creationChangeData->subjectId()); + QCOMPARE(blitFramebuffer->isEnabled(), creationChangeData->isNodeEnabled()); + QCOMPARE(blitFramebuffer->metaObject(), creationChangeData->metaObject()); + QCOMPARE(blitFramebuffer->source()->id(), cloneData.m_sourceRenderTargetId); + QCOMPARE(blitFramebuffer->destination()->id(), cloneData.m_destinationRenderTargetId); + QCOMPARE(blitFramebuffer->sourceRect(), cloneData.m_sourceRect); + QCOMPARE(blitFramebuffer->destinationRect(), cloneData.m_destinationRect); + QCOMPARE(blitFramebuffer->sourceAttachmentPoint(), cloneData.m_sourceAttachmentPoint); + QCOMPARE(blitFramebuffer->destinationAttachmentPoint(), cloneData.m_destinationAttachmentPoint); + + + delete blitFramebuffer; + } + + void checkPropertyUpdate() + { + // GIVEN + TestArbiter arbiter; + QScopedPointer<Qt3DRender::QBlitFramebuffer> blitFramebuffer(new Qt3DRender::QBlitFramebuffer()); + arbiter.setArbiterOnNode(blitFramebuffer.data()); + + Qt3DRender::QRenderTarget *sourceRenderTarget = new Qt3DRender::QRenderTarget; + Qt3DRender::QRenderTarget *destinationRenderTarget = new Qt3DRender::QRenderTarget; + + // sourceRenderTarget + // WHEN + blitFramebuffer->setSource(sourceRenderTarget); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "source"); + QCOMPARE(change->subjectId(), blitFramebuffer->id()); + QCOMPARE(change->value().value<Qt3DCore::QNodeId>(), sourceRenderTarget->id()); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + + // WHEN + blitFramebuffer->setSource(sourceRenderTarget); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + + // WHEN + blitFramebuffer->setSource(nullptr); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "source"); + QCOMPARE(change->subjectId(), blitFramebuffer->id()); + QCOMPARE(change->value().value<Qt3DCore::QNodeId>(), Qt3DCore::QNodeId()); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + + // destinationRenderTarget + // WHEN + blitFramebuffer->setDestination(destinationRenderTarget); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "destination"); + QCOMPARE(change->subjectId(), blitFramebuffer->id()); + QCOMPARE(change->value().value<Qt3DCore::QNodeId>(), destinationRenderTarget->id()); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + + // WHEN + blitFramebuffer->setDestination(destinationRenderTarget); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + + // WHEN + blitFramebuffer->setDestination(nullptr); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "destination"); + QCOMPARE(change->subjectId(), blitFramebuffer->id()); + QCOMPARE(change->value().value<Qt3DCore::QNodeId>(), Qt3DCore::QNodeId()); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + + // sourceRect + // WHEN + blitFramebuffer->setSourceRect(QRect(0,0,1,1)); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "sourceRect"); + QCOMPARE(change->subjectId(), blitFramebuffer->id()); + QCOMPARE(change->value().value<QRect>(), QRect(0,0,1,1)) ; + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + + // WHEN + blitFramebuffer->setSourceRect(QRect(0,0,1,1)); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + + // WHEN + blitFramebuffer->setSourceRect(QRect()); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "sourceRect"); + QCOMPARE(change->subjectId(), blitFramebuffer->id()); + QCOMPARE(change->value().value<QRect>(), QRect()); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + + // destinationRect + blitFramebuffer->setDestinationRect(QRect(0,0,1,1)); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "destinationRect"); + QCOMPARE(change->subjectId(), blitFramebuffer->id()); + QCOMPARE(change->value().value<QRect>(), QRect(0,0,1,1)) ; + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + + // WHEN + blitFramebuffer->setDestinationRect(QRect(0,0,1,1)); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + + // WHEN + blitFramebuffer->setDestinationRect(QRect()); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "destinationRect"); + QCOMPARE(change->subjectId(), blitFramebuffer->id()); + QCOMPARE(change->value().value<QRect>(), QRect()); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + + // sourceAttachmentPoint + // WHEN + blitFramebuffer->setSourceAttachmentPoint(Qt3DRender::QRenderTargetOutput::Color1); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "sourceAttachmentPoint"); + QCOMPARE(change->subjectId(), blitFramebuffer->id()); + QCOMPARE(change->value().value<Qt3DRender::QRenderTargetOutput::AttachmentPoint>(), Qt3DRender::QRenderTargetOutput::Color1); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + + // WHEN + blitFramebuffer->setSourceAttachmentPoint(Qt3DRender::QRenderTargetOutput::Color1); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + + // WHEN + blitFramebuffer->setSourceAttachmentPoint(Qt3DRender::QRenderTargetOutput::Color0); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "sourceAttachmentPoint"); + QCOMPARE(change->subjectId(), blitFramebuffer->id()); + QCOMPARE(change->value().value<Qt3DRender::QRenderTargetOutput::AttachmentPoint>(), Qt3DRender::QRenderTargetOutput::Color0); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + + // destinationAttachmentPoint + // WHEN + blitFramebuffer->setDestinationAttachmentPoint(Qt3DRender::QRenderTargetOutput::Color1); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "destinationAttachmentPoint"); + QCOMPARE(change->subjectId(), blitFramebuffer->id()); + QCOMPARE(change->value().value<Qt3DRender::QRenderTargetOutput::AttachmentPoint>(), Qt3DRender::QRenderTargetOutput::Color1); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + + // WHEN + blitFramebuffer->setDestinationAttachmentPoint(Qt3DRender::QRenderTargetOutput::Color1); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + + // WHEN + blitFramebuffer->setDestinationAttachmentPoint(Qt3DRender::QRenderTargetOutput::Color0); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "destinationAttachmentPoint"); + QCOMPARE(change->subjectId(), blitFramebuffer->id()); + QCOMPARE(change->value().value<Qt3DRender::QRenderTargetOutput::AttachmentPoint>(), Qt3DRender::QRenderTargetOutput::Color0); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + } +}; + +QTEST_MAIN(tst_QBlitFrameBuffer) + +#include "tst_qblitframebuffer.moc" diff --git a/tests/auto/render/qbuffer/tst_qbuffer.cpp b/tests/auto/render/qbuffer/tst_qbuffer.cpp index fdc25cbca..719c6229f 100644 --- a/tests/auto/render/qbuffer/tst_qbuffer.cpp +++ b/tests/auto/render/qbuffer/tst_qbuffer.cpp @@ -112,7 +112,6 @@ private Q_SLOTS: QCOMPARE(buffer->metaObject(), creationChangeData->metaObject()); QCOMPARE(buffer->data(), cloneData.data); QCOMPARE(buffer->usage(), cloneData.usage); - QCOMPARE(buffer->type(), cloneData.type); QCOMPARE(buffer->dataGenerator(), cloneData.functor); QCOMPARE(buffer->isSyncData(), cloneData.syncData); if (buffer->dataGenerator()) { diff --git a/tests/auto/render/qgeometryrenderer/tst_qgeometryrenderer.cpp b/tests/auto/render/qgeometryrenderer/tst_qgeometryrenderer.cpp index 94f720097..edd767ad9 100644 --- a/tests/auto/render/qgeometryrenderer/tst_qgeometryrenderer.cpp +++ b/tests/auto/render/qgeometryrenderer/tst_qgeometryrenderer.cpp @@ -88,6 +88,7 @@ private Q_SLOTS: geometry1->setInstanceCount(1); geometry1->setIndexOffset(0); geometry1->setFirstInstance(55); + geometry1->setIndexBufferByteOffset(48); geometry1->setRestartIndexValue(-1); geometry1->setPrimitiveRestartEnabled(false); geometry1->setPrimitiveType(Qt3DRender::QGeometryRenderer::Triangles); @@ -101,6 +102,7 @@ private Q_SLOTS: geometry2->setInstanceCount(200); geometry2->setIndexOffset(58); geometry2->setFirstInstance(10); + geometry2->setIndexBufferByteOffset(96); geometry2->setRestartIndexValue(65535); geometry2->setVertexCount(2056); geometry2->setPrimitiveRestartEnabled(true); @@ -134,6 +136,7 @@ private Q_SLOTS: QCOMPARE(cloneData.vertexCount, geometryRenderer->vertexCount()); QCOMPARE(cloneData.indexOffset, geometryRenderer->indexOffset()); QCOMPARE(cloneData.firstInstance, geometryRenderer->firstInstance()); + QCOMPARE(cloneData.indexBufferByteOffset, geometryRenderer->indexBufferByteOffset()); QCOMPARE(cloneData.restartIndexValue, geometryRenderer->restartIndexValue()); QCOMPARE(cloneData.primitiveRestart, geometryRenderer->primitiveRestartEnabled()); QCOMPARE(cloneData.primitiveType, geometryRenderer->primitiveType()); @@ -207,6 +210,19 @@ private Q_SLOTS: arbiter.events.clear(); // WHEN + geometryRenderer->setIndexBufferByteOffset(91); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "indexBufferByteOffset"); + QCOMPARE(change->value().value<int>(), 91); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + + // WHEN geometryRenderer->setRestartIndexValue(65535); QCoreApplication::processEvents(); diff --git a/tests/auto/render/qgraphicsapifilter/tst_qgraphicsapifilter.cpp b/tests/auto/render/qgraphicsapifilter/tst_qgraphicsapifilter.cpp index ac6f79b3f..9e0cb8e57 100644 --- a/tests/auto/render/qgraphicsapifilter/tst_qgraphicsapifilter.cpp +++ b/tests/auto/render/qgraphicsapifilter/tst_qgraphicsapifilter.cpp @@ -36,6 +36,13 @@ class tst_QGraphicsApiFilter : public QObject { Q_OBJECT +public: + tst_QGraphicsApiFilter() : QObject() + { + qRegisterMetaType<Qt3DRender::QGraphicsApiFilter::Api>(); + qRegisterMetaType<Qt3DRender::QGraphicsApiFilter::OpenGLProfile>(); + } + private Q_SLOTS: void defaultConstruction() { diff --git a/tests/auto/render/qmesh/tst_qmesh.cpp b/tests/auto/render/qmesh/tst_qmesh.cpp index 2122d7eb5..127371750 100644 --- a/tests/auto/render/qmesh/tst_qmesh.cpp +++ b/tests/auto/render/qmesh/tst_qmesh.cpp @@ -34,6 +34,7 @@ #include <QSignalSpy> #include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DCore/private/qnodecreatedchangegenerator_p.h> +#include <Qt3DCore/private/qscene_p.h> #include <Qt3DCore/qnodecreatedchange.h> #include "testpostmanarbiter.h" @@ -121,9 +122,8 @@ private Q_SLOTS: const auto creationChangeData = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DRender::QGeometryRendererData>>(creationChanges.first()); const Qt3DRender::QGeometryRendererData cloneData = creationChangeData->data; - Qt3DRender::MeshFunctor meshFunctor(mesh.source(), mesh.meshName()); - - QVERIFY(meshFunctor == *cloneData.geometryFactory); + // Geometry factory is null until the engine becomes available + QVERIFY(cloneData.geometryFactory == nullptr); QCOMPARE(mesh.id(), creationChangeData->subjectId()); QCOMPARE(mesh.isEnabled(), true); QCOMPARE(mesh.isEnabled(), creationChangeData->isNodeEnabled()); @@ -158,6 +158,13 @@ private Q_SLOTS: Qt3DRender::QMesh mesh; arbiter.setArbiterOnNode(&mesh); + Qt3DCore::QAspectEngine *engine = reinterpret_cast<Qt3DCore::QAspectEngine*>(0xdeadbeef); + Qt3DCore::QScene *scene = new Qt3DCore::QScene(engine); + Qt3DCore::QNodePrivate *meshd = Qt3DCore::QNodePrivate::get(&mesh); + meshd->setScene(scene); + QCoreApplication::processEvents(); + arbiter.events.clear(); + { // WHEN mesh.setSource(QUrl(QStringLiteral("qrc:/toyplane.obj"))); @@ -165,13 +172,15 @@ private Q_SLOTS: // THEN QCOMPARE(arbiter.events.size(), 1); - auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + auto change = arbiter.events.last().staticCast<Qt3DCore::QPropertyUpdatedChange>(); QCOMPARE(change->propertyName(), "geometryFactory"); QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); - Qt3DRender::MeshFunctor meshFunctor(mesh.source()); Qt3DRender::QGeometryFactoryPtr factory = change->value().value<Qt3DRender::QGeometryFactoryPtr>(); - QVERIFY(meshFunctor == *factory); + QSharedPointer<Qt3DRender::MeshLoaderFunctor> meshFunctor = qSharedPointerCast<Qt3DRender::MeshLoaderFunctor>(factory); + QVERIFY(meshFunctor != nullptr); + QCOMPARE(meshFunctor->m_mesh, mesh.id()); + QCOMPARE(meshFunctor->m_sourcePath, mesh.source()); arbiter.events.clear(); } @@ -194,6 +203,13 @@ private Q_SLOTS: Qt3DRender::QMesh mesh; arbiter.setArbiterOnNode(&mesh); + Qt3DCore::QAspectEngine *engine = reinterpret_cast<Qt3DCore::QAspectEngine*>(0xdeadbeef); + Qt3DCore::QScene *scene = new Qt3DCore::QScene(engine); + Qt3DCore::QNodePrivate *meshd = Qt3DCore::QNodePrivate::get(&mesh); + meshd->setScene(scene); + QCoreApplication::processEvents(); + arbiter.events.clear(); + { // WHEN mesh.setMeshName(QStringLiteral("Phil")); @@ -205,9 +221,11 @@ private Q_SLOTS: QCOMPARE(change->propertyName(), "geometryFactory"); QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); - Qt3DRender::MeshFunctor meshFunctor(QUrl(), mesh.meshName()); Qt3DRender::QGeometryFactoryPtr factory = change->value().value<Qt3DRender::QGeometryFactoryPtr>(); - QVERIFY(meshFunctor == *factory); + QSharedPointer<Qt3DRender::MeshLoaderFunctor> meshFunctor = qSharedPointerCast<Qt3DRender::MeshLoaderFunctor>(factory); + QVERIFY(meshFunctor != nullptr); + QCOMPARE(meshFunctor->m_mesh, mesh.id()); + QCOMPARE(meshFunctor->m_meshName, mesh.meshName()); arbiter.events.clear(); } diff --git a/tests/auto/render/qproximityfilter/qproximityfilter.pro b/tests/auto/render/qproximityfilter/qproximityfilter.pro new file mode 100644 index 000000000..4a12e244f --- /dev/null +++ b/tests/auto/render/qproximityfilter/qproximityfilter.pro @@ -0,0 +1,12 @@ +TEMPLATE = app + +TARGET = tst_qproximityfilter + +QT += 3dcore 3dcore-private 3drender 3drender-private testlib + +CONFIG += testcase + +SOURCES += tst_qproximityfilter.cpp + +include(../../core/common/common.pri) +include(../commons/commons.pri) diff --git a/tests/auto/render/qproximityfilter/tst_qproximityfilter.cpp b/tests/auto/render/qproximityfilter/tst_qproximityfilter.cpp new file mode 100644 index 000000000..890d6ee3e --- /dev/null +++ b/tests/auto/render/qproximityfilter/tst_qproximityfilter.cpp @@ -0,0 +1,270 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Paul Lemire <paul.lemire350@gmail.com> +** 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$ +** +****************************************************************************/ + +#include <QtTest/QTest> +#include <Qt3DRender/qproximityfilter.h> +#include <Qt3DRender/private/qproximityfilter_p.h> +#include <QObject> +#include <QSignalSpy> +#include <Qt3DCore/qpropertyupdatedchange.h> +#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h> +#include <Qt3DCore/qnodecreatedchange.h> +#include <Qt3DCore/qentity.h> +#include "testpostmanarbiter.h" + +class tst_QProximityFilter : public QObject +{ + Q_OBJECT + +public: + tst_QProximityFilter() : QObject() + { + qRegisterMetaType<Qt3DCore::QEntity*>(); + } + +private Q_SLOTS: + + void checkDefaultConstruction() + { + // GIVEN + Qt3DRender::QProximityFilter proximityFilter; + + // THEN + QVERIFY(proximityFilter.entity() == nullptr); + QCOMPARE(proximityFilter.distanceThreshold(), 0.0f); + } + + void checkPropertyChanges() + { + // GIVEN + Qt3DRender::QProximityFilter proximityFilter; + + { + // WHEN + Qt3DCore::QEntity entity; + + QSignalSpy spy(&proximityFilter, SIGNAL(entityChanged(Qt3DCore::QEntity *))); + Qt3DCore::QEntity *newValue = &entity; + proximityFilter.setEntity(newValue); + + // THEN + QVERIFY(spy.isValid()); + QCOMPARE(proximityFilter.entity(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + proximityFilter.setEntity(newValue); + + // THEN + QCOMPARE(proximityFilter.entity(), newValue); + QCOMPARE(spy.count(), 0); + } + { + // WHEN + QSignalSpy spy(&proximityFilter, SIGNAL(distanceThresholdChanged(float))); + const float newValue = 883.0f; + proximityFilter.setDistanceThreshold(newValue); + + // THEN + QVERIFY(spy.isValid()); + QCOMPARE(proximityFilter.distanceThreshold(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + proximityFilter.setDistanceThreshold(newValue); + + // THEN + QCOMPARE(proximityFilter.distanceThreshold(), newValue); + QCOMPARE(spy.count(), 0); + } + } + + void checkCreationData() + { + // GIVEN + Qt3DRender::QProximityFilter proximityFilter; + Qt3DCore::QEntity entity; + + proximityFilter.setEntity(&entity); + proximityFilter.setDistanceThreshold(1584.0f); + + // WHEN + QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges; + + { + Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&proximityFilter); + creationChanges = creationChangeGenerator.creationChanges(); + } + + // THEN + { + QCOMPARE(creationChanges.size(), 2); // Entity creation change is the second change + + const auto creationChangeData = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DRender::QProximityFilterData>>(creationChanges.first()); + const Qt3DRender::QProximityFilterData cloneData = creationChangeData->data; + + QCOMPARE(proximityFilter.entity()->id(), cloneData.entityId); + QCOMPARE(proximityFilter.distanceThreshold(), cloneData.distanceThreshold); + QCOMPARE(proximityFilter.id(), creationChangeData->subjectId()); + QCOMPARE(proximityFilter.isEnabled(), true); + QCOMPARE(proximityFilter.isEnabled(), creationChangeData->isNodeEnabled()); + QCOMPARE(proximityFilter.metaObject(), creationChangeData->metaObject()); + } + + // WHEN + proximityFilter.setEnabled(false); + + { + Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&proximityFilter); + creationChanges = creationChangeGenerator.creationChanges(); + } + + // THEN + { + QCOMPARE(creationChanges.size(), 2); // Entity creation change is the second change + + const auto creationChangeData = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DRender::QProximityFilterData>>(creationChanges.first()); + const Qt3DRender::QProximityFilterData cloneData = creationChangeData->data; + + QCOMPARE(proximityFilter.entity()->id(), cloneData.entityId); + QCOMPARE(proximityFilter.distanceThreshold(), cloneData.distanceThreshold); + QCOMPARE(proximityFilter.id(), creationChangeData->subjectId()); + QCOMPARE(proximityFilter.isEnabled(), false); + QCOMPARE(proximityFilter.isEnabled(), creationChangeData->isNodeEnabled()); + QCOMPARE(proximityFilter.metaObject(), creationChangeData->metaObject()); + } + } + + void checkEntityUpdate() + { + // GIVEN + TestArbiter arbiter; + Qt3DRender::QProximityFilter proximityFilter; + arbiter.setArbiterOnNode(&proximityFilter); + Qt3DCore::QEntity entity; + + { + // WHEN + proximityFilter.setEntity(&entity); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "entity"); + QCOMPARE(change->value().value<Qt3DCore::QNodeId>(), proximityFilter.entity()->id()); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + } + + { + // WHEN + proximityFilter.setEntity(&entity); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + } + + } + + void checkDistanceThresholdUpdate() + { + // GIVEN + TestArbiter arbiter; + Qt3DRender::QProximityFilter proximityFilter; + arbiter.setArbiterOnNode(&proximityFilter); + + { + // WHEN + proximityFilter.setDistanceThreshold(454.0f); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "distanceThreshold"); + QCOMPARE(change->value().value<float>(), proximityFilter.distanceThreshold()); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + } + + { + // WHEN + proximityFilter.setDistanceThreshold(454.0f); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + } + + } + + void checkEntityBookkeeping() + { + // GIVEN + QScopedPointer<Qt3DRender::QProximityFilter> proximityFilter(new Qt3DRender::QProximityFilter); + { + // WHEN + Qt3DCore::QEntity entity; + proximityFilter->setEntity(&entity); + + // THEN + QCOMPARE(entity.parent(), proximityFilter.data()); + QCOMPARE(proximityFilter->entity(), &entity); + } + + // THEN (Should not crash and parameter be unset) + QVERIFY(proximityFilter->entity() == nullptr); + + { + // WHEN + Qt3DRender::QProximityFilter someOtherProximityFilter; + QScopedPointer<Qt3DCore::QEntity> entity(new Qt3DCore::QEntity(&someOtherProximityFilter)); + proximityFilter->setEntity(entity.data()); + + // THEN + QCOMPARE(entity->parent(), &someOtherProximityFilter); + QCOMPARE(proximityFilter->entity(), entity.data()); + + // WHEN + proximityFilter.reset(); + entity.reset(); + + // THEN Should not crash when the camera is destroyed (tests for failed removal of destruction helper) + } + } +}; + +QTEST_MAIN(tst_QProximityFilter) + +#include "tst_qproximityfilter.moc" diff --git a/tests/auto/render/qrendercapture/tst_qrendercapture.cpp b/tests/auto/render/qrendercapture/tst_qrendercapture.cpp index d4e603ea4..830615a95 100644 --- a/tests/auto/render/qrendercapture/tst_qrendercapture.cpp +++ b/tests/auto/render/qrendercapture/tst_qrendercapture.cpp @@ -67,7 +67,7 @@ private Q_SLOTS: arbiter.setArbiterOnNode(renderCapture.data()); // WHEN - QScopedPointer<Qt3DRender::QRenderCaptureReply> reply(renderCapture->requestCapture()); + QScopedPointer<Qt3DRender::QRenderCaptureReply> reply(renderCapture->requestCapture(QRect(10, 15, 20, 50))); // THEN QCOMPARE(arbiter.events.size(), 1); @@ -75,7 +75,10 @@ private Q_SLOTS: QCOMPARE(change->propertyName(), "renderCaptureRequest"); QCOMPARE(change->subjectId(),renderCapture->id()); QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); - QCOMPARE(change->value().toInt(), 1); + QVERIFY(change->value().canConvert<Qt3DRender::QRenderCaptureRequest>()); + const Qt3DRender::QRenderCaptureRequest request = change->value().value<Qt3DRender::QRenderCaptureRequest>(); + QCOMPARE(request.captureId, 1); + QCOMPARE(request.rect, QRect(10, 15, 20, 50)); arbiter.events.clear(); } diff --git a/tests/auto/render/qrendersettings/tst_qrendersettings.cpp b/tests/auto/render/qrendersettings/tst_qrendersettings.cpp index 1f0a9f066..6f182cbeb 100644 --- a/tests/auto/render/qrendersettings/tst_qrendersettings.cpp +++ b/tests/auto/render/qrendersettings/tst_qrendersettings.cpp @@ -184,6 +184,7 @@ private Q_SLOTS: pickingSettings->setPickMethod(Qt3DRender::QPickingSettings::TrianglePicking); pickingSettings->setPickResultMode(Qt3DRender::QPickingSettings::AllPicks); pickingSettings->setFaceOrientationPickingMode(Qt3DRender::QPickingSettings::FrontAndBackFace); + pickingSettings->setWorldSpaceTolerance(5.f); // WHEN QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges; @@ -203,6 +204,7 @@ private Q_SLOTS: QCOMPARE(renderSettings.pickingSettings()->pickMethod(), cloneData.pickMethod); QCOMPARE(renderSettings.pickingSettings()->pickResultMode(), cloneData.pickResultMode); QCOMPARE(renderSettings.pickingSettings()->faceOrientationPickingMode(), cloneData.faceOrientationPickingMode); + QCOMPARE(renderSettings.pickingSettings()->worldSpaceTolerance(), cloneData.pickWorldSpaceTolerance); QCOMPARE(renderSettings.renderPolicy(), cloneData.renderPolicy); QCOMPARE(renderSettings.activeFrameGraph()->id(), cloneData.activeFrameGraphId); QCOMPARE(renderSettings.id(), creationChangeData->subjectId()); @@ -410,6 +412,41 @@ private Q_SLOTS: } + void checkWorldSpaceToleranceUpdate() + { + // GIVEN + TestArbiter arbiter; + Qt3DRender::QRenderSettings renderSettings; + Qt3DRender::QPickingSettings *pickingSettings = renderSettings.pickingSettings(); + + arbiter.setArbiterOnNode(&renderSettings); + + { + // WHEN + pickingSettings->setWorldSpaceTolerance(5.f); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "pickWorldSpaceTolerance"); + QCOMPARE(change->value().toFloat(), pickingSettings->worldSpaceTolerance()); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + } + + { + // WHEN + pickingSettings->setWorldSpaceTolerance(5.f); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + } + + } + }; QTEST_MAIN(tst_QRenderSettings) diff --git a/tests/auto/render/qshaderprogrambuilder/qshaderprogrambuilder.pro b/tests/auto/render/qshaderprogrambuilder/qshaderprogrambuilder.pro new file mode 100644 index 000000000..32fe88e9f --- /dev/null +++ b/tests/auto/render/qshaderprogrambuilder/qshaderprogrambuilder.pro @@ -0,0 +1,12 @@ +TEMPLATE = app + +TARGET = tst_qshaderprogrambuilder + +QT += 3dcore 3dcore-private 3drender 3drender-private testlib + +CONFIG += testcase + +SOURCES += tst_qshaderprogrambuilder.cpp + +include(../../core/common/common.pri) +include(../commons/commons.pri) diff --git a/tests/auto/render/qshaderprogrambuilder/tst_qshaderprogrambuilder.cpp b/tests/auto/render/qshaderprogrambuilder/tst_qshaderprogrambuilder.cpp new file mode 100644 index 000000000..93bee22cc --- /dev/null +++ b/tests/auto/render/qshaderprogrambuilder/tst_qshaderprogrambuilder.cpp @@ -0,0 +1,601 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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$ +** +****************************************************************************/ + + +#include <QtTest/QTest> +#include <Qt3DRender/qshaderprogram.h> +#include <Qt3DRender/qshaderprogrambuilder.h> +#include <Qt3DRender/private/qshaderprogrambuilder_p.h> +#include <QObject> +#include <QSignalSpy> +#include <Qt3DCore/qpropertyupdatedchange.h> +#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h> +#include <Qt3DCore/qnodecreatedchange.h> +#include "testpostmanarbiter.h" + +class tst_QShaderProgramBuilder : public QObject +{ + Q_OBJECT +public: + tst_QShaderProgramBuilder() + : QObject() + { + qRegisterMetaType<Qt3DRender::QShaderProgram*>("Qt3DRender::QShaderProgram*"); + } + +private Q_SLOTS: + void checkDefaultConstruction() + { + // GIVEN + Qt3DRender::QShaderProgramBuilder builder; + + // THEN + QVERIFY(!builder.shaderProgram()); + QVERIFY(builder.enabledLayers().isEmpty()); + QCOMPARE(builder.vertexShaderGraph(), QUrl()); + QCOMPARE(builder.tessellationControlShaderGraph(), QUrl()); + QCOMPARE(builder.tessellationEvaluationShaderGraph(), QUrl()); + QCOMPARE(builder.geometryShaderGraph(), QUrl()); + QCOMPARE(builder.fragmentShaderGraph(), QUrl()); + QCOMPARE(builder.computeShaderGraph(), QUrl()); + } + + void checkPropertyChanges() + { + // GIVEN + Qt3DRender::QShaderProgramBuilder builder; + + { + // WHEN + QSignalSpy spy(&builder, SIGNAL(shaderProgramChanged(Qt3DRender::QShaderProgram*))); + auto newValue = new Qt3DRender::QShaderProgram(&builder); + builder.setShaderProgram(newValue); + + // THEN + QVERIFY(spy.isValid()); + QCOMPARE(builder.shaderProgram(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + builder.setShaderProgram(newValue); + + // THEN + QCOMPARE(builder.shaderProgram(), newValue); + QCOMPARE(spy.count(), 0); + } + { + // WHEN + QSignalSpy spy(&builder, SIGNAL(enabledLayersChanged(QStringList))); + const auto newValue = QStringList() << "foo" << "bar"; + builder.setEnabledLayers(newValue); + + // THEN + QVERIFY(spy.isValid()); + QCOMPARE(builder.enabledLayers(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + builder.setEnabledLayers(newValue); + + // THEN + QCOMPARE(builder.enabledLayers(), newValue); + QCOMPARE(spy.count(), 0); + } + { + // WHEN + QSignalSpy spy(&builder, SIGNAL(vertexShaderGraphChanged(QUrl))); + const auto newValue = QUrl::fromEncoded("qrc:/vertex.json"); + builder.setVertexShaderGraph(newValue); + + // THEN + QVERIFY(spy.isValid()); + QCOMPARE(builder.vertexShaderGraph(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + builder.setVertexShaderGraph(newValue); + + // THEN + QCOMPARE(builder.vertexShaderGraph(), newValue); + QCOMPARE(spy.count(), 0); + } + { + // WHEN + QSignalSpy spy(&builder, SIGNAL(tessellationControlShaderGraphChanged(QUrl))); + const auto newValue = QUrl::fromEncoded("qrc:/tesscontrol.json"); + builder.setTessellationControlShaderGraph(newValue); + + // THEN + QVERIFY(spy.isValid()); + QCOMPARE(builder.tessellationControlShaderGraph(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + builder.setTessellationControlShaderGraph(newValue); + + // THEN + QCOMPARE(builder.tessellationControlShaderGraph(), newValue); + QCOMPARE(spy.count(), 0); + } + { + // WHEN + QSignalSpy spy(&builder, SIGNAL(tessellationEvaluationShaderGraphChanged(QUrl))); + const auto newValue = QUrl::fromEncoded("qrc:/tesseval.json"); + builder.setTessellationEvaluationShaderGraph(newValue); + + // THEN + QVERIFY(spy.isValid()); + QCOMPARE(builder.tessellationEvaluationShaderGraph(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + builder.setTessellationEvaluationShaderGraph(newValue); + + // THEN + QCOMPARE(builder.tessellationEvaluationShaderGraph(), newValue); + QCOMPARE(spy.count(), 0); + } + { + // WHEN + QSignalSpy spy(&builder, SIGNAL(geometryShaderGraphChanged(QUrl))); + const auto newValue = QUrl::fromEncoded("qrc:/geometry.json"); + builder.setGeometryShaderGraph(newValue); + + // THEN + QVERIFY(spy.isValid()); + QCOMPARE(builder.geometryShaderGraph(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + builder.setGeometryShaderGraph(newValue); + + // THEN + QCOMPARE(builder.geometryShaderGraph(), newValue); + QCOMPARE(spy.count(), 0); + } + { + // WHEN + QSignalSpy spy(&builder, SIGNAL(fragmentShaderGraphChanged(QUrl))); + const auto newValue = QUrl::fromEncoded("qrc:/fragment.json"); + builder.setFragmentShaderGraph(newValue); + + // THEN + QVERIFY(spy.isValid()); + QCOMPARE(builder.fragmentShaderGraph(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + builder.setFragmentShaderGraph(newValue); + + // THEN + QCOMPARE(builder.fragmentShaderGraph(), newValue); + QCOMPARE(spy.count(), 0); + } + { + // WHEN + QSignalSpy spy(&builder, SIGNAL(computeShaderGraphChanged(QUrl))); + const auto newValue = QUrl::fromEncoded("qrc:/compute.json"); + builder.setComputeShaderGraph(newValue); + + // THEN + QVERIFY(spy.isValid()); + QCOMPARE(builder.computeShaderGraph(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + builder.setComputeShaderGraph(newValue); + + // THEN + QCOMPARE(builder.computeShaderGraph(), newValue); + QCOMPARE(spy.count(), 0); + } + } + + void checkShaderProgramBookkeeping() + { + // GIVEN + QScopedPointer<Qt3DRender::QShaderProgramBuilder> builder(new Qt3DRender::QShaderProgramBuilder); + { + // WHEN + Qt3DRender::QShaderProgram program; + builder->setShaderProgram(&program); + + // THEN + QCOMPARE(program.parent(), builder.data()); + QCOMPARE(builder->shaderProgram(), &program); + } + // THEN (Should not crash and effect be unset) + QVERIFY(!builder->shaderProgram()); + + { + // WHEN + Qt3DRender::QShaderProgramBuilder someOtherBuilder; + QScopedPointer<Qt3DRender::QShaderProgram> program(new Qt3DRender::QShaderProgram(&someOtherBuilder)); + builder->setShaderProgram(program.data()); + + // THEN + QCOMPARE(program->parent(), &someOtherBuilder); + QCOMPARE(builder->shaderProgram(), program.data()); + + // WHEN + builder.reset(); + program.reset(); + + // THEN Should not crash when the effect is destroyed (tests for failed removal of destruction helper) + } + } + + void checkCreationData() + { + // GIVEN + Qt3DRender::QShaderProgramBuilder builder; + + builder.setShaderProgram(new Qt3DRender::QShaderProgram(&builder)); + builder.setEnabledLayers({"foo", "bar"}); + builder.setVertexShaderGraph(QUrl::fromEncoded("qrc:/vertex.json")); + builder.setTessellationControlShaderGraph(QUrl::fromEncoded("qrc:/tesscontrol.json")); + builder.setTessellationEvaluationShaderGraph(QUrl::fromEncoded("qrc:/tesseval.json")); + builder.setGeometryShaderGraph(QUrl::fromEncoded("qrc:/geometry.json")); + builder.setFragmentShaderGraph(QUrl::fromEncoded("qrc:/fragment.json")); + builder.setComputeShaderGraph(QUrl::fromEncoded("qrc:/compute.json")); + + // WHEN + QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges; + + { + Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&builder); + creationChanges = creationChangeGenerator.creationChanges(); + } + + // THEN + { + QCOMPARE(creationChanges.size(), 2); // second one is for the shader program child + + const auto creationChangeData = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DRender::QShaderProgramBuilderData>>(creationChanges.first()); + const Qt3DRender::QShaderProgramBuilderData cloneData = creationChangeData->data; + + QCOMPARE(builder.shaderProgram()->id(), cloneData.shaderProgramId); + QCOMPARE(builder.enabledLayers(), cloneData.enabledLayers); + QCOMPARE(builder.vertexShaderGraph(), cloneData.vertexShaderGraph); + QCOMPARE(builder.tessellationControlShaderGraph(), cloneData.tessellationControlShaderGraph); + QCOMPARE(builder.tessellationEvaluationShaderGraph(), cloneData.tessellationEvaluationShaderGraph); + QCOMPARE(builder.geometryShaderGraph(), cloneData.geometryShaderGraph); + QCOMPARE(builder.fragmentShaderGraph(), cloneData.fragmentShaderGraph); + QCOMPARE(builder.computeShaderGraph(), cloneData.computeShaderGraph); + QCOMPARE(builder.id(), creationChangeData->subjectId()); + QCOMPARE(builder.isEnabled(), true); + QCOMPARE(builder.isEnabled(), creationChangeData->isNodeEnabled()); + QCOMPARE(builder.metaObject(), creationChangeData->metaObject()); + } + + // WHEN + builder.setEnabled(false); + + { + Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&builder); + creationChanges = creationChangeGenerator.creationChanges(); + } + + // THEN + { + QCOMPARE(creationChanges.size(), 2); // second one is for the shader program child + + const auto creationChangeData = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DRender::QShaderProgramBuilderData>>(creationChanges.first()); + const Qt3DRender::QShaderProgramBuilderData cloneData = creationChangeData->data; + + QCOMPARE(builder.shaderProgram()->id(), cloneData.shaderProgramId); + QCOMPARE(builder.enabledLayers(), cloneData.enabledLayers); + QCOMPARE(builder.vertexShaderGraph(), cloneData.vertexShaderGraph); + QCOMPARE(builder.tessellationControlShaderGraph(), cloneData.tessellationControlShaderGraph); + QCOMPARE(builder.tessellationEvaluationShaderGraph(), cloneData.tessellationEvaluationShaderGraph); + QCOMPARE(builder.geometryShaderGraph(), cloneData.geometryShaderGraph); + QCOMPARE(builder.fragmentShaderGraph(), cloneData.fragmentShaderGraph); + QCOMPARE(builder.computeShaderGraph(), cloneData.computeShaderGraph); + QCOMPARE(builder.id(), creationChangeData->subjectId()); + QCOMPARE(builder.isEnabled(), false); + QCOMPARE(builder.isEnabled(), creationChangeData->isNodeEnabled()); + QCOMPARE(builder.metaObject(), creationChangeData->metaObject()); + } + } + + void checkShaderProgramUpdate() + { + // GIVEN + TestArbiter arbiter; + Qt3DRender::QShaderProgramBuilder builder; + arbiter.setArbiterOnNode(&builder); + auto program = new Qt3DRender::QShaderProgram(&builder); + + { + // WHEN + builder.setShaderProgram(program); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "shaderProgram"); + QCOMPARE(change->value().value<Qt3DCore::QNodeId>(), builder.shaderProgram()->id()); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + } + + { + // WHEN + builder.setShaderProgram(program); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + } + } + + void checkEnabledLayersUpdate() + { + // GIVEN + TestArbiter arbiter; + Qt3DRender::QShaderProgramBuilder builder; + arbiter.setArbiterOnNode(&builder); + const auto layers = QStringList() << "foo" << "bar"; + + { + // WHEN + builder.setEnabledLayers(layers); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "enabledLayers"); + QCOMPARE(change->value().toStringList(), layers); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + } + + { + // WHEN + builder.setEnabledLayers(layers); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + } + } + + void checkVertexShaderGraphUpdate() + { + // GIVEN + TestArbiter arbiter; + Qt3DRender::QShaderProgramBuilder builder; + arbiter.setArbiterOnNode(&builder); + + { + // WHEN + builder.setVertexShaderGraph(QUrl::fromEncoded("qrc:/vertex.json")); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "vertexShaderGraph"); + QCOMPARE(change->value().value<QUrl>(), builder.vertexShaderGraph()); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + } + + { + // WHEN + builder.setVertexShaderGraph(QUrl::fromEncoded("qrc:/vertex.json")); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + } + + } + + void checkTessellationControlShaderGraphUpdate() + { + // GIVEN + TestArbiter arbiter; + Qt3DRender::QShaderProgramBuilder builder; + arbiter.setArbiterOnNode(&builder); + + { + // WHEN + builder.setTessellationControlShaderGraph(QUrl::fromEncoded("qrc:/tesscontrol.json")); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "tessellationControlShaderGraph"); + QCOMPARE(change->value().value<QUrl>(), builder.tessellationControlShaderGraph()); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + } + + { + // WHEN + builder.setTessellationControlShaderGraph(QUrl::fromEncoded("qrc:/tesscontrol.json")); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + } + + } + + void checkTessellationEvaluationShaderGraphUpdate() + { + // GIVEN + TestArbiter arbiter; + Qt3DRender::QShaderProgramBuilder builder; + arbiter.setArbiterOnNode(&builder); + + { + // WHEN + builder.setTessellationEvaluationShaderGraph(QUrl::fromEncoded("qrc:/tesseval.json")); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "tessellationEvaluationShaderGraph"); + QCOMPARE(change->value().value<QUrl>(), builder.tessellationEvaluationShaderGraph()); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + } + + { + // WHEN + builder.setTessellationEvaluationShaderGraph(QUrl::fromEncoded("qrc:/tesseval.json")); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + } + + } + + void checkGeometryShaderGraphUpdate() + { + // GIVEN + TestArbiter arbiter; + Qt3DRender::QShaderProgramBuilder builder; + arbiter.setArbiterOnNode(&builder); + + { + // WHEN + builder.setGeometryShaderGraph(QUrl::fromEncoded("qrc:/geometry.json")); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "geometryShaderGraph"); + QCOMPARE(change->value().value<QUrl>(), builder.geometryShaderGraph()); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + } + + { + // WHEN + builder.setGeometryShaderGraph(QUrl::fromEncoded("qrc:/geometry.json")); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + } + + } + + void checkFragmentShaderGraphUpdate() + { + // GIVEN + TestArbiter arbiter; + Qt3DRender::QShaderProgramBuilder builder; + arbiter.setArbiterOnNode(&builder); + + { + // WHEN + builder.setFragmentShaderGraph(QUrl::fromEncoded("qrc:/fragment.json")); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "fragmentShaderGraph"); + QCOMPARE(change->value().value<QUrl>(), builder.fragmentShaderGraph()); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + } + + { + // WHEN + builder.setFragmentShaderGraph(QUrl::fromEncoded("qrc:/fragment.json")); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + } + + } + + void checkComputeShaderGraphUpdate() + { + // GIVEN + TestArbiter arbiter; + Qt3DRender::QShaderProgramBuilder builder; + arbiter.setArbiterOnNode(&builder); + + { + // WHEN + builder.setComputeShaderGraph(QUrl::fromEncoded("qrc:/compute.json")); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "computeShaderGraph"); + QCOMPARE(change->value().value<QUrl>(), builder.computeShaderGraph()); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + + arbiter.events.clear(); + } + + { + // WHEN + builder.setComputeShaderGraph(QUrl::fromEncoded("qrc:/compute.json")); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + } + + } +}; + +QTEST_MAIN(tst_QShaderProgramBuilder) + +#include "tst_qshaderprogrambuilder.moc" diff --git a/tests/auto/render/render.pro b/tests/auto/render/render.pro index 5a82ee835..32a7b35fc 100644 --- a/tests/auto/render/render.pro +++ b/tests/auto/render/render.pro @@ -7,13 +7,13 @@ qtConfig(private_tests) { renderpass \ qgraphicsutils \ shader \ + shaderbuilder \ texture \ renderviewutils \ renderviews \ material \ vsyncframeadvanceservice \ meshfunctors \ - qmaterial \ qattribute \ qbuffer \ qgeometry \ @@ -23,7 +23,6 @@ qtConfig(private_tests) { buffer \ attribute \ geometry \ - geometryloaders \ geometryrenderer \ raycasting \ qcameraselector \ @@ -44,11 +43,8 @@ qtConfig(private_tests) { framegraphnode \ qobjectpicker \ objectpicker \ - picking \ # qboundingvolumedebug \ # boundingvolumedebug \ - boundingsphere \ - qdefaultmeshes \ trianglesextractor \ triangleboundingvolume \ ddstextures \ @@ -70,8 +66,6 @@ qtConfig(private_tests) { graphicshelpergl3_3 \ graphicshelpergl3_2 \ graphicshelpergl2 \ - gltfplugins \ - pickboundingvolumejob \ sendrendercapturejob \ textures \ qparameter \ @@ -81,8 +75,6 @@ qtConfig(private_tests) { qabstracttexture \ qabstracttextureimage \ qrendersettings \ - updatemeshtrianglelistjob \ - updateshaderdatatransformjob \ texturedatamanager \ rendertarget \ transform \ @@ -101,14 +93,43 @@ qtConfig(private_tests) { renderviewbuilder \ filtercompatibletechniquejob \ rendercapture \ + segmentvisitor \ trianglevisitor \ qmemorybarrier \ memorybarrier \ qshaderprogram \ - qscene2d \ - scene2d \ + qshaderprogrambuilder \ coordinatereader \ - framegraphvisitor + framegraphvisitor \ + renderer \ + armature \ + skeleton \ + joint \ + qproximityfilter \ + proximityfilter \ + proximityfiltering \ + qblitframebuffer \ + blitframebuffer + + QT_FOR_CONFIG = 3dcore-private + qtConfig(qt3d-extras) { + SUBDIRS += \ + qmaterial \ + geometryloaders \ + picking \ + boundingsphere \ + qdefaultmeshes \ + pickboundingvolumejob \ + gltfplugins \ + updatemeshtrianglelistjob \ + updateshaderdatatransformjob + } + + qtConfig(qt3d-input) { + SUBDIRS += \ + qscene2d \ + scene2d + } !macos: SUBDIRS += graphicshelpergl4 } diff --git a/tests/auto/render/rendercapture/tst_rendercapture.cpp b/tests/auto/render/rendercapture/tst_rendercapture.cpp index 4029ba136..799a7ccff 100644 --- a/tests/auto/render/rendercapture/tst_rendercapture.cpp +++ b/tests/auto/render/rendercapture/tst_rendercapture.cpp @@ -90,7 +90,7 @@ private Q_SLOTS: QCOMPARE(renderCapture.wasCaptureRequested(), true); } - void checkAcknowledgeCaptureRequest() + void checkTakeCaptureRequest() { // GIVEN Qt3DRender::Render::RenderCapture renderCapture; @@ -99,22 +99,26 @@ private Q_SLOTS: renderCapture.setEnabled(true); // WHEN - renderCapture.requestCapture(2); - renderCapture.requestCapture(4); + renderCapture.requestCapture({ 2, QRect(10, 10, 20, 20) }); + renderCapture.requestCapture({ 4, QRect(15, 15, 30, 30) }); // THEN QCOMPARE(renderCapture.wasCaptureRequested(), true); // WHEN - renderCapture.acknowledgeCaptureRequest(); + Qt3DRender::QRenderCaptureRequest r1 = renderCapture.takeCaptureRequest(); // THEN + QCOMPARE(r1.captureId, 2); + QCOMPARE(r1.rect, QRect(10, 10, 20, 20)); QCOMPARE(renderCapture.wasCaptureRequested(), true); // WHEN - renderCapture.acknowledgeCaptureRequest(); + Qt3DRender::QRenderCaptureRequest r2 = renderCapture.takeCaptureRequest(); // THEN + QCOMPARE(r2.captureId, 4); + QCOMPARE(r2.rect, QRect(15, 15, 30, 30)); QCOMPARE(renderCapture.wasCaptureRequested(), false); } }; diff --git a/tests/auto/render/renderer/renderer.pro b/tests/auto/render/renderer/renderer.pro new file mode 100644 index 000000000..cbafc156b --- /dev/null +++ b/tests/auto/render/renderer/renderer.pro @@ -0,0 +1,9 @@ +TEMPLATE = app + +TARGET = tst_renderer + +QT += 3dcore 3dcore-private 3drender 3drender-private testlib + +CONFIG += testcase + +SOURCES += tst_renderer.cpp diff --git a/tests/auto/render/renderer/tst_renderer.cpp b/tests/auto/render/renderer/tst_renderer.cpp new file mode 100644 index 000000000..85d978926 --- /dev/null +++ b/tests/auto/render/renderer/tst_renderer.cpp @@ -0,0 +1,234 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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$ +** +****************************************************************************/ + +#include <QtTest/QtTest> +#include <QMutex> +#include <QWaitCondition> +#include <QThread> +#include <Qt3DRender/private/renderer_p.h> +#include <Qt3DRender/private/viewportnode_p.h> +#include <Qt3DRender/private/renderview_p.h> +#include <Qt3DRender/private/renderviewbuilder_p.h> + +class tst_Renderer : public QObject +{ + Q_OBJECT +public : + tst_Renderer() {} + ~tst_Renderer() {} + +private Q_SLOTS: + void checkRenderBinJobs() + { + // GIVEN + Qt3DRender::Render::NodeManagers nodeManagers; + Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); + Qt3DRender::Render::RenderSettings settings; + // owned by FG manager + Qt3DRender::Render::ViewportNode *fgRoot = new Qt3DRender::Render::ViewportNode(); + const Qt3DCore::QNodeId fgRootId = Qt3DCore::QNodeId::createId(); + + nodeManagers.frameGraphManager()->appendNode(fgRootId, fgRoot); + settings.setActiveFrameGraphId(fgRootId); + + renderer.setNodeManagers(&nodeManagers); + renderer.setSettings(&settings); + renderer.initialize(); + + const int singleRenderViewJobCount = 11 + 2 * Qt3DRender::Render::RenderViewBuilder::optimalJobCount(); + // RenderViewBuilder renderViewJob, + // renderableEntityFilterJob, + // lightGatherJob, + // computableEntityFilterJob, + // syncRenderViewInitializationJob, + // syncFrustumCullingJob, + // filterEntityByLayerJob, + // filterProximityJob, + // setClearDrawBufferIndexJob, + // frustumCullingJob, + // syncRenderCommandBuldingJob, + // syncRenderViewCommandBuilderJob) + // n * (RenderViewCommandBuildJobs + MaterialGathererJobs + + // WHEN (nothing dirty, no buffers) + QVector<Qt3DCore::QAspectJobPtr> jobs = renderer.renderBinJobs(); + + // THEN (level + QCOMPARE(jobs.size(), + 1 + // updateLevelOfDetailJob + 1 + // cleanupJob + 1 + // sendRenderCaptureJob + 1 + // sendBufferCaptureJob + 1 + // filterCompatibleTechniquesJob + 1 + // VAOGatherer + 1 + // updateSkinningPaletteJob + singleRenderViewJobCount); // Only valid for the first call to renderBinJobs(), since subsequent calls won't have the renderqueue reset + + + // WHEN + renderer.markDirty(Qt3DRender::Render::AbstractRenderer::EntityEnabledDirty, nullptr); + jobs = renderer.renderBinJobs(); + + // THEN (level + QCOMPARE(jobs.size(), + 1 + // updateLevelOfDetailJob + 1 + // cleanupJob + 1 + // sendRenderCaptureJob + 1 + // sendBufferCaptureJob + 1 + // filterCompatibleTechniquesJob + 1 + // VAOGatherer + 1 + // updateSkinningPaletteJob + 1); // EntityEnabledDirty + + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + + // WHEN + renderer.markDirty(Qt3DRender::Render::AbstractRenderer::TransformDirty, nullptr); + jobs = renderer.renderBinJobs(); + + // THEN (level + QCOMPARE(jobs.size(), + 1 + // updateLevelOfDetailJob + 1 + // cleanupJob + 1 + // sendRenderCaptureJob + 1 + // sendBufferCaptureJob + 1 + // filterCompatibleTechniquesJob + 1 + // VAOGatherer + 1 + // WorldTransformJob + 1 + // UpdateWorldBoundingVolume + 1 + // UpdateShaderDataTransform + 1 + // updateSkinningPaletteJob + 1); // ExpandBoundingVolumeJob + + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + + // WHEN + renderer.markDirty(Qt3DRender::Render::AbstractRenderer::GeometryDirty, nullptr); + jobs = renderer.renderBinJobs(); + + // THEN (level + QCOMPARE(jobs.size(), + 1 + // updateLevelOfDetailJob + 1 + // cleanupJob + 1 + // sendRenderCaptureJob + 1 + // sendBufferCaptureJob + 1 + // filterCompatibleTechniquesJob + 1 + // VAOGatherer + 1 + // CalculateBoundingVolumeJob + 1 + // UpdateMeshTriangleListJob + 1 + // updateSkinningPaletteJob + 1); // ExpandBoundingVolumeJob + + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + + // WHEN + renderer.markDirty(Qt3DRender::Render::AbstractRenderer::BuffersDirty, nullptr); + jobs = renderer.renderBinJobs(); + + // THEN (level + QCOMPARE(jobs.size(), + 1 + // updateLevelOfDetailJob + 1 + // cleanupJob + 1 + // sendRenderCaptureJob + 1 + // sendBufferCaptureJob + 1 + // filterCompatibleTechniquesJob + 1 + // VAOGatherer + 1 + // updateSkinningPaletteJob + 1); // BufferGathererJob + + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + + // WHEN + renderer.markDirty(Qt3DRender::Render::AbstractRenderer::ShadersDirty, nullptr); + jobs = renderer.renderBinJobs(); + + // THEN (level + QCOMPARE(jobs.size(), + 1 + // updateLevelOfDetailJob + 1 + // cleanupJob + 1 + // sendRenderCaptureJob + 1 + // sendBufferCaptureJob + 1 + // filterCompatibleTechniquesJob + 1 + // VAOGatherer + 1 + // updateSkinningPaletteJob + 1); // ShaderGathererJob + + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + + // WHEN + renderer.markDirty(Qt3DRender::Render::AbstractRenderer::TexturesDirty, nullptr); + jobs = renderer.renderBinJobs(); + + // THEN (level + QCOMPARE(jobs.size(), + 1 + // updateLevelOfDetailJob + 1 + // cleanupJob + 1 + // sendRenderCaptureJob + 1 + // sendBufferCaptureJob + 1 + // filterCompatibleTechniquesJob + 1 + // VAOGatherer + 1 + // TexturesGathererJob + 1 + // updateSkinningPaletteJob + 1); // SyncTexturesGathererJob + + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + + // WHEN + renderer.markDirty(Qt3DRender::Render::AbstractRenderer::AllDirty, nullptr); + jobs = renderer.renderBinJobs(); + + // THEN (level + QCOMPARE(jobs.size(), + 1 + // updateLevelOfDetailJob + 1 + // cleanupJob + 1 + // sendRenderCaptureJob + 1 + // sendBufferCaptureJob + 1 + // filterCompatibleTechniquesJob + 1 + // VAOGatherer + 1 + // EntityEnabledDirty + 1 + // WorldTransformJob + 1 + // UpdateWorldBoundingVolume + 1 + // UpdateShaderDataTransform + 1 + // ExpandBoundingVolumeJob + 1 + // CalculateBoundingVolumeJob + 1 + // UpdateMeshTriangleListJob + 1 + // BufferGathererJob + 1 + // ShaderGathererJob + 1 + // TexturesGathererJob + 1 + // updateSkinningPaletteJob + 1); // SyncTexturesGathererJob + + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + + + } +}; + +QTEST_MAIN(tst_Renderer) + +#include "tst_renderer.moc" diff --git a/tests/auto/render/renderviewbuilder/tst_renderviewbuilder.cpp b/tests/auto/render/renderviewbuilder/tst_renderviewbuilder.cpp index 1ab687b34..23861f3a9 100644 --- a/tests/auto/render/renderviewbuilder/tst_renderviewbuilder.cpp +++ b/tests/auto/render/renderviewbuilder/tst_renderviewbuilder.cpp @@ -179,27 +179,60 @@ private Q_SLOTS: Qt3DRender::Render::FrameGraphNode *leafNode = testAspect.nodeManagers()->frameGraphManager()->lookupNode(clearBuffer->id()); QVERIFY(leafNode != nullptr); - // WHEN - Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); + { + // WHEN + Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); + + // THEN + QCOMPARE(renderViewBuilder.renderViewIndex(), 0); + QCOMPARE(renderViewBuilder.renderer(), testAspect.renderer()); + QCOMPARE(renderViewBuilder.layerCacheNeedsToBeRebuilt(), false); + QVERIFY(!renderViewBuilder.renderViewJob().isNull()); + QVERIFY(!renderViewBuilder.lightGathererJob().isNull()); + QVERIFY(!renderViewBuilder.renderableEntityFilterJob().isNull()); + QVERIFY(!renderViewBuilder.computableEntityFilterJob().isNull()); + QVERIFY(!renderViewBuilder.frustumCullingJob().isNull()); + QVERIFY(!renderViewBuilder.syncFrustumCullingJob().isNull()); + QVERIFY(!renderViewBuilder.setClearDrawBufferIndexJob().isNull()); + + QVERIFY(renderViewBuilder.filterEntityByLayerJob().isNull()); + QVERIFY(renderViewBuilder.syncFilterEntityByLayerJob().isNull()); + QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob().isNull()); + QVERIFY(renderViewBuilder.syncRenderViewCommandBuildersJob().isNull()); + QVERIFY(renderViewBuilder.syncRenderViewInitializationJob().isNull()); + + QCOMPARE(renderViewBuilder.renderViewBuilderJobs().size(), 0); + QCOMPARE(renderViewBuilder.materialGathererJobs().size(), 0); + + // WHEN + renderViewBuilder.prepareJobs(); + + // THEN + QVERIFY(!renderViewBuilder.syncRenderCommandBuildingJob().isNull()); + QVERIFY(!renderViewBuilder.syncRenderViewCommandBuildersJob().isNull()); + QVERIFY(!renderViewBuilder.syncRenderViewInitializationJob().isNull()); + QVERIFY(renderViewBuilder.filterEntityByLayerJob().isNull()); + QVERIFY(renderViewBuilder.syncFilterEntityByLayerJob().isNull()); + + QCOMPARE(renderViewBuilder.renderViewBuilderJobs().size(), Qt3DRender::Render::RenderViewBuilder::optimalJobCount()); + QCOMPARE(renderViewBuilder.materialGathererJobs().size(), Qt3DRender::Render::RenderViewBuilder::optimalJobCount()); + QCOMPARE(renderViewBuilder.buildJobHierachy().size(), 11 + 2 * Qt3DRender::Render::RenderViewBuilder::optimalJobCount()); + } - // THEN - QCOMPARE(renderViewBuilder.renderViewIndex(), 0); - QCOMPARE(renderViewBuilder.renderer(), testAspect.renderer()); - QVERIFY(!renderViewBuilder.renderViewJob().isNull()); - QVERIFY(!renderViewBuilder.filterEntityByLayerJob().isNull()); - QVERIFY(!renderViewBuilder.lightGathererJob().isNull()); - QVERIFY(!renderViewBuilder.renderableEntityFilterJob().isNull()); - QVERIFY(!renderViewBuilder.computableEntityFilterJob().isNull()); - QVERIFY(!renderViewBuilder.frustumCullingJob().isNull()); - QVERIFY(!renderViewBuilder.syncRenderViewInitializationJob().isNull()); - QVERIFY(!renderViewBuilder.syncFrustumCullingJob().isNull()); - QVERIFY(!renderViewBuilder.syncRenderCommandBuildingJob().isNull()); - QVERIFY(!renderViewBuilder.syncRenderViewCommandBuildersJob().isNull()); - QVERIFY(!renderViewBuilder.setClearDrawBufferIndexJob().isNull()); - QCOMPARE(renderViewBuilder.renderViewBuilderJobs().size(), Qt3DRender::Render::RenderViewBuilder::optimalJobCount()); - QCOMPARE(renderViewBuilder.materialGathererJobs().size(), Qt3DRender::Render::RenderViewBuilder::optimalJobCount()); - - QCOMPARE(renderViewBuilder.buildJobHierachy().size(), 11 + 2 * Qt3DRender::Render::RenderViewBuilder::optimalJobCount()); + { + // WHEN + Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); + renderViewBuilder.setLayerCacheNeedsToBeRebuilt(true); + renderViewBuilder.prepareJobs(); + + // THEN + QCOMPARE(renderViewBuilder.layerCacheNeedsToBeRebuilt(), true); + QVERIFY(!renderViewBuilder.filterEntityByLayerJob().isNull()); + QVERIFY(!renderViewBuilder.syncFilterEntityByLayerJob().isNull()); + + // mark jobs dirty and recheck + QCOMPARE(renderViewBuilder.buildJobHierachy().size(), 13 + 2 * Qt3DRender::Render::RenderViewBuilder::optimalJobCount()); + } } void checkCheckJobDependencies() @@ -213,66 +246,145 @@ private Q_SLOTS: Qt3DRender::Render::FrameGraphNode *leafNode = testAspect.nodeManagers()->frameGraphManager()->lookupNode(clearBuffer->id()); QVERIFY(leafNode != nullptr); - // WHEN - Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); - renderViewBuilder.buildJobHierachy(); - - // THEN - // Step 1 - QCOMPARE(renderViewBuilder.renderViewJob()->dependencies().size(), 0); - QCOMPARE(renderViewBuilder.lightGathererJob()->dependencies().size(), 0); - QCOMPARE(renderViewBuilder.renderableEntityFilterJob()->dependencies().size(),0); - QCOMPARE(renderViewBuilder.computableEntityFilterJob()->dependencies().size(), 0); - - // Step 2 - QCOMPARE(renderViewBuilder.syncRenderViewInitializationJob()->dependencies().size(), 1); - QCOMPARE(renderViewBuilder.syncRenderViewInitializationJob()->dependencies().first().data(), renderViewBuilder.renderViewJob().data()); - - // Step 3 - QCOMPARE(renderViewBuilder.filterEntityByLayerJob()->dependencies().size(), 2); - QVERIFY(renderViewBuilder.filterEntityByLayerJob()->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob())); - QVERIFY(renderViewBuilder.filterEntityByLayerJob()->dependencies().contains(testAspect.renderer()->updateTreeEnabledJob())); - - QCOMPARE(renderViewBuilder.setClearDrawBufferIndexJob()->dependencies().size(), 1); - QCOMPARE(renderViewBuilder.setClearDrawBufferIndexJob()->dependencies().first().data(), renderViewBuilder.syncRenderViewInitializationJob().data()); - - QCOMPARE(renderViewBuilder.syncFrustumCullingJob()->dependencies().size(), 3); - QVERIFY(renderViewBuilder.syncFrustumCullingJob()->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob())); - QVERIFY(renderViewBuilder.syncFrustumCullingJob()->dependencies().contains(testAspect.renderer()->updateWorldTransformJob())); - QVERIFY(renderViewBuilder.syncFrustumCullingJob()->dependencies().contains(testAspect.renderer()->updateShaderDataTransformJob())); - - for (const auto materialGatherer : renderViewBuilder.materialGathererJobs()) { - QCOMPARE(materialGatherer->dependencies().size(), 2); - QVERIFY(materialGatherer->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob())); - QVERIFY(materialGatherer->dependencies().contains(testAspect.renderer()->filterCompatibleTechniqueJob())); - } - - // Step 4 - QCOMPARE(renderViewBuilder.frustumCullingJob()->dependencies().size(), 2); - QVERIFY(renderViewBuilder.frustumCullingJob()->dependencies().contains(renderViewBuilder.syncFrustumCullingJob())); - QVERIFY(renderViewBuilder.frustumCullingJob()->dependencies().contains(testAspect.renderer()->expandBoundingVolumeJob())); - - QCOMPARE(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().size(), renderViewBuilder.materialGathererJobs().size() + 6); - QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob())); - QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.renderableEntityFilterJob())); - QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.computableEntityFilterJob())); - QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.filterEntityByLayerJob())); - QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.lightGathererJob())); - QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.frustumCullingJob())); - for (const auto materialGatherer : renderViewBuilder.materialGathererJobs()) { - QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(materialGatherer)); + { + // WHEN + Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); + renderViewBuilder.prepareJobs(); + renderViewBuilder.buildJobHierachy(); + + // THEN + // Step 1 + QCOMPARE(renderViewBuilder.renderViewJob()->dependencies().size(), 1); // Depends upon skinning palette update + QCOMPARE(renderViewBuilder.lightGathererJob()->dependencies().size(), 0); + QCOMPARE(renderViewBuilder.renderableEntityFilterJob()->dependencies().size(),0); + QCOMPARE(renderViewBuilder.computableEntityFilterJob()->dependencies().size(), 0); + + // Step 2 + QCOMPARE(renderViewBuilder.syncRenderViewInitializationJob()->dependencies().size(), 1); + QCOMPARE(renderViewBuilder.syncRenderViewInitializationJob()->dependencies().first().data(), renderViewBuilder.renderViewJob().data()); + + // Step 3 + QVERIFY(renderViewBuilder.filterEntityByLayerJob().isNull()); + QVERIFY(renderViewBuilder.syncFilterEntityByLayerJob().isNull()); + + QCOMPARE(renderViewBuilder.filterProximityJob()->dependencies().size(), 2); + QVERIFY(renderViewBuilder.filterProximityJob()->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob())); + QVERIFY(renderViewBuilder.filterProximityJob()->dependencies().contains(testAspect.renderer()->expandBoundingVolumeJob())); + + QCOMPARE(renderViewBuilder.setClearDrawBufferIndexJob()->dependencies().size(), 1); + QCOMPARE(renderViewBuilder.setClearDrawBufferIndexJob()->dependencies().first().data(), renderViewBuilder.syncRenderViewInitializationJob().data()); + + QCOMPARE(renderViewBuilder.syncFrustumCullingJob()->dependencies().size(), 3); + QVERIFY(renderViewBuilder.syncFrustumCullingJob()->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob())); + QVERIFY(renderViewBuilder.syncFrustumCullingJob()->dependencies().contains(testAspect.renderer()->updateWorldTransformJob())); + QVERIFY(renderViewBuilder.syncFrustumCullingJob()->dependencies().contains(testAspect.renderer()->updateShaderDataTransformJob())); + + for (const auto materialGatherer : renderViewBuilder.materialGathererJobs()) { + QCOMPARE(materialGatherer->dependencies().size(), 2); + QVERIFY(materialGatherer->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob())); + QVERIFY(materialGatherer->dependencies().contains(testAspect.renderer()->filterCompatibleTechniqueJob())); + } + + // Step 4 + QCOMPARE(renderViewBuilder.frustumCullingJob()->dependencies().size(), 2); + QVERIFY(renderViewBuilder.frustumCullingJob()->dependencies().contains(renderViewBuilder.syncFrustumCullingJob())); + QVERIFY(renderViewBuilder.frustumCullingJob()->dependencies().contains(testAspect.renderer()->expandBoundingVolumeJob())); + + QCOMPARE(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().size(), renderViewBuilder.materialGathererJobs().size() + 6); + QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob())); + QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.renderableEntityFilterJob())); + QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.computableEntityFilterJob())); + QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.filterProximityJob())); + QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.lightGathererJob())); + QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.frustumCullingJob())); + for (const auto materialGatherer : renderViewBuilder.materialGathererJobs()) { + QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(materialGatherer)); + } + + // Step 5 + for (const auto renderViewBuilderJob : renderViewBuilder.renderViewBuilderJobs()) { + QCOMPARE(renderViewBuilderJob->dependencies().size(), 1); + QCOMPARE(renderViewBuilderJob->dependencies().first().data(), renderViewBuilder.syncRenderCommandBuildingJob().data()); + } + + // Step 6 + QCOMPARE(renderViewBuilder.syncRenderViewCommandBuildersJob()->dependencies().size(), renderViewBuilder.renderViewBuilderJobs().size()); + for (const auto renderViewBuilderJob : renderViewBuilder.renderViewBuilderJobs()) { + QVERIFY(renderViewBuilder.syncRenderViewCommandBuildersJob()->dependencies().contains(renderViewBuilderJob)); + } } - - // Step 5 - for (const auto renderViewBuilderJob : renderViewBuilder.renderViewBuilderJobs()) { - QCOMPARE(renderViewBuilderJob->dependencies().size(), 1); - QCOMPARE(renderViewBuilderJob->dependencies().first().data(), renderViewBuilder.syncRenderCommandBuildingJob().data()); - } - - // Step 6 - QCOMPARE(renderViewBuilder.syncRenderViewCommandBuildersJob()->dependencies().size(), renderViewBuilder.renderViewBuilderJobs().size()); - for (const auto renderViewBuilderJob : renderViewBuilder.renderViewBuilderJobs()) { - QVERIFY(renderViewBuilder.syncRenderViewCommandBuildersJob()->dependencies().contains(renderViewBuilderJob)); + { + // WHEN + Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); + renderViewBuilder.setLayerCacheNeedsToBeRebuilt(true); + renderViewBuilder.prepareJobs(); + renderViewBuilder.buildJobHierachy(); + + // THEN + // Step 1 + QCOMPARE(renderViewBuilder.renderViewJob()->dependencies().size(), 1); // Depends upon skinning palette update + QCOMPARE(renderViewBuilder.lightGathererJob()->dependencies().size(), 0); + QCOMPARE(renderViewBuilder.renderableEntityFilterJob()->dependencies().size(),0); + QCOMPARE(renderViewBuilder.computableEntityFilterJob()->dependencies().size(), 0); + + // Step 2 + QCOMPARE(renderViewBuilder.syncRenderViewInitializationJob()->dependencies().size(), 1); + QCOMPARE(renderViewBuilder.syncRenderViewInitializationJob()->dependencies().first().data(), renderViewBuilder.renderViewJob().data()); + + // Step 3 + QCOMPARE(renderViewBuilder.filterEntityByLayerJob()->dependencies().size(), 2); + QVERIFY(renderViewBuilder.filterEntityByLayerJob()->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob())); + QVERIFY(renderViewBuilder.filterEntityByLayerJob()->dependencies().contains(testAspect.renderer()->updateTreeEnabledJob())); + + QCOMPARE(renderViewBuilder.syncFilterEntityByLayerJob()->dependencies().size(), 1); + QVERIFY(renderViewBuilder.syncFilterEntityByLayerJob()->dependencies().contains(renderViewBuilder.filterEntityByLayerJob())); + + QCOMPARE(renderViewBuilder.filterProximityJob()->dependencies().size(), 2); + QVERIFY(renderViewBuilder.filterProximityJob()->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob())); + QVERIFY(renderViewBuilder.filterProximityJob()->dependencies().contains(testAspect.renderer()->expandBoundingVolumeJob())); + + QCOMPARE(renderViewBuilder.setClearDrawBufferIndexJob()->dependencies().size(), 1); + QCOMPARE(renderViewBuilder.setClearDrawBufferIndexJob()->dependencies().first().data(), renderViewBuilder.syncRenderViewInitializationJob().data()); + + QCOMPARE(renderViewBuilder.syncFrustumCullingJob()->dependencies().size(), 3); + QVERIFY(renderViewBuilder.syncFrustumCullingJob()->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob())); + QVERIFY(renderViewBuilder.syncFrustumCullingJob()->dependencies().contains(testAspect.renderer()->updateWorldTransformJob())); + QVERIFY(renderViewBuilder.syncFrustumCullingJob()->dependencies().contains(testAspect.renderer()->updateShaderDataTransformJob())); + + for (const auto materialGatherer : renderViewBuilder.materialGathererJobs()) { + QCOMPARE(materialGatherer->dependencies().size(), 2); + QVERIFY(materialGatherer->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob())); + QVERIFY(materialGatherer->dependencies().contains(testAspect.renderer()->filterCompatibleTechniqueJob())); + } + + // Step 4 + QCOMPARE(renderViewBuilder.frustumCullingJob()->dependencies().size(), 2); + QVERIFY(renderViewBuilder.frustumCullingJob()->dependencies().contains(renderViewBuilder.syncFrustumCullingJob())); + QVERIFY(renderViewBuilder.frustumCullingJob()->dependencies().contains(testAspect.renderer()->expandBoundingVolumeJob())); + + QCOMPARE(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().size(), renderViewBuilder.materialGathererJobs().size() + 7); + QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob())); + QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.renderableEntityFilterJob())); + QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.computableEntityFilterJob())); + QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.syncFilterEntityByLayerJob())); + QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.lightGathererJob())); + QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.frustumCullingJob())); + QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.filterProximityJob())); + for (const auto materialGatherer : renderViewBuilder.materialGathererJobs()) { + QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(materialGatherer)); + } + + // Step 5 + for (const auto renderViewBuilderJob : renderViewBuilder.renderViewBuilderJobs()) { + QCOMPARE(renderViewBuilderJob->dependencies().size(), 1); + QCOMPARE(renderViewBuilderJob->dependencies().first().data(), renderViewBuilder.syncRenderCommandBuildingJob().data()); + } + + // Step 6 + QCOMPARE(renderViewBuilder.syncRenderViewCommandBuildersJob()->dependencies().size(), renderViewBuilder.renderViewBuilderJobs().size()); + for (const auto renderViewBuilderJob : renderViewBuilder.renderViewBuilderJobs()) { + QVERIFY(renderViewBuilder.syncRenderViewCommandBuildersJob()->dependencies().contains(renderViewBuilderJob)); + } } } @@ -289,6 +401,7 @@ private Q_SLOTS: // WHEN Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); + renderViewBuilder.prepareJobs(); renderViewBuilder.buildJobHierachy(); renderViewBuilder.renderViewJob()->run(); @@ -309,6 +422,7 @@ private Q_SLOTS: // WHEN Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); + renderViewBuilder.prepareJobs(); renderViewBuilder.buildJobHierachy(); renderViewBuilder.renderableEntityFilterJob()->run(); @@ -329,6 +443,7 @@ private Q_SLOTS: // WHEN Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); + renderViewBuilder.prepareJobs(); renderViewBuilder.buildJobHierachy(); renderViewBuilder.computableEntityFilterJob()->run(); @@ -354,30 +469,58 @@ private Q_SLOTS: Qt3DRender::Render::FrameGraphNode *leafNode = testAspect.nodeManagers()->frameGraphManager()->lookupNode(renderPassFilter->id()); QVERIFY(leafNode != nullptr); - // WHEN - Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); - renderViewBuilder.buildJobHierachy(); - - // THEN - QCOMPARE(renderViewBuilder.frustumCullingJob()->isActive(), false); - QCOMPARE(renderViewBuilder.filterEntityByLayerJob()->hasLayerFilter(), false); - QCOMPARE(renderViewBuilder.filterEntityByLayerJob()->layers().size(), 0); - for (const auto materialGatherer : renderViewBuilder.materialGathererJobs()) { - QVERIFY(materialGatherer->techniqueFilter() == nullptr); - QVERIFY(materialGatherer->renderPassFilter() == nullptr); + { + // WHEN + Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); + renderViewBuilder.prepareJobs(); + renderViewBuilder.buildJobHierachy(); + + // THEN + QCOMPARE(renderViewBuilder.frustumCullingJob()->isActive(), false); + for (const auto materialGatherer : renderViewBuilder.materialGathererJobs()) { + QVERIFY(materialGatherer->techniqueFilter() == nullptr); + QVERIFY(materialGatherer->renderPassFilter() == nullptr); + } + + // WHEN + renderViewBuilder.renderViewJob()->run(); + renderViewBuilder.syncRenderViewInitializationJob()->run(); + + // THEN + QCOMPARE(renderViewBuilder.frustumCullingJob()->isActive(), true); + for (const auto materialGatherer : renderViewBuilder.materialGathererJobs()) { + QVERIFY(materialGatherer->techniqueFilter() != nullptr); + QVERIFY(materialGatherer->renderPassFilter() != nullptr); + } } - - // WHEN - renderViewBuilder.renderViewJob()->run(); - renderViewBuilder.syncRenderViewInitializationJob()->run(); - - // THEN - QCOMPARE(renderViewBuilder.frustumCullingJob()->isActive(), true); - QCOMPARE(renderViewBuilder.filterEntityByLayerJob()->hasLayerFilter(), true); - QCOMPARE(renderViewBuilder.filterEntityByLayerJob()->layers().size(), 1); - for (const auto materialGatherer : renderViewBuilder.materialGathererJobs()) { - QVERIFY(materialGatherer->techniqueFilter() != nullptr); - QVERIFY(materialGatherer->renderPassFilter() != nullptr); + { + // WHEN + Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); + renderViewBuilder.setLayerCacheNeedsToBeRebuilt(true); + renderViewBuilder.prepareJobs(); + renderViewBuilder.buildJobHierachy(); + + // THEN + QCOMPARE(renderViewBuilder.frustumCullingJob()->isActive(), false); + QCOMPARE(renderViewBuilder.filterEntityByLayerJob()->hasLayerFilter(), false); + QCOMPARE(renderViewBuilder.filterEntityByLayerJob()->layerFilters().size(), 0); + for (const auto materialGatherer : renderViewBuilder.materialGathererJobs()) { + QVERIFY(materialGatherer->techniqueFilter() == nullptr); + QVERIFY(materialGatherer->renderPassFilter() == nullptr); + } + + // WHEN + renderViewBuilder.renderViewJob()->run(); + renderViewBuilder.syncRenderViewInitializationJob()->run(); + + // THEN + QCOMPARE(renderViewBuilder.frustumCullingJob()->isActive(), true); + QCOMPARE(renderViewBuilder.filterEntityByLayerJob()->hasLayerFilter(), true); + QCOMPARE(renderViewBuilder.filterEntityByLayerJob()->layerFilters().size(), 1); + for (const auto materialGatherer : renderViewBuilder.materialGathererJobs()) { + QVERIFY(materialGatherer->techniqueFilter() != nullptr); + QVERIFY(materialGatherer->renderPassFilter() != nullptr); + } } } @@ -399,6 +542,7 @@ private Q_SLOTS: // WHEN Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); + renderViewBuilder.prepareJobs(); renderViewBuilder.buildJobHierachy(); // THEN @@ -428,6 +572,8 @@ private Q_SLOTS: // WHEN Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); + renderViewBuilder.setLayerCacheNeedsToBeRebuilt(true); + renderViewBuilder.prepareJobs(); renderViewBuilder.buildJobHierachy(); renderViewBuilder.renderViewJob()->run(); diff --git a/tests/auto/render/sceneloader/tst_sceneloader.cpp b/tests/auto/render/sceneloader/tst_sceneloader.cpp index 18cfe0aeb..9aac50c73 100644 --- a/tests/auto/render/sceneloader/tst_sceneloader.cpp +++ b/tests/auto/render/sceneloader/tst_sceneloader.cpp @@ -79,7 +79,7 @@ private Q_SLOTS: { // GIVEN Qt3DRender::QSceneLoader frontendSceneLoader; - frontendSceneLoader.setSource(QUrl(QStringLiteral("CorvetteMuseum"))); + frontendSceneLoader.setSource(QUrl(QStringLiteral("file:///CorvetteMuseum"))); Qt3DRender::Render::Scene sceneLoader; Qt3DRender::Render::SceneManager sceneManager; @@ -109,7 +109,7 @@ private Q_SLOTS: // WHEN Qt3DCore::QPropertyUpdatedChangePtr updateChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId())); - const QUrl newUrl(QStringLiteral("Bownling_Green_KY")); + const QUrl newUrl(QStringLiteral("file:///Bownling_Green_KY")); updateChange->setValue(newUrl); updateChange->setPropertyName("source"); sceneLoader.sceneChangeEvent(updateChange); diff --git a/tests/auto/render/segmentvisitor/segmentvisitor.pro b/tests/auto/render/segmentvisitor/segmentvisitor.pro new file mode 100644 index 000000000..2f650aa0b --- /dev/null +++ b/tests/auto/render/segmentvisitor/segmentvisitor.pro @@ -0,0 +1,12 @@ +TEMPLATE = app + +TARGET = segmentvisitor + +QT += 3dcore 3dcore-private 3drender 3drender-private testlib + +CONFIG += testcase + +SOURCES += tst_segmentvisitor.cpp + +include(../../core/common/common.pri) +include(../commons/commons.pri) diff --git a/tests/auto/render/segmentvisitor/tst_segmentvisitor.cpp b/tests/auto/render/segmentvisitor/tst_segmentvisitor.cpp new file mode 100644 index 000000000..d56daf159 --- /dev/null +++ b/tests/auto/render/segmentvisitor/tst_segmentvisitor.cpp @@ -0,0 +1,814 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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$ +** +****************************************************************************/ + +#include <QtTest/QTest> +#include <qbackendnodetester.h> +#include <Qt3DRender/qgeometryrenderer.h> +#include <Qt3DRender/qbuffer.h> +#include <private/segmentsvisitor_p.h> +#include <private/nodemanagers_p.h> +#include <private/managers_p.h> +#include <private/geometryrenderer_p.h> +#include <private/geometryrenderermanager_p.h> +#include <private/buffermanager_p.h> +#include "testrenderer.h" + +using namespace Qt3DRender::Render; + +class TestVisitor : public SegmentsVisitor +{ +public: + TestVisitor(NodeManagers *manager) + : SegmentsVisitor(manager) + { + + } + + virtual void visit(uint andx, const QVector3D &a, uint bndx, const QVector3D &b) + { + m_segments.push_back(TestSegment(andx, a, bndx, b)); + } + + NodeManagers *nodeManagers() const + { + return m_manager; + } + + Qt3DCore::QNodeId nodeId() const + { + return m_nodeId; + } + + uint segmentCount() const + { + return m_segments.size(); + } + + bool verifySegment(uint segment, uint andx, uint bndx, QVector3D a, QVector3D b) const + { + if (segment >= uint(m_segments.size())) + return false; + if (andx != m_segments[segment].abcndx[0] + || bndx != m_segments[segment].abcndx[1]) + return false; + + if (!qFuzzyCompare(a, m_segments[segment].abc[0]) + || !qFuzzyCompare(b, m_segments[segment].abc[1])) + return false; + + return true; + } +private: + struct TestSegment + { + uint abcndx[2]; + QVector3D abc[2]; + TestSegment() + { + abcndx[0] = abcndx[1] = uint(-1); + } + + TestSegment(uint andx, const QVector3D &a, uint bndx, const QVector3D &b) + { + abcndx[0] = andx; + abcndx[1] = bndx; + abc[0] = a; + abc[1] = b; + } + }; + QVector<TestSegment> m_segments; +}; + +class tst_SegmentVisitor : public Qt3DCore::QBackendNodeTester +{ + Q_OBJECT + +private Q_SLOTS: + + void checkInitialize() + { + // WHEN + QScopedPointer<NodeManagers> nodeManagers(new NodeManagers()); + TestVisitor visitor(nodeManagers.data()); + + // THEN + QCOMPARE(visitor.nodeManagers(), nodeManagers.data()); + } + + void checkApplyEntity() + { + QScopedPointer<NodeManagers> nodeManagers(new NodeManagers()); + QScopedPointer<Qt3DCore::QEntity> entity(new Qt3DCore::QEntity()); + TestVisitor visitor(nodeManagers.data()); + + // WHEN + visitor.apply(entity.data()); + + // THEN + QCOMPARE(visitor.nodeId(), entity->id()); + QCOMPARE(visitor.segmentCount(), uint(0)); + } + + void checkApplyGeometryRenderer() + { + QScopedPointer<NodeManagers> nodeManagers(new NodeManagers()); + QScopedPointer<GeometryRenderer> geometryRenderer(new GeometryRenderer()); + TestVisitor visitor(nodeManagers.data()); + + // WHEN + visitor.apply(geometryRenderer.data(), Qt3DCore::QNodeId()); + + // THEN + // tadaa, nothing should happen + } + + void testVisitSegments() + { + QScopedPointer<NodeManagers> nodeManagers(new NodeManagers()); + Qt3DRender::QGeometry *geometry = new Qt3DRender::QGeometry(); + QScopedPointer<Qt3DRender::QGeometryRenderer> geometryRenderer(new Qt3DRender::QGeometryRenderer()); + QScopedPointer<Qt3DRender::QAttribute> positionAttribute(new Qt3DRender::QAttribute()); + QScopedPointer<Qt3DRender::QBuffer> dataBuffer(new Qt3DRender::QBuffer()); + TestVisitor visitor(nodeManagers.data()); + TestRenderer renderer; + + QByteArray data; + data.resize(sizeof(float) * 3 * 2 * 3); + float *dataPtr = reinterpret_cast<float *>(data.data()); + dataPtr[0] = 0; + dataPtr[1] = 0; + dataPtr[2] = 1.0f; + dataPtr[3] = 1.0f; + dataPtr[4] = 0; + dataPtr[5] = 0; + + dataPtr[6] = 0; + dataPtr[7] = 1.0f; + dataPtr[8] = 0; + dataPtr[9] = 0; + dataPtr[10] = 0; + dataPtr[11] = 1.0f; + + dataPtr[12] = 1.0f; + dataPtr[13] = 0; + dataPtr[14] = 0; + dataPtr[15] = 0; + dataPtr[16] = 1.0f; + dataPtr[17] = 0; + + dataBuffer->setData(data); + Buffer *backendBuffer = nodeManagers->bufferManager()->getOrCreateResource(dataBuffer->id()); + backendBuffer->setRenderer(&renderer); + backendBuffer->setManager(nodeManagers->bufferManager()); + simulateInitialization(dataBuffer.data(), backendBuffer); + + positionAttribute->setBuffer(dataBuffer.data()); + positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName()); + positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float); + positionAttribute->setVertexSize(3); + positionAttribute->setCount(6); + positionAttribute->setByteStride(3*4); + positionAttribute->setByteOffset(0); + positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute); + geometry->addAttribute(positionAttribute.data()); + + geometryRenderer->setGeometry(geometry); + geometryRenderer->setPrimitiveType(Qt3DRender::QGeometryRenderer::Lines); + + Attribute *backendAttribute = nodeManagers->attributeManager()->getOrCreateResource(positionAttribute->id()); + backendAttribute->setRenderer(&renderer); + simulateInitialization(positionAttribute.data(), backendAttribute); + + Geometry *backendGeometry = nodeManagers->geometryManager()->getOrCreateResource(geometry->id()); + backendGeometry->setRenderer(&renderer); + simulateInitialization(geometry, backendGeometry); + + GeometryRenderer *backendRenderer = nodeManagers->geometryRendererManager()->getOrCreateResource(geometryRenderer->id()); + backendRenderer->setRenderer(&renderer); + backendRenderer->setManager(nodeManagers->geometryRendererManager()); + simulateInitialization(geometryRenderer.data(), backendRenderer); + + // WHEN + visitor.apply(backendRenderer, Qt3DCore::QNodeId()); + + // THEN + QCOMPARE(visitor.segmentCount(), uint(3)); + QVERIFY(visitor.verifySegment(0, 0,1, QVector3D(0,0,1), QVector3D(1,0,0))); + QVERIFY(visitor.verifySegment(1, 2,3, QVector3D(0,1,0), QVector3D(0,0,1))); + QVERIFY(visitor.verifySegment(2, 4,5, QVector3D(1,0,0), QVector3D(0,1,0))); + } + + void testVisitSegmentsIndexed() + { + QScopedPointer<NodeManagers> nodeManagers(new NodeManagers()); + Qt3DRender::QGeometry *geometry = new Qt3DRender::QGeometry(); + QScopedPointer<Qt3DRender::QGeometryRenderer> geometryRenderer(new Qt3DRender::QGeometryRenderer()); + QScopedPointer<Qt3DRender::QAttribute> positionAttribute(new Qt3DRender::QAttribute()); + QScopedPointer<Qt3DRender::QAttribute> indexAttribute(new Qt3DRender::QAttribute()); + QScopedPointer<Qt3DRender::QBuffer> dataBuffer(new Qt3DRender::QBuffer()); + QScopedPointer<Qt3DRender::QBuffer> indexDataBuffer(new Qt3DRender::QBuffer()); + TestVisitor visitor(nodeManagers.data()); + TestRenderer renderer; + + QByteArray data; + data.resize(sizeof(float) * 3 * 4); + float *dataPtr = reinterpret_cast<float *>(data.data()); + dataPtr[0] = 0; + dataPtr[1] = 0; + dataPtr[2] = 0.0f; + dataPtr[3] = 1.0f; + dataPtr[4] = 0; + dataPtr[5] = 0; + dataPtr[6] = 1.0; + dataPtr[7] = 1.0f; + dataPtr[8] = 0; + dataPtr[9] = 0; + dataPtr[10] = 1.0f; + dataPtr[11] = 0; + dataBuffer->setData(data); + Buffer *backendBuffer = nodeManagers->bufferManager()->getOrCreateResource(dataBuffer->id()); + backendBuffer->setRenderer(&renderer); + backendBuffer->setManager(nodeManagers->bufferManager()); + simulateInitialization(dataBuffer.data(), backendBuffer); + + QByteArray indexData; + indexData.resize(sizeof(uint) * 2 * 5); + uint *iDataPtr = reinterpret_cast<uint *>(indexData.data()); + iDataPtr[0] = 0; + iDataPtr[1] = 1; + iDataPtr[2] = 1; + iDataPtr[3] = 2; + iDataPtr[4] = 2; + iDataPtr[5] = 3; + iDataPtr[6] = 0; + iDataPtr[7] = 2; + iDataPtr[8] = 1; + iDataPtr[9] = 3; + indexDataBuffer->setData(indexData); + + Buffer *backendIndexBuffer = nodeManagers->bufferManager()->getOrCreateResource(indexDataBuffer->id()); + backendIndexBuffer->setRenderer(&renderer); + backendIndexBuffer->setManager(nodeManagers->bufferManager()); + simulateInitialization(indexDataBuffer.data(), backendIndexBuffer); + + positionAttribute->setBuffer(dataBuffer.data()); + positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName()); + positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float); + positionAttribute->setVertexSize(3); + positionAttribute->setCount(4); + positionAttribute->setByteStride(3*sizeof(float)); + positionAttribute->setByteOffset(0); + positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute); + + indexAttribute->setBuffer(indexDataBuffer.data()); + indexAttribute->setVertexBaseType(Qt3DRender::QAttribute::UnsignedInt); + indexAttribute->setCount(2*5); + indexAttribute->setAttributeType(Qt3DRender::QAttribute::IndexAttribute); + + geometry->addAttribute(positionAttribute.data()); + geometry->addAttribute(indexAttribute.data()); + + geometryRenderer->setGeometry(geometry); + geometryRenderer->setPrimitiveType(Qt3DRender::QGeometryRenderer::Lines); + + Attribute *backendAttribute = nodeManagers->attributeManager()->getOrCreateResource(positionAttribute->id()); + backendAttribute->setRenderer(&renderer); + simulateInitialization(positionAttribute.data(), backendAttribute); + + Attribute *backendIndexAttribute = nodeManagers->attributeManager()->getOrCreateResource(indexAttribute->id()); + backendIndexAttribute->setRenderer(&renderer); + simulateInitialization(indexAttribute.data(), backendIndexAttribute); + + Geometry *backendGeometry = nodeManagers->geometryManager()->getOrCreateResource(geometry->id()); + backendGeometry->setRenderer(&renderer); + simulateInitialization(geometry, backendGeometry); + + GeometryRenderer *backendRenderer = nodeManagers->geometryRendererManager()->getOrCreateResource(geometryRenderer->id()); + backendRenderer->setRenderer(&renderer); + backendRenderer->setManager(nodeManagers->geometryRendererManager()); + simulateInitialization(geometryRenderer.data(), backendRenderer); + + // WHEN + visitor.apply(backendRenderer, Qt3DCore::QNodeId()); + + // THEN + QCOMPARE(visitor.segmentCount(), uint(5)); + QVERIFY(visitor.verifySegment(0, 0,1, QVector3D(0,0,0), QVector3D(1,0,0))); + QVERIFY(visitor.verifySegment(1, 1,2, QVector3D(1,0,0), QVector3D(1,1,0))); + QVERIFY(visitor.verifySegment(2, 2,3, QVector3D(1,1,0), QVector3D(0,1,0))); + QVERIFY(visitor.verifySegment(3, 0,2, QVector3D(0,0,0), QVector3D(1,1,0))); + QVERIFY(visitor.verifySegment(4, 1,3, QVector3D(1,0,0), QVector3D(0,1,0))); + } + + void testVisitLineStrip() + { + QScopedPointer<NodeManagers> nodeManagers(new NodeManagers()); + Qt3DRender::QGeometry *geometry = new Qt3DRender::QGeometry(); + QScopedPointer<Qt3DRender::QGeometryRenderer> geometryRenderer(new Qt3DRender::QGeometryRenderer()); + QScopedPointer<Qt3DRender::QAttribute> positionAttribute(new Qt3DRender::QAttribute()); + QScopedPointer<Qt3DRender::QBuffer> dataBuffer(new Qt3DRender::QBuffer()); + TestVisitor visitor(nodeManagers.data()); + TestRenderer renderer; + + QByteArray data; + data.resize(sizeof(float) * 3 * 4); + float *dataPtr = reinterpret_cast<float *>(data.data()); + dataPtr[0] = 0; + dataPtr[1] = 0; + dataPtr[2] = 0.0f; + dataPtr[3] = 1.0f; + dataPtr[4] = 0; + dataPtr[5] = 0; + dataPtr[6] = 1.0f; + dataPtr[7] = 1.0f; + dataPtr[8] = 0; + dataPtr[9] = 0; + dataPtr[10] = 1.0f; + dataPtr[11] = 0; + dataBuffer->setData(data); + Buffer *backendBuffer = nodeManagers->bufferManager()->getOrCreateResource(dataBuffer->id()); + backendBuffer->setRenderer(&renderer); + backendBuffer->setManager(nodeManagers->bufferManager()); + simulateInitialization(dataBuffer.data(), backendBuffer); + + positionAttribute->setBuffer(dataBuffer.data()); + positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName()); + positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float); + positionAttribute->setVertexSize(3); + positionAttribute->setCount(4); + positionAttribute->setByteStride(3*4); + positionAttribute->setByteOffset(0); + positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute); + geometry->addAttribute(positionAttribute.data()); + + geometryRenderer->setGeometry(geometry); + geometryRenderer->setPrimitiveType(Qt3DRender::QGeometryRenderer::LineStrip); + + Attribute *backendAttribute = nodeManagers->attributeManager()->getOrCreateResource(positionAttribute->id()); + backendAttribute->setRenderer(&renderer); + simulateInitialization(positionAttribute.data(), backendAttribute); + + Geometry *backendGeometry = nodeManagers->geometryManager()->getOrCreateResource(geometry->id()); + backendGeometry->setRenderer(&renderer); + simulateInitialization(geometry, backendGeometry); + + GeometryRenderer *backendRenderer = nodeManagers->geometryRendererManager()->getOrCreateResource(geometryRenderer->id()); + backendRenderer->setRenderer(&renderer); + backendRenderer->setManager(nodeManagers->geometryRendererManager()); + simulateInitialization(geometryRenderer.data(), backendRenderer); + + // WHEN + visitor.apply(backendRenderer, Qt3DCore::QNodeId()); + + // THEN + QCOMPARE(visitor.segmentCount(), uint(3)); + QVERIFY(visitor.verifySegment(0, 0,1, QVector3D(0,0,0), QVector3D(1,0,0))); + QVERIFY(visitor.verifySegment(1, 1,2, QVector3D(1,0,0), QVector3D(1,1,0))); + QVERIFY(visitor.verifySegment(2, 2,3, QVector3D(1,1,0), QVector3D(0,1,0))); + } + + void testVisitListStripIndexed() + { + QScopedPointer<NodeManagers> nodeManagers(new NodeManagers()); + Qt3DRender::QGeometry *geometry = new Qt3DRender::QGeometry(); + QScopedPointer<Qt3DRender::QGeometryRenderer> geometryRenderer(new Qt3DRender::QGeometryRenderer()); + QScopedPointer<Qt3DRender::QAttribute> positionAttribute(new Qt3DRender::QAttribute()); + QScopedPointer<Qt3DRender::QAttribute> indexAttribute(new Qt3DRender::QAttribute()); + QScopedPointer<Qt3DRender::QBuffer> dataBuffer(new Qt3DRender::QBuffer()); + QScopedPointer<Qt3DRender::QBuffer> indexDataBuffer(new Qt3DRender::QBuffer()); + TestVisitor visitor(nodeManagers.data()); + TestRenderer renderer; + + QByteArray data; + data.resize(sizeof(float) * 3 * 4); + float *dataPtr = reinterpret_cast<float *>(data.data()); + dataPtr[0] = 0; + dataPtr[1] = 0; + dataPtr[2] = 0.0f; + dataPtr[3] = 1.0f; + dataPtr[4] = 0; + dataPtr[5] = 0; + dataPtr[6] = 1.0; + dataPtr[7] = 1.0f; + dataPtr[8] = 0; + dataPtr[9] = 0; + dataPtr[10] = 1.0f; + dataPtr[11] = 0; + dataBuffer->setData(data); + Buffer *backendBuffer = nodeManagers->bufferManager()->getOrCreateResource(dataBuffer->id()); + backendBuffer->setRenderer(&renderer); + backendBuffer->setManager(nodeManagers->bufferManager()); + simulateInitialization(dataBuffer.data(), backendBuffer); + + QByteArray indexData; + indexData.resize(sizeof(uint) * 2 * 4); + uint *iDataPtr = reinterpret_cast<uint *>(indexData.data()); + iDataPtr[0] = 0; + iDataPtr[1] = 1; + iDataPtr[2] = 2; + iDataPtr[3] = 3; + indexDataBuffer->setData(indexData); + + Buffer *backendIndexBuffer = nodeManagers->bufferManager()->getOrCreateResource(indexDataBuffer->id()); + backendIndexBuffer->setRenderer(&renderer); + backendIndexBuffer->setManager(nodeManagers->bufferManager()); + simulateInitialization(indexDataBuffer.data(), backendIndexBuffer); + + positionAttribute->setBuffer(dataBuffer.data()); + positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName()); + positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float); + positionAttribute->setVertexSize(3); + positionAttribute->setCount(4); + positionAttribute->setByteStride(3*sizeof(float)); + positionAttribute->setByteOffset(0); + positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute); + + indexAttribute->setBuffer(indexDataBuffer.data()); + indexAttribute->setVertexBaseType(Qt3DRender::QAttribute::UnsignedInt); + indexAttribute->setCount(4); + indexAttribute->setAttributeType(Qt3DRender::QAttribute::IndexAttribute); + + geometry->addAttribute(positionAttribute.data()); + geometry->addAttribute(indexAttribute.data()); + + geometryRenderer->setGeometry(geometry); + geometryRenderer->setPrimitiveType(Qt3DRender::QGeometryRenderer::LineStrip); + + Attribute *backendAttribute = nodeManagers->attributeManager()->getOrCreateResource(positionAttribute->id()); + backendAttribute->setRenderer(&renderer); + simulateInitialization(positionAttribute.data(), backendAttribute); + + Attribute *backendIndexAttribute = nodeManagers->attributeManager()->getOrCreateResource(indexAttribute->id()); + backendIndexAttribute->setRenderer(&renderer); + simulateInitialization(indexAttribute.data(), backendIndexAttribute); + + Geometry *backendGeometry = nodeManagers->geometryManager()->getOrCreateResource(geometry->id()); + backendGeometry->setRenderer(&renderer); + simulateInitialization(geometry, backendGeometry); + + GeometryRenderer *backendRenderer = nodeManagers->geometryRendererManager()->getOrCreateResource(geometryRenderer->id()); + backendRenderer->setRenderer(&renderer); + backendRenderer->setManager(nodeManagers->geometryRendererManager()); + simulateInitialization(geometryRenderer.data(), backendRenderer); + + // WHEN + visitor.apply(backendRenderer, Qt3DCore::QNodeId()); + + // THEN + QCOMPARE(visitor.segmentCount(), uint(3)); + QVERIFY(visitor.verifySegment(0, 0,1, QVector3D(0,0,0), QVector3D(1,0,0))); + QVERIFY(visitor.verifySegment(1, 1,2, QVector3D(1,0,0), QVector3D(1,1,0))); + QVERIFY(visitor.verifySegment(2, 2,3, QVector3D(1,1,0), QVector3D(0,1,0))); + } + + void testVisitLineLoop() + { + QScopedPointer<NodeManagers> nodeManagers(new NodeManagers()); + Qt3DRender::QGeometry *geometry = new Qt3DRender::QGeometry(); + QScopedPointer<Qt3DRender::QGeometryRenderer> geometryRenderer(new Qt3DRender::QGeometryRenderer()); + QScopedPointer<Qt3DRender::QAttribute> positionAttribute(new Qt3DRender::QAttribute()); + QScopedPointer<Qt3DRender::QBuffer> dataBuffer(new Qt3DRender::QBuffer()); + TestVisitor visitor(nodeManagers.data()); + TestRenderer renderer; + + QByteArray data; + data.resize(sizeof(float) * 3 * 4); + float *dataPtr = reinterpret_cast<float *>(data.data()); + dataPtr[0] = 0; + dataPtr[1] = 0; + dataPtr[2] = 0.0f; + dataPtr[3] = 1.0f; + dataPtr[4] = 0; + dataPtr[5] = 0; + dataPtr[6] = 1.0f; + dataPtr[7] = 1.0f; + dataPtr[8] = 0; + dataPtr[9] = 0; + dataPtr[10] = 1.0f; + dataPtr[11] = 0; + dataBuffer->setData(data); + Buffer *backendBuffer = nodeManagers->bufferManager()->getOrCreateResource(dataBuffer->id()); + backendBuffer->setRenderer(&renderer); + backendBuffer->setManager(nodeManagers->bufferManager()); + simulateInitialization(dataBuffer.data(), backendBuffer); + + positionAttribute->setBuffer(dataBuffer.data()); + positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName()); + positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float); + positionAttribute->setVertexSize(3); + positionAttribute->setCount(4); + positionAttribute->setByteStride(3*4); + positionAttribute->setByteOffset(0); + positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute); + geometry->addAttribute(positionAttribute.data()); + + geometryRenderer->setGeometry(geometry); + geometryRenderer->setPrimitiveType(Qt3DRender::QGeometryRenderer::LineLoop); + + Attribute *backendAttribute = nodeManagers->attributeManager()->getOrCreateResource(positionAttribute->id()); + backendAttribute->setRenderer(&renderer); + simulateInitialization(positionAttribute.data(), backendAttribute); + + Geometry *backendGeometry = nodeManagers->geometryManager()->getOrCreateResource(geometry->id()); + backendGeometry->setRenderer(&renderer); + simulateInitialization(geometry, backendGeometry); + + GeometryRenderer *backendRenderer = nodeManagers->geometryRendererManager()->getOrCreateResource(geometryRenderer->id()); + backendRenderer->setRenderer(&renderer); + backendRenderer->setManager(nodeManagers->geometryRendererManager()); + simulateInitialization(geometryRenderer.data(), backendRenderer); + + // WHEN + visitor.apply(backendRenderer, Qt3DCore::QNodeId()); + + // THEN + QCOMPARE(visitor.segmentCount(), uint(4)); + QVERIFY(visitor.verifySegment(0, 0,1, QVector3D(0,0,0), QVector3D(1,0,0))); + QVERIFY(visitor.verifySegment(1, 1,2, QVector3D(1,0,0), QVector3D(1,1,0))); + QVERIFY(visitor.verifySegment(2, 2,3, QVector3D(1,1,0), QVector3D(0,1,0))); + QVERIFY(visitor.verifySegment(3, 3,0, QVector3D(0,1,0), QVector3D(0,0,0))); + } + + void testVisitLineLoopIndexed() + { + QScopedPointer<NodeManagers> nodeManagers(new NodeManagers()); + Qt3DRender::QGeometry *geometry = new Qt3DRender::QGeometry(); + QScopedPointer<Qt3DRender::QGeometryRenderer> geometryRenderer(new Qt3DRender::QGeometryRenderer()); + QScopedPointer<Qt3DRender::QAttribute> positionAttribute(new Qt3DRender::QAttribute()); + QScopedPointer<Qt3DRender::QAttribute> indexAttribute(new Qt3DRender::QAttribute()); + QScopedPointer<Qt3DRender::QBuffer> dataBuffer(new Qt3DRender::QBuffer()); + QScopedPointer<Qt3DRender::QBuffer> indexDataBuffer(new Qt3DRender::QBuffer()); + TestVisitor visitor(nodeManagers.data()); + TestRenderer renderer; + + QByteArray data; + data.resize(sizeof(float) * 3 * 4); + float *dataPtr = reinterpret_cast<float *>(data.data()); + dataPtr[0] = 0; + dataPtr[1] = 0; + dataPtr[2] = 0.0f; + dataPtr[3] = 1.0f; + dataPtr[4] = 0; + dataPtr[5] = 0; + dataPtr[6] = 1.0; + dataPtr[7] = 1.0f; + dataPtr[8] = 0; + dataPtr[9] = 0; + dataPtr[10] = 1.0f; + dataPtr[11] = 0; + dataBuffer->setData(data); + Buffer *backendBuffer = nodeManagers->bufferManager()->getOrCreateResource(dataBuffer->id()); + backendBuffer->setRenderer(&renderer); + backendBuffer->setManager(nodeManagers->bufferManager()); + simulateInitialization(dataBuffer.data(), backendBuffer); + + QByteArray indexData; + indexData.resize(sizeof(uint) * 2 * 4); + uint *iDataPtr = reinterpret_cast<uint *>(indexData.data()); + iDataPtr[0] = 0; + iDataPtr[1] = 1; + iDataPtr[2] = 2; + iDataPtr[3] = 3; + indexDataBuffer->setData(indexData); + + Buffer *backendIndexBuffer = nodeManagers->bufferManager()->getOrCreateResource(indexDataBuffer->id()); + backendIndexBuffer->setRenderer(&renderer); + backendIndexBuffer->setManager(nodeManagers->bufferManager()); + simulateInitialization(indexDataBuffer.data(), backendIndexBuffer); + + positionAttribute->setBuffer(dataBuffer.data()); + positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName()); + positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float); + positionAttribute->setVertexSize(3); + positionAttribute->setCount(4); + positionAttribute->setByteStride(3*sizeof(float)); + positionAttribute->setByteOffset(0); + positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute); + + indexAttribute->setBuffer(indexDataBuffer.data()); + indexAttribute->setVertexBaseType(Qt3DRender::QAttribute::UnsignedInt); + indexAttribute->setCount(4); + indexAttribute->setAttributeType(Qt3DRender::QAttribute::IndexAttribute); + + geometry->addAttribute(positionAttribute.data()); + geometry->addAttribute(indexAttribute.data()); + + geometryRenderer->setGeometry(geometry); + geometryRenderer->setPrimitiveType(Qt3DRender::QGeometryRenderer::LineLoop); + + Attribute *backendAttribute = nodeManagers->attributeManager()->getOrCreateResource(positionAttribute->id()); + backendAttribute->setRenderer(&renderer); + simulateInitialization(positionAttribute.data(), backendAttribute); + + Attribute *backendIndexAttribute = nodeManagers->attributeManager()->getOrCreateResource(indexAttribute->id()); + backendIndexAttribute->setRenderer(&renderer); + simulateInitialization(indexAttribute.data(), backendIndexAttribute); + + Geometry *backendGeometry = nodeManagers->geometryManager()->getOrCreateResource(geometry->id()); + backendGeometry->setRenderer(&renderer); + simulateInitialization(geometry, backendGeometry); + + GeometryRenderer *backendRenderer = nodeManagers->geometryRendererManager()->getOrCreateResource(geometryRenderer->id()); + backendRenderer->setRenderer(&renderer); + backendRenderer->setManager(nodeManagers->geometryRendererManager()); + simulateInitialization(geometryRenderer.data(), backendRenderer); + + // WHEN + visitor.apply(backendRenderer, Qt3DCore::QNodeId()); + + // THEN + QCOMPARE(visitor.segmentCount(), uint(4)); + QVERIFY(visitor.verifySegment(0, 0,1, QVector3D(0,0,0), QVector3D(1,0,0))); + QVERIFY(visitor.verifySegment(1, 1,2, QVector3D(1,0,0), QVector3D(1,1,0))); + QVERIFY(visitor.verifySegment(2, 2,3, QVector3D(1,1,0), QVector3D(0,1,0))); + QVERIFY(visitor.verifySegment(3, 3,0, QVector3D(0,1,0), QVector3D(0,0,0))); + } + + void testVisitLineAdjacency() + { + QScopedPointer<NodeManagers> nodeManagers(new NodeManagers()); + Qt3DRender::QGeometry *geometry = new Qt3DRender::QGeometry(); + QScopedPointer<Qt3DRender::QGeometryRenderer> geometryRenderer(new Qt3DRender::QGeometryRenderer()); + QScopedPointer<Qt3DRender::QAttribute> positionAttribute(new Qt3DRender::QAttribute()); + QScopedPointer<Qt3DRender::QBuffer> dataBuffer(new Qt3DRender::QBuffer()); + TestVisitor visitor(nodeManagers.data()); + TestRenderer renderer; + + QByteArray data; + data.resize(sizeof(float) * 3 * 2 * 2); + float *dataPtr = reinterpret_cast<float *>(data.data()); + dataPtr[0] = 0; + dataPtr[1] = 0; + dataPtr[2] = 1.0f; + dataPtr[3] = 1.0f; + dataPtr[4] = 0; + dataPtr[5] = 0; + + dataPtr[6] = 0; + dataPtr[7] = 1.0f; + dataPtr[8] = 0; + dataPtr[9] = 1.0f; + dataPtr[10] = 0; + dataPtr[12] = 0; + dataBuffer->setData(data); + Buffer *backendBuffer = nodeManagers->bufferManager()->getOrCreateResource(dataBuffer->id()); + backendBuffer->setRenderer(&renderer); + backendBuffer->setManager(nodeManagers->bufferManager()); + simulateInitialization(dataBuffer.data(), backendBuffer); + + positionAttribute->setBuffer(dataBuffer.data()); + positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName()); + positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float); + positionAttribute->setVertexSize(3); + positionAttribute->setCount(4); + positionAttribute->setByteStride(3*4); + positionAttribute->setByteOffset(0); + positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute); + geometry->addAttribute(positionAttribute.data()); + + geometryRenderer->setGeometry(geometry); + geometryRenderer->setPrimitiveType(Qt3DRender::QGeometryRenderer::LinesAdjacency); + + Attribute *backendAttribute = nodeManagers->attributeManager()->getOrCreateResource(positionAttribute->id()); + backendAttribute->setRenderer(&renderer); + simulateInitialization(positionAttribute.data(), backendAttribute); + + Geometry *backendGeometry = nodeManagers->geometryManager()->getOrCreateResource(geometry->id()); + backendGeometry->setRenderer(&renderer); + simulateInitialization(geometry, backendGeometry); + + GeometryRenderer *backendRenderer = nodeManagers->geometryRendererManager()->getOrCreateResource(geometryRenderer->id()); + backendRenderer->setRenderer(&renderer); + backendRenderer->setManager(nodeManagers->geometryRendererManager()); + simulateInitialization(geometryRenderer.data(), backendRenderer); + + // WHEN + visitor.apply(backendRenderer, Qt3DCore::QNodeId()); + + // THEN + QCOMPARE(visitor.segmentCount(), uint(1)); + QVERIFY(visitor.verifySegment(0, 1, 2, QVector3D(1,0,0), QVector3D(0,1,0))); + } + + void testVisitLinesAdjacencyIndexed() + { + QScopedPointer<NodeManagers> nodeManagers(new NodeManagers()); + Qt3DRender::QGeometry *geometry = new Qt3DRender::QGeometry(); + QScopedPointer<Qt3DRender::QGeometryRenderer> geometryRenderer(new Qt3DRender::QGeometryRenderer()); + QScopedPointer<Qt3DRender::QAttribute> positionAttribute(new Qt3DRender::QAttribute()); + QScopedPointer<Qt3DRender::QAttribute> indexAttribute(new Qt3DRender::QAttribute()); + QScopedPointer<Qt3DRender::QBuffer> dataBuffer(new Qt3DRender::QBuffer()); + QScopedPointer<Qt3DRender::QBuffer> indexDataBuffer(new Qt3DRender::QBuffer()); + TestVisitor visitor(nodeManagers.data()); + TestRenderer renderer; + + QByteArray data; + data.resize(sizeof(float) * 3 * 2 * 2); + float *dataPtr = reinterpret_cast<float *>(data.data()); + dataPtr[0] = 0; + dataPtr[1] = 0; + dataPtr[2] = 1.0f; + dataPtr[3] = 1.0f; + dataPtr[4] = 0; + dataPtr[5] = 0; + + dataPtr[6] = 0; + dataPtr[7] = 1.0f; + dataPtr[8] = 0; + dataPtr[9] = 1.0f; + dataPtr[10] = 0; + dataPtr[12] = 0; + dataBuffer->setData(data); + Buffer *backendBuffer = nodeManagers->bufferManager()->getOrCreateResource(dataBuffer->id()); + backendBuffer->setRenderer(&renderer); + backendBuffer->setManager(nodeManagers->bufferManager()); + simulateInitialization(dataBuffer.data(), backendBuffer); + + QByteArray indexData; + indexData.resize(sizeof(uint) * 2); + uint *iDataPtr = reinterpret_cast<uint *>(indexData.data()); + iDataPtr[0] = 0; + iDataPtr[1] = 1; + iDataPtr[2] = 2; + iDataPtr[3] = 3; + indexDataBuffer->setData(indexData); + + Buffer *backendIndexBuffer = nodeManagers->bufferManager()->getOrCreateResource(indexDataBuffer->id()); + backendIndexBuffer->setRenderer(&renderer); + backendIndexBuffer->setManager(nodeManagers->bufferManager()); + simulateInitialization(indexDataBuffer.data(), backendIndexBuffer); + + positionAttribute->setBuffer(dataBuffer.data()); + positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName()); + positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float); + positionAttribute->setVertexSize(3); + positionAttribute->setCount(4); + positionAttribute->setByteStride(3*sizeof(float)); + positionAttribute->setByteOffset(0); + positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute); + + indexAttribute->setBuffer(indexDataBuffer.data()); + indexAttribute->setVertexBaseType(Qt3DRender::QAttribute::UnsignedInt); + indexAttribute->setCount(4); + indexAttribute->setAttributeType(Qt3DRender::QAttribute::IndexAttribute); + + geometry->addAttribute(positionAttribute.data()); + geometry->addAttribute(indexAttribute.data()); + + geometryRenderer->setGeometry(geometry); + geometryRenderer->setPrimitiveType(Qt3DRender::QGeometryRenderer::LinesAdjacency); + + Attribute *backendAttribute = nodeManagers->attributeManager()->getOrCreateResource(positionAttribute->id()); + backendAttribute->setRenderer(&renderer); + simulateInitialization(positionAttribute.data(), backendAttribute); + + Attribute *backendIndexAttribute = nodeManagers->attributeManager()->getOrCreateResource(indexAttribute->id()); + backendIndexAttribute->setRenderer(&renderer); + simulateInitialization(indexAttribute.data(), backendIndexAttribute); + + Geometry *backendGeometry = nodeManagers->geometryManager()->getOrCreateResource(geometry->id()); + backendGeometry->setRenderer(&renderer); + simulateInitialization(geometry, backendGeometry); + + GeometryRenderer *backendRenderer = nodeManagers->geometryRendererManager()->getOrCreateResource(geometryRenderer->id()); + backendRenderer->setRenderer(&renderer); + backendRenderer->setManager(nodeManagers->geometryRendererManager()); + simulateInitialization(geometryRenderer.data(), backendRenderer); + + // WHEN + visitor.apply(backendRenderer, Qt3DCore::QNodeId()); + + // THEN + QCOMPARE(visitor.segmentCount(), uint(1)); + QVERIFY(visitor.verifySegment(0, 1, 2, QVector3D(1,0,0), QVector3D(0,1,0))); + } +}; + +QTEST_MAIN(tst_SegmentVisitor) + +#include "tst_segmentvisitor.moc" diff --git a/tests/auto/render/sendrendercapturejob/tst_sendrendercapturejob.cpp b/tests/auto/render/sendrendercapturejob/tst_sendrendercapturejob.cpp index 3310941ed..c6bd65324 100644 --- a/tests/auto/render/sendrendercapturejob/tst_sendrendercapturejob.cpp +++ b/tests/auto/render/sendrendercapturejob/tst_sendrendercapturejob.cpp @@ -55,9 +55,9 @@ private Q_SLOTS: renderer.setNodeManagers(&nodeManagers); job.setManagers(&nodeManagers); - renderCapture->requestCapture(42); - renderCapture->acknowledgeCaptureRequest(); - renderCapture->addRenderCapture(image); + renderCapture->requestCapture({ 42, QRect() }); + auto request = renderCapture->takeCaptureRequest(); + renderCapture->addRenderCapture(request.captureId, image); renderer.addRenderCaptureSendRequest(renderCapture->peerId()); //WHEN diff --git a/tests/auto/render/shader/shader.pro b/tests/auto/render/shader/shader.pro index 7c908e0f6..6e8a8ec2e 100644 --- a/tests/auto/render/shader/shader.pro +++ b/tests/auto/render/shader/shader.pro @@ -9,3 +9,4 @@ CONFIG += testcase SOURCES += tst_shader.cpp include(../../core/common/common.pri) +include(../commons/commons.pri) diff --git a/tests/auto/render/shader/tst_shader.cpp b/tests/auto/render/shader/tst_shader.cpp index f6ed41a8b..067db55e7 100644 --- a/tests/auto/render/shader/tst_shader.cpp +++ b/tests/auto/render/shader/tst_shader.cpp @@ -30,6 +30,7 @@ #include <qbackendnodetester.h> #include <Qt3DRender/private/shader_p.h> #include <Qt3DRender/qshaderprogram.h> +#include "testrenderer.h" class tst_RenderShader : public Qt3DCore::QBackendNodeTester { @@ -39,6 +40,11 @@ private slots: void hasCoherentInitialState(); void matchesFrontendPeer(); void cleanupLeavesACoherentState(); + void dealWithPropertyChanges_data(); + void dealWithPropertyChanges(); + void checkSetRendererDirtyOnInitialization(); + void allowToChangeShaderCode_data(); + void allowToChangeShaderCode(); }; @@ -86,36 +92,180 @@ void tst_RenderShader::hasCoherentInitialState() void tst_RenderShader::matchesFrontendPeer() { - Qt3DRender::QShaderProgram *frontend = createFrontendShader(); - Qt3DRender::Render::Shader *backend = new Qt3DRender::Render::Shader(); + QScopedPointer<Qt3DRender::QShaderProgram> frontend(createFrontendShader()); + TestRenderer renderer; + Qt3DRender::Render::Shader backend; - simulateInitialization(frontend, backend); - QCOMPARE(backend->isLoaded(), false); - QVERIFY(backend->dna() != 0U); + backend.setRenderer(&renderer); + simulateInitialization(frontend.data(), &backend); + QCOMPARE(backend.isLoaded(), false); + QVERIFY(backend.dna() != 0U); for (int i = Qt3DRender::QShaderProgram::Vertex; i <= Qt3DRender::QShaderProgram::Compute; ++i) - QCOMPARE(backend->shaderCode()[i], + QCOMPARE(backend.shaderCode()[i], frontend->shaderCode( static_cast<const Qt3DRender::QShaderProgram::ShaderType>(i))); } void tst_RenderShader::cleanupLeavesACoherentState() { - Qt3DRender::QShaderProgram *frontend = createFrontendShader(); - Qt3DRender::Render::Shader *shader = new Qt3DRender::Render::Shader(); + QScopedPointer<Qt3DRender::QShaderProgram> frontend(createFrontendShader()); + TestRenderer renderer; + Qt3DRender::Render::Shader shader; - simulateInitialization(frontend, shader); + shader.setRenderer(&renderer); + simulateInitialization(frontend.data(), &shader); - shader->cleanup(); + shader.cleanup(); - QCOMPARE(shader->isLoaded(), false); - QCOMPARE(shader->dna(), 0U); - QVERIFY(shader->uniformsNames().isEmpty()); - QVERIFY(shader->attributesNames().isEmpty()); - QVERIFY(shader->uniformBlockNames().isEmpty()); - QVERIFY(shader->uniforms().isEmpty()); - QVERIFY(shader->attributes().isEmpty()); - QVERIFY(shader->uniformBlocks().isEmpty()); - QCOMPARE(shader->status(), Qt3DRender::QShaderProgram::NotReady); + QCOMPARE(shader.isLoaded(), false); + QCOMPARE(shader.dna(), 0U); + QVERIFY(shader.uniformsNames().isEmpty()); + QVERIFY(shader.attributesNames().isEmpty()); + QVERIFY(shader.uniformBlockNames().isEmpty()); + QVERIFY(shader.uniforms().isEmpty()); + QVERIFY(shader.attributes().isEmpty()); + QVERIFY(shader.uniformBlocks().isEmpty()); + QCOMPARE(shader.status(), Qt3DRender::QShaderProgram::NotReady); +} + +void tst_RenderShader::dealWithPropertyChanges_data() +{ + QTest::addColumn<QByteArray>("property"); + QTest::addColumn<Qt3DRender::QShaderProgram::ShaderType>("type"); + + QTest::newRow("vertex") << QByteArrayLiteral("vertexShaderCode") + << Qt3DRender::QShaderProgram::Vertex; + + QTest::newRow("tessControl") << QByteArrayLiteral("tessellationControlShaderCode") + << Qt3DRender::QShaderProgram::TessellationControl; + + QTest::newRow("tessEval") << QByteArrayLiteral("tessellationEvaluationShaderCode") + << Qt3DRender::QShaderProgram::TessellationEvaluation; + + QTest::newRow("geometry") << QByteArrayLiteral("geometryShaderCode") + << Qt3DRender::QShaderProgram::Geometry; + + QTest::newRow("fragment") << QByteArrayLiteral("fragmentShaderCode") + << Qt3DRender::QShaderProgram::Fragment; + + QTest::newRow("compute") << QByteArrayLiteral("computeShaderCode") + << Qt3DRender::QShaderProgram::Compute; +} + +void tst_RenderShader::dealWithPropertyChanges() +{ + // GIVEN + QFETCH(QByteArray, property); + QFETCH(Qt3DRender::QShaderProgram::ShaderType, type); + + Qt3DRender::Render::Shader backend; + backend.setLoaded(true); + TestRenderer renderer; + backend.setRenderer(&renderer); + + // WHEN + auto updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + updateChange->setValue(QStringLiteral("foo")); + updateChange->setPropertyName(property); + backend.sceneChangeEvent(updateChange); + + // THEN + QCOMPARE(backend.shaderCode().at(type), QStringLiteral("foo")); + QVERIFY(!backend.isLoaded()); + QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::ShadersDirty); + renderer.resetDirty(); + backend.setLoaded(true); + + // WHEN + updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + updateChange->setValue(QStringLiteral("foo")); + updateChange->setPropertyName(property); + backend.sceneChangeEvent(updateChange); + + // THEN + QCOMPARE(backend.shaderCode().at(type), QStringLiteral("foo")); + QVERIFY(backend.isLoaded()); + QCOMPARE(renderer.dirtyBits(), 0); + renderer.resetDirty(); + backend.setLoaded(true); + + // WHEN + updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + updateChange->setValue(QStringLiteral("bar")); + updateChange->setPropertyName(property); + backend.sceneChangeEvent(updateChange); + + // THEN + QCOMPARE(backend.shaderCode().at(type), QStringLiteral("bar")); + QVERIFY(!backend.isLoaded()); + QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::ShadersDirty); + renderer.resetDirty(); + backend.setLoaded(true); +} + +void tst_RenderShader::checkSetRendererDirtyOnInitialization() +{ + // GIVEN + QScopedPointer<Qt3DRender::QShaderProgram> frontend(createFrontendShader()); + Qt3DRender::Render::Shader shader; + TestRenderer renderer; + + shader.setRenderer(&renderer); + + // THEN + QCOMPARE(renderer.dirtyBits(), 0); + + // WHEN + simulateInitialization(frontend.data(), &shader); + + // THEN + QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::ShadersDirty); +} + +void tst_RenderShader::allowToChangeShaderCode_data() +{ + dealWithPropertyChanges_data(); +} + +void tst_RenderShader::allowToChangeShaderCode() +{ + // GIVEN + QFETCH(Qt3DRender::QShaderProgram::ShaderType, type); + + Qt3DRender::Render::Shader backend; + backend.setLoaded(true); + TestRenderer renderer; + backend.setRenderer(&renderer); + + // WHEN + backend.setShaderCode(type, QByteArrayLiteral("foo")); + + // THEN + QCOMPARE(backend.shaderCode().at(type), QStringLiteral("foo")); + QVERIFY(!backend.isLoaded()); + QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::ShadersDirty); + renderer.resetDirty(); + backend.setLoaded(true); + + // WHEN + backend.setShaderCode(type, QByteArrayLiteral("foo")); + + // THEN + QCOMPARE(backend.shaderCode().at(type), QStringLiteral("foo")); + QVERIFY(backend.isLoaded()); + QCOMPARE(renderer.dirtyBits(), 0); + renderer.resetDirty(); + backend.setLoaded(true); + + // WHEN + backend.setShaderCode(type, QByteArrayLiteral("bar")); + + // THEN + QCOMPARE(backend.shaderCode().at(type), QStringLiteral("bar")); + QVERIFY(!backend.isLoaded()); + QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::ShadersDirty); + renderer.resetDirty(); + backend.setLoaded(true); } QTEST_APPLESS_MAIN(tst_RenderShader) diff --git a/tests/auto/render/shaderbuilder/input.json b/tests/auto/render/shaderbuilder/input.json new file mode 100644 index 000000000..5437bd5b5 --- /dev/null +++ b/tests/auto/render/shaderbuilder/input.json @@ -0,0 +1,90 @@ +{ + "nodes": [ + { + "uuid": "{00000000-0000-0000-0000-000000000001}", + "type": "worldPosition" + }, + { + "uuid": "{00000000-0000-0000-0000-000000000002}", + "type": "texture" + }, + { + "uuid": "{00000000-0000-0000-0000-000000000003}", + "type": "texCoord" + }, + { + "uuid": "{00000000-0000-0000-0000-000000000004}", + "type": "lightIntensity" + }, + { + "uuid": "{00000000-0000-0000-0000-000000000005}", + "type": "exposure" + }, + { + "uuid": "{00000000-0000-0000-0000-000000000006}", + "type": "fragColor" + }, + { + "uuid": "{00000000-0000-0000-0000-000000000007}", + "type": "sampleTexture" + }, + { + "uuid": "{00000000-0000-0000-0000-000000000008}", + "type": "lightModel" + }, + { + "uuid": "{00000000-0000-0000-0000-000000000009}", + "type": "exposureFunction" + } + ], + "edges": [ + { + "sourceUuid": "{00000000-0000-0000-0000-000000000002}", + "sourcePort": "texture", + "targetUuid": "{00000000-0000-0000-0000-000000000007}", + "targetPort": "sampler" + }, + { + "sourceUuid": "{00000000-0000-0000-0000-000000000003}", + "sourcePort": "texCoord", + "targetUuid": "{00000000-0000-0000-0000-000000000007}", + "targetPort": "coord" + }, + { + "sourceUuid": "{00000000-0000-0000-0000-000000000001}", + "sourcePort": "worldPosition", + "targetUuid": "{00000000-0000-0000-0000-000000000008}", + "targetPort": "position" + }, + { + "sourceUuid": "{00000000-0000-0000-0000-000000000007}", + "sourcePort": "color", + "targetUuid": "{00000000-0000-0000-0000-000000000008}", + "targetPort": "baseColor" + }, + { + "sourceUuid": "{00000000-0000-0000-0000-000000000004}", + "sourcePort": "lightIntensity", + "targetUuid": "{00000000-0000-0000-0000-000000000008}", + "targetPort": "lightIntensity" + }, + { + "sourceUuid": "{00000000-0000-0000-0000-000000000008}", + "sourcePort": "outputColor", + "targetUuid": "{00000000-0000-0000-0000-000000000009}", + "targetPort": "inputColor" + }, + { + "sourceUuid": "{00000000-0000-0000-0000-000000000005}", + "sourcePort": "exposure", + "targetUuid": "{00000000-0000-0000-0000-000000000009}", + "targetPort": "exposure" + }, + { + "sourceUuid": "{00000000-0000-0000-0000-000000000009}", + "sourcePort": "outputColor", + "targetUuid": "{00000000-0000-0000-0000-000000000006}", + "targetPort": "fragColor" + } + ] +} diff --git a/tests/auto/render/shaderbuilder/lightmodel.es2.inc b/tests/auto/render/shaderbuilder/lightmodel.es2.inc new file mode 100644 index 000000000..8e603d9a8 --- /dev/null +++ b/tests/auto/render/shaderbuilder/lightmodel.es2.inc @@ -0,0 +1,6 @@ +highp vec4 lightModel(const in highp vec3 baseColor, + const in highp vec3 pos, + const in highp float intensity) +{ + ... +} diff --git a/tests/auto/render/shaderbuilder/lightmodel.gl3.inc b/tests/auto/render/shaderbuilder/lightmodel.gl3.inc new file mode 100644 index 000000000..31615dfcd --- /dev/null +++ b/tests/auto/render/shaderbuilder/lightmodel.gl3.inc @@ -0,0 +1,6 @@ +vec4 lightModel(const in vec3 baseColor, + const in vec3 pos, + const in float intensity) +{ + ... +} diff --git a/tests/auto/render/shaderbuilder/output.es2 b/tests/auto/render/shaderbuilder/output.es2 new file mode 100644 index 000000000..b543bc5ee --- /dev/null +++ b/tests/auto/render/shaderbuilder/output.es2 @@ -0,0 +1,36 @@ +#version 100 + +varying highp vec3 worldPosition; +uniform sampler2D texture; +varying highp vec2 texCoord; +uniform highp float lightIntensity; +uniform highp float exposure; +highp vec4 lightModel(const in highp vec3 baseColor, + const in highp vec3 pos, + const in highp float intensity) +{ + ... +} + +#line 9 +highp vec4 lightModel(const in highp vec3 baseColor, + const in highp vec3 pos, + const in highp float intensity) +{ + ... +} + +#line 11 + +void main() +{ + highp vec2 v2 = texCoord; + sampler2D v1 = texture; + highp float v3 = lightIntensity; + highp vec4 v5 = texture2D(v1, v2); + highp vec3 v0 = worldPosition; + highp float v4 = exposure; + highp vec4 v6 = lightModel(v5, v0, v3); + highp vec4 v7 = v6 * pow(2.0, v4); + gl_fragColor = v7; +} diff --git a/tests/auto/render/shaderbuilder/output.gl3 b/tests/auto/render/shaderbuilder/output.gl3 new file mode 100644 index 000000000..95a9c53fd --- /dev/null +++ b/tests/auto/render/shaderbuilder/output.gl3 @@ -0,0 +1,37 @@ +#version 150 core + +in vec3 worldPosition; +uniform sampler2D texture; +in vec2 texCoord; +uniform float lightIntensity; +uniform float exposure; +out vec4 fragColor; +vec4 lightModel(const in vec3 baseColor, + const in vec3 pos, + const in float intensity) +{ + ... +} + +#line 10 +vec4 lightModel(const in vec3 baseColor, + const in vec3 pos, + const in float intensity) +{ + ... +} + +#line 12 + +void main() +{ + vec2 v2 = texCoord; + sampler2D v1 = texture; + float v3 = lightIntensity; + vec4 v5 = texture2D(v1, v2); + vec3 v0 = worldPosition; + float v4 = exposure; + vec4 v6 = lightModel(v5, v0, v3); + vec4 v7 = v6 * pow(2.0, v4); + fragColor = v7; +} diff --git a/tests/auto/render/shaderbuilder/prototypes.json b/tests/auto/render/shaderbuilder/prototypes.json new file mode 100644 index 000000000..e9bf2e802 --- /dev/null +++ b/tests/auto/render/shaderbuilder/prototypes.json @@ -0,0 +1,237 @@ +{ + "worldPosition": { + "outputs": [ + "worldPosition" + ], + "rules": [ + { + "format": { + "api": "OpenGLES", + "major": 2, + "minor": 0 + }, + "substitution": "highp vec3 $worldPosition = worldPosition;", + "headerSnippets": [ "varying highp vec3 worldPosition;" ] + }, + { + "format": { + "api": "OpenGLCoreProfile", + "major": 3, + "minor": 2 + }, + "substitution": "vec3 $worldPosition = worldPosition;", + "headerSnippets": [ "in vec3 worldPosition;" ] + } + ] + }, + "texture": { + "outputs": [ + "texture" + ], + "rules": [ + { + "format": { + "api": "OpenGLES", + "major": 2, + "minor": 0 + }, + "substitution": "sampler2D $texture = texture;", + "headerSnippets": [ "uniform sampler2D texture;" ] + }, + { + "format": { + "api": "OpenGLCoreProfile", + "major": 3, + "minor": 2 + }, + "substitution": "sampler2D $texture = texture;", + "headerSnippets": [ "uniform sampler2D texture;" ] + } + ] + }, + "texCoord": { + "outputs": [ + "texCoord" + ], + "rules": [ + { + "format": { + "api": "OpenGLES", + "major": 2, + "minor": 0 + }, + "substitution": "highp vec2 $texCoord = texCoord;", + "headerSnippets": [ "varying highp vec2 texCoord;" ] + }, + { + "format": { + "api": "OpenGLCoreProfile", + "major": 3, + "minor": 2 + }, + "substitution": "vec2 $texCoord = texCoord;", + "headerSnippets": [ "in vec2 texCoord;" ] + } + ] + }, + "lightIntensity": { + "outputs": [ + "lightIntensity" + ], + "rules": [ + { + "format": { + "api": "OpenGLES", + "major": 2, + "minor": 0 + }, + "substitution": "highp float $lightIntensity = lightIntensity;", + "headerSnippets": [ "uniform highp float lightIntensity;" ] + }, + { + "format": { + "api": "OpenGLCoreProfile", + "major": 3, + "minor": 2 + }, + "substitution": "float $lightIntensity = lightIntensity;", + "headerSnippets": [ "uniform float lightIntensity;" ] + } + ] + }, + "exposure": { + "outputs": [ + "exposure" + ], + "rules": [ + { + "format": { + "api": "OpenGLES", + "major": 2, + "minor": 0 + }, + "substitution": "highp float $exposure = exposure;", + "headerSnippets": [ "uniform highp float exposure;" ] + }, + { + "format": { + "api": "OpenGLCoreProfile", + "major": 3, + "minor": 2 + }, + "substitution": "float $exposure = exposure;", + "headerSnippets": [ "uniform float exposure;" ] + } + ] + }, + "fragColor": { + "inputs": [ + "fragColor" + ], + "rules": [ + { + "format": { + "api": "OpenGLES", + "major": 2, + "minor": 0 + }, + "substitution": "gl_fragColor = $fragColor;" + }, + { + "format": { + "api": "OpenGLCoreProfile", + "major": 3, + "minor": 2 + }, + "substitution": "fragColor = $fragColor;", + "headerSnippets": [ "out vec4 fragColor;" ] + } + ] + }, + "sampleTexture": { + "inputs": [ + "sampler", + "coord" + ], + "outputs": [ + "color" + ], + "rules": [ + { + "format": { + "api": "OpenGLES", + "major": 2, + "minor": 0 + }, + "substitution": "highp vec4 $color = texture2D($sampler, $coord);" + }, + { + "format": { + "api": "OpenGLCoreProfile", + "major": 3, + "minor": 2 + }, + "substitution": "vec4 $color = texture2D($sampler, $coord);" + } + ] + }, + "lightModel": { + "inputs": [ + "baseColor", + "position", + "lightIntensity" + ], + "outputs": [ + "outputColor" + ], + "rules": [ + { + "format": { + "api": "OpenGLES", + "major": 2, + "minor": 0 + }, + "substitution": "highp vec4 $outputColor = lightModel($baseColor, $position, $lightIntensity);", + "headerSnippets": [ "#pragma include lightmodel.es2.inc" ] + }, + { + "format": { + "api": "OpenGLCoreProfile", + "major": 3, + "minor": 2 + }, + "substitution": "vec4 $outputColor = lightModel($baseColor, $position, $lightIntensity);", + "headerSnippets": [ "#pragma include lightmodel.gl3.inc" ] + } + ] + }, + "exposureFunction": { + "inputs": [ + "inputColor", + "exposure" + ], + "outputs": [ + "outputColor" + ], + "rules": [ + { + "format": { + "api": "OpenGLES", + "major": 2, + "minor": 0 + }, + "substitution": "highp vec4 $outputColor = $inputColor * pow(2.0, $exposure);", + "headerSnippets": [ "#pragma include :/lightmodel.es2.inc" ] + }, + { + "format": { + "api": "OpenGLCoreProfile", + "major": 3, + "minor": 2 + }, + "substitution": "vec4 $outputColor = $inputColor * pow(2.0, $exposure);", + "headerSnippets": [ "#pragma include :/lightmodel.gl3.inc" ] + } + ] + } +} diff --git a/tests/auto/render/shaderbuilder/shaderbuilder.pro b/tests/auto/render/shaderbuilder/shaderbuilder.pro new file mode 100644 index 000000000..bd5f7dfe2 --- /dev/null +++ b/tests/auto/render/shaderbuilder/shaderbuilder.pro @@ -0,0 +1,13 @@ +TEMPLATE = app + +TARGET = tst_shaderbuilder + +QT += core-private 3dcore 3dcore-private 3drender 3drender-private testlib + +CONFIG += testcase + +SOURCES += tst_shaderbuilder.cpp +RESOURCES += shaderbuilder.qrc + +include(../../core/common/common.pri) +include(../commons/commons.pri) diff --git a/tests/auto/render/shaderbuilder/shaderbuilder.qrc b/tests/auto/render/shaderbuilder/shaderbuilder.qrc new file mode 100644 index 000000000..92ab0405c --- /dev/null +++ b/tests/auto/render/shaderbuilder/shaderbuilder.qrc @@ -0,0 +1,10 @@ +<RCC> + <qresource prefix="/"> + <file>prototypes.json</file> + <file>input.json</file> + <file>output.gl3</file> + <file>output.es2</file> + <file>lightmodel.gl3.inc</file> + <file>lightmodel.es2.inc</file> + </qresource> +</RCC> diff --git a/tests/auto/render/shaderbuilder/tst_shaderbuilder.cpp b/tests/auto/render/shaderbuilder/tst_shaderbuilder.cpp new file mode 100644 index 000000000..6557acb6c --- /dev/null +++ b/tests/auto/render/shaderbuilder/tst_shaderbuilder.cpp @@ -0,0 +1,548 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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$ +** +****************************************************************************/ + +#include <QtTest/QTest> +#include <qbackendnodetester.h> +#include <Qt3DRender/private/shaderbuilder_p.h> +#include <Qt3DRender/qshaderprogram.h> +#include <Qt3DRender/qshaderprogrambuilder.h> +#include "testrenderer.h" + +Q_DECLARE_METATYPE(Qt3DRender::Render::ShaderBuilder::ShaderType) + +class tst_ShaderBuilder : public Qt3DCore::QBackendNodeTester +{ + Q_OBJECT +private slots: + void shouldHaveGlobalDefaultPrototypes() + { + // GIVEN + + // THEN + QCOMPARE(Qt3DRender::Render::ShaderBuilder::getPrototypesFile(), QStringLiteral(":/prototypes/default.json")); + QVERIFY(!Qt3DRender::Render::ShaderBuilder::getPrototypeNames().isEmpty()); + + // WHEN + Qt3DRender::Render::ShaderBuilder::setPrototypesFile(":/prototypes.json"); + + // THEN + QCOMPARE(Qt3DRender::Render::ShaderBuilder::getPrototypesFile(), QStringLiteral(":/prototypes.json")); + auto prototypeNames = Qt3DRender::Render::ShaderBuilder::getPrototypeNames(); + prototypeNames.sort(); + const auto expectedPrototypeNames = QStringList() << "exposure" + << "exposureFunction" + << "fragColor" + << "lightIntensity" + << "lightModel" + << "sampleTexture" + << "texCoord" + << "texture" + << "worldPosition"; + QCOMPARE(prototypeNames, expectedPrototypeNames); + } + + void shouldHaveInitialState() + { + // GIVEN + Qt3DRender::Render::ShaderBuilder shaderBuilder; + + // THEN + QVERIFY(!shaderBuilder.isEnabled()); + QVERIFY(shaderBuilder.enabledLayers().isEmpty()); + for (int i = 0; i <= Qt3DRender::Render::ShaderBuilder::Compute; i++) { + const auto type = static_cast<Qt3DRender::Render::ShaderBuilder::ShaderType>(i); + QCOMPARE(shaderBuilder.shaderGraph(type), QUrl()); + QCOMPARE(shaderBuilder.shaderCode(type), QByteArray()); + QVERIFY(!shaderBuilder.isShaderCodeDirty(type)); + } + } + + void shouldHavePropertiesMirroringFromItsPeer_data() + { + QTest::addColumn<Qt3DRender::QShaderProgramBuilder*>("frontend"); + + { + auto frontend = new Qt3DRender::QShaderProgramBuilder; + QTest::newRow("empty") << frontend; + } + { + auto frontend = new Qt3DRender::QShaderProgramBuilder; + auto program = new Qt3DRender::QShaderProgram(frontend); + frontend->setShaderProgram(program); + QTest::newRow("shaderProgram") << frontend; + } + { + auto frontend = new Qt3DRender::QShaderProgramBuilder; + frontend->setEnabledLayers({"foo", "bar"}); + QTest::newRow("enabledLayers") << frontend; + } + { + auto frontend = new Qt3DRender::QShaderProgramBuilder; + frontend->setVertexShaderGraph(QUrl::fromEncoded("qrc:/vertex.json")); + QTest::newRow("vertex") << frontend; + } + { + auto frontend = new Qt3DRender::QShaderProgramBuilder; + frontend->setTessellationControlShaderGraph(QUrl::fromEncoded("qrc:/tesscontrol.json")); + QTest::newRow("tessellationControl") << frontend; + } + { + auto frontend = new Qt3DRender::QShaderProgramBuilder; + frontend->setTessellationEvaluationShaderGraph(QUrl::fromEncoded("qrc:/tesseval.json")); + QTest::newRow("tessellationEvaluation") << frontend; + } + { + auto frontend = new Qt3DRender::QShaderProgramBuilder; + frontend->setGeometryShaderGraph(QUrl::fromEncoded("qrc:/geometry.json")); + QTest::newRow("geometry") << frontend; + } + { + auto frontend = new Qt3DRender::QShaderProgramBuilder; + frontend->setFragmentShaderGraph(QUrl::fromEncoded("qrc:/fragment.json")); + QTest::newRow("fragment") << frontend; + } + { + auto frontend = new Qt3DRender::QShaderProgramBuilder; + frontend->setComputeShaderGraph(QUrl::fromEncoded("qrc:/compute.json")); + QTest::newRow("compute") << frontend; + } + } + + void shouldHavePropertiesMirroringFromItsPeer() + { + // GIVEN + QFETCH(Qt3DRender::QShaderProgramBuilder*, frontend); + Qt3DRender::Render::ShaderBuilder backend; + + // WHEN + simulateInitialization(frontend, &backend); + + // THEN + QVERIFY(backend.isEnabled() == frontend->isEnabled()); + + if (frontend->shaderProgram()) + QCOMPARE(backend.shaderProgramId(), frontend->shaderProgram()->id()); + else + QVERIFY(backend.shaderProgramId().isNull()); + + QCOMPARE(backend.enabledLayers(), frontend->enabledLayers()); + + QCOMPARE(backend.shaderGraph(Qt3DRender::Render::ShaderBuilder::Vertex), frontend->vertexShaderGraph()); + QCOMPARE(backend.shaderCode(Qt3DRender::Render::ShaderBuilder::Vertex), QByteArray()); + QCOMPARE(backend.isShaderCodeDirty(Qt3DRender::Render::ShaderBuilder::Vertex), !frontend->vertexShaderGraph().isEmpty()); + + QCOMPARE(backend.shaderGraph(Qt3DRender::Render::ShaderBuilder::TessellationControl), frontend->tessellationControlShaderGraph()); + QCOMPARE(backend.shaderCode(Qt3DRender::Render::ShaderBuilder::TessellationControl), QByteArray()); + QCOMPARE(backend.isShaderCodeDirty(Qt3DRender::Render::ShaderBuilder::TessellationControl), !frontend->tessellationControlShaderGraph().isEmpty()); + + QCOMPARE(backend.shaderGraph(Qt3DRender::Render::ShaderBuilder::TessellationEvaluation), frontend->tessellationEvaluationShaderGraph()); + QCOMPARE(backend.shaderCode(Qt3DRender::Render::ShaderBuilder::TessellationEvaluation), QByteArray()); + QCOMPARE(backend.isShaderCodeDirty(Qt3DRender::Render::ShaderBuilder::TessellationEvaluation), !frontend->tessellationEvaluationShaderGraph().isEmpty()); + + QCOMPARE(backend.shaderGraph(Qt3DRender::Render::ShaderBuilder::Geometry), frontend->geometryShaderGraph()); + QCOMPARE(backend.shaderCode(Qt3DRender::Render::ShaderBuilder::Geometry), QByteArray()); + QCOMPARE(backend.isShaderCodeDirty(Qt3DRender::Render::ShaderBuilder::Geometry), !frontend->geometryShaderGraph().isEmpty()); + + QCOMPARE(backend.shaderGraph(Qt3DRender::Render::ShaderBuilder::Fragment), frontend->fragmentShaderGraph()); + QCOMPARE(backend.shaderCode(Qt3DRender::Render::ShaderBuilder::Fragment), QByteArray()); + QCOMPARE(backend.isShaderCodeDirty(Qt3DRender::Render::ShaderBuilder::Fragment), !frontend->fragmentShaderGraph().isEmpty()); + + QCOMPARE(backend.shaderGraph(Qt3DRender::Render::ShaderBuilder::Compute), frontend->computeShaderGraph()); + QCOMPARE(backend.shaderCode(Qt3DRender::Render::ShaderBuilder::Compute), QByteArray()); + QCOMPARE(backend.isShaderCodeDirty(Qt3DRender::Render::ShaderBuilder::Compute), !frontend->computeShaderGraph().isEmpty()); + + // WHEN + backend.cleanup(); + + // THEN + QVERIFY(!backend.isEnabled()); + QVERIFY(backend.enabledLayers().isEmpty()); + for (int i = 0; i <= Qt3DRender::Render::ShaderBuilder::Compute; i++) { + const auto type = static_cast<Qt3DRender::Render::ShaderBuilder::ShaderType>(i); + QCOMPARE(backend.shaderGraph(type), QUrl()); + QCOMPARE(backend.shaderCode(type), QByteArray()); + QVERIFY(!backend.isShaderCodeDirty(type)); + } + + delete frontend; + } + + void shouldHandleEnablePropertyChange() + { + // GIVEN + Qt3DRender::Render::ShaderBuilder backend; + TestRenderer renderer; + backend.setRenderer(&renderer); + + // WHEN + auto updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + updateChange->setValue(true); + updateChange->setPropertyName("enabled"); + backend.sceneChangeEvent(updateChange); + + // THEN + QVERIFY(backend.isEnabled()); + QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::ShadersDirty); + renderer.resetDirty(); + + // WHEN + updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + updateChange->setValue(false); + updateChange->setPropertyName("enabled"); + backend.sceneChangeEvent(updateChange); + + // THEN + QVERIFY(!backend.isEnabled()); + QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::ShadersDirty); + renderer.resetDirty(); + + // WHEN + updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + updateChange->setValue(true); + updateChange->setPropertyName("enabled"); + backend.sceneChangeEvent(updateChange); + // AND + backend.cleanup(); + + // THEN + QVERIFY(!backend.isEnabled()); + QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::ShadersDirty); + renderer.resetDirty(); + } + + void shouldHandleShaderProgramPropertyChange() + { + // GIVEN + Qt3DRender::Render::ShaderBuilder backend; + TestRenderer renderer; + backend.setRenderer(&renderer); + const auto programId = Qt3DCore::QNodeId::createId(); + + // WHEN + auto updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + updateChange->setValue(QVariant::fromValue(programId)); + updateChange->setPropertyName("shaderProgram"); + backend.sceneChangeEvent(updateChange); + + // THEN + QCOMPARE(backend.shaderProgramId(), programId); + QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::ShadersDirty); + renderer.resetDirty(); + + // WHEN + updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + updateChange->setValue(QVariant::fromValue(Qt3DCore::QNodeId())); + updateChange->setPropertyName("shaderProgram"); + backend.sceneChangeEvent(updateChange); + + // THEN + QVERIFY(backend.shaderProgramId().isNull()); + QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::ShadersDirty); + renderer.resetDirty(); + + // WHEN + updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + updateChange->setValue(QVariant::fromValue(programId)); + updateChange->setPropertyName("shaderProgram"); + backend.sceneChangeEvent(updateChange); + // AND + backend.cleanup(); + + // THEN + QVERIFY(backend.shaderProgramId().isNull()); + QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::ShadersDirty); + renderer.resetDirty(); + } + + void shouldHandleEnabledLayersPropertyChange() + { + // GIVEN + Qt3DRender::Render::ShaderBuilder backend; + TestRenderer renderer; + backend.setRenderer(&renderer); + const auto layers = QStringList() << "foo" << "bar"; + + for (int i = 0; i <= Qt3DRender::Render::ShaderBuilder::Compute; i++) { + const auto type = static_cast<Qt3DRender::Render::ShaderBuilder::ShaderType>(i); + const auto graphUrl = QUrl::fromEncoded("qrc:/input.json"); + backend.setShaderGraph(type, graphUrl); + } + + // WHEN + auto updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + updateChange->setValue(layers); + updateChange->setPropertyName("enabledLayers"); + backend.sceneChangeEvent(updateChange); + + // THEN + QCOMPARE(backend.enabledLayers(), layers); + for (int i = 0; i <= Qt3DRender::Render::ShaderBuilder::Compute; i++) { + const auto type = static_cast<Qt3DRender::Render::ShaderBuilder::ShaderType>(i); + QVERIFY(backend.isShaderCodeDirty(type)); + backend.generateCode(type); // Resets the dirty flag + } + QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::ShadersDirty); + renderer.resetDirty(); + + // WHEN + updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + updateChange->setValue(layers); + updateChange->setPropertyName("enabledLayers"); + backend.sceneChangeEvent(updateChange); + + // THEN + QCOMPARE(backend.enabledLayers(), layers); + for (int i = 0; i <= Qt3DRender::Render::ShaderBuilder::Compute; i++) { + const auto type = static_cast<Qt3DRender::Render::ShaderBuilder::ShaderType>(i); + QVERIFY(!backend.isShaderCodeDirty(type)); + backend.generateCode(type); // Resets the dirty flag + } + QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::ShadersDirty); + renderer.resetDirty(); + + // WHEN + updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + updateChange->setValue(QStringList()); + updateChange->setPropertyName("enabledLayers"); + backend.sceneChangeEvent(updateChange); + + // THEN + QVERIFY(backend.shaderProgramId().isNull()); + for (int i = 0; i <= Qt3DRender::Render::ShaderBuilder::Compute; i++) { + const auto type = static_cast<Qt3DRender::Render::ShaderBuilder::ShaderType>(i); + QVERIFY(backend.isShaderCodeDirty(type)); + backend.generateCode(type); // Resets the dirty flag + } + QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::ShadersDirty); + renderer.resetDirty(); + + // WHEN + updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + updateChange->setValue(layers); + updateChange->setPropertyName("enabledLayers"); + backend.sceneChangeEvent(updateChange); + // AND + backend.cleanup(); + + // THEN + QVERIFY(backend.enabledLayers().isEmpty()); + for (int i = 0; i <= Qt3DRender::Render::ShaderBuilder::Compute; i++) { + const auto type = static_cast<Qt3DRender::Render::ShaderBuilder::ShaderType>(i); + QVERIFY(!backend.isShaderCodeDirty(type)); + backend.generateCode(type); // Resets the dirty flag + } + QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::ShadersDirty); + renderer.resetDirty(); + } + + void shouldHandleShaderGraphPropertiesChanges_data() + { + QTest::addColumn<QByteArray>("property"); + QTest::addColumn<Qt3DRender::Render::ShaderBuilder::ShaderType>("type"); + QTest::addColumn<QUrl>("graphUrl"); + + QTest::newRow("vertex") << QByteArrayLiteral("vertexShaderGraph") + << Qt3DRender::Render::ShaderBuilder::Vertex + << QUrl::fromEncoded("qrc:/vertex.json"); + + QTest::newRow("tessControl") << QByteArrayLiteral("tessellationControlShaderGraph") + << Qt3DRender::Render::ShaderBuilder::TessellationControl + << QUrl::fromEncoded("qrc:/tesscontrol.json"); + + QTest::newRow("tessEval") << QByteArrayLiteral("tessellationEvaluationShaderGraph") + << Qt3DRender::Render::ShaderBuilder::TessellationEvaluation + << QUrl::fromEncoded("qrc:/tesseval.json"); + + QTest::newRow("geometry") << QByteArrayLiteral("geometryShaderGraph") + << Qt3DRender::Render::ShaderBuilder::Geometry + << QUrl::fromEncoded("qrc:/geometry.json"); + + QTest::newRow("fragment") << QByteArrayLiteral("fragmentShaderGraph") + << Qt3DRender::Render::ShaderBuilder::Fragment + << QUrl::fromEncoded("qrc:/fragment.json"); + + QTest::newRow("compute") << QByteArrayLiteral("computeShaderGraph") + << Qt3DRender::Render::ShaderBuilder::Compute + << QUrl::fromEncoded("qrc:/compute.json"); + } + + void shouldHandleShaderGraphPropertiesChanges() + { + // GIVEN + QFETCH(QByteArray, property); + QFETCH(Qt3DRender::Render::ShaderBuilder::ShaderType, type); + QFETCH(QUrl, graphUrl); + + Qt3DRender::Render::ShaderBuilder backend; + TestRenderer renderer; + backend.setRenderer(&renderer); + + // WHEN + auto updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + updateChange->setValue(QUrl()); + updateChange->setPropertyName(property); + backend.sceneChangeEvent(updateChange); + + // THEN + QCOMPARE(backend.shaderGraph(type), QUrl()); + QVERIFY(!backend.isShaderCodeDirty(type)); + QVERIFY(backend.shaderCode(type).isEmpty()); + QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::ShadersDirty); + renderer.resetDirty(); + + // WHEN + updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + updateChange->setValue(graphUrl); + updateChange->setPropertyName(property); + backend.sceneChangeEvent(updateChange); + + // THEN + QCOMPARE(backend.shaderGraph(type), graphUrl); + QVERIFY(backend.isShaderCodeDirty(type)); + QVERIFY(backend.shaderCode(type).isEmpty()); + QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::ShadersDirty); + renderer.resetDirty(); + + // WHEN + updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + updateChange->setValue(QUrl()); + updateChange->setPropertyName(property); + backend.sceneChangeEvent(updateChange); + + // THEN + QCOMPARE(backend.shaderGraph(type), QUrl()); + QVERIFY(backend.isShaderCodeDirty(type)); + QVERIFY(backend.shaderCode(type).isEmpty()); + QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::ShadersDirty); + renderer.resetDirty(); + + // WHEN + updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + updateChange->setValue(graphUrl); + updateChange->setPropertyName(property); + backend.sceneChangeEvent(updateChange); + // AND + backend.cleanup(); + + // THEN + QCOMPARE(backend.shaderGraph(type), QUrl()); + QVERIFY(!backend.isShaderCodeDirty(type)); + QVERIFY(backend.shaderCode(type).isEmpty()); + QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::ShadersDirty); + renderer.resetDirty(); + } + + void shouldHandleShaderCodeGeneration_data() + { + QTest::addColumn<Qt3DRender::Render::ShaderBuilder::ShaderType>("type"); + + QTest::newRow("vertex") << Qt3DRender::Render::ShaderBuilder::Vertex; + QTest::newRow("tessControl") << Qt3DRender::Render::ShaderBuilder::TessellationControl; + QTest::newRow("tessEval") << Qt3DRender::Render::ShaderBuilder::TessellationEvaluation; + QTest::newRow("geometry") << Qt3DRender::Render::ShaderBuilder::Geometry; + QTest::newRow("fragment") << Qt3DRender::Render::ShaderBuilder::Fragment; + QTest::newRow("compute") << Qt3DRender::Render::ShaderBuilder::Compute; + } + + void shouldHandleShaderCodeGeneration() + { + // GIVEN + Qt3DRender::Render::ShaderBuilder::setPrototypesFile(":/prototypes.json"); + QVERIFY(!Qt3DRender::Render::ShaderBuilder::getPrototypeNames().isEmpty()); + + QFETCH(Qt3DRender::Render::ShaderBuilder::ShaderType, type); + + const auto gl3Api = []{ + auto api = Qt3DRender::GraphicsApiFilterData(); + api.m_api = Qt3DRender::QGraphicsApiFilter::OpenGL; + api.m_profile = Qt3DRender::QGraphicsApiFilter::CoreProfile; + api.m_major = 3; + api.m_minor = 2; + return api; + }(); + + const auto es2Api = []{ + auto api = Qt3DRender::GraphicsApiFilterData(); + api.m_api = Qt3DRender::QGraphicsApiFilter::OpenGLES; + api.m_major = 2; + api.m_minor = 0; + return api; + }(); + + const auto readCode = [](const QString &suffix) -> QString { + const auto filePath = QStringLiteral(":/output.") + suffix; + QFile file(filePath); + if (!file.open(QFile::ReadOnly | QFile::Text)) + qFatal("File open failed: %s", qPrintable(filePath)); + return file.readAll(); + }; + + const auto gl3Code = readCode("gl3"); + const auto es2Code = readCode("es2"); + + Qt3DRender::Render::ShaderBuilder backend; + + // WHEN + const auto graphUrl = QUrl::fromEncoded("qrc:/input.json"); + backend.setShaderGraph(type, graphUrl); + + // THEN + QCOMPARE(backend.shaderGraph(type), graphUrl); + QVERIFY(backend.isShaderCodeDirty(type)); + QVERIFY(backend.shaderCode(type).isEmpty()); + + // WHEN + backend.setGraphicsApi(gl3Api); + backend.generateCode(type); + + // THEN + QCOMPARE(backend.shaderGraph(type), graphUrl); + QVERIFY(!backend.isShaderCodeDirty(type)); + QCOMPARE(backend.shaderCode(type), gl3Code); + + // WHEN + backend.setGraphicsApi(es2Api); + + // THEN + QCOMPARE(backend.shaderGraph(type), graphUrl); + QVERIFY(backend.isShaderCodeDirty(type)); + QCOMPARE(backend.shaderCode(type), gl3Code); + + // WHEN + backend.generateCode(type); + + // THEN + QCOMPARE(backend.shaderGraph(type), graphUrl); + QVERIFY(!backend.isShaderCodeDirty(type)); +// QCOMPARE(backend.shaderCode(type), es2Code); + } +}; + +QTEST_MAIN(tst_ShaderBuilder) + +#include "tst_shaderbuilder.moc" diff --git a/tests/auto/render/skeleton/skeleton.pro b/tests/auto/render/skeleton/skeleton.pro new file mode 100644 index 000000000..8dbd1b3df --- /dev/null +++ b/tests/auto/render/skeleton/skeleton.pro @@ -0,0 +1,13 @@ +TEMPLATE = app + +TARGET = tst_skeleton + +QT += core-private 3dcore 3dcore-private 3drender 3drender-private testlib + +CONFIG += testcase + +SOURCES += \ + tst_skeleton.cpp + +include(../../core/common/common.pri) +include(../commons/commons.pri) diff --git a/tests/auto/render/skeleton/tst_skeleton.cpp b/tests/auto/render/skeleton/tst_skeleton.cpp new file mode 100644 index 000000000..499bb7cc7 --- /dev/null +++ b/tests/auto/render/skeleton/tst_skeleton.cpp @@ -0,0 +1,405 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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$ +** +****************************************************************************/ + +#include <QtTest/QTest> +#include <Qt3DRender/private/skeleton_p.h> +#include <Qt3DRender/private/nodemanagers_p.h> +#include <Qt3DCore/qjoint.h> +#include <Qt3DCore/qskeleton.h> +#include <Qt3DCore/qskeletonloader.h> +#include <Qt3DCore/private/qnode_p.h> +#include <Qt3DCore/private/qscene_p.h> +#include <Qt3DCore/qpropertyupdatedchange.h> +#include <Qt3DCore/private/qbackendnode_p.h> +#include <Qt3DCore/private/qpropertyupdatedchangebase_p.h> +#include <qbackendnodetester.h> +#include <testpostmanarbiter.h> +#include <testrenderer.h> + +using namespace Qt3DCore; +using namespace Qt3DRender; +using namespace Qt3DRender::Render; + +Q_DECLARE_METATYPE(Qt3DRender::Render::JointInfo) +Q_DECLARE_METATYPE(Qt3DRender::Render::SkeletonData) +Q_DECLARE_METATYPE(Qt3DCore::Sqt) + +namespace { + +void linearizeTreeHelper(QJoint *joint, QVector<QJoint *> &joints) +{ + joints.push_back(joint); + for (const auto child : joint->childJoints()) + linearizeTreeHelper(child, joints); +} + +QVector<QJoint *> linearizeTree(QJoint *rootJoint) +{ + QVector<QJoint *> joints; + linearizeTreeHelper(rootJoint, joints); + return joints; +} + +} + +class tst_Skeleton : public Qt3DCore::QBackendNodeTester +{ + Q_OBJECT + +private Q_SLOTS: + void checkPeerPropertyMirroring() + { + // GIVEN + TestRenderer renderer; + NodeManagers nodeManagers; + renderer.setNodeManagers(&nodeManagers); + Skeleton backendSkeleton; + backendSkeleton.setRenderer(&renderer); + backendSkeleton.setSkeletonManager(nodeManagers.skeletonManager()); + QSkeletonLoader skeleton; + + skeleton.setSource(QUrl::fromLocalFile("funnybones.json")); + + // WHEN + simulateInitialization(&skeleton, &backendSkeleton); + + // THEN + QCOMPARE(backendSkeleton.peerId(), skeleton.id()); + QCOMPARE(backendSkeleton.isEnabled(), skeleton.isEnabled()); + QCOMPARE(backendSkeleton.source(), skeleton.source()); + QCOMPARE(backendSkeleton.rootJointId(), QNodeId()); + + // GIVEN + Skeleton backendSkeleton2; + backendSkeleton2.setRenderer(&renderer); + backendSkeleton2.setSkeletonManager(nodeManagers.skeletonManager()); + QSkeleton skeleton2; + + QJoint *joint = new QJoint(); + skeleton2.setRootJoint(joint); + + // WHEN + simulateInitialization(&skeleton2, &backendSkeleton2); + + // THEN + QCOMPARE(backendSkeleton2.peerId(), skeleton2.id()); + QCOMPARE(backendSkeleton2.isEnabled(), skeleton2.isEnabled()); + QCOMPARE(backendSkeleton2.source(), QUrl()); + QCOMPARE(backendSkeleton2.rootJointId(), joint->id()); + } + + void checkInitialAndCleanedUpState() + { + // GIVEN + TestRenderer renderer; + NodeManagers nodeManagers; + renderer.setNodeManagers(&nodeManagers); + Skeleton backendSkeleton; + backendSkeleton.setRenderer(&renderer); + backendSkeleton.setSkeletonManager(nodeManagers.skeletonManager()); + + // THEN + QVERIFY(backendSkeleton.peerId().isNull()); + QCOMPARE(backendSkeleton.isEnabled(), false); + QCOMPARE(backendSkeleton.source(), QUrl()); + QCOMPARE(backendSkeleton.status(), QSkeletonLoader::NotReady); + QCOMPARE(backendSkeleton.rootJointId(), QNodeId()); + + // GIVEN + QSkeletonLoader skeleton; + skeleton.setSource(QUrl::fromLocalFile("skeleton1.json")); + + // WHEN + simulateInitialization(&skeleton, &backendSkeleton); + backendSkeleton.cleanup(); + + // THEN + QCOMPARE(backendSkeleton.source(), QUrl()); + QCOMPARE(backendSkeleton.isEnabled(), false); + QCOMPARE(backendSkeleton.status(), QSkeletonLoader::NotReady); + QCOMPARE(backendSkeleton.rootJointId(), QNodeId()); + } + + void checkPropertyChanges() + { + // GIVEN + TestRenderer renderer; + NodeManagers nodeManagers; + renderer.setNodeManagers(&nodeManagers); + Skeleton backendSkeleton; + backendSkeleton.setRenderer(&renderer); + backendSkeleton.setSkeletonManager(nodeManagers.skeletonManager()); + backendSkeleton.setDataType(Skeleton::File); + Qt3DCore::QPropertyUpdatedChangePtr updateChange; + + // Initialize to ensure skeleton manager is set + QSkeletonLoader skeleton; + skeleton.setSource(QUrl::fromLocalFile("skeleton1.json")); + simulateInitialization(&skeleton, &backendSkeleton); + + // WHEN + updateChange.reset(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId())); + updateChange->setPropertyName("enabled"); + updateChange->setValue(true); + backendSkeleton.sceneChangeEvent(updateChange); + + // THEN + QCOMPARE(backendSkeleton.isEnabled(), true); + + // WHEN + const QUrl newSource = QUrl::fromLocalFile("terminator.json"); + updateChange.reset(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId())); + updateChange->setPropertyName("source"); + updateChange->setValue(newSource); + backendSkeleton.sceneChangeEvent(updateChange); + + // THEN + QCOMPARE(backendSkeleton.source(), newSource); + + // WHEN + const QNodeId newRootJointId = QNodeId::createId(); + updateChange.reset(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId())); + updateChange->setPropertyName("rootJoint"); + updateChange->setValue(QVariant::fromValue(newRootJointId)); + backendSkeleton.sceneChangeEvent(updateChange); + + // THEN + QCOMPARE(backendSkeleton.rootJointId(), newRootJointId); + } + + void checkStatusPropertyBackendNotification() + { + // GIVEN + TestRenderer renderer; + NodeManagers nodeManagers; + renderer.setNodeManagers(&nodeManagers); + TestArbiter arbiter; + Skeleton backendSkeleton; + backendSkeleton.setRenderer(&renderer); + backendSkeleton.setSkeletonManager(nodeManagers.skeletonManager()); + backendSkeleton.setEnabled(true); + Qt3DCore::QBackendNodePrivate::get(&backendSkeleton)->setArbiter(&arbiter); + + // WHEN + backendSkeleton.setStatus(QSkeletonLoader::Error); + + // THEN + QCOMPARE(backendSkeleton.status(), QSkeletonLoader::Error); + QCOMPARE(arbiter.events.count(), 1); + Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "status"); + QCOMPARE(change->value().value<QSkeletonLoader::Status>(), backendSkeleton.status()); + QCOMPARE(Qt3DCore::QPropertyUpdatedChangeBasePrivate::get(change.data())->m_isIntermediate, + false); + + arbiter.events.clear(); + + // WHEN + backendSkeleton.setStatus(QSkeletonLoader::Error); + + // THEN + QCOMPARE(backendSkeleton.status(), QSkeletonLoader::Error); + QCOMPARE(arbiter.events.count(), 0); + + arbiter.events.clear(); + } + + void checkCreateFrontendJoint_data() + { + QTest::addColumn<QMatrix4x4>("inverseBindMatrix"); + QTest::addColumn<Qt3DCore::Sqt>("localPose"); + QTest::addColumn<QString>("jointName"); + QTest::addColumn<QJoint *>("expectedJoint"); + + QMatrix4x4 m; + Qt3DCore::Sqt localPose; + QTest::newRow("default") << m << localPose << QString() << new QJoint(); + + const QVector3D t(1.0f, 2.0f, 3.0f); + const QQuaternion r = QQuaternion::fromAxisAndAngle(1.0f, 0.0f, 0.0f, 45.0f); + const QVector3D s(1.5f, 2.5f, 3.5f); + localPose.scale = s; + localPose.rotation = r; + localPose.translation = t; + + + QString name = QLatin1String("Foo"); + QJoint *joint = new QJoint(); + joint->setTranslation(t); + joint->setRotation(r); + joint->setScale(s); + joint->setName(name); + joint->setInverseBindMatrix(m); + QTest::newRow("localPose") << m << localPose << name << joint; + + m.rotate(r); + m.scale(QVector3D(1.0f, 1.0f, 1.0f) / s); + m.translate(-t); + name = QLatin1String("Bar"); + + joint = new QJoint(); + joint->setTranslation(t); + joint->setRotation(r); + joint->setScale(s); + joint->setInverseBindMatrix(m); + joint->setName(name); + QTest::newRow("inverseBind") << m << localPose << name << joint; + } + + void checkCreateFrontendJoint() + { + // GIVEN + Skeleton backendSkeleton; + QFETCH(QMatrix4x4, inverseBindMatrix); + QFETCH(Qt3DCore::Sqt, localPose); + QFETCH(QString, jointName); + QFETCH(QJoint *, expectedJoint); + + // WHEN + const QJoint *actualJoint = backendSkeleton.createFrontendJoint(jointName, localPose, inverseBindMatrix); + + // THEN + QCOMPARE(actualJoint->scale(), expectedJoint->scale()); + QCOMPARE(actualJoint->rotation(), expectedJoint->rotation()); + QCOMPARE(actualJoint->translation(), expectedJoint->translation()); + QCOMPARE(actualJoint->inverseBindMatrix(), expectedJoint->inverseBindMatrix()); + QCOMPARE(actualJoint->name(), expectedJoint->name()); + + // Cleanup + delete actualJoint; + delete expectedJoint; + } + + void checkCreateFrontendJoints_data() + { + QTest::addColumn<SkeletonData>("skeletonData"); + QTest::addColumn<QJoint *>("expectedRootJoint"); + + QTest::newRow("empty") << SkeletonData() << (QJoint*)nullptr; + + SkeletonData skeletonData; + JointInfo rootJointInfo; + skeletonData.joints.push_back(rootJointInfo); + skeletonData.jointNames.push_back(QLatin1String("rootJoint")); + skeletonData.localPoses.push_back(Qt3DCore::Sqt()); + const int childCount = 10; + for (int i = 0; i < childCount; ++i) { + JointInfo childJointInfo; + childJointInfo.parentIndex = 0; + skeletonData.joints.push_back(childJointInfo); + + const float x = static_cast<float>(i); + Qt3DCore::Sqt localPose; + localPose.translation = QVector3D(x, x, x); + skeletonData.localPoses.push_back(localPose); + + skeletonData.jointNames.push_back(QString("Child-%1").arg(i)); + } + + QJoint *rootJoint = new QJoint(); + for (int i = 0; i < childCount; ++i) { + QJoint *childJoint = new QJoint(); + const float x = static_cast<float>(i); + childJoint->setTranslation(QVector3D(x, x, x)); + rootJoint->addChildJoint(childJoint); + } + + QTest::newRow("wide") << skeletonData << rootJoint; + + skeletonData.joints.clear(); + skeletonData.joints.push_back(rootJointInfo); + for (int i = 0; i < childCount; ++i) { + JointInfo childJointInfo; + childJointInfo.parentIndex = i; + skeletonData.joints.push_back(childJointInfo); + + const float x = static_cast<float>(i); + Qt3DCore::Sqt localPose; + localPose.translation = QVector3D(x, x, x); + skeletonData.localPoses.push_back(localPose); + + skeletonData.jointNames.push_back(QString("Child-%1").arg(i)); + } + + rootJoint = new QJoint(); + QJoint *previousJoint = rootJoint; + for (int i = 0; i < childCount; ++i) { + QJoint *childJoint = new QJoint(); + const float x = static_cast<float>(i); + childJoint->setTranslation(QVector3D(x, x, x)); + previousJoint->addChildJoint(childJoint); + previousJoint = childJoint; + } + + QTest::newRow("deep") << skeletonData << rootJoint; + } + + void checkCreateFrontendJoints() + { + // GIVEN + Skeleton backendSkeleton; + QFETCH(SkeletonData, skeletonData); + QFETCH(QJoint *, expectedRootJoint); + + // WHEN + QJoint *actualRootJoint = backendSkeleton.createFrontendJoints(skeletonData); + + // THEN + if (skeletonData.joints.isEmpty()) { + QVERIFY(actualRootJoint == expectedRootJoint); // nullptr + return; + } + + // Linearise the tree of joints and check them against the skeletonData + QVector<QJoint *> joints = linearizeTree(actualRootJoint); + QCOMPARE(joints.size(), skeletonData.joints.size()); + for (int i = 0; i < joints.size(); ++i) { + // Check the translations match + QCOMPARE(joints[i]->translation(), skeletonData.localPoses[i].translation); + } + + // Now we know the order of Joints match. Check the parents match too + for (int i = 0; i < joints.size(); ++i) { + // Get parent index from joint info + const int parentIndex = skeletonData.joints[i].parentIndex; + if (parentIndex == -1) { + QVERIFY(joints[i]->parent() == nullptr); + } else { + QCOMPARE(joints[i]->parent(), joints[parentIndex]); + } + } + + // Cleanup + delete actualRootJoint; + delete expectedRootJoint; + } +}; + +QTEST_APPLESS_MAIN(tst_Skeleton) + +#include "tst_skeleton.moc" diff --git a/tests/auto/render/texture/tst_texture.cpp b/tests/auto/render/texture/tst_texture.cpp index 9a84714a6..784186690 100644 --- a/tests/auto/render/texture/tst_texture.cpp +++ b/tests/auto/render/texture/tst_texture.cpp @@ -223,6 +223,8 @@ void tst_RenderTexture::checkPropertyChanges() // THEN QCOMPARE(backend.properties().width, 256); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::TexturesDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); // WHEN updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId()); @@ -232,6 +234,8 @@ void tst_RenderTexture::checkPropertyChanges() // THEN QCOMPARE(backend.properties().height, 128); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::TexturesDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); // WHEN updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId()); @@ -241,6 +245,8 @@ void tst_RenderTexture::checkPropertyChanges() // THEN QCOMPARE(backend.properties().depth, 16); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::TexturesDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); // WHEN updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId()); @@ -250,6 +256,8 @@ void tst_RenderTexture::checkPropertyChanges() // THEN QCOMPARE(backend.properties().layers, 32); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::TexturesDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); // WHEN updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId()); @@ -259,6 +267,8 @@ void tst_RenderTexture::checkPropertyChanges() // THEN QCOMPARE(backend.properties().samples, 64); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::TexturesDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); } QTEST_APPLESS_MAIN(tst_RenderTexture) diff --git a/tests/auto/render/transform/tst_transform.cpp b/tests/auto/render/transform/tst_transform.cpp index 26916b2ab..ebb27953d 100644 --- a/tests/auto/render/transform/tst_transform.cpp +++ b/tests/auto/render/transform/tst_transform.cpp @@ -127,6 +127,8 @@ private Q_SLOTS: // THEN QCOMPARE(backendTransform.isEnabled(), newValue); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::TransformDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); } { // WHEN @@ -138,6 +140,8 @@ private Q_SLOTS: // THEN QCOMPARE(backendTransform.rotation(), newValue); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::TransformDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); } { // WHEN @@ -149,6 +153,8 @@ private Q_SLOTS: // THEN QCOMPARE(backendTransform.scale(), newValue); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::TransformDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); } { // WHEN @@ -160,6 +166,8 @@ private Q_SLOTS: // THEN QCOMPARE(backendTransform.translation(), newValue); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::TransformDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); } } diff --git a/tests/auto/render/trianglevisitor/tst_trianglevisitor.cpp b/tests/auto/render/trianglevisitor/tst_trianglevisitor.cpp index 1e76751cc..9b6481423 100644 --- a/tests/auto/render/trianglevisitor/tst_trianglevisitor.cpp +++ b/tests/auto/render/trianglevisitor/tst_trianglevisitor.cpp @@ -191,8 +191,8 @@ private Q_SLOTS: positionAttribute->setBuffer(dataBuffer.data()); positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName()); - positionAttribute->setDataType(Qt3DRender::QAttribute::Float); - positionAttribute->setDataSize(3); + positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float); + positionAttribute->setVertexSize(3); positionAttribute->setCount(6); positionAttribute->setByteStride(3*4); positionAttribute->setByteOffset(0); @@ -291,15 +291,15 @@ private Q_SLOTS: positionAttribute->setBuffer(dataBuffer.data()); positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName()); - positionAttribute->setDataType(Qt3DRender::QAttribute::Float); - positionAttribute->setDataSize(3); + positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float); + positionAttribute->setVertexSize(3); positionAttribute->setCount(6); positionAttribute->setByteStride(3*sizeof(float)); positionAttribute->setByteOffset(0); positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute); indexAttribute->setBuffer(indexDataBuffer.data()); - indexAttribute->setDataType(Qt3DRender::QAttribute::UnsignedInt); + indexAttribute->setVertexBaseType(Qt3DRender::QAttribute::UnsignedInt); indexAttribute->setCount(3*5); indexAttribute->setAttributeType(Qt3DRender::QAttribute::IndexAttribute); @@ -378,8 +378,8 @@ private Q_SLOTS: positionAttribute->setBuffer(dataBuffer.data()); positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName()); - positionAttribute->setDataType(Qt3DRender::QAttribute::Float); - positionAttribute->setDataSize(3); + positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float); + positionAttribute->setVertexSize(3); positionAttribute->setCount(6); positionAttribute->setByteStride(3*4); positionAttribute->setByteOffset(0); @@ -477,15 +477,15 @@ private Q_SLOTS: positionAttribute->setBuffer(dataBuffer.data()); positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName()); - positionAttribute->setDataType(Qt3DRender::QAttribute::Float); - positionAttribute->setDataSize(3); + positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float); + positionAttribute->setVertexSize(3); positionAttribute->setCount(6); positionAttribute->setByteStride(3*sizeof(float)); positionAttribute->setByteOffset(0); positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute); indexAttribute->setBuffer(indexDataBuffer.data()); - indexAttribute->setDataType(Qt3DRender::QAttribute::UnsignedInt); + indexAttribute->setVertexBaseType(Qt3DRender::QAttribute::UnsignedInt); indexAttribute->setCount(3*4); indexAttribute->setAttributeType(Qt3DRender::QAttribute::IndexAttribute); @@ -567,8 +567,8 @@ private Q_SLOTS: positionAttribute->setBuffer(dataBuffer.data()); positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName()); - positionAttribute->setDataType(Qt3DRender::QAttribute::Float); - positionAttribute->setDataSize(3); + positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float); + positionAttribute->setVertexSize(3); positionAttribute->setCount(6); positionAttribute->setByteStride(3*4); positionAttribute->setByteOffset(0); @@ -660,15 +660,15 @@ private Q_SLOTS: positionAttribute->setBuffer(dataBuffer.data()); positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName()); - positionAttribute->setDataType(Qt3DRender::QAttribute::Float); - positionAttribute->setDataSize(3); + positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float); + positionAttribute->setVertexSize(3); positionAttribute->setCount(6); positionAttribute->setByteStride(3*sizeof(float)); positionAttribute->setByteOffset(0); positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute); indexAttribute->setBuffer(indexDataBuffer.data()); - indexAttribute->setDataType(Qt3DRender::QAttribute::UnsignedInt); + indexAttribute->setVertexBaseType(Qt3DRender::QAttribute::UnsignedInt); indexAttribute->setCount(3*2); indexAttribute->setAttributeType(Qt3DRender::QAttribute::IndexAttribute); @@ -746,8 +746,8 @@ private Q_SLOTS: positionAttribute->setBuffer(dataBuffer.data()); positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName()); - positionAttribute->setDataType(Qt3DRender::QAttribute::Float); - positionAttribute->setDataSize(3); + positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float); + positionAttribute->setVertexSize(3); positionAttribute->setCount(6); positionAttribute->setByteStride(3*4); positionAttribute->setByteOffset(0); @@ -843,15 +843,15 @@ private Q_SLOTS: positionAttribute->setBuffer(dataBuffer.data()); positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName()); - positionAttribute->setDataType(Qt3DRender::QAttribute::Float); - positionAttribute->setDataSize(3); + positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float); + positionAttribute->setVertexSize(3); positionAttribute->setCount(6); positionAttribute->setByteStride(3*sizeof(float)); positionAttribute->setByteOffset(0); positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute); indexAttribute->setBuffer(indexDataBuffer.data()); - indexAttribute->setDataType(Qt3DRender::QAttribute::UnsignedInt); + indexAttribute->setVertexBaseType(Qt3DRender::QAttribute::UnsignedInt); indexAttribute->setCount(3*4); indexAttribute->setAttributeType(Qt3DRender::QAttribute::IndexAttribute); @@ -940,8 +940,8 @@ private Q_SLOTS: positionAttribute->setBuffer(dataBuffer.data()); positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName()); - positionAttribute->setDataType(Qt3DRender::QAttribute::Float); - positionAttribute->setDataSize(3); + positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float); + positionAttribute->setVertexSize(3); positionAttribute->setCount(8); positionAttribute->setByteStride(3*4); positionAttribute->setByteOffset(0); @@ -1034,15 +1034,15 @@ private Q_SLOTS: positionAttribute->setBuffer(dataBuffer.data()); positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName()); - positionAttribute->setDataType(Qt3DRender::QAttribute::Float); - positionAttribute->setDataSize(3); + positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float); + positionAttribute->setVertexSize(3); positionAttribute->setCount(6); positionAttribute->setByteStride(3*sizeof(float)); positionAttribute->setByteOffset(0); positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute); indexAttribute->setBuffer(indexDataBuffer.data()); - indexAttribute->setDataType(Qt3DRender::QAttribute::UnsignedInt); + indexAttribute->setVertexBaseType(Qt3DRender::QAttribute::UnsignedInt); indexAttribute->setCount(8); indexAttribute->setAttributeType(Qt3DRender::QAttribute::IndexAttribute); diff --git a/tests/auto/render/uniform/tst_uniform.cpp b/tests/auto/render/uniform/tst_uniform.cpp index 47e64eafe..b8578b294 100644 --- a/tests/auto/render/uniform/tst_uniform.cpp +++ b/tests/auto/render/uniform/tst_uniform.cpp @@ -123,6 +123,26 @@ private Q_SLOTS: QCOMPARE(v.constData<float>()[2], 1340.0f); QCOMPARE(v.constData<float>()[3], 1603.0f); } + { + // GIVEN + const QMatrix4x4 m1; + QMatrix4x4 m2; + m2.rotate(90.0f, 1.0f, 0.0f, 0.0f); + QMatrix4x4 m3; + m3.scale(2.5f); + QMatrix4x4 m4; + m4.translate(1.0f, 2.0f, 3.0f); + + const QVector<QMatrix4x4> matrices = (QVector<QMatrix4x4>() << m1 << m2 << m3 << m4); + UniformValue v(matrices); + + // THEN + for (int j = 0; j < matrices.size(); ++j) { + for (int i = 0; i < 16; ++i) { + QCOMPARE(v.constData<float>()[16 * j + i], matrices[j].constData()[i]); + } + } + } } void checkFromVariant() @@ -345,6 +365,51 @@ private Q_SLOTS: QVERIFY(!(v1 == v2)); QVERIFY(v1 != v2); } + + void checkSetData() + { + // GIVEN + const QMatrix4x4 m1; + QMatrix4x4 m2; + m2.rotate(90.0f, 1.0f, 0.0f, 0.0f); + QMatrix4x4 m3; + m3.scale(2.5f); + QMatrix4x4 m4; + m4.translate(1.0f, 2.0f, 3.0f); + + const QVector<QMatrix4x4> matrices1 = (QVector<QMatrix4x4>() << m1 << m2 << m3 << m4); + UniformValue v(matrices1); + + // WHEN + const QVector<QMatrix4x4> matrices2 = (QVector<QMatrix4x4>() << m4 << m3 << m2 << m1 << m4); + v.setData(matrices2); + + // THEN + for (int j = 0; j < matrices2.size(); ++j) { + for (int i = 0; i < 16; ++i) { + QCOMPARE(v.constData<float>()[16 * j + i], matrices2[j].constData()[i]); + } + } + + // GIVEN + const int positionCount = 10; + QVector<QVector3D> positions(positionCount); + for (int i = 0; i < positionCount; ++i) { + const QVector3D p(float(i), 10.0f * i, 100.0f * i); + positions[i] = p; + } + + UniformValue positionsUniform; + + // WHEN + positionsUniform.setData(positions); + + // THEN + const QVector3D *data = positionsUniform.constData<QVector3D>(); + for (int i = 0; i < positionCount; ++i) { + QCOMPARE(*(data + i), positions[i]); + } + } }; |