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/QTest>
30#include <Qt3DCore/private/qnode_p.h>
31#include <Qt3DCore/private/qscene_p.h>
32#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
33
34#include <Qt3DRender/QAttribute>
35#include <Qt3DRender/private/qattribute_p.h>
36#include <Qt3DRender/QBuffer>
37
38#include "testpostmanarbiter.h"
39
40class tst_QAttribute: public QObject
41{
42 Q_OBJECT
43public:
44 tst_QAttribute()
45 {
46 qRegisterMetaType<Qt3DRender::QBuffer*>(typeName: "Qt3DCore::QBuffer*");
47 }
48
49private Q_SLOTS:
50 void shouldHaveDefaultAttributeNames()
51 {
52 // GIVEN
53 Qt3DRender::QAttribute attribute;
54
55 // THEN
56 QCOMPARE(Qt3DRender::QAttribute::defaultPositionAttributeName(), QStringLiteral("vertexPosition"));
57 QCOMPARE(Qt3DRender::QAttribute::defaultNormalAttributeName(), QStringLiteral("vertexNormal"));
58 QCOMPARE(Qt3DRender::QAttribute::defaultColorAttributeName(), QStringLiteral("vertexColor"));
59 QCOMPARE(Qt3DRender::QAttribute::defaultTextureCoordinateAttributeName(), QStringLiteral("vertexTexCoord"));
60 QCOMPARE(Qt3DRender::QAttribute::defaultTangentAttributeName(), QStringLiteral("vertexTangent"));
61 QCOMPARE(Qt3DRender::QAttribute::defaultJointIndicesAttributeName(), QStringLiteral("vertexJointIndices"));
62 QCOMPARE(Qt3DRender::QAttribute::defaultJointWeightsAttributeName(), QStringLiteral("vertexJointWeights"));
63
64 QCOMPARE(attribute.property("defaultPositionAttributeName").toString(),
65 Qt3DRender::QAttribute::defaultPositionAttributeName());
66 QCOMPARE(attribute.property("defaultNormalAttributeName").toString(),
67 Qt3DRender::QAttribute::defaultNormalAttributeName());
68 QCOMPARE(attribute.property("defaultColorAttributeName").toString(),
69 Qt3DRender::QAttribute::defaultColorAttributeName());
70 QCOMPARE(attribute.property("defaultTextureCoordinateAttributeName").toString(),
71 Qt3DRender::QAttribute::defaultTextureCoordinateAttributeName());
72 QCOMPARE(attribute.property("defaultTangentAttributeName").toString(),
73 Qt3DRender::QAttribute::defaultTangentAttributeName());
74 QCOMPARE(attribute.property("defaultJointIndicesAttributeName").toString(),
75 Qt3DRender::QAttribute::defaultJointIndicesAttributeName());
76 QCOMPARE(attribute.property("defaultJointWeightsAttributeName").toString(),
77 Qt3DRender::QAttribute::defaultJointWeightsAttributeName());
78 }
79
80 void checkCloning_data()
81 {
82 QTest::addColumn<Qt3DRender::QAttribute *>(name: "attribute");
83
84 Qt3DRender::QAttribute *defaultConstructed = new Qt3DRender::QAttribute();
85 QTest::newRow(dataTag: "defaultConstructed") << defaultConstructed;
86
87 Qt3DRender::QAttribute *customVertex = new Qt3DRender::QAttribute();
88 Qt3DRender::QBuffer *buffer = new Qt3DRender::QBuffer();
89 customVertex->setBuffer(buffer);
90 customVertex->setAttributeType(Qt3DRender::QAttribute::VertexAttribute);
91 customVertex->setCount(454);
92 customVertex->setByteStride(427);
93 customVertex->setByteOffset(305);
94 customVertex->setDivisor(235);
95 customVertex->setName("BB");
96 customVertex->setVertexBaseType(Qt3DRender::QAttribute::Float);
97 customVertex->setVertexSize(4);
98 QTest::newRow(dataTag: "vertex") << customVertex;
99
100 Qt3DRender::QAttribute *customIndex = new Qt3DRender::QAttribute();
101 Qt3DRender::QBuffer *indexBuffer = new Qt3DRender::QBuffer();
102 customIndex->setBuffer(indexBuffer);
103 customIndex->setAttributeType(Qt3DRender::QAttribute::IndexAttribute);
104 customIndex->setCount(383);
105 customIndex->setByteStride(350);
106 customIndex->setByteOffset(327);
107 customIndex->setDivisor(355);
108 customIndex->setName("SB");
109 customIndex->setVertexBaseType(Qt3DRender::QAttribute::Float);
110 customIndex->setVertexSize(3);
111 QTest::newRow(dataTag: "index") << customIndex;
112
113 Qt3DRender::QAttribute *customIndirect = new Qt3DRender::QAttribute();
114 Qt3DRender::QBuffer *indirectBuffer = new Qt3DRender::QBuffer();
115 customIndirect->setBuffer(indirectBuffer);
116 customIndirect->setAttributeType(Qt3DRender::QAttribute::DrawIndirectAttribute);
117 customIndirect->setCount(1);
118 customIndirect->setByteStride(12);
119 customIndirect->setByteOffset(0);
120 customIndirect->setName("DrawIndirect");
121 QTest::newRow(dataTag: "index") << customIndirect;
122 }
123
124 void checkCloning()
125 {
126 // GIVEN
127 QFETCH(Qt3DRender::QAttribute *, attribute);
128
129 // WHEN
130 Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(attribute);
131 QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges = creationChangeGenerator.creationChanges();
132
133 // THEN
134 QCOMPARE(creationChanges.size(), 1 + (attribute->buffer() ? 1 : 0));
135
136 const Qt3DCore::QNodeCreatedChangePtr<Qt3DRender::QAttributeData> creationChangeData =
137 qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DRender::QAttributeData>>(src: creationChanges.first());
138 const Qt3DRender::QAttributeData &cloneData = creationChangeData->data;
139
140 QCOMPARE(attribute->id(), creationChangeData->subjectId());
141 QCOMPARE(attribute->isEnabled(), creationChangeData->isNodeEnabled());
142 QCOMPARE(attribute->metaObject(), creationChangeData->metaObject());
143 QCOMPARE(attribute->name(), cloneData.name);
144 QCOMPARE(attribute->count(), cloneData.count);
145 QCOMPARE(attribute->byteStride(), cloneData.byteStride);
146 QCOMPARE(attribute->byteOffset(), cloneData.byteOffset);
147 QCOMPARE(attribute->divisor(), cloneData.divisor);
148 QCOMPARE(attribute->vertexBaseType(), cloneData.vertexBaseType);
149 QCOMPARE(attribute->vertexSize(), cloneData.vertexSize);
150 QVERIFY(attribute->attributeType() == cloneData.attributeType);
151 QCOMPARE(attribute->buffer() ? attribute->buffer()->id() : Qt3DCore::QNodeId(), cloneData.bufferId);
152 }
153
154 void checkPropertyUpdates()
155 {
156 // GIVEN
157 TestArbiter arbiter;
158 QScopedPointer<Qt3DRender::QAttribute> attribute(new Qt3DRender::QAttribute());
159 arbiter.setArbiterOnNode(attribute.data());
160
161 // WHEN
162 attribute->setVertexBaseType(Qt3DRender::QAttribute::Double);
163
164 // THEN
165 QCOMPARE(arbiter.dirtyNodes.size(), 1);
166 QCOMPARE(arbiter.dirtyNodes.front(), attribute.data());
167
168 arbiter.dirtyNodes.clear();
169
170 // WHEN
171 attribute->setVertexSize(4);
172
173 // THEN
174 QCOMPARE(arbiter.dirtyNodes.size(), 1);
175 QCOMPARE(arbiter.dirtyNodes.front(), attribute.data());
176
177 arbiter.dirtyNodes.clear();
178
179 // WHEN
180 attribute->setName(QStringLiteral("Duntov"));
181
182 // THEN
183 QCOMPARE(arbiter.dirtyNodes.size(), 1);
184 QCOMPARE(arbiter.dirtyNodes.front(), attribute.data());
185
186 arbiter.dirtyNodes.clear();
187
188 // WHEN
189 attribute->setCount(883);
190
191 // THEN
192 QCOMPARE(arbiter.dirtyNodes.size(), 1);
193 QCOMPARE(arbiter.dirtyNodes.front(), attribute.data());
194
195 arbiter.dirtyNodes.clear();
196
197 // WHEN
198 attribute->setByteStride(1340);
199
200 // THEN
201 QCOMPARE(arbiter.dirtyNodes.size(), 1);
202 QCOMPARE(arbiter.dirtyNodes.front(), attribute.data());
203
204 arbiter.dirtyNodes.clear();
205
206 // WHEN
207 attribute->setByteOffset(1584);
208
209 // THEN
210 QCOMPARE(arbiter.dirtyNodes.size(), 1);
211 QCOMPARE(arbiter.dirtyNodes.front(), attribute.data());
212
213 arbiter.dirtyNodes.clear();
214
215 // WHEN
216 attribute->setDivisor(1450);
217
218 // THEN
219 QCOMPARE(arbiter.dirtyNodes.size(), 1);
220 QCOMPARE(arbiter.dirtyNodes.front(), attribute.data());
221
222 arbiter.dirtyNodes.clear();
223
224 // WHEN
225 attribute->setAttributeType(Qt3DRender::QAttribute::IndexAttribute);
226
227 // THEN
228 QCOMPARE(arbiter.dirtyNodes.size(), 1);
229 QCOMPARE(arbiter.dirtyNodes.front(), attribute.data());
230
231 arbiter.dirtyNodes.clear();
232
233 // WHEN
234 Qt3DRender::QBuffer buf;
235 attribute->setBuffer(&buf);
236
237 // THEN
238 QCOMPARE(arbiter.dirtyNodes.size(), 1);
239 QCOMPARE(arbiter.dirtyNodes.front(), attribute.data());
240
241 arbiter.dirtyNodes.clear();
242
243 // WHEN
244 Qt3DRender::QBuffer buf2;
245 attribute->setBuffer(&buf2);
246
247 // THEN
248 QCOMPARE(arbiter.dirtyNodes.size(), 1);
249 QCOMPARE(arbiter.dirtyNodes.front(), attribute.data());
250
251 arbiter.dirtyNodes.clear();
252 }
253
254 void checkBufferBookkeeping()
255 {
256 // GIVEN
257 QScopedPointer<Qt3DRender::QAttribute> attribute(new Qt3DRender::QAttribute);
258 {
259 // WHEN
260 Qt3DRender::QBuffer buf;
261 attribute->setBuffer(&buf);
262
263 // THEN
264 QCOMPARE(buf.parent(), attribute.data());
265 QCOMPARE(attribute->buffer(), &buf);
266 }
267 // THEN (Should not crash and parameter be unset)
268 QVERIFY(attribute->buffer() == nullptr);
269
270 {
271 // WHEN
272 Qt3DRender::QAttribute someOtherAttribute;
273 QScopedPointer<Qt3DRender::QBuffer> buf(new Qt3DRender::QBuffer(&someOtherAttribute));
274 attribute->setBuffer(buf.data());
275
276 // THEN
277 QCOMPARE(buf->parent(), &someOtherAttribute);
278 QCOMPARE(attribute->buffer(), buf.data());
279
280 // WHEN
281 attribute.reset();
282 buf.reset();
283
284 // THEN Should not crash when the buffer is destroyed (tests for failed removal of destruction helper)
285 }
286 }
287};
288
289QTEST_MAIN(tst_QAttribute)
290
291#include "tst_qattribute.moc"
292

source code of qt3d/tests/auto/render/qattribute/tst_qattribute.cpp