1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the test suite of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
44 #include <QtQuick/qquickitem.h>
45 #include <QtQuick/qquickview.h>
46 #include <QtGui/qopenglcontext.h>
48 #include "../../shared/util.h"
50 class tst_QQuickItemLayer: public QQmlDataTest
54 tst_QQuickItemLayer();
56 QImage runTest(const QString &fileName)
59 view.setSource(testFileUrl(fileName));
62 QTest::qWaitForWindowShown(&view);
64 return view.grabWindow();
73 void layerVisibility_data();
74 void layerVisibility();
76 void layerSourceRect();
78 void layerZOrder_data();
81 void layerIsTextureProvider();
83 void changeZOrder_data();
86 void toggleLayerAndEffect();
88 void changeSamplerName();
90 void rectangleEffect();
93 bool m_isMesaSoftwareRasterizer;
97 tst_QQuickItemLayer::tst_QQuickItemLayer()
101 QOpenGLContext context;
102 window.setSurfaceType(QWindow::OpenGLSurface);
105 context.makeCurrent(&window);
106 const char *vendor = (const char *)glGetString(GL_VENDOR);
107 const char *renderer = (const char *)glGetString(GL_RENDERER);
108 m_isMesaSoftwareRasterizer = strcmp(vendor, "Mesa Project") == 0
109 && strcmp(renderer, "Software Rasterizer") == 0;
110 if (m_isMesaSoftwareRasterizer) {
111 // Expects format: <OpenGL version> Mesa <Mesa version>[-devel] [...]
112 const char *version = (const char *)glGetString(GL_VERSION);
113 QList<QByteArray> list = QByteArray(version).split(' ');
114 if (list.size() >= 3) {
115 list = list.at(2).split('-').at(0).split('.');
119 if (list.size() >= 1)
120 major = list.at(0).toInt();
121 if (list.size() >= 2)
122 minor = list.at(1).toInt();
123 if (list.size() >= 3)
124 patch = list.at(2).toInt();
125 m_mesaVersion = QT_VERSION_CHECK(major, minor, patch);
130 // The test draws a red and a blue box next to each other and tests that the
131 // output is still red and blue on the left and right and a combination of
132 // the two in the middle.
134 void tst_QQuickItemLayer::layerSmooth()
136 if (m_isMesaSoftwareRasterizer && m_mesaVersion < QT_VERSION_CHECK(7, 11, 0))
137 QSKIP("Mesa Software Rasterizer below version 7.11 does not render this test correctly.");
138 QImage fb = runTest("Smooth.qml");
139 QCOMPARE(fb.pixel(0, 0), qRgb(0xff, 0, 0));
140 QCOMPARE(fb.pixel(fb.width() - 1, 0), qRgb(0, 0, 0xff));
142 uint pixel = fb.pixel(fb.width() / 2, 0);
143 QVERIFY(qRed(pixel) > 0);
144 QVERIFY(qBlue(pixel) > 0);
149 // The test draws a gradient at a small size into a layer and scales the
150 // layer. If the layer is enabled there should be very visible bands in
153 void tst_QQuickItemLayer::layerEnabled()
155 if (m_isMesaSoftwareRasterizer && m_mesaVersion < QT_VERSION_CHECK(7, 11, 0))
156 QSKIP("Mesa Software Rasterizer below version 7.11 does not render this test correctly.");
157 QImage fb = runTest("Enabled.qml");
158 // Verify the banding
159 QCOMPARE(fb.pixel(0, 0), fb.pixel(0, 1));
160 // Verify the gradient
161 QVERIFY(fb.pixel(0, 0) != fb.pixel(0, fb.height() - 1));
166 // The test draws a one pixel wide line and scales it down by more than a a factor 2
167 // If mipmpping works, the pixels should be gray, not white or black
169 void tst_QQuickItemLayer::layerMipmap()
171 if (m_isMesaSoftwareRasterizer)
172 QSKIP("Mipmapping does not work with the Mesa Software Rasterizer.");
173 QImage fb = runTest("Mipmap.qml");
174 QVERIFY(fb.pixel(0, 0) != 0xff000000);
175 QVERIFY(fb.pixel(0, 0) != 0xffffffff);
180 // The test implements an rgb swapping effect sourced from a blue rectangle. The
181 // resulting pixel should be red
183 void tst_QQuickItemLayer::layerEffect()
185 if (m_isMesaSoftwareRasterizer && m_mesaVersion < QT_VERSION_CHECK(7, 11, 0))
186 QSKIP("Mesa Software Rasterizer below version 7.11 does not render this test correctly.");
187 QImage fb = runTest("Effect.qml");
188 QCOMPARE(fb.pixel(0, 0), qRgb(0xff, 0, 0));
189 QCOMPARE(fb.pixel(fb.width() - 1, 0), qRgb(0, 0xff, 0));
194 // The test draws a rectangle and verifies that there is padding on each side
195 // as the source rect spans outside the item. The padding is verified using
196 // a shader that pads transparent to blue. Everything else is red.
197 void tst_QQuickItemLayer::layerSourceRect()
199 if (m_isMesaSoftwareRasterizer && m_mesaVersion < QT_VERSION_CHECK(7, 11, 0))
200 QSKIP("Mesa Software Rasterizer below version 7.11 does not render this test correctly.");
202 QImage fb = runTest("SourceRect.qml");
204 // Check that the edges are converted to blue
205 QCOMPARE(fb.pixel(0, 0), qRgb(0, 0, 0xff));
206 QCOMPARE(fb.pixel(fb.width() - 1, 0), qRgb(0, 0, 0xff));
207 QCOMPARE(fb.pixel(0, fb.height() - 1), qRgb(0, 0, 0xff));
208 QCOMPARE(fb.pixel(fb.width() - 1, fb.height() - 1), qRgb(0, 0, 0xff));
210 // The center pixel should be red
211 QCOMPARE(fb.pixel(fb.width() / 2, fb.height() / 2), qRgb(0xff, 0, 0));
216 // Same as the effect test up above, but this time use the item
217 // directly in a stand alone ShaderEffect
218 void tst_QQuickItemLayer::layerIsTextureProvider()
220 if (m_isMesaSoftwareRasterizer && m_mesaVersion < QT_VERSION_CHECK(7, 11, 0))
221 QSKIP("Mesa Software Rasterizer below version 7.11 does not render this test correctly.");
222 QImage fb = runTest("TextureProvider.qml");
223 QCOMPARE(fb.pixel(0, 0), qRgb(0xff, 0, 0));
224 QCOMPARE(fb.pixel(fb.width() - 1, 0), qRgb(0, 0xff, 0));
228 void tst_QQuickItemLayer::layerVisibility_data()
230 QTest::addColumn<bool>("visible");
231 QTest::addColumn<bool>("effect");
232 QTest::addColumn<qreal>("opacity");
234 QTest::newRow("!effect, !visible, a=1") << false << false << 1.;
235 QTest::newRow("!effect, visible, a=1") << false << true << 1.;
236 QTest::newRow("effect, !visible, a=1") << true << false << 1.;
237 QTest::newRow("effect, visible, a=1") << true << true << 1.;
239 QTest::newRow("!effect, !visible, a=.5") << false << false << .5;
240 QTest::newRow("!effect, visible, a=.5") << false << true << .5;
241 QTest::newRow("effect, !visible, a=.5") << true << false << .5;
242 QTest::newRow("effect, visible, a=.5") << true << true << .5;
244 QTest::newRow("!effect, !visible, a=0") << false << false << 0.;
245 QTest::newRow("!effect, visible, a=0") << false << true << 0.;
246 QTest::newRow("effect, !visible, a=0") << true << false << 0.;
247 QTest::newRow("effect, visible, a=0") << true << true << 0.;
250 void tst_QQuickItemLayer::layerVisibility()
252 if (m_isMesaSoftwareRasterizer && m_mesaVersion < QT_VERSION_CHECK(7, 11, 0))
253 QSKIP("Mesa Software Rasterizer below version 7.11 does not render this test correctly.");
255 QFETCH(bool, visible);
256 QFETCH(bool, effect);
257 QFETCH(qreal, opacity);
260 view.setSource(testFileUrl("Visible.qml"));
262 QQuickItem *child = view.rootItem()->childItems().at(0);
263 child->setProperty("layerVisible", visible);
264 child->setProperty("layerEffect", effect);
265 child->setProperty("layerOpacity", opacity);
269 QTest::qWaitForWindowActive(&view);
271 QImage fb = view.grabWindow();
272 uint pixel = fb.pixel(0, 0);
274 if (!visible || opacity == 0) {
275 QCOMPARE(pixel, qRgb(0xff, 0xff, 0xff));
277 QCOMPARE(qRed(pixel), 0xff);
278 QVERIFY(qGreen(pixel) < 0xff);
279 QVERIFY(qBlue(pixel) < 0xff);
280 } else { // no effect
281 QCOMPARE(qBlue(pixel), 0xff);
282 QVERIFY(qGreen(pixel) < 0xff);
283 QVERIFY(qRed(pixel) < 0xff);
290 void tst_QQuickItemLayer::layerZOrder_data()
292 QTest::addColumn<bool>("effect");
294 QTest::newRow("!effect") << false;
295 QTest::newRow("effect") << true;
298 void tst_QQuickItemLayer::layerZOrder()
300 if (m_isMesaSoftwareRasterizer && m_mesaVersion < QT_VERSION_CHECK(7, 11, 0))
301 QSKIP("Mesa Software Rasterizer below version 7.11 does not render this test correctly.");
303 QFETCH(bool, effect);
306 view.setSource(testFileUrl("ZOrder.qml"));
308 QQuickItem *child = view.rootItem()->childItems().at(0);
309 child->setProperty("layerEffect", effect);
313 QTest::qWaitForWindowShown(&view);
315 QImage fb = view.grabWindow();
317 QCOMPARE(fb.pixel(50, 50), qRgb(0, 0, 0xff));
318 QCOMPARE(fb.pixel(150, 150), qRgb(0, 0xff, 00));
322 void tst_QQuickItemLayer::changeZOrder_data()
324 QTest::addColumn<bool>("layered");
325 QTest::addColumn<bool>("effect");
327 QTest::newRow("layered, effect") << true << true;
328 QTest::newRow("layered, !effect") << true << false;
329 QTest::newRow("!layered") << false << false;
332 void tst_QQuickItemLayer::changeZOrder()
334 if (m_isMesaSoftwareRasterizer && m_mesaVersion < QT_VERSION_CHECK(7, 11, 0))
335 QSKIP("Mesa Software Rasterizer below version 7.11 does not render this test correctly.");
337 QFETCH(bool, layered);
338 QFETCH(bool, effect);
341 view.setSource(testFileUrl("ZOrderChange.qml"));
343 QQuickItem *child = view.rootItem()->childItems().at(0);
344 child->setProperty("layerEnabled", layered);
345 child->setProperty("layerEffect", effect);
346 child->setProperty("layerZ", 1);
350 QTest::qWaitForWindowShown(&view);
352 QImage fb = view.grabWindow();
354 QRgb topLeft = fb.pixel(50, 50);
355 QRgb topRight = fb.pixel(150, 50);
356 QRgb bottomLeft = fb.pixel(50, 150);
357 QRgb bottomRight = fb.pixel(150, 150);
359 QCOMPARE(bottomLeft, qRgb(0, 0, 0xff));
362 QCOMPARE(topLeft, qRgb(0, 0xff, 0xff));
364 QCOMPARE(qGreen(topLeft), 0xff);
365 QVERIFY(qAbs(qRed(topLeft) - 0x3f) < 4);
366 QVERIFY(qAbs(qBlue(topLeft) - 0xbf) < 4);
369 if (layered && effect) {
370 QCOMPARE(qRed(topRight), 0xff);
371 QCOMPARE(qGreen(topRight), 0x00);
372 QVERIFY(qAbs(qBlue(topRight) - 0x7f) < 4);
374 QVERIFY(qAbs(qRed(bottomRight) - 0x7f) < 4);
375 QCOMPARE(qBlue(bottomRight), 0xff);
376 QVERIFY(qAbs(qGreen(bottomRight) - 0x7f) < 4);
378 QCOMPARE(qRed(topRight), 0xff);
379 QCOMPARE(qBlue(topRight), 0x00);
380 QVERIFY(qAbs(qGreen(topRight) - 0x7f) < 4);
382 QVERIFY(qAbs(qRed(bottomRight) - 0x7f) < 4);
383 QCOMPARE(qGreen(bottomRight), 0xff);
384 QVERIFY(qAbs(qBlue(bottomRight) - 0x7f) < 4);
388 void tst_QQuickItemLayer::toggleLayerAndEffect()
390 // This test passes if it doesn't crash.
391 runTest("ToggleLayerAndEffect.qml");
394 void tst_QQuickItemLayer::disableLayer()
396 // This test passes if it doesn't crash.
397 runTest("DisableLayer.qml");
400 void tst_QQuickItemLayer::changeSamplerName()
402 if (m_isMesaSoftwareRasterizer && m_mesaVersion < QT_VERSION_CHECK(7, 11, 0))
403 QSKIP("Mesa Software Rasterizer below version 7.11 does not render this test correctly.");
404 QImage fb = runTest("SamplerNameChange.qml");
405 QCOMPARE(fb.pixel(0, 0), qRgb(0, 0, 0xff));
408 void tst_QQuickItemLayer::itemEffect()
410 if (m_isMesaSoftwareRasterizer && m_mesaVersion < QT_VERSION_CHECK(7, 11, 0))
411 QSKIP("Mesa Software Rasterizer below version 7.11 does not render this test correctly.");
412 QImage fb = runTest("ItemEffect.qml");
413 QCOMPARE(fb.pixel(0, 0), qRgb(0xff, 0, 0));
414 QCOMPARE(fb.pixel(199, 0), qRgb(0xff, 0, 0));
415 QCOMPARE(fb.pixel(0, 199), qRgb(0, 0, 0xff));
416 QCOMPARE(fb.pixel(199, 199), qRgb(0, 0, 0xff));
419 void tst_QQuickItemLayer::rectangleEffect()
421 QImage fb = runTest("RectangleEffect.qml");
422 QCOMPARE(fb.pixel(0, 0), qRgb(0, 0xff, 0));
423 QCOMPARE(fb.pixel(199, 0), qRgb(0, 0xff, 0));
424 QCOMPARE(fb.pixel(0, 199), qRgb(0, 0xff, 0));
425 QCOMPARE(fb.pixel(199, 199), qRgb(0, 0xff, 0));
427 QCOMPARE(fb.pixel(100, 0), qRgb(0, 0, 0xff));
428 QCOMPARE(fb.pixel(199, 100), qRgb(0, 0, 0xff));
429 QCOMPARE(fb.pixel(100, 199), qRgb(0, 0, 0xff));
430 QCOMPARE(fb.pixel(0, 100), qRgb(0, 0, 0xff));
434 QTEST_MAIN(tst_QQuickItemLayer)
436 #include "tst_qquickitemlayer.moc"