diff options
author | Wieland Hagen <wieland.hagen@kdab.com> | 2017-07-21 12:12:30 +0200 |
---|---|---|
committer | Wieland Hagen <wieland.hagen@kdab.com> | 2017-08-03 15:57:06 +0000 |
commit | 6e71be0630da0a7c9e460ed7adda8ed7ac7434f6 (patch) | |
tree | eba7f40e0f51e60c2d1ca0580cec3165d2be22cc | |
parent | 176f088c540fc17ebc6f18b436017b1975edf511 (diff) |
Add QRenderState unit test
Backend nodes should receive frontend proeperty changes
Change-Id: I19ba70d08de833aab467a51d5b21553f0b602ec6
Reviewed-by: Sean Harmer <sean.harmer@kdab.com>
-rw-r--r-- | src/render/renderstates/statevariant_p.h | 2 | ||||
-rw-r--r-- | tests/auto/render/qrenderstate/qrenderstate.pro | 12 | ||||
-rw-r--r-- | tests/auto/render/qrenderstate/tst_qrenderstate.cpp | 300 | ||||
-rw-r--r-- | tests/auto/render/render.pro | 1 |
4 files changed, 314 insertions, 1 deletions
diff --git a/src/render/renderstates/statevariant_p.h b/src/render/renderstates/statevariant_p.h index e13599e75..7f118d229 100644 --- a/src/render/renderstates/statevariant_p.h +++ b/src/render/renderstates/statevariant_p.h @@ -58,7 +58,7 @@ QT_BEGIN_NAMESPACE namespace Qt3DRender { namespace Render { -struct StateVariant +struct Q_AUTOTEST_EXPORT StateVariant { StateMask type; diff --git a/tests/auto/render/qrenderstate/qrenderstate.pro b/tests/auto/render/qrenderstate/qrenderstate.pro new file mode 100644 index 000000000..60bdfef01 --- /dev/null +++ b/tests/auto/render/qrenderstate/qrenderstate.pro @@ -0,0 +1,12 @@ +TEMPLATE = app + +TARGET = tst_qrenderstate + +QT += core-private 3dcore 3dcore-private 3drender 3drender-private testlib + +CONFIG += testcase + +SOURCES += tst_qrenderstate.cpp + +include(../../core/common/common.pri) +include(../commons/commons.pri) diff --git a/tests/auto/render/qrenderstate/tst_qrenderstate.cpp b/tests/auto/render/qrenderstate/tst_qrenderstate.cpp new file mode 100644 index 000000000..6e90f4ce1 --- /dev/null +++ b/tests/auto/render/qrenderstate/tst_qrenderstate.cpp @@ -0,0 +1,300 @@ +/**************************************************************************** +** +** 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 <testrenderer.h> + +#include <Qt3DCore/private/qscene_p.h> +#include <Qt3DRender/private/renderstatenode_p.h> +#include <Qt3DRender/private/managers_p.h> + +#include <Qt3DRender/QRenderState> +#include <Qt3DRender/QAlphaCoverage> +#include <Qt3DRender/QAlphaTest> +#include <Qt3DRender/QBlendEquation> +#include <Qt3DRender/QBlendEquationArguments> +#include <Qt3DRender/QColorMask> +#include <Qt3DRender/QCullFace> +#include <Qt3DRender/QDepthTest> +#include <Qt3DRender/QDithering> +#include <Qt3DRender/QFrontFace> +#include <Qt3DRender/QPointSize> +#include <Qt3DRender/QPolygonOffset> +#include <Qt3DRender/QScissorTest> +#include <Qt3DRender/QStencilTest> +#include <Qt3DRender/QStencilTestArguments> +#include <Qt3DRender/QStencilMask> +#include <Qt3DRender/QStencilOperation> +#include <Qt3DRender/QStencilOperationArguments> +#include <Qt3DRender/QClipPlane> + +#include "testpostmanarbiter.h" + +using namespace Qt3DCore; +using namespace Qt3DRender; +using namespace Qt3DRender::Render; + +class tst_QRenderState : public QBackendNodeTester +{ + Q_OBJECT +public: + tst_QRenderState() {} + ~tst_QRenderState() {} + +private: + RenderStateManager m_renderStateManager; + TestRenderer m_renderer; + + RenderStateNode* createBackendNode(QRenderState *frontend) + { + RenderStateNode *backend = m_renderStateManager.getOrCreateResource(frontend->id()); + simulateInitialization(frontend, backend); + backend->setRenderer(&m_renderer); + return backend; + } + + // Create two frontend objects of class T and set given property to v1 / v2 respectively + template <class T, class V, class Setter> + void addTestCase(Qt3DRender::Render::StateMask mask, const char *property, Setter setter, V v1, V v2) + { + T *obj1 = new T(); + T *obj2 = new T(); + + (obj1->*(setter))(v1); + (obj2->*(setter))(v2); + + QTest::addRow("%s::%s", obj1->metaObject()->className(), property) + << (QRenderState*) obj1 + << (QRenderState*) obj2 + << (quint64) mask + << QString(property) + << QVariant(v2); + } + + // Create two frontend objects of class T and set given property to v1 / v2 respectively, for the specified arguments sub-object + template <class T, class Args, class V, class Setter> + void addStencilTestCase(Qt3DRender::Render::StateMask mask, const char *argsName, const char *property, Setter setter, V v1, V v2) + { + T *obj1 = new T(); + T *obj2 = new T(); + + const QMetaObject *metaObj = obj1->metaObject(); + const int pIndex = metaObj->indexOfProperty(argsName); + const QMetaProperty prop = metaObj->property(pIndex); + Args *args1 = qvariant_cast<Args*>(prop.read(obj1)); + Args *args2 = qvariant_cast<Args*>(prop.read(obj2)); + + (args1->*(setter))(v1); + (args2->*(setter))(v2); + + QTest::addRow("%s::%s::%s", metaObj->className(), argsName, property) + << (QRenderState*) obj1 + << (QObject*) args1 + << (QRenderState*) obj2 + << (quint64) mask + << QString(property) + << QVariant(v2); + } + +private Q_SLOTS: + + void checkPropertyUpdates_data() + { + QTest::addColumn<QRenderState *>("frontend1"); + QTest::addColumn<QRenderState *>("frontend2"); + QTest::addColumn<quint64>("mask"); + QTest::addColumn<QString>("propertyName"); + QTest::addColumn<QVariant>("value"); + + addTestCase<QAlphaTest>(AlphaTestMask, "alphaFunction", &QAlphaTest::setAlphaFunction, QAlphaTest::Always, QAlphaTest::LessOrEqual); + addTestCase<QAlphaTest>(AlphaTestMask, "referenceValue", &QAlphaTest::setReferenceValue, 0.f, 1.f); + + addTestCase<QBlendEquation>(BlendStateMask, "blendFunction", &QBlendEquation::setBlendFunction, QBlendEquation::Add, QBlendEquation::Subtract); + + addTestCase<QBlendEquationArguments>(BlendEquationArgumentsMask, "sourceRgb", &QBlendEquationArguments::setSourceRgb, QBlendEquationArguments::Zero, QBlendEquationArguments::One); + addTestCase<QBlendEquationArguments>(BlendEquationArgumentsMask, "sourceAlpha", &QBlendEquationArguments::setSourceAlpha, QBlendEquationArguments::SourceAlpha, QBlendEquationArguments::OneMinusSource1Color); + addTestCase<QBlendEquationArguments>(BlendEquationArgumentsMask, "destinationRgb", &QBlendEquationArguments::setDestinationRgb, QBlendEquationArguments::DestinationColor, QBlendEquationArguments::OneMinusSourceAlpha); + addTestCase<QBlendEquationArguments>(BlendEquationArgumentsMask, "destinationAlpha", &QBlendEquationArguments::setDestinationAlpha, QBlendEquationArguments::DestinationAlpha, QBlendEquationArguments::DestinationColor); + addTestCase<QBlendEquationArguments>(BlendEquationArgumentsMask, "bufferIndex", &QBlendEquationArguments::setBufferIndex, 0, 1); + + addTestCase<QClipPlane>(ClipPlaneMask, "planeIndex", &QClipPlane::setPlaneIndex, 0, 1); + addTestCase<QClipPlane>(ClipPlaneMask, "normal", &QClipPlane::setNormal, QVector3D(0, 1, 0), QVector3D(0, 0, 1)); + addTestCase<QClipPlane>(ClipPlaneMask, "distance", &QClipPlane::setDistance, 1.f, 2.f); + + addTestCase<QColorMask>(ColorStateMask, "redMasked", &QColorMask::setRedMasked, false, true); + addTestCase<QColorMask>(ColorStateMask, "blueMasked", &QColorMask::setBlueMasked, false, true); + addTestCase<QColorMask>(ColorStateMask, "greenMasked", &QColorMask::setGreenMasked, false, true); + addTestCase<QColorMask>(ColorStateMask, "alphaMasked", &QColorMask::setAlphaMasked, false, true); + + addTestCase<QCullFace>(CullFaceStateMask, "mode", &QCullFace::setMode, QCullFace::Back, QCullFace::FrontAndBack); + + addTestCase<QFrontFace>(FrontFaceStateMask, "direction", &QFrontFace::setDirection, QFrontFace::ClockWise, QFrontFace::CounterClockWise); + + addTestCase<QPointSize>(PointSizeMask, "sizeMode", &QPointSize::setSizeMode, QPointSize::Programmable, QPointSize::Fixed); + addTestCase<QPointSize>(PointSizeMask, "value", &QPointSize::setValue, 2.f, 4.f); + + addTestCase<QPolygonOffset>(PolygonOffsetStateMask, "scaleFactor", &QPolygonOffset::setScaleFactor, 1.f, 2.f); + addTestCase<QPolygonOffset>(PolygonOffsetStateMask, "depthSteps", &QPolygonOffset::setDepthSteps, 1.f, 2.f); + + addTestCase<QScissorTest>(ScissorStateMask, "left", &QScissorTest::setLeft, 10, 20); + addTestCase<QScissorTest>(ScissorStateMask, "bottom", &QScissorTest::setBottom, 10, 20); + addTestCase<QScissorTest>(ScissorStateMask, "width", &QScissorTest::setWidth, 10, 20); + addTestCase<QScissorTest>(ScissorStateMask, "height", &QScissorTest::setHeight, 10, 20); + + addTestCase<QStencilMask>(StencilWriteStateMask, "frontOutputMask", &QStencilMask::setFrontOutputMask, 0x12, 0x34); + addTestCase<QStencilMask>(StencilWriteStateMask, "backOutputMask", &QStencilMask::setBackOutputMask, 0x12, 0x34); + } + + void checkPropertyUpdates() + { + // GIVEN + QFETCH(QRenderState*, frontend1); + QFETCH(QRenderState*, frontend2); + QFETCH(quint64, mask); + QFETCH(QString, propertyName); + QFETCH(QVariant, value); + + // THEN + RenderStateNode *backend1 = createBackendNode(frontend1); + RenderStateNode *backend2 = createBackendNode(frontend2); + QVERIFY(backend1->mask() == mask); + QVERIFY(backend2->mask() == mask); + QVERIFY(backend1->impl() != backend2->impl()); + + // WHEN + TestArbiter arbiter; + arbiter.setArbiterOnNode(frontend1); + const QMetaObject *metaObj = frontend1->metaObject(); + const int pIndex = metaObj->indexOfProperty(propertyName.toStdString().c_str()); + metaObj->property(pIndex).write(frontend1, value); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<QPropertyUpdatedChange>(); + QVERIFY(change->propertyName() == propertyName); + QCOMPARE(change->subjectId(), frontend1->id()); + + // WHEN + backend1->sceneChangeEvent(change.staticCast<QSceneChange>()); + + // THEN + QVERIFY(backend1->impl() == backend2->impl()); + + arbiter.events.clear(); + } + + void checkStencilUpdates_data() + { + QTest::addColumn<QRenderState *>("frontend1"); + QTest::addColumn<QObject *>("args1"); + QTest::addColumn<QRenderState *>("frontend2"); + QTest::addColumn<quint64>("mask"); + QTest::addColumn<QString>("propertyName"); + QTest::addColumn<QVariant>("value"); + + qRegisterMetaType<QStencilOperationArguments*>("QStencilOperationArguments*"); + qRegisterMetaType<QStencilTestArguments*>("QStencilTestArguments*"); + + for (bool front : QVector<bool>{false, true}) { + const char *argsProperty = front ? "front" : "back"; + + addStencilTestCase<QStencilOperation, QStencilOperationArguments>( + StencilOpMask, argsProperty, "allTestsPassOperation", + &QStencilOperationArguments::setAllTestsPassOperation, + QStencilOperationArguments::Zero, QStencilOperationArguments::Keep); + + addStencilTestCase<QStencilOperation, QStencilOperationArguments>( + StencilOpMask, argsProperty, "depthTestFailureOperation", + &QStencilOperationArguments::setDepthTestFailureOperation, + QStencilOperationArguments::Replace, QStencilOperationArguments::Zero); + + addStencilTestCase<QStencilOperation, QStencilOperationArguments>( + StencilOpMask, argsProperty, "stencilTestFailureOperation", + &QStencilOperationArguments::setStencilTestFailureOperation, + QStencilOperationArguments::Increment, QStencilOperationArguments::Decrement); + + addStencilTestCase<QStencilTest, QStencilTestArguments>( + StencilTestStateMask, argsProperty, "comparisonMask", + &QStencilTestArguments::setComparisonMask, 0x12, 0x34); + + addStencilTestCase<QStencilTest, QStencilTestArguments>( + StencilTestStateMask, argsProperty, "referenceValue", + &QStencilTestArguments::setReferenceValue, 1, 2); + + addStencilTestCase<QStencilTest, QStencilTestArguments>( + StencilTestStateMask, argsProperty, "stencilFunction", + &QStencilTestArguments::setStencilFunction, + QStencilTestArguments::Always, QStencilTestArguments::Equal); + } + } + + void checkStencilUpdates() + { + // GIVEN + QFETCH(QRenderState*, frontend1); + QFETCH(QObject*, args1); + QFETCH(QRenderState*, frontend2); + QFETCH(quint64, mask); + QFETCH(QString, propertyName); + QFETCH(QVariant, value); + + // THEN + RenderStateNode *backend1 = createBackendNode(frontend1); + RenderStateNode *backend2 = createBackendNode(frontend2); + QVERIFY(backend1->mask() == mask); + QVERIFY(backend2->mask() == mask); + QVERIFY(backend1->impl() != backend2->impl()); + + // WHEN + TestArbiter arbiter; + arbiter.setArbiterOnNode(frontend1); + const QMetaObject *metaObj = args1->metaObject(); + const int pIndex = metaObj->indexOfProperty(propertyName.toStdString().c_str()); + metaObj->property(pIndex).write(args1, value); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<QPropertyUpdatedChange>(); + QCOMPARE(change->subjectId(), frontend1->id()); + + // WHEN + backend1->sceneChangeEvent(change.staticCast<QSceneChange>()); + + // THEN + QVERIFY(backend1->impl() == backend2->impl()); + + arbiter.events.clear(); + } +}; + +QTEST_MAIN(tst_QRenderState) + +#include "tst_qrenderstate.moc" diff --git a/tests/auto/render/render.pro b/tests/auto/render/render.pro index 8eea3d032..5a82ee835 100644 --- a/tests/auto/render/render.pro +++ b/tests/auto/render/render.pro @@ -34,6 +34,7 @@ qtConfig(private_tests) { qenvironmentlight \ qray3d \ qrenderpassfilter \ + qrenderstate \ qrendertargetselector \ qsortpolicy \ qrenderstateset \ |