|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2009 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 test suite 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 |
|
43 #include <QtTest/QtTest> |
|
44 |
|
45 #include <qcoreapplication.h> |
|
46 #include <qdebug.h> |
|
47 #include <qgl.h> |
|
48 #include <qglpixelbuffer.h> |
|
49 #include <qglframebufferobject.h> |
|
50 #include <qglcolormap.h> |
|
51 #include <qpaintengine.h> |
|
52 |
|
53 #include <QGraphicsView> |
|
54 #include <QGraphicsProxyWidget> |
|
55 #include <QVBoxLayout> |
|
56 |
|
57 #ifdef QT_BUILD_INTERNAL |
|
58 #include <QtOpenGL/private/qgl_p.h> |
|
59 #endif |
|
60 |
|
61 //TESTED_CLASS= |
|
62 //TESTED_FILES= |
|
63 |
|
64 class tst_QGL : public QObject |
|
65 { |
|
66 Q_OBJECT |
|
67 |
|
68 public: |
|
69 tst_QGL(); |
|
70 virtual ~tst_QGL(); |
|
71 |
|
72 private slots: |
|
73 void getSetCheck(); |
|
74 void openGLVersionCheck(); |
|
75 void graphicsViewClipping(); |
|
76 void partialGLWidgetUpdates_data(); |
|
77 void partialGLWidgetUpdates(); |
|
78 void glWidgetRendering(); |
|
79 void glFBORendering(); |
|
80 void multipleFBOInterleavedRendering(); |
|
81 void glFBOUseInGLWidget(); |
|
82 void glPBufferRendering(); |
|
83 void glWidgetReparent(); |
|
84 void glWidgetRenderPixmap(); |
|
85 void stackedFBOs(); |
|
86 void colormap(); |
|
87 void fboFormat(); |
|
88 void testDontCrashOnDanglingResources(); |
|
89 void replaceClipping(); |
|
90 void clipTest(); |
|
91 void destroyFBOAfterContext(); |
|
92 void shareRegister(); |
|
93 }; |
|
94 |
|
95 tst_QGL::tst_QGL() |
|
96 { |
|
97 } |
|
98 |
|
99 tst_QGL::~tst_QGL() |
|
100 { |
|
101 } |
|
102 |
|
103 class MyGLContext : public QGLContext |
|
104 { |
|
105 public: |
|
106 MyGLContext(const QGLFormat& format) : QGLContext(format) {} |
|
107 bool windowCreated() const { return QGLContext::windowCreated(); } |
|
108 void setWindowCreated(bool on) { QGLContext::setWindowCreated(on); } |
|
109 bool initialized() const { return QGLContext::initialized(); } |
|
110 void setInitialized(bool on) { QGLContext::setInitialized(on); } |
|
111 }; |
|
112 |
|
113 class MyGLWidget : public QGLWidget |
|
114 { |
|
115 public: |
|
116 MyGLWidget() : QGLWidget() {} |
|
117 bool autoBufferSwap() const { return QGLWidget::autoBufferSwap(); } |
|
118 void setAutoBufferSwap(bool on) { QGLWidget::setAutoBufferSwap(on); } |
|
119 }; |
|
120 |
|
121 // Using INT_MIN and INT_MAX will cause failures on systems |
|
122 // where "int" is 64-bit, so use the explicit values instead. |
|
123 #define TEST_INT_MIN (-2147483647 - 1) |
|
124 #define TEST_INT_MAX 2147483647 |
|
125 |
|
126 // Testing get/set functions |
|
127 void tst_QGL::getSetCheck() |
|
128 { |
|
129 if (!QGLFormat::hasOpenGL()) |
|
130 QSKIP("QGL not supported on this platform", SkipAll); |
|
131 |
|
132 QGLFormat obj1; |
|
133 // int QGLFormat::depthBufferSize() |
|
134 // void QGLFormat::setDepthBufferSize(int) |
|
135 QCOMPARE(-1, obj1.depthBufferSize()); |
|
136 obj1.setDepthBufferSize(0); |
|
137 QCOMPARE(0, obj1.depthBufferSize()); |
|
138 QTest::ignoreMessage(QtWarningMsg, "QGLFormat::setDepthBufferSize: Cannot set negative depth buffer size -2147483648"); |
|
139 obj1.setDepthBufferSize(TEST_INT_MIN); |
|
140 QCOMPARE(0, obj1.depthBufferSize()); // Makes no sense with a negative buffer size |
|
141 obj1.setDepthBufferSize(3); |
|
142 QTest::ignoreMessage(QtWarningMsg, "QGLFormat::setDepthBufferSize: Cannot set negative depth buffer size -1"); |
|
143 obj1.setDepthBufferSize(-1); |
|
144 QCOMPARE(3, obj1.depthBufferSize()); |
|
145 obj1.setDepthBufferSize(TEST_INT_MAX); |
|
146 QCOMPARE(TEST_INT_MAX, obj1.depthBufferSize()); |
|
147 |
|
148 // int QGLFormat::accumBufferSize() |
|
149 // void QGLFormat::setAccumBufferSize(int) |
|
150 QCOMPARE(-1, obj1.accumBufferSize()); |
|
151 obj1.setAccumBufferSize(0); |
|
152 QCOMPARE(0, obj1.accumBufferSize()); |
|
153 QTest::ignoreMessage(QtWarningMsg, "QGLFormat::setAccumBufferSize: Cannot set negative accumulate buffer size -2147483648"); |
|
154 obj1.setAccumBufferSize(TEST_INT_MIN); |
|
155 QCOMPARE(0, obj1.accumBufferSize()); // Makes no sense with a negative buffer size |
|
156 obj1.setAccumBufferSize(3); |
|
157 QTest::ignoreMessage(QtWarningMsg, "QGLFormat::setAccumBufferSize: Cannot set negative accumulate buffer size -1"); |
|
158 obj1.setAccumBufferSize(-1); |
|
159 QCOMPARE(3, obj1.accumBufferSize()); |
|
160 obj1.setAccumBufferSize(TEST_INT_MAX); |
|
161 QCOMPARE(TEST_INT_MAX, obj1.accumBufferSize()); |
|
162 |
|
163 // int QGLFormat::redBufferSize() |
|
164 // void QGLFormat::setRedBufferSize(int) |
|
165 QCOMPARE(-1, obj1.redBufferSize()); |
|
166 obj1.setRedBufferSize(0); |
|
167 QCOMPARE(0, obj1.redBufferSize()); |
|
168 QTest::ignoreMessage(QtWarningMsg, "QGLFormat::setRedBufferSize: Cannot set negative red buffer size -2147483648"); |
|
169 obj1.setRedBufferSize(TEST_INT_MIN); |
|
170 QCOMPARE(0, obj1.redBufferSize()); // Makes no sense with a negative buffer size |
|
171 obj1.setRedBufferSize(3); |
|
172 QTest::ignoreMessage(QtWarningMsg, "QGLFormat::setRedBufferSize: Cannot set negative red buffer size -1"); |
|
173 obj1.setRedBufferSize(-1); |
|
174 QCOMPARE(3, obj1.redBufferSize()); |
|
175 obj1.setRedBufferSize(TEST_INT_MAX); |
|
176 QCOMPARE(TEST_INT_MAX, obj1.redBufferSize()); |
|
177 |
|
178 // int QGLFormat::greenBufferSize() |
|
179 // void QGLFormat::setGreenBufferSize(int) |
|
180 QCOMPARE(-1, obj1.greenBufferSize()); |
|
181 obj1.setGreenBufferSize(0); |
|
182 QCOMPARE(0, obj1.greenBufferSize()); |
|
183 QTest::ignoreMessage(QtWarningMsg, "QGLFormat::setGreenBufferSize: Cannot set negative green buffer size -2147483648"); |
|
184 obj1.setGreenBufferSize(TEST_INT_MIN); |
|
185 QCOMPARE(0, obj1.greenBufferSize()); // Makes no sense with a negative buffer size |
|
186 obj1.setGreenBufferSize(3); |
|
187 QTest::ignoreMessage(QtWarningMsg, "QGLFormat::setGreenBufferSize: Cannot set negative green buffer size -1"); |
|
188 obj1.setGreenBufferSize(-1); |
|
189 QCOMPARE(3, obj1.greenBufferSize()); |
|
190 obj1.setGreenBufferSize(TEST_INT_MAX); |
|
191 QCOMPARE(TEST_INT_MAX, obj1.greenBufferSize()); |
|
192 |
|
193 // int QGLFormat::blueBufferSize() |
|
194 // void QGLFormat::setBlueBufferSize(int) |
|
195 QCOMPARE(-1, obj1.blueBufferSize()); |
|
196 obj1.setBlueBufferSize(0); |
|
197 QCOMPARE(0, obj1.blueBufferSize()); |
|
198 QTest::ignoreMessage(QtWarningMsg, "QGLFormat::setBlueBufferSize: Cannot set negative blue buffer size -2147483648"); |
|
199 obj1.setBlueBufferSize(TEST_INT_MIN); |
|
200 QCOMPARE(0, obj1.blueBufferSize()); // Makes no sense with a negative buffer size |
|
201 obj1.setBlueBufferSize(3); |
|
202 QTest::ignoreMessage(QtWarningMsg, "QGLFormat::setBlueBufferSize: Cannot set negative blue buffer size -1"); |
|
203 obj1.setBlueBufferSize(-1); |
|
204 QCOMPARE(3, obj1.blueBufferSize()); |
|
205 obj1.setBlueBufferSize(TEST_INT_MAX); |
|
206 QCOMPARE(TEST_INT_MAX, obj1.blueBufferSize()); |
|
207 |
|
208 // int QGLFormat::alphaBufferSize() |
|
209 // void QGLFormat::setAlphaBufferSize(int) |
|
210 QCOMPARE(-1, obj1.alphaBufferSize()); |
|
211 QCOMPARE(false, obj1.alpha()); |
|
212 QVERIFY(!obj1.testOption(QGL::AlphaChannel)); |
|
213 QVERIFY(obj1.testOption(QGL::NoAlphaChannel)); |
|
214 obj1.setAlphaBufferSize(0); |
|
215 QCOMPARE(true, obj1.alpha()); // setAlphaBufferSize() enables alpha. |
|
216 QCOMPARE(0, obj1.alphaBufferSize()); |
|
217 QTest::ignoreMessage(QtWarningMsg, "QGLFormat::setAlphaBufferSize: Cannot set negative alpha buffer size -2147483648"); |
|
218 obj1.setAlphaBufferSize(TEST_INT_MIN); |
|
219 QCOMPARE(0, obj1.alphaBufferSize()); // Makes no sense with a negative buffer size |
|
220 obj1.setAlphaBufferSize(3); |
|
221 QTest::ignoreMessage(QtWarningMsg, "QGLFormat::setAlphaBufferSize: Cannot set negative alpha buffer size -1"); |
|
222 obj1.setAlphaBufferSize(-1); |
|
223 QCOMPARE(3, obj1.alphaBufferSize()); |
|
224 obj1.setAlphaBufferSize(TEST_INT_MAX); |
|
225 QCOMPARE(TEST_INT_MAX, obj1.alphaBufferSize()); |
|
226 |
|
227 // int QGLFormat::stencilBufferSize() |
|
228 // void QGLFormat::setStencilBufferSize(int) |
|
229 QCOMPARE(-1, obj1.stencilBufferSize()); |
|
230 obj1.setStencilBufferSize(0); |
|
231 QCOMPARE(0, obj1.stencilBufferSize()); |
|
232 QTest::ignoreMessage(QtWarningMsg, "QGLFormat::setStencilBufferSize: Cannot set negative stencil buffer size -2147483648"); |
|
233 obj1.setStencilBufferSize(TEST_INT_MIN); |
|
234 QCOMPARE(0, obj1.stencilBufferSize()); // Makes no sense with a negative buffer size |
|
235 obj1.setStencilBufferSize(3); |
|
236 QTest::ignoreMessage(QtWarningMsg, "QGLFormat::setStencilBufferSize: Cannot set negative stencil buffer size -1"); |
|
237 obj1.setStencilBufferSize(-1); |
|
238 QCOMPARE(3, obj1.stencilBufferSize()); |
|
239 obj1.setStencilBufferSize(TEST_INT_MAX); |
|
240 QCOMPARE(TEST_INT_MAX, obj1.stencilBufferSize()); |
|
241 |
|
242 // bool QGLFormat::sampleBuffers() |
|
243 // void QGLFormat::setSampleBuffers(bool) |
|
244 #if !defined(QT_OPENGL_ES_2) |
|
245 QCOMPARE(false, obj1.sampleBuffers()); |
|
246 QVERIFY(!obj1.testOption(QGL::SampleBuffers)); |
|
247 QVERIFY(obj1.testOption(QGL::NoSampleBuffers)); |
|
248 #else |
|
249 QCOMPARE(true, obj1.sampleBuffers()); |
|
250 QVERIFY(obj1.testOption(QGL::SampleBuffers)); |
|
251 QVERIFY(!obj1.testOption(QGL::NoSampleBuffers)); |
|
252 #endif |
|
253 obj1.setSampleBuffers(false); |
|
254 QCOMPARE(false, obj1.sampleBuffers()); |
|
255 QVERIFY(obj1.testOption(QGL::NoSampleBuffers)); |
|
256 obj1.setSampleBuffers(true); |
|
257 QCOMPARE(true, obj1.sampleBuffers()); |
|
258 QVERIFY(obj1.testOption(QGL::SampleBuffers)); |
|
259 |
|
260 // int QGLFormat::samples() |
|
261 // void QGLFormat::setSamples(int) |
|
262 QCOMPARE(-1, obj1.samples()); |
|
263 obj1.setSamples(0); |
|
264 QCOMPARE(0, obj1.samples()); |
|
265 QTest::ignoreMessage(QtWarningMsg, "QGLFormat::setSamples: Cannot have negative number of samples per pixel -2147483648"); |
|
266 obj1.setSamples(TEST_INT_MIN); |
|
267 QCOMPARE(0, obj1.samples()); // Makes no sense with a negative sample size |
|
268 obj1.setSamples(3); |
|
269 QTest::ignoreMessage(QtWarningMsg, "QGLFormat::setSamples: Cannot have negative number of samples per pixel -1"); |
|
270 obj1.setSamples(-1); |
|
271 QCOMPARE(3, obj1.samples()); |
|
272 obj1.setSamples(TEST_INT_MAX); |
|
273 QCOMPARE(TEST_INT_MAX, obj1.samples()); |
|
274 |
|
275 // int QGLFormat::swapInterval() |
|
276 // void QGLFormat::setSwapInterval(int) |
|
277 QCOMPARE(-1, obj1.swapInterval()); |
|
278 obj1.setSwapInterval(0); |
|
279 QCOMPARE(0, obj1.swapInterval()); |
|
280 obj1.setSwapInterval(TEST_INT_MIN); |
|
281 QCOMPARE(TEST_INT_MIN, obj1.swapInterval()); |
|
282 obj1.setSwapInterval(-1); |
|
283 QCOMPARE(-1, obj1.swapInterval()); |
|
284 obj1.setSwapInterval(TEST_INT_MAX); |
|
285 QCOMPARE(TEST_INT_MAX, obj1.swapInterval()); |
|
286 |
|
287 // bool QGLFormat::doubleBuffer() |
|
288 // void QGLFormat::setDoubleBuffer(bool) |
|
289 QCOMPARE(true, obj1.doubleBuffer()); |
|
290 QVERIFY(obj1.testOption(QGL::DoubleBuffer)); |
|
291 QVERIFY(!obj1.testOption(QGL::SingleBuffer)); |
|
292 obj1.setDoubleBuffer(false); |
|
293 QCOMPARE(false, obj1.doubleBuffer()); |
|
294 QVERIFY(!obj1.testOption(QGL::DoubleBuffer)); |
|
295 QVERIFY(obj1.testOption(QGL::SingleBuffer)); |
|
296 obj1.setDoubleBuffer(true); |
|
297 QCOMPARE(true, obj1.doubleBuffer()); |
|
298 QVERIFY(obj1.testOption(QGL::DoubleBuffer)); |
|
299 QVERIFY(!obj1.testOption(QGL::SingleBuffer)); |
|
300 |
|
301 // bool QGLFormat::depth() |
|
302 // void QGLFormat::setDepth(bool) |
|
303 QCOMPARE(true, obj1.depth()); |
|
304 QVERIFY(obj1.testOption(QGL::DepthBuffer)); |
|
305 QVERIFY(!obj1.testOption(QGL::NoDepthBuffer)); |
|
306 obj1.setDepth(false); |
|
307 QCOMPARE(false, obj1.depth()); |
|
308 QVERIFY(!obj1.testOption(QGL::DepthBuffer)); |
|
309 QVERIFY(obj1.testOption(QGL::NoDepthBuffer)); |
|
310 obj1.setDepth(true); |
|
311 QCOMPARE(true, obj1.depth()); |
|
312 QVERIFY(obj1.testOption(QGL::DepthBuffer)); |
|
313 QVERIFY(!obj1.testOption(QGL::NoDepthBuffer)); |
|
314 |
|
315 // bool QGLFormat::rgba() |
|
316 // void QGLFormat::setRgba(bool) |
|
317 QCOMPARE(true, obj1.rgba()); |
|
318 QVERIFY(obj1.testOption(QGL::Rgba)); |
|
319 QVERIFY(!obj1.testOption(QGL::ColorIndex)); |
|
320 obj1.setRgba(false); |
|
321 QCOMPARE(false, obj1.rgba()); |
|
322 QVERIFY(!obj1.testOption(QGL::Rgba)); |
|
323 QVERIFY(obj1.testOption(QGL::ColorIndex)); |
|
324 obj1.setRgba(true); |
|
325 QCOMPARE(true, obj1.rgba()); |
|
326 QVERIFY(obj1.testOption(QGL::Rgba)); |
|
327 QVERIFY(!obj1.testOption(QGL::ColorIndex)); |
|
328 |
|
329 // bool QGLFormat::alpha() |
|
330 // void QGLFormat::setAlpha(bool) |
|
331 QVERIFY(obj1.testOption(QGL::AlphaChannel)); |
|
332 QVERIFY(!obj1.testOption(QGL::NoAlphaChannel)); |
|
333 obj1.setAlpha(false); |
|
334 QCOMPARE(false, obj1.alpha()); |
|
335 QVERIFY(!obj1.testOption(QGL::AlphaChannel)); |
|
336 QVERIFY(obj1.testOption(QGL::NoAlphaChannel)); |
|
337 obj1.setAlpha(true); |
|
338 QCOMPARE(true, obj1.alpha()); |
|
339 QVERIFY(obj1.testOption(QGL::AlphaChannel)); |
|
340 QVERIFY(!obj1.testOption(QGL::NoAlphaChannel)); |
|
341 |
|
342 // bool QGLFormat::accum() |
|
343 // void QGLFormat::setAccum(bool) |
|
344 QCOMPARE(false, obj1.accum()); |
|
345 QVERIFY(!obj1.testOption(QGL::AccumBuffer)); |
|
346 QVERIFY(obj1.testOption(QGL::NoAccumBuffer)); |
|
347 obj1.setAccum(false); |
|
348 QCOMPARE(false, obj1.accum()); |
|
349 QVERIFY(!obj1.testOption(QGL::AccumBuffer)); |
|
350 QVERIFY(obj1.testOption(QGL::NoAccumBuffer)); |
|
351 obj1.setAccum(true); |
|
352 QCOMPARE(true, obj1.accum()); |
|
353 QVERIFY(obj1.testOption(QGL::AccumBuffer)); |
|
354 QVERIFY(!obj1.testOption(QGL::NoAccumBuffer)); |
|
355 |
|
356 // bool QGLFormat::stencil() |
|
357 // void QGLFormat::setStencil(bool) |
|
358 QCOMPARE(true, obj1.stencil()); |
|
359 QVERIFY(obj1.testOption(QGL::StencilBuffer)); |
|
360 QVERIFY(!obj1.testOption(QGL::NoStencilBuffer)); |
|
361 obj1.setStencil(false); |
|
362 QCOMPARE(false, obj1.stencil()); |
|
363 QVERIFY(!obj1.testOption(QGL::StencilBuffer)); |
|
364 QVERIFY(obj1.testOption(QGL::NoStencilBuffer)); |
|
365 obj1.setStencil(true); |
|
366 QCOMPARE(true, obj1.stencil()); |
|
367 QVERIFY(obj1.testOption(QGL::StencilBuffer)); |
|
368 QVERIFY(!obj1.testOption(QGL::NoStencilBuffer)); |
|
369 |
|
370 // bool QGLFormat::stereo() |
|
371 // void QGLFormat::setStereo(bool) |
|
372 QCOMPARE(false, obj1.stereo()); |
|
373 QVERIFY(!obj1.testOption(QGL::StereoBuffers)); |
|
374 QVERIFY(obj1.testOption(QGL::NoStereoBuffers)); |
|
375 obj1.setStereo(false); |
|
376 QCOMPARE(false, obj1.stereo()); |
|
377 QVERIFY(!obj1.testOption(QGL::StereoBuffers)); |
|
378 QVERIFY(obj1.testOption(QGL::NoStereoBuffers)); |
|
379 obj1.setStereo(true); |
|
380 QCOMPARE(true, obj1.stereo()); |
|
381 QVERIFY(obj1.testOption(QGL::StereoBuffers)); |
|
382 QVERIFY(!obj1.testOption(QGL::NoStereoBuffers)); |
|
383 |
|
384 // bool QGLFormat::directRendering() |
|
385 // void QGLFormat::setDirectRendering(bool) |
|
386 QCOMPARE(true, obj1.directRendering()); |
|
387 QVERIFY(obj1.testOption(QGL::DirectRendering)); |
|
388 QVERIFY(!obj1.testOption(QGL::IndirectRendering)); |
|
389 obj1.setDirectRendering(false); |
|
390 QCOMPARE(false, obj1.directRendering()); |
|
391 QVERIFY(!obj1.testOption(QGL::DirectRendering)); |
|
392 QVERIFY(obj1.testOption(QGL::IndirectRendering)); |
|
393 obj1.setDirectRendering(true); |
|
394 QCOMPARE(true, obj1.directRendering()); |
|
395 QVERIFY(obj1.testOption(QGL::DirectRendering)); |
|
396 QVERIFY(!obj1.testOption(QGL::IndirectRendering)); |
|
397 |
|
398 // bool QGLFormat::overlay() |
|
399 // void QGLFormat::setOverlay(bool) |
|
400 QCOMPARE(false, obj1.hasOverlay()); |
|
401 QVERIFY(!obj1.testOption(QGL::HasOverlay)); |
|
402 QVERIFY(obj1.testOption(QGL::NoOverlay)); |
|
403 obj1.setOverlay(false); |
|
404 QCOMPARE(false, obj1.hasOverlay()); |
|
405 QVERIFY(!obj1.testOption(QGL::HasOverlay)); |
|
406 QVERIFY(obj1.testOption(QGL::NoOverlay)); |
|
407 obj1.setOverlay(true); |
|
408 QCOMPARE(true, obj1.hasOverlay()); |
|
409 QVERIFY(obj1.testOption(QGL::HasOverlay)); |
|
410 QVERIFY(!obj1.testOption(QGL::NoOverlay)); |
|
411 |
|
412 // int QGLFormat::plane() |
|
413 // void QGLFormat::setPlane(int) |
|
414 QCOMPARE(0, obj1.plane()); |
|
415 obj1.setPlane(0); |
|
416 QCOMPARE(0, obj1.plane()); |
|
417 obj1.setPlane(TEST_INT_MIN); |
|
418 QCOMPARE(TEST_INT_MIN, obj1.plane()); |
|
419 obj1.setPlane(TEST_INT_MAX); |
|
420 QCOMPARE(TEST_INT_MAX, obj1.plane()); |
|
421 |
|
422 // operator== and operator!= for QGLFormat |
|
423 QGLFormat format1; |
|
424 QGLFormat format2; |
|
425 |
|
426 QVERIFY(format1 == format2); |
|
427 QVERIFY(!(format1 != format2)); |
|
428 format1.setDoubleBuffer(false); |
|
429 QVERIFY(!(format1 == format2)); |
|
430 QVERIFY(format1 != format2); |
|
431 format2.setDoubleBuffer(false); |
|
432 QVERIFY(format1 == format2); |
|
433 QVERIFY(!(format1 != format2)); |
|
434 |
|
435 format1.setDepthBufferSize(8); |
|
436 QVERIFY(!(format1 == format2)); |
|
437 QVERIFY(format1 != format2); |
|
438 format2.setDepthBufferSize(8); |
|
439 QVERIFY(format1 == format2); |
|
440 QVERIFY(!(format1 != format2)); |
|
441 |
|
442 format1.setAccumBufferSize(8); |
|
443 QVERIFY(!(format1 == format2)); |
|
444 QVERIFY(format1 != format2); |
|
445 format2.setAccumBufferSize(8); |
|
446 QVERIFY(format1 == format2); |
|
447 QVERIFY(!(format1 != format2)); |
|
448 |
|
449 format1.setRedBufferSize(8); |
|
450 QVERIFY(!(format1 == format2)); |
|
451 QVERIFY(format1 != format2); |
|
452 format2.setRedBufferSize(8); |
|
453 QVERIFY(format1 == format2); |
|
454 QVERIFY(!(format1 != format2)); |
|
455 |
|
456 format1.setGreenBufferSize(8); |
|
457 QVERIFY(!(format1 == format2)); |
|
458 QVERIFY(format1 != format2); |
|
459 format2.setGreenBufferSize(8); |
|
460 QVERIFY(format1 == format2); |
|
461 QVERIFY(!(format1 != format2)); |
|
462 |
|
463 format1.setBlueBufferSize(8); |
|
464 QVERIFY(!(format1 == format2)); |
|
465 QVERIFY(format1 != format2); |
|
466 format2.setBlueBufferSize(8); |
|
467 QVERIFY(format1 == format2); |
|
468 QVERIFY(!(format1 != format2)); |
|
469 |
|
470 format1.setAlphaBufferSize(8); |
|
471 QVERIFY(!(format1 == format2)); |
|
472 QVERIFY(format1 != format2); |
|
473 format2.setAlphaBufferSize(8); |
|
474 QVERIFY(format1 == format2); |
|
475 QVERIFY(!(format1 != format2)); |
|
476 |
|
477 format1.setStencilBufferSize(8); |
|
478 QVERIFY(!(format1 == format2)); |
|
479 QVERIFY(format1 != format2); |
|
480 format2.setStencilBufferSize(8); |
|
481 QVERIFY(format1 == format2); |
|
482 QVERIFY(!(format1 != format2)); |
|
483 |
|
484 format1.setSamples(8); |
|
485 QVERIFY(!(format1 == format2)); |
|
486 QVERIFY(format1 != format2); |
|
487 format2.setSamples(8); |
|
488 QVERIFY(format1 == format2); |
|
489 QVERIFY(!(format1 != format2)); |
|
490 |
|
491 format1.setSwapInterval(8); |
|
492 QVERIFY(!(format1 == format2)); |
|
493 QVERIFY(format1 != format2); |
|
494 format2.setSwapInterval(8); |
|
495 QVERIFY(format1 == format2); |
|
496 QVERIFY(!(format1 != format2)); |
|
497 |
|
498 format1.setPlane(8); |
|
499 QVERIFY(!(format1 == format2)); |
|
500 QVERIFY(format1 != format2); |
|
501 format2.setPlane(8); |
|
502 QVERIFY(format1 == format2); |
|
503 QVERIFY(!(format1 != format2)); |
|
504 |
|
505 // Copy constructor and assignment for QGLFormat. |
|
506 QGLFormat format3(format1); |
|
507 QGLFormat format4; |
|
508 QVERIFY(format1 == format3); |
|
509 QVERIFY(format1 != format4); |
|
510 format4 = format1; |
|
511 QVERIFY(format1 == format4); |
|
512 |
|
513 // Check that modifying a copy doesn't affect the original. |
|
514 format3.setRedBufferSize(16); |
|
515 format4.setPlane(16); |
|
516 QCOMPARE(format1.redBufferSize(), 8); |
|
517 QCOMPARE(format1.plane(), 8); |
|
518 |
|
519 // Check the QGLFormat constructor that takes an option list. |
|
520 QGLFormat format5 |
|
521 (QGL::DepthBuffer | QGL::StereoBuffers | QGL::ColorIndex, 3); |
|
522 QVERIFY(format5.depth()); |
|
523 QVERIFY(format5.stereo()); |
|
524 QVERIFY(format5.doubleBuffer()); // From defaultFormat() |
|
525 QVERIFY(!format5.hasOverlay()); // From defaultFormat() |
|
526 QVERIFY(!format5.rgba()); |
|
527 QCOMPARE(format5.plane(), 3); |
|
528 |
|
529 // The default format should be the same as QGLFormat(). |
|
530 QVERIFY(QGLFormat::defaultFormat() == QGLFormat()); |
|
531 |
|
532 // Modify the default format and check that it was changed. |
|
533 QGLFormat::setDefaultFormat(format1); |
|
534 QVERIFY(QGLFormat::defaultFormat() == format1); |
|
535 |
|
536 // Restore the default format. |
|
537 QGLFormat::setDefaultFormat(QGLFormat()); |
|
538 QVERIFY(QGLFormat::defaultFormat() == QGLFormat()); |
|
539 |
|
540 // Check the default overlay format's expected values. |
|
541 QGLFormat overlay(QGLFormat::defaultOverlayFormat()); |
|
542 QCOMPARE(overlay.depthBufferSize(), -1); |
|
543 QCOMPARE(overlay.accumBufferSize(), -1); |
|
544 QCOMPARE(overlay.redBufferSize(), -1); |
|
545 QCOMPARE(overlay.greenBufferSize(), -1); |
|
546 QCOMPARE(overlay.blueBufferSize(), -1); |
|
547 QCOMPARE(overlay.alphaBufferSize(), -1); |
|
548 QCOMPARE(overlay.samples(), -1); |
|
549 QCOMPARE(overlay.swapInterval(), -1); |
|
550 QCOMPARE(overlay.plane(), 1); |
|
551 QVERIFY(!overlay.sampleBuffers()); |
|
552 QVERIFY(!overlay.doubleBuffer()); |
|
553 QVERIFY(!overlay.depth()); |
|
554 QVERIFY(!overlay.rgba()); |
|
555 QVERIFY(!overlay.alpha()); |
|
556 QVERIFY(!overlay.accum()); |
|
557 QVERIFY(!overlay.stencil()); |
|
558 QVERIFY(!overlay.stereo()); |
|
559 QVERIFY(overlay.directRendering()); // Only option that should be on. |
|
560 QVERIFY(!overlay.hasOverlay()); // Overlay doesn't need an overlay! |
|
561 |
|
562 // Modify the default overlay format and check that it was changed. |
|
563 QGLFormat::setDefaultOverlayFormat(format1); |
|
564 QVERIFY(QGLFormat::defaultOverlayFormat() == format1); |
|
565 |
|
566 // Restore the default overlay format. |
|
567 QGLFormat::setDefaultOverlayFormat(overlay); |
|
568 QVERIFY(QGLFormat::defaultOverlayFormat() == overlay); |
|
569 |
|
570 MyGLContext obj2(obj1); |
|
571 // bool QGLContext::windowCreated() |
|
572 // void QGLContext::setWindowCreated(bool) |
|
573 obj2.setWindowCreated(false); |
|
574 QCOMPARE(false, obj2.windowCreated()); |
|
575 obj2.setWindowCreated(true); |
|
576 QCOMPARE(true, obj2.windowCreated()); |
|
577 |
|
578 // bool QGLContext::initialized() |
|
579 // void QGLContext::setInitialized(bool) |
|
580 obj2.setInitialized(false); |
|
581 QCOMPARE(false, obj2.initialized()); |
|
582 obj2.setInitialized(true); |
|
583 QCOMPARE(true, obj2.initialized()); |
|
584 |
|
585 MyGLWidget obj3; |
|
586 // bool QGLWidget::autoBufferSwap() |
|
587 // void QGLWidget::setAutoBufferSwap(bool) |
|
588 obj3.setAutoBufferSwap(false); |
|
589 QCOMPARE(false, obj3.autoBufferSwap()); |
|
590 obj3.setAutoBufferSwap(true); |
|
591 QCOMPARE(true, obj3.autoBufferSwap()); |
|
592 } |
|
593 |
|
594 #ifdef QT_BUILD_INTERNAL |
|
595 QT_BEGIN_NAMESPACE |
|
596 extern QGLFormat::OpenGLVersionFlags qOpenGLVersionFlagsFromString(const QString &versionString); |
|
597 QT_END_NAMESPACE |
|
598 #endif |
|
599 |
|
600 void tst_QGL::openGLVersionCheck() |
|
601 { |
|
602 #ifdef QT_BUILD_INTERNAL |
|
603 if (!QGLFormat::hasOpenGL()) |
|
604 QSKIP("QGL not supported on this platform", SkipAll); |
|
605 |
|
606 QString versionString; |
|
607 QGLFormat::OpenGLVersionFlags expectedFlag; |
|
608 QGLFormat::OpenGLVersionFlags versionFlag; |
|
609 |
|
610 versionString = "1.1 Irix 6.5"; |
|
611 expectedFlag = QGLFormat::OpenGL_Version_1_1; |
|
612 versionFlag = qOpenGLVersionFlagsFromString(versionString); |
|
613 QCOMPARE(versionFlag, expectedFlag); |
|
614 |
|
615 versionString = "1.2 Microsoft"; |
|
616 expectedFlag = QGLFormat::OpenGL_Version_1_2 | QGLFormat::OpenGL_Version_1_1; |
|
617 versionFlag = qOpenGLVersionFlagsFromString(versionString); |
|
618 QCOMPARE(versionFlag, expectedFlag); |
|
619 |
|
620 versionString = "1.2.1"; |
|
621 expectedFlag = QGLFormat::OpenGL_Version_1_2 | QGLFormat::OpenGL_Version_1_1; |
|
622 versionFlag = qOpenGLVersionFlagsFromString(versionString); |
|
623 QCOMPARE(versionFlag, expectedFlag); |
|
624 |
|
625 versionString = "1.3 NVIDIA"; |
|
626 expectedFlag = QGLFormat::OpenGL_Version_1_3 | QGLFormat::OpenGL_Version_1_2 | QGLFormat::OpenGL_Version_1_1; |
|
627 versionFlag = qOpenGLVersionFlagsFromString(versionString); |
|
628 QCOMPARE(versionFlag, expectedFlag); |
|
629 |
|
630 versionString = "1.4"; |
|
631 expectedFlag = QGLFormat::OpenGL_Version_1_4 | QGLFormat::OpenGL_Version_1_3 | QGLFormat::OpenGL_Version_1_2 | QGLFormat::OpenGL_Version_1_1; |
|
632 versionFlag = qOpenGLVersionFlagsFromString(versionString); |
|
633 QCOMPARE(versionFlag, expectedFlag); |
|
634 |
|
635 versionString = "1.5 NVIDIA"; |
|
636 expectedFlag = QGLFormat::OpenGL_Version_1_5 | QGLFormat::OpenGL_Version_1_4 | QGLFormat::OpenGL_Version_1_3 | QGLFormat::OpenGL_Version_1_2 | QGLFormat::OpenGL_Version_1_1; |
|
637 versionFlag = qOpenGLVersionFlagsFromString(versionString); |
|
638 QCOMPARE(versionFlag, expectedFlag); |
|
639 |
|
640 versionString = "2.0.2 NVIDIA 87.62"; |
|
641 expectedFlag = QGLFormat::OpenGL_Version_2_0 | QGLFormat::OpenGL_Version_1_5 | QGLFormat::OpenGL_Version_1_4 | QGLFormat::OpenGL_Version_1_3 | QGLFormat::OpenGL_Version_1_2 | QGLFormat::OpenGL_Version_1_1; |
|
642 versionFlag = qOpenGLVersionFlagsFromString(versionString); |
|
643 QCOMPARE(versionFlag, expectedFlag); |
|
644 |
|
645 versionString = "2.1 NVIDIA"; |
|
646 expectedFlag = QGLFormat::OpenGL_Version_2_1 | QGLFormat::OpenGL_Version_2_0 | QGLFormat::OpenGL_Version_1_5 | QGLFormat::OpenGL_Version_1_4 | QGLFormat::OpenGL_Version_1_3 | QGLFormat::OpenGL_Version_1_2 | QGLFormat::OpenGL_Version_1_1; |
|
647 versionFlag = qOpenGLVersionFlagsFromString(versionString); |
|
648 QCOMPARE(versionFlag, expectedFlag); |
|
649 |
|
650 versionString = "2.1"; |
|
651 expectedFlag = QGLFormat::OpenGL_Version_2_1 | QGLFormat::OpenGL_Version_2_0 | QGLFormat::OpenGL_Version_1_5 | QGLFormat::OpenGL_Version_1_4 | QGLFormat::OpenGL_Version_1_3 | QGLFormat::OpenGL_Version_1_2 | QGLFormat::OpenGL_Version_1_1; |
|
652 versionFlag = qOpenGLVersionFlagsFromString(versionString); |
|
653 QCOMPARE(versionFlag, expectedFlag); |
|
654 |
|
655 versionString = "OpenGL ES-CM 1.0 ATI"; |
|
656 expectedFlag = QGLFormat::OpenGL_ES_Common_Version_1_0 | QGLFormat::OpenGL_ES_CommonLite_Version_1_0; |
|
657 versionFlag = qOpenGLVersionFlagsFromString(versionString); |
|
658 QCOMPARE(versionFlag, expectedFlag); |
|
659 |
|
660 versionString = "OpenGL ES-CL 1.0 ATI"; |
|
661 expectedFlag = QGLFormat::OpenGL_ES_CommonLite_Version_1_0; |
|
662 versionFlag = qOpenGLVersionFlagsFromString(versionString); |
|
663 QCOMPARE(versionFlag, expectedFlag); |
|
664 |
|
665 versionString = "OpenGL ES-CM 1.1 ATI"; |
|
666 expectedFlag = QGLFormat::OpenGL_ES_Common_Version_1_1 | QGLFormat::OpenGL_ES_CommonLite_Version_1_1 | QGLFormat::OpenGL_ES_Common_Version_1_0 | QGLFormat::OpenGL_ES_CommonLite_Version_1_0; |
|
667 versionFlag = qOpenGLVersionFlagsFromString(versionString); |
|
668 QCOMPARE(versionFlag, expectedFlag); |
|
669 |
|
670 versionString = "OpenGL ES-CL 1.1 ATI"; |
|
671 expectedFlag = QGLFormat::OpenGL_ES_CommonLite_Version_1_1 | QGLFormat::OpenGL_ES_CommonLite_Version_1_0; |
|
672 versionFlag = qOpenGLVersionFlagsFromString(versionString); |
|
673 QCOMPARE(versionFlag, expectedFlag); |
|
674 |
|
675 versionString = "OpenGL ES 2.0 ATI"; |
|
676 expectedFlag = QGLFormat::OpenGL_ES_Version_2_0; |
|
677 versionFlag = qOpenGLVersionFlagsFromString(versionString); |
|
678 QCOMPARE(versionFlag, expectedFlag); |
|
679 |
|
680 versionString = "3.0"; |
|
681 expectedFlag = QGLFormat::OpenGL_Version_3_0 | QGLFormat::OpenGL_Version_2_1 | QGLFormat::OpenGL_Version_2_0 | QGLFormat::OpenGL_Version_1_5 | QGLFormat::OpenGL_Version_1_4 | QGLFormat::OpenGL_Version_1_3 | QGLFormat::OpenGL_Version_1_2 | QGLFormat::OpenGL_Version_1_1; |
|
682 versionFlag = qOpenGLVersionFlagsFromString(versionString); |
|
683 QCOMPARE(versionFlag, expectedFlag); |
|
684 |
|
685 QGLWidget glWidget; |
|
686 glWidget.show(); |
|
687 glWidget.makeCurrent(); |
|
688 |
|
689 // This is unfortunately the only test we can make on the actual openGLVersionFlags() |
|
690 // However, the complicated parts are in openGLVersionFlags(const QString &versionString) |
|
691 // tested above |
|
692 |
|
693 #if defined(QT_OPENGL_ES_1) |
|
694 QVERIFY(QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_ES_Common_Version_1_0); |
|
695 #elif defined(QT_OPENGL_ES_1_CL) |
|
696 QVERIFY(QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_ES_CommonLite_Version_1_0); |
|
697 #elif defined(QT_OPENGL_ES_2) |
|
698 QVERIFY(QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_ES_Version_2_0); |
|
699 #else |
|
700 QVERIFY(QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_1_1); |
|
701 #endif //defined(QT_OPENGL_ES_1) |
|
702 #endif //QT_BUILD_INTERNAL |
|
703 } |
|
704 |
|
705 class UnclippedWidget : public QWidget |
|
706 { |
|
707 public: |
|
708 void paintEvent(QPaintEvent *) |
|
709 { |
|
710 QPainter p(this); |
|
711 p.fillRect(rect().adjusted(-1000, -1000, 1000, 1000), Qt::black); |
|
712 } |
|
713 }; |
|
714 |
|
715 void tst_QGL::graphicsViewClipping() |
|
716 { |
|
717 const int size = 64; |
|
718 UnclippedWidget *widget = new UnclippedWidget; |
|
719 widget->setFixedSize(size, size); |
|
720 |
|
721 QGraphicsScene scene; |
|
722 |
|
723 scene.addWidget(widget)->setPos(0, 0); |
|
724 |
|
725 QGraphicsView view(&scene); |
|
726 view.resize(2*size, 2*size); |
|
727 |
|
728 QGLWidget *viewport = new QGLWidget; |
|
729 view.setViewport(viewport); |
|
730 view.show(); |
|
731 |
|
732 if (!viewport->isValid()) |
|
733 return; |
|
734 |
|
735 scene.setSceneRect(view.viewport()->rect()); |
|
736 |
|
737 #ifdef Q_WS_X11 |
|
738 qt_x11_wait_for_window_manager(&view); |
|
739 #endif |
|
740 QTest::qWait(500); |
|
741 |
|
742 QImage image = viewport->grabFrameBuffer(); |
|
743 QImage expected = image; |
|
744 |
|
745 QPainter p(&expected); |
|
746 p.fillRect(expected.rect(), Qt::white); |
|
747 p.fillRect(QRect(0, 0, size, size), Qt::black); |
|
748 p.end(); |
|
749 |
|
750 QCOMPARE(image, expected); |
|
751 } |
|
752 |
|
753 void tst_QGL::partialGLWidgetUpdates_data() |
|
754 { |
|
755 QTest::addColumn<bool>("doubleBufferedContext"); |
|
756 QTest::addColumn<bool>("autoFillBackground"); |
|
757 QTest::addColumn<bool>("supportsPartialUpdates"); |
|
758 |
|
759 QTest::newRow("Double buffered context") << true << true << false; |
|
760 QTest::newRow("Double buffered context without auto-fill background") << true << false << false; |
|
761 QTest::newRow("Single buffered context") << false << true << false; |
|
762 QTest::newRow("Single buffered context without auto-fill background") << false << false << true; |
|
763 } |
|
764 |
|
765 void tst_QGL::partialGLWidgetUpdates() |
|
766 { |
|
767 if (!QGLFormat::hasOpenGL()) |
|
768 QSKIP("QGL not supported on this platform", SkipAll); |
|
769 |
|
770 QFETCH(bool, doubleBufferedContext); |
|
771 QFETCH(bool, autoFillBackground); |
|
772 QFETCH(bool, supportsPartialUpdates); |
|
773 |
|
774 class MyGLWidget : public QGLWidget |
|
775 { |
|
776 public: |
|
777 QRegion paintEventRegion; |
|
778 void paintEvent(QPaintEvent *e) |
|
779 { |
|
780 paintEventRegion = e->region(); |
|
781 } |
|
782 }; |
|
783 |
|
784 QGLFormat format = QGLFormat::defaultFormat(); |
|
785 format.setDoubleBuffer(doubleBufferedContext); |
|
786 QGLFormat::setDefaultFormat(format); |
|
787 |
|
788 MyGLWidget widget; |
|
789 widget.setFixedSize(150, 150); |
|
790 widget.setAutoFillBackground(autoFillBackground); |
|
791 widget.show(); |
|
792 #ifdef Q_WS_X11 |
|
793 qt_x11_wait_for_window_manager(&widget); |
|
794 #endif |
|
795 QTest::qWait(200); |
|
796 |
|
797 if (widget.format().doubleBuffer() != doubleBufferedContext) |
|
798 QSKIP("Platform does not support requested format", SkipAll); |
|
799 |
|
800 widget.paintEventRegion = QRegion(); |
|
801 widget.repaint(50, 50, 50, 50); |
|
802 #ifdef Q_WS_MAC |
|
803 // repaint() is not immediate on the Mac; it has to go through the event loop. |
|
804 QTest::qWait(200); |
|
805 #endif |
|
806 if (supportsPartialUpdates) |
|
807 QCOMPARE(widget.paintEventRegion, QRegion(50, 50, 50, 50)); |
|
808 else |
|
809 QCOMPARE(widget.paintEventRegion, QRegion(widget.rect())); |
|
810 } |
|
811 |
|
812 |
|
813 // This tests that rendering to a QGLPBuffer using QPainter works. |
|
814 void tst_QGL::glPBufferRendering() |
|
815 { |
|
816 if (!QGLPixelBuffer::hasOpenGLPbuffers()) |
|
817 QSKIP("QGLPixelBuffer not supported on this platform", SkipSingle); |
|
818 |
|
819 QGLPixelBuffer* pbuf = new QGLPixelBuffer(128, 128); |
|
820 |
|
821 QPainter p; |
|
822 bool begun = p.begin(pbuf); |
|
823 QVERIFY(begun); |
|
824 |
|
825 QPaintEngine::Type engineType = p.paintEngine()->type(); |
|
826 QVERIFY(engineType == QPaintEngine::OpenGL || engineType == QPaintEngine::OpenGL2); |
|
827 |
|
828 p.fillRect(0, 0, 128, 128, Qt::red); |
|
829 p.fillRect(32, 32, 64, 64, Qt::blue); |
|
830 p.end(); |
|
831 |
|
832 QImage fb = pbuf->toImage(); |
|
833 delete pbuf; |
|
834 |
|
835 QImage reference(128, 128, fb.format()); |
|
836 p.begin(&reference); |
|
837 p.fillRect(0, 0, 128, 128, Qt::red); |
|
838 p.fillRect(32, 32, 64, 64, Qt::blue); |
|
839 p.end(); |
|
840 |
|
841 QCOMPARE(fb, reference); |
|
842 } |
|
843 |
|
844 class GLWidget : public QGLWidget |
|
845 { |
|
846 public: |
|
847 GLWidget(QWidget* p = 0) |
|
848 : QGLWidget(p), beginOk(false), engineType(QPaintEngine::MaxUser) {} |
|
849 bool beginOk; |
|
850 QPaintEngine::Type engineType; |
|
851 void paintGL() |
|
852 { |
|
853 QPainter p; |
|
854 beginOk = p.begin(this); |
|
855 QPaintEngine* pe = p.paintEngine(); |
|
856 engineType = pe->type(); |
|
857 |
|
858 // This test only ensures it's possible to paint onto a QGLWidget. Full |
|
859 // paint engine feature testing is way out of scope! |
|
860 |
|
861 p.fillRect(0, 0, width(), height(), Qt::red); |
|
862 // No p.end() or swap buffers, should be done automatically |
|
863 } |
|
864 |
|
865 }; |
|
866 |
|
867 void tst_QGL::glWidgetRendering() |
|
868 { |
|
869 GLWidget w; |
|
870 w.show(); |
|
871 |
|
872 #ifdef Q_WS_X11 |
|
873 qt_x11_wait_for_window_manager(&w); |
|
874 #endif |
|
875 QTest::qWait(200); |
|
876 |
|
877 QVERIFY(w.beginOk); |
|
878 QVERIFY(w.engineType == QPaintEngine::OpenGL || w.engineType == QPaintEngine::OpenGL2); |
|
879 |
|
880 QImage fb = w.grabFrameBuffer(false).convertToFormat(QImage::Format_RGB32); |
|
881 QImage reference(fb.size(), QImage::Format_RGB32); |
|
882 reference.fill(0xffff0000); |
|
883 |
|
884 QCOMPARE(fb, reference); |
|
885 } |
|
886 |
|
887 // NOTE: This tests that CombinedDepthStencil attachment works by assuming the |
|
888 // GL2 engine is being used and is implemented the same way as it was when |
|
889 // this autotest was written. If this is not the case, there may be some |
|
890 // false-positives: I.e. The test passes when either the depth or stencil |
|
891 // buffer is actually missing. But that's probably ok anyway. |
|
892 void tst_QGL::glFBORendering() |
|
893 { |
|
894 if (!QGLFramebufferObject::hasOpenGLFramebufferObjects()) |
|
895 QSKIP("QGLFramebufferObject not supported on this platform", SkipSingle); |
|
896 |
|
897 QGLWidget glw; |
|
898 glw.makeCurrent(); |
|
899 |
|
900 // No multisample with combined depth/stencil attachment: |
|
901 QGLFramebufferObjectFormat fboFormat; |
|
902 fboFormat.setAttachment(QGLFramebufferObject::CombinedDepthStencil); |
|
903 |
|
904 // Don't complicate things by using NPOT: |
|
905 QGLFramebufferObject *fbo = new QGLFramebufferObject(256, 128, fboFormat); |
|
906 |
|
907 QPainter fboPainter; |
|
908 bool painterBegun = fboPainter.begin(fbo); |
|
909 QVERIFY(painterBegun); |
|
910 |
|
911 QPainterPath intersectingPath; |
|
912 intersectingPath.moveTo(0, 0); |
|
913 intersectingPath.lineTo(100, 0); |
|
914 intersectingPath.lineTo(0, 100); |
|
915 intersectingPath.lineTo(100, 100); |
|
916 intersectingPath.closeSubpath(); |
|
917 |
|
918 QPainterPath trianglePath; |
|
919 trianglePath.moveTo(50, 0); |
|
920 trianglePath.lineTo(100, 100); |
|
921 trianglePath.lineTo(0, 100); |
|
922 trianglePath.closeSubpath(); |
|
923 |
|
924 fboPainter.fillRect(0, 0, fbo->width(), fbo->height(), Qt::red); // Background |
|
925 fboPainter.translate(14, 14); |
|
926 fboPainter.fillPath(intersectingPath, Qt::blue); // Test stencil buffer works |
|
927 fboPainter.translate(128, 0); |
|
928 fboPainter.setClipPath(trianglePath); // Test depth buffer works |
|
929 fboPainter.setTransform(QTransform()); // reset xform |
|
930 fboPainter.fillRect(0, 0, fbo->width(), fbo->height(), Qt::green); |
|
931 fboPainter.end(); |
|
932 |
|
933 QImage fb = fbo->toImage().convertToFormat(QImage::Format_RGB32); |
|
934 delete fbo; |
|
935 |
|
936 // As we're doing more than trivial painting, we can't just compare to |
|
937 // an image rendered with raster. Instead, we sample at well-defined |
|
938 // test-points: |
|
939 QCOMPARE(fb.pixel(39, 64), QColor(Qt::red).rgb()); |
|
940 QCOMPARE(fb.pixel(89, 64), QColor(Qt::red).rgb()); |
|
941 QCOMPARE(fb.pixel(64, 39), QColor(Qt::blue).rgb()); |
|
942 QCOMPARE(fb.pixel(64, 89), QColor(Qt::blue).rgb()); |
|
943 |
|
944 QCOMPARE(fb.pixel(167, 39), QColor(Qt::red).rgb()); |
|
945 QCOMPARE(fb.pixel(217, 39), QColor(Qt::red).rgb()); |
|
946 QCOMPARE(fb.pixel(192, 64), QColor(Qt::green).rgb()); |
|
947 } |
|
948 |
|
949 |
|
950 // Tests multiple QPainters active on different FBOs at the same time, with |
|
951 // interleaving painting. Performance-wise, this is sub-optimal, but it still |
|
952 // has to work flawlessly |
|
953 void tst_QGL::multipleFBOInterleavedRendering() |
|
954 { |
|
955 if (!QGLFramebufferObject::hasOpenGLFramebufferObjects()) |
|
956 QSKIP("QGLFramebufferObject not supported on this platform", SkipSingle); |
|
957 |
|
958 QGLWidget glw; |
|
959 glw.makeCurrent(); |
|
960 |
|
961 // No multisample with combined depth/stencil attachment: |
|
962 QGLFramebufferObjectFormat fboFormat; |
|
963 fboFormat.setAttachment(QGLFramebufferObject::CombinedDepthStencil); |
|
964 |
|
965 QGLFramebufferObject *fbo1 = new QGLFramebufferObject(256, 128, fboFormat); |
|
966 QGLFramebufferObject *fbo2 = new QGLFramebufferObject(256, 128, fboFormat); |
|
967 QGLFramebufferObject *fbo3 = new QGLFramebufferObject(256, 128, fboFormat); |
|
968 |
|
969 QPainter fbo1Painter; |
|
970 QPainter fbo2Painter; |
|
971 QPainter fbo3Painter; |
|
972 |
|
973 QVERIFY(fbo1Painter.begin(fbo1)); |
|
974 QVERIFY(fbo2Painter.begin(fbo2)); |
|
975 QVERIFY(fbo3Painter.begin(fbo3)); |
|
976 |
|
977 // Confirm we're using the GL2 engine, as interleaved rendering isn't supported |
|
978 // on the GL1 engine: |
|
979 if (fbo1Painter.paintEngine()->type() != QPaintEngine::OpenGL2) |
|
980 QSKIP("Interleaved GL rendering requires OpenGL 2.0 or higher", SkipSingle); |
|
981 |
|
982 QPainterPath intersectingPath; |
|
983 intersectingPath.moveTo(0, 0); |
|
984 intersectingPath.lineTo(100, 0); |
|
985 intersectingPath.lineTo(0, 100); |
|
986 intersectingPath.lineTo(100, 100); |
|
987 intersectingPath.closeSubpath(); |
|
988 |
|
989 QPainterPath trianglePath; |
|
990 trianglePath.moveTo(50, 0); |
|
991 trianglePath.lineTo(100, 100); |
|
992 trianglePath.lineTo(0, 100); |
|
993 trianglePath.closeSubpath(); |
|
994 |
|
995 fbo1Painter.fillRect(0, 0, fbo1->width(), fbo1->height(), Qt::red); // Background |
|
996 fbo2Painter.fillRect(0, 0, fbo2->width(), fbo2->height(), Qt::green); // Background |
|
997 fbo3Painter.fillRect(0, 0, fbo3->width(), fbo3->height(), Qt::blue); // Background |
|
998 |
|
999 fbo1Painter.translate(14, 14); |
|
1000 fbo2Painter.translate(14, 14); |
|
1001 fbo3Painter.translate(14, 14); |
|
1002 |
|
1003 fbo1Painter.fillPath(intersectingPath, Qt::blue); // Test stencil buffer works |
|
1004 fbo2Painter.fillPath(intersectingPath, Qt::red); // Test stencil buffer works |
|
1005 fbo3Painter.fillPath(intersectingPath, Qt::green); // Test stencil buffer works |
|
1006 |
|
1007 fbo1Painter.translate(128, 0); |
|
1008 fbo2Painter.translate(128, 0); |
|
1009 fbo3Painter.translate(128, 0); |
|
1010 |
|
1011 fbo1Painter.setClipPath(trianglePath); |
|
1012 fbo2Painter.setClipPath(trianglePath); |
|
1013 fbo3Painter.setClipPath(trianglePath); |
|
1014 |
|
1015 fbo1Painter.setTransform(QTransform()); // reset xform |
|
1016 fbo2Painter.setTransform(QTransform()); // reset xform |
|
1017 fbo3Painter.setTransform(QTransform()); // reset xform |
|
1018 |
|
1019 fbo1Painter.fillRect(0, 0, fbo1->width(), fbo1->height(), Qt::green); |
|
1020 fbo2Painter.fillRect(0, 0, fbo2->width(), fbo2->height(), Qt::blue); |
|
1021 fbo3Painter.fillRect(0, 0, fbo3->width(), fbo3->height(), Qt::red); |
|
1022 |
|
1023 fbo1Painter.end(); |
|
1024 fbo2Painter.end(); |
|
1025 fbo3Painter.end(); |
|
1026 |
|
1027 QImage fb1 = fbo1->toImage().convertToFormat(QImage::Format_RGB32); |
|
1028 QImage fb2 = fbo2->toImage().convertToFormat(QImage::Format_RGB32); |
|
1029 QImage fb3 = fbo3->toImage().convertToFormat(QImage::Format_RGB32); |
|
1030 delete fbo1; |
|
1031 delete fbo2; |
|
1032 delete fbo3; |
|
1033 |
|
1034 // As we're doing more than trivial painting, we can't just compare to |
|
1035 // an image rendered with raster. Instead, we sample at well-defined |
|
1036 // test-points: |
|
1037 QCOMPARE(fb1.pixel(39, 64), QColor(Qt::red).rgb()); |
|
1038 QCOMPARE(fb1.pixel(89, 64), QColor(Qt::red).rgb()); |
|
1039 QCOMPARE(fb1.pixel(64, 39), QColor(Qt::blue).rgb()); |
|
1040 QCOMPARE(fb1.pixel(64, 89), QColor(Qt::blue).rgb()); |
|
1041 QCOMPARE(fb1.pixel(167, 39), QColor(Qt::red).rgb()); |
|
1042 QCOMPARE(fb1.pixel(217, 39), QColor(Qt::red).rgb()); |
|
1043 QCOMPARE(fb1.pixel(192, 64), QColor(Qt::green).rgb()); |
|
1044 |
|
1045 QCOMPARE(fb2.pixel(39, 64), QColor(Qt::green).rgb()); |
|
1046 QCOMPARE(fb2.pixel(89, 64), QColor(Qt::green).rgb()); |
|
1047 QCOMPARE(fb2.pixel(64, 39), QColor(Qt::red).rgb()); |
|
1048 QCOMPARE(fb2.pixel(64, 89), QColor(Qt::red).rgb()); |
|
1049 QCOMPARE(fb2.pixel(167, 39), QColor(Qt::green).rgb()); |
|
1050 QCOMPARE(fb2.pixel(217, 39), QColor(Qt::green).rgb()); |
|
1051 QCOMPARE(fb2.pixel(192, 64), QColor(Qt::blue).rgb()); |
|
1052 |
|
1053 QCOMPARE(fb3.pixel(39, 64), QColor(Qt::blue).rgb()); |
|
1054 QCOMPARE(fb3.pixel(89, 64), QColor(Qt::blue).rgb()); |
|
1055 QCOMPARE(fb3.pixel(64, 39), QColor(Qt::green).rgb()); |
|
1056 QCOMPARE(fb3.pixel(64, 89), QColor(Qt::green).rgb()); |
|
1057 QCOMPARE(fb3.pixel(167, 39), QColor(Qt::blue).rgb()); |
|
1058 QCOMPARE(fb3.pixel(217, 39), QColor(Qt::blue).rgb()); |
|
1059 QCOMPARE(fb3.pixel(192, 64), QColor(Qt::red).rgb()); |
|
1060 } |
|
1061 |
|
1062 class FBOUseInGLWidget : public QGLWidget |
|
1063 { |
|
1064 public: |
|
1065 bool widgetPainterBeginOk; |
|
1066 bool fboPainterBeginOk; |
|
1067 QImage fboImage; |
|
1068 protected: |
|
1069 void paintEvent(QPaintEvent*) |
|
1070 { |
|
1071 QPainter widgetPainter; |
|
1072 widgetPainterBeginOk = widgetPainter.begin(this); |
|
1073 QGLFramebufferObjectFormat fboFormat; |
|
1074 fboFormat.setAttachment(QGLFramebufferObject::CombinedDepthStencil); |
|
1075 QGLFramebufferObject *fbo = new QGLFramebufferObject(128, 128, fboFormat); |
|
1076 |
|
1077 QPainter fboPainter; |
|
1078 fboPainterBeginOk = fboPainter.begin(fbo); |
|
1079 fboPainter.fillRect(0, 0, 128, 128, Qt::red); |
|
1080 fboPainter.end(); |
|
1081 fboImage = fbo->toImage(); |
|
1082 |
|
1083 widgetPainter.fillRect(rect(), Qt::blue); |
|
1084 |
|
1085 delete fbo; |
|
1086 } |
|
1087 |
|
1088 }; |
|
1089 |
|
1090 void tst_QGL::glFBOUseInGLWidget() |
|
1091 { |
|
1092 if (!QGLFramebufferObject::hasOpenGLFramebufferObjects()) |
|
1093 QSKIP("QGLFramebufferObject not supported on this platform", SkipSingle); |
|
1094 |
|
1095 FBOUseInGLWidget w; |
|
1096 w.resize(128, 128); |
|
1097 w.show(); |
|
1098 |
|
1099 #ifdef Q_WS_X11 |
|
1100 qt_x11_wait_for_window_manager(&w); |
|
1101 #endif |
|
1102 QTest::qWait(200); |
|
1103 |
|
1104 QVERIFY(w.widgetPainterBeginOk); |
|
1105 QVERIFY(w.fboPainterBeginOk); |
|
1106 |
|
1107 QImage widgetFB = w.grabFrameBuffer(false); |
|
1108 QImage widgetReference(widgetFB.size(), widgetFB.format()); |
|
1109 widgetReference.fill(0xff0000ff); |
|
1110 QCOMPARE(widgetFB, widgetReference); |
|
1111 |
|
1112 QImage fboReference(w.fboImage.size(), w.fboImage.format()); |
|
1113 fboReference.fill(0xffff0000); |
|
1114 QCOMPARE(w.fboImage, fboReference); |
|
1115 } |
|
1116 |
|
1117 void tst_QGL::glWidgetReparent() |
|
1118 { |
|
1119 // Try it as a top-level first: |
|
1120 GLWidget *widget = new GLWidget; |
|
1121 widget->setGeometry(0, 0, 200, 30); |
|
1122 widget->show(); |
|
1123 |
|
1124 QWidget grandParentWidget; |
|
1125 grandParentWidget.setPalette(Qt::blue); |
|
1126 QVBoxLayout grandParentLayout(&grandParentWidget); |
|
1127 |
|
1128 QWidget parentWidget(&grandParentWidget); |
|
1129 grandParentLayout.addWidget(&parentWidget); |
|
1130 parentWidget.setPalette(Qt::green); |
|
1131 parentWidget.setAutoFillBackground(true); |
|
1132 QVBoxLayout parentLayout(&parentWidget); |
|
1133 |
|
1134 grandParentWidget.setGeometry(0, 100, 200, 200); |
|
1135 grandParentWidget.show(); |
|
1136 |
|
1137 #ifdef Q_WS_X11 |
|
1138 qt_x11_wait_for_window_manager(widget); |
|
1139 qt_x11_wait_for_window_manager(&parentWidget); |
|
1140 #endif |
|
1141 QTest::qWait(200); |
|
1142 |
|
1143 QVERIFY(parentWidget.children().count() == 1); // The layout |
|
1144 |
|
1145 // Now both widgets should be created & shown, time to re-parent: |
|
1146 parentLayout.addWidget(widget); |
|
1147 |
|
1148 #ifdef Q_WS_X11 |
|
1149 qt_x11_wait_for_window_manager(&parentWidget); |
|
1150 #endif |
|
1151 QTest::qWait(200); |
|
1152 |
|
1153 QVERIFY(parentWidget.children().count() == 2); // Layout & glwidget |
|
1154 QVERIFY(parentWidget.children().contains(widget)); |
|
1155 QVERIFY(widget->height() > 30); |
|
1156 |
|
1157 delete widget; |
|
1158 |
|
1159 #ifdef Q_WS_X11 |
|
1160 qt_x11_wait_for_window_manager(&parentWidget); |
|
1161 #endif |
|
1162 QTest::qWait(200); |
|
1163 |
|
1164 QVERIFY(parentWidget.children().count() == 1); // The layout |
|
1165 |
|
1166 // Now do pretty much the same thing, but don't show the |
|
1167 // widget first: |
|
1168 widget = new GLWidget; |
|
1169 parentLayout.addWidget(widget); |
|
1170 |
|
1171 #ifdef Q_WS_X11 |
|
1172 qt_x11_wait_for_window_manager(&parentWidget); |
|
1173 #endif |
|
1174 QTest::qWait(200); |
|
1175 |
|
1176 QVERIFY(parentWidget.children().count() == 2); // Layout & glwidget |
|
1177 QVERIFY(parentWidget.children().contains(widget)); |
|
1178 QVERIFY(widget->height() > 30); |
|
1179 |
|
1180 delete widget; |
|
1181 } |
|
1182 |
|
1183 class RenderPixmapWidget : public QGLWidget |
|
1184 { |
|
1185 protected: |
|
1186 void initializeGL() { |
|
1187 // Set some gl state: |
|
1188 glClearColor(1.0, 0.0, 0.0, 1.0); |
|
1189 } |
|
1190 |
|
1191 void paintGL() { |
|
1192 glClear(GL_COLOR_BUFFER_BIT); |
|
1193 } |
|
1194 }; |
|
1195 |
|
1196 void tst_QGL::glWidgetRenderPixmap() |
|
1197 { |
|
1198 RenderPixmapWidget *w = new RenderPixmapWidget; |
|
1199 |
|
1200 QPixmap pm = w->renderPixmap(100, 100, false); |
|
1201 |
|
1202 delete w; |
|
1203 |
|
1204 QImage fb = pm.toImage().convertToFormat(QImage::Format_RGB32); |
|
1205 QImage reference(fb.size(), QImage::Format_RGB32); |
|
1206 reference.fill(0xffff0000); |
|
1207 |
|
1208 QCOMPARE(fb, reference); |
|
1209 } |
|
1210 |
|
1211 |
|
1212 // When using multiple FBOs at the same time, unbinding one FBO should re-bind the |
|
1213 // previous. I.e. It should be possible to have a stack of FBOs where pop'ing there |
|
1214 // top re-binds the one underneeth. |
|
1215 void tst_QGL::stackedFBOs() |
|
1216 { |
|
1217 if (!QGLFramebufferObject::hasOpenGLFramebufferObjects()) |
|
1218 QSKIP("QGLFramebufferObject not supported on this platform", SkipSingle); |
|
1219 |
|
1220 QGLWidget glw; |
|
1221 glw.show(); |
|
1222 |
|
1223 #ifdef Q_WS_X11 |
|
1224 qt_x11_wait_for_window_manager(&glw); |
|
1225 #endif |
|
1226 QTest::qWait(200); |
|
1227 |
|
1228 glw.makeCurrent(); |
|
1229 |
|
1230 // No multisample with combined depth/stencil attachment: |
|
1231 QGLFramebufferObjectFormat fboFormat; |
|
1232 fboFormat.setAttachment(QGLFramebufferObject::CombinedDepthStencil); |
|
1233 |
|
1234 // Don't complicate things by using NPOT: |
|
1235 QGLFramebufferObject *fbo1 = new QGLFramebufferObject(128, 128, fboFormat); |
|
1236 QGLFramebufferObject *fbo2 = new QGLFramebufferObject(128, 128, fboFormat); |
|
1237 QGLFramebufferObject *fbo3 = new QGLFramebufferObject(128, 128, fboFormat); |
|
1238 |
|
1239 glClearColor(1.0, 0.0, 1.0, 1.0); |
|
1240 glClear(GL_COLOR_BUFFER_BIT); |
|
1241 |
|
1242 fbo1->bind(); |
|
1243 glClearColor(1.0, 0.0, 0.0, 1.0); |
|
1244 glClear(GL_COLOR_BUFFER_BIT); |
|
1245 |
|
1246 fbo2->bind(); |
|
1247 glClearColor(0.0, 1.0, 0.0, 1.0); |
|
1248 glClear(GL_COLOR_BUFFER_BIT); |
|
1249 |
|
1250 fbo3->bind(); |
|
1251 glClearColor(0.0, 0.0, 1.0, 1.0); |
|
1252 glClear(GL_COLOR_BUFFER_BIT); |
|
1253 glScissor(32, 32, 64, 64); |
|
1254 glEnable(GL_SCISSOR_TEST); |
|
1255 glClearColor(0.0, 1.0, 1.0, 1.0); |
|
1256 glClear(GL_COLOR_BUFFER_BIT); |
|
1257 fbo3->release(); |
|
1258 |
|
1259 // Scissor rect & test should be left untouched by the fbo release... |
|
1260 glClearColor(0.0, 0.0, 0.0, 1.0); |
|
1261 glClear(GL_COLOR_BUFFER_BIT); |
|
1262 fbo2->release(); |
|
1263 |
|
1264 glClearColor(1.0, 1.0, 1.0, 1.0); |
|
1265 glClear(GL_COLOR_BUFFER_BIT); |
|
1266 fbo1->release(); |
|
1267 |
|
1268 glClearColor(1.0, 1.0, 0.0, 1.0); |
|
1269 glClear(GL_COLOR_BUFFER_BIT); |
|
1270 |
|
1271 glw.swapBuffers(); |
|
1272 |
|
1273 QImage widgetFB = glw.grabFrameBuffer(false).convertToFormat(QImage::Format_RGB32); |
|
1274 QImage fb1 = fbo1->toImage().convertToFormat(QImage::Format_RGB32); |
|
1275 QImage fb2 = fbo2->toImage().convertToFormat(QImage::Format_RGB32); |
|
1276 QImage fb3 = fbo3->toImage().convertToFormat(QImage::Format_RGB32); |
|
1277 |
|
1278 delete fbo1; |
|
1279 delete fbo2; |
|
1280 delete fbo3; |
|
1281 |
|
1282 QImage widgetReference(widgetFB.size(), widgetFB.format()); |
|
1283 QImage fb1Reference(fb1.size(), fb1.format()); |
|
1284 QImage fb2Reference(fb2.size(), fb2.format()); |
|
1285 QImage fb3Reference(fb3.size(), fb3.format()); |
|
1286 |
|
1287 QPainter widgetReferencePainter(&widgetReference); |
|
1288 QPainter fb1ReferencePainter(&fb1Reference); |
|
1289 QPainter fb2ReferencePainter(&fb2Reference); |
|
1290 QPainter fb3ReferencePainter(&fb3Reference); |
|
1291 |
|
1292 widgetReferencePainter.fillRect(0, 0, widgetReference.width(), widgetReference.height(), Qt::magenta); |
|
1293 fb1ReferencePainter.fillRect(0, 0, fb1Reference.width(), fb1Reference.height(), Qt::red); |
|
1294 fb2ReferencePainter.fillRect(0, 0, fb2Reference.width(), fb2Reference.height(), Qt::green); |
|
1295 fb3ReferencePainter.fillRect(0, 0, fb3Reference.width(), fb3Reference.height(), Qt::blue); |
|
1296 |
|
1297 // Flip y-coords to match GL for the widget (which can be any size) |
|
1298 widgetReferencePainter.fillRect(32, glw.height() - 96, 64, 64, Qt::yellow); |
|
1299 fb1ReferencePainter.fillRect(32, 32, 64, 64, Qt::white); |
|
1300 fb2ReferencePainter.fillRect(32, 32, 64, 64, Qt::black); |
|
1301 fb3ReferencePainter.fillRect(32, 32, 64, 64, Qt::cyan); |
|
1302 |
|
1303 widgetReferencePainter.end(); |
|
1304 fb1ReferencePainter.end(); |
|
1305 fb2ReferencePainter.end(); |
|
1306 fb3ReferencePainter.end(); |
|
1307 |
|
1308 QCOMPARE(widgetFB, widgetReference); |
|
1309 QCOMPARE(fb1, fb1Reference); |
|
1310 QCOMPARE(fb2, fb2Reference); |
|
1311 QCOMPARE(fb3, fb3Reference); |
|
1312 } |
|
1313 |
|
1314 |
|
1315 class ColormapExtended : public QGLColormap |
|
1316 { |
|
1317 public: |
|
1318 ColormapExtended() {} |
|
1319 |
|
1320 Qt::HANDLE handle() { return QGLColormap::handle(); } |
|
1321 void setHandle(Qt::HANDLE handle) { QGLColormap::setHandle(handle); } |
|
1322 }; |
|
1323 |
|
1324 void tst_QGL::colormap() |
|
1325 { |
|
1326 // Check the properties of the default empty colormap. |
|
1327 QGLColormap cmap1; |
|
1328 QVERIFY(cmap1.isEmpty()); |
|
1329 QCOMPARE(cmap1.size(), 0); |
|
1330 QVERIFY(cmap1.entryRgb(0) == 0); |
|
1331 QVERIFY(cmap1.entryRgb(-1) == 0); |
|
1332 QVERIFY(cmap1.entryRgb(100) == 0); |
|
1333 QVERIFY(!cmap1.entryColor(0).isValid()); |
|
1334 QVERIFY(!cmap1.entryColor(-1).isValid()); |
|
1335 QVERIFY(!cmap1.entryColor(100).isValid()); |
|
1336 QCOMPARE(cmap1.find(qRgb(255, 0, 0)), -1); |
|
1337 QCOMPARE(cmap1.findNearest(qRgb(255, 0, 0)), -1); |
|
1338 |
|
1339 // Set an entry and re-test. |
|
1340 cmap1.setEntry(56, qRgb(255, 0, 0)); |
|
1341 // The colormap is still considered "empty" even though it |
|
1342 // has entries in it now. The isEmpty() method is used to |
|
1343 // detect when the colormap is in use by a GL widget, |
|
1344 // not to detect when it is empty! |
|
1345 QVERIFY(cmap1.isEmpty()); |
|
1346 QCOMPARE(cmap1.size(), 256); |
|
1347 QVERIFY(cmap1.entryRgb(0) == 0); |
|
1348 QVERIFY(cmap1.entryColor(0) == QColor(0, 0, 0, 255)); |
|
1349 QVERIFY(cmap1.entryRgb(56) == qRgb(255, 0, 0)); |
|
1350 QVERIFY(cmap1.entryColor(56) == QColor(255, 0, 0, 255)); |
|
1351 QCOMPARE(cmap1.find(qRgb(255, 0, 0)), 56); |
|
1352 QCOMPARE(cmap1.findNearest(qRgb(255, 0, 0)), 56); |
|
1353 |
|
1354 // Set some more entries. |
|
1355 static QRgb const colors[] = { |
|
1356 qRgb(255, 0, 0), |
|
1357 qRgb(0, 255, 0), |
|
1358 qRgb(255, 255, 255), |
|
1359 qRgb(0, 0, 255), |
|
1360 qRgb(0, 0, 0) |
|
1361 }; |
|
1362 cmap1.setEntry(57, QColor(0, 255, 0)); |
|
1363 cmap1.setEntries(3, colors + 2, 58); |
|
1364 cmap1.setEntries(5, colors, 251); |
|
1365 int idx; |
|
1366 for (idx = 0; idx < 5; ++idx) { |
|
1367 QVERIFY(cmap1.entryRgb(56 + idx) == colors[idx]); |
|
1368 QVERIFY(cmap1.entryColor(56 + idx) == QColor(colors[idx])); |
|
1369 QVERIFY(cmap1.entryRgb(251 + idx) == colors[idx]); |
|
1370 QVERIFY(cmap1.entryColor(251 + idx) == QColor(colors[idx])); |
|
1371 } |
|
1372 QCOMPARE(cmap1.size(), 256); |
|
1373 |
|
1374 // Perform color lookups. |
|
1375 QCOMPARE(cmap1.find(qRgb(255, 0, 0)), 56); |
|
1376 QCOMPARE(cmap1.find(qRgb(0, 0, 0)), 60); // Actually finds 0, 0, 0, 255. |
|
1377 QCOMPARE(cmap1.find(qRgba(0, 0, 0, 0)), 0); |
|
1378 QCOMPARE(cmap1.find(qRgb(0, 255, 0)), 57); |
|
1379 QCOMPARE(cmap1.find(qRgb(255, 255, 255)), 58); |
|
1380 QCOMPARE(cmap1.find(qRgb(0, 0, 255)), 59); |
|
1381 QCOMPARE(cmap1.find(qRgb(140, 0, 0)), -1); |
|
1382 QCOMPARE(cmap1.find(qRgb(0, 140, 0)), -1); |
|
1383 QCOMPARE(cmap1.find(qRgb(0, 0, 140)), -1); |
|
1384 QCOMPARE(cmap1.find(qRgb(64, 0, 0)), -1); |
|
1385 QCOMPARE(cmap1.find(qRgb(0, 64, 0)), -1); |
|
1386 QCOMPARE(cmap1.find(qRgb(0, 0, 64)), -1); |
|
1387 QCOMPARE(cmap1.findNearest(qRgb(255, 0, 0)), 56); |
|
1388 QCOMPARE(cmap1.findNearest(qRgb(0, 0, 0)), 60); |
|
1389 QCOMPARE(cmap1.findNearest(qRgba(0, 0, 0, 0)), 0); |
|
1390 QCOMPARE(cmap1.findNearest(qRgb(0, 255, 0)), 57); |
|
1391 QCOMPARE(cmap1.findNearest(qRgb(255, 255, 255)), 58); |
|
1392 QCOMPARE(cmap1.findNearest(qRgb(0, 0, 255)), 59); |
|
1393 QCOMPARE(cmap1.findNearest(qRgb(140, 0, 0)), 56); |
|
1394 QCOMPARE(cmap1.findNearest(qRgb(0, 140, 0)), 57); |
|
1395 QCOMPARE(cmap1.findNearest(qRgb(0, 0, 140)), 59); |
|
1396 QCOMPARE(cmap1.findNearest(qRgb(64, 0, 0)), 0); |
|
1397 QCOMPARE(cmap1.findNearest(qRgb(0, 64, 0)), 0); |
|
1398 QCOMPARE(cmap1.findNearest(qRgb(0, 0, 64)), 0); |
|
1399 |
|
1400 // Make some copies of the colormap and check that they are the same. |
|
1401 QGLColormap cmap2(cmap1); |
|
1402 QGLColormap cmap3; |
|
1403 cmap3 = cmap1; |
|
1404 QVERIFY(cmap2.isEmpty()); |
|
1405 QVERIFY(cmap3.isEmpty()); |
|
1406 QCOMPARE(cmap2.size(), 256); |
|
1407 QCOMPARE(cmap3.size(), 256); |
|
1408 for (idx = 0; idx < 256; ++idx) { |
|
1409 QCOMPARE(cmap1.entryRgb(idx), cmap2.entryRgb(idx)); |
|
1410 QCOMPARE(cmap1.entryRgb(idx), cmap3.entryRgb(idx)); |
|
1411 } |
|
1412 |
|
1413 // Modify an entry in one of the copies and recheck the original. |
|
1414 cmap2.setEntry(45, qRgb(255, 0, 0)); |
|
1415 for (idx = 0; idx < 256; ++idx) { |
|
1416 if (idx != 45) |
|
1417 QCOMPARE(cmap1.entryRgb(idx), cmap2.entryRgb(idx)); |
|
1418 else |
|
1419 QCOMPARE(cmap2.entryRgb(45), qRgb(255, 0, 0)); |
|
1420 QCOMPARE(cmap1.entryRgb(idx), cmap3.entryRgb(idx)); |
|
1421 } |
|
1422 |
|
1423 // Check that setting the handle will cause isEmpty() to work right. |
|
1424 ColormapExtended cmap4; |
|
1425 cmap4.setEntry(56, qRgb(255, 0, 0)); |
|
1426 QVERIFY(cmap4.isEmpty()); |
|
1427 QCOMPARE(cmap4.size(), 256); |
|
1428 cmap4.setHandle(Qt::HANDLE(42)); |
|
1429 QVERIFY(cmap4.handle() == Qt::HANDLE(42)); |
|
1430 QVERIFY(!cmap4.isEmpty()); |
|
1431 QCOMPARE(cmap4.size(), 256); |
|
1432 } |
|
1433 |
|
1434 #ifndef QT_OPENGL_ES |
|
1435 #define DEFAULT_FORMAT GL_RGBA8 |
|
1436 #else |
|
1437 #define DEFAULT_FORMAT GL_RGBA |
|
1438 #endif |
|
1439 |
|
1440 #ifndef GL_TEXTURE_3D |
|
1441 #define GL_TEXTURE_3D 0x806F |
|
1442 #endif |
|
1443 |
|
1444 #ifndef GL_RGB16 |
|
1445 #define GL_RGB16 0x8054 |
|
1446 #endif |
|
1447 |
|
1448 void tst_QGL::fboFormat() |
|
1449 { |
|
1450 // Check the initial conditions. |
|
1451 QGLFramebufferObjectFormat format1; |
|
1452 QCOMPARE(format1.samples(), 0); |
|
1453 QVERIFY(format1.attachment() == QGLFramebufferObject::NoAttachment); |
|
1454 QCOMPARE(int(format1.textureTarget()), int(GL_TEXTURE_2D)); |
|
1455 QCOMPARE(int(format1.internalTextureFormat()), int(DEFAULT_FORMAT)); |
|
1456 |
|
1457 // Modify the values and re-check. |
|
1458 format1.setSamples(8); |
|
1459 format1.setAttachment(QGLFramebufferObject::CombinedDepthStencil); |
|
1460 format1.setTextureTarget(GL_TEXTURE_3D); |
|
1461 format1.setInternalTextureFormat(GL_RGB16); |
|
1462 QCOMPARE(format1.samples(), 8); |
|
1463 QVERIFY(format1.attachment() == QGLFramebufferObject::CombinedDepthStencil); |
|
1464 QCOMPARE(int(format1.textureTarget()), int(GL_TEXTURE_3D)); |
|
1465 QCOMPARE(int(format1.internalTextureFormat()), int(GL_RGB16)); |
|
1466 |
|
1467 // Make copies and check that they are the same. |
|
1468 QGLFramebufferObjectFormat format2(format1); |
|
1469 QGLFramebufferObjectFormat format3; |
|
1470 QCOMPARE(format2.samples(), 8); |
|
1471 QVERIFY(format2.attachment() == QGLFramebufferObject::CombinedDepthStencil); |
|
1472 QCOMPARE(int(format2.textureTarget()), int(GL_TEXTURE_3D)); |
|
1473 QCOMPARE(int(format2.internalTextureFormat()), int(GL_RGB16)); |
|
1474 format3 = format1; |
|
1475 QCOMPARE(format3.samples(), 8); |
|
1476 QVERIFY(format3.attachment() == QGLFramebufferObject::CombinedDepthStencil); |
|
1477 QCOMPARE(int(format3.textureTarget()), int(GL_TEXTURE_3D)); |
|
1478 QCOMPARE(int(format3.internalTextureFormat()), int(GL_RGB16)); |
|
1479 |
|
1480 // Modify the copies and check that the original is unchanged. |
|
1481 format2.setSamples(9); |
|
1482 format3.setTextureTarget(GL_TEXTURE_2D); |
|
1483 QCOMPARE(format1.samples(), 8); |
|
1484 QVERIFY(format1.attachment() == QGLFramebufferObject::CombinedDepthStencil); |
|
1485 QCOMPARE(int(format1.textureTarget()), int(GL_TEXTURE_3D)); |
|
1486 QCOMPARE(int(format1.internalTextureFormat()), int(GL_RGB16)); |
|
1487 |
|
1488 // operator== and operator!= for QGLFramebufferObjectFormat. |
|
1489 QGLFramebufferObjectFormat format1c; |
|
1490 QGLFramebufferObjectFormat format2c; |
|
1491 |
|
1492 QVERIFY(format1c == format2c); |
|
1493 QVERIFY(!(format1c != format2c)); |
|
1494 format1c.setSamples(8); |
|
1495 QVERIFY(!(format1c == format2c)); |
|
1496 QVERIFY(format1c != format2c); |
|
1497 format2c.setSamples(8); |
|
1498 QVERIFY(format1c == format2c); |
|
1499 QVERIFY(!(format1c != format2c)); |
|
1500 |
|
1501 format1c.setAttachment(QGLFramebufferObject::CombinedDepthStencil); |
|
1502 QVERIFY(!(format1c == format2c)); |
|
1503 QVERIFY(format1c != format2c); |
|
1504 format2c.setAttachment(QGLFramebufferObject::CombinedDepthStencil); |
|
1505 QVERIFY(format1c == format2c); |
|
1506 QVERIFY(!(format1c != format2c)); |
|
1507 |
|
1508 format1c.setTextureTarget(GL_TEXTURE_3D); |
|
1509 QVERIFY(!(format1c == format2c)); |
|
1510 QVERIFY(format1c != format2c); |
|
1511 format2c.setTextureTarget(GL_TEXTURE_3D); |
|
1512 QVERIFY(format1c == format2c); |
|
1513 QVERIFY(!(format1c != format2c)); |
|
1514 |
|
1515 format1c.setInternalTextureFormat(GL_RGB16); |
|
1516 QVERIFY(!(format1c == format2c)); |
|
1517 QVERIFY(format1c != format2c); |
|
1518 format2c.setInternalTextureFormat(GL_RGB16); |
|
1519 QVERIFY(format1c == format2c); |
|
1520 QVERIFY(!(format1c != format2c)); |
|
1521 |
|
1522 QGLFramebufferObjectFormat format3c(format1c); |
|
1523 QGLFramebufferObjectFormat format4c; |
|
1524 QVERIFY(format1c == format3c); |
|
1525 QVERIFY(!(format1c != format3c)); |
|
1526 format3c.setInternalTextureFormat(DEFAULT_FORMAT); |
|
1527 QVERIFY(!(format1c == format3c)); |
|
1528 QVERIFY(format1c != format3c); |
|
1529 |
|
1530 format4c = format1c; |
|
1531 QVERIFY(format1c == format4c); |
|
1532 QVERIFY(!(format1c != format4c)); |
|
1533 format4c.setInternalTextureFormat(DEFAULT_FORMAT); |
|
1534 QVERIFY(!(format1c == format4c)); |
|
1535 QVERIFY(format1c != format4c); |
|
1536 } |
|
1537 |
|
1538 void tst_QGL::testDontCrashOnDanglingResources() |
|
1539 { |
|
1540 // We have a number of Q_GLOBAL_STATICS inside the QtOpenGL |
|
1541 // library. This test is verify that we don't crash as a result of |
|
1542 // them calling into libgl on application shutdown. |
|
1543 QWidget *widget = new UnclippedWidget(); |
|
1544 widget->show(); |
|
1545 qApp->processEvents(); |
|
1546 widget->hide(); |
|
1547 } |
|
1548 |
|
1549 class ReplaceClippingGLWidget : public QGLWidget |
|
1550 { |
|
1551 public: |
|
1552 void paint(QPainter *painter) |
|
1553 { |
|
1554 painter->fillRect(rect(), Qt::white); |
|
1555 |
|
1556 QPainterPath path; |
|
1557 path.addRect(0, 0, 100, 100); |
|
1558 path.addRect(50, 50, 100, 100); |
|
1559 |
|
1560 painter->setClipRect(0, 0, 150, 150); |
|
1561 painter->fillPath(path, Qt::red); |
|
1562 |
|
1563 painter->translate(150, 150); |
|
1564 painter->setClipRect(0, 0, 150, 150); |
|
1565 painter->fillPath(path, Qt::red); |
|
1566 } |
|
1567 |
|
1568 protected: |
|
1569 void paintEvent(QPaintEvent*) |
|
1570 { |
|
1571 // clear the stencil with junk |
|
1572 glStencilMask(0xFFFF); |
|
1573 glClearStencil(0xFFFF); |
|
1574 glDisable(GL_STENCIL_TEST); |
|
1575 glDisable(GL_SCISSOR_TEST); |
|
1576 glClear(GL_STENCIL_BUFFER_BIT); |
|
1577 |
|
1578 QPainter painter(this); |
|
1579 paint(&painter); |
|
1580 } |
|
1581 }; |
|
1582 |
|
1583 void tst_QGL::replaceClipping() |
|
1584 { |
|
1585 ReplaceClippingGLWidget glw; |
|
1586 glw.resize(300, 300); |
|
1587 glw.show(); |
|
1588 |
|
1589 #ifdef Q_WS_X11 |
|
1590 qt_x11_wait_for_window_manager(&glw); |
|
1591 #endif |
|
1592 QTest::qWait(200); |
|
1593 |
|
1594 QImage reference(300, 300, QImage::Format_RGB32); |
|
1595 QPainter referencePainter(&reference); |
|
1596 glw.paint(&referencePainter); |
|
1597 referencePainter.end(); |
|
1598 |
|
1599 const QImage widgetFB = glw.grabFrameBuffer(false).convertToFormat(QImage::Format_RGB32); |
|
1600 |
|
1601 QCOMPARE(widgetFB, reference); |
|
1602 } |
|
1603 |
|
1604 class ClipTestGLWidget : public QGLWidget |
|
1605 { |
|
1606 public: |
|
1607 void paint(QPainter *painter) |
|
1608 { |
|
1609 painter->fillRect(rect(), Qt::white); |
|
1610 painter->setClipRect(10, 10, width()-20, height()-20); |
|
1611 painter->fillRect(rect(), Qt::cyan); |
|
1612 |
|
1613 painter->save(); |
|
1614 painter->setClipRect(10, 10, 100, 100, Qt::IntersectClip); |
|
1615 |
|
1616 painter->fillRect(rect(), Qt::blue); |
|
1617 |
|
1618 painter->save(); |
|
1619 painter->setClipRect(10, 10, 50, 50, Qt::IntersectClip); |
|
1620 painter->fillRect(rect(), Qt::red); |
|
1621 painter->restore(); |
|
1622 painter->fillRect(0, 0, 40, 40, Qt::white); |
|
1623 painter->save(); |
|
1624 |
|
1625 painter->setClipRect(0, 0, 35, 35, Qt::IntersectClip); |
|
1626 painter->fillRect(rect(), Qt::black); |
|
1627 painter->restore(); |
|
1628 |
|
1629 painter->fillRect(0, 0, 30, 30, Qt::magenta); |
|
1630 |
|
1631 painter->save(); |
|
1632 painter->setClipRect(60, 10, 50, 50, Qt::ReplaceClip); |
|
1633 painter->fillRect(rect(), Qt::green); |
|
1634 painter->restore(); |
|
1635 |
|
1636 painter->save(); |
|
1637 painter->setClipRect(0, 60, 60, 25, Qt::IntersectClip); |
|
1638 painter->setClipRect(60, 60, 50, 25, Qt::UniteClip); |
|
1639 painter->fillRect(rect(), Qt::yellow); |
|
1640 painter->restore(); |
|
1641 |
|
1642 painter->restore(); |
|
1643 |
|
1644 painter->translate(100, 100); |
|
1645 |
|
1646 { |
|
1647 QPainterPath path; |
|
1648 path.addRect(10, 10, 100, 100); |
|
1649 path.addRect(10, 10, 10, 10); |
|
1650 painter->setClipPath(path, Qt::IntersectClip); |
|
1651 } |
|
1652 |
|
1653 painter->fillRect(rect(), Qt::blue); |
|
1654 |
|
1655 painter->save(); |
|
1656 { |
|
1657 QPainterPath path; |
|
1658 path.addRect(10, 10, 50, 50); |
|
1659 path.addRect(10, 10, 10, 10); |
|
1660 painter->setClipPath(path, Qt::IntersectClip); |
|
1661 } |
|
1662 painter->fillRect(rect(), Qt::red); |
|
1663 painter->restore(); |
|
1664 painter->fillRect(0, 0, 40, 40, Qt::white); |
|
1665 painter->save(); |
|
1666 |
|
1667 { |
|
1668 QPainterPath path; |
|
1669 path.addRect(0, 0, 35, 35); |
|
1670 path.addRect(10, 10, 10, 10); |
|
1671 painter->setClipPath(path, Qt::IntersectClip); |
|
1672 } |
|
1673 painter->fillRect(rect(), Qt::black); |
|
1674 painter->restore(); |
|
1675 |
|
1676 painter->fillRect(0, 0, 30, 30, Qt::magenta); |
|
1677 |
|
1678 painter->save(); |
|
1679 { |
|
1680 QPainterPath path; |
|
1681 path.addRect(60, 10, 50, 50); |
|
1682 path.addRect(10, 10, 10, 10); |
|
1683 painter->setClipPath(path, Qt::ReplaceClip); |
|
1684 } |
|
1685 painter->fillRect(rect(), Qt::green); |
|
1686 painter->restore(); |
|
1687 |
|
1688 painter->save(); |
|
1689 { |
|
1690 QPainterPath path; |
|
1691 path.addRect(0, 60, 60, 25); |
|
1692 path.addRect(10, 10, 10, 10); |
|
1693 painter->setClipPath(path, Qt::IntersectClip); |
|
1694 } |
|
1695 painter->setClipRect(60, 60, 50, 25, Qt::UniteClip); |
|
1696 painter->fillRect(rect(), Qt::yellow); |
|
1697 painter->restore(); |
|
1698 } |
|
1699 |
|
1700 protected: |
|
1701 void paintEvent(QPaintEvent*) |
|
1702 { |
|
1703 QPainter painter(this); |
|
1704 paint(&painter); |
|
1705 } |
|
1706 }; |
|
1707 |
|
1708 void tst_QGL::clipTest() |
|
1709 { |
|
1710 ClipTestGLWidget glw; |
|
1711 glw.resize(220, 220); |
|
1712 glw.show(); |
|
1713 |
|
1714 #ifdef Q_WS_X11 |
|
1715 qt_x11_wait_for_window_manager(&glw); |
|
1716 #endif |
|
1717 QTest::qWait(200); |
|
1718 |
|
1719 QImage reference(glw.size(), QImage::Format_RGB32); |
|
1720 QPainter referencePainter(&reference); |
|
1721 glw.paint(&referencePainter); |
|
1722 referencePainter.end(); |
|
1723 |
|
1724 const QImage widgetFB = glw.grabFrameBuffer(false).convertToFormat(QImage::Format_RGB32); |
|
1725 |
|
1726 QCOMPARE(widgetFB, reference); |
|
1727 } |
|
1728 |
|
1729 void tst_QGL::destroyFBOAfterContext() |
|
1730 { |
|
1731 if (!QGLFramebufferObject::hasOpenGLFramebufferObjects()) |
|
1732 QSKIP("QGLFramebufferObject not supported on this platform", SkipSingle); |
|
1733 |
|
1734 QGLWidget *glw = new QGLWidget(); |
|
1735 glw->makeCurrent(); |
|
1736 |
|
1737 // No multisample with combined depth/stencil attachment: |
|
1738 QGLFramebufferObjectFormat fboFormat; |
|
1739 fboFormat.setAttachment(QGLFramebufferObject::CombinedDepthStencil); |
|
1740 |
|
1741 // Don't complicate things by using NPOT: |
|
1742 QGLFramebufferObject *fbo = new QGLFramebufferObject(256, 128, fboFormat); |
|
1743 |
|
1744 // The handle should be valid until the context is destroyed. |
|
1745 QVERIFY(fbo->handle() != 0); |
|
1746 QVERIFY(fbo->isValid()); |
|
1747 |
|
1748 delete glw; |
|
1749 |
|
1750 // The handle should now be zero. |
|
1751 QVERIFY(fbo->handle() == 0); |
|
1752 QVERIFY(!fbo->isValid()); |
|
1753 |
|
1754 delete fbo; |
|
1755 } |
|
1756 |
|
1757 #ifdef QT_BUILD_INTERNAL |
|
1758 |
|
1759 class tst_QGLResource : public QObject |
|
1760 { |
|
1761 Q_OBJECT |
|
1762 public: |
|
1763 tst_QGLResource(QObject *parent = 0) : QObject(parent) {} |
|
1764 ~tst_QGLResource() { ++deletions; } |
|
1765 |
|
1766 static int deletions; |
|
1767 }; |
|
1768 |
|
1769 int tst_QGLResource::deletions = 0; |
|
1770 |
|
1771 static void qt_shared_test_free(void *data) |
|
1772 { |
|
1773 delete reinterpret_cast<tst_QGLResource *>(data); |
|
1774 } |
|
1775 |
|
1776 Q_GLOBAL_STATIC_WITH_ARGS(QGLContextResource, qt_shared_test, (qt_shared_test_free)) |
|
1777 |
|
1778 #endif |
|
1779 |
|
1780 void tst_QGL::shareRegister() |
|
1781 { |
|
1782 #ifdef QT_BUILD_INTERNAL |
|
1783 QGLShareRegister *shareReg = qgl_share_reg(); |
|
1784 QVERIFY(shareReg != 0); |
|
1785 |
|
1786 // Create a context. |
|
1787 QGLWidget *glw1 = new QGLWidget(); |
|
1788 glw1->makeCurrent(); |
|
1789 |
|
1790 // Nothing should be sharing with glw1's context yet. |
|
1791 QList<const QGLContext *> list; |
|
1792 list = shareReg->shares(glw1->context()); |
|
1793 QCOMPARE(list.size(), 0); |
|
1794 |
|
1795 // Create a guard for the first context. |
|
1796 QGLSharedResourceGuard guard(glw1->context()); |
|
1797 QVERIFY(guard.id() == 0); |
|
1798 guard.setId(3); |
|
1799 QVERIFY(guard.id() == 3); |
|
1800 |
|
1801 // Add a resource to the first context. |
|
1802 tst_QGLResource *res1 = new tst_QGLResource(); |
|
1803 QVERIFY(!qt_shared_test()->value(glw1->context())); |
|
1804 qt_shared_test()->insert(glw1->context(), res1); |
|
1805 QVERIFY(qt_shared_test()->value(glw1->context()) == res1); |
|
1806 |
|
1807 // Create another context that shares with the first. |
|
1808 QGLWidget *glw2 = new QGLWidget(0, glw1); |
|
1809 if (!glw2->isSharing()) { |
|
1810 delete glw2; |
|
1811 delete glw1; |
|
1812 QSKIP("Context sharing is not supported", SkipSingle); |
|
1813 } |
|
1814 QVERIFY(glw1->context() != glw2->context()); |
|
1815 |
|
1816 // Check that the first context's resource is also on the second. |
|
1817 QVERIFY(qt_shared_test()->value(glw1->context()) == res1); |
|
1818 QVERIFY(qt_shared_test()->value(glw2->context()) == res1); |
|
1819 |
|
1820 // Guard should still be the same. |
|
1821 QVERIFY(guard.context() == glw1->context()); |
|
1822 QVERIFY(guard.id() == 3); |
|
1823 |
|
1824 // Now there are two items in the share lists. |
|
1825 list = shareReg->shares(glw1->context()); |
|
1826 QCOMPARE(list.size(), 2); |
|
1827 QVERIFY(list.contains(glw1->context())); |
|
1828 QVERIFY(list.contains(glw2->context())); |
|
1829 list = shareReg->shares(glw2->context()); |
|
1830 QCOMPARE(list.size(), 2); |
|
1831 QVERIFY(list.contains(glw1->context())); |
|
1832 QVERIFY(list.contains(glw2->context())); |
|
1833 |
|
1834 // Check the sharing relationships. |
|
1835 QVERIFY(QGLContext::areSharing(glw1->context(), glw1->context())); |
|
1836 QVERIFY(QGLContext::areSharing(glw2->context(), glw2->context())); |
|
1837 QVERIFY(QGLContext::areSharing(glw1->context(), glw2->context())); |
|
1838 QVERIFY(QGLContext::areSharing(glw2->context(), glw1->context())); |
|
1839 QVERIFY(!QGLContext::areSharing(0, glw2->context())); |
|
1840 QVERIFY(!QGLContext::areSharing(glw1->context(), 0)); |
|
1841 QVERIFY(!QGLContext::areSharing(0, 0)); |
|
1842 |
|
1843 // Create a third context, not sharing with the others. |
|
1844 QGLWidget *glw3 = new QGLWidget(); |
|
1845 |
|
1846 // Create a guard on the standalone context. |
|
1847 QGLSharedResourceGuard guard3(glw3->context()); |
|
1848 guard3.setId(5); |
|
1849 |
|
1850 // Add a resource to the third context. |
|
1851 tst_QGLResource *res3 = new tst_QGLResource(); |
|
1852 QVERIFY(!qt_shared_test()->value(glw3->context())); |
|
1853 qt_shared_test()->insert(glw3->context(), res3); |
|
1854 QVERIFY(qt_shared_test()->value(glw1->context()) == res1); |
|
1855 QVERIFY(qt_shared_test()->value(glw2->context()) == res1); |
|
1856 QVERIFY(qt_shared_test()->value(glw3->context()) == res3); |
|
1857 |
|
1858 // First two should still be sharing, but third is in its own list. |
|
1859 list = shareReg->shares(glw1->context()); |
|
1860 QCOMPARE(list.size(), 2); |
|
1861 QVERIFY(list.contains(glw1->context())); |
|
1862 QVERIFY(list.contains(glw2->context())); |
|
1863 list = shareReg->shares(glw2->context()); |
|
1864 QCOMPARE(list.size(), 2); |
|
1865 QVERIFY(list.contains(glw1->context())); |
|
1866 QVERIFY(list.contains(glw2->context())); |
|
1867 list = shareReg->shares(glw3->context()); |
|
1868 QCOMPARE(list.size(), 0); |
|
1869 |
|
1870 // Check the sharing relationships again. |
|
1871 QVERIFY(QGLContext::areSharing(glw1->context(), glw1->context())); |
|
1872 QVERIFY(QGLContext::areSharing(glw2->context(), glw2->context())); |
|
1873 QVERIFY(QGLContext::areSharing(glw1->context(), glw2->context())); |
|
1874 QVERIFY(QGLContext::areSharing(glw2->context(), glw1->context())); |
|
1875 QVERIFY(!QGLContext::areSharing(glw1->context(), glw3->context())); |
|
1876 QVERIFY(!QGLContext::areSharing(glw2->context(), glw3->context())); |
|
1877 QVERIFY(!QGLContext::areSharing(glw3->context(), glw1->context())); |
|
1878 QVERIFY(!QGLContext::areSharing(glw3->context(), glw2->context())); |
|
1879 QVERIFY(QGLContext::areSharing(glw3->context(), glw3->context())); |
|
1880 QVERIFY(!QGLContext::areSharing(0, glw2->context())); |
|
1881 QVERIFY(!QGLContext::areSharing(glw1->context(), 0)); |
|
1882 QVERIFY(!QGLContext::areSharing(0, glw3->context())); |
|
1883 QVERIFY(!QGLContext::areSharing(glw3->context(), 0)); |
|
1884 QVERIFY(!QGLContext::areSharing(0, 0)); |
|
1885 |
|
1886 // Shared guard should still be the same. |
|
1887 QVERIFY(guard.context() == glw1->context()); |
|
1888 QVERIFY(guard.id() == 3); |
|
1889 |
|
1890 // Delete the first context. |
|
1891 delete glw1; |
|
1892 |
|
1893 // The first context's resource should transfer to the second context. |
|
1894 QCOMPARE(tst_QGLResource::deletions, 0); |
|
1895 QVERIFY(qt_shared_test()->value(glw2->context()) == res1); |
|
1896 QVERIFY(qt_shared_test()->value(glw3->context()) == res3); |
|
1897 |
|
1898 // Shared guard should now be the second context, with the id the same. |
|
1899 QVERIFY(guard.context() == glw2->context()); |
|
1900 QVERIFY(guard.id() == 3); |
|
1901 QVERIFY(guard3.context() == glw3->context()); |
|
1902 QVERIFY(guard3.id() == 5); |
|
1903 |
|
1904 // Re-check the share list for the second context (should be empty now). |
|
1905 list = shareReg->shares(glw2->context()); |
|
1906 QCOMPARE(list.size(), 0); |
|
1907 |
|
1908 // Clean up and check that the resources are properly deleted. |
|
1909 delete glw2; |
|
1910 QCOMPARE(tst_QGLResource::deletions, 1); |
|
1911 delete glw3; |
|
1912 QCOMPARE(tst_QGLResource::deletions, 2); |
|
1913 |
|
1914 // Guards should now be null and the id zero. |
|
1915 QVERIFY(guard.context() == 0); |
|
1916 QVERIFY(guard.id() == 0); |
|
1917 QVERIFY(guard3.context() == 0); |
|
1918 QVERIFY(guard3.id() == 0); |
|
1919 #endif |
|
1920 } |
|
1921 |
|
1922 QTEST_MAIN(tst_QGL) |
|
1923 #include "tst_qgl.moc" |