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
35class tst_GLShaderManager : public Qt3DCore::QBackendNodeTester
36{
37 Q_OBJECT
38
39private Q_SLOTS:
40 void adopt();
41 void lookupResource();
42 void abandon();
43 void insertAfterRemoval();
44};
45
46void 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
87void 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
117void 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
155void 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
197QTEST_APPLESS_MAIN(tst_GLShaderManager)
198
199#include "tst_glshadermanager.moc"
200

source code of qt3d/tests/auto/render/opengl/glshadermanager/tst_glshadermanager.cpp