|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 ** |
|
7 ** This file is part of the QtOpenGL module of the Qt Toolkit. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:LGPL$ |
|
10 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
15 ** |
|
16 ** GNU Lesser General Public License Usage |
|
17 ** Alternatively, this file may be used under the terms of the GNU Lesser |
|
18 ** General Public License version 2.1 as published by the Free Software |
|
19 ** Foundation and appearing in the file LICENSE.LGPL included in the |
|
20 ** packaging of this file. Please review the following information to |
|
21 ** ensure the GNU Lesser General Public License version 2.1 requirements |
|
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
23 ** |
|
24 ** In addition, as a special exception, Nokia gives you certain additional |
|
25 ** rights. These rights are described in the Nokia Qt LGPL Exception |
|
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
27 ** |
|
28 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
38 ** $QT_END_LICENSE$ |
|
39 ** |
|
40 ****************************************************************************/ |
|
41 |
|
42 #include <QtTest/QtTest> |
|
43 #include <QtOpenGL/qgl.h> |
|
44 #include <QtOpenGL/qglbuffer.h> |
|
45 |
|
46 class tst_QGLBuffer : public QObject |
|
47 { |
|
48 Q_OBJECT |
|
49 public: |
|
50 tst_QGLBuffer() {} |
|
51 ~tst_QGLBuffer() {} |
|
52 |
|
53 private slots: |
|
54 void vertexBuffer_data(); |
|
55 void vertexBuffer(); |
|
56 void indexBuffer_data(); |
|
57 void indexBuffer(); |
|
58 void bufferSharing(); |
|
59 |
|
60 private: |
|
61 void testBuffer(QGLBuffer::Type type); |
|
62 }; |
|
63 |
|
64 void tst_QGLBuffer::vertexBuffer_data() |
|
65 { |
|
66 QTest::addColumn<int>("usagePattern"); |
|
67 |
|
68 QTest::newRow("StreamDraw") << int(QGLBuffer::StreamDraw); |
|
69 QTest::newRow("StaticDraw") << int(QGLBuffer::StaticDraw); |
|
70 QTest::newRow("DynamicDraw") << int(QGLBuffer::DynamicDraw); |
|
71 } |
|
72 |
|
73 void tst_QGLBuffer::vertexBuffer() |
|
74 { |
|
75 testBuffer(QGLBuffer::VertexBuffer); |
|
76 } |
|
77 |
|
78 void tst_QGLBuffer::indexBuffer_data() |
|
79 { |
|
80 vertexBuffer_data(); |
|
81 } |
|
82 |
|
83 void tst_QGLBuffer::indexBuffer() |
|
84 { |
|
85 testBuffer(QGLBuffer::IndexBuffer); |
|
86 } |
|
87 |
|
88 void tst_QGLBuffer::testBuffer(QGLBuffer::Type type) |
|
89 { |
|
90 QFETCH(int, usagePattern); |
|
91 |
|
92 QGLWidget w; |
|
93 w.makeCurrent(); |
|
94 |
|
95 // Create the local object, but not the buffer in the server. |
|
96 QGLBuffer buffer(type); |
|
97 QVERIFY(buffer.usagePattern() == QGLBuffer::StaticDraw); |
|
98 buffer.setUsagePattern(QGLBuffer::UsagePattern(usagePattern)); |
|
99 |
|
100 // Check the initial state. |
|
101 QVERIFY(buffer.type() == type); |
|
102 QVERIFY(!buffer.isCreated()); |
|
103 QVERIFY(buffer.bufferId() == 0); |
|
104 QVERIFY(buffer.usagePattern() == QGLBuffer::UsagePattern(usagePattern)); |
|
105 QCOMPARE(buffer.size(), -1); |
|
106 |
|
107 // Should not be able to bind it yet because it isn't created. |
|
108 QVERIFY(!buffer.bind()); |
|
109 |
|
110 // Create the buffer - if this fails, then assume that the |
|
111 // GL implementation does not support buffers at all. |
|
112 if (!buffer.create()) |
|
113 QSKIP("Buffers are not supported on this platform", SkipAll); |
|
114 |
|
115 // Should now have a buffer id. |
|
116 QVERIFY(buffer.bufferId() != 0); |
|
117 |
|
118 // Bind the buffer and upload some data. |
|
119 QVERIFY(buffer.bind()); |
|
120 static GLfloat const data[] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; |
|
121 buffer.allocate(data, sizeof(data)); |
|
122 |
|
123 // Check the buffer size. |
|
124 QCOMPARE(buffer.size(), int(sizeof(data))); |
|
125 |
|
126 // Map the buffer and read back its contents. |
|
127 bool haveMap = false; |
|
128 GLfloat *mapped = reinterpret_cast<GLfloat *> |
|
129 (buffer.map(QGLBuffer::ReadOnly)); |
|
130 if (mapped) { |
|
131 for (int index = 0; index < 9; ++index) |
|
132 QCOMPARE(mapped[index], data[index]); |
|
133 buffer.unmap(); |
|
134 haveMap = true; |
|
135 } else { |
|
136 qWarning("QGLBuffer::map() is not supported on this platform"); |
|
137 } |
|
138 |
|
139 // Read back the buffer contents using read(). |
|
140 bool haveRead = false; |
|
141 GLfloat readdata[9]; |
|
142 if (buffer.read(0, readdata, sizeof(readdata))) { |
|
143 for (int index = 0; index < 9; ++index) |
|
144 QCOMPARE(readdata[index], data[index]); |
|
145 haveRead = true; |
|
146 } else { |
|
147 qWarning("QGLBuffer::read() is not supported on this platform"); |
|
148 } |
|
149 |
|
150 // Write some different data to a specific location and check it. |
|
151 static GLfloat const diffdata[] = {11, 12, 13}; |
|
152 buffer.write(sizeof(GLfloat) * 3, diffdata, sizeof(diffdata)); |
|
153 if (haveMap) { |
|
154 mapped = reinterpret_cast<GLfloat *>(buffer.map(QGLBuffer::ReadOnly)); |
|
155 QVERIFY(mapped != 0); |
|
156 for (int index = 0; index < 9; ++index) { |
|
157 if (index >= 3 && index <= 5) |
|
158 QCOMPARE(mapped[index], diffdata[index - 3]); |
|
159 else |
|
160 QCOMPARE(mapped[index], data[index]); |
|
161 } |
|
162 buffer.unmap(); |
|
163 } |
|
164 if (haveRead) { |
|
165 QVERIFY(buffer.read(0, readdata, sizeof(readdata))); |
|
166 for (int index = 0; index < 9; ++index) { |
|
167 if (index >= 3 && index <= 5) |
|
168 QCOMPARE(readdata[index], diffdata[index - 3]); |
|
169 else |
|
170 QCOMPARE(readdata[index], data[index]); |
|
171 } |
|
172 } |
|
173 |
|
174 // Write to the buffer using the return value from map. |
|
175 if (haveMap) { |
|
176 mapped = reinterpret_cast<GLfloat *>(buffer.map(QGLBuffer::WriteOnly)); |
|
177 QVERIFY(mapped != 0); |
|
178 mapped[6] = 14; |
|
179 buffer.unmap(); |
|
180 |
|
181 mapped = reinterpret_cast<GLfloat *>(buffer.map(QGLBuffer::ReadOnly)); |
|
182 QVERIFY(mapped != 0); |
|
183 static GLfloat const diff2data[] = {11, 12, 13, 14}; |
|
184 for (int index = 0; index < 9; ++index) { |
|
185 if (index >= 3 && index <= 6) |
|
186 QCOMPARE(mapped[index], diff2data[index - 3]); |
|
187 else |
|
188 QCOMPARE(mapped[index], data[index]); |
|
189 } |
|
190 buffer.unmap(); |
|
191 } |
|
192 |
|
193 // Resize the buffer. |
|
194 buffer.allocate(sizeof(GLfloat) * 20); |
|
195 QCOMPARE(buffer.size(), int(sizeof(GLfloat) * 20)); |
|
196 buffer.allocate(0, sizeof(GLfloat) * 32); |
|
197 QCOMPARE(buffer.size(), int(sizeof(GLfloat) * 32)); |
|
198 |
|
199 // Release the buffer. |
|
200 buffer.release(); |
|
201 } |
|
202 |
|
203 void tst_QGLBuffer::bufferSharing() |
|
204 { |
|
205 QGLWidget *w1 = new QGLWidget(); |
|
206 w1->makeCurrent(); |
|
207 |
|
208 QGLWidget *w2 = new QGLWidget(0, w1); |
|
209 if (!w2->isSharing()) { |
|
210 delete w2; |
|
211 delete w1; |
|
212 QSKIP("Context sharing is not supported on this platform", SkipSingle); |
|
213 } |
|
214 |
|
215 // Bind the buffer in the first context and write some data to it. |
|
216 QGLBuffer buffer(QGLBuffer::VertexBuffer); |
|
217 if (!buffer.create()) |
|
218 QSKIP("Buffers are not supported on this platform", SkipSingle); |
|
219 QVERIFY(buffer.isCreated()); |
|
220 QVERIFY(buffer.bind()); |
|
221 static GLfloat const data[] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; |
|
222 buffer.allocate(data, sizeof(data)); |
|
223 QCOMPARE(buffer.size(), int(sizeof(data))); |
|
224 buffer.release(); |
|
225 |
|
226 // Bind the buffer in the second context and read back the data. |
|
227 w2->makeCurrent(); |
|
228 QVERIFY(buffer.bind()); |
|
229 QCOMPARE(buffer.size(), int(sizeof(data))); |
|
230 GLfloat readdata[9]; |
|
231 if (buffer.read(0, readdata, sizeof(readdata))) { |
|
232 for (int index = 0; index < 9; ++index) |
|
233 QCOMPARE(readdata[index], data[index]); |
|
234 } |
|
235 buffer.release(); |
|
236 |
|
237 // Delete the first context. |
|
238 delete w1; |
|
239 |
|
240 // Make the second context current again because deleting the first |
|
241 // one will call doneCurrent() even though it wasn't current! |
|
242 w2->makeCurrent(); |
|
243 |
|
244 // The buffer should still be valid in the second context. |
|
245 QVERIFY(buffer.bufferId() != 0); |
|
246 QVERIFY(buffer.isCreated()); |
|
247 QVERIFY(buffer.bind()); |
|
248 QCOMPARE(buffer.size(), int(sizeof(data))); |
|
249 buffer.release(); |
|
250 |
|
251 // Delete the second context. |
|
252 delete w2; |
|
253 |
|
254 // The buffer should now be invalid. |
|
255 QVERIFY(buffer.bufferId() == 0); |
|
256 QVERIFY(!buffer.isCreated()); |
|
257 } |
|
258 |
|
259 QTEST_MAIN(tst_QGLBuffer) |
|
260 |
|
261 #include "tst_qglbuffer.moc" |