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 | // TODO Remove in Qt6 |
30 | #include <QtCore/qcompilerdetection.h> |
31 | QT_WARNING_DISABLE_DEPRECATED |
32 | |
33 | #include <QtTest/QTest> |
34 | #include <Qt3DCore/private/qnode_p.h> |
35 | #include <Qt3DCore/private/qscene_p.h> |
36 | #include <Qt3DCore/private/qnodecreatedchangegenerator_p.h> |
37 | |
38 | #include <Qt3DRender/qbuffer.h> |
39 | #include <Qt3DRender/private/qbuffer_p.h> |
40 | #include <Qt3DRender/qbufferdatagenerator.h> |
41 | |
42 | #include "testpostmanarbiter.h" |
43 | |
44 | class TestFunctor : public Qt3DRender::QBufferDataGenerator |
45 | { |
46 | public: |
47 | explicit TestFunctor(int size) |
48 | : m_size(size) |
49 | {} |
50 | |
51 | QByteArray operator ()() final |
52 | { |
53 | return QByteArray(); |
54 | } |
55 | |
56 | bool operator ==(const Qt3DRender::QBufferDataGenerator &other) const final |
57 | { |
58 | const TestFunctor *otherFunctor = Qt3DRender::functor_cast<TestFunctor>(other: &other); |
59 | if (otherFunctor != nullptr) |
60 | return otherFunctor->m_size == m_size; |
61 | return false; |
62 | } |
63 | |
64 | QT3D_FUNCTOR(TestFunctor) |
65 | |
66 | private: |
67 | int m_size; |
68 | }; |
69 | |
70 | class tst_QBuffer: public QObject |
71 | { |
72 | Q_OBJECT |
73 | |
74 | private Q_SLOTS: |
75 | |
76 | void checkCloning_data() |
77 | { |
78 | QTest::addColumn<Qt3DRender::QBuffer *>(name: "buffer" ); |
79 | |
80 | Qt3DRender::QBuffer *defaultConstructed = new Qt3DRender::QBuffer(); |
81 | QTest::newRow(dataTag: "defaultConstructed" ) << defaultConstructed; |
82 | |
83 | auto buffer = new Qt3DRender::QBuffer; |
84 | buffer->setUsage(Qt3DRender::QBuffer::DynamicRead); |
85 | buffer->setData(QByteArrayLiteral("There's no replacement" )); |
86 | buffer->setDataGenerator(Qt3DRender::QBufferDataGeneratorPtr(new TestFunctor(883))); |
87 | QTest::newRow(dataTag: "vertex" ) << buffer; |
88 | |
89 | auto indexBuffer = new Qt3DRender::QBuffer; |
90 | indexBuffer->setUsage(Qt3DRender::QBuffer::StaticCopy); |
91 | indexBuffer->setData(QByteArrayLiteral("For displacement" )); |
92 | indexBuffer->setDataGenerator(Qt3DRender::QBufferDataGeneratorPtr(new TestFunctor(1340))); |
93 | indexBuffer->setSyncData(true); |
94 | QTest::newRow(dataTag: "index" ) << indexBuffer; |
95 | } |
96 | |
97 | void checkCloning() |
98 | { |
99 | // GIVEN |
100 | QFETCH(Qt3DRender::QBuffer *, buffer); |
101 | |
102 | // WHEN |
103 | Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(buffer); |
104 | QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges = creationChangeGenerator.creationChanges(); |
105 | |
106 | // THEN |
107 | QCOMPARE(creationChanges.size(), 1); |
108 | |
109 | const Qt3DCore::QNodeCreatedChangePtr<Qt3DRender::QBufferData> creationChangeData = |
110 | qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DRender::QBufferData>>(src: creationChanges.first()); |
111 | const Qt3DRender::QBufferData &cloneData = creationChangeData->data; |
112 | |
113 | |
114 | QCOMPARE(buffer->id(), creationChangeData->subjectId()); |
115 | QCOMPARE(buffer->isEnabled(), creationChangeData->isNodeEnabled()); |
116 | QCOMPARE(buffer->metaObject(), creationChangeData->metaObject()); |
117 | QCOMPARE(buffer->data(), cloneData.data); |
118 | QCOMPARE(buffer->usage(), cloneData.usage); |
119 | QCOMPARE(buffer->dataGenerator(), cloneData.functor); |
120 | QCOMPARE(buffer->isSyncData(), cloneData.syncData); |
121 | if (buffer->dataGenerator()) { |
122 | QVERIFY(cloneData.functor); |
123 | QVERIFY(*cloneData.functor == *buffer->dataGenerator()); |
124 | QCOMPARE((*cloneData.functor)(), (*buffer->dataGenerator())()); |
125 | } |
126 | } |
127 | |
128 | void checkPropertyUpdates() |
129 | { |
130 | // GIVEN |
131 | TestArbiter arbiter; |
132 | QScopedPointer<Qt3DRender::QBuffer> buffer(new Qt3DRender::QBuffer); |
133 | arbiter.setArbiterOnNode(buffer.data()); |
134 | |
135 | // WHEN |
136 | buffer->setUsage(Qt3DRender::QBuffer::DynamicCopy); |
137 | |
138 | // THEN |
139 | QCOMPARE(arbiter.events.size(), 0); |
140 | QCOMPARE(arbiter.dirtyNodes.size(), 1); |
141 | QCOMPARE(arbiter.dirtyNodes.front(), buffer.data()); |
142 | |
143 | arbiter.dirtyNodes.clear(); |
144 | |
145 | // WHEN |
146 | buffer->setData(QByteArrayLiteral("Z28" )); |
147 | |
148 | // THEN |
149 | QCOMPARE(arbiter.events.size(), 0); |
150 | QCOMPARE(arbiter.dirtyNodes.size(), 1); |
151 | QCOMPARE(arbiter.dirtyNodes.front(), buffer.data()); |
152 | |
153 | arbiter.dirtyNodes.clear(); |
154 | |
155 | // WHEN |
156 | Qt3DRender::QBufferDataGeneratorPtr functor(new TestFunctor(355)); |
157 | buffer->setDataGenerator(functor); |
158 | QCoreApplication::processEvents(); |
159 | |
160 | // THEN |
161 | QCOMPARE(arbiter.dirtyNodes.size(), 1); |
162 | QCOMPARE(arbiter.dirtyNodes.front(), buffer.data()); |
163 | |
164 | arbiter.dirtyNodes.clear(); |
165 | |
166 | // WHEN |
167 | buffer->setSyncData(true); |
168 | |
169 | // THEN |
170 | QCOMPARE(arbiter.events.size(), 0); |
171 | QCOMPARE(arbiter.dirtyNodes.size(), 1); |
172 | QCOMPARE(arbiter.dirtyNodes.front(), buffer.data()); |
173 | |
174 | arbiter.dirtyNodes.clear(); |
175 | |
176 | // WHEN |
177 | buffer->updateData(offset: 1, QByteArrayLiteral("L1" )); |
178 | QCoreApplication::processEvents(); |
179 | |
180 | // THEN |
181 | QCOMPARE(arbiter.dirtyNodes.size(), 1); |
182 | QCOMPARE(arbiter.dirtyNodes.front(), buffer.data()); |
183 | } |
184 | |
185 | void checkAccumulatesBufferUpdates() |
186 | { |
187 | // GIVEN |
188 | TestArbiter arbiter; |
189 | QScopedPointer<Qt3DRender::QBuffer> buffer(new Qt3DRender::QBuffer); |
190 | arbiter.setArbiterOnNode(buffer.data()); |
191 | |
192 | QByteArray initData(6, '\0'); |
193 | buffer->setData(initData); |
194 | |
195 | // THEN |
196 | QCOMPARE(buffer->data(), initData); |
197 | QCOMPARE(buffer->property(Qt3DRender::QBufferPrivate::UpdateDataPropertyName), QVariant()); |
198 | |
199 | // WHEN |
200 | const QByteArray uData("012" ); |
201 | buffer->updateData(offset: 0, bytes: uData); |
202 | |
203 | // THEN |
204 | { |
205 | const QVariant v = buffer->property(name: Qt3DRender::QBufferPrivate::UpdateDataPropertyName); |
206 | QVERIFY(v.isValid()); |
207 | const QVariantList l = v.toList(); |
208 | QCOMPARE(l.size(), 1); |
209 | const Qt3DRender::QBufferUpdate update = l.first().value<Qt3DRender::QBufferUpdate>(); |
210 | QCOMPARE(update.offset, 0); |
211 | QCOMPARE(update.data, uData); |
212 | QCOMPARE(buffer->data().mid(0, 3), uData); |
213 | } |
214 | |
215 | // WHEN |
216 | const QByteArray uData2("345" ); |
217 | buffer->updateData(offset: 3, bytes: uData2); |
218 | |
219 | // THEN |
220 | { |
221 | const QVariant v = buffer->property(name: Qt3DRender::QBufferPrivate::UpdateDataPropertyName); |
222 | QVERIFY(v.isValid()); |
223 | const QVariantList l = v.toList(); |
224 | QCOMPARE(l.size(), 2); |
225 | const Qt3DRender::QBufferUpdate update = l.last().value<Qt3DRender::QBufferUpdate>(); |
226 | QCOMPARE(update.offset, 3); |
227 | QCOMPARE(update.data, uData2); |
228 | QCOMPARE(buffer->data(), QByteArray("012345" )); |
229 | } |
230 | } |
231 | }; |
232 | |
233 | QTEST_MAIN(tst_QBuffer) |
234 | |
235 | #include "tst_qbuffer.moc" |
236 | |