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 | |
45 | class tst_QRenderPass : public QObject |
46 | { |
47 | Q_OBJECT |
48 | |
49 | private 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: ¶meter); |
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: ¶meter); |
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: ¶meter); |
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: ¶meter); |
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 | |
436 | QTEST_MAIN(tst_QRenderPass) |
437 | |
438 | #include "tst_qrenderpass.moc" |
439 | |