aboutsummaryrefslogtreecommitdiffstats
path: root/tests/auto/quick/rendernode/tst_rendernode.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/quick/rendernode/tst_rendernode.cpp')
-rw-r--r--tests/auto/quick/rendernode/tst_rendernode.cpp554
1 files changed, 289 insertions, 265 deletions
diff --git a/tests/auto/quick/rendernode/tst_rendernode.cpp b/tests/auto/quick/rendernode/tst_rendernode.cpp
index 87d710ee47..b21c1f01b1 100644
--- a/tests/auto/quick/rendernode/tst_rendernode.cpp
+++ b/tests/auto/quick/rendernode/tst_rendernode.cpp
@@ -1,367 +1,391 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the test suite 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QtQuick/qquickitem.h>
#include <QtQuick/qquickview.h>
-#include <qopenglcontext.h>
-#include <qopenglfunctions.h>
-#include <QtGui/qscreen.h>
#include <private/qsgrendernode_p.h>
+#include <rhi/qrhi.h>
-#include "../../shared/util.h"
+#include <QtQuickTestUtils/private/qmlutils_p.h>
+
+#if QT_CONFIG(opengl)
+#include <QOpenGLContext>
+#include <QOpenGLFunctions>
+#endif
class tst_rendernode: public QQmlDataTest
{
Q_OBJECT
+
public:
tst_rendernode();
- QImage runTest(const QString &fileName)
- {
- QQuickView view(&outerWindow);
- view.setResizeMode(QQuickView::SizeViewToRootObject);
- view.setSource(testFileUrl(fileName));
- view.setVisible(true);
- return QTest::qWaitForWindowExposed(&view) ? view.grabWindow() : QImage();
- }
-
- //It is important for platforms that only are able to show fullscreen windows
- //to have a container for the window that is painted on.
- QQuickWindow outerWindow;
-
private slots:
- void renderOrder();
- void messUpState();
- void matrix();
+ void test_data();
+ void test();
+#if QT_CONFIG(opengl)
+ void gltest_data();
+ void gltest();
+#endif
private:
+ QQuickView *createView(const QString &file, QWindow *parent, int x, int y, int w, int h);
bool isRunningOnRhi() const;
};
-class ClearNode : public QSGRenderNode
+static QShader getShader(const QString &name)
+{
+ QFile f(name);
+ if (f.open(QIODevice::ReadOnly))
+ return QShader::fromSerialized(f.readAll());
+
+ return QShader();
+}
+
+// *****
+// * *
+// * *
+// *
+// assumes the top-left scenegraph coordinate system, will be scaled to the item size
+static float vertexData[] = {
+ 0, 0, 0, 0, 1, // blue
+ 0, 1, 0, 0, 1,
+ 1, 0, 0, 0, 1
+};
+
+class SimpleNode : public QSGRenderNode
{
public:
+ SimpleNode(QQuickWindow *window)
+ : m_window(window)
+ {
+ }
+
StateFlags changedStates() const override
{
- return ColorState;
+ return ViewportState; // nothing else matters in Qt 6
+ }
+
+ RenderingFlags flags() const override
+ {
+ // this node uses QRhi directly and is also well behaving depth-wise
+ return NoExternalRendering | DepthAwareRendering;
+ }
+
+ void prepare() override
+ {
+ QSGRendererInterface *rif = m_window->rendererInterface();
+ QRhi *rhi = static_cast<QRhi *>(rif->getResource(m_window, QSGRendererInterface::RhiResource));
+ QVERIFY(rhi);
+
+ QSGRenderNodePrivate *d = QSGRenderNodePrivate::get(this);
+ QRhiRenderTarget *rt = d->m_rt.rt;
+ QRhiCommandBuffer *cb = d->m_rt.cb;
+
+ QRhiResourceUpdateBatch *u = rhi->nextResourceUpdateBatch();
+
+ if (!m_vbuf) {
+ m_vbuf.reset(rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertexData)));
+ QVERIFY(m_vbuf->create());
+ u->uploadStaticBuffer(m_vbuf.data(), vertexData);
+ }
+
+ if (!m_ubuf) {
+ m_ubuf.reset(rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 68));
+ QVERIFY(m_ubuf->create());
+ }
+
+ if (!m_srb) {
+ m_srb.reset(rhi->newShaderResourceBindings());
+ m_srb->setBindings({
+ QRhiShaderResourceBinding::uniformBuffer(0,
+ QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage,
+ m_ubuf.get())
+ });
+ m_srb->create();
+ }
+
+ if (!m_ps) {
+ m_ps.reset(rhi->newGraphicsPipeline());
+
+ const QShader vs = getShader(QLatin1String(":/shaders/color.vert.qsb"));
+ if (!vs.isValid())
+ qFatal("Failed to load shader pack (vertex)");
+ const QShader fs = getShader(QLatin1String(":/shaders/color.frag.qsb"));
+ if (!fs.isValid())
+ qFatal("Failed to load shader pack (fragment)");
+
+ m_ps->setShaderStages({
+ { QRhiShaderStage::Vertex, vs },
+ { QRhiShaderStage::Fragment, fs }
+ });
+
+ m_ps->setCullMode(QRhiGraphicsPipeline::Back);
+ // important to test against what's already in the depth buffer from the opaque pass
+ m_ps->setDepthTest(true);
+ m_ps->setDepthOp(QRhiGraphicsPipeline::LessOrEqual);
+ // we are in the alpha pass always so not writing out the depth
+ m_ps->setDepthWrite(false);
+
+ QRhiVertexInputLayout inputLayout;
+ inputLayout.setBindings({
+ { 5 * sizeof(float) }
+ });
+ inputLayout.setAttributes({
+ { 0, 0, QRhiVertexInputAttribute::Float2, 0 },
+ { 0, 1, QRhiVertexInputAttribute::Float3, 2 * sizeof(float) }
+ });
+
+ m_ps->setVertexInputLayout(inputLayout);
+ m_ps->setShaderResourceBindings(m_srb.data());
+ m_ps->setRenderPassDescriptor(rt->renderPassDescriptor());
+
+ QVERIFY(m_ps->create());
+ }
+
+ // follow what the scenegraph tells us, hence DepthAwareRendering from
+ // flags, the downside is that we are stuck with the scenegraph
+ // coordinate system but that's enough for this test.
+ QMatrix4x4 mvp = *projectionMatrix() * *matrix();
+
+ mvp.scale(m_itemSize.width(), m_itemSize.height());
+ u->updateDynamicBuffer(m_ubuf.data(), 0, 64, mvp.constData());
+
+ const float opacity = inheritedOpacity();
+ u->updateDynamicBuffer(m_ubuf.data(), 64, 4, &opacity);
+
+ cb->resourceUpdate(u);
}
void render(const RenderState *) override
{
- // If clip has been set, scissoring will make sure the right area is cleared.
- QOpenGLContext::currentContext()->functions()->glClearColor(color.redF(), color.greenF(), color.blueF(), 1.0f);
- QOpenGLContext::currentContext()->functions()->glClear(GL_COLOR_BUFFER_BIT);
+ QSGRenderNodePrivate *d = QSGRenderNodePrivate::get(this);
+ QRhiRenderTarget *rt = d->m_rt.rt;
+ QRhiCommandBuffer *cb = d->m_rt.cb;
+
+ cb->setGraphicsPipeline(m_ps.data());
+ cb->setViewport({ 0, 0, float(rt->pixelSize().width()), float(rt->pixelSize().height()) });
+ cb->setShaderResources();
+ const QRhiCommandBuffer::VertexInput vbufBinding(m_vbuf.get(), 0);
+ cb->setVertexInput(0, 1, &vbufBinding);
+ cb->draw(3);
}
- QColor color;
+ QQuickWindow *m_window;
+ QScopedPointer<QRhiBuffer> m_vbuf;
+ QScopedPointer<QRhiBuffer> m_ubuf;
+ QScopedPointer<QRhiShaderResourceBindings> m_srb;
+ QScopedPointer<QRhiGraphicsPipeline> m_ps;
+ QSizeF m_itemSize;
};
-class ClearItem : public QQuickItem
+class SimpleItem : public QQuickItem
{
Q_OBJECT
- Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
public:
- ClearItem() : m_color(Qt::black)
+ SimpleItem()
{
setFlag(ItemHasContents, true);
}
-
- QColor color() const { return m_color; }
- void setColor(const QColor &color)
- {
- if (color == m_color)
- return;
- m_color = color;
- emit colorChanged();
- }
-
protected:
- virtual QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
+ QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) override
{
- ClearNode *node = static_cast<ClearNode *>(oldNode);
+ if (size().isEmpty()) {
+ delete oldNode;
+ return nullptr;
+ }
+
+ SimpleNode *node = static_cast<SimpleNode *>(oldNode);
if (!node)
- node = new ClearNode;
- node->color = m_color;
- return node;
- }
+ node = new SimpleNode(window());
-Q_SIGNALS:
- void colorChanged();
+ node->m_itemSize = size();
-private:
- QColor m_color;
+ return node;
+ }
};
-class MessUpNode : public QSGRenderNode, protected QOpenGLFunctions
+#if QT_CONFIG(opengl)
+class GLNode : public QSGRenderNode
{
public:
- MessUpNode() {}
-
StateFlags changedStates() const override
{
- return StateFlags(DepthState) | StencilState | ScissorState | ColorState | BlendState
- | CullState | ViewportState | RenderTargetState;
+ return ViewportState; // nothing else matters in Qt 6
}
- void render(const RenderState *) override
+ RenderingFlags flags() const override
{
- if (!initialized) {
- initializeOpenGLFunctions();
- initialized = true;
- }
- // Don't draw anything, just mess up the state
- glViewport(10, 10, 10, 10);
- glDisable(GL_SCISSOR_TEST);
- glDepthMask(true);
- glEnable(GL_DEPTH_TEST);
- glDepthFunc(GL_EQUAL);
- glClearDepthf(1);
- glClearStencil(42);
- glClearColor(1.0f, 0.5f, 1.0f, 0.0f);
- glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
- glEnable(GL_SCISSOR_TEST);
- glScissor(190, 190, 10, 10);
- glStencilFunc(GL_EQUAL, 28, 0xff);
- glBlendFunc(GL_ZERO, GL_ZERO);
- GLint frontFace;
- glGetIntegerv(GL_FRONT_FACE, &frontFace);
- glFrontFace(frontFace == GL_CW ? GL_CCW : GL_CW);
- glEnable(GL_CULL_FACE);
- GLuint fbo;
- glGenFramebuffers(1, &fbo);
- glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+ return {};
}
- bool initialized = false;
+ void prepare() override
+ {
+ QVERIFY(QOpenGLContext::currentContext());
+ }
+
+ void render(const RenderState *) override
+ {
+ QVERIFY(QOpenGLContext::currentContext());
+ QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
+ QVERIFY(f);
+ f->glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
+ f->glClear(GL_COLOR_BUFFER_BIT);
+ }
};
-class MessUpItem : public QQuickItem
+class GLItem : public QQuickItem
{
Q_OBJECT
public:
- MessUpItem()
+ GLItem()
{
setFlag(ItemHasContents, true);
}
-
protected:
- virtual QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
+ QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) override
{
- MessUpNode *node = static_cast<MessUpNode *>(oldNode);
+ if (size().isEmpty()) {
+ delete oldNode;
+ return nullptr;
+ }
+
+ GLNode *node = static_cast<GLNode *>(oldNode);
if (!node)
- node = new MessUpNode;
+ node = new GLNode;
+
return node;
}
};
+#endif // QT_CONFIG(opengl)
tst_rendernode::tst_rendernode()
+ : QQmlDataTest(QT_QMLTEST_DATADIR)
{
- qmlRegisterType<ClearItem>("Test", 1, 0, "ClearItem");
- qmlRegisterType<MessUpItem>("Test", 1, 0, "MessUpItem");
- outerWindow.showNormal();
- outerWindow.setGeometry(0,0,400,400);
+ qmlRegisterType<SimpleItem>("Test", 1, 0, "SimpleItem");
+#if QT_CONFIG(opengl)
+ qmlRegisterType<GLItem>("Test", 1, 0, "GLSimpleItem");
+#endif
}
-static bool fuzzyCompareColor(QRgb x, QRgb y, QByteArray *errorMessage)
+void tst_rendernode::test_data()
{
- enum { fuzz = 4 };
- if (qAbs(qRed(x) - qRed(y)) >= fuzz || qAbs(qGreen(x) - qGreen(y)) >= fuzz || qAbs(qBlue(x) - qBlue(y)) >= fuzz) {
- QString s;
- QDebug(&s).nospace() << Qt::hex << "Color mismatch 0x" << x << " 0x" << y << Qt::dec << " (fuzz=" << fuzz << ").";
- *errorMessage = s.toLocal8Bit();
- return false;
- }
- return true;
-}
+ QTest::addColumn<QString>("file");
-static inline QByteArray msgColorMismatchAt(const QByteArray &colorMsg, int x, int y)
-{
- return colorMsg + QByteArrayLiteral(" at ") + QByteArray::number(x) +',' + QByteArray::number(y);
+ QTest::newRow("simple") << QStringLiteral("simple.qml");
}
-/* The test draws four rects, each 100x100 and verifies
- * that a rendernode which calls glClear() is stacked
- * correctly. The red rectangles come under the white
- * and are obscured.
- */
-void tst_rendernode::renderOrder()
+void tst_rendernode::test()
{
- if (QGuiApplication::primaryScreen()->depth() < 24)
- QSKIP("This test does not work at display depths < 24");
-
if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
|| (QGuiApplication::platformName() == QLatin1String("minimal")))
QSKIP("Skipping due to grabWindow not functional on offscreen/minimal platforms");
- if (isRunningOnRhi())
- QSKIP("Render nodes not yet supported with QRhi");
-
- QImage fb = runTest("RenderOrder.qml");
- QVERIFY(!fb.isNull());
+ if (!isRunningOnRhi())
+ QSKIP("Skipping QSGRenderNode test due to not running with QRhi");
+
+ QFETCH(QString, file);
+
+ QScopedPointer<QQuickView> view(createView(file, nullptr, 100, 100, 320, 200));
+ QVERIFY(QTest::qWaitForWindowExposed(view.data()));
+ QImage result = view->grabWindow();
+
+ const int maxFuzz = 5;
+ // red background
+ int x = 10, y = 10;
+ QVERIFY(qAbs(qRed(result.pixel(x, y)) - 255) < maxFuzz);
+ QVERIFY(qAbs(qGreen(result.pixel(x, y))) < maxFuzz);
+ QVERIFY(qAbs(qBlue(result.pixel(x, y))) < maxFuzz);
+
+ // gray rectangle in the middle
+ x = result.width() / 2;
+ y = result.height() / 2;
+ QVERIFY(qAbs(qRed(result.pixel(x, y)) - 128) < maxFuzz);
+ QVERIFY(qAbs(qGreen(result.pixel(x, y)) - 128) < maxFuzz);
+ QVERIFY(qAbs(qBlue(result.pixel(x, y)) - 128) < maxFuzz);
+
+ // check a bit up and left, this catches if the triangle is not depth
+ // tested correctly and so appears above the gray rect, not below as it should
+ x = result.width() / 2 - 5;
+ y = result.height() / 2 - 5;
+ QVERIFY(qAbs(qRed(result.pixel(x, y)) - 128) < maxFuzz);
+ QVERIFY(qAbs(qGreen(result.pixel(x, y)) - 128) < maxFuzz);
+ QVERIFY(qAbs(qBlue(result.pixel(x, y)) - 128) < maxFuzz);
+
+ // in search for blue pixels
+ int blueCount = 0;
+ for (y = 0; y < result.height(); ++y) {
+ for (x = 0; x < result.width(); ++x) {
+ if (qAbs(qRed(result.pixel(x, y))) < maxFuzz
+ && qAbs(qGreen(result.pixel(x, y))) < maxFuzz
+ && qAbs(qBlue(result.pixel(x, y)) - 255) < maxFuzz)
+ {
+ ++blueCount;
+ }
+ }
+ }
- const qreal scaleFactor = QGuiApplication::primaryScreen()->devicePixelRatio();
- QCOMPARE(fb.width(), qRound(200 * scaleFactor));
- QCOMPARE(fb.height(), qRound(200 * scaleFactor));
+ // if the blue triangle is rendered by SimpleNode, there should be lots of
+ // blue pixels present
+ QVERIFY(blueCount > 5000);
+}
- QCOMPARE(fb.pixel(50 * scaleFactor, 50 * scaleFactor), qRgb(0xff, 0xff, 0xff));
- QCOMPARE(fb.pixel(50 * scaleFactor, 150 * scaleFactor), qRgb(0xff, 0xff, 0xff));
- QCOMPARE(fb.pixel(150 * scaleFactor, 50 * scaleFactor), qRgb(0x00, 0x00, 0xff));
+#if QT_CONFIG(opengl)
+void tst_rendernode::gltest_data()
+{
+ QTest::addColumn<QString>("file");
- QByteArray errorMessage;
- const qreal coordinate = 150 * scaleFactor;
- QVERIFY2(fuzzyCompareColor(fb.pixel(coordinate, coordinate), qRgb(0x7f, 0x7f, 0xff), &errorMessage),
- msgColorMismatchAt(errorMessage, coordinate, coordinate).constData());
+ QTest::newRow("simple") << QStringLiteral("glsimple.qml");
}
-/* The test uses a number of nested rectangles with clipping
- * and rotation to verify that using a render node which messes
- * with the state does not break rendering that comes after it.
- */
-void tst_rendernode::messUpState()
+void tst_rendernode::gltest()
{
- if (QGuiApplication::primaryScreen()->depth() < 24)
- QSKIP("This test does not work at display depths < 24");
-
if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
|| (QGuiApplication::platformName() == QLatin1String("minimal")))
QSKIP("Skipping due to grabWindow not functional on offscreen/minimal platforms");
- if (isRunningOnRhi())
- QSKIP("Render nodes not yet supported with QRhi");
-
- QImage fb = runTest("MessUpState.qml");
- QVERIFY(!fb.isNull());
- int x1 = 0;
- int x2 = fb.width() / 2;
- int x3 = fb.width() - 1;
- int y1 = 0;
- int y2 = fb.height() * 3 / 16;
- int y3 = fb.height() / 2;
- int y4 = fb.height() * 13 / 16;
- int y5 = fb.height() - 1;
-
- QCOMPARE(fb.pixel(x1, y3), qRgb(0xff, 0xff, 0xff));
- QCOMPARE(fb.pixel(x3, y3), qRgb(0xff, 0xff, 0xff));
-
- QCOMPARE(fb.pixel(x2, y1), qRgb(0x00, 0x00, 0x00));
- QCOMPARE(fb.pixel(x2, y2), qRgb(0x00, 0x00, 0x00));
- QByteArray errorMessage;
- QVERIFY2(fuzzyCompareColor(fb.pixel(x2, y3), qRgb(0x7f, 0x00, 0x7f), &errorMessage),
- msgColorMismatchAt(errorMessage, x2, y3).constData());
- QCOMPARE(fb.pixel(x2, y4), qRgb(0x00, 0x00, 0x00));
- QCOMPARE(fb.pixel(x2, y5), qRgb(0x00, 0x00, 0x00));
-}
+ if (!isRunningOnRhi())
+ QSKIP("Skipping QSGRenderNode test due to not running with QRhi");
-class StateRecordingRenderNode : public QSGRenderNode
-{
-public:
- StateFlags changedStates() const override { return StateFlags(-1); }
- void render(const RenderState *) override {
- matrices[name] = *matrix();
+ if (QQuickWindow::graphicsApi() != QSGRendererInterface::OpenGL)
+ QSKIP("Skipping test due to not using OpenGL");
- }
+ QFETCH(QString, file);
- QString name;
- static QHash<QString, QMatrix4x4> matrices;
-};
+ QScopedPointer<QQuickView> view(createView(file, nullptr, 100, 100, 320, 200));
+ QVERIFY(QTest::qWaitForWindowExposed(view.data()));
+ QImage result = view->grabWindow();
-QHash<QString, QMatrix4x4> StateRecordingRenderNode::matrices;
+ const int maxFuzz = 5;
-class StateRecordingRenderNodeItem : public QQuickItem
-{
- Q_OBJECT
-public:
- StateRecordingRenderNodeItem() { setFlag(ItemHasContents, true); }
- QSGNode *updatePaintNode(QSGNode *r, UpdatePaintNodeData *) {
- if (r)
- return r;
- StateRecordingRenderNode *rn = new StateRecordingRenderNode();
- rn->name = objectName();
- return rn;
- }
-};
-
-void tst_rendernode::matrix()
-{
- if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
- || (QGuiApplication::platformName() == QLatin1String("minimal")))
- QSKIP("Skipping due to grabWindow not functional on offscreen/minimal platforms");
-
- if (isRunningOnRhi())
- QSKIP("Render nodes not yet supported with QRhi");
-
- qmlRegisterType<StateRecordingRenderNodeItem>("RenderNode", 1, 0, "StateRecorder");
- StateRecordingRenderNode::matrices.clear();
- QVERIFY(!runTest("matrix.qml").isNull());
+ // green
+ int x = 10, y = 10;
+ QVERIFY(qAbs(qRed(result.pixel(x, y))) < maxFuzz);
+ QVERIFY(qAbs(qGreen(result.pixel(x, y)) - 255) < maxFuzz);
+ QVERIFY(qAbs(qBlue(result.pixel(x, y))) < maxFuzz);
- QMatrix4x4 noRotateOffset;
- noRotateOffset.translate(20, 20);
- { QMatrix4x4 result = StateRecordingRenderNode::matrices.value(QStringLiteral("no-clip; no-rotation"));
- QCOMPARE(result, noRotateOffset);
- }
- { QMatrix4x4 result = StateRecordingRenderNode::matrices.value(QStringLiteral("parent-clip; no-rotation"));
- QCOMPARE(result, noRotateOffset);
- }
- { QMatrix4x4 result = StateRecordingRenderNode::matrices.value(QStringLiteral("self-clip; no-rotation"));
- QCOMPARE(result, noRotateOffset);
- }
-
- QMatrix4x4 parentRotation;
- parentRotation.translate(10, 10); // parent at x/y: 10
- parentRotation.translate(5, 5); // rotate 90 around center (width/height: 10)
- parentRotation.rotate(90, 0, 0, 1);
- parentRotation.translate(-5, -5);
- parentRotation.translate(10, 10); // StateRecorder at: x/y: 10
- { QMatrix4x4 result = StateRecordingRenderNode::matrices.value(QStringLiteral("no-clip; parent-rotation"));
- QCOMPARE(result, parentRotation);
- }
- { QMatrix4x4 result = StateRecordingRenderNode::matrices.value(QStringLiteral("parent-clip; parent-rotation"));
- QCOMPARE(result, parentRotation);
- }
- { QMatrix4x4 result = StateRecordingRenderNode::matrices.value(QStringLiteral("self-clip; parent-rotation"));
- QCOMPARE(result, parentRotation);
- }
+ // gray rectangle in the middle
+ x = result.width() / 2;
+ y = result.height() / 2;
+ QVERIFY(qAbs(qRed(result.pixel(x, y)) - 128) < maxFuzz);
+ QVERIFY(qAbs(qGreen(result.pixel(x, y)) - 128) < maxFuzz);
+ QVERIFY(qAbs(qBlue(result.pixel(x, y)) - 128) < maxFuzz);
+}
+#endif // QT_CONFIG(opengl)
- QMatrix4x4 selfRotation;
- selfRotation.translate(10, 10); // parent at x/y: 10
- selfRotation.translate(10, 10); // StateRecorder at: x/y: 10
- selfRotation.rotate(90, 0, 0, 1); // rotate 90, width/height: 0
- { QMatrix4x4 result = StateRecordingRenderNode::matrices.value(QStringLiteral("no-clip; self-rotation"));
- QCOMPARE(result, selfRotation);
- }
- { QMatrix4x4 result = StateRecordingRenderNode::matrices.value(QStringLiteral("parent-clip; self-rotation"));
- QCOMPARE(result, selfRotation);
- }
- { QMatrix4x4 result = StateRecordingRenderNode::matrices.value(QStringLiteral("self-clip; self-rotation"));
- QCOMPARE(result, selfRotation);
- }
+QQuickView *tst_rendernode::createView(const QString &file, QWindow *parent, int x, int y, int w, int h)
+{
+ QQuickView *view = new QQuickView(parent);
+ view->setResizeMode(QQuickView::SizeRootObjectToView);
+ view->setSource(testFileUrl(file));
+ if (x >= 0 && y >= 0)
+ view->setPosition(x, y);
+ if (w >= 0 && h >= 0)
+ view->resize(w, h);
+ view->show();
+ return view;
}
bool tst_rendernode::isRunningOnRhi() const