1 /****************************************************************************
3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the Qt scene graph research project.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include <QtCore/QString>
43 #include <QtTest/QtTest>
46 #include <private/qsgrenderer_p.h>
47 #include <private/qsgnodeupdater_p.h>
49 #include <qsgsimplerectnode.h>
51 class NodesTest : public QObject
60 void cleanupTestCase() {
66 void propegateWithMultipleRoots();
67 void simulatedEffect_data();
68 void simulatedEffect();
71 void basicOpacityNode();
72 void opacityPropegation();
75 void isBlockedCheck();
80 QSGNodeUpdater updater;
83 void NodesTest::initTestCase()
85 widget = new QGLWidget();
86 widget->resize(100, 30);
90 class DummyRenderer : public QSGRenderer
93 DummyRenderer(QSGRootNode *root)
94 : QSGRenderer(QSGContext::createDefaultContext())
104 renderingOrder = ++globalRendereringOrder;
107 void nodeChanged(QSGNode *node, QSGNode::DirtyFlags flags) {
109 changedFlags = flags;
110 QSGRenderer::nodeChanged(node, flags);
113 QSGNode *changedNode;
114 QSGNode::DirtyFlags changedFlags;
118 static int globalRendereringOrder;
121 int DummyRenderer::globalRendereringOrder;
123 NodesTest::NodesTest()
128 void NodesTest::propegate()
131 QSGNode child; child.setFlag(QSGNode::OwnedByParent, false);
132 root.appendChildNode(&child);
134 DummyRenderer renderer(&root);
136 child.markDirty(QSGNode::DirtyGeometry);
138 QCOMPARE(&child, renderer.changedNode);
139 QCOMPARE((int) renderer.changedFlags, (int) QSGNode::DirtyGeometry);
143 void NodesTest::propegateWithMultipleRoots()
146 QSGNode child2; child2.setFlag(QSGNode::OwnedByParent, false);
147 QSGRootNode root3; root3.setFlag(QSGNode::OwnedByParent, false);
148 QSGNode child4; child4.setFlag(QSGNode::OwnedByParent, false);
150 root1.appendChildNode(&child2);
151 child2.appendChildNode(&root3);
152 root3.appendChildNode(&child4);
154 DummyRenderer ren1(&root1);
155 DummyRenderer ren2(&root3);
157 child4.markDirty(QSGNode::DirtyGeometry);
159 QCOMPARE(ren1.changedNode, &child4);
160 QCOMPARE(ren2.changedNode, &child4);
162 QCOMPARE((int) ren1.changedFlags, (int) QSGNode::DirtyGeometry);
163 QCOMPARE((int) ren2.changedFlags, (int) QSGNode::DirtyGeometry);
168 class SimulatedEffectRenderer : public DummyRenderer
171 SimulatedEffectRenderer(QSGRootNode *root, QSGBasicGeometryNode *c)
172 : DummyRenderer(root)
178 matrix = child->matrix() ? *child->matrix() : QMatrix4x4();
179 DummyRenderer::render();
182 QSGBasicGeometryNode *child;
187 class PseudoEffectNode : public QSGNode {
189 PseudoEffectNode(QSGRenderer *r)
192 setFlag(UsePreprocess);
197 if (renderer->rootNode()->parent()) {
198 // Mark the root dirty to build a clean state from the root and down
199 renderer->rootNode()->markDirty(QSGNode::DirtyForceUpdate);
202 renderer->renderScene();
204 if (renderer->rootNode()->parent()) {
205 // Mark the parent of the root dirty to force the root and down to be updated.
206 renderer->rootNode()->parent()->markDirty(QSGNode::DirtyForceUpdate);
210 QSGRenderer *renderer;
213 void NodesTest::simulatedEffect_data()
215 QTest::addColumn<bool>("connected");
217 QTest::newRow("connected") << true;
218 QTest::newRow("disconnected") << false;
221 void NodesTest::simulatedEffect()
223 QSKIP("QTBUG-20029", SkipAll);
225 QFETCH(bool, connected);
229 QSGTransformNode xform;
230 QSGSimpleRectNode geometry;
231 geometry.setRect(QRectF(0, 0, 1, 1));
232 geometry.setColor(Qt::red);
234 root.setFlag(QSGNode::OwnedByParent, false);
235 source.setFlag(QSGNode::OwnedByParent, false);
236 xform.setFlag(QSGNode::OwnedByParent, false);
237 geometry.setFlag(QSGNode::OwnedByParent, false);
239 SimulatedEffectRenderer rootRenderer(&root, &geometry);
240 SimulatedEffectRenderer sourceRenderer(&source, &geometry);
242 PseudoEffectNode effect(&sourceRenderer);
245 root Source is redirected into effect using the SimulatedEffectRenderer
254 root.appendChildNode(&xform);
255 root.appendChildNode(&effect);
257 xform.appendChildNode(&source);
258 source.appendChildNode(&geometry);
259 QMatrix4x4 m; m.translate(1, 2, 3);
262 // Clear all dirty states...
263 updater.updateStates(&root);
265 rootRenderer.renderScene();
267 // compare that we got one render call to each
268 QCOMPARE(rootRenderer.renderCount, 1);
269 QCOMPARE(sourceRenderer.renderCount, 1);
270 QVERIFY(sourceRenderer.renderingOrder < rootRenderer.renderingOrder);
271 if (connected) // geometry is not rendered in this case, so skip it...
272 QCOMPARE(rootRenderer.matrix, xform.matrix());
273 QCOMPARE(sourceRenderer.matrix, QMatrix4x4());
276 void NodesTest::basicOpacityNode()
279 QCOMPARE(n.opacity(), 1.);
282 QCOMPARE(n.opacity(), 0.5);
285 QCOMPARE(n.opacity(), 0.);
288 QCOMPARE(n.opacity(), 1.);
291 void NodesTest::opacityPropegation()
294 QSGOpacityNode *a = new QSGOpacityNode;
295 QSGOpacityNode *b = new QSGOpacityNode;
296 QSGOpacityNode *c = new QSGOpacityNode;
298 QSGSimpleRectNode *geometry = new QSGSimpleRectNode;
299 geometry->setRect(0, 0, 100, 100);
301 root.appendChildNode(a);
302 a->appendChildNode(b);
303 b->appendChildNode(c);
304 c->appendChildNode(geometry);
310 updater.updateStates(&root);
312 QCOMPARE(a->combinedOpacity(), 0.9);
313 QCOMPARE(b->combinedOpacity(), 0.9 * 0.8);
314 QCOMPARE(c->combinedOpacity(), 0.9 * 0.8 * 0.7);
315 QCOMPARE(geometry->inheritedOpacity(), 0.9 * 0.8 * 0.7);
318 updater.updateStates(&root);
320 QCOMPARE(a->combinedOpacity(), 0.9);
321 QCOMPARE(b->combinedOpacity(), 0.9 * 0.1);
322 QCOMPARE(c->combinedOpacity(), 0.9 * 0.1 * 0.7);
323 QCOMPARE(geometry->inheritedOpacity(), 0.9 * 0.1 * 0.7);
326 updater.updateStates(&root);
328 QVERIFY(b->isSubtreeBlocked());
330 // Verify that geometry did not get updated as it is in a blocked
332 QCOMPARE(c->combinedOpacity(), 0.9 * 0.1 * 0.7);
333 QCOMPARE(geometry->inheritedOpacity(), 0.9 * 0.1 * 0.7);
336 void NodesTest::isBlockedCheck()
339 QSGOpacityNode *opacity = new QSGOpacityNode();
340 QSGNode *node = new QSGNode();
342 root.appendChildNode(opacity);
343 opacity->appendChildNode(node);
345 QSGNodeUpdater updater;
347 opacity->setOpacity(0);
348 QVERIFY(updater.isNodeBlocked(node, &root));
350 opacity->setOpacity(1);
351 QVERIFY(!updater.isNodeBlocked(node, &root));
354 QTEST_MAIN(NodesTest);
356 #include "tst_nodestest.moc"