1/****************************************************************************
2**
3** Copyright (C) 2016 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
30#include <QtTest/QTest>
31#include <Qt3DRender/qrenderpass.h>
32#include <Qt3DRender/qfilterkey.h>
33#include <Qt3DRender/qparameter.h>
34#include <Qt3DRender/qdepthtest.h>
35#include <Qt3DRender/qshaderprogram.h>
36#include <Qt3DRender/private/qrenderpass_p.h>
37#include <QObject>
38#include <QSignalSpy>
39#include <Qt3DCore/qpropertynodeaddedchange.h>
40#include <Qt3DCore/qpropertynoderemovedchange.h>
41#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
42#include <Qt3DCore/qnodecreatedchange.h>
43#include "testpostmanarbiter.h"
44
45class tst_QRenderPass : public QObject
46{
47 Q_OBJECT
48
49private Q_SLOTS:
50
51 void initTestCase()
52 {
53 qRegisterMetaType<Qt3DRender::QShaderProgram *>(typeName: "QShaderProgram *");
54 }
55
56 void checkDefaultConstruction()
57 {
58 // GIVEN
59 Qt3DRender::QRenderPass renderPass;
60
61 // THEN
62 QVERIFY(renderPass.shaderProgram() == nullptr);
63 QCOMPARE(renderPass.filterKeys().size(), 0);
64 QCOMPARE(renderPass.renderStates().size(), 0);
65 QCOMPARE(renderPass.parameters().size(), 0);
66 }
67
68 void checkPropertyChanges()
69 {
70 // GIVEN
71 Qt3DRender::QRenderPass renderPass;
72
73 {
74 // WHEN
75 QSignalSpy spy(&renderPass, SIGNAL(shaderProgramChanged(QShaderProgram *)));
76 Qt3DRender::QShaderProgram newValue;
77 renderPass.setShaderProgram(&newValue);
78
79 // THEN
80 QVERIFY(spy.isValid());
81 QCOMPARE(renderPass.shaderProgram(), &newValue);
82 QCOMPARE(spy.count(), 1);
83
84 // WHEN
85 spy.clear();
86 renderPass.setShaderProgram(&newValue);
87
88 // THEN
89 QCOMPARE(renderPass.shaderProgram(), &newValue);
90 QCOMPARE(spy.count(), 0);
91 }
92 {
93 // WHEN
94 Qt3DRender::QFilterKey newValue;
95 renderPass.addFilterKey(filterKey: &newValue);
96
97 // THEN
98 QCOMPARE(renderPass.filterKeys().size(), 1);
99
100 // WHEN
101 renderPass.addFilterKey(filterKey: &newValue);
102
103 // THEN
104 QCOMPARE(renderPass.filterKeys().size(), 1);
105
106 // WHEN
107 renderPass.removeFilterKey(filterKey: &newValue);
108
109 // THEN
110 QCOMPARE(renderPass.filterKeys().size(), 0);
111 }
112 {
113 // WHEN
114 Qt3DRender::QDepthTest newValue;
115 renderPass.addRenderState(state: &newValue);
116
117 // THEN
118 QCOMPARE(renderPass.renderStates().size(), 1);
119
120 // WHEN
121 renderPass.addRenderState(state: &newValue);
122
123 // THEN
124 QCOMPARE(renderPass.renderStates().size(), 1);
125
126 // WHEN
127 renderPass.removeRenderState(state: &newValue);
128
129 // THEN
130 QCOMPARE(renderPass.renderStates().size(), 0);
131 }
132 {
133 // WHEN
134 Qt3DRender::QParameter newValue;
135 renderPass.addParameter(p: &newValue);
136
137 // THEN
138 QCOMPARE(renderPass.parameters().size(), 1);
139
140 // WHEN
141 renderPass.addParameter(p: &newValue);
142
143 // THEN
144 QCOMPARE(renderPass.parameters().size(), 1);
145
146 // WHEN
147 renderPass.removeParameter(p: &newValue);
148
149 // THEN
150 QCOMPARE(renderPass.parameters().size(), 0);
151 }
152 }
153
154 void checkCreationData()
155 {
156 // GIVEN
157 Qt3DRender::QRenderPass renderPass;
158
159 Qt3DRender::QShaderProgram shader;
160 renderPass.setShaderProgram(&shader);
161 Qt3DRender::QFilterKey filterKey;
162 renderPass.addFilterKey(filterKey: &filterKey);
163 Qt3DRender::QDepthTest renderState;
164 renderPass.addRenderState(state: &renderState);
165 Qt3DRender::QParameter parameter;
166 renderPass.addParameter(p: &parameter);
167
168 // WHEN
169 QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges;
170
171 {
172 Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&renderPass);
173 creationChanges = creationChangeGenerator.creationChanges();
174 }
175
176 // THEN
177 {
178 QCOMPARE(creationChanges.size(), 5); // RenderPass + Shader + FilterKey + Parameter + State
179
180 const auto creationChangeData = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DRender::QRenderPassData>>(src: creationChanges.first());
181 const Qt3DRender::QRenderPassData cloneData = creationChangeData->data;
182
183 QCOMPARE(renderPass.shaderProgram()->id(), cloneData.shaderId);
184 QCOMPARE(cloneData.filterKeyIds.size(), 1);
185 QCOMPARE(filterKey.id(), cloneData.filterKeyIds.first());
186 QCOMPARE(cloneData.renderStateIds.size(), 1);
187 QCOMPARE(renderState.id(), cloneData.renderStateIds.first());
188 QCOMPARE(cloneData.parameterIds.size(), 1);
189 QCOMPARE(parameter.id(), cloneData.parameterIds.first());
190 QCOMPARE(renderPass.id(), creationChangeData->subjectId());
191 QCOMPARE(renderPass.isEnabled(), true);
192 QCOMPARE(renderPass.isEnabled(), creationChangeData->isNodeEnabled());
193 QCOMPARE(renderPass.metaObject(), creationChangeData->metaObject());
194 }
195
196 // WHEN
197 renderPass.setEnabled(false);
198
199 {
200 Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&renderPass);
201 creationChanges = creationChangeGenerator.creationChanges();
202 }
203
204 // THEN
205 {
206 QCOMPARE(creationChanges.size(), 5); // RenderPass + Shader + FilterKey + Parameter + State
207
208 const auto creationChangeData = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DRender::QRenderPassData>>(src: creationChanges.first());
209 const Qt3DRender::QRenderPassData cloneData = creationChangeData->data;
210
211 QCOMPARE(renderPass.shaderProgram()->id(), cloneData.shaderId);
212 QCOMPARE(cloneData.filterKeyIds.size(), 1);
213 QCOMPARE(filterKey.id(), cloneData.filterKeyIds.first());
214 QCOMPARE(cloneData.renderStateIds.size(), 1);
215 QCOMPARE(renderState.id(), cloneData.renderStateIds.first());
216 QCOMPARE(cloneData.parameterIds.size(), 1);
217 QCOMPARE(parameter.id(), cloneData.parameterIds.first());
218 QCOMPARE(renderPass.id(), creationChangeData->subjectId());
219 QCOMPARE(renderPass.isEnabled(), false);
220 QCOMPARE(renderPass.isEnabled(), creationChangeData->isNodeEnabled());
221 QCOMPARE(renderPass.metaObject(), creationChangeData->metaObject());
222 }
223 }
224
225 void checkShaderProgramBookkeeping()
226 {
227 // GIVEN
228 Qt3DRender::QRenderPass renderPass;
229
230 {
231 // WHEN
232 Qt3DRender::QShaderProgram shaderProgram;
233 renderPass.setShaderProgram(&shaderProgram);
234
235 QCOMPARE(renderPass.shaderProgram(), &shaderProgram);
236 }
237
238 // THEN -> should not crash
239 QVERIFY(renderPass.shaderProgram() == nullptr);
240 }
241
242 void checkFilterKeyBookkeeping()
243 {
244 // GIVEN
245 Qt3DRender::QRenderPass renderPass;
246
247 {
248 // WHEN
249 Qt3DRender::QFilterKey filterKey;
250 renderPass.addFilterKey(filterKey: &filterKey);
251
252 QCOMPARE(renderPass.filterKeys().size(), 1);
253 }
254
255 // THEN -> should not crash
256 QCOMPARE(renderPass.filterKeys().size(), 0);
257 }
258
259 void checkRenderStateBookkeeping()
260 {
261 // GIVEN
262 Qt3DRender::QRenderPass renderPass;
263
264 {
265 // WHEN
266 Qt3DRender::QDepthTest renderState;
267 renderPass.addRenderState(state: &renderState);
268
269 QCOMPARE(renderPass.renderStates().size(), 1);
270 }
271
272 // THEN -> should not crash
273 QCOMPARE(renderPass.renderStates().size(), 0);
274 }
275
276 void checkParameterBookkeeping()
277 {
278 // GIVEN
279 Qt3DRender::QRenderPass renderPass;
280
281 {
282 // WHEN
283 Qt3DRender::QParameter parameter;
284 renderPass.addParameter(p: &parameter);
285
286 QCOMPARE(renderPass.parameters().size(), 1);
287 }
288
289 // THEN -> should not crash
290 QCOMPARE(renderPass.parameters().size(), 0);
291 }
292
293 void checkShaderProgramUpdate()
294 {
295 // GIVEN
296 TestArbiter arbiter;
297 Qt3DRender::QRenderPass renderPass;
298 Qt3DRender::QShaderProgram shaderProgram;
299 arbiter.setArbiterOnNode(&renderPass);
300
301 {
302 // WHEN
303 renderPass.setShaderProgram(&shaderProgram);
304 QCoreApplication::processEvents();
305
306 // THEN
307 QCOMPARE(arbiter.events.size(), 0);
308 QCOMPARE(arbiter.dirtyNodes.size(), 1);
309 QCOMPARE(arbiter.dirtyNodes.front(), &renderPass);
310
311 arbiter.dirtyNodes.clear();
312 }
313
314 {
315 // WHEN
316 renderPass.setShaderProgram(&shaderProgram);
317 QCoreApplication::processEvents();
318
319 // THEN
320 QCOMPARE(arbiter.events.size(), 0);
321 QCOMPARE(arbiter.dirtyNodes.size(), 0);
322 }
323
324 }
325
326 void checkFilterKeyUpdate()
327 {
328 // GIVEN
329 TestArbiter arbiter;
330 Qt3DRender::QRenderPass renderPass;
331 Qt3DRender::QFilterKey filterKey;
332 arbiter.setArbiterOnNode(&renderPass);
333
334 {
335 // WHEN
336 renderPass.addFilterKey(filterKey: &filterKey);
337 QCoreApplication::processEvents();
338
339 // THEN
340 QCOMPARE(arbiter.events.size(), 0);
341 QCOMPARE(arbiter.dirtyNodes.size(), 1);
342 QCOMPARE(arbiter.dirtyNodes.front(), &renderPass);
343
344 arbiter.events.clear();
345 }
346
347 {
348 // WHEN
349 renderPass.removeFilterKey(filterKey: &filterKey);
350 QCoreApplication::processEvents();
351
352 // THEN
353 QCOMPARE(arbiter.events.size(), 0);
354 QCOMPARE(arbiter.dirtyNodes.size(), 1);
355 QCOMPARE(arbiter.dirtyNodes.front(), &renderPass);
356
357 arbiter.events.clear();
358 }
359
360 }
361
362 void checkRenderStateUpdate()
363 {
364 // GIVEN
365 TestArbiter arbiter;
366 Qt3DRender::QRenderPass renderPass;
367 Qt3DRender::QDepthTest renderState;
368 arbiter.setArbiterOnNode(&renderPass);
369
370 {
371 // WHEN
372 renderPass.addRenderState(state: &renderState);
373 QCoreApplication::processEvents();
374
375 // THEN
376 QCOMPARE(arbiter.events.size(), 0);
377 QCOMPARE(arbiter.dirtyNodes.size(), 1);
378 QCOMPARE(arbiter.dirtyNodes.front(), &renderPass);
379
380 arbiter.events.clear();
381 }
382
383 {
384 // WHEN
385 renderPass.removeRenderState(state: &renderState);
386 QCoreApplication::processEvents();
387
388 // THEN
389 QCOMPARE(arbiter.events.size(), 0);
390 QCOMPARE(arbiter.dirtyNodes.size(), 1);
391 QCOMPARE(arbiter.dirtyNodes.front(), &renderPass);
392
393 arbiter.events.clear();
394 }
395
396 }
397
398 void checkParameterUpdate()
399 {
400 // GIVEN
401 TestArbiter arbiter;
402 Qt3DRender::QRenderPass renderPass;
403 Qt3DRender::QParameter parameter;
404 arbiter.setArbiterOnNode(&renderPass);
405
406 {
407 // WHEN
408 renderPass.addParameter(p: &parameter);
409 QCoreApplication::processEvents();
410
411 // THEN
412 QCOMPARE(arbiter.events.size(), 0);
413 QCOMPARE(arbiter.dirtyNodes.size(), 1);
414 QCOMPARE(arbiter.dirtyNodes.front(), &renderPass);
415
416 arbiter.events.clear();
417 }
418
419 {
420 // WHEN
421 renderPass.removeParameter(p: &parameter);
422 QCoreApplication::processEvents();
423
424 // THEN
425 QCOMPARE(arbiter.events.size(), 0);
426 QCOMPARE(arbiter.dirtyNodes.size(), 1);
427 QCOMPARE(arbiter.dirtyNodes.front(), &renderPass);
428
429 arbiter.events.clear();
430 }
431
432 }
433
434};
435
436QTEST_MAIN(tst_QRenderPass)
437
438#include "tst_qrenderpass.moc"
439

source code of qt3d/tests/auto/render/qrenderpass/tst_qrenderpass.cpp