1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the test suite of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28
29#include <QtTest/QtTest>
30#include <QtTest/QSignalSpy>
31#include <QtQuick/qquickpainteditem.h>
32#include <QtQuick/qquickview.h>
33
34#include <private/qquickitem_p.h>
35#if QT_CONFIG(opengl)
36#include <private/qsgdefaultpainternode_p.h>
37#else
38#include <private/qsgsoftwarepainternode_p.h>
39#endif
40class tst_QQuickPaintedItem: public QObject
41{
42 Q_OBJECT
43private slots:
44 void initTestCase();
45 void update();
46 void opaquePainting();
47 void antialiasing();
48 void mipmap();
49 void performanceHints();
50 void contentsSize();
51 void contentScale();
52 void contentsBoundingRect();
53 void fillColor();
54 void renderTarget();
55
56private:
57 QQuickWindow window;
58};
59
60class TestPaintedItem : public QQuickPaintedItem
61{
62 Q_OBJECT
63public:
64 TestPaintedItem(QQuickItem *parent = nullptr)
65 : QQuickPaintedItem(parent)
66 , paintNode(nullptr)
67 , paintRequests(0)
68 {
69 }
70
71 void paint(QPainter *painter)
72 {
73 ++paintRequests;
74 clipRect = painter->clipBoundingRect();
75 }
76#if QT_CONFIG(opengl)
77 QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
78 {
79 paintNode = static_cast<QSGDefaultPainterNode *>(QQuickPaintedItem::updatePaintNode(oldNode, data));
80 return paintNode;
81 }
82
83 QSGDefaultPainterNode *paintNode;
84#else
85 QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
86 {
87 paintNode = static_cast<QSGSoftwarePainterNode *>(QQuickPaintedItem::updatePaintNode(oldNode, data));
88 return paintNode;
89 }
90
91 QSGSoftwarePainterNode *paintNode;
92#endif
93 int paintRequests;
94 QRectF clipRect;
95};
96
97static bool hasDirtyContentFlag(QQuickItem *item) {
98 return QQuickItemPrivate::get(item)->dirtyAttributes & QQuickItemPrivate::Content; }
99static void clearDirtyContentFlag(QQuickItem *item) {
100 QQuickItemPrivate::get(item)->dirtyAttributes &= ~QQuickItemPrivate::Content; }
101
102void tst_QQuickPaintedItem::initTestCase()
103{
104 window.resize(w: 320, h: 240);
105 window.show();
106 QVERIFY(QTest::qWaitForWindowExposed(&window));
107}
108
109void tst_QQuickPaintedItem::update()
110{
111 TestPaintedItem item;
112 item.setParentItem(window.contentItem());
113
114 QCOMPARE(hasDirtyContentFlag(&item), false);
115 item.update();
116 QCOMPARE(hasDirtyContentFlag(&item), true);
117
118 QTRY_COMPARE(hasDirtyContentFlag(&item), false);
119 QCOMPARE(item.paintRequests, 0); // Size empty
120
121 item.setSize(QSizeF(320, 240));
122
123 item.update();
124 QCOMPARE(hasDirtyContentFlag(&item), true);
125
126 QTRY_COMPARE(hasDirtyContentFlag(&item), false);
127 QCOMPARE(item.paintRequests, 1);
128 QCOMPARE(item.clipRect, QRectF(0, 0, 0, 0));
129
130 item.update(rect: QRect(30, 25, 12, 11));
131 QCOMPARE(hasDirtyContentFlag(&item), true);
132
133 QTRY_COMPARE(hasDirtyContentFlag(&item), false);
134 QCOMPARE(item.paintRequests, 2);
135 QCOMPARE(item.clipRect, QRectF(30, 25, 12, 11));
136
137 item.update(rect: QRect(30, 25, 12, 11));
138 item.update(rect: QRect(112, 56, 20, 20));
139
140 QCOMPARE(hasDirtyContentFlag(&item), true);
141
142 QTRY_COMPARE(hasDirtyContentFlag(&item), false);
143 QCOMPARE(item.paintRequests, 3);
144 QCOMPARE(item.clipRect, QRectF(30, 25, 102, 51));
145}
146
147void tst_QQuickPaintedItem::opaquePainting()
148{
149 TestPaintedItem item;
150 item.setSize(QSizeF(320, 240));
151 item.setParentItem(window.contentItem());
152
153 QCOMPARE(item.opaquePainting(), false);
154
155 item.setOpaquePainting(false);
156 QCOMPARE(item.opaquePainting(), false);
157 QCOMPARE(hasDirtyContentFlag(&item), false);
158
159 item.update();
160 QTRY_COMPARE(hasDirtyContentFlag(&item), false);
161 QVERIFY(item.paintNode);
162 QCOMPARE(item.paintNode->opaquePainting(), false);
163
164 item.setOpaquePainting(true);
165 QCOMPARE(item.opaquePainting(), true);
166 QCOMPARE(hasDirtyContentFlag(&item), true);
167
168 QTRY_COMPARE(hasDirtyContentFlag(&item), false);
169 QVERIFY(item.paintNode);
170 QCOMPARE(item.paintNode->opaquePainting(), true);
171
172 item.setOpaquePainting(true);
173 QCOMPARE(item.opaquePainting(), true);
174 QCOMPARE(hasDirtyContentFlag(&item), false);
175
176 item.setOpaquePainting(false);
177 QCOMPARE(item.opaquePainting(), false);
178 QCOMPARE(hasDirtyContentFlag(&item), true);
179
180 QTRY_COMPARE(hasDirtyContentFlag(&item), false);
181 QVERIFY(item.paintNode);
182 QCOMPARE(item.paintNode->opaquePainting(), false);
183}
184
185void tst_QQuickPaintedItem::antialiasing()
186{
187 TestPaintedItem item;
188 item.setSize(QSizeF(320, 240));
189 item.setParentItem(window.contentItem());
190
191 QCOMPARE(item.antialiasing(), false);
192
193 item.setAntialiasing(false);
194 QCOMPARE(item.antialiasing(), false);
195 QCOMPARE(hasDirtyContentFlag(&item), false);
196
197 item.update();
198 QTRY_COMPARE(hasDirtyContentFlag(&item), false);
199 QVERIFY(item.paintNode);
200 QCOMPARE(item.paintNode->smoothPainting(), false);
201
202 item.setAntialiasing(true);
203 QCOMPARE(item.antialiasing(), true);
204 QCOMPARE(hasDirtyContentFlag(&item), true);
205
206 QTRY_COMPARE(hasDirtyContentFlag(&item), false);
207 QVERIFY(item.paintNode);
208 QCOMPARE(item.paintNode->smoothPainting(), true);
209
210 item.setAntialiasing(true);
211 QCOMPARE(item.antialiasing(), true);
212 QCOMPARE(hasDirtyContentFlag(&item), false);
213
214 item.setAntialiasing(false);
215 QCOMPARE(item.antialiasing(), false);
216 QCOMPARE(hasDirtyContentFlag(&item), true);
217
218 QTRY_COMPARE(hasDirtyContentFlag(&item), false);
219 QVERIFY(item.paintNode);
220 QCOMPARE(item.paintNode->smoothPainting(), false);
221}
222
223void tst_QQuickPaintedItem::mipmap()
224{
225 TestPaintedItem item;
226 item.setSize(QSizeF(320, 240));
227 item.setParentItem(window.contentItem());
228
229 QCOMPARE(item.mipmap(), false);
230
231 item.setMipmap(false);
232 QCOMPARE(item.mipmap(), false);
233 QCOMPARE(hasDirtyContentFlag(&item), false);
234
235 item.update();
236 QTRY_COMPARE(hasDirtyContentFlag(&item), false);
237 QVERIFY(item.paintNode);
238 QCOMPARE(item.paintNode->mipmapping(), false);
239
240 item.setMipmap(true);
241 QCOMPARE(item.mipmap(), true);
242 QCOMPARE(hasDirtyContentFlag(&item), true);
243
244 QTRY_COMPARE(hasDirtyContentFlag(&item), false);
245 QVERIFY(item.paintNode);
246 QCOMPARE(item.paintNode->mipmapping(), true);
247
248 item.setMipmap(true);
249 QCOMPARE(item.mipmap(), true);
250 QCOMPARE(hasDirtyContentFlag(&item), false);
251
252 item.setMipmap(false);
253 QCOMPARE(item.mipmap(), false);
254 QCOMPARE(hasDirtyContentFlag(&item), true);
255
256 QTRY_COMPARE(hasDirtyContentFlag(&item), false);
257 QVERIFY(item.paintNode);
258 QCOMPARE(item.paintNode->mipmapping(), false);
259}
260
261void tst_QQuickPaintedItem::performanceHints()
262{
263 TestPaintedItem item;
264 item.setSize(QSizeF(320, 240));
265 item.setParentItem(window.contentItem());
266
267 QCOMPARE(item.performanceHints(), QQuickPaintedItem::PerformanceHints());
268
269 item.setPerformanceHints(QQuickPaintedItem::PerformanceHints());
270 QCOMPARE(item.performanceHints(), QQuickPaintedItem::PerformanceHints());
271 QCOMPARE(hasDirtyContentFlag(&item), false);
272
273 item.update();
274 QTRY_COMPARE(hasDirtyContentFlag(&item), false);
275 QVERIFY(item.paintNode);
276 QCOMPARE(item.paintNode->fastFBOResizing(), false);
277
278 item.setPerformanceHints(QQuickPaintedItem::PerformanceHints(QQuickPaintedItem::FastFBOResizing));
279 QCOMPARE(item.performanceHints(), QQuickPaintedItem::PerformanceHints(QQuickPaintedItem::FastFBOResizing));
280 QCOMPARE(hasDirtyContentFlag(&item), true);
281
282 QTRY_COMPARE(hasDirtyContentFlag(&item), false);
283 QVERIFY(item.paintNode);
284 QCOMPARE(item.paintNode->fastFBOResizing(), true);
285
286 item.setPerformanceHint(hint: QQuickPaintedItem::FastFBOResizing, enabled: true);
287 QCOMPARE(item.performanceHints(), QQuickPaintedItem::PerformanceHints(QQuickPaintedItem::FastFBOResizing));
288 QCOMPARE(hasDirtyContentFlag(&item), false);
289
290 item.setPerformanceHint(hint: QQuickPaintedItem::FastFBOResizing, enabled: false);
291 QCOMPARE(item.performanceHints(), QQuickPaintedItem::PerformanceHints());
292 QCOMPARE(hasDirtyContentFlag(&item), true);
293
294 QTRY_COMPARE(hasDirtyContentFlag(&item), false);
295 QVERIFY(item.paintNode);
296 QCOMPARE(item.paintNode->fastFBOResizing(), false);
297}
298
299void tst_QQuickPaintedItem::contentsSize()
300{
301 TestPaintedItem item;
302
303 QSignalSpy spy(&item, SIGNAL(contentsSizeChanged()));
304
305 QCOMPARE(item.contentsSize(), QSize());
306
307 item.setContentsSize(QSize());
308 QCOMPARE(item.contentsSize(), QSize());
309 QCOMPARE(hasDirtyContentFlag(&item), false);
310 QCOMPARE(spy.count(), 0);
311
312 item.setContentsSize(QSize(320, 240));
313 QCOMPARE(item.contentsSize(), QSize(320, 240));
314 QCOMPARE(hasDirtyContentFlag(&item), true);
315 QCOMPARE(spy.count(), 1);
316
317 clearDirtyContentFlag(item: &item);
318
319 item.setContentsSize(QSize(320, 240));
320 QCOMPARE(item.contentsSize(), QSize(320, 240));
321 QCOMPARE(hasDirtyContentFlag(&item), false);
322 QCOMPARE(spy.count(), 1);
323
324 item.resetContentsSize();
325 QCOMPARE(item.contentsSize(), QSize());
326 QCOMPARE(hasDirtyContentFlag(&item), true);
327 QCOMPARE(spy.count(), 2);
328}
329
330void tst_QQuickPaintedItem::contentScale()
331{
332 TestPaintedItem item;
333 item.setSize(QSizeF(320, 240));
334 item.setParentItem(window.contentItem());
335
336 QSignalSpy spy(&item, SIGNAL(contentsScaleChanged()));
337
338 QCOMPARE(item.contentsScale(), 1.);
339
340 item.setContentsScale(1.);
341 QCOMPARE(item.contentsScale(), 1.);
342 QCOMPARE(hasDirtyContentFlag(&item), false);
343 QCOMPARE(spy.count(), 0);
344
345 item.update();
346 QTRY_COMPARE(hasDirtyContentFlag(&item), false);
347 QVERIFY(item.paintNode);
348 QCOMPARE(item.paintNode->contentsScale(), 1.0);
349
350 item.setContentsScale(0.4);
351 QCOMPARE(item.contentsScale(), 0.4);
352 QCOMPARE(hasDirtyContentFlag(&item), true);
353 QCOMPARE(spy.count(), 1);
354
355 QTRY_COMPARE(hasDirtyContentFlag(&item), false);
356 QVERIFY(item.paintNode);
357 QCOMPARE(item.paintNode->contentsScale(), 0.4);
358
359 item.setContentsScale(0.4);
360 QCOMPARE(item.contentsScale(), 0.4);
361 QCOMPARE(hasDirtyContentFlag(&item), false);
362 QCOMPARE(spy.count(), 1);
363
364 item.setContentsScale(2.5);
365 QCOMPARE(item.contentsScale(), 2.5);
366 QCOMPARE(hasDirtyContentFlag(&item), true);
367 QCOMPARE(spy.count(), 2);
368
369 QTRY_COMPARE(hasDirtyContentFlag(&item), false);
370 QVERIFY(item.paintNode);
371 QCOMPARE(item.paintNode->contentsScale(), 2.5);
372}
373
374void tst_QQuickPaintedItem::contentsBoundingRect()
375{
376 TestPaintedItem item;
377 item.setSize(QSizeF(320, 240));
378 item.setParentItem(window.contentItem());
379
380 QCOMPARE(item.contentsBoundingRect(), QRectF(0, 0, 320, 240));
381
382 item.setContentsSize(QSize(500, 500));
383 QCOMPARE(item.contentsBoundingRect(), QRectF(0, 0, 500, 500));
384
385 QTRY_COMPARE(hasDirtyContentFlag(&item), false);
386 QVERIFY(item.paintNode);
387 QCOMPARE(item.paintNode->size(), QSize(500, 500));
388
389 item.setContentsScale(0.5);
390 QCOMPARE(item.contentsBoundingRect(), QRectF(0, 0, 320, 250));
391
392 QTRY_COMPARE(hasDirtyContentFlag(&item), false);
393 QVERIFY(item.paintNode);
394 QCOMPARE(item.paintNode->size(), QSize(320, 250));
395
396 item.setContentsSize(QSize(150, 150));
397 QCOMPARE(item.contentsBoundingRect(), QRectF(0, 0, 320, 240));
398
399 QTRY_COMPARE(hasDirtyContentFlag(&item), false);
400 QVERIFY(item.paintNode);
401 QCOMPARE(item.paintNode->size(), QSize(320, 240));
402
403 item.setContentsScale(2.0);
404 QCOMPARE(item.contentsBoundingRect(), QRectF(0, 0, 320, 300));
405
406 QTRY_COMPARE(hasDirtyContentFlag(&item), false);
407 QVERIFY(item.paintNode);
408 QCOMPARE(item.paintNode->size(), QSize(320, 300));
409
410}
411
412void tst_QQuickPaintedItem::fillColor()
413{
414 TestPaintedItem item;
415 item.setSize(QSizeF(320, 240));
416 item.setParentItem(window.contentItem());
417
418 QSignalSpy spy(&item, SIGNAL(fillColorChanged()));
419
420 QCOMPARE(item.fillColor(), QColor(Qt::transparent));
421
422 item.setFillColor(QColor(Qt::transparent));
423 QCOMPARE(item.fillColor(), QColor(Qt::transparent));
424 QCOMPARE(hasDirtyContentFlag(&item), false);
425 QCOMPARE(spy.count(), 0);
426
427 item.update();
428 QTRY_COMPARE(hasDirtyContentFlag(&item), false);
429 QVERIFY(item.paintNode);
430 QCOMPARE(item.paintNode->fillColor(), QColor(Qt::transparent));
431
432 item.setFillColor(QColor(Qt::green));
433 QCOMPARE(item.fillColor(), QColor(Qt::green));
434 QCOMPARE(hasDirtyContentFlag(&item), true);
435 QCOMPARE(spy.count(), 1);
436
437 QTRY_COMPARE(hasDirtyContentFlag(&item), false);
438 QVERIFY(item.paintNode);
439 QCOMPARE(item.paintNode->fillColor(), QColor(Qt::green));
440
441 item.setFillColor(QColor(Qt::green));
442 QCOMPARE(item.fillColor(), QColor(Qt::green));
443 QCOMPARE(hasDirtyContentFlag(&item), false);
444 QCOMPARE(spy.count(), 1);
445
446 item.setFillColor(QColor(Qt::blue));
447 QCOMPARE(item.fillColor(), QColor(Qt::blue));
448 QCOMPARE(hasDirtyContentFlag(&item), true);
449 QCOMPARE(spy.count(), 2);
450
451 QTRY_COMPARE(hasDirtyContentFlag(&item), false);
452 QVERIFY(item.paintNode);
453 QCOMPARE(item.paintNode->fillColor(), QColor(Qt::blue));
454
455}
456
457void tst_QQuickPaintedItem::renderTarget()
458{
459 TestPaintedItem item;
460
461 QSignalSpy spy(&item, SIGNAL(renderTargetChanged()));
462
463 QCOMPARE(item.renderTarget(), QQuickPaintedItem::Image);
464
465 item.setRenderTarget(QQuickPaintedItem::Image);
466 QCOMPARE(item.renderTarget(), QQuickPaintedItem::Image);
467 QCOMPARE(hasDirtyContentFlag(&item), false);
468 QCOMPARE(spy.count(), 0);
469
470 item.setRenderTarget(QQuickPaintedItem::FramebufferObject);
471 QCOMPARE(item.renderTarget(), QQuickPaintedItem::FramebufferObject);
472 QCOMPARE(hasDirtyContentFlag(&item), true);
473 QCOMPARE(spy.count(), 1);
474
475 clearDirtyContentFlag(item: &item);
476
477 item.setRenderTarget(QQuickPaintedItem::FramebufferObject);
478 QCOMPARE(item.renderTarget(), QQuickPaintedItem::FramebufferObject);
479 QCOMPARE(hasDirtyContentFlag(&item), false);
480 QCOMPARE(spy.count(), 1);
481
482 item.setRenderTarget(QQuickPaintedItem::InvertedYFramebufferObject);
483 QCOMPARE(item.renderTarget(), QQuickPaintedItem::InvertedYFramebufferObject);
484 QCOMPARE(hasDirtyContentFlag(&item), true);
485 QCOMPARE(spy.count(), 2);
486}
487
488QTEST_MAIN(tst_QQuickPaintedItem)
489
490#include "tst_qquickpainteditem.moc"
491

source code of qtdeclarative/tests/auto/quick/qquickpainteditem/tst_qquickpainteditem.cpp