1/****************************************************************************
2**
3** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB).
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the Qt3D module 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// TODO Remove in Qt6
30#include <QtCore/qcompilerdetection.h>
31QT_WARNING_DISABLE_DEPRECATED
32
33#include <QtTest/QTest>
34#include <qbackendnodetester.h>
35#include <Qt3DRender/private/geometryrenderer_p.h>
36#include <Qt3DRender/private/geometryrenderermanager_p.h>
37#include <Qt3DRender/qgeometry.h>
38#include <Qt3DRender/qgeometryfactory.h>
39#include "testrenderer.h"
40
41class TestFactory : public Qt3DRender::QGeometryFactory
42{
43public:
44 explicit TestFactory(int size)
45 : m_size(size)
46 {}
47
48 Qt3DRender::QGeometry *operator ()() final
49 {
50 return nullptr;
51 }
52
53 bool equals(const Qt3DRender::QGeometryFactory &other) const final
54 {
55 const TestFactory *otherFactory = Qt3DRender::functor_cast<TestFactory>(other: &other);
56 if (otherFactory != nullptr)
57 return otherFactory->m_size == m_size;
58 return false;
59 }
60
61 QT3D_FUNCTOR(TestFactory)
62
63 private:
64 int m_size;
65};
66
67class DummyGeometry : public Qt3DRender::QGeometry
68{
69 Q_OBJECT
70public:
71 DummyGeometry(Qt3DCore::QNode *parent = nullptr)
72 : Qt3DRender::QGeometry(parent)
73 {}
74};
75
76class tst_RenderGeometryRenderer : public Qt3DCore::QBackendNodeTester
77{
78 Q_OBJECT
79
80private Q_SLOTS:
81
82 void checkPeerPropertyMirroring()
83 {
84 // GIVEN
85 Qt3DRender::Render::GeometryRenderer renderGeometryRenderer;
86 Qt3DRender::QGeometryRenderer geometryRenderer;
87 Qt3DRender::QGeometry geometry;
88 Qt3DRender::QGeometryFactoryPtr factory(new TestFactory(1200));
89 Qt3DRender::Render::GeometryRendererManager geometryRendererManager;
90 TestRenderer renderer;
91
92 geometryRenderer.setInstanceCount(1584);
93 geometryRenderer.setVertexCount(1609);
94 geometryRenderer.setIndexOffset(750);
95 geometryRenderer.setFirstInstance(883);
96 geometryRenderer.setIndexBufferByteOffset(96);
97 geometryRenderer.setRestartIndexValue(65536);
98 geometryRenderer.setPrimitiveRestartEnabled(true);
99 geometryRenderer.setPrimitiveType(Qt3DRender::QGeometryRenderer::Patches);
100 geometryRenderer.setGeometry(&geometry);
101 geometryRenderer.setGeometryFactory(factory);
102 geometryRenderer.setEnabled(false);
103
104 // WHEN
105 renderGeometryRenderer.setRenderer(&renderer);
106 renderGeometryRenderer.setManager(&geometryRendererManager);
107 simulateInitializationSync(frontend: &geometryRenderer, backend: &renderGeometryRenderer);
108
109 // THEN
110 QCOMPARE(renderGeometryRenderer.peerId(), geometryRenderer.id());
111 QCOMPARE(renderGeometryRenderer.isDirty(), true);
112 QCOMPARE(renderGeometryRenderer.instanceCount(), geometryRenderer.instanceCount());
113 QCOMPARE(renderGeometryRenderer.vertexCount(), geometryRenderer.vertexCount());
114 QCOMPARE(renderGeometryRenderer.indexOffset(), geometryRenderer.indexOffset());
115 QCOMPARE(renderGeometryRenderer.firstInstance(), geometryRenderer.firstInstance());
116 QCOMPARE(renderGeometryRenderer.indexBufferByteOffset(), geometryRenderer.indexBufferByteOffset());
117 QCOMPARE(renderGeometryRenderer.restartIndexValue(), geometryRenderer.restartIndexValue());
118 QCOMPARE(renderGeometryRenderer.primitiveRestartEnabled(), geometryRenderer.primitiveRestartEnabled());
119 QCOMPARE(renderGeometryRenderer.primitiveType(), geometryRenderer.primitiveType());
120 QCOMPARE(renderGeometryRenderer.geometryId(), geometry.id());
121 QCOMPARE(renderGeometryRenderer.geometryFactory(), factory);
122 QCOMPARE(renderGeometryRenderer.isEnabled(), false);
123 QVERIFY(*renderGeometryRenderer.geometryFactory() == *factory);
124 }
125
126 void checkInitialAndCleanedUpState()
127 {
128 // GIVEN
129 Qt3DRender::Render::GeometryRenderer renderGeometryRenderer;
130 Qt3DRender::Render::GeometryRendererManager geometryRendererManager;
131
132 // THEN
133 QVERIFY(renderGeometryRenderer.peerId().isNull());
134 QVERIFY(renderGeometryRenderer.geometryId().isNull());
135 QCOMPARE(renderGeometryRenderer.isDirty(), false);
136 QCOMPARE(renderGeometryRenderer.instanceCount(), 0);
137 QCOMPARE(renderGeometryRenderer.vertexCount(), 0);
138 QCOMPARE(renderGeometryRenderer.indexOffset(), 0);
139 QCOMPARE(renderGeometryRenderer.firstInstance(), 0);
140 QCOMPARE(renderGeometryRenderer.indexBufferByteOffset(), 0);
141 QCOMPARE(renderGeometryRenderer.restartIndexValue(), -1);
142 QCOMPARE(renderGeometryRenderer.primitiveRestartEnabled(), false);
143 QCOMPARE(renderGeometryRenderer.primitiveType(), Qt3DRender::QGeometryRenderer::Triangles);
144 QVERIFY(renderGeometryRenderer.geometryFactory().isNull());
145 QVERIFY(!renderGeometryRenderer.isEnabled());
146
147 // GIVEN
148 Qt3DRender::QGeometryRenderer geometryRenderer;
149 Qt3DRender::QGeometry geometry;
150 Qt3DRender::QGeometryFactoryPtr factory(new TestFactory(1200));
151 TestRenderer renderer;
152
153 geometryRenderer.setInstanceCount(454);
154 geometryRenderer.setVertexCount(350);
155 geometryRenderer.setIndexOffset(427);
156 geometryRenderer.setFirstInstance(383);
157 geometryRenderer.setIndexBufferByteOffset(96);
158 geometryRenderer.setRestartIndexValue(555);
159 geometryRenderer.setPrimitiveRestartEnabled(true);
160 geometryRenderer.setPrimitiveType(Qt3DRender::QGeometryRenderer::Patches);
161 geometryRenderer.setGeometry(&geometry);
162 geometryRenderer.setGeometryFactory(factory);
163 geometryRenderer.setEnabled(true);
164
165 // WHEN
166 renderGeometryRenderer.setRenderer(&renderer);
167 renderGeometryRenderer.setManager(&geometryRendererManager);
168 simulateInitializationSync(frontend: &geometryRenderer, backend: &renderGeometryRenderer);
169 renderGeometryRenderer.cleanup();
170
171 // THEN
172 QVERIFY(renderGeometryRenderer.geometryId().isNull());
173 QCOMPARE(renderGeometryRenderer.isDirty(), false);
174 QCOMPARE(renderGeometryRenderer.instanceCount(), 0);
175 QCOMPARE(renderGeometryRenderer.vertexCount(), 0);
176 QCOMPARE(renderGeometryRenderer.indexOffset(), 0);
177 QCOMPARE(renderGeometryRenderer.firstInstance(), 0);
178 QCOMPARE(renderGeometryRenderer.indexBufferByteOffset(), 0);
179 QCOMPARE(renderGeometryRenderer.restartIndexValue(), -1);
180 QCOMPARE(renderGeometryRenderer.primitiveRestartEnabled(), false);
181 QCOMPARE(renderGeometryRenderer.primitiveType(), Qt3DRender::QGeometryRenderer::Triangles);
182 QVERIFY(renderGeometryRenderer.geometryFactory().isNull());
183 QVERIFY(!renderGeometryRenderer.isEnabled());
184 }
185
186 void checkPropertyChanges()
187 {
188 // GIVEN
189 Qt3DRender::QGeometryRenderer frontEndRenderer;
190 Qt3DRender::Render::GeometryRenderer backEndRenderer;
191 TestRenderer renderer;
192 backEndRenderer.setRenderer(&renderer);
193
194 QVERIFY(!backEndRenderer.isDirty());
195
196 // WHEN
197 frontEndRenderer.setInstanceCount(2);
198 backEndRenderer.syncFromFrontEnd(frontEnd: &frontEndRenderer, firstTime: false);
199
200 // THEN
201 QCOMPARE(backEndRenderer.instanceCount(), 2);
202 QVERIFY(backEndRenderer.isDirty());
203 QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::GeometryDirty);
204 renderer.clearDirtyBits(changes: Qt3DRender::Render::AbstractRenderer::AllDirty);
205
206 backEndRenderer.unsetDirty();
207 QVERIFY(!backEndRenderer.isDirty());
208
209 // WHEN
210 frontEndRenderer.setVertexCount(56);
211 backEndRenderer.syncFromFrontEnd(frontEnd: &frontEndRenderer, firstTime: false);
212
213 // THEN
214 QCOMPARE(backEndRenderer.vertexCount(), 56);
215 QVERIFY(backEndRenderer.isDirty());
216
217 QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::GeometryDirty);
218 renderer.clearDirtyBits(changes: Qt3DRender::Render::AbstractRenderer::AllDirty);
219
220 backEndRenderer.unsetDirty();
221 QVERIFY(!backEndRenderer.isDirty());
222
223 // WHEN
224 frontEndRenderer.setIndexOffset(65);
225 backEndRenderer.syncFromFrontEnd(frontEnd: &frontEndRenderer, firstTime: false);
226
227 // THEN
228 QCOMPARE(backEndRenderer.indexOffset(), 65);
229 QVERIFY(backEndRenderer.isDirty());
230
231 QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::GeometryDirty);
232 renderer.clearDirtyBits(changes: Qt3DRender::Render::AbstractRenderer::AllDirty);
233
234 backEndRenderer.unsetDirty();
235 QVERIFY(!backEndRenderer.isDirty());
236
237 // WHEN
238 frontEndRenderer.setFirstInstance(82);
239 backEndRenderer.syncFromFrontEnd(frontEnd: &frontEndRenderer, firstTime: false);
240
241 // THEN
242 QCOMPARE(backEndRenderer.firstInstance(), 82);
243 QVERIFY(backEndRenderer.isDirty());
244
245 QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::GeometryDirty);
246 renderer.clearDirtyBits(changes: Qt3DRender::Render::AbstractRenderer::AllDirty);
247
248 backEndRenderer.unsetDirty();
249 QVERIFY(!backEndRenderer.isDirty());
250
251 // WHEN
252 frontEndRenderer.setIndexBufferByteOffset(96);
253 backEndRenderer.syncFromFrontEnd(frontEnd: &frontEndRenderer, firstTime: false);
254
255 // THEN
256 QCOMPARE(backEndRenderer.indexBufferByteOffset(), 96);
257 QVERIFY(backEndRenderer.isDirty());
258
259 QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::GeometryDirty);
260 renderer.clearDirtyBits(changes: Qt3DRender::Render::AbstractRenderer::AllDirty);
261
262 backEndRenderer.unsetDirty();
263 QVERIFY(!backEndRenderer.isDirty());
264
265 // WHEN
266 frontEndRenderer.setRestartIndexValue(46);
267 backEndRenderer.syncFromFrontEnd(frontEnd: &frontEndRenderer, firstTime: false);
268
269 // THEN
270 QCOMPARE(backEndRenderer.restartIndexValue(), 46);
271 QVERIFY(backEndRenderer.isDirty());
272
273 QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::GeometryDirty);
274 renderer.clearDirtyBits(changes: Qt3DRender::Render::AbstractRenderer::AllDirty);
275
276 backEndRenderer.unsetDirty();
277 QVERIFY(!backEndRenderer.isDirty());
278
279 // WHEN
280 frontEndRenderer.setPrimitiveRestartEnabled(true);
281 backEndRenderer.syncFromFrontEnd(frontEnd: &frontEndRenderer, firstTime: false);
282
283 // THEN
284 QCOMPARE(backEndRenderer.primitiveRestartEnabled(), true);
285 QVERIFY(backEndRenderer.isDirty());
286
287 QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::GeometryDirty);
288 renderer.clearDirtyBits(changes: Qt3DRender::Render::AbstractRenderer::AllDirty);
289
290 backEndRenderer.unsetDirty();
291 QVERIFY(!backEndRenderer.isDirty());
292
293 // WHEN
294 frontEndRenderer.setPrimitiveType(Qt3DRender::QGeometryRenderer::LineLoop);
295 backEndRenderer.syncFromFrontEnd(frontEnd: &frontEndRenderer, firstTime: false);
296
297 // THEN
298 QCOMPARE(backEndRenderer.primitiveType(), Qt3DRender::QGeometryRenderer::LineLoop);
299 QVERIFY(backEndRenderer.isDirty());
300
301 QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::GeometryDirty);
302 renderer.clearDirtyBits(changes: Qt3DRender::Render::AbstractRenderer::AllDirty);
303
304 backEndRenderer.unsetDirty();
305 QVERIFY(!backEndRenderer.isDirty());
306
307 // WHEN
308 Qt3DRender::QGeometryFactoryPtr factory(new TestFactory(1450));
309 frontEndRenderer.setGeometryFactory(factory);
310 backEndRenderer.syncFromFrontEnd(frontEnd: &frontEndRenderer, firstTime: false);
311
312 // THEN
313 QCOMPARE(backEndRenderer.geometryFactory(), factory);
314 QVERIFY(backEndRenderer.isDirty());
315
316 QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::GeometryDirty);
317 renderer.clearDirtyBits(changes: Qt3DRender::Render::AbstractRenderer::AllDirty);
318
319 backEndRenderer.unsetDirty();
320 QVERIFY(!backEndRenderer.isDirty());
321
322 // WHEN we set an identical factory again
323 Qt3DRender::QGeometryFactoryPtr factory2(new TestFactory(1450));
324 frontEndRenderer.setGeometryFactory(factory2);
325 backEndRenderer.syncFromFrontEnd(frontEnd: &frontEndRenderer, firstTime: false);
326
327 // THEN not dirty and still uses original factory
328 QCOMPARE(backEndRenderer.geometryFactory(), factory);
329 QVERIFY(!backEndRenderer.isDirty());
330
331 // WHEN
332 DummyGeometry geometry;
333 const Qt3DCore::QNodeId geometryId = geometry.id();
334 frontEndRenderer.setGeometry(&geometry);
335 backEndRenderer.syncFromFrontEnd(frontEnd: &frontEndRenderer, firstTime: false);
336
337 // THEN
338 QCOMPARE(backEndRenderer.geometryId(), geometryId);
339 QVERIFY(backEndRenderer.isDirty());
340
341 QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::GeometryDirty);
342 renderer.clearDirtyBits(changes: Qt3DRender::Render::AbstractRenderer::AllDirty);
343
344 backEndRenderer.unsetDirty();
345 QVERIFY(!backEndRenderer.isDirty());
346
347 // WHEN
348 frontEndRenderer.setGeometry(nullptr);
349 backEndRenderer.syncFromFrontEnd(frontEnd: &frontEndRenderer, firstTime: false);
350
351 // THEN
352 QCOMPARE(backEndRenderer.geometryId(), Qt3DCore::QNodeId());
353 QVERIFY(backEndRenderer.isDirty());
354
355 QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::GeometryDirty);
356 renderer.clearDirtyBits(changes: Qt3DRender::Render::AbstractRenderer::AllDirty);
357
358 backEndRenderer.unsetDirty();
359 QVERIFY(!backEndRenderer.isDirty());
360
361 // WHEN
362 frontEndRenderer.setEnabled(true);
363 backEndRenderer.syncFromFrontEnd(frontEnd: &frontEndRenderer, firstTime: false);
364
365 // THEN
366 QCOMPARE(backEndRenderer.isEnabled(), true);
367 QVERIFY(!backEndRenderer.isDirty());
368 }
369
370 void checkSetRendererDirtyOnInitialization()
371 {
372 // GIVEN
373 Qt3DRender::Render::GeometryRendererManager geometryRendererManager;
374 Qt3DRender::Render::GeometryRenderer renderGeometryRenderer;
375 Qt3DRender::QGeometryRenderer geometryRenderer;
376 TestRenderer renderer;
377
378 renderGeometryRenderer.setRenderer(&renderer);
379 renderGeometryRenderer.setManager(&geometryRendererManager);
380
381 // THEN
382 QCOMPARE(renderer.dirtyBits(), 0);
383
384 // WHEN
385 simulateInitializationSync(frontend: &geometryRenderer, backend: &renderGeometryRenderer);
386
387 // THEN
388 QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::GeometryDirty);
389 }
390};
391
392QTEST_APPLESS_MAIN(tst_RenderGeometryRenderer)
393
394#include "tst_geometryrenderer.moc"
395

source code of qt3d/tests/auto/render/geometryrenderer/tst_geometryrenderer.cpp