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>
31QT_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
44class TestFunctor : public Qt3DRender::QBufferDataGenerator
45{
46public:
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
66private:
67 int m_size;
68};
69
70class tst_QBuffer: public QObject
71{
72 Q_OBJECT
73
74private 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
233QTEST_MAIN(tst_QBuffer)
234
235#include "tst_qbuffer.moc"
236

source code of qt3d/tests/auto/render/qbuffer/tst_qbuffer.cpp