1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2017 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/QTest> |
30 | #include <glresourcemanagers_p.h> |
31 | #include <Qt3DCore/qnodeid.h> |
32 | #include "qbackendnodetester.h" |
33 | #include "testrenderer.h" |
34 | |
35 | class tst_GLShaderManager : public Qt3DCore::QBackendNodeTester |
36 | { |
37 | Q_OBJECT |
38 | |
39 | private Q_SLOTS: |
40 | void adopt(); |
41 | void lookupResource(); |
42 | void abandon(); |
43 | void insertAfterRemoval(); |
44 | }; |
45 | |
46 | void tst_GLShaderManager::adopt() |
47 | { |
48 | // GIVEN |
49 | Qt3DRender::Render::OpenGL::GLShaderManager cache; |
50 | Qt3DRender::QShaderProgram frontendShader1; |
51 | Qt3DRender::QShaderProgram frontendShader2; |
52 | TestRenderer renderer; |
53 | Qt3DRender::Render::Shader backendShaderNode1; |
54 | Qt3DRender::Render::Shader backendShaderNode2; |
55 | |
56 | backendShaderNode1.setRenderer(&renderer); |
57 | backendShaderNode2.setRenderer(&renderer); |
58 | simulateInitialization(frontend: &frontendShader1, backend: &backendShaderNode1); |
59 | simulateInitialization(frontend: &frontendShader2, backend: &backendShaderNode2); |
60 | |
61 | // THEN |
62 | QVERIFY(cache.lookupResource(backendShaderNode1.peerId()) == nullptr); |
63 | QVERIFY(cache.lookupResource(backendShaderNode2.peerId()) == nullptr); |
64 | QVERIFY(backendShaderNode1.peerId() != backendShaderNode2.peerId()); |
65 | |
66 | // WHEN |
67 | Qt3DRender::Render::OpenGL::GLShader *glShader1 = cache.createOrAdoptExisting(shader: &backendShaderNode1); |
68 | |
69 | // THEN |
70 | QVERIFY(glShader1 != nullptr); |
71 | QVector<Qt3DCore::QNodeId> shaderNodeIds = cache.shaderIdsForProgram(glShader: glShader1); |
72 | QCOMPARE(shaderNodeIds.size(), 1); |
73 | QCOMPARE(shaderNodeIds.first(), backendShaderNode1.peerId()); |
74 | |
75 | // WHEN |
76 | Qt3DRender::Render::OpenGL::GLShader *glShader2 = cache.createOrAdoptExisting(shader: &backendShaderNode2); |
77 | |
78 | // THEN |
79 | QCOMPARE(glShader1, glShader2); |
80 | |
81 | shaderNodeIds = cache.shaderIdsForProgram(glShader: glShader2); |
82 | QCOMPARE(shaderNodeIds.size(), 2); |
83 | QCOMPARE(shaderNodeIds.first(), backendShaderNode1.peerId()); |
84 | QCOMPARE(shaderNodeIds.last(), backendShaderNode2.peerId()); |
85 | } |
86 | |
87 | void tst_GLShaderManager::lookupResource() |
88 | { |
89 | // GIVEN |
90 | Qt3DRender::Render::OpenGL::GLShaderManager cache; |
91 | Qt3DRender::QShaderProgram frontendShader1; |
92 | Qt3DRender::QShaderProgram frontendShader2; |
93 | TestRenderer renderer; |
94 | Qt3DRender::Render::Shader backendShaderNode1; |
95 | Qt3DRender::Render::Shader backendShaderNode2; |
96 | |
97 | backendShaderNode1.setRenderer(&renderer); |
98 | backendShaderNode2.setRenderer(&renderer); |
99 | simulateInitialization(frontend: &frontendShader1, backend: &backendShaderNode1); |
100 | simulateInitialization(frontend: &frontendShader2, backend: &backendShaderNode2); |
101 | |
102 | // WHEN |
103 | cache.createOrAdoptExisting(shader: &backendShaderNode1); |
104 | cache.createOrAdoptExisting(shader: &backendShaderNode2); |
105 | |
106 | // THEN |
107 | Qt3DRender::Render::OpenGL::GLShader *glShader1 = cache.lookupResource(shaderId: backendShaderNode1.peerId()); |
108 | Qt3DRender::Render::OpenGL::GLShader *glShader2 = cache.lookupResource(shaderId: backendShaderNode2.peerId()); |
109 | QVERIFY(glShader1 != nullptr); |
110 | QCOMPARE(glShader1, glShader2); |
111 | const QVector<Qt3DCore::QNodeId> shaderNodeIds = cache.shaderIdsForProgram(glShader: glShader1); |
112 | QCOMPARE(shaderNodeIds.size(), 2); |
113 | QVERIFY(shaderNodeIds.contains(frontendShader1.id())); |
114 | QVERIFY(shaderNodeIds.contains(frontendShader2.id())); |
115 | } |
116 | |
117 | void tst_GLShaderManager::abandon() |
118 | { |
119 | // GIVEN |
120 | Qt3DRender::Render::OpenGL::GLShaderManager cache; |
121 | Qt3DRender::QShaderProgram frontendShader1; |
122 | Qt3DRender::QShaderProgram frontendShader2; |
123 | TestRenderer renderer; |
124 | Qt3DRender::Render::Shader backendShaderNode1; |
125 | Qt3DRender::Render::Shader backendShaderNode2; |
126 | |
127 | backendShaderNode1.setRenderer(&renderer); |
128 | backendShaderNode2.setRenderer(&renderer); |
129 | simulateInitialization(frontend: &frontendShader1, backend: &backendShaderNode1); |
130 | simulateInitialization(frontend: &frontendShader2, backend: &backendShaderNode2); |
131 | cache.createOrAdoptExisting(shader: &backendShaderNode1); |
132 | cache.createOrAdoptExisting(shader: &backendShaderNode2); |
133 | |
134 | // WHEN |
135 | Qt3DRender::Render::OpenGL::GLShader *glShader = cache.lookupResource(shaderId: backendShaderNode1.peerId()); |
136 | cache.abandon(apiShader: glShader, shader: &backendShaderNode1); |
137 | |
138 | // THEN |
139 | QVector<Qt3DCore::QNodeId> shaderNodeIds = cache.shaderIdsForProgram(glShader); |
140 | QVERIFY(cache.takeAbandonned().isEmpty()); |
141 | QCOMPARE(shaderNodeIds.size(), 1); |
142 | QCOMPARE(shaderNodeIds.first(), backendShaderNode2.peerId()); |
143 | |
144 | // WHEN |
145 | cache.abandon(apiShader: glShader, shader: &backendShaderNode2); |
146 | |
147 | // THEN |
148 | shaderNodeIds = cache.shaderIdsForProgram(glShader); |
149 | QCOMPARE(shaderNodeIds.size(), 0); |
150 | const QVector<Qt3DRender::Render::OpenGL::GLShader *> releasedShaders = cache.takeAbandonned(); |
151 | QCOMPARE(releasedShaders.size(), 1); |
152 | QCOMPARE(releasedShaders.first(), glShader); |
153 | } |
154 | |
155 | void tst_GLShaderManager::insertAfterRemoval() |
156 | { |
157 | // GIVEN |
158 | Qt3DRender::Render::OpenGL::GLShaderManager cache; |
159 | Qt3DRender::QShaderProgram frontendShader; |
160 | TestRenderer renderer; |
161 | Qt3DRender::Render::Shader backendShaderNode; |
162 | |
163 | |
164 | backendShaderNode.setRenderer(&renderer); |
165 | simulateInitialization(frontend: &frontendShader, backend: &backendShaderNode); |
166 | |
167 | // WHEN |
168 | Qt3DRender::Render::OpenGL::GLShader *apiShader1 = cache.createOrAdoptExisting(shader: &backendShaderNode); |
169 | const Qt3DRender::Render::OpenGL::GLShader *originalApiShader = apiShader1; |
170 | |
171 | // THEN |
172 | auto apiShader2 = cache.lookupResource(shaderId: frontendShader.id()); |
173 | QVERIFY(apiShader1 != nullptr); |
174 | QVERIFY(apiShader2 != nullptr); |
175 | QVERIFY(apiShader1 == originalApiShader); |
176 | QVERIFY(apiShader1 == apiShader2); |
177 | |
178 | // WHEN |
179 | cache.abandon(apiShader: apiShader1, shader: &backendShaderNode); |
180 | |
181 | // THEN |
182 | Qt3DRender::Render::OpenGL::GLShader *apiShaderEmpty = cache.lookupResource(shaderId: frontendShader.id()); |
183 | QVERIFY(apiShaderEmpty == nullptr); |
184 | |
185 | // WHEN |
186 | apiShader1 = cache.createOrAdoptExisting(shader: &backendShaderNode); |
187 | cache.purge(); |
188 | apiShader2 = cache.lookupResource(shaderId: frontendShader.id()); |
189 | |
190 | // THEN |
191 | QVERIFY(apiShader1 != nullptr); |
192 | QVERIFY(apiShader2 != nullptr); |
193 | QVERIFY(apiShader1 == apiShader2); |
194 | QVERIFY(apiShader2 == originalApiShader); |
195 | } |
196 | |
197 | QTEST_APPLESS_MAIN(tst_GLShaderManager) |
198 | |
199 | #include "tst_glshadermanager.moc" |
200 | |