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#include <QtTest/QtTest>
30#include <qbackendnodetester.h>
31#include <Qt3DRender/private/renderpass_p.h>
32
33#include <Qt3DRender/QFilterKey>
34#include <Qt3DRender/QRenderPass>
35#include <Qt3DRender/QShaderProgram>
36#include <Qt3DRender/QParameter>
37
38#include <Qt3DRender/QAlphaCoverage>
39#include <Qt3DRender/QAlphaTest>
40#include <Qt3DRender/QBlendEquation>
41#include <Qt3DRender/QBlendEquationArguments>
42#include <Qt3DRender/QColorMask>
43#include <Qt3DRender/QCullFace>
44#include <Qt3DRender/QNoDepthMask>
45#include <Qt3DRender/QDepthTest>
46#include <Qt3DRender/QDithering>
47#include <Qt3DRender/QFrontFace>
48#include <Qt3DRender/QPolygonOffset>
49#include <Qt3DRender/QScissorTest>
50#include <Qt3DRender/QStencilTest>
51#include <Qt3DRender/QStencilTestArguments>
52#include <Qt3DRender/QStencilMask>
53#include <Qt3DRender/QStencilOperation>
54#include <Qt3DRender/QStencilOperationArguments>
55#include <Qt3DRender/QClipPlane>
56
57#include <Qt3DRender/private/renderstates_p.h>
58#include <Qt3DRender/private/managers_p.h>
59
60#include "testrenderer.h"
61
62using namespace Qt3DCore;
63using namespace Qt3DRender;
64using namespace Qt3DRender::Render;
65
66class tst_RenderRenderPass : public Qt3DCore::QBackendNodeTester
67{
68 Q_OBJECT
69
70public:
71 tst_RenderRenderPass()
72 : m_renderStateManager(new RenderStateManager())
73 {
74 qRegisterMetaType<Qt3DCore::QNode *>();
75 }
76 ~tst_RenderRenderPass() {}
77
78private slots:
79 void shouldHaveInitialState()
80 {
81 // GIVEN
82 RenderPass backend;
83
84 // THEN
85 QVERIFY(!backend.isEnabled());
86 QVERIFY(backend.shaderProgram().isNull());
87 QVERIFY(backend.filterKeys().isEmpty());
88 QVERIFY(backend.renderStates().isEmpty());
89 QVERIFY(backend.parameters().isEmpty());
90 }
91
92 void checkCleanupState()
93 {
94 // GIVEN
95 RenderPass backend;
96 TestRenderer renderer;
97 backend.setRenderer(&renderer);
98
99 // WHEN
100 backend.setEnabled(true);
101
102 {
103 QRenderPass frontend;
104 QShaderProgram program;
105 QBlendEquationArguments state;
106 QParameter parameter;
107 QFilterKey filterKey;
108
109 frontend.addFilterKey(filterKey: &filterKey);
110 frontend.addParameter(p: &parameter);
111 frontend.addRenderState(state: &state);
112 frontend.setShaderProgram(&program);
113
114 simulateInitializationSync(frontend: &frontend, backend: &backend);
115 }
116
117 backend.cleanup();
118
119 // THEN
120 QVERIFY(!backend.isEnabled());
121 QVERIFY(backend.shaderProgram().isNull());
122 QVERIFY(backend.filterKeys().isEmpty());
123 QVERIFY(backend.renderStates().isEmpty());
124 QVERIFY(backend.parameters().isEmpty());
125 QVERIFY(!backend.hasRenderStates());
126 }
127
128 void shouldHavePropertiesMirroringItsPeer()
129 {
130 // GIVEN
131 QRenderPass frontend;
132 frontend.setShaderProgram(new QShaderProgram(&frontend));
133
134 frontend.addFilterKey(filterKey: new QFilterKey(&frontend));
135
136 frontend.addParameter(p: new QParameter(&frontend));
137
138 QRenderState *frontendState = new QBlendEquationArguments();
139 frontendState->setParent(&frontend);
140 frontend.addRenderState(state: frontendState);
141
142 RenderPass backend;
143 TestRenderer renderer;
144 backend.setRenderer(&renderer);
145
146 RenderStateNode *backendState = m_renderStateManager->getOrCreateResource(id: frontendState->id());
147 backendState->setRenderer(&renderer);
148 simulateInitializationSync(frontend: frontendState, backend: backendState);
149
150 // WHEN
151 simulateInitializationSync(frontend: &frontend, backend: &backend);
152
153 // THEN
154 QCOMPARE(backend.shaderProgram(), frontend.shaderProgram()->id());
155
156 QCOMPARE(backend.filterKeys().size(), 1);
157 QCOMPARE(backend.filterKeys().first(), frontend.filterKeys().first()->id());
158
159 QCOMPARE(backend.parameters().size(), 1);
160 QCOMPARE(backend.parameters().first(), frontend.parameters().first()->id());
161
162 QCOMPARE(backend.renderStates().size(), 1);
163 QCOMPARE(backend.renderStates().first(), backendState->peerId());
164 QVERIFY(backend.hasRenderStates());
165 }
166
167 void shouldHandleShaderPropertyChangeEvents()
168 {
169 // GIVEN
170 QShaderProgram *shader = new QShaderProgram;
171
172 RenderPass backend;
173 TestRenderer renderer;
174 backend.setRenderer(&renderer);
175
176 QRenderPass frontend;
177 simulateInitializationSync(frontend: &frontend, backend: &backend);
178
179 // WHEN
180 frontend.setShaderProgram(shader);
181 backend.syncFromFrontEnd(frontEnd: &frontend, firstTime: false);
182
183 // THEN
184 QCOMPARE(backend.shaderProgram(), shader->id());
185 QVERIFY(renderer.dirtyBits() != 0);
186
187 // WHEN
188 frontend.setShaderProgram(nullptr);
189 backend.syncFromFrontEnd(frontEnd: &frontend, firstTime: false);
190
191 // THEN
192 QVERIFY(backend.shaderProgram().isNull());
193 }
194
195 void shouldHandleAnnotationsPropertyChangeEvents()
196 {
197 // GIVEN
198 QFilterKey *annotation = new QFilterKey;
199
200 RenderPass backend;
201 TestRenderer renderer;
202 backend.setRenderer(&renderer);
203
204 QRenderPass frontend;
205 simulateInitializationSync(frontend: &frontend, backend: &backend);
206
207 // WHEN
208 frontend.addFilterKey(filterKey: annotation);
209 backend.syncFromFrontEnd(frontEnd: &frontend, firstTime: false);
210
211 // THEN
212 QCOMPARE(backend.filterKeys().size(), 1);
213 QCOMPARE(backend.filterKeys().first(), annotation->id());
214 QVERIFY(renderer.dirtyBits() != 0);
215
216 // WHEN
217 frontend.removeFilterKey(filterKey: annotation);
218 backend.syncFromFrontEnd(frontEnd: &frontend, firstTime: false);
219
220 // THEN
221 QVERIFY(backend.filterKeys().isEmpty());
222 }
223
224 void shouldHandleParametersPropertyChangeEvents()
225 {
226 // GIVEN
227 QParameter *parameter = new QParameter;
228
229 RenderPass backend;
230 TestRenderer renderer;
231 backend.setRenderer(&renderer);
232
233 QRenderPass frontend;
234 simulateInitializationSync(frontend: &frontend, backend: &backend);
235
236 // WHEN
237 frontend.addParameter(p: parameter);
238 backend.syncFromFrontEnd(frontEnd: &frontend, firstTime: false);
239
240 // THEN
241 QCOMPARE(backend.parameters().size(), 1);
242 QCOMPARE(backend.parameters().first(), parameter->id());
243 QVERIFY(renderer.dirtyBits() != 0);
244
245 // WHEN
246 frontend.removeParameter(p: parameter);
247 backend.syncFromFrontEnd(frontEnd: &frontend, firstTime: false);
248
249 // THEN
250 QVERIFY(backend.parameters().isEmpty());
251 }
252
253 void shouldHandleRenderStatePropertyChangeEvents()
254 {
255 QRenderState *frontendState = new QBlendEquationArguments();
256
257 RenderPass backend;
258 TestRenderer renderer;
259 backend.setRenderer(&renderer);
260
261 RenderStateNode *backendState = m_renderStateManager->getOrCreateResource(id: frontendState->id());
262 backendState->setRenderer(&renderer);
263 simulateInitializationSync(frontend: frontendState, backend: backendState);
264
265 QRenderPass frontend;
266 simulateInitializationSync(frontend: &frontend, backend: &backend);
267
268 // WHEN
269 frontend.addRenderState(state: frontendState);
270 backend.syncFromFrontEnd(frontEnd: &frontend, firstTime: false);
271
272 // THEN
273 QCOMPARE(backend.renderStates().size(), 1);
274 QCOMPARE(backend.renderStates().first(), backendState->peerId());
275 QVERIFY(renderer.dirtyBits() != 0);
276
277 // WHEN
278 frontend.removeRenderState(state: frontendState);
279 backend.syncFromFrontEnd(frontEnd: &frontend, firstTime: false);
280
281 // THEN
282 QVERIFY(backend.renderStates().isEmpty());
283 }
284
285private:
286 RenderStateManager *m_renderStateManager;
287};
288
289QTEST_APPLESS_MAIN(tst_RenderRenderPass)
290
291#include "tst_renderpass.moc"
292

source code of qt3d/tests/auto/render/renderpass/tst_renderpass.cpp