source: trunk/src/opengl/qgl.cpp@ 603

Last change on this file since 603 was 561, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.1 sources.

File size: 159.0 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtOpenGL module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
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** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qapplication.h"
43#include "qplatformdefs.h"
44#include "qgl.h"
45#include <qdebug.h>
46
47#if defined(Q_WS_X11)
48#include "private/qt_x11_p.h"
49#include "private/qpixmap_x11_p.h"
50#define INT32 dummy_INT32
51#define INT8 dummy_INT8
52#if !defined(QT_OPENGL_ES)
53# include <GL/glx.h>
54#endif
55#undef INT32
56#undef INT8
57#include "qx11info_x11.h"
58#elif defined(Q_WS_MAC)
59# include <private/qt_mac_p.h>
60#endif
61
62#include <qdatetime.h>
63
64#include <stdlib.h> // malloc
65
66#include "qpixmap.h"
67#include "qimage.h"
68#include "qgl_p.h"
69
70#if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
71#include "gl2paintengineex/qpaintengineex_opengl2_p.h"
72#endif
73
74#ifndef QT_OPENGL_ES_2
75#include <private/qpaintengine_opengl_p.h>
76#endif
77
78#ifdef Q_WS_QWS
79#include <private/qglwindowsurface_qws_p.h>
80#endif
81
82#include <qglpixelbuffer.h>
83#include <qglframebufferobject.h>
84
85#include <private/qimage_p.h>
86#include <private/qpixmapdata_p.h>
87#include <private/qpixmapdata_gl_p.h>
88#include <private/qglpixelbuffer_p.h>
89#include <private/qwindowsurface_gl_p.h>
90#include <private/qimagepixmapcleanuphooks_p.h>
91#include "qcolormap.h"
92#include "qfile.h"
93#include "qlibrary.h"
94
95
96QT_BEGIN_NAMESPACE
97
98#ifdef QT_OPENGL_ES_1_CL
99#include "qgl_cl_p.h"
100#endif
101
102
103#if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS)
104QGLExtensionFuncs QGLContextPrivate::qt_extensionFuncs;
105#endif
106
107struct QGLThreadContext {
108 QGLContext *context;
109};
110
111static QThreadStorage<QGLThreadContext *> qgl_context_storage;
112
113Q_GLOBAL_STATIC(QGLFormat, qgl_default_format)
114
115class QGLDefaultOverlayFormat: public QGLFormat
116{
117public:
118 inline QGLDefaultOverlayFormat()
119 {
120 setOption(QGL::FormatOption(0xffff << 16)); // turn off all options
121 setOption(QGL::DirectRendering);
122 setPlane(1);
123 }
124};
125Q_GLOBAL_STATIC(QGLDefaultOverlayFormat, defaultOverlayFormatInstance)
126
127QGLExtensions::Extensions QGLExtensions::glExtensions = 0;
128bool QGLExtensions::nvidiaFboNeedsFinish = false;
129
130Q_GLOBAL_STATIC(QGLSignalProxy, theSignalProxy)
131QGLSignalProxy *QGLSignalProxy::instance()
132{
133 return theSignalProxy();
134}
135
136
137class QGLEngineSelector
138{
139public:
140 QGLEngineSelector() : engineType(QPaintEngine::MaxUser)
141 {
142 }
143
144 void setPreferredPaintEngine(QPaintEngine::Type type) {
145 if (type == QPaintEngine::OpenGL || type == QPaintEngine::OpenGL2)
146 engineType = type;
147 }
148
149 QPaintEngine::Type preferredPaintEngine() {
150#ifdef Q_WS_MAC
151 // The ATI X1600 driver for Mac OS X does not support return
152 // values from functions in GLSL. Since working around this in
153 // the GL2 engine would require a big, ugly rewrite, we're
154 // falling back to the GL 1 engine..
155 static bool mac_x1600_check_done = false;
156 if (!mac_x1600_check_done) {
157 QGLWidget *tmp = 0;
158 if (!QGLContext::currentContext()) {
159 tmp = new QGLWidget();
160 tmp->makeCurrent();
161 }
162 if (strstr((char *) glGetString(GL_RENDERER), "X1600"))
163 engineType = QPaintEngine::OpenGL;
164 if (tmp)
165 delete tmp;
166 mac_x1600_check_done = true;
167 }
168#endif
169 if (engineType == QPaintEngine::MaxUser) {
170 // No user-set engine - use the defaults
171#if defined(QT_OPENGL_ES_2)
172 engineType = QPaintEngine::OpenGL2;
173#else
174 // We can't do this in the constructor for this object because it
175 // needs to be called *before* the QApplication constructor.
176 // Also check for the FragmentShader extension in conjunction with
177 // the 2.0 version flag, to cover the case where we export the display
178 // from an old GL 1.1 server to a GL 2.x client. In that case we can't
179 // use GL 2.0.
180 if ((QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_2_0)
181 && (QGLExtensions::glExtensions & QGLExtensions::FragmentShader)
182 && qgetenv("QT_GL_USE_OPENGL1ENGINE").isEmpty())
183 engineType = QPaintEngine::OpenGL2;
184 else
185 engineType = QPaintEngine::OpenGL;
186#endif
187 }
188 return engineType;
189 }
190
191private:
192 QPaintEngine::Type engineType;
193};
194
195Q_GLOBAL_STATIC(QGLEngineSelector, qgl_engine_selector)
196
197
198bool qt_gl_preferGL2Engine()
199{
200 return qgl_engine_selector()->preferredPaintEngine() == QPaintEngine::OpenGL2;
201}
202
203
204/*!
205 \namespace QGL
206 \inmodule QtOpenGL
207
208 \brief The QGL namespace specifies miscellaneous identifiers used
209 in the Qt OpenGL module.
210
211 \ingroup painting-3D
212*/
213
214/*!
215 \enum QGL::FormatOption
216
217 This enum specifies the format options that can be used to configure an OpenGL
218 context. These are set using QGLFormat::setOption().
219
220 \value DoubleBuffer Specifies the use of double buffering.
221 \value DepthBuffer Enables the use of a depth buffer.
222 \value Rgba Specifies that the context should use RGBA as its pixel format.
223 \value AlphaChannel Enables the use of an alpha channel.
224 \value AccumBuffer Enables the use of an accumulation buffer.
225 \value StencilBuffer Enables the use of a stencil buffer.
226 \value StereoBuffers Enables the use of a stereo buffers for use with visualization hardware.
227 \value DirectRendering Specifies that the context is used for direct rendering to a display.
228 \value HasOverlay Enables the use of an overlay.
229 \value SampleBuffers Enables the use of sample buffers.
230 \value SingleBuffer Specifies the use of a single buffer, as opposed to double buffers.
231 \value NoDepthBuffer Disables the use of a depth buffer.
232 \value ColorIndex Specifies that the context should use a color index as its pixel format.
233 \value NoAlphaChannel Disables the use of an alpha channel.
234 \value NoAccumBuffer Disables the use of an accumulation buffer.
235 \value NoStencilBuffer Disables the use of a stencil buffer.
236 \value NoStereoBuffers Disables the use of stereo buffers.
237 \value IndirectRendering Specifies that the context is used for indirect rendering to a buffer.
238 \value NoOverlay Disables the use of an overlay.
239 \value NoSampleBuffers Disables the use of sample buffers.
240
241 \sa {Sample Buffers Example}
242*/
243
244/*!
245 \fn void QGL::setPreferredPaintEngine(QPaintEngine::Type engineType)
246
247 \since 4.6
248
249 Sets the preferred OpenGL paint engine that is used to draw onto
250 QGLWidget, QGLPixelBuffer and QGLFramebufferObject targets with QPainter
251 in Qt.
252
253 The \a engineType parameter specifies which of the GL engines to
254 use. Only \c QPaintEngine::OpenGL and \c QPaintEngine::OpenGL2 are
255 valid parameters to this function. All other values are ignored.
256
257 By default, the \c QPaintEngine::OpenGL2 engine is used if GL/GLES
258 version 2.0 is available, otherwise \c QPaintEngine::OpenGL is
259 used.
260
261 \warning This function must be called before the QApplication
262 constructor is called.
263*/
264void QGL::setPreferredPaintEngine(QPaintEngine::Type engineType)
265{
266 qgl_engine_selector()->setPreferredPaintEngine(engineType);
267}
268
269
270/*****************************************************************************
271 QGLFormat implementation
272 *****************************************************************************/
273
274
275/*!
276 \class QGLFormat
277 \brief The QGLFormat class specifies the display format of an OpenGL
278 rendering context.
279
280 \ingroup painting-3D
281
282 A display format has several characteristics:
283 \list
284 \i \link setDoubleBuffer() Double or single buffering.\endlink
285 \i \link setDepth() Depth buffer.\endlink
286 \i \link setRgba() RGBA or color index mode.\endlink
287 \i \link setAlpha() Alpha channel.\endlink
288 \i \link setAccum() Accumulation buffer.\endlink
289 \i \link setStencil() Stencil buffer.\endlink
290 \i \link setStereo() Stereo buffers.\endlink
291 \i \link setDirectRendering() Direct rendering.\endlink
292 \i \link setOverlay() Presence of an overlay.\endlink
293 \i \link setPlane() Plane of an overlay.\endlink
294 \i \link setSampleBuffers() Multisample buffers.\endlink
295 \endlist
296
297 You can also specify preferred bit depths for the color buffer,
298 depth buffer, alpha buffer, accumulation buffer and the stencil
299 buffer with the functions: setRedBufferSize(), setGreenBufferSize(),
300 setBlueBufferSize(), setDepthBufferSize(), setAlphaBufferSize(),
301 setAccumBufferSize() and setStencilBufferSize().
302
303 Note that even if you specify that you prefer a 32 bit depth
304 buffer (e.g. with setDepthBufferSize(32)), the format that is
305 chosen may not have a 32 bit depth buffer, even if there is a
306 format available with a 32 bit depth buffer. The main reason for
307 this is how the system dependant picking algorithms work on the
308 different platforms, and some format options may have higher
309 precedence than others.
310
311 You create and tell a QGLFormat object what rendering options you
312 want from an OpenGL rendering context.
313
314 OpenGL drivers or accelerated hardware may or may not support
315 advanced features such as alpha channel or stereographic viewing.
316 If you request some features that the driver/hardware does not
317 provide when you create a QGLWidget, you will get a rendering
318 context with the nearest subset of features.
319
320 There are different ways to define the display characteristics of
321 a rendering context. One is to create a QGLFormat and make it the
322 default for the entire application:
323 \snippet doc/src/snippets/code/src_opengl_qgl.cpp 0
324
325 Or you can specify the desired format when creating an object of
326 your QGLWidget subclass:
327 \snippet doc/src/snippets/code/src_opengl_qgl.cpp 1
328
329 After the widget has been created, you can find out which of the
330 requested features the system was able to provide:
331 \snippet doc/src/snippets/code/src_opengl_qgl.cpp 2
332
333 \legalese
334 OpenGL is a trademark of Silicon Graphics, Inc. in the
335 United States and other countries.
336 \endlegalese
337
338 \sa QGLContext, QGLWidget
339*/
340
341#ifndef QT_OPENGL_ES
342
343static inline void transform_point(GLdouble out[4], const GLdouble m[16], const GLdouble in[4])
344{
345#define M(row,col) m[col*4+row]
346 out[0] =
347 M(0, 0) * in[0] + M(0, 1) * in[1] + M(0, 2) * in[2] + M(0, 3) * in[3];
348 out[1] =
349 M(1, 0) * in[0] + M(1, 1) * in[1] + M(1, 2) * in[2] + M(1, 3) * in[3];
350 out[2] =
351 M(2, 0) * in[0] + M(2, 1) * in[1] + M(2, 2) * in[2] + M(2, 3) * in[3];
352 out[3] =
353 M(3, 0) * in[0] + M(3, 1) * in[1] + M(3, 2) * in[2] + M(3, 3) * in[3];
354#undef M
355}
356
357static inline GLint qgluProject(GLdouble objx, GLdouble objy, GLdouble objz,
358 const GLdouble model[16], const GLdouble proj[16],
359 const GLint viewport[4],
360 GLdouble * winx, GLdouble * winy, GLdouble * winz)
361{
362 GLdouble in[4], out[4];
363
364 in[0] = objx;
365 in[1] = objy;
366 in[2] = objz;
367 in[3] = 1.0;
368 transform_point(out, model, in);
369 transform_point(in, proj, out);
370
371 if (in[3] == 0.0)
372 return GL_FALSE;
373
374 in[0] /= in[3];
375 in[1] /= in[3];
376 in[2] /= in[3];
377
378 *winx = viewport[0] + (1 + in[0]) * viewport[2] / 2;
379 *winy = viewport[1] + (1 + in[1]) * viewport[3] / 2;
380
381 *winz = (1 + in[2]) / 2;
382 return GL_TRUE;
383}
384
385#endif // !QT_OPENGL_ES
386
387/*!
388 Constructs a QGLFormat object with the following default settings:
389 \list
390 \i \link setDoubleBuffer() Double buffer:\endlink Enabled.
391 \i \link setDepth() Depth buffer:\endlink Enabled.
392 \i \link setRgba() RGBA:\endlink Enabled (i.e., color index disabled).
393 \i \link setAlpha() Alpha channel:\endlink Disabled.
394 \i \link setAccum() Accumulator buffer:\endlink Disabled.
395 \i \link setStencil() Stencil buffer:\endlink Enabled.
396 \i \link setStereo() Stereo:\endlink Disabled.
397 \i \link setDirectRendering() Direct rendering:\endlink Enabled.
398 \i \link setOverlay() Overlay:\endlink Disabled.
399 \i \link setPlane() Plane:\endlink 0 (i.e., normal plane).
400 \i \link setSampleBuffers() Multisample buffers:\endlink Disabled.
401 \endlist
402*/
403
404QGLFormat::QGLFormat()
405{
406 d = new QGLFormatPrivate;
407}
408
409
410/*!
411 Creates a QGLFormat object that is a copy of the current
412 defaultFormat().
413
414 If \a options is not 0, the default format is modified by the
415 specified format options. The \a options parameter should be
416 QGL::FormatOption values OR'ed together.
417
418 This constructor makes it easy to specify a certain desired format
419 in classes derived from QGLWidget, for example:
420 \snippet doc/src/snippets/code/src_opengl_qgl.cpp 3
421
422 Note that there are QGL::FormatOption values to turn format settings
423 both on and off, e.g. QGL::DepthBuffer and QGL::NoDepthBuffer,
424 QGL::DirectRendering and QGL::IndirectRendering, etc.
425
426 The \a plane parameter defaults to 0 and is the plane which this
427 format should be associated with. Not all OpenGL implementations
428 supports overlay/underlay rendering planes.
429
430 \sa defaultFormat(), setOption(), setPlane()
431*/
432
433QGLFormat::QGLFormat(QGL::FormatOptions options, int plane)
434{
435 d = new QGLFormatPrivate;
436 QGL::FormatOptions newOpts = options;
437 d->opts = defaultFormat().d->opts;
438 d->opts |= (newOpts & 0xffff);
439 d->opts &= ~(newOpts >> 16);
440 d->pln = plane;
441}
442
443/*!
444 \internal
445*/
446void QGLFormat::detach()
447{
448 if (d->ref != 1) {
449 QGLFormatPrivate *newd = new QGLFormatPrivate(d);
450 if (!d->ref.deref())
451 delete d;
452 d = newd;
453 }
454}
455
456/*!
457 Constructs a copy of \a other.
458*/
459
460QGLFormat::QGLFormat(const QGLFormat &other)
461{
462 d = other.d;
463 d->ref.ref();
464}
465
466/*!
467 Assigns \a other to this object.
468*/
469
470QGLFormat &QGLFormat::operator=(const QGLFormat &other)
471{
472 if (d != other.d) {
473 other.d->ref.ref();
474 if (!d->ref.deref())
475 delete d;
476 d = other.d;
477 }
478 return *this;
479}
480
481/*!
482 Destroys the QGLFormat.
483*/
484QGLFormat::~QGLFormat()
485{
486 if (!d->ref.deref())
487 delete d;
488}
489
490/*!
491 \fn bool QGLFormat::doubleBuffer() const
492
493 Returns true if double buffering is enabled; otherwise returns
494 false. Double buffering is enabled by default.
495
496 \sa setDoubleBuffer()
497*/
498
499/*!
500 If \a enable is true sets double buffering; otherwise sets single
501 buffering.
502
503 Double buffering is enabled by default.
504
505 Double buffering is a technique where graphics are rendered on an
506 off-screen buffer and not directly to the screen. When the drawing
507 has been completed, the program calls a swapBuffers() function to
508 exchange the screen contents with the buffer. The result is
509 flicker-free drawing and often better performance.
510
511 \sa doubleBuffer(), QGLContext::swapBuffers(),
512 QGLWidget::swapBuffers()
513*/
514
515void QGLFormat::setDoubleBuffer(bool enable)
516{
517 setOption(enable ? QGL::DoubleBuffer : QGL::SingleBuffer);
518}
519
520
521/*!
522 \fn bool QGLFormat::depth() const
523
524 Returns true if the depth buffer is enabled; otherwise returns
525 false. The depth buffer is enabled by default.
526
527 \sa setDepth(), setDepthBufferSize()
528*/
529
530/*!
531 If \a enable is true enables the depth buffer; otherwise disables
532 the depth buffer.
533
534 The depth buffer is enabled by default.
535
536 The purpose of a depth buffer (or Z-buffering) is to remove hidden
537 surfaces. Pixels are assigned Z values based on the distance to
538 the viewer. A pixel with a high Z value is closer to the viewer
539 than a pixel with a low Z value. This information is used to
540 decide whether to draw a pixel or not.
541
542 \sa depth(), setDepthBufferSize()
543*/
544
545void QGLFormat::setDepth(bool enable)
546{
547 setOption(enable ? QGL::DepthBuffer : QGL::NoDepthBuffer);
548}
549
550
551/*!
552 \fn bool QGLFormat::rgba() const
553
554 Returns true if RGBA color mode is set. Returns false if color
555 index mode is set. The default color mode is RGBA.
556
557 \sa setRgba()
558*/
559
560/*!
561 If \a enable is true sets RGBA mode. If \a enable is false sets
562 color index mode.
563
564 The default color mode is RGBA.
565
566 RGBA is the preferred mode for most OpenGL applications. In RGBA
567 color mode you specify colors as red + green + blue + alpha
568 quadruplets.
569
570 In color index mode you specify an index into a color lookup
571 table.
572
573 \sa rgba()
574*/
575
576void QGLFormat::setRgba(bool enable)
577{
578 setOption(enable ? QGL::Rgba : QGL::ColorIndex);
579}
580
581
582/*!
583 \fn bool QGLFormat::alpha() const
584
585 Returns true if the alpha buffer in the framebuffer is enabled;
586 otherwise returns false. The alpha buffer is disabled by default.
587
588 \sa setAlpha(), setAlphaBufferSize()
589*/
590
591/*!
592 If \a enable is true enables the alpha buffer; otherwise disables
593 the alpha buffer.
594
595 The alpha buffer is disabled by default.
596
597 The alpha buffer is typically used for implementing transparency
598 or translucency. The A in RGBA specifies the transparency of a
599 pixel.
600
601 \sa alpha(), setAlphaBufferSize()
602*/
603
604void QGLFormat::setAlpha(bool enable)
605{
606 setOption(enable ? QGL::AlphaChannel : QGL::NoAlphaChannel);
607}
608
609
610/*!
611 \fn bool QGLFormat::accum() const
612
613 Returns true if the accumulation buffer is enabled; otherwise
614 returns false. The accumulation buffer is disabled by default.
615
616 \sa setAccum(), setAccumBufferSize()
617*/
618
619/*!
620 If \a enable is true enables the accumulation buffer; otherwise
621 disables the accumulation buffer.
622
623 The accumulation buffer is disabled by default.
624
625 The accumulation buffer is used to create blur effects and
626 multiple exposures.
627
628 \sa accum(), setAccumBufferSize()
629*/
630
631void QGLFormat::setAccum(bool enable)
632{
633 setOption(enable ? QGL::AccumBuffer : QGL::NoAccumBuffer);
634}
635
636
637/*!
638 \fn bool QGLFormat::stencil() const
639
640 Returns true if the stencil buffer is enabled; otherwise returns
641 false. The stencil buffer is enabled by default.
642
643 \sa setStencil(), setStencilBufferSize()
644*/
645
646/*!
647 If \a enable is true enables the stencil buffer; otherwise
648 disables the stencil buffer.
649
650 The stencil buffer is enabled by default.
651
652 The stencil buffer masks certain parts of the drawing area so that
653 masked parts are not drawn on.
654
655 \sa stencil(), setStencilBufferSize()
656*/
657
658void QGLFormat::setStencil(bool enable)
659{
660 setOption(enable ? QGL::StencilBuffer: QGL::NoStencilBuffer);
661}
662
663
664/*!
665 \fn bool QGLFormat::stereo() const
666
667 Returns true if stereo buffering is enabled; otherwise returns
668 false. Stereo buffering is disabled by default.
669
670 \sa setStereo()
671*/
672
673/*!
674 If \a enable is true enables stereo buffering; otherwise disables
675 stereo buffering.
676
677 Stereo buffering is disabled by default.
678
679 Stereo buffering provides extra color buffers to generate left-eye
680 and right-eye images.
681
682 \sa stereo()
683*/
684
685void QGLFormat::setStereo(bool enable)
686{
687 setOption(enable ? QGL::StereoBuffers : QGL::NoStereoBuffers);
688}
689
690
691/*!
692 \fn bool QGLFormat::directRendering() const
693
694 Returns true if direct rendering is enabled; otherwise returns
695 false.
696
697 Direct rendering is enabled by default.
698
699 \sa setDirectRendering()
700*/
701
702/*!
703 If \a enable is true enables direct rendering; otherwise disables
704 direct rendering.
705
706 Direct rendering is enabled by default.
707
708 Enabling this option will make OpenGL bypass the underlying window
709 system and render directly from hardware to the screen, if this is
710 supported by the system.
711
712 \sa directRendering()
713*/
714
715void QGLFormat::setDirectRendering(bool enable)
716{
717 setOption(enable ? QGL::DirectRendering : QGL::IndirectRendering);
718}
719
720/*!
721 \fn bool QGLFormat::sampleBuffers() const
722
723 Returns true if multisample buffer support is enabled; otherwise
724 returns false.
725
726 The multisample buffer is disabled by default.
727
728 \sa setSampleBuffers()
729*/
730
731/*!
732 If \a enable is true, a GL context with multisample buffer support
733 is picked; otherwise ignored.
734
735 \sa sampleBuffers(), setSamples(), samples()
736*/
737void QGLFormat::setSampleBuffers(bool enable)
738{
739 setOption(enable ? QGL::SampleBuffers : QGL::NoSampleBuffers);
740}
741
742/*!
743 Returns the number of samples per pixel when multisampling is
744 enabled. By default, the highest number of samples that is
745 available is used.
746
747 \sa setSampleBuffers(), sampleBuffers(), setSamples()
748*/
749int QGLFormat::samples() const
750{
751 return d->numSamples;
752}
753
754/*!
755 Set the preferred number of samples per pixel when multisampling
756 is enabled to \a numSamples. By default, the highest number of
757 samples available is used.
758
759 \sa setSampleBuffers(), sampleBuffers(), samples()
760*/
761void QGLFormat::setSamples(int numSamples)
762{
763 detach();
764 if (numSamples < 0) {
765 qWarning("QGLFormat::setSamples: Cannot have negative number of samples per pixel %d", numSamples);
766 return;
767 }
768 d->numSamples = numSamples;
769}
770
771/*!
772 \since 4.2
773
774 Set the preferred swap interval. This can be used to sync the GL
775 drawing into a system window to the vertical refresh of the screen.
776 Setting an \a interval value of 0 will turn the vertical refresh syncing
777 off, any value higher than 0 will turn the vertical syncing on.
778
779 Under Windows and under X11, where the \c{WGL_EXT_swap_control}
780 and \c{GLX_SGI_video_sync} extensions are used, the \a interval
781 parameter can be used to set the minimum number of video frames
782 that are displayed before a buffer swap will occur. In effect,
783 setting the \a interval to 10, means there will be 10 vertical
784 retraces between every buffer swap.
785
786 Under Windows the \c{WGL_EXT_swap_control} extension has to be present,
787 and under X11 the \c{GLX_SGI_video_sync} extension has to be present.
788*/
789void QGLFormat::setSwapInterval(int interval)
790{
791 detach();
792 d->swapInterval = interval;
793}
794
795/*!
796 \since 4.2
797
798 Returns the currently set swap interval. -1 is returned if setting
799 the swap interval isn't supported in the system GL implementation.
800*/
801int QGLFormat::swapInterval() const
802{
803 return d->swapInterval;
804}
805
806/*!
807 \fn bool QGLFormat::hasOverlay() const
808
809 Returns true if overlay plane is enabled; otherwise returns false.
810
811 Overlay is disabled by default.
812
813 \sa setOverlay()
814*/
815
816/*!
817 If \a enable is true enables an overlay plane; otherwise disables
818 the overlay plane.
819
820 Enabling the overlay plane will cause QGLWidget to create an
821 additional context in an overlay plane. See the QGLWidget
822 documentation for further information.
823
824 \sa hasOverlay()
825*/
826
827void QGLFormat::setOverlay(bool enable)
828{
829 setOption(enable ? QGL::HasOverlay : QGL::NoOverlay);
830}
831
832/*!
833 Returns the plane of this format. The default for normal formats
834 is 0, which means the normal plane. The default for overlay
835 formats is 1, which is the first overlay plane.
836
837 \sa setPlane(), defaultOverlayFormat()
838*/
839int QGLFormat::plane() const
840{
841 return d->pln;
842}
843
844/*!
845 Sets the requested plane to \a plane. 0 is the normal plane, 1 is
846 the first overlay plane, 2 is the second overlay plane, etc.; -1,
847 -2, etc. are underlay planes.
848
849 Note that in contrast to other format specifications, the plane
850 specifications will be matched exactly. This means that if you
851 specify a plane that the underlying OpenGL system cannot provide,
852 an \link QGLWidget::isValid() invalid\endlink QGLWidget will be
853 created.
854
855 \sa plane()
856*/
857void QGLFormat::setPlane(int plane)
858{
859 detach();
860 d->pln = plane;
861}
862
863/*!
864 Sets the format option to \a opt.
865
866 \sa testOption()
867*/
868
869void QGLFormat::setOption(QGL::FormatOptions opt)
870{
871 detach();
872 if (opt & 0xffff)
873 d->opts |= opt;
874 else
875 d->opts &= ~(opt >> 16);
876}
877
878
879
880/*!
881 Returns true if format option \a opt is set; otherwise returns false.
882
883 \sa setOption()
884*/
885
886bool QGLFormat::testOption(QGL::FormatOptions opt) const
887{
888 if (opt & 0xffff)
889 return (d->opts & opt) != 0;
890 else
891 return (d->opts & (opt >> 16)) == 0;
892}
893
894/*!
895 Set the minimum depth buffer size to \a size.
896
897 \sa depthBufferSize(), setDepth(), depth()
898*/
899void QGLFormat::setDepthBufferSize(int size)
900{
901 detach();
902 if (size < 0) {
903 qWarning("QGLFormat::setDepthBufferSize: Cannot set negative depth buffer size %d", size);
904 return;
905 }
906 d->depthSize = size;
907}
908
909/*!
910 Returns the depth buffer size.
911
912 \sa depth(), setDepth(), setDepthBufferSize()
913*/
914int QGLFormat::depthBufferSize() const
915{
916 return d->depthSize;
917}
918
919/*!
920 \since 4.2
921
922 Set the preferred red buffer size to \a size.
923
924 \sa setGreenBufferSize(), setBlueBufferSize(), setAlphaBufferSize()
925*/
926void QGLFormat::setRedBufferSize(int size)
927{
928 detach();
929 if (size < 0) {
930 qWarning("QGLFormat::setRedBufferSize: Cannot set negative red buffer size %d", size);
931 return;
932 }
933 d->redSize = size;
934}
935
936/*!
937 \since 4.2
938
939 Returns the red buffer size.
940
941 \sa setRedBufferSize()
942*/
943int QGLFormat::redBufferSize() const
944{
945 return d->redSize;
946}
947
948/*!
949 \since 4.2
950
951 Set the preferred green buffer size to \a size.
952
953 \sa setRedBufferSize(), setBlueBufferSize(), setAlphaBufferSize()
954*/
955void QGLFormat::setGreenBufferSize(int size)
956{
957 detach();
958 if (size < 0) {
959 qWarning("QGLFormat::setGreenBufferSize: Cannot set negative green buffer size %d", size);
960 return;
961 }
962 d->greenSize = size;
963}
964
965/*!
966 \since 4.2
967
968 Returns the green buffer size.
969
970 \sa setGreenBufferSize()
971*/
972int QGLFormat::greenBufferSize() const
973{
974 return d->greenSize;
975}
976
977/*!
978 \since 4.2
979
980 Set the preferred blue buffer size to \a size.
981
982 \sa setRedBufferSize(), setGreenBufferSize(), setAlphaBufferSize()
983*/
984void QGLFormat::setBlueBufferSize(int size)
985{
986 detach();
987 if (size < 0) {
988 qWarning("QGLFormat::setBlueBufferSize: Cannot set negative blue buffer size %d", size);
989 return;
990 }
991 d->blueSize = size;
992}
993
994/*!
995 \since 4.2
996
997 Returns the blue buffer size.
998
999 \sa setBlueBufferSize()
1000*/
1001int QGLFormat::blueBufferSize() const
1002{
1003 return d->blueSize;
1004}
1005
1006/*!
1007 Set the preferred alpha buffer size to \a size.
1008 This function implicitly enables the alpha channel.
1009
1010 \sa setRedBufferSize(), setGreenBufferSize(), alphaBufferSize()
1011*/
1012void QGLFormat::setAlphaBufferSize(int size)
1013{
1014 detach();
1015 if (size < 0) {
1016 qWarning("QGLFormat::setAlphaBufferSize: Cannot set negative alpha buffer size %d", size);
1017 return;
1018 }
1019 d->alphaSize = size;
1020 setOption(QGL::AlphaChannel);
1021}
1022
1023/*!
1024 Returns the alpha buffer size.
1025
1026 \sa alpha(), setAlpha(), setAlphaBufferSize()
1027*/
1028int QGLFormat::alphaBufferSize() const
1029{
1030 return d->alphaSize;
1031}
1032
1033/*!
1034 Set the preferred accumulation buffer size, where \a size is the
1035 bit depth for each RGBA component.
1036
1037 \sa accum(), setAccum(), accumBufferSize()
1038*/
1039void QGLFormat::setAccumBufferSize(int size)
1040{
1041 detach();
1042 if (size < 0) {
1043 qWarning("QGLFormat::setAccumBufferSize: Cannot set negative accumulate buffer size %d", size);
1044 return;
1045 }
1046 d->accumSize = size;
1047}
1048
1049/*!
1050 Returns the accumulation buffer size.
1051
1052 \sa setAccumBufferSize(), accum(), setAccum()
1053*/
1054int QGLFormat::accumBufferSize() const
1055{
1056 return d->accumSize;
1057}
1058
1059/*!
1060 Set the preferred stencil buffer size to \a size.
1061
1062 \sa stencilBufferSize(), setStencil(), stencil()
1063*/
1064void QGLFormat::setStencilBufferSize(int size)
1065{
1066 detach();
1067 if (size < 0) {
1068 qWarning("QGLFormat::setStencilBufferSize: Cannot set negative stencil buffer size %d", size);
1069 return;
1070 }
1071 d->stencilSize = size;
1072}
1073
1074/*!
1075 Returns the stencil buffer size.
1076
1077 \sa stencil(), setStencil(), setStencilBufferSize()
1078*/
1079int QGLFormat::stencilBufferSize() const
1080{
1081 return d->stencilSize;
1082}
1083
1084/*!
1085 \fn bool QGLFormat::hasOpenGL()
1086
1087 Returns true if the window system has any OpenGL support;
1088 otherwise returns false.
1089
1090 \warning This function must not be called until the QApplication
1091 object has been created.
1092*/
1093
1094
1095
1096/*!
1097 \fn bool QGLFormat::hasOpenGLOverlays()
1098
1099 Returns true if the window system supports OpenGL overlays;
1100 otherwise returns false.
1101
1102 \warning This function must not be called until the QApplication
1103 object has been created.
1104*/
1105
1106QGLFormat::OpenGLVersionFlags Q_AUTOTEST_EXPORT qOpenGLVersionFlagsFromString(const QString &versionString)
1107{
1108 QGLFormat::OpenGLVersionFlags versionFlags = QGLFormat::OpenGL_Version_None;
1109
1110 if (versionString.startsWith(QLatin1String("OpenGL ES"))) {
1111 QStringList parts = versionString.split(QLatin1Char(' '));
1112 if (parts.size() >= 3) {
1113 if (parts[2].startsWith(QLatin1String("1."))) {
1114 if (parts[1].endsWith(QLatin1String("-CM"))) {
1115 versionFlags |= QGLFormat::OpenGL_ES_Common_Version_1_0 |
1116 QGLFormat::OpenGL_ES_CommonLite_Version_1_0;
1117 if (parts[2].startsWith(QLatin1String("1.1")))
1118 versionFlags |= QGLFormat::OpenGL_ES_Common_Version_1_1 |
1119 QGLFormat::OpenGL_ES_CommonLite_Version_1_1;
1120 }
1121 else {
1122 // Not -CM, must be CL, CommonLite
1123 versionFlags |= QGLFormat::OpenGL_ES_CommonLite_Version_1_0;
1124 if (parts[2].startsWith(QLatin1String("1.1")))
1125 versionFlags |= QGLFormat::OpenGL_ES_CommonLite_Version_1_1;
1126 }
1127 }
1128 else {
1129 // OpenGL ES version 2.0 or higher
1130 versionFlags |= QGLFormat::OpenGL_ES_Version_2_0;
1131 }
1132 }
1133 else {
1134 // if < 3 parts to the name, it is an unrecognised OpenGL ES
1135 qWarning("Unrecognised OpenGL ES version");
1136 }
1137 }
1138 else {
1139 // not ES, regular OpenGL, the version numbers are first in the string
1140 if (versionString.startsWith(QLatin1String("1."))) {
1141 switch (versionString[2].toAscii()) {
1142 case '5':
1143 versionFlags |= QGLFormat::OpenGL_Version_1_5;
1144 case '4':
1145 versionFlags |= QGLFormat::OpenGL_Version_1_4;
1146 case '3':
1147 versionFlags |= QGLFormat::OpenGL_Version_1_3;
1148 case '2':
1149 versionFlags |= QGLFormat::OpenGL_Version_1_2;
1150 case '1':
1151 versionFlags |= QGLFormat::OpenGL_Version_1_1;
1152 default:
1153 break;
1154 }
1155 }
1156 else if (versionString.startsWith(QLatin1String("2."))) {
1157 versionFlags |= QGLFormat::OpenGL_Version_1_1 |
1158 QGLFormat::OpenGL_Version_1_2 |
1159 QGLFormat::OpenGL_Version_1_3 |
1160 QGLFormat::OpenGL_Version_1_4 |
1161 QGLFormat::OpenGL_Version_1_5 |
1162 QGLFormat::OpenGL_Version_2_0;
1163 QString minorVersion = versionString.section(QLatin1Char(' '), 0, 0).section(QLatin1Char('.'), 1, 1);
1164 if (minorVersion == QChar(QLatin1Char('1')))
1165 versionFlags |= QGLFormat::OpenGL_Version_2_1;
1166 }
1167 else if (versionString.startsWith(QLatin1String("3."))) {
1168 versionFlags |= QGLFormat::OpenGL_Version_1_1 |
1169 QGLFormat::OpenGL_Version_1_2 |
1170 QGLFormat::OpenGL_Version_1_3 |
1171 QGLFormat::OpenGL_Version_1_4 |
1172 QGLFormat::OpenGL_Version_1_5 |
1173 QGLFormat::OpenGL_Version_2_0 |
1174 QGLFormat::OpenGL_Version_2_1 |
1175 QGLFormat::OpenGL_Version_3_0;
1176 }
1177 else
1178 qWarning("Unrecognised OpenGL version");
1179 }
1180 return versionFlags;
1181}
1182
1183/*!
1184 \enum QGLFormat::OpenGLVersionFlag
1185 \since 4.2
1186
1187 This enum describes the various OpenGL versions that are
1188 recognized by Qt. Use the QGLFormat::openGLVersionFlags() function
1189 to identify which versions that are supported at runtime.
1190
1191 \value OpenGL_Version_None If no OpenGL is present or if no OpenGL context is current.
1192
1193 \value OpenGL_Version_1_1 OpenGL version 1.1 or higher is present.
1194
1195 \value OpenGL_Version_1_2 OpenGL version 1.2 or higher is present.
1196
1197 \value OpenGL_Version_1_3 OpenGL version 1.3 or higher is present.
1198
1199 \value OpenGL_Version_1_4 OpenGL version 1.4 or higher is present.
1200
1201 \value OpenGL_Version_1_5 OpenGL version 1.5 or higher is present.
1202
1203 \value OpenGL_Version_2_0 OpenGL version 2.0 or higher is present.
1204 Note that version 2.0 supports all the functionality of version 1.5.
1205
1206 \value OpenGL_Version_2_1 OpenGL version 2.1 or higher is present.
1207
1208 \value OpenGL_Version_3_0 OpenGL version 3.0 or higher is present.
1209
1210 \value OpenGL_ES_CommonLite_Version_1_0 OpenGL ES version 1.0 Common Lite or higher is present.
1211
1212 \value OpenGL_ES_Common_Version_1_0 OpenGL ES version 1.0 Common or higher is present.
1213 The Common profile supports all the features of Common Lite.
1214
1215 \value OpenGL_ES_CommonLite_Version_1_1 OpenGL ES version 1.1 Common Lite or higher is present.
1216
1217 \value OpenGL_ES_Common_Version_1_1 OpenGL ES version 1.1 Common or higher is present.
1218 The Common profile supports all the features of Common Lite.
1219
1220 \value OpenGL_ES_Version_2_0 OpenGL ES version 2.0 or higher is present.
1221 Note that OpenGL ES version 2.0 does not support all the features of OpenGL ES 1.x.
1222 So if OpenGL_ES_Version_2_0 is returned, none of the ES 1.x flags are returned.
1223
1224 See also \l{http://www.opengl.org} for more information about the different
1225 revisions of OpenGL.
1226
1227 \sa openGLVersionFlags()
1228*/
1229
1230/*!
1231 \since 4.2
1232
1233 Identifies, at runtime, which OpenGL versions that are supported
1234 by the current platform.
1235
1236 Note that if OpenGL version 1.5 is supported, its predecessors
1237 (i.e., version 1.4 and lower) are also supported. To identify the
1238 support of a particular feature, like multi texturing, test for
1239 the version in which the feature was first introduced (i.e.,
1240 version 1.3 in the case of multi texturing) to adapt to the largest
1241 possible group of runtime platforms.
1242
1243 This function needs a valid current OpenGL context to work;
1244 otherwise it will return OpenGL_Version_None.
1245
1246 \sa hasOpenGL(), hasOpenGLOverlays()
1247*/
1248QGLFormat::OpenGLVersionFlags QGLFormat::openGLVersionFlags()
1249{
1250 static bool cachedDefault = false;
1251 static OpenGLVersionFlags defaultVersionFlags = OpenGL_Version_None;
1252 QGLContext *currentCtx = const_cast<QGLContext *>(QGLContext::currentContext());
1253 QGLWidget *dummy = 0;
1254
1255 if (currentCtx && currentCtx->d_func()->version_flags_cached)
1256 return currentCtx->d_func()->version_flags;
1257
1258 if (!currentCtx) {
1259 if (cachedDefault) {
1260 return defaultVersionFlags;
1261 } else {
1262 if (!hasOpenGL())
1263 return defaultVersionFlags;
1264 dummy = new QGLWidget;
1265 dummy->makeCurrent(); // glGetString() needs a current context
1266 cachedDefault = true;
1267 }
1268 }
1269
1270 QString versionString(QLatin1String(reinterpret_cast<const char*>(glGetString(GL_VERSION))));
1271 OpenGLVersionFlags versionFlags = qOpenGLVersionFlagsFromString(versionString);
1272 if (currentCtx) {
1273 currentCtx->d_func()->version_flags_cached = true;
1274 currentCtx->d_func()->version_flags = versionFlags;
1275 }
1276 if (dummy) {
1277 defaultVersionFlags = versionFlags;
1278 delete dummy;
1279 }
1280
1281 return versionFlags;
1282}
1283
1284
1285/*!
1286 Returns the default QGLFormat for the application. All QGLWidget
1287 objects that are created use this format unless another format is
1288 specified, e.g. when they are constructed.
1289
1290 If no special default format has been set using
1291 setDefaultFormat(), the default format is the same as that created
1292 with QGLFormat().
1293
1294 \sa setDefaultFormat()
1295*/
1296
1297QGLFormat QGLFormat::defaultFormat()
1298{
1299 return *qgl_default_format();
1300}
1301
1302/*!
1303 Sets a new default QGLFormat for the application to \a f. For
1304 example, to set single buffering as the default instead of double
1305 buffering, your main() might contain code like this:
1306 \snippet doc/src/snippets/code/src_opengl_qgl.cpp 4
1307
1308 \sa defaultFormat()
1309*/
1310
1311void QGLFormat::setDefaultFormat(const QGLFormat &f)
1312{
1313 *qgl_default_format() = f;
1314}
1315
1316
1317/*!
1318 Returns the default QGLFormat for overlay contexts.
1319
1320 The default overlay format is:
1321 \list
1322 \i \link setDoubleBuffer() Double buffer:\endlink Disabled.
1323 \i \link setDepth() Depth buffer:\endlink Disabled.
1324 \i \link setRgba() RGBA:\endlink Disabled (i.e., color index enabled).
1325 \i \link setAlpha() Alpha channel:\endlink Disabled.
1326 \i \link setAccum() Accumulator buffer:\endlink Disabled.
1327 \i \link setStencil() Stencil buffer:\endlink Disabled.
1328 \i \link setStereo() Stereo:\endlink Disabled.
1329 \i \link setDirectRendering() Direct rendering:\endlink Enabled.
1330 \i \link setOverlay() Overlay:\endlink Disabled.
1331 \i \link setSampleBuffers() Multisample buffers:\endlink Disabled.
1332 \i \link setPlane() Plane:\endlink 1 (i.e., first overlay plane).
1333 \endlist
1334
1335 \sa setDefaultFormat()
1336*/
1337
1338QGLFormat QGLFormat::defaultOverlayFormat()
1339{
1340 return *defaultOverlayFormatInstance();
1341}
1342
1343/*!
1344 Sets a new default QGLFormat for overlay contexts to \a f. This
1345 format is used whenever a QGLWidget is created with a format that
1346 hasOverlay() enabled.
1347
1348 For example, to get a double buffered overlay context (if
1349 available), use code like this:
1350
1351 \snippet doc/src/snippets/code/src_opengl_qgl.cpp 5
1352
1353 As usual, you can find out after widget creation whether the
1354 underlying OpenGL system was able to provide the requested
1355 specification:
1356
1357 \snippet doc/src/snippets/code/src_opengl_qgl.cpp 6
1358
1359 \sa defaultOverlayFormat()
1360*/
1361
1362void QGLFormat::setDefaultOverlayFormat(const QGLFormat &f)
1363{
1364 QGLFormat *defaultFormat = defaultOverlayFormatInstance();
1365 *defaultFormat = f;
1366 // Make sure the user doesn't request that the overlays themselves
1367 // have overlays, since it is unlikely that the system supports
1368 // infinitely many planes...
1369 defaultFormat->setOverlay(false);
1370}
1371
1372
1373/*!
1374 Returns true if all the options of the two QGLFormat objects
1375 \a a and \a b are equal; otherwise returns false.
1376
1377 \relates QGLFormat
1378*/
1379
1380bool operator==(const QGLFormat& a, const QGLFormat& b)
1381{
1382 return (int) a.d->opts == (int) b.d->opts && a.d->pln == b.d->pln && a.d->alphaSize == b.d->alphaSize
1383 && a.d->accumSize == b.d->accumSize && a.d->stencilSize == b.d->stencilSize
1384 && a.d->depthSize == b.d->depthSize
1385 && a.d->redSize == b.d->redSize
1386 && a.d->greenSize == b.d->greenSize
1387 && a.d->blueSize == b.d->blueSize
1388 && a.d->numSamples == b.d->numSamples
1389 && a.d->swapInterval == b.d->swapInterval;
1390}
1391
1392
1393/*!
1394 Returns false if all the options of the two QGLFormat objects
1395 \a a and \a b are equal; otherwise returns true.
1396
1397 \relates QGLFormat
1398*/
1399
1400bool operator!=(const QGLFormat& a, const QGLFormat& b)
1401{
1402 return !(a == b);
1403}
1404
1405/*****************************************************************************
1406 QGLContext implementation
1407 *****************************************************************************/
1408
1409QGLContextGroup::~QGLContextGroup()
1410{
1411 // Clear any remaining QGLSharedResourceGuard objects on the group.
1412 QGLSharedResourceGuard *guard = m_guards;
1413 while (guard != 0) {
1414 guard->m_group = 0;
1415 guard->m_id = 0;
1416 guard = guard->m_next;
1417 }
1418}
1419
1420void QGLContextGroup::addGuard(QGLSharedResourceGuard *guard)
1421{
1422 if (m_guards)
1423 m_guards->m_prev = guard;
1424 guard->m_next = m_guards;
1425 guard->m_prev = 0;
1426 m_guards = guard;
1427}
1428
1429void QGLContextGroup::removeGuard(QGLSharedResourceGuard *guard)
1430{
1431 if (guard->m_next)
1432 guard->m_next->m_prev = guard->m_prev;
1433 if (guard->m_prev)
1434 guard->m_prev->m_next = guard->m_next;
1435 else
1436 m_guards = guard->m_next;
1437}
1438
1439QGLContextPrivate::~QGLContextPrivate()
1440{
1441 if (!group->m_refs.deref()) {
1442 Q_ASSERT(group->context() == q_ptr);
1443 delete group;
1444 }
1445}
1446
1447void QGLContextPrivate::init(QPaintDevice *dev, const QGLFormat &format)
1448{
1449 Q_Q(QGLContext);
1450 glFormat = reqFormat = format;
1451 valid = false;
1452 q->setDevice(dev);
1453#if defined(Q_WS_X11)
1454 pbuf = 0;
1455 gpm = 0;
1456 vi = 0;
1457 screen = QX11Info::appScreen();
1458#endif
1459#if defined(Q_WS_WIN)
1460 dc = 0;
1461 win = 0;
1462 pixelFormatId = 0;
1463 cmap = 0;
1464 hbitmap = 0;
1465 hbitmap_hdc = 0;
1466#endif
1467#if defined(Q_WS_MAC)
1468# ifndef QT_MAC_USE_COCOA
1469 update = false;
1470# endif
1471 vi = 0;
1472#endif
1473#if defined(QT_OPENGL_ES)
1474 eglContext = 0;
1475 eglSurface = EGL_NO_SURFACE;
1476#endif
1477 fbo = 0;
1478 crWin = false;
1479 initDone = false;
1480 sharing = false;
1481 max_texture_size = -1;
1482 version_flags_cached = false;
1483 version_flags = QGLFormat::OpenGL_Version_None;
1484 current_fbo = 0;
1485 default_fbo = 0;
1486 active_engine = 0;
1487}
1488
1489QGLContext* QGLContext::currentCtx = 0;
1490
1491/*
1492 Read back the contents of the currently bound framebuffer, used in
1493 QGLWidget::grabFrameBuffer(), QGLPixelbuffer::toImage() and
1494 QGLFramebufferObject::toImage()
1495*/
1496
1497static void convertFromGLImage(QImage &img, int w, int h, bool alpha_format, bool include_alpha)
1498{
1499 if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
1500 // OpenGL gives RGBA; Qt wants ARGB
1501 uint *p = (uint*)img.bits();
1502 uint *end = p + w*h;
1503 if (alpha_format && include_alpha) {
1504 while (p < end) {
1505 uint a = *p << 24;
1506 *p = (*p >> 8) | a;
1507 p++;
1508 }
1509 } else {
1510 // This is an old legacy fix for PowerPC based Macs, which
1511 // we shouldn't remove
1512 while (p < end) {
1513 *p = 0xff000000 | (*p>>8);
1514 ++p;
1515 }
1516 }
1517 } else {
1518 // OpenGL gives ABGR (i.e. RGBA backwards); Qt wants ARGB
1519 for (int y = 0; y < h; y++) {
1520 uint *q = (uint*)img.scanLine(y);
1521 for (int x=0; x < w; ++x) {
1522 const uint pixel = *q;
1523 *q = ((pixel << 16) & 0xff0000) | ((pixel >> 16) & 0xff) | (pixel & 0xff00ff00);
1524 q++;
1525 }
1526 }
1527
1528 }
1529 img = img.mirrored();
1530}
1531
1532QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha)
1533{
1534 QImage img(size, alpha_format ? QImage::Format_ARGB32 : QImage::Format_RGB32);
1535 int w = size.width();
1536 int h = size.height();
1537 glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, img.bits());
1538 convertFromGLImage(img, w, h, alpha_format, include_alpha);
1539 return img;
1540}
1541
1542QImage qt_gl_read_texture(const QSize &size, bool alpha_format, bool include_alpha)
1543{
1544 QImage img(size, alpha_format ? QImage::Format_ARGB32 : QImage::Format_RGB32);
1545 int w = size.width();
1546 int h = size.height();
1547#if !defined(QT_OPENGL_ES_2) && !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
1548 //### glGetTexImage not in GL ES 2.0, need to do something else here!
1549 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, img.bits());
1550#endif
1551 convertFromGLImage(img, w, h, alpha_format, include_alpha);
1552 return img;
1553}
1554
1555// returns the highest number closest to v, which is a power of 2
1556// NB! assumes 32 bit ints
1557int qt_next_power_of_two(int v)
1558{
1559 v--;
1560 v |= v >> 1;
1561 v |= v >> 2;
1562 v |= v >> 4;
1563 v |= v >> 8;
1564 v |= v >> 16;
1565 ++v;
1566 return v;
1567}
1568
1569typedef void (*_qt_pixmap_cleanup_hook_64)(qint64);
1570typedef void (*_qt_image_cleanup_hook_64)(qint64);
1571
1572extern Q_GUI_EXPORT _qt_pixmap_cleanup_hook_64 qt_pixmap_cleanup_hook_64;
1573extern Q_GUI_EXPORT _qt_image_cleanup_hook_64 qt_image_cleanup_hook_64;
1574
1575static QGLTextureCache *qt_gl_texture_cache = 0;
1576
1577QGLTextureCache::QGLTextureCache()
1578 : m_cache(64*1024) // cache ~64 MB worth of textures - this is not accurate though
1579{
1580 Q_ASSERT(qt_gl_texture_cache == 0);
1581 qt_gl_texture_cache = this;
1582
1583 QImagePixmapCleanupHooks::instance()->addPixmapModificationHook(cleanupTextures);
1584#ifdef Q_WS_X11
1585 QImagePixmapCleanupHooks::instance()->addPixmapDestructionHook(cleanupPixmapSurfaces);
1586#endif
1587 QImagePixmapCleanupHooks::instance()->addImageHook(imageCleanupHook);
1588}
1589
1590QGLTextureCache::~QGLTextureCache()
1591{
1592 qt_gl_texture_cache = 0;
1593
1594 QImagePixmapCleanupHooks::instance()->removePixmapModificationHook(cleanupTextures);
1595#ifdef Q_WS_X11
1596 QImagePixmapCleanupHooks::instance()->removePixmapDestructionHook(cleanupPixmapSurfaces);
1597#endif
1598 QImagePixmapCleanupHooks::instance()->removeImageHook(imageCleanupHook);
1599}
1600
1601void QGLTextureCache::insert(QGLContext* ctx, qint64 key, QGLTexture* texture, int cost)
1602{
1603 if (m_cache.totalCost() + cost > m_cache.maxCost()) {
1604 // the cache is full - make an attempt to remove something
1605 const QList<qint64> keys = m_cache.keys();
1606 int i = 0;
1607 while (i < m_cache.count()
1608 && (m_cache.totalCost() + cost > m_cache.maxCost())) {
1609 QGLTexture *tex = m_cache.object(keys.at(i));
1610 if (tex->context == ctx)
1611 m_cache.remove(keys.at(i));
1612 ++i;
1613 }
1614 }
1615 m_cache.insert(key, texture, cost);
1616}
1617
1618bool QGLTextureCache::remove(QGLContext* ctx, GLuint textureId)
1619{
1620 QList<qint64> keys = m_cache.keys();
1621 for (int i = 0; i < keys.size(); ++i) {
1622 QGLTexture *tex = m_cache.object(keys.at(i));
1623 if (tex->id == textureId && tex->context == ctx) {
1624 tex->options |= QGLContext::MemoryManagedBindOption; // forces a glDeleteTextures() call
1625 m_cache.remove(keys.at(i));
1626 return true;
1627 }
1628 }
1629 return false;
1630}
1631
1632void QGLTextureCache::removeContextTextures(QGLContext* ctx)
1633{
1634 QList<qint64> keys = m_cache.keys();
1635 for (int i = 0; i < keys.size(); ++i) {
1636 const qint64 &key = keys.at(i);
1637 if (m_cache.object(key)->context == ctx)
1638 m_cache.remove(key);
1639 }
1640}
1641
1642QGLTextureCache* QGLTextureCache::instance()
1643{
1644 if (!qt_gl_texture_cache)
1645 qt_gl_texture_cache = new QGLTextureCache;
1646
1647 return qt_gl_texture_cache;
1648}
1649
1650/*
1651 a hook that removes textures from the cache when a pixmap/image
1652 is deref'ed
1653*/
1654void QGLTextureCache::imageCleanupHook(qint64 cacheKey)
1655{
1656 // ### remove when the GL texture cache becomes thread-safe
1657 if (qApp->thread() != QThread::currentThread())
1658 return;
1659 QGLTexture *texture = instance()->getTexture(cacheKey);
1660 if (texture && texture->options & QGLContext::MemoryManagedBindOption)
1661 instance()->remove(cacheKey);
1662}
1663
1664
1665void QGLTextureCache::cleanupTextures(QPixmap* pixmap)
1666{
1667 // ### remove when the GL texture cache becomes thread-safe
1668 if (qApp->thread() == QThread::currentThread()) {
1669 const qint64 cacheKey = pixmap->cacheKey();
1670 QGLTexture *texture = instance()->getTexture(cacheKey);
1671 if (texture && texture->options & QGLContext::MemoryManagedBindOption)
1672 instance()->remove(cacheKey);
1673 }
1674}
1675
1676#if defined(Q_WS_X11)
1677void QGLTextureCache::cleanupPixmapSurfaces(QPixmap* pixmap)
1678{
1679 // Remove any bound textures first:
1680 cleanupTextures(pixmap);
1681
1682 QPixmapData *pd = pixmap->data_ptr().data();
1683 if (pd->classId() == QPixmapData::X11Class) {
1684 Q_ASSERT(pd->ref == 1); // Make sure reference counting isn't broken
1685 QGLContextPrivate::destroyGlSurfaceForPixmap(pd);
1686 }
1687}
1688#endif
1689
1690void QGLTextureCache::deleteIfEmpty()
1691{
1692 if (instance()->size() == 0)
1693 delete instance();
1694}
1695
1696// DDS format structure
1697struct DDSFormat {
1698 quint32 dwSize;
1699 quint32 dwFlags;
1700 quint32 dwHeight;
1701 quint32 dwWidth;
1702 quint32 dwLinearSize;
1703 quint32 dummy1;
1704 quint32 dwMipMapCount;
1705 quint32 dummy2[11];
1706 struct {
1707 quint32 dummy3[2];
1708 quint32 dwFourCC;
1709 quint32 dummy4[5];
1710 } ddsPixelFormat;
1711};
1712
1713// compressed texture pixel formats
1714#define FOURCC_DXT1 0x31545844
1715#define FOURCC_DXT2 0x32545844
1716#define FOURCC_DXT3 0x33545844
1717#define FOURCC_DXT4 0x34545844
1718#define FOURCC_DXT5 0x35545844
1719
1720#ifndef GL_COMPRESSED_RGB_S3TC_DXT1_EXT
1721#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
1722#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
1723#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2
1724#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3
1725#endif
1726
1727#ifndef GL_GENERATE_MIPMAP_SGIS
1728#define GL_GENERATE_MIPMAP_SGIS 0x8191
1729#define GL_GENERATE_MIPMAP_HINT_SGIS 0x8192
1730#endif
1731
1732Q_GLOBAL_STATIC(QGLShareRegister, _qgl_share_reg)
1733Q_OPENGL_EXPORT QGLShareRegister* qgl_share_reg()
1734{
1735 return _qgl_share_reg();
1736}
1737
1738/*!
1739 \class QGLContext
1740 \brief The QGLContext class encapsulates an OpenGL rendering context.
1741
1742 \ingroup painting-3D
1743
1744 An OpenGL rendering context is a complete set of OpenGL state
1745 variables. The rendering context's \l {QGL::FormatOption} {format}
1746 is set in the constructor, but it can also be set later with
1747 setFormat(). The format options that are actually set are returned
1748 by format(); the options you asked for are returned by
1749 requestedFormat(). Note that after a QGLContext object has been
1750 constructed, the actual OpenGL context must be created by
1751 explicitly calling the \link create() create()\endlink
1752 function. The makeCurrent() function makes this context the
1753 current rendering context. You can make \e no context current
1754 using doneCurrent(). The reset() function will reset the context
1755 and make it invalid.
1756
1757 You can examine properties of the context with, e.g. isValid(),
1758 isSharing(), initialized(), windowCreated() and
1759 overlayTransparentColor().
1760
1761 If you're using double buffering you can swap the screen contents
1762 with the off-screen buffer using swapBuffers().
1763
1764 Please note that QGLContext is not thread safe.
1765*/
1766
1767/*!
1768 \enum QGLContext::BindOption
1769 \since 4.6
1770
1771 A set of options to decide how to bind a texture using bindTexture().
1772
1773 \value NoBindOption Don't do anything, pass the texture straight
1774 through.
1775
1776 \value InvertedYBindOption Specifies that the texture should be flipped
1777 over the X axis so that the texture coordinate 0,0 corresponds to
1778 the top left corner. Inverting the texture implies a deep copy
1779 prior to upload.
1780
1781 \value MipmapBindOption Specifies that bindTexture() should try
1782 to generate mipmaps. If the GL implementation supports the \c
1783 GL_SGIS_generate_mipmap extension, mipmaps will be automatically
1784 generated for the texture. Mipmap generation is only supported for
1785 the \c GL_TEXTURE_2D target.
1786
1787 \value PremultipliedAlphaBindOption Specifies that the image should be
1788 uploaded with premultiplied alpha and does a conversion accordingly.
1789
1790 \value LinearFilteringBindOption Specifies that the texture filtering
1791 should be set to GL_LINEAR. Default is GL_NEAREST. If mipmap is
1792 also enabled, filtering will be set to GL_LINEAR_MIPMAP_LINEAR.
1793
1794 \value DefaultBindOption In Qt 4.5 and earlier, bindTexture()
1795 would mirror the image and automatically generate mipmaps. This
1796 option helps preserve this default behavior.
1797
1798 \omitvalue CanFlipNativePixmapBindOption Used by x11 from pixmap to choose
1799 wether or not it can bind the pixmap upside down or not.
1800
1801 \omitvalue MemoryManagedBindOption Used by paint engines to
1802 indicate that the pixmap should be memory managed along side with
1803 the pixmap/image that it stems from, e.g. installing destruction
1804 hooks in them.
1805
1806 \omitvalue InternalBindOption
1807*/
1808
1809/*!
1810 \obsolete
1811
1812 Constructs an OpenGL context for the given paint \a device, which
1813 can be a widget or a pixmap. The \a format specifies several
1814 display options for the context.
1815
1816 If the underlying OpenGL/Window system cannot satisfy all the
1817 features requested in \a format, the nearest subset of features
1818 will be used. After creation, the format() method will return the
1819 actual format obtained.
1820
1821 Note that after a QGLContext object has been constructed, \l
1822 create() must be called explicitly to create the actual OpenGL
1823 context. The context will be \l {isValid()}{invalid} if it was not
1824 possible to obtain a GL context at all.
1825*/
1826
1827QGLContext::QGLContext(const QGLFormat &format, QPaintDevice *device)
1828 : d_ptr(new QGLContextPrivate(this))
1829{
1830 Q_D(QGLContext);
1831 d->init(device, format);
1832}
1833
1834/*!
1835 Constructs an OpenGL context with the given \a format which
1836 specifies several display options for the context.
1837
1838 If the underlying OpenGL/Window system cannot satisfy all the
1839 features requested in \a format, the nearest subset of features
1840 will be used. After creation, the format() method will return the
1841 actual format obtained.
1842
1843 Note that after a QGLContext object has been constructed, \l
1844 create() must be called explicitly to create the actual OpenGL
1845 context. The context will be \l {isValid()}{invalid} if it was not
1846 possible to obtain a GL context at all.
1847
1848 \sa format(), isValid()
1849*/
1850QGLContext::QGLContext(const QGLFormat &format)
1851 : d_ptr(new QGLContextPrivate(this))
1852{
1853 Q_D(QGLContext);
1854 d->init(0, format);
1855}
1856
1857/*!
1858 Destroys the OpenGL context and frees its resources.
1859*/
1860
1861QGLContext::~QGLContext()
1862{
1863 // remove any textures cached in this context
1864 QGLTextureCache::instance()->removeContextTextures(this);
1865 QGLTextureCache::deleteIfEmpty(); // ### thread safety
1866
1867 d_ptr->group->cleanupResources(this);
1868
1869 QGLSignalProxy::instance()->emitAboutToDestroyContext(this);
1870 reset();
1871}
1872
1873void QGLContextPrivate::cleanup()
1874{
1875}
1876
1877/*!
1878 \overload
1879
1880 Reads the compressed texture file \a fileName and generates a 2D GL
1881 texture from it.
1882
1883 This function can load DirectDrawSurface (DDS) textures in the
1884 DXT1, DXT3 and DXT5 DDS formats if the \c GL_ARB_texture_compression
1885 and \c GL_EXT_texture_compression_s3tc extensions are supported.
1886
1887 Since 4.6.1, textures in the ETC1 format can be loaded if the
1888 \c GL_OES_compressed_ETC1_RGB8_texture extension is supported
1889 and the ETC1 texture has been encapsulated in the PVR container format.
1890 Also, textures in the PVRTC2 and PVRTC4 formats can be loaded
1891 if the \c GL_IMG_texture_compression_pvrtc extension is supported.
1892
1893 \sa deleteTexture()
1894*/
1895
1896GLuint QGLContext::bindTexture(const QString &fileName)
1897{
1898 Q_D(QGLContext);
1899 QGLDDSCache *dds_cache = &(d->group->m_dds_cache);
1900 QGLDDSCache::const_iterator it = dds_cache->constFind(fileName);
1901 if (it != dds_cache->constEnd()) {
1902 glBindTexture(GL_TEXTURE_2D, it.value());
1903 return it.value();
1904 }
1905
1906 QGLTexture texture(this);
1907 QSize size = texture.bindCompressedTexture(fileName);
1908 if (!size.isValid())
1909 return 0;
1910
1911 dds_cache->insert(fileName, texture.id);
1912 return texture.id;
1913}
1914
1915static inline QRgb qt_gl_convertToGLFormatHelper(QRgb src_pixel, GLenum texture_format)
1916{
1917 if (texture_format == GL_BGRA) {
1918 if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
1919 return ((src_pixel << 24) & 0xff000000)
1920 | ((src_pixel >> 24) & 0x000000ff)
1921 | ((src_pixel << 8) & 0x00ff0000)
1922 | ((src_pixel >> 8) & 0x0000ff00);
1923 } else {
1924 return src_pixel;
1925 }
1926 } else { // GL_RGBA
1927 if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
1928 return (src_pixel << 8) | ((src_pixel >> 24) & 0xff);
1929 } else {
1930 return ((src_pixel << 16) & 0xff0000)
1931 | ((src_pixel >> 16) & 0xff)
1932 | (src_pixel & 0xff00ff00);
1933 }
1934 }
1935}
1936
1937QRgb qt_gl_convertToGLFormat(QRgb src_pixel, GLenum texture_format)
1938{
1939 return qt_gl_convertToGLFormatHelper(src_pixel, texture_format);
1940}
1941
1942static void convertToGLFormatHelper(QImage &dst, const QImage &img, GLenum texture_format)
1943{
1944 Q_ASSERT(dst.depth() == 32);
1945 Q_ASSERT(img.depth() == 32);
1946
1947 if (dst.size() != img.size()) {
1948 int target_width = dst.width();
1949 int target_height = dst.height();
1950 qreal sx = target_width / qreal(img.width());
1951 qreal sy = target_height / qreal(img.height());
1952
1953 quint32 *dest = (quint32 *) dst.scanLine(0); // NB! avoid detach here
1954 uchar *srcPixels = (uchar *) img.scanLine(img.height() - 1);
1955 int sbpl = img.bytesPerLine();
1956 int dbpl = dst.bytesPerLine();
1957
1958 int ix = int(0x00010000 / sx);
1959 int iy = int(0x00010000 / sy);
1960
1961 quint32 basex = int(0.5 * ix);
1962 quint32 srcy = int(0.5 * iy);
1963
1964 // scale, swizzle and mirror in one loop
1965 while (target_height--) {
1966 const uint *src = (const quint32 *) (srcPixels - (srcy >> 16) * sbpl);
1967 int srcx = basex;
1968 for (int x=0; x<target_width; ++x) {
1969 dest[x] = qt_gl_convertToGLFormatHelper(src[srcx >> 16], texture_format);
1970 srcx += ix;
1971 }
1972 dest = (quint32 *)(((uchar *) dest) + dbpl);
1973 srcy += iy;
1974 }
1975 } else {
1976 const int width = img.width();
1977 const int height = img.height();
1978 const uint *p = (const uint*) img.scanLine(img.height() - 1);
1979 uint *q = (uint*) dst.scanLine(0);
1980
1981 if (texture_format == GL_BGRA) {
1982 if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
1983 // mirror + swizzle
1984 for (int i=0; i < height; ++i) {
1985 const uint *end = p + width;
1986 while (p < end) {
1987 *q = ((*p << 24) & 0xff000000)
1988 | ((*p >> 24) & 0x000000ff)
1989 | ((*p << 8) & 0x00ff0000)
1990 | ((*p >> 8) & 0x0000ff00);
1991 p++;
1992 q++;
1993 }
1994 p -= 2 * width;
1995 }
1996 } else {
1997 const uint bytesPerLine = img.bytesPerLine();
1998 for (int i=0; i < height; ++i) {
1999 memcpy(q, p, bytesPerLine);
2000 q += width;
2001 p -= width;
2002 }
2003 }
2004 } else {
2005 if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
2006 for (int i=0; i < height; ++i) {
2007 const uint *end = p + width;
2008 while (p < end) {
2009 *q = (*p << 8) | ((*p >> 24) & 0xff);
2010 p++;
2011 q++;
2012 }
2013 p -= 2 * width;
2014 }
2015 } else {
2016 for (int i=0; i < height; ++i) {
2017 const uint *end = p + width;
2018 while (p < end) {
2019 *q = ((*p << 16) & 0xff0000) | ((*p >> 16) & 0xff) | (*p & 0xff00ff00);
2020 p++;
2021 q++;
2022 }
2023 p -= 2 * width;
2024 }
2025 }
2026 }
2027 }
2028}
2029
2030QImage QGLContextPrivate::convertToGLFormat(const QImage &image, bool force_premul,
2031 GLenum texture_format)
2032{
2033 QImage::Format target_format = image.format();
2034 if (force_premul || image.format() != QImage::Format_ARGB32)
2035 target_format = QImage::Format_ARGB32_Premultiplied;
2036
2037 QImage result(image.width(), image.height(), target_format);
2038 convertToGLFormatHelper(result, image.convertToFormat(target_format), texture_format);
2039 return result;
2040}
2041
2042/*! \internal */
2043QGLTexture *QGLContextPrivate::bindTexture(const QImage &image, GLenum target, GLint format,
2044 QGLContext::BindOptions options)
2045{
2046 const qint64 key = image.cacheKey();
2047 QGLTexture *texture = textureCacheLookup(key, target);
2048 if (texture) {
2049 glBindTexture(target, texture->id);
2050 return texture;
2051 }
2052
2053 if (!texture)
2054 texture = bindTexture(image, target, format, key, options);
2055 // NOTE: bindTexture(const QImage&, GLenum, GLint, const qint64, bool) should never return null
2056 Q_ASSERT(texture);
2057
2058 if (texture->id > 0)
2059 QImagePixmapCleanupHooks::enableCleanupHooks(image);
2060
2061 return texture;
2062}
2063
2064// #define QGL_BIND_TEXTURE_DEBUG
2065
2066// map from Qt's ARGB endianness-dependent format to GL's big-endian RGBA layout
2067static inline void qgl_byteSwapImage(QImage &img, GLenum pixel_type)
2068{
2069 const int width = img.width();
2070 const int height = img.height();
2071
2072 if (pixel_type == GL_UNSIGNED_INT_8_8_8_8_REV
2073 || (pixel_type == GL_UNSIGNED_BYTE && QSysInfo::ByteOrder == QSysInfo::LittleEndian))
2074 {
2075 for (int i = 0; i < height; ++i) {
2076 uint *p = (uint *) img.scanLine(i);
2077 for (int x = 0; x < width; ++x)
2078 p[x] = ((p[x] << 16) & 0xff0000) | ((p[x] >> 16) & 0xff) | (p[x] & 0xff00ff00);
2079 }
2080 } else {
2081 for (int i = 0; i < height; ++i) {
2082 uint *p = (uint *) img.scanLine(i);
2083 for (int x = 0; x < width; ++x)
2084 p[x] = (p[x] << 8) | ((p[x] >> 24) & 0xff);
2085 }
2086 }
2087}
2088
2089QGLTexture* QGLContextPrivate::bindTexture(const QImage &image, GLenum target, GLint internalFormat,
2090 const qint64 key, QGLContext::BindOptions options)
2091{
2092 Q_Q(QGLContext);
2093
2094#ifdef QGL_BIND_TEXTURE_DEBUG
2095 printf("QGLContextPrivate::bindTexture(), imageSize=(%d,%d), internalFormat =0x%x, options=%x\n",
2096 image.width(), image.height(), internalFormat, int(options));
2097 QTime time;
2098 time.start();
2099#endif
2100
2101#ifndef QT_NO_DEBUG
2102 // Reset the gl error stack...git
2103 while (glGetError() != GL_NO_ERROR) ;
2104#endif
2105
2106 // Scale the pixmap if needed. GL textures needs to have the
2107 // dimensions 2^n+2(border) x 2^m+2(border), unless we're using GL
2108 // 2.0 or use the GL_TEXTURE_RECTANGLE texture target
2109 int tx_w = qt_next_power_of_two(image.width());
2110 int tx_h = qt_next_power_of_two(image.height());
2111
2112 QImage img = image;
2113 if (!(QGLExtensions::glExtensions & QGLExtensions::NPOTTextures)
2114 && !(QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_ES_Version_2_0)
2115 && (target == GL_TEXTURE_2D && (tx_w != image.width() || tx_h != image.height())))
2116 {
2117 img = img.scaled(tx_w, tx_h);
2118#ifdef QGL_BIND_TEXTURE_DEBUG
2119 printf(" - upscaled to %dx%d (%d ms)\n", tx_w, tx_h, time.elapsed());
2120
2121#endif
2122 }
2123
2124 GLuint filtering = options & QGLContext::LinearFilteringBindOption ? GL_LINEAR : GL_NEAREST;
2125
2126 GLuint tx_id;
2127 glGenTextures(1, &tx_id);
2128 glBindTexture(target, tx_id);
2129 glTexParameterf(target, GL_TEXTURE_MAG_FILTER, filtering);
2130
2131#if defined(QT_OPENGL_ES_2)
2132 bool genMipmap = false;
2133#endif
2134 if (glFormat.directRendering()
2135 && (QGLExtensions::glExtensions & QGLExtensions::GenerateMipmap)
2136 && target == GL_TEXTURE_2D
2137 && (options & QGLContext::MipmapBindOption))
2138 {
2139#ifdef QGL_BIND_TEXTURE_DEBUG
2140 printf(" - generating mipmaps (%d ms)\n", time.elapsed());
2141#endif
2142#if !defined(QT_OPENGL_ES_2)
2143 glHint(GL_GENERATE_MIPMAP_HINT_SGIS, GL_NICEST);
2144#ifndef QT_OPENGL_ES
2145 glTexParameteri(target, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
2146#else
2147 glTexParameterf(target, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
2148#endif
2149#else
2150 glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST);
2151 genMipmap = true;
2152#endif
2153 glTexParameterf(target, GL_TEXTURE_MIN_FILTER, options & QGLContext::LinearFilteringBindOption
2154 ? GL_LINEAR_MIPMAP_LINEAR : GL_NEAREST_MIPMAP_NEAREST);
2155 } else {
2156 glTexParameterf(target, GL_TEXTURE_MIN_FILTER, filtering);
2157 }
2158
2159 QImage::Format target_format = img.format();
2160 bool premul = options & QGLContext::PremultipliedAlphaBindOption;
2161 GLenum externalFormat;
2162 GLuint pixel_type;
2163 if (QGLExtensions::glExtensions & QGLExtensions::BGRATextureFormat) {
2164 externalFormat = GL_BGRA;
2165 pixel_type = GL_UNSIGNED_INT_8_8_8_8_REV;
2166 } else {
2167 externalFormat = GL_RGBA;
2168 pixel_type = GL_UNSIGNED_BYTE;
2169 }
2170
2171 switch (target_format) {
2172 case QImage::Format_ARGB32:
2173 if (premul) {
2174 img = img.convertToFormat(target_format = QImage::Format_ARGB32_Premultiplied);
2175#ifdef QGL_BIND_TEXTURE_DEBUG
2176 printf(" - converting ARGB32 -> ARGB32_Premultiplied (%d ms) \n", time.elapsed());
2177#endif
2178 }
2179 break;
2180 case QImage::Format_ARGB32_Premultiplied:
2181 if (!premul) {
2182 img = img.convertToFormat(target_format = QImage::Format_ARGB32);
2183#ifdef QGL_BIND_TEXTURE_DEBUG
2184 printf(" - converting ARGB32_Premultiplied -> ARGB32 (%d ms)\n", time.elapsed());
2185#endif
2186 }
2187 break;
2188 case QImage::Format_RGB16:
2189 pixel_type = GL_UNSIGNED_SHORT_5_6_5;
2190 externalFormat = GL_RGB;
2191 internalFormat = GL_RGB;
2192 break;
2193 case QImage::Format_RGB32:
2194 break;
2195 default:
2196 if (img.hasAlphaChannel()) {
2197 img = img.convertToFormat(premul
2198 ? QImage::Format_ARGB32_Premultiplied
2199 : QImage::Format_ARGB32);
2200#ifdef QGL_BIND_TEXTURE_DEBUG
2201 printf(" - converting to 32-bit alpha format (%d ms)\n", time.elapsed());
2202#endif
2203 } else {
2204 img = img.convertToFormat(QImage::Format_RGB32);
2205#ifdef QGL_BIND_TEXTURE_DEBUG
2206 printf(" - converting to 32-bit (%d ms)\n", time.elapsed());
2207#endif
2208 }
2209 }
2210
2211 if (options & QGLContext::InvertedYBindOption) {
2212#ifdef QGL_BIND_TEXTURE_DEBUG
2213 printf(" - flipping bits over y (%d ms)\n", time.elapsed());
2214#endif
2215 if (img.isDetached()) {
2216 int ipl = img.bytesPerLine() / 4;
2217 int h = img.height();
2218 for (int y=0; y<h/2; ++y) {
2219 int *a = (int *) img.scanLine(y);
2220 int *b = (int *) img.scanLine(h - y - 1);
2221 for (int x=0; x<ipl; ++x)
2222 qSwap(a[x], b[x]);
2223 }
2224 } else {
2225 // Create a new image and copy across. If we use the
2226 // above in-place code then a full copy of the image is
2227 // made before the lines are swapped, which processes the
2228 // data twice. This version should only do it once.
2229 img = img.mirrored();
2230 }
2231 }
2232
2233 if (externalFormat == GL_RGBA) {
2234#ifdef QGL_BIND_TEXTURE_DEBUG
2235 printf(" - doing byte swapping (%d ms)\n", time.elapsed());
2236#endif
2237 // The only case where we end up with a depth different from
2238 // 32 in the switch above is for the RGB16 case, where we set
2239 // the format to GL_RGB
2240 Q_ASSERT(img.depth() == 32);
2241 qgl_byteSwapImage(img, pixel_type);
2242 }
2243#ifdef QT_OPENGL_ES
2244 // OpenGL/ES requires that the internal and external formats be identical.
2245 // This is typically used to convert GL_RGBA into GL_BGRA.
2246 // Also, we need to use GL_UNSIGNED_BYTE when the format is GL_BGRA.
2247 internalFormat = externalFormat;
2248 if (pixel_type == GL_UNSIGNED_INT_8_8_8_8_REV)
2249 pixel_type = GL_UNSIGNED_BYTE;
2250#endif
2251#ifdef QGL_BIND_TEXTURE_DEBUG
2252 printf(" - uploading, image.format=%d, externalFormat=0x%x, internalFormat=0x%x, pixel_type=0x%x\n",
2253 img.format(), externalFormat, internalFormat, pixel_type);
2254#endif
2255
2256 const QImage &constRef = img; // to avoid detach in bits()...
2257 glTexImage2D(target, 0, internalFormat, img.width(), img.height(), 0, externalFormat,
2258 pixel_type, constRef.bits());
2259#if defined(QT_OPENGL_ES_2)
2260 if (genMipmap)
2261 glGenerateMipmap(target);
2262#endif
2263#ifndef QT_NO_DEBUG
2264 GLenum error = glGetError();
2265 if (error != GL_NO_ERROR) {
2266 qWarning(" - texture upload failed, error code 0x%x\n", error);
2267 }
2268#endif
2269
2270#ifdef QGL_BIND_TEXTURE_DEBUG
2271 static int totalUploadTime = 0;
2272 totalUploadTime += time.elapsed();
2273 printf(" - upload done in (%d ms) time=%d\n", time.elapsed(), totalUploadTime);
2274#endif
2275
2276
2277 // this assumes the size of a texture is always smaller than the max cache size
2278 int cost = img.width()*img.height()*4/1024;
2279 QGLTexture *texture = new QGLTexture(q, tx_id, target, options);
2280 QGLTextureCache::instance()->insert(q, key, texture, cost);
2281 return texture;
2282}
2283
2284QGLTexture *QGLContextPrivate::textureCacheLookup(const qint64 key, GLenum target)
2285{
2286 Q_Q(QGLContext);
2287 QGLTexture *texture = QGLTextureCache::instance()->getTexture(key);
2288 if (texture && texture->target == target
2289 && (texture->context == q || QGLContext::areSharing(q, texture->context)))
2290 {
2291 return texture;
2292 }
2293 return 0;
2294}
2295
2296
2297/*! \internal */
2298QGLTexture *QGLContextPrivate::bindTexture(const QPixmap &pixmap, GLenum target, GLint format, QGLContext::BindOptions options)
2299{
2300 Q_Q(QGLContext);
2301 QPixmapData *pd = pixmap.pixmapData();
2302#if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
2303 if (target == GL_TEXTURE_2D && pd->classId() == QPixmapData::OpenGLClass) {
2304 const QGLPixmapData *data = static_cast<const QGLPixmapData *>(pd);
2305
2306 if (data->isValidContext(q)) {
2307 data->bind();
2308 return data->texture();
2309 }
2310 }
2311#else
2312 Q_UNUSED(pd);
2313 Q_UNUSED(q);
2314#endif
2315
2316 const qint64 key = pixmap.cacheKey();
2317 QGLTexture *texture = textureCacheLookup(key, target);
2318 if (texture) {
2319 glBindTexture(target, texture->id);
2320 return texture;
2321 }
2322
2323#if defined(Q_WS_X11)
2324 // Try to use texture_from_pixmap
2325 if (pd->classId() == QPixmapData::X11Class && pd->pixelType() == QPixmapData::PixmapType) {
2326 texture = bindTextureFromNativePixmap(pd, key, options);
2327 if (texture) {
2328 texture->options |= QGLContext::MemoryManagedBindOption;
2329 texture->boundPixmap = pd;
2330 boundPixmaps.insert(pd, QPixmap(pixmap));
2331 }
2332 }
2333#endif
2334
2335 if (!texture)
2336 texture = bindTexture(pixmap.toImage(), target, format, key, options);
2337 // NOTE: bindTexture(const QImage&, GLenum, GLint, const qint64, bool) should never return null
2338 Q_ASSERT(texture);
2339
2340 if (texture->id > 0)
2341 QImagePixmapCleanupHooks::enableCleanupHooks(pixmap);
2342
2343 return texture;
2344}
2345
2346/*! \internal */
2347int QGLContextPrivate::maxTextureSize()
2348{
2349 if (max_texture_size != -1)
2350 return max_texture_size;
2351
2352 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size);
2353
2354#if defined(QT_OPENGL_ES)
2355 return max_texture_size;
2356#else
2357 GLenum proxy = GL_PROXY_TEXTURE_2D;
2358
2359 GLint size;
2360 GLint next = 64;
2361 glTexImage2D(proxy, 0, GL_RGBA, next, next, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
2362 glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &size);
2363 if (size == 0) {
2364 return max_texture_size;
2365 }
2366 do {
2367 size = next;
2368 next = size * 2;
2369
2370 if (next > max_texture_size)
2371 break;
2372 glTexImage2D(proxy, 0, GL_RGBA, next, next, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
2373 glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &next);
2374 } while (next > size);
2375
2376 max_texture_size = size;
2377 return max_texture_size;
2378#endif
2379}
2380
2381/*!
2382 Generates and binds a 2D GL texture to the current context, based
2383 on \a image. The generated texture id is returned and can be used in
2384 later \c glBindTexture() calls.
2385
2386 \overload
2387*/
2388GLuint QGLContext::bindTexture(const QImage &image, GLenum target, GLint format)
2389{
2390 if (image.isNull())
2391 return 0;
2392
2393 Q_D(QGLContext);
2394 QGLTexture *texture = d->bindTexture(image, target, format, false, DefaultBindOption);
2395 return texture->id;
2396}
2397
2398/*!
2399 \since 4.6
2400
2401 Generates and binds a 2D GL texture to the current context, based
2402 on \a image. The generated texture id is returned and can be used
2403 in later \c glBindTexture() calls.
2404
2405 The \a target parameter specifies the texture target. The default
2406 target is \c GL_TEXTURE_2D.
2407
2408 The \a format parameter sets the internal format for the
2409 texture. The default format is \c GL_RGBA.
2410
2411 The binding \a options are a set of options used to decide how to
2412 bind the texture to the context.
2413
2414 The texture that is generated is cached, so multiple calls to
2415 bindTexture() with the same QImage will return the same texture
2416 id.
2417
2418 Note that we assume default values for the glPixelStore() and
2419 glPixelTransfer() parameters.
2420
2421 \sa deleteTexture()
2422*/
2423GLuint QGLContext::bindTexture(const QImage &image, GLenum target, GLint format, BindOptions options)
2424{
2425 if (image.isNull())
2426 return 0;
2427
2428 Q_D(QGLContext);
2429 QGLTexture *texture = d->bindTexture(image, target, format, false, options);
2430 return texture->id;
2431}
2432
2433#ifdef Q_MAC_COMPAT_GL_FUNCTIONS
2434/*! \internal */
2435GLuint QGLContext::bindTexture(const QImage &image, QMacCompatGLenum target, QMacCompatGLint format)
2436{
2437 if (image.isNull())
2438 return 0;
2439
2440 Q_D(QGLContext);
2441 QGLTexture *texture = d->bindTexture(image, GLenum(target), GLint(format), false, DefaultBindOption);
2442 return texture->id;
2443}
2444
2445/*! \internal */
2446GLuint QGLContext::bindTexture(const QImage &image, QMacCompatGLenum target, QMacCompatGLint format,
2447 BindOptions options)
2448{
2449 if (image.isNull())
2450 return 0;
2451
2452 Q_D(QGLContext);
2453 QGLTexture *texture = d->bindTexture(image, GLenum(target), GLint(format), false, options);
2454 return texture->id;
2455}
2456#endif
2457
2458/*! \overload
2459
2460 Generates and binds a 2D GL texture based on \a pixmap.
2461*/
2462GLuint QGLContext::bindTexture(const QPixmap &pixmap, GLenum target, GLint format)
2463{
2464 if (pixmap.isNull())
2465 return 0;
2466
2467 Q_D(QGLContext);
2468 QGLTexture *texture = d->bindTexture(pixmap, target, format, DefaultBindOption);
2469 return texture->id;
2470}
2471
2472/*!
2473 \overload
2474 \since 4.6
2475
2476 Generates and binds a 2D GL texture to the current context, based
2477 on \a pixmap.
2478*/
2479GLuint QGLContext::bindTexture(const QPixmap &pixmap, GLenum target, GLint format, BindOptions options)
2480{
2481 if (pixmap.isNull())
2482 return 0;
2483
2484 Q_D(QGLContext);
2485 QGLTexture *texture = d->bindTexture(pixmap, target, format, options);
2486 return texture->id;
2487}
2488
2489#ifdef Q_MAC_COMPAT_GL_FUNCTIONS
2490/*! \internal */
2491GLuint QGLContext::bindTexture(const QPixmap &pixmap, QMacCompatGLenum target, QMacCompatGLint format)
2492{
2493 if (pixmap.isNull())
2494 return 0;
2495
2496 Q_D(QGLContext);
2497 QGLTexture *texture = d->bindTexture(pixmap, GLenum(target), GLint(format), DefaultBindOption);
2498 return texture->id;
2499}
2500/*! \internal */
2501GLuint QGLContext::bindTexture(const QPixmap &pixmap, QMacCompatGLenum target, QMacCompatGLint format,
2502 BindOptions options)
2503{
2504 if (pixmap.isNull())
2505 return 0;
2506
2507 Q_D(QGLContext);
2508 QGLTexture *texture = d->bindTexture(pixmap, GLenum(target), GLint(format), options);
2509 return texture->id;
2510}
2511#endif
2512
2513/*!
2514 Removes the texture identified by \a id from the texture cache,
2515 and calls glDeleteTextures() to delete the texture from the
2516 context.
2517
2518 \sa bindTexture()
2519*/
2520void QGLContext::deleteTexture(GLuint id)
2521{
2522 Q_D(QGLContext);
2523
2524 if (QGLTextureCache::instance()->remove(this, id))
2525 return;
2526
2527 // check the DDS cache if the texture wasn't found in the pixmap/image
2528 // cache
2529 QGLDDSCache *dds_cache = &(d->group->m_dds_cache);
2530 QList<QString> ddsKeys = dds_cache->keys();
2531 for (int i = 0; i < ddsKeys.size(); ++i) {
2532 GLuint texture = dds_cache->value(ddsKeys.at(i));
2533 if (id == texture) {
2534 glDeleteTextures(1, &texture);
2535 dds_cache->remove(ddsKeys.at(i));
2536 return;
2537 }
2538 }
2539}
2540
2541#ifdef Q_MAC_COMPAT_GL_FUNCTIONS
2542/*! \internal */
2543void QGLContext::deleteTexture(QMacCompatGLuint id)
2544{
2545 return deleteTexture(GLuint(id));
2546}
2547#endif
2548
2549void qt_add_rect_to_array(const QRectF &r, q_vertexType *array)
2550{
2551 qreal left = r.left();
2552 qreal right = r.right();
2553 qreal top = r.top();
2554 qreal bottom = r.bottom();
2555
2556 array[0] = f2vt(left);
2557 array[1] = f2vt(top);
2558 array[2] = f2vt(right);
2559 array[3] = f2vt(top);
2560 array[4] = f2vt(right);
2561 array[5] = f2vt(bottom);
2562 array[6] = f2vt(left);
2563 array[7] = f2vt(bottom);
2564}
2565
2566void qt_add_texcoords_to_array(qreal x1, qreal y1, qreal x2, qreal y2, q_vertexType *array)
2567{
2568 array[0] = f2vt(x1);
2569 array[1] = f2vt(y1);
2570 array[2] = f2vt(x2);
2571 array[3] = f2vt(y1);
2572 array[4] = f2vt(x2);
2573 array[5] = f2vt(y2);
2574 array[6] = f2vt(x1);
2575 array[7] = f2vt(y2);
2576}
2577
2578#if !defined(QT_OPENGL_ES_2)
2579
2580static void qDrawTextureRect(const QRectF &target, GLint textureWidth, GLint textureHeight, GLenum textureTarget)
2581{
2582 q_vertexType tx = f2vt(1);
2583 q_vertexType ty = f2vt(1);
2584
2585#ifdef QT_OPENGL_ES
2586 Q_UNUSED(textureWidth);
2587 Q_UNUSED(textureHeight);
2588 Q_UNUSED(textureTarget);
2589#else
2590 if (textureTarget != GL_TEXTURE_2D) {
2591 if (textureWidth == -1 || textureHeight == -1) {
2592 glGetTexLevelParameteriv(textureTarget, 0, GL_TEXTURE_WIDTH, &textureWidth);
2593 glGetTexLevelParameteriv(textureTarget, 0, GL_TEXTURE_HEIGHT, &textureHeight);
2594 }
2595
2596 tx = f2vt(textureWidth);
2597 ty = f2vt(textureHeight);
2598 }
2599#endif
2600
2601 q_vertexType texCoordArray[4*2] = {
2602 0, ty, tx, ty, tx, 0, 0, 0
2603 };
2604
2605 q_vertexType vertexArray[4*2];
2606 qt_add_rect_to_array(target, vertexArray);
2607
2608 glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray);
2609 glTexCoordPointer(2, q_vertexTypeEnum, 0, texCoordArray);
2610
2611 glEnableClientState(GL_VERTEX_ARRAY);
2612 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
2613 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
2614
2615 glDisableClientState(GL_VERTEX_ARRAY);
2616 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
2617}
2618
2619#endif // !QT_OPENGL_ES_2
2620
2621/*!
2622 \since 4.4
2623
2624 Draws the given texture, \a textureId, to the given target rectangle,
2625 \a target, in OpenGL model space. The \a textureTarget should be a 2D
2626 texture target.
2627
2628 \note This function is not supported under OpenGL/ES 2.0.
2629*/
2630void QGLContext::drawTexture(const QRectF &target, GLuint textureId, GLenum textureTarget)
2631{
2632#ifndef QT_OPENGL_ES_2
2633#ifdef QT_OPENGL_ES
2634 if (textureTarget != GL_TEXTURE_2D) {
2635 qWarning("QGLContext::drawTexture(): texture target must be GL_TEXTURE_2D on OpenGL ES");
2636 return;
2637 }
2638#else
2639 const bool wasEnabled = glIsEnabled(GL_TEXTURE_2D);
2640 GLint oldTexture;
2641 glGetIntegerv(GL_TEXTURE_BINDING_2D, &oldTexture);
2642#endif
2643
2644 glEnable(textureTarget);
2645 glBindTexture(textureTarget, textureId);
2646
2647 qDrawTextureRect(target, -1, -1, textureTarget);
2648
2649#ifdef QT_OPENGL_ES
2650 glDisable(textureTarget);
2651#else
2652 if (!wasEnabled)
2653 glDisable(textureTarget);
2654 glBindTexture(textureTarget, oldTexture);
2655#endif
2656#else
2657 Q_UNUSED(target);
2658 Q_UNUSED(textureId);
2659 Q_UNUSED(textureTarget);
2660 qWarning("drawTexture(const QRectF &target, GLuint textureId, GLenum textureTarget) not supported with OpenGL ES/2.0");
2661#endif
2662}
2663
2664#ifdef Q_MAC_COMPAT_GL_FUNCTIONS
2665/*! \internal */
2666void QGLContext::drawTexture(const QRectF &target, QMacCompatGLuint textureId, QMacCompatGLenum textureTarget)
2667{
2668 drawTexture(target, GLuint(textureId), GLenum(textureTarget));
2669}
2670#endif
2671
2672/*!
2673 \since 4.4
2674
2675 Draws the given texture at the given \a point in OpenGL model
2676 space. The \a textureTarget should be a 2D texture target.
2677
2678 \note This function is not supported under OpenGL/ES.
2679*/
2680void QGLContext::drawTexture(const QPointF &point, GLuint textureId, GLenum textureTarget)
2681{
2682 // this would be ok on OpenGL ES 2.0, but currently we don't have a define for that
2683#ifdef QT_OPENGL_ES
2684 Q_UNUSED(point);
2685 Q_UNUSED(textureId);
2686 Q_UNUSED(textureTarget);
2687 qWarning("drawTexture(const QPointF &point, GLuint textureId, GLenum textureTarget) not supported with OpenGL ES, use rect version instead");
2688#else
2689 const bool wasEnabled = glIsEnabled(GL_TEXTURE_2D);
2690 GLint oldTexture;
2691 glGetIntegerv(GL_TEXTURE_BINDING_2D, &oldTexture);
2692
2693 glEnable(textureTarget);
2694 glBindTexture(textureTarget, textureId);
2695
2696 GLint textureWidth;
2697 GLint textureHeight;
2698
2699 glGetTexLevelParameteriv(textureTarget, 0, GL_TEXTURE_WIDTH, &textureWidth);
2700 glGetTexLevelParameteriv(textureTarget, 0, GL_TEXTURE_HEIGHT, &textureHeight);
2701
2702 qDrawTextureRect(QRectF(point, QSizeF(textureWidth, textureHeight)), textureWidth, textureHeight, textureTarget);
2703
2704 if (!wasEnabled)
2705 glDisable(textureTarget);
2706 glBindTexture(textureTarget, oldTexture);
2707#endif
2708}
2709
2710#ifdef Q_MAC_COMPAT_GL_FUNCTIONS
2711/*! \internal */
2712void QGLContext::drawTexture(const QPointF &point, QMacCompatGLuint textureId, QMacCompatGLenum textureTarget)
2713{
2714 drawTexture(point, GLuint(textureId), GLenum(textureTarget));
2715}
2716#endif
2717
2718
2719/*!
2720 This function sets the limit for the texture cache to \a size,
2721 expressed in kilobytes.
2722
2723 By default, the cache limit is approximately 64 MB.
2724
2725 \sa textureCacheLimit()
2726*/
2727void QGLContext::setTextureCacheLimit(int size)
2728{
2729 QGLTextureCache::instance()->setMaxCost(size);
2730}
2731
2732/*!
2733 Returns the current texture cache limit in kilobytes.
2734
2735 \sa setTextureCacheLimit()
2736*/
2737int QGLContext::textureCacheLimit()
2738{
2739 return QGLTextureCache::instance()->maxCost();
2740}
2741
2742
2743/*!
2744 \fn QGLFormat QGLContext::format() const
2745
2746 Returns the frame buffer format that was obtained (this may be a
2747 subset of what was requested).
2748
2749 \sa requestedFormat()
2750*/
2751
2752/*!
2753 \fn QGLFormat QGLContext::requestedFormat() const
2754
2755 Returns the frame buffer format that was originally requested in
2756 the constructor or setFormat().
2757
2758 \sa format()
2759*/
2760
2761/*!
2762 Sets a \a format for this context. The context is \link reset()
2763 reset\endlink.
2764
2765 Call create() to create a new GL context that tries to match the
2766 new format.
2767
2768 \snippet doc/src/snippets/code/src_opengl_qgl.cpp 7
2769
2770 \sa format(), reset(), create()
2771*/
2772
2773void QGLContext::setFormat(const QGLFormat &format)
2774{
2775 Q_D(QGLContext);
2776 reset();
2777 d->glFormat = d->reqFormat = format;
2778}
2779
2780/*!
2781 \internal
2782*/
2783void QGLContext::setDevice(QPaintDevice *pDev)
2784{
2785 Q_D(QGLContext);
2786 if (isValid())
2787 reset();
2788 d->paintDevice = pDev;
2789 if (d->paintDevice && (d->paintDevice->devType() != QInternal::Widget
2790 && d->paintDevice->devType() != QInternal::Pixmap
2791 && d->paintDevice->devType() != QInternal::Pbuffer)) {
2792 qWarning("QGLContext: Unsupported paint device type");
2793 }
2794}
2795
2796/*!
2797 \fn bool QGLContext::isValid() const
2798
2799 Returns true if a GL rendering context has been successfully
2800 created; otherwise returns false.
2801*/
2802
2803/*!
2804 \fn void QGLContext::setValid(bool valid)
2805 \internal
2806
2807 Forces the GL rendering context to be valid.
2808*/
2809
2810/*!
2811 \fn bool QGLContext::isSharing() const
2812
2813 Returns true if this context is sharing its GL context with
2814 another QGLContext, otherwise false is returned. Note that context
2815 sharing might not be supported between contexts with different
2816 formats.
2817*/
2818
2819/*!
2820 Returns true if \a context1 and \a context2 are sharing their
2821 GL resources such as textures, shader programs, etc;
2822 otherwise returns false.
2823
2824 \since 4.6
2825*/
2826bool QGLContext::areSharing(const QGLContext *context1, const QGLContext *context2)
2827{
2828 if (!context1 || !context2)
2829 return false;
2830 return context1->d_ptr->group == context2->d_ptr->group;
2831}
2832
2833/*!
2834 \fn bool QGLContext::deviceIsPixmap() const
2835
2836 Returns true if the paint device of this context is a pixmap;
2837 otherwise returns false.
2838*/
2839
2840/*!
2841 \fn bool QGLContext::windowCreated() const
2842
2843 Returns true if a window has been created for this context;
2844 otherwise returns false.
2845
2846 \sa setWindowCreated()
2847*/
2848
2849/*!
2850 \fn void QGLContext::setWindowCreated(bool on)
2851
2852 If \a on is true the context has had a window created for it. If
2853 \a on is false no window has been created for the context.
2854
2855 \sa windowCreated()
2856*/
2857
2858/*!
2859 \fn uint QGLContext::colorIndex(const QColor& c) const
2860
2861 \internal
2862
2863 Returns a colormap index for the color c, in ColorIndex mode. Used
2864 by qglColor() and qglClearColor().
2865*/
2866
2867
2868/*!
2869 \fn bool QGLContext::initialized() const
2870
2871 Returns true if this context has been initialized, i.e. if
2872 QGLWidget::initializeGL() has been performed on it; otherwise
2873 returns false.
2874
2875 \sa setInitialized()
2876*/
2877
2878/*!
2879 \fn void QGLContext::setInitialized(bool on)
2880
2881 If \a on is true the context has been initialized, i.e.
2882 QGLContext::setInitialized() has been called on it. If \a on is
2883 false the context has not been initialized.
2884
2885 \sa initialized()
2886*/
2887
2888/*!
2889 \fn const QGLContext* QGLContext::currentContext()
2890
2891 Returns the current context, i.e. the context to which any OpenGL
2892 commands will currently be directed. Returns 0 if no context is
2893 current.
2894
2895 \sa makeCurrent()
2896*/
2897
2898/*!
2899 \fn QColor QGLContext::overlayTransparentColor() const
2900
2901 If this context is a valid context in an overlay plane, returns
2902 the plane's transparent color. Otherwise returns an \link
2903 QColor::isValid() invalid \endlink color.
2904
2905 The returned color's \link QColor::pixel() pixel \endlink value is
2906 the index of the transparent color in the colormap of the overlay
2907 plane. (Naturally, the color's RGB values are meaningless.)
2908
2909 The returned QColor object will generally work as expected only
2910 when passed as the argument to QGLWidget::qglColor() or
2911 QGLWidget::qglClearColor(). Under certain circumstances it can
2912 also be used to draw transparent graphics with a QPainter. See the
2913 examples/opengl/overlay_x11 example for details.
2914*/
2915
2916
2917/*!
2918 Creates the GL context. Returns true if it was successful in
2919 creating a valid GL rendering context on the paint device
2920 specified in the constructor; otherwise returns false (i.e. the
2921 context is invalid).
2922
2923 After successful creation, format() returns the set of features of
2924 the created GL rendering context.
2925
2926 If \a shareContext points to a valid QGLContext, this method will
2927 try to establish OpenGL display list and texture object sharing
2928 between this context and the \a shareContext. Note that this may
2929 fail if the two contexts have different \l {format()} {formats}.
2930 Use isSharing() to see if sharing is in effect.
2931
2932 \warning Implementation note: initialization of C++ class
2933 members usually takes place in the class constructor. QGLContext
2934 is an exception because it must be simple to customize. The
2935 virtual functions chooseContext() (and chooseVisual() for X11) can
2936 be reimplemented in a subclass to select a particular context. The
2937 problem is that virtual functions are not properly called during
2938 construction (even though this is correct C++) because C++
2939 constructs class hierarchies from the bottom up. For this reason
2940 we need a create() function.
2941
2942 \sa chooseContext(), format(), isValid()
2943*/
2944
2945bool QGLContext::create(const QGLContext* shareContext)
2946{
2947 Q_D(QGLContext);
2948 if (!d->paintDevice)
2949 return false;
2950 reset();
2951 d->valid = chooseContext(shareContext);
2952 if (d->valid && d->paintDevice->devType() == QInternal::Widget) {
2953 QWidgetPrivate *wd = qt_widget_private(static_cast<QWidget *>(d->paintDevice));
2954 wd->usesDoubleBufferedGLContext = d->glFormat.doubleBuffer();
2955 }
2956 if (d->sharing) // ok, we managed to share
2957 qgl_share_reg()->addShare(this, shareContext);
2958 return d->valid;
2959}
2960
2961bool QGLContext::isValid() const
2962{
2963 Q_D(const QGLContext);
2964 return d->valid;
2965}
2966
2967void QGLContext::setValid(bool valid)
2968{
2969 Q_D(QGLContext);
2970 d->valid = valid;
2971}
2972
2973bool QGLContext::isSharing() const
2974{
2975 Q_D(const QGLContext);
2976 return d->group->isSharing();
2977}
2978
2979QGLFormat QGLContext::format() const
2980{
2981 Q_D(const QGLContext);
2982 return d->glFormat;
2983}
2984
2985QGLFormat QGLContext::requestedFormat() const
2986{
2987 Q_D(const QGLContext);
2988 return d->reqFormat;
2989}
2990
2991 QPaintDevice* QGLContext::device() const
2992{
2993 Q_D(const QGLContext);
2994 return d->paintDevice;
2995}
2996
2997bool QGLContext::deviceIsPixmap() const
2998{
2999 Q_D(const QGLContext);
3000 return d->paintDevice->devType() == QInternal::Pixmap;
3001}
3002
3003
3004bool QGLContext::windowCreated() const
3005{
3006 Q_D(const QGLContext);
3007 return d->crWin;
3008}
3009
3010
3011void QGLContext::setWindowCreated(bool on)
3012{
3013 Q_D(QGLContext);
3014 d->crWin = on;
3015}
3016
3017bool QGLContext::initialized() const
3018{
3019 Q_D(const QGLContext);
3020 return d->initDone;
3021}
3022
3023void QGLContext::setInitialized(bool on)
3024{
3025 Q_D(QGLContext);
3026 d->initDone = on;
3027}
3028
3029const QGLContext* QGLContext::currentContext()
3030{
3031 QGLThreadContext *threadContext = qgl_context_storage.localData();
3032 if (threadContext)
3033 return threadContext->context;
3034 return 0;
3035}
3036
3037void QGLContextPrivate::setCurrentContext(QGLContext *context)
3038{
3039 QGLThreadContext *threadContext = qgl_context_storage.localData();
3040 if (!threadContext) {
3041 if (!QThread::currentThread()) {
3042 // We don't have a current QThread, so just set the static.
3043 QGLContext::currentCtx = context;
3044 return;
3045 }
3046 threadContext = new QGLThreadContext;
3047 qgl_context_storage.setLocalData(threadContext);
3048 }
3049 threadContext->context = context;
3050 QGLContext::currentCtx = context; // XXX: backwards-compat, not thread-safe
3051}
3052
3053/*!
3054 \fn bool QGLContext::chooseContext(const QGLContext* shareContext = 0)
3055
3056 This semi-internal function is called by create(). It creates a
3057 system-dependent OpenGL handle that matches the format() of \a
3058 shareContext as closely as possible, returning true if successful
3059 or false if a suitable handle could not be found.
3060
3061 On Windows, it calls the virtual function choosePixelFormat(),
3062 which finds a matching pixel format identifier. On X11, it calls
3063 the virtual function chooseVisual() which finds an appropriate X
3064 visual. On other platforms it may work differently.
3065*/
3066
3067/*! \fn int QGLContext::choosePixelFormat(void* dummyPfd, HDC pdc)
3068
3069 \bold{Win32 only:} This virtual function chooses a pixel format
3070 that matches the OpenGL \link setFormat() format\endlink.
3071 Reimplement this function in a subclass if you need a custom
3072 context.
3073
3074 \warning The \a dummyPfd pointer and \a pdc are used as a \c
3075 PIXELFORMATDESCRIPTOR*. We use \c void to avoid using
3076 Windows-specific types in our header files.
3077
3078 \sa chooseContext()
3079*/
3080
3081/*! \fn void *QGLContext::chooseVisual()
3082
3083 \bold{X11 only:} This virtual function tries to find a visual that
3084 matches the format, reducing the demands if the original request
3085 cannot be met.
3086
3087 The algorithm for reducing the demands of the format is quite
3088 simple-minded, so override this method in your subclass if your
3089 application has spcific requirements on visual selection.
3090
3091 \sa chooseContext()
3092*/
3093
3094/*! \fn void *QGLContext::tryVisual(const QGLFormat& f, int bufDepth)
3095 \internal
3096
3097 \bold{X11 only:} This virtual function chooses a visual that matches
3098 the OpenGL \link format() format\endlink. Reimplement this function
3099 in a subclass if you need a custom visual.
3100
3101 \sa chooseContext()
3102*/
3103
3104/*!
3105 \fn void QGLContext::reset()
3106
3107 Resets the context and makes it invalid.
3108
3109 \sa create(), isValid()
3110*/
3111
3112
3113/*!
3114 \fn void QGLContext::makeCurrent()
3115
3116 Makes this context the current OpenGL rendering context. All GL
3117 functions you call operate on this context until another context
3118 is made current.
3119
3120 In some very rare cases the underlying call may fail. If this
3121 occurs an error message is output to stderr.
3122*/
3123
3124
3125/*!
3126 \fn void QGLContext::swapBuffers() const
3127
3128 Swaps the screen contents with an off-screen buffer. Only works if
3129 the context is in double buffer mode.
3130
3131 \sa QGLFormat::setDoubleBuffer()
3132*/
3133
3134
3135/*!
3136 \fn void QGLContext::doneCurrent()
3137
3138 Makes no GL context the current context. Normally, you do not need
3139 to call this function; QGLContext calls it as necessary.
3140*/
3141
3142
3143/*!
3144 \fn QPaintDevice* QGLContext::device() const
3145
3146 Returns the paint device set for this context.
3147
3148 \sa QGLContext::QGLContext()
3149*/
3150
3151/*!
3152 \obsolete
3153 \fn void QGLContext::generateFontDisplayLists(const QFont& font, int listBase)
3154
3155 Generates a set of 256 display lists for the 256 first characters
3156 in the font \a font. The first list will start at index \a listBase.
3157
3158 \sa QGLWidget::renderText()
3159*/
3160
3161
3162/*****************************************************************************
3163 QGLWidget implementation
3164 *****************************************************************************/
3165
3166
3167/*!
3168 \class QGLWidget
3169 \brief The QGLWidget class is a widget for rendering OpenGL graphics.
3170
3171 \ingroup painting-3D
3172
3173
3174 QGLWidget provides functionality for displaying OpenGL graphics
3175 integrated into a Qt application. It is very simple to use. You
3176 inherit from it and use the subclass like any other QWidget,
3177 except that you have the choice between using QPainter and
3178 standard OpenGL rendering commands.
3179
3180 QGLWidget provides three convenient virtual functions that you can
3181 reimplement in your subclass to perform the typical OpenGL tasks:
3182
3183 \list
3184 \i paintGL() - Renders the OpenGL scene. Gets called whenever the widget
3185 needs to be updated.
3186 \i resizeGL() - Sets up the OpenGL viewport, projection, etc. Gets
3187 called whenever the widget has been resized (and also when it
3188 is shown for the first time because all newly created widgets get a
3189 resize event automatically).
3190 \i initializeGL() - Sets up the OpenGL rendering context, defines display
3191 lists, etc. Gets called once before the first time resizeGL() or
3192 paintGL() is called.
3193 \endlist
3194
3195 Here is a rough outline of how a QGLWidget subclass might look:
3196
3197 \snippet doc/src/snippets/code/src_opengl_qgl.cpp 8
3198
3199 If you need to trigger a repaint from places other than paintGL()
3200 (a typical example is when using \link QTimer timers\endlink to
3201 animate scenes), you should call the widget's updateGL() function.
3202
3203 Your widget's OpenGL rendering context is made current when
3204 paintGL(), resizeGL(), or initializeGL() is called. If you need to
3205 call the standard OpenGL API functions from other places (e.g. in
3206 your widget's constructor or in your own paint functions), you
3207 must call makeCurrent() first.
3208
3209 QGLWidget provides functions for requesting a new display \link
3210 QGLFormat format\endlink and you can also create widgets with
3211 customized rendering \link QGLContext contexts\endlink.
3212
3213 You can also share OpenGL display lists between QGLWidget objects (see
3214 the documentation of the QGLWidget constructors for details).
3215
3216 Note that under Windows, the QGLContext belonging to a QGLWidget
3217 has to be recreated when the QGLWidget is reparented. This is
3218 necessary due to limitations on the Windows platform. This will
3219 most likely cause problems for users that have subclassed and
3220 installed their own QGLContext on a QGLWidget. It is possible to
3221 work around this issue by putting the QGLWidget inside a dummy
3222 widget and then reparenting the dummy widget, instead of the
3223 QGLWidget. This will side-step the issue altogether, and is what
3224 we recommend for users that need this kind of functionality.
3225
3226 On Mac OS X, when Qt is built with Cocoa support, a QGLWidget
3227 can't have any sibling widgets placed ontop of itself. This is due
3228 to limitations in the Cocoa API and is not supported by Apple.
3229
3230 \section1 Overlays
3231
3232 The QGLWidget creates a GL overlay context in addition to the
3233 normal context if overlays are supported by the underlying system.
3234
3235 If you want to use overlays, you specify it in the \link QGLFormat
3236 format\endlink. (Note: Overlay must be requested in the format
3237 passed to the QGLWidget constructor.) Your GL widget should also
3238 implement some or all of these virtual methods:
3239
3240 \list
3241 \i paintOverlayGL()
3242 \i resizeOverlayGL()
3243 \i initializeOverlayGL()
3244 \endlist
3245
3246 These methods work in the same way as the normal paintGL() etc.
3247 functions, except that they will be called when the overlay
3248 context is made current. You can explicitly make the overlay
3249 context current by using makeOverlayCurrent(), and you can access
3250 the overlay context directly (e.g. to ask for its transparent
3251 color) by calling overlayContext().
3252
3253 On X servers in which the default visual is in an overlay plane,
3254 non-GL Qt windows can also be used for overlays.
3255
3256 \section1 Painting Techniques
3257
3258 As described above, subclass QGLWidget to render pure 3D content in the
3259 following way:
3260
3261 \list
3262 \o Reimplement the QGLWidget::initializeGL() and QGLWidget::resizeGL() to
3263 set up the OpenGL state and provide a perspective transformation.
3264 \o Reimplement QGLWidget::paintGL() to paint the 3D scene, calling only
3265 OpenGL functions to draw on the widget.
3266 \endlist
3267
3268 It is also possible to draw 2D graphics onto a QGLWidget subclass, it is necessary
3269 to reimplement QGLWidget::paintEvent() and do the following:
3270
3271 \list
3272 \o Construct a QPainter object.
3273 \o Initialize it for use on the widget with the QPainter::begin() function.
3274 \o Draw primitives using QPainter's member functions.
3275 \o Call QPainter::end() to finish painting.
3276 \endlist
3277
3278 Overpainting 2D content on top of 3D content takes a little more effort.
3279 One approach to doing this is shown in the
3280 \l{Overpainting Example}{Overpainting} example.
3281
3282 \e{OpenGL is a trademark of Silicon Graphics, Inc. in the United States and other
3283 countries.}
3284
3285 \sa QGLPixelBuffer, {Hello GL Example}, {2D Painting Example}, {Overpainting Example},
3286 {Grabber Example}
3287*/
3288
3289/*!
3290 Constructs an OpenGL widget with a \a parent widget.
3291
3292 The \link QGLFormat::defaultFormat() default format\endlink is
3293 used. The widget will be \link isValid() invalid\endlink if the
3294 system has no \link QGLFormat::hasOpenGL() OpenGL support\endlink.
3295
3296 The \a parent and widget flag, \a f, arguments are passed
3297 to the QWidget constructor.
3298
3299 If \a shareWidget is a valid QGLWidget, this widget will share
3300 OpenGL display lists and texture objects with \a shareWidget. But
3301 if \a shareWidget and this widget have different \l {format()}
3302 {formats}, sharing might not be possible. You can check whether
3303 sharing is in effect by calling isSharing().
3304
3305 The initialization of OpenGL rendering state, etc. should be done
3306 by overriding the initializeGL() function, rather than in the
3307 constructor of your QGLWidget subclass.
3308
3309 \sa QGLFormat::defaultFormat(), {Textures Example}
3310*/
3311
3312QGLWidget::QGLWidget(QWidget *parent, const QGLWidget* shareWidget, Qt::WindowFlags f)
3313 : QWidget(*(new QGLWidgetPrivate), parent, f | Qt::MSWindowsOwnDC)
3314{
3315 Q_D(QGLWidget);
3316 setAttribute(Qt::WA_PaintOnScreen);
3317 setAttribute(Qt::WA_NoSystemBackground);
3318 setAutoFillBackground(true); // for compatibility
3319 d->init(new QGLContext(QGLFormat::defaultFormat(), this), shareWidget);
3320}
3321
3322
3323/*!
3324 Constructs an OpenGL widget with parent \a parent.
3325
3326 The \a format argument specifies the desired \link QGLFormat
3327 rendering options \endlink. If the underlying OpenGL/Window system
3328 cannot satisfy all the features requested in \a format, the
3329 nearest subset of features will be used. After creation, the
3330 format() method will return the actual format obtained.
3331
3332 The widget will be \link isValid() invalid\endlink if the system
3333 has no \link QGLFormat::hasOpenGL() OpenGL support\endlink.
3334
3335 The \a parent and widget flag, \a f, arguments are passed
3336 to the QWidget constructor.
3337
3338 If \a shareWidget is a valid QGLWidget, this widget will share
3339 OpenGL display lists and texture objects with \a shareWidget. But
3340 if \a shareWidget and this widget have different \l {format()}
3341 {formats}, sharing might not be possible. You can check whether
3342 sharing is in effect by calling isSharing().
3343
3344 The initialization of OpenGL rendering state, etc. should be done
3345 by overriding the initializeGL() function, rather than in the
3346 constructor of your QGLWidget subclass.
3347
3348 \sa QGLFormat::defaultFormat(), isValid()
3349*/
3350
3351QGLWidget::QGLWidget(const QGLFormat &format, QWidget *parent, const QGLWidget* shareWidget,
3352 Qt::WindowFlags f)
3353 : QWidget(*(new QGLWidgetPrivate), parent, f | Qt::MSWindowsOwnDC)
3354{
3355 Q_D(QGLWidget);
3356 setAttribute(Qt::WA_PaintOnScreen);
3357 setAttribute(Qt::WA_NoSystemBackground);
3358 setAutoFillBackground(true); // for compatibility
3359 d->init(new QGLContext(format, this), shareWidget);
3360}
3361
3362/*!
3363 Constructs an OpenGL widget with parent \a parent.
3364
3365 The \a context argument is a pointer to the QGLContext that
3366 you wish to be bound to this widget. This allows you to pass in
3367 your own QGLContext sub-classes.
3368
3369 The widget will be \link isValid() invalid\endlink if the system
3370 has no \link QGLFormat::hasOpenGL() OpenGL support\endlink.
3371
3372 The \a parent and widget flag, \a f, arguments are passed
3373 to the QWidget constructor.
3374
3375 If \a shareWidget is a valid QGLWidget, this widget will share
3376 OpenGL display lists and texture objects with \a shareWidget. But
3377 if \a shareWidget and this widget have different \l {format()}
3378 {formats}, sharing might not be possible. You can check whether
3379 sharing is in effect by calling isSharing().
3380
3381 The initialization of OpenGL rendering state, etc. should be done
3382 by overriding the initializeGL() function, rather than in the
3383 constructor of your QGLWidget subclass.
3384
3385 \sa QGLFormat::defaultFormat(), isValid()
3386*/
3387QGLWidget::QGLWidget(QGLContext *context, QWidget *parent, const QGLWidget *shareWidget,
3388 Qt::WindowFlags f)
3389 : QWidget(*(new QGLWidgetPrivate), parent, f | Qt::MSWindowsOwnDC)
3390{
3391 Q_D(QGLWidget);
3392 setAttribute(Qt::WA_PaintOnScreen);
3393 setAttribute(Qt::WA_NoSystemBackground);
3394 setAutoFillBackground(true); // for compatibility
3395 d->init(context, shareWidget);
3396}
3397
3398/*!
3399 Destroys the widget.
3400*/
3401
3402QGLWidget::~QGLWidget()
3403{
3404 Q_D(QGLWidget);
3405#if defined(GLX_MESA_release_buffers) && defined(QGL_USE_MESA_EXT)
3406 bool doRelease = (glcx && glcx->windowCreated());
3407#endif
3408 delete d->glcx;
3409#if defined(Q_WGL)
3410 delete d->olcx;
3411#endif
3412#if defined(GLX_MESA_release_buffers) && defined(QGL_USE_MESA_EXT)
3413 if (doRelease)
3414 glXReleaseBuffersMESA(x11Display(), winId());
3415#endif
3416 d->cleanupColormaps();
3417
3418#ifdef Q_WS_MAC
3419 QWidget *current = parentWidget();
3420 while (current) {
3421 qt_widget_private(current)->glWidgets.removeAll(QWidgetPrivate::GlWidgetInfo(this));
3422 if (current->isWindow())
3423 break;
3424 current = current->parentWidget();
3425 };
3426#endif
3427}
3428
3429/*!
3430 \fn QGLFormat QGLWidget::format() const
3431
3432 Returns the format of the contained GL rendering context.
3433*/
3434
3435/*!
3436 \fn bool QGLWidget::doubleBuffer() const
3437
3438 Returns true if the contained GL rendering context has double
3439 buffering; otherwise returns false.
3440
3441 \sa QGLFormat::doubleBuffer()
3442*/
3443
3444/*!
3445 \fn void QGLWidget::setAutoBufferSwap(bool on)
3446
3447 If \a on is true automatic GL buffer swapping is switched on;
3448 otherwise it is switched off.
3449
3450 If \a on is true and the widget is using a double-buffered format,
3451 the background and foreground GL buffers will automatically be
3452 swapped after each paintGL() call.
3453
3454 The buffer auto-swapping is on by default.
3455
3456 \sa autoBufferSwap(), doubleBuffer(), swapBuffers()
3457*/
3458
3459/*!
3460 \fn bool QGLWidget::autoBufferSwap() const
3461
3462 Returns true if the widget is doing automatic GL buffer swapping;
3463 otherwise returns false.
3464
3465 \sa setAutoBufferSwap()
3466*/
3467
3468/*!
3469 \fn void *QGLContext::getProcAddress(const QString &proc) const
3470
3471 Returns a function pointer to the GL extension function passed in
3472 \a proc. 0 is returned if a pointer to the function could not be
3473 obtained.
3474*/
3475
3476/*!
3477 \fn bool QGLWidget::isValid() const
3478
3479 Returns true if the widget has a valid GL rendering context;
3480 otherwise returns false. A widget will be invalid if the system
3481 has no \link QGLFormat::hasOpenGL() OpenGL support\endlink.
3482*/
3483
3484bool QGLWidget::isValid() const
3485{
3486 Q_D(const QGLWidget);
3487 return d->glcx && d->glcx->isValid();
3488}
3489
3490/*!
3491 \fn bool QGLWidget::isSharing() const
3492
3493 Returns true if this widget's GL context is shared with another GL
3494 context, otherwise false is returned. Context sharing might not be
3495 possible if the widgets use different formats.
3496
3497 \sa format()
3498*/
3499
3500bool QGLWidget::isSharing() const
3501{
3502 Q_D(const QGLWidget);
3503 return d->glcx->isSharing();
3504}
3505
3506/*!
3507 \fn void QGLWidget::makeCurrent()
3508
3509 Makes this widget the current widget for OpenGL operations, i.e.
3510 makes the widget's rendering context the current OpenGL rendering
3511 context.
3512*/
3513
3514void QGLWidget::makeCurrent()
3515{
3516 Q_D(QGLWidget);
3517 d->glcx->makeCurrent();
3518}
3519
3520/*!
3521 \fn void QGLWidget::doneCurrent()
3522
3523 Makes no GL context the current context. Normally, you do not need
3524 to call this function; QGLContext calls it as necessary. However,
3525 it may be useful in multithreaded environments.
3526*/
3527
3528void QGLWidget::doneCurrent()
3529{
3530 Q_D(QGLWidget);
3531 d->glcx->doneCurrent();
3532}
3533
3534/*!
3535 \fn void QGLWidget::swapBuffers()
3536
3537 Swaps the screen contents with an off-screen buffer. This only
3538 works if the widget's format specifies double buffer mode.
3539
3540 Normally, there is no need to explicitly call this function
3541 because it is done automatically after each widget repaint, i.e.
3542 each time after paintGL() has been executed.
3543
3544 \sa doubleBuffer(), setAutoBufferSwap(), QGLFormat::setDoubleBuffer()
3545*/
3546
3547void QGLWidget::swapBuffers()
3548{
3549 Q_D(QGLWidget);
3550 d->glcx->swapBuffers();
3551}
3552
3553
3554/*!
3555 \fn const QGLContext* QGLWidget::overlayContext() const
3556
3557 Returns the overlay context of this widget, or 0 if this widget
3558 has no overlay.
3559
3560 \sa context()
3561*/
3562
3563
3564
3565/*!
3566 \fn void QGLWidget::makeOverlayCurrent()
3567
3568 Makes the overlay context of this widget current. Use this if you
3569 need to issue OpenGL commands to the overlay context outside of
3570 initializeOverlayGL(), resizeOverlayGL(), and paintOverlayGL().
3571
3572 Does nothing if this widget has no overlay.
3573
3574 \sa makeCurrent()
3575*/
3576
3577
3578/*!
3579 \obsolete
3580
3581 Sets a new format for this widget.
3582
3583 If the underlying OpenGL/Window system cannot satisfy all the
3584 features requested in \a format, the nearest subset of features will
3585 be used. After creation, the format() method will return the actual
3586 rendering context format obtained.
3587
3588 The widget will be assigned a new QGLContext, and the initializeGL()
3589 function will be executed for this new context before the first
3590 resizeGL() or paintGL().
3591
3592 This method will try to keep display list and texture object sharing
3593 in effect with other QGLWidget objects, but changing the format might make
3594 sharing impossible. Use isSharing() to see if sharing is still in
3595 effect.
3596
3597 \sa format(), isSharing(), isValid()
3598*/
3599
3600void QGLWidget::setFormat(const QGLFormat &format)
3601{
3602 setContext(new QGLContext(format,this));
3603}
3604
3605
3606
3607
3608/*!
3609 \fn const QGLContext *QGLWidget::context() const
3610
3611 Returns the context of this widget.
3612
3613 It is possible that the context is not valid (see isValid()), for
3614 example, if the underlying hardware does not support the format
3615 attributes that were requested.
3616*/
3617
3618/*
3619 \fn void QGLWidget::setContext(QGLContext *context,
3620 const QGLContext* shareContext,
3621 bool deleteOldContext)
3622 \obsolete
3623
3624 Sets a new context for this widget. The QGLContext \a context must
3625 be created using \e new. QGLWidget will delete \a context when
3626 another context is set or when the widget is destroyed.
3627
3628 If \a context is invalid, QGLContext::create() is performed on
3629 it. The initializeGL() function will then be executed for the new
3630 context before the first resizeGL() or paintGL().
3631
3632 If \a context is invalid, this method will try to keep display list
3633 and texture object sharing in effect, or (if \a shareContext points
3634 to a valid context) start display list and texture object sharing
3635 with that context, but sharing might be impossible if the two
3636 contexts have different \l {format()} {formats}. Use isSharing() to
3637 see whether sharing is in effect.
3638
3639 If \a deleteOldContext is true (the default), the existing context
3640 will be deleted. You may use false here if you have kept a pointer
3641 to the old context (as returned by context()), and want to restore
3642 that context later.
3643
3644 \sa context(), isSharing()
3645*/
3646
3647
3648
3649/*!
3650 \fn void QGLWidget::updateGL()
3651
3652 Updates the widget by calling glDraw().
3653*/
3654
3655void QGLWidget::updateGL()
3656{
3657 if (updatesEnabled())
3658 glDraw();
3659}
3660
3661
3662/*!
3663 \fn void QGLWidget::updateOverlayGL()
3664
3665 Updates the widget's overlay (if any). Will cause the virtual
3666 function paintOverlayGL() to be executed.
3667
3668 The widget's rendering context will become the current context and
3669 initializeGL() will be called if it hasn't already been called.
3670*/
3671
3672
3673/*!
3674 This virtual function is called once before the first call to
3675 paintGL() or resizeGL(), and then once whenever the widget has
3676 been assigned a new QGLContext. Reimplement it in a subclass.
3677
3678 This function should set up any required OpenGL context rendering
3679 flags, defining display lists, etc.
3680
3681 There is no need to call makeCurrent() because this has already
3682 been done when this function is called.
3683*/
3684
3685void QGLWidget::initializeGL()
3686{
3687}
3688
3689
3690/*!
3691 This virtual function is called whenever the widget needs to be
3692 painted. Reimplement it in a subclass.
3693
3694 There is no need to call makeCurrent() because this has already
3695 been done when this function is called.
3696*/
3697
3698void QGLWidget::paintGL()
3699{
3700}
3701
3702
3703/*!
3704 \fn void QGLWidget::resizeGL(int width , int height)
3705
3706 This virtual function is called whenever the widget has been
3707 resized. The new size is passed in \a width and \a height.
3708 Reimplement it in a subclass.
3709
3710 There is no need to call makeCurrent() because this has already
3711 been done when this function is called.
3712*/
3713
3714void QGLWidget::resizeGL(int, int)
3715{
3716}
3717
3718
3719
3720/*!
3721 This virtual function is used in the same manner as initializeGL()
3722 except that it operates on the widget's overlay context instead of
3723 the widget's main context. This means that initializeOverlayGL()
3724 is called once before the first call to paintOverlayGL() or
3725 resizeOverlayGL(). Reimplement it in a subclass.
3726
3727 This function should set up any required OpenGL context rendering
3728 flags, defining display lists, etc. for the overlay context.
3729
3730 There is no need to call makeOverlayCurrent() because this has
3731 already been done when this function is called.
3732*/
3733
3734void QGLWidget::initializeOverlayGL()
3735{
3736}
3737
3738
3739/*!
3740 This virtual function is used in the same manner as paintGL()
3741 except that it operates on the widget's overlay context instead of
3742 the widget's main context. This means that paintOverlayGL() is
3743 called whenever the widget's overlay needs to be painted.
3744 Reimplement it in a subclass.
3745
3746 There is no need to call makeOverlayCurrent() because this has
3747 already been done when this function is called.
3748*/
3749
3750void QGLWidget::paintOverlayGL()
3751{
3752}
3753
3754
3755/*!
3756 \fn void QGLWidget::resizeOverlayGL(int width , int height)
3757
3758 This virtual function is used in the same manner as paintGL()
3759 except that it operates on the widget's overlay context instead of
3760 the widget's main context. This means that resizeOverlayGL() is
3761 called whenever the widget has been resized. The new size is
3762 passed in \a width and \a height. Reimplement it in a subclass.
3763
3764 There is no need to call makeOverlayCurrent() because this has
3765 already been done when this function is called.
3766*/
3767
3768void QGLWidget::resizeOverlayGL(int, int)
3769{
3770}
3771
3772/*! \fn bool QGLWidget::event(QEvent *e)
3773 \reimp
3774*/
3775#if !defined(Q_OS_WINCE) && !defined(Q_WS_QWS)
3776bool QGLWidget::event(QEvent *e)
3777{
3778 Q_D(QGLWidget);
3779
3780 if (e->type() == QEvent::Paint) {
3781 QPoint offset;
3782 QPaintDevice *redirectedDevice = d->redirected(&offset);
3783 if (redirectedDevice && redirectedDevice->devType() == QInternal::Pixmap) {
3784 d->restoreRedirected();
3785 QPixmap pixmap = renderPixmap();
3786 d->setRedirected(redirectedDevice, offset);
3787 QPainter p(redirectedDevice);
3788 p.drawPixmap(-offset, pixmap);
3789 return true;
3790 }
3791 }
3792
3793#if defined(Q_WS_X11)
3794 // prevents X errors on some systems, where we get a flush to a
3795 // hidden widget
3796 if (e->type() == QEvent::Hide) {
3797 makeCurrent();
3798 glFinish();
3799 doneCurrent();
3800 } else if (e->type() == QEvent::ParentChange) {
3801 // if we've reparented a window that has the current context
3802 // bound, we need to rebind that context to the new window id
3803 if (d->glcx == QGLContext::currentContext())
3804 makeCurrent();
3805
3806 if (d->glcx->d_func()->screen != d->xinfo.screen() || testAttribute(Qt::WA_TranslucentBackground)) {
3807 setContext(new QGLContext(d->glcx->requestedFormat(), this));
3808 // ### recreating the overlay isn't supported atm
3809 }
3810 }
3811
3812#if defined(QT_OPENGL_ES)
3813 // A re-parent is likely to destroy the X11 window and re-create it. It is important
3814 // that we free the EGL surface _before_ the winID changes - otherwise we can leak.
3815 if (e->type() == QEvent::ParentAboutToChange)
3816 d->glcx->d_func()->destroyEglSurfaceForDevice();
3817
3818 if ((e->type() == QEvent::ParentChange) || (e->type() == QEvent::WindowStateChange)) {
3819 // The window may have been re-created during re-parent or state change - if so, the EGL
3820 // surface will need to be re-created.
3821 d->recreateEglSurface(false);
3822 }
3823#endif
3824#elif defined(Q_WS_WIN)
3825 if (e->type() == QEvent::ParentChange) {
3826 QGLContext *newContext = new QGLContext(d->glcx->requestedFormat(), this);
3827 setContext(newContext, d->glcx);
3828
3829 // the overlay needs to be recreated as well
3830 delete d->olcx;
3831 if (isValid() && context()->format().hasOverlay()) {
3832 d->olcx = new QGLContext(QGLFormat::defaultOverlayFormat(), this);
3833 if (!d->olcx->create(isSharing() ? d->glcx : 0)) {
3834 delete d->olcx;
3835 d->olcx = 0;
3836 d->glcx->d_func()->glFormat.setOverlay(false);
3837 }
3838 } else {
3839 d->olcx = 0;
3840 }
3841 } else if (e->type() == QEvent::Show) {
3842 if (!format().rgba())
3843 d->updateColormap();
3844 }
3845#elif defined(Q_WS_MAC)
3846 if (e->type() == QEvent::MacGLWindowChange
3847#if 0 //(MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5)
3848 && ((QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5 && isWindow())
3849 || QSysInfo::MacintoshVersion <= QSysInfo::MV_10_4)
3850#endif
3851 ) {
3852 if (d->needWindowChange) {
3853 d->needWindowChange = false;
3854 d->glcx->updatePaintDevice();
3855 update();
3856 }
3857 return true;
3858# if defined(QT_MAC_USE_COCOA)
3859 } else if (e->type() == QEvent::MacGLClearDrawable) {
3860 d->glcx->d_ptr->clearDrawable();
3861# endif
3862 }
3863#endif
3864
3865 return QWidget::event(e);
3866}
3867#endif
3868
3869/*!
3870 \fn void QGLWidget::paintEvent(QPaintEvent *event)
3871
3872 Handles paint events passed in the \a event parameter. Will cause
3873 the virtual paintGL() function to be called.
3874
3875 The widget's rendering context will become the current context and
3876 initializeGL() will be called if it hasn't already been called.
3877*/
3878
3879void QGLWidget::paintEvent(QPaintEvent *)
3880{
3881 if (updatesEnabled()) {
3882 glDraw();
3883 updateOverlayGL();
3884 }
3885}
3886
3887
3888/*!
3889 \fn void QGLWidget::resizeEvent(QResizeEvent *event)
3890
3891 Handles resize events that are passed in the \a event parameter.
3892 Calls the virtual function resizeGL().
3893*/
3894
3895
3896/*!
3897 \fn void QGLWidget::setMouseTracking(bool enable)
3898
3899 If \a enable is true then mouse tracking is enabled; otherwise it
3900 is disabled.
3901*/
3902
3903
3904/*!
3905 Renders the current scene on a pixmap and returns the pixmap.
3906
3907 You can use this method on both visible and invisible QGLWidget objects.
3908
3909 This method will create a pixmap and a temporary QGLContext to
3910 render on the pixmap. It will then call initializeGL(),
3911 resizeGL(), and paintGL() on this context. Finally, the widget's
3912 original GL context is restored.
3913
3914 The size of the pixmap will be \a w pixels wide and \a h pixels
3915 high unless one of these parameters is 0 (the default), in which
3916 case the pixmap will have the same size as the widget.
3917
3918 If \a useContext is true, this method will try to be more
3919 efficient by using the existing GL context to render the pixmap.
3920 The default is false. Only use true if you understand the risks.
3921 Note that under Windows a temporary context has to be created
3922 and usage of the \e useContext parameter is not supported.
3923
3924 Overlays are not rendered onto the pixmap.
3925
3926 If the GL rendering context and the desktop have different bit
3927 depths, the result will most likely look surprising.
3928
3929 Note that the creation of display lists, modifications of the view
3930 frustum etc. should be done from within initializeGL(). If this is
3931 not done, the temporary QGLContext will not be initialized
3932 properly, and the rendered pixmap may be incomplete/corrupted.
3933*/
3934
3935QPixmap QGLWidget::renderPixmap(int w, int h, bool useContext)
3936{
3937 Q_D(QGLWidget);
3938 QSize sz = size();
3939 if ((w > 0) && (h > 0))
3940 sz = QSize(w, h);
3941
3942#if defined(Q_WS_X11)
3943 extern int qt_x11_preferred_pixmap_depth;
3944 int old_depth = qt_x11_preferred_pixmap_depth;
3945 qt_x11_preferred_pixmap_depth = x11Info().depth();
3946
3947 QPixmapData *data = new QX11PixmapData(QPixmapData::PixmapType);
3948 data->resize(sz.width(), sz.height());
3949 QPixmap pm(data);
3950 qt_x11_preferred_pixmap_depth = old_depth;
3951 QX11Info xinfo = x11Info();
3952
3953 // make sure we use a pixmap with the same depth/visual as the widget
3954 if (xinfo.visual() != QX11Info::appVisual()) {
3955 QX11InfoData* xd = pm.x11Info().getX11Data(true);
3956 xd->depth = xinfo.depth();
3957 xd->visual = static_cast<Visual *>(xinfo.visual());
3958 const_cast<QX11Info &>(pm.x11Info()).setX11Data(xd);
3959 }
3960
3961#else
3962 QPixmap pm(sz);
3963#endif
3964
3965 d->glcx->doneCurrent();
3966
3967 bool success = true;
3968
3969 if (useContext && isValid() && d->renderCxPm(&pm))
3970 return pm;
3971
3972 QGLFormat fmt = d->glcx->requestedFormat();
3973 fmt.setDirectRendering(false); // Direct is unlikely to work
3974 fmt.setDoubleBuffer(false); // We don't need dbl buf
3975#ifdef Q_WS_MAC // crash prevention on the Mac - it's unlikely to work anyway
3976 fmt.setSampleBuffers(false);
3977#endif
3978
3979 QGLContext* ocx = d->glcx;
3980 ocx->doneCurrent();
3981 d->glcx = new QGLContext(fmt, &pm);
3982 d->glcx->create();
3983
3984 if (d->glcx->isValid())
3985 updateGL();
3986 else
3987 success = false;
3988
3989 delete d->glcx;
3990 d->glcx = ocx;
3991
3992 ocx->makeCurrent();
3993
3994 if (success) {
3995#if defined(Q_WS_X11)
3996 if (xinfo.visual() != QX11Info::appVisual()) {
3997 QImage image = pm.toImage();
3998 QPixmap p = QPixmap::fromImage(image);
3999 return p;
4000 }
4001#endif
4002 return pm;
4003 }
4004 return QPixmap();
4005}
4006
4007/*!
4008 Returns an image of the frame buffer. If \a withAlpha is true the
4009 alpha channel is included.
4010
4011 Depending on your hardware, you can explicitly select which color
4012 buffer to grab with a glReadBuffer() call before calling this
4013 function.
4014*/
4015QImage QGLWidget::grabFrameBuffer(bool withAlpha)
4016{
4017 makeCurrent();
4018 QImage res;
4019 int w = width();
4020 int h = height();
4021 if (format().rgba()) {
4022 res = qt_gl_read_framebuffer(QSize(w, h), format().alpha(), withAlpha);
4023 } else {
4024#if defined (Q_WS_WIN) && !defined(QT_OPENGL_ES)
4025 res = QImage(w, h, QImage::Format_Indexed8);
4026 glReadPixels(0, 0, w, h, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, res.bits());
4027 const QVector<QColor> pal = QColormap::instance().colormap();
4028 if (pal.size()) {
4029 res.setColorCount(pal.size());
4030 for (int i = 0; i < pal.size(); i++)
4031 res.setColor(i, pal.at(i).rgb());
4032 }
4033 res = res.mirrored();
4034#endif
4035 }
4036
4037 return res;
4038}
4039
4040
4041
4042/*!
4043 Initializes OpenGL for this widget's context. Calls the virtual
4044 function initializeGL().
4045*/
4046
4047void QGLWidget::glInit()
4048{
4049 Q_D(QGLWidget);
4050 if (!isValid())
4051 return;
4052 makeCurrent();
4053 initializeGL();
4054 d->glcx->setInitialized(true);
4055}
4056
4057
4058/*!
4059 Executes the virtual function paintGL().
4060
4061 The widget's rendering context will become the current context and
4062 initializeGL() will be called if it hasn't already been called.
4063*/
4064
4065void QGLWidget::glDraw()
4066{
4067 Q_D(QGLWidget);
4068 if (!isValid())
4069 return;
4070 makeCurrent();
4071#ifndef QT_OPENGL_ES
4072 if (d->glcx->deviceIsPixmap())
4073 glDrawBuffer(GL_FRONT);
4074#endif
4075 if (!d->glcx->initialized()) {
4076 glInit();
4077 resizeGL(d->glcx->device()->width(), d->glcx->device()->height()); // New context needs this "resize"
4078 }
4079 paintGL();
4080 if (doubleBuffer()) {
4081 if (d->autoSwap)
4082 swapBuffers();
4083 } else {
4084 glFlush();
4085 }
4086}
4087
4088/*!
4089 Convenience function for specifying a drawing color to OpenGL.
4090 Calls glColor4 (in RGBA mode) or glIndex (in color-index mode)
4091 with the color \a c. Applies to this widgets GL context.
4092
4093 \note This function is not supported on OpenGL/ES 2.0 systems.
4094
4095 \sa qglClearColor(), QGLContext::currentContext(), QColor
4096*/
4097
4098void QGLWidget::qglColor(const QColor& c) const
4099{
4100#if !defined(QT_OPENGL_ES_2)
4101#ifdef QT_OPENGL_ES
4102 glColor4f(c.redF(), c.greenF(), c.blueF(), c.alphaF());
4103#else
4104 Q_D(const QGLWidget);
4105 const QGLContext *ctx = QGLContext::currentContext();
4106 if (ctx) {
4107 if (ctx->format().rgba())
4108 glColor4f(c.redF(), c.greenF(), c.blueF(), c.alphaF());
4109 else if (!d->cmap.isEmpty()) { // QGLColormap in use?
4110 int i = d->cmap.find(c.rgb());
4111 if (i < 0)
4112 i = d->cmap.findNearest(c.rgb());
4113 glIndexi(i);
4114 } else
4115 glIndexi(ctx->colorIndex(c));
4116 }
4117#endif //QT_OPENGL_ES
4118#else
4119 Q_UNUSED(c);
4120#endif //QT_OPENGL_ES_2
4121}
4122
4123/*!
4124 Convenience function for specifying the clearing color to OpenGL.
4125 Calls glClearColor (in RGBA mode) or glClearIndex (in color-index
4126 mode) with the color \a c. Applies to this widgets GL context.
4127
4128 \sa qglColor(), QGLContext::currentContext(), QColor
4129*/
4130
4131void QGLWidget::qglClearColor(const QColor& c) const
4132{
4133#ifdef QT_OPENGL_ES
4134 glClearColor(c.redF(), c.greenF(), c.blueF(), c.alphaF());
4135#else
4136 Q_D(const QGLWidget);
4137 const QGLContext *ctx = QGLContext::currentContext();
4138 if (ctx) {
4139 if (ctx->format().rgba())
4140 glClearColor(c.redF(), c.greenF(), c.blueF(), c.alphaF());
4141 else if (!d->cmap.isEmpty()) { // QGLColormap in use?
4142 int i = d->cmap.find(c.rgb());
4143 if (i < 0)
4144 i = d->cmap.findNearest(c.rgb());
4145 glClearIndex(i);
4146 } else
4147 glClearIndex(ctx->colorIndex(c));
4148 }
4149#endif
4150}
4151
4152
4153/*!
4154 Converts the image \a img into the unnamed format expected by
4155 OpenGL functions such as glTexImage2D(). The returned image is not
4156 usable as a QImage, but QImage::width(), QImage::height() and
4157 QImage::bits() may be used with OpenGL. The GL format used is
4158 \c GL_RGBA.
4159
4160 \omit ###
4161
4162 \l opengl/texture example
4163 The following few lines are from the texture example. Most of the
4164 code is irrelevant, so we just quote the relevant bits:
4165
4166 \quotefromfile opengl/texture/gltexobj.cpp
4167 \skipto tex1
4168 \printline tex1
4169 \printline gllogo.bmp
4170
4171 We create \e tex1 (and another variable) for OpenGL, and load a real
4172 image into \e buf.
4173
4174 \skipto convertToGLFormat
4175 \printline convertToGLFormat
4176
4177 A few lines later, we convert \e buf into OpenGL format and store it
4178 in \e tex1.
4179
4180 \skipto glTexImage2D
4181 \printline glTexImage2D
4182 \printline tex1.bits
4183
4184 Note the dimension restrictions for texture images as described in
4185 the glTexImage2D() documentation. The width must be 2^m + 2*border
4186 and the height 2^n + 2*border where m and n are integers and
4187 border is either 0 or 1.
4188
4189 Another function in the same example uses \e tex1 with OpenGL.
4190
4191 \endomit
4192*/
4193
4194QImage QGLWidget::convertToGLFormat(const QImage& img)
4195{
4196 QImage res(img.size(), QImage::Format_ARGB32);
4197 convertToGLFormatHelper(res, img.convertToFormat(QImage::Format_ARGB32), GL_RGBA);
4198 return res;
4199}
4200
4201
4202/*!
4203 \fn QGLColormap & QGLWidget::colormap() const
4204
4205 Returns the colormap for this widget.
4206
4207 Usually it is only top-level widgets that can have different
4208 colormaps installed. Asking for the colormap of a child widget
4209 will return the colormap for the child's top-level widget.
4210
4211 If no colormap has been set for this widget, the QGLColormap
4212 returned will be empty.
4213
4214 \sa setColormap(), QGLColormap::isEmpty()
4215*/
4216
4217/*!
4218 \fn void QGLWidget::setColormap(const QGLColormap & cmap)
4219
4220 Set the colormap for this widget to \a cmap. Usually it is only
4221 top-level widgets that can have colormaps installed.
4222
4223 \sa colormap()
4224*/
4225
4226
4227/*!
4228 \obsolete
4229
4230 Returns the value of the first display list that is generated for
4231 the characters in the given \a font. \a listBase indicates the base
4232 value used when generating the display lists for the font. The
4233 default value is 2000.
4234
4235 \note This function is not supported on OpenGL/ES systems.
4236*/
4237int QGLWidget::fontDisplayListBase(const QFont & font, int listBase)
4238{
4239#ifndef QT_OPENGL_ES
4240 Q_D(QGLWidget);
4241 int base;
4242
4243 if (!d->glcx) { // this can't happen unless we run out of mem
4244 return 0;
4245 }
4246
4247 // always regenerate font disp. lists for pixmaps - hw accelerated
4248 // contexts can't handle this otherwise
4249 bool regenerate = d->glcx->deviceIsPixmap();
4250#ifndef QT_NO_FONTCONFIG
4251 // font color needs to be part of the font cache key when using
4252 // antialiased fonts since one set of glyphs needs to be generated
4253 // for each font color
4254 QString color_key;
4255 if (font.styleStrategy() != QFont::NoAntialias) {
4256 GLfloat color[4];
4257 glGetFloatv(GL_CURRENT_COLOR, color);
4258 color_key.sprintf("%f_%f_%f",color[0], color[1], color[2]);
4259 }
4260 QString key = font.key() + color_key + QString::number((int) regenerate);
4261#else
4262 QString key = font.key() + QString::number((int) regenerate);
4263#endif
4264 if (!regenerate && (d->displayListCache.find(key) != d->displayListCache.end())) {
4265 base = d->displayListCache[key];
4266 } else {
4267 int maxBase = listBase - 256;
4268 QMap<QString,int>::ConstIterator it;
4269 for (it = d->displayListCache.constBegin(); it != d->displayListCache.constEnd(); ++it) {
4270 if (maxBase < it.value()) {
4271 maxBase = it.value();
4272 }
4273 }
4274 maxBase += 256;
4275 d->glcx->generateFontDisplayLists(font, maxBase);
4276 d->displayListCache[key] = maxBase;
4277 base = maxBase;
4278 }
4279 return base;
4280#else // QT_OPENGL_ES
4281 Q_UNUSED(font);
4282 Q_UNUSED(listBase);
4283 return 0;
4284#endif
4285}
4286
4287#ifndef QT_OPENGL_ES
4288
4289static void qt_save_gl_state()
4290{
4291 glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS);
4292 glPushAttrib(GL_ALL_ATTRIB_BITS);
4293 glMatrixMode(GL_TEXTURE);
4294 glPushMatrix();
4295 glLoadIdentity();
4296 glMatrixMode(GL_PROJECTION);
4297 glPushMatrix();
4298 glMatrixMode(GL_MODELVIEW);
4299 glPushMatrix();
4300
4301 glShadeModel(GL_FLAT);
4302 glDisable(GL_CULL_FACE);
4303 glDisable(GL_LIGHTING);
4304 glDisable(GL_STENCIL_TEST);
4305 glDisable(GL_DEPTH_TEST);
4306 glEnable(GL_BLEND);
4307 glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
4308}
4309
4310static void qt_restore_gl_state()
4311{
4312 glMatrixMode(GL_TEXTURE);
4313 glPopMatrix();
4314 glMatrixMode(GL_PROJECTION);
4315 glPopMatrix();
4316 glMatrixMode(GL_MODELVIEW);
4317 glPopMatrix();
4318 glPopAttrib();
4319 glPopClientAttrib();
4320}
4321
4322static void qt_gl_draw_text(QPainter *p, int x, int y, const QString &str,
4323 const QFont &font)
4324{
4325 GLfloat color[4];
4326 glGetFloatv(GL_CURRENT_COLOR, &color[0]);
4327
4328 QColor col;
4329 col.setRgbF(color[0], color[1], color[2],color[3]);
4330 QPen old_pen = p->pen();
4331 QFont old_font = p->font();
4332
4333 p->setPen(col);
4334 p->setFont(font);
4335 p->drawText(x, y, str);
4336
4337 p->setPen(old_pen);
4338 p->setFont(old_font);
4339}
4340
4341#endif // !QT_OPENGL_ES
4342
4343/*!
4344 Renders the string \a str into the GL context of this widget.
4345
4346 \a x and \a y are specified in window coordinates, with the origin
4347 in the upper left-hand corner of the window. If \a font is not
4348 specified, the currently set application font will be used to
4349 render the string. To change the color of the rendered text you can
4350 use the glColor() call (or the qglColor() convenience function),
4351 just before the renderText() call.
4352
4353 The \a listBase parameter is obsolete and will be removed in a
4354 future version of Qt.
4355
4356 \note This function clears the stencil buffer.
4357
4358 \note This function is not supported on OpenGL/ES systems.
4359
4360 \note This function temporarily disables depth-testing when the
4361 text is drawn.
4362
4363 \l{Overpainting Example}{Overpaint} with QPainter::drawText() instead.
4364*/
4365
4366void QGLWidget::renderText(int x, int y, const QString &str, const QFont &font, int)
4367{
4368#ifndef QT_OPENGL_ES
4369 Q_D(QGLWidget);
4370 if (str.isEmpty() || !isValid())
4371 return;
4372
4373 GLint view[4];
4374 bool use_scissor_testing = glIsEnabled(GL_SCISSOR_TEST);
4375 if (!use_scissor_testing)
4376 glGetIntegerv(GL_VIEWPORT, &view[0]);
4377 int width = d->glcx->device()->width();
4378 int height = d->glcx->device()->height();
4379 bool auto_swap = autoBufferSwap();
4380
4381 QPaintEngine::Type oldEngineType = qgl_engine_selector()->preferredPaintEngine();
4382 qgl_engine_selector()->setPreferredPaintEngine(QPaintEngine::OpenGL);
4383 QPaintEngine *engine = paintEngine();
4384 QPainter *p;
4385 bool reuse_painter = false;
4386 if (engine->isActive()) {
4387 reuse_painter = true;
4388 p = engine->painter();
4389 qt_save_gl_state();
4390
4391 glDisable(GL_DEPTH_TEST);
4392 glViewport(0, 0, width, height);
4393 glMatrixMode(GL_PROJECTION);
4394 glLoadIdentity();
4395 glOrtho(0, width, height, 0, 0, 1);
4396 glMatrixMode(GL_MODELVIEW);
4397
4398 glLoadIdentity();
4399 } else {
4400 setAutoBufferSwap(false);
4401 // disable glClear() as a result of QPainter::begin()
4402 d->disable_clear_on_painter_begin = true;
4403 p = new QPainter(this);
4404 }
4405
4406 QRect viewport(view[0], view[1], view[2], view[3]);
4407 if (!use_scissor_testing && viewport != rect()) {
4408 // if the user hasn't set a scissor box, we set one that
4409 // covers the current viewport
4410 glScissor(view[0], view[1], view[2], view[3]);
4411 glEnable(GL_SCISSOR_TEST);
4412 } else if (use_scissor_testing) {
4413 // use the scissor box set by the user
4414 glEnable(GL_SCISSOR_TEST);
4415 }
4416
4417 qt_gl_draw_text(p, x, y, str, font);
4418
4419 if (reuse_painter) {
4420 qt_restore_gl_state();
4421 } else {
4422 p->end();
4423 delete p;
4424 setAutoBufferSwap(auto_swap);
4425 d->disable_clear_on_painter_begin = false;
4426 }
4427 qgl_engine_selector()->setPreferredPaintEngine(oldEngineType);
4428#else // QT_OPENGL_ES
4429 Q_UNUSED(x);
4430 Q_UNUSED(y);
4431 Q_UNUSED(str);
4432 Q_UNUSED(font);
4433 qWarning("QGLWidget::renderText is not supported under OpenGL/ES");
4434#endif
4435}
4436
4437/*! \overload
4438
4439 \a x, \a y and \a z are specified in scene or object coordinates
4440 relative to the currently set projection and model matrices. This
4441 can be useful if you want to annotate models with text labels and
4442 have the labels move with the model as it is rotated etc.
4443
4444 \note This function is not supported on OpenGL/ES systems.
4445
4446 \note If depth testing is enabled before this function is called,
4447 then the drawn text will be depth-tested against the models that
4448 have already been drawn in the scene. Use \c{glDisable(GL_DEPTH_TEST)}
4449 before calling this function to annotate the models without
4450 depth-testing the text.
4451
4452 \l{Overpainting Example}{Overpaint} with QPainter::drawText() instead.
4453*/
4454void QGLWidget::renderText(double x, double y, double z, const QString &str, const QFont &font, int)
4455{
4456#ifndef QT_OPENGL_ES
4457 Q_D(QGLWidget);
4458 if (str.isEmpty() || !isValid())
4459 return;
4460
4461 bool auto_swap = autoBufferSwap();
4462
4463 int width = d->glcx->device()->width();
4464 int height = d->glcx->device()->height();
4465 GLdouble model[4][4], proj[4][4];
4466 GLint view[4];
4467 glGetDoublev(GL_MODELVIEW_MATRIX, &model[0][0]);
4468 glGetDoublev(GL_PROJECTION_MATRIX, &proj[0][0]);
4469 glGetIntegerv(GL_VIEWPORT, &view[0]);
4470 GLdouble win_x = 0, win_y = 0, win_z = 0;
4471 qgluProject(x, y, z, &model[0][0], &proj[0][0], &view[0],
4472 &win_x, &win_y, &win_z);
4473 win_y = height - win_y; // y is inverted
4474
4475 QPaintEngine::Type oldEngineType = qgl_engine_selector()->preferredPaintEngine();
4476 qgl_engine_selector()->setPreferredPaintEngine(QPaintEngine::OpenGL);
4477 QPaintEngine *engine = paintEngine();
4478 QPainter *p;
4479 bool reuse_painter = false;
4480 bool use_depth_testing = glIsEnabled(GL_DEPTH_TEST);
4481 bool use_scissor_testing = glIsEnabled(GL_SCISSOR_TEST);
4482
4483 if (engine->isActive()) {
4484 reuse_painter = true;
4485 p = engine->painter();
4486 qt_save_gl_state();
4487 } else {
4488 setAutoBufferSwap(false);
4489 // disable glClear() as a result of QPainter::begin()
4490 d->disable_clear_on_painter_begin = true;
4491 p = new QPainter(this);
4492 }
4493
4494 QRect viewport(view[0], view[1], view[2], view[3]);
4495 if (!use_scissor_testing && viewport != rect()) {
4496 glScissor(view[0], view[1], view[2], view[3]);
4497 glEnable(GL_SCISSOR_TEST);
4498 } else if (use_scissor_testing) {
4499 glEnable(GL_SCISSOR_TEST);
4500 }
4501 glMatrixMode(GL_PROJECTION);
4502 glLoadIdentity();
4503 glViewport(0, 0, width, height);
4504 glOrtho(0, width, height, 0, 0, 1);
4505 glMatrixMode(GL_MODELVIEW);
4506 glLoadIdentity();
4507 glAlphaFunc(GL_GREATER, 0.0);
4508 glEnable(GL_ALPHA_TEST);
4509 if (use_depth_testing)
4510 glEnable(GL_DEPTH_TEST);
4511 glTranslated(0, 0, -win_z);
4512 qt_gl_draw_text(p, qRound(win_x), qRound(win_y), str, font);
4513
4514 if (reuse_painter) {
4515 qt_restore_gl_state();
4516 } else {
4517 p->end();
4518 delete p;
4519 setAutoBufferSwap(auto_swap);
4520 d->disable_clear_on_painter_begin = false;
4521 }
4522 qgl_engine_selector()->setPreferredPaintEngine(oldEngineType);
4523#else // QT_OPENGL_ES
4524 Q_UNUSED(x);
4525 Q_UNUSED(y);
4526 Q_UNUSED(z);
4527 Q_UNUSED(str);
4528 Q_UNUSED(font);
4529 qWarning("QGLWidget::renderText is not supported under OpenGL/ES");
4530#endif
4531}
4532
4533QGLFormat QGLWidget::format() const
4534{
4535 Q_D(const QGLWidget);
4536 return d->glcx->format();
4537}
4538
4539const QGLContext *QGLWidget::context() const
4540{
4541 Q_D(const QGLWidget);
4542 return d->glcx;
4543}
4544
4545bool QGLWidget::doubleBuffer() const
4546{
4547 Q_D(const QGLWidget);
4548 return d->glcx->d_ptr->glFormat.testOption(QGL::DoubleBuffer);
4549}
4550
4551void QGLWidget::setAutoBufferSwap(bool on)
4552{
4553 Q_D(QGLWidget);
4554 d->autoSwap = on;
4555}
4556
4557bool QGLWidget::autoBufferSwap() const
4558{
4559 Q_D(const QGLWidget);
4560 return d->autoSwap;
4561}
4562
4563/*!
4564 Calls QGLContext:::bindTexture(\a image, \a target, \a format) on the currently
4565 set context.
4566
4567 \sa deleteTexture()
4568*/
4569GLuint QGLWidget::bindTexture(const QImage &image, GLenum target, GLint format)
4570{
4571 if (image.isNull())
4572 return 0;
4573
4574 Q_D(QGLWidget);
4575 return d->glcx->bindTexture(image, target, format, QGLContext::DefaultBindOption);
4576}
4577
4578/*!
4579 \overload
4580 \since 4.6
4581
4582 The binding \a options are a set of options used to decide how to
4583 bind the texture to the context.
4584 */
4585GLuint QGLWidget::bindTexture(const QImage &image, GLenum target, GLint format, QGLContext::BindOptions options)
4586{
4587 if (image.isNull())
4588 return 0;
4589
4590 Q_D(QGLWidget);
4591 return d->glcx->bindTexture(image, target, format, options);
4592}
4593
4594
4595#ifdef Q_MAC_COMPAT_GL_FUNCTIONS
4596/*! \internal */
4597GLuint QGLWidget::bindTexture(const QImage &image, QMacCompatGLenum target, QMacCompatGLint format)
4598{
4599 if (image.isNull())
4600 return 0;
4601
4602 Q_D(QGLWidget);
4603 return d->glcx->bindTexture(image, GLenum(target), GLint(format), QGLContext::DefaultBindOption);
4604}
4605
4606GLuint QGLWidget::bindTexture(const QImage &image, QMacCompatGLenum target, QMacCompatGLint format,
4607 QGLContext::BindOptions options)
4608{
4609 if (image.isNull())
4610 return 0;
4611
4612 Q_D(QGLWidget);
4613 return d->glcx->bindTexture(image, GLenum(target), GLint(format), options);
4614}
4615#endif
4616
4617/*!
4618 Calls QGLContext:::bindTexture(\a pixmap, \a target, \a format) on the currently
4619 set context.
4620
4621 \sa deleteTexture()
4622*/
4623GLuint QGLWidget::bindTexture(const QPixmap &pixmap, GLenum target, GLint format)
4624{
4625 if (pixmap.isNull())
4626 return 0;
4627
4628 Q_D(QGLWidget);
4629 return d->glcx->bindTexture(pixmap, target, format, QGLContext::DefaultBindOption);
4630}
4631
4632/*!
4633 \overload
4634 \since 4.6
4635
4636 Generates and binds a 2D GL texture to the current context, based
4637 on \a pixmap. The generated texture id is returned and can be used in
4638
4639 The binding \a options are a set of options used to decide how to
4640 bind the texture to the context.
4641 */
4642GLuint QGLWidget::bindTexture(const QPixmap &pixmap, GLenum target, GLint format,
4643 QGLContext::BindOptions options)
4644{
4645 Q_D(QGLWidget);
4646 return d->glcx->bindTexture(pixmap, target, format, options);
4647}
4648
4649#ifdef Q_MAC_COMPAT_GL_FUNCTIONS
4650/*! \internal */
4651GLuint QGLWidget::bindTexture(const QPixmap &pixmap, QMacCompatGLenum target, QMacCompatGLint format)
4652{
4653 Q_D(QGLWidget);
4654 return d->glcx->bindTexture(pixmap, target, format, QGLContext::DefaultBindOption);
4655}
4656
4657GLuint QGLWidget::bindTexture(const QPixmap &pixmap, QMacCompatGLenum target, QMacCompatGLint format,
4658 QGLContext::BindOptions options)
4659{
4660 Q_D(QGLWidget);
4661 return d->glcx->bindTexture(pixmap, target, format, options);
4662}
4663#endif
4664
4665
4666/*! \overload
4667
4668 Calls QGLContext::bindTexture(\a fileName) on the currently set context.
4669
4670 \sa deleteTexture()
4671*/
4672GLuint QGLWidget::bindTexture(const QString &fileName)
4673{
4674 Q_D(QGLWidget);
4675 return d->glcx->bindTexture(fileName);
4676}
4677
4678/*!
4679 Calls QGLContext::deleteTexture(\a id) on the currently set
4680 context.
4681
4682 \sa bindTexture()
4683*/
4684void QGLWidget::deleteTexture(GLuint id)
4685{
4686 Q_D(QGLWidget);
4687 d->glcx->deleteTexture(id);
4688}
4689
4690#ifdef Q_MAC_COMPAT_GL_FUNCTIONS
4691/*! \internal */
4692void QGLWidget::deleteTexture(QMacCompatGLuint id)
4693{
4694 Q_D(QGLWidget);
4695 d->glcx->deleteTexture(GLuint(id));
4696}
4697#endif
4698
4699/*!
4700 \since 4.4
4701
4702 Draws the given texture, \a textureId to the given target rectangle,
4703 \a target, in OpenGL model space. The \a textureTarget should be a 2D
4704 texture target.
4705
4706 Equivalent to the corresponding QGLContext::drawTexture().
4707*/
4708void QGLWidget::drawTexture(const QRectF &target, GLuint textureId, GLenum textureTarget)
4709{
4710 Q_D(QGLWidget);
4711 d->glcx->drawTexture(target, textureId, textureTarget);
4712}
4713
4714#ifdef Q_MAC_COMPAT_GL_FUNCTIONS
4715/*! \internal */
4716void QGLWidget::drawTexture(const QRectF &target, QMacCompatGLuint textureId, QMacCompatGLenum textureTarget)
4717{
4718 Q_D(QGLWidget);
4719 d->glcx->drawTexture(target, GLint(textureId), GLenum(textureTarget));
4720}
4721#endif
4722
4723/*!
4724 \since 4.4
4725
4726 Draws the given texture, \a textureId, at the given \a point in OpenGL
4727 model space. The \a textureTarget should be a 2D texture target.
4728
4729 Equivalent to the corresponding QGLContext::drawTexture().
4730*/
4731void QGLWidget::drawTexture(const QPointF &point, GLuint textureId, GLenum textureTarget)
4732{
4733 Q_D(QGLWidget);
4734 d->glcx->drawTexture(point, textureId, textureTarget);
4735}
4736
4737#ifdef Q_MAC_COMPAT_GL_FUNCTIONS
4738/*! \internal */
4739void QGLWidget::drawTexture(const QPointF &point, QMacCompatGLuint textureId, QMacCompatGLenum textureTarget)
4740{
4741 Q_D(QGLWidget);
4742 d->glcx->drawTexture(point, GLuint(textureId), GLenum(textureTarget));
4743}
4744#endif
4745
4746#if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
4747Q_GLOBAL_STATIC(QGL2PaintEngineEx, qt_gl_2_engine)
4748#endif
4749
4750#ifndef QT_OPENGL_ES_2
4751Q_GLOBAL_STATIC(QOpenGLPaintEngine, qt_gl_engine)
4752#endif
4753
4754Q_OPENGL_EXPORT QPaintEngine* qt_qgl_paint_engine()
4755{
4756#if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_1_CL)
4757 return qt_gl_engine();
4758#elif defined(QT_OPENGL_ES_2)
4759 return qt_gl_2_engine();
4760#else
4761 if (qt_gl_preferGL2Engine())
4762 return qt_gl_2_engine();
4763 else
4764 return qt_gl_engine();
4765#endif
4766}
4767
4768/*!
4769 \internal
4770
4771 Returns the GL widget's paint engine. This is normally a
4772 QOpenGLPaintEngine.
4773*/
4774QPaintEngine *QGLWidget::paintEngine() const
4775{
4776 return qt_qgl_paint_engine();
4777}
4778
4779#ifdef QT3_SUPPORT
4780/*!
4781 \overload
4782 \obsolete
4783 */
4784QGLWidget::QGLWidget(QWidget *parent, const char *name,
4785 const QGLWidget* shareWidget, Qt::WindowFlags f)
4786 : QWidget(*(new QGLWidgetPrivate), parent, f | Qt::MSWindowsOwnDC)
4787{
4788 Q_D(QGLWidget);
4789 if (name)
4790 setObjectName(QString::fromAscii(name));
4791 setAttribute(Qt::WA_PaintOnScreen);
4792 setAttribute(Qt::WA_NoSystemBackground);
4793 setAutoFillBackground(true); // for compatibility
4794 d->init(new QGLContext(QGLFormat::defaultFormat(), this), shareWidget);
4795}
4796
4797/*!
4798 \overload
4799 \obsolete
4800 */
4801QGLWidget::QGLWidget(const QGLFormat &format, QWidget *parent,
4802 const char *name, const QGLWidget* shareWidget,
4803 Qt::WindowFlags f)
4804 : QWidget(*(new QGLWidgetPrivate), parent, f | Qt::MSWindowsOwnDC)
4805{
4806 Q_D(QGLWidget);
4807 if (name)
4808 setObjectName(QString::fromAscii(name));
4809 setAttribute(Qt::WA_PaintOnScreen);
4810 setAttribute(Qt::WA_NoSystemBackground);
4811 setAutoFillBackground(true); // for compatibility
4812 d->init(new QGLContext(format, this), shareWidget);
4813}
4814
4815/*!
4816 \overload
4817 \obsolete
4818 */
4819QGLWidget::QGLWidget(QGLContext *context, QWidget *parent,
4820 const char *name, const QGLWidget *shareWidget, Qt::WindowFlags f)
4821 : QWidget(*(new QGLWidgetPrivate), parent, f | Qt::MSWindowsOwnDC)
4822{
4823 Q_D(QGLWidget);
4824 if (name)
4825 setObjectName(QString::fromAscii(name));
4826 setAttribute(Qt::WA_PaintOnScreen);
4827 setAttribute(Qt::WA_NoSystemBackground);
4828 setAutoFillBackground(true); // for compatibility
4829 d->init(context, shareWidget);
4830}
4831
4832#endif // QT3_SUPPORT
4833
4834void QGLExtensions::init_extensions()
4835{
4836 QGLExtensionMatcher extensions(reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS)));
4837
4838 if (extensions.match("GL_ARB_texture_rectangle"))
4839 glExtensions |= TextureRectangle;
4840 if (extensions.match("GL_ARB_multisample"))
4841 glExtensions |= SampleBuffers;
4842 if (extensions.match("GL_SGIS_generate_mipmap"))
4843 glExtensions |= GenerateMipmap;
4844 if (extensions.match("GL_ARB_texture_compression"))
4845 glExtensions |= TextureCompression;
4846 if (extensions.match("GL_EXT_texture_compression_s3tc"))
4847 glExtensions |= DDSTextureCompression;
4848 if (extensions.match("GL_OES_compressed_ETC1_RGB8_texture"))
4849 glExtensions |= ETC1TextureCompression;
4850 if (extensions.match("GL_IMG_texture_compression_pvrtc"))
4851 glExtensions |= PVRTCTextureCompression;
4852 if (extensions.match("GL_ARB_fragment_program"))
4853 glExtensions |= FragmentProgram;
4854 if (extensions.match("GL_ARB_fragment_shader"))
4855 glExtensions |= FragmentShader;
4856 if (extensions.match("GL_ARB_texture_mirrored_repeat"))
4857 glExtensions |= MirroredRepeat;
4858 if (extensions.match("GL_EXT_framebuffer_object"))
4859 glExtensions |= FramebufferObject;
4860 if (extensions.match("GL_EXT_stencil_two_side"))
4861 glExtensions |= StencilTwoSide;
4862 if (extensions.match("GL_EXT_stencil_wrap"))
4863 glExtensions |= StencilWrap;
4864 if (extensions.match("GL_EXT_packed_depth_stencil"))
4865 glExtensions |= PackedDepthStencil;
4866 if (extensions.match("GL_NV_float_buffer"))
4867 glExtensions |= NVFloatBuffer;
4868 if (extensions.match("GL_ARB_pixel_buffer_object"))
4869 glExtensions |= PixelBufferObject;
4870#if defined(QT_OPENGL_ES_2)
4871 glExtensions |= FramebufferObject;
4872 glExtensions |= GenerateMipmap;
4873 glExtensions |= FragmentShader;
4874#endif
4875#if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_1_CL)
4876 if (extensions.match("GL_OES_framebuffer_object"))
4877 glExtensions |= FramebufferObject;
4878#endif
4879#if defined(QT_OPENGL_ES)
4880 if (extensions.match("GL_OES_packed_depth_stencil"))
4881 glExtensions |= PackedDepthStencil;
4882#endif
4883 if (extensions.match("GL_ARB_framebuffer_object")) {
4884 // ARB_framebuffer_object also includes EXT_framebuffer_blit.
4885 glExtensions |= FramebufferObject;
4886 glExtensions |= FramebufferBlit;
4887 }
4888
4889 if (extensions.match("GL_EXT_framebuffer_blit"))
4890 glExtensions |= FramebufferBlit;
4891
4892 if (extensions.match("GL_ARB_texture_non_power_of_two"))
4893 glExtensions |= NPOTTextures;
4894
4895 if (extensions.match("GL_EXT_bgra"))
4896 glExtensions |= BGRATextureFormat;
4897}
4898
4899/*
4900 This is the shared initialization for all platforms. Called from QGLWidgetPrivate::init()
4901*/
4902void QGLWidgetPrivate::initContext(QGLContext *context, const QGLWidget* shareWidget)
4903{
4904 Q_Q(QGLWidget);
4905
4906 glDevice.setWidget(q);
4907
4908 QGLExtensions::init();
4909 glcx = 0;
4910 autoSwap = true;
4911
4912 if (context && !context->device())
4913 context->setDevice(q);
4914 q->setContext(context, shareWidget ? shareWidget->context() : 0);
4915
4916 if (!glcx)
4917 glcx = new QGLContext(QGLFormat::defaultFormat(), q);
4918
4919 q->setAttribute(Qt::WA_NoSystemBackground);
4920}
4921
4922#if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS)
4923Q_GLOBAL_STATIC(QString, qt_gl_lib_name)
4924
4925Q_OPENGL_EXPORT void qt_set_gl_library_name(const QString& name)
4926{
4927 qt_gl_lib_name()->operator=(name);
4928}
4929
4930Q_OPENGL_EXPORT const QString qt_gl_library_name()
4931{
4932 if (qt_gl_lib_name()->isNull()) {
4933#if defined(Q_WS_X11) || defined(Q_WS_QWS)
4934 return QLatin1String("GL");
4935#else // Q_WS_MAC
4936 return QLatin1String("/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib");
4937#endif
4938 }
4939 return *qt_gl_lib_name();
4940}
4941#endif
4942
4943void QGLShareRegister::addShare(const QGLContext *context, const QGLContext *share) {
4944 Q_ASSERT(context && share);
4945 if (context->d_ptr->group == share->d_ptr->group)
4946 return;
4947
4948 // Make sure 'context' is not already shared with another group of contexts.
4949 Q_ASSERT(context->d_ptr->group->m_refs == 1);
4950
4951 // Free 'context' group resources and make it use the same resources as 'share'.
4952 QGLContextGroup *group = share->d_ptr->group;
4953 delete context->d_ptr->group;
4954 context->d_ptr->group = group;
4955 group->m_refs.ref();
4956
4957 // Maintain a list of all the contexts in each group of sharing contexts.
4958 // The list is empty if the "share" context wasn't sharing already.
4959 if (group->m_shares.isEmpty())
4960 group->m_shares.append(share);
4961 group->m_shares.append(context);
4962}
4963
4964QList<const QGLContext *> QGLShareRegister::shares(const QGLContext *context) {
4965 return context->d_ptr->group->m_shares;
4966}
4967
4968void QGLShareRegister::removeShare(const QGLContext *context) {
4969 // Remove the context from the group.
4970 QGLContextGroup *group = context->d_ptr->group;
4971 if (group->m_shares.isEmpty())
4972 return;
4973 group->m_shares.removeAll(context);
4974
4975 // Update context group representative.
4976 Q_ASSERT(group->m_shares.size() != 0);
4977 if (group->m_context == context)
4978 group->m_context = group->m_shares[0];
4979
4980 // If there is only one context left, then make the list empty.
4981 if (group->m_shares.size() == 1)
4982 group->m_shares.clear();
4983}
4984
4985QGLContextResource::QGLContextResource(FreeFunc f)
4986 : free(f), active(0)
4987{
4988}
4989
4990QGLContextResource::~QGLContextResource()
4991{
4992#ifndef QT_NO_DEBUG
4993 if (active != 0) {
4994 qWarning("QtOpenGL: Resources are still available at program shutdown.\n"
4995 " This is possibly caused by a leaked QGLWidget, \n"
4996 " QGLFramebufferObject or QGLPixelBuffer.");
4997 }
4998#endif
4999}
5000
5001void QGLContextResource::insert(const QGLContext *key, void *value)
5002{
5003 QGLContextGroup *group = QGLContextPrivate::contextGroup(key);
5004 Q_ASSERT(!group->m_resources.contains(this));
5005 group->m_resources.insert(this, value);
5006 active.ref();
5007}
5008
5009void *QGLContextResource::value(const QGLContext *key)
5010{
5011 QGLContextGroup *group = QGLContextPrivate::contextGroup(key);
5012 return group->m_resources.value(this, 0);
5013}
5014
5015void QGLContextResource::cleanup(const QGLContext *ctx, void *value)
5016{
5017 QGLShareContextScope scope(ctx);
5018 free(value);
5019 active.deref();
5020}
5021
5022void QGLContextGroup::cleanupResources(const QGLContext *ctx)
5023{
5024 // If there are still shares, then no cleanup to be done yet.
5025 if (m_shares.size() > 1)
5026 return;
5027
5028 // Iterate over all resources and free each in turn.
5029 QHash<QGLContextResource *, void *>::ConstIterator it;
5030 for (it = m_resources.begin(); it != m_resources.end(); ++it)
5031 it.key()->cleanup(ctx, it.value());
5032}
5033
5034QGLSharedResourceGuard::~QGLSharedResourceGuard()
5035{
5036 if (m_group)
5037 m_group->removeGuard(this);
5038}
5039
5040void QGLSharedResourceGuard::setContext(const QGLContext *context)
5041{
5042 if (m_group)
5043 m_group->removeGuard(this);
5044 if (context) {
5045 m_group = QGLContextPrivate::contextGroup(context);
5046 m_group->addGuard(this);
5047 } else {
5048 m_group = 0;
5049 }
5050}
5051
5052QSize QGLTexture::bindCompressedTexture
5053 (const QString& fileName, const char *format)
5054{
5055 QFile file(fileName);
5056 if (!file.open(QIODevice::ReadOnly))
5057 return QSize();
5058 QByteArray contents = file.readAll();
5059 file.close();
5060 return bindCompressedTexture
5061 (contents.constData(), contents.size(), format);
5062}
5063
5064// PVR header format for container files that store textures compressed
5065// with the ETC1, PVRTC2, and PVRTC4 encodings. Format information from the
5066// PowerVR SDK at http://www.imgtec.com/powervr/insider/powervr-sdk.asp
5067// "PVRTexTool Reference Manual, version 1.11f".
5068struct PvrHeader
5069{
5070 quint32 headerSize;
5071 quint32 height;
5072 quint32 width;
5073 quint32 mipMapCount;
5074 quint32 flags;
5075 quint32 dataSize;
5076 quint32 bitsPerPixel;
5077 quint32 redMask;
5078 quint32 greenMask;
5079 quint32 blueMask;
5080 quint32 alphaMask;
5081 quint32 magic;
5082 quint32 surfaceCount;
5083};
5084
5085#define PVR_MAGIC 0x21525650 // "PVR!" in little-endian
5086
5087#define PVR_FORMAT_MASK 0x000000FF
5088#define PVR_FORMAT_PVRTC2 0x00000018
5089#define PVR_FORMAT_PVRTC4 0x00000019
5090#define PVR_FORMAT_ETC1 0x00000036
5091
5092#define PVR_HAS_MIPMAPS 0x00000100
5093#define PVR_TWIDDLED 0x00000200
5094#define PVR_NORMAL_MAP 0x00000400
5095#define PVR_BORDER_ADDED 0x00000800
5096#define PVR_CUBE_MAP 0x00001000
5097#define PVR_FALSE_COLOR_MIPMAPS 0x00002000
5098#define PVR_VOLUME_TEXTURE 0x00004000
5099#define PVR_ALPHA_IN_TEXTURE 0x00008000
5100#define PVR_VERTICAL_FLIP 0x00010000
5101
5102#ifndef GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
5103#define GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG 0x8C00
5104#define GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG 0x8C01
5105#define GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG 0x8C02
5106#define GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG 0x8C03
5107#endif
5108
5109#ifndef GL_ETC1_RGB8_OES
5110#define GL_ETC1_RGB8_OES 0x8D64
5111#endif
5112
5113bool QGLTexture::canBindCompressedTexture
5114 (const char *buf, int len, const char *format, bool *hasAlpha)
5115{
5116 if (QSysInfo::ByteOrder != QSysInfo::LittleEndian) {
5117 // Compressed texture loading only supported on little-endian
5118 // systems such as x86 and ARM at the moment.
5119 return false;
5120 }
5121 if (!format) {
5122 // Auto-detect the format from the header.
5123 if (len >= 4 && !qstrncmp(buf, "DDS ", 4)) {
5124 *hasAlpha = true;
5125 return true;
5126 } else if (len >= 52 && !qstrncmp(buf + 44, "PVR!", 4)) {
5127 const PvrHeader *pvrHeader =
5128 reinterpret_cast<const PvrHeader *>(buf);
5129 *hasAlpha = (pvrHeader->alphaMask != 0);
5130 return true;
5131 }
5132 } else {
5133 // Validate the format against the header.
5134 if (!qstricmp(format, "DDS")) {
5135 if (len >= 4 && !qstrncmp(buf, "DDS ", 4)) {
5136 *hasAlpha = true;
5137 return true;
5138 }
5139 } else if (!qstricmp(format, "PVR") || !qstricmp(format, "ETC1")) {
5140 if (len >= 52 && !qstrncmp(buf + 44, "PVR!", 4)) {
5141 const PvrHeader *pvrHeader =
5142 reinterpret_cast<const PvrHeader *>(buf);
5143 *hasAlpha = (pvrHeader->alphaMask != 0);
5144 return true;
5145 }
5146 }
5147 }
5148 return false;
5149}
5150
5151#define ctx QGLContext::currentContext()
5152
5153QSize QGLTexture::bindCompressedTexture
5154 (const char *buf, int len, const char *format)
5155{
5156 if (QSysInfo::ByteOrder != QSysInfo::LittleEndian) {
5157 // Compressed texture loading only supported on little-endian
5158 // systems such as x86 and ARM at the moment.
5159 return QSize();
5160 }
5161#if !defined(QT_OPENGL_ES)
5162 if (!glCompressedTexImage2D) {
5163 if (!(QGLExtensions::glExtensions & QGLExtensions::TextureCompression)) {
5164 qWarning("QGLContext::bindTexture(): The GL implementation does "
5165 "not support texture compression extensions.");
5166 return QSize();
5167 }
5168 glCompressedTexImage2D = (_glCompressedTexImage2DARB) ctx->getProcAddress(QLatin1String("glCompressedTexImage2DARB"));
5169 if (!glCompressedTexImage2D) {
5170 qWarning("QGLContext::bindTexture(): could not resolve "
5171 "glCompressedTexImage2DARB.");
5172 return QSize();
5173 }
5174 }
5175#endif
5176 if (!format) {
5177 // Auto-detect the format from the header.
5178 if (len >= 4 && !qstrncmp(buf, "DDS ", 4))
5179 return bindCompressedTextureDDS(buf, len);
5180 else if (len >= 52 && !qstrncmp(buf + 44, "PVR!", 4))
5181 return bindCompressedTexturePVR(buf, len);
5182 } else {
5183 // Validate the format against the header.
5184 if (!qstricmp(format, "DDS")) {
5185 if (len >= 4 && !qstrncmp(buf, "DDS ", 4))
5186 return bindCompressedTextureDDS(buf, len);
5187 } else if (!qstricmp(format, "PVR") || !qstricmp(format, "ETC1")) {
5188 if (len >= 52 && !qstrncmp(buf + 44, "PVR!", 4))
5189 return bindCompressedTexturePVR(buf, len);
5190 }
5191 }
5192 return QSize();
5193}
5194
5195QSize QGLTexture::bindCompressedTextureDDS(const char *buf, int len)
5196{
5197 // We only support 2D texture loading at present.
5198 if (target != GL_TEXTURE_2D)
5199 return QSize();
5200
5201 // Bail out if the necessary extension is not present.
5202 if (!(QGLExtensions::glExtensions & QGLExtensions::DDSTextureCompression)) {
5203 qWarning("QGLContext::bindTexture(): DDS texture compression is not supported.");
5204 return QSize();
5205 }
5206
5207 const DDSFormat *ddsHeader = reinterpret_cast<const DDSFormat *>(buf + 4);
5208 if (!ddsHeader->dwLinearSize) {
5209 qWarning("QGLContext::bindTexture(): DDS image size is not valid.");
5210 return QSize();
5211 }
5212
5213 int blockSize = 16;
5214 GLenum format;
5215
5216 switch(ddsHeader->ddsPixelFormat.dwFourCC) {
5217 case FOURCC_DXT1:
5218 format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
5219 blockSize = 8;
5220 break;
5221 case FOURCC_DXT3:
5222 format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
5223 break;
5224 case FOURCC_DXT5:
5225 format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
5226 break;
5227 default:
5228 qWarning("QGLContext::bindTexture(): DDS image format not supported.");
5229 return QSize();
5230 }
5231
5232 const GLubyte *pixels =
5233 reinterpret_cast<const GLubyte *>(buf + ddsHeader->dwSize + 4);
5234
5235 glGenTextures(1, &id);
5236 glBindTexture(GL_TEXTURE_2D, id);
5237 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
5238 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5239
5240 int size;
5241 int offset = 0;
5242 int available = len - int(ddsHeader->dwSize + 4);
5243 int w = ddsHeader->dwWidth;
5244 int h = ddsHeader->dwHeight;
5245
5246 // load mip-maps
5247 for(int i = 0; i < (int) ddsHeader->dwMipMapCount; ++i) {
5248 if (w == 0) w = 1;
5249 if (h == 0) h = 1;
5250
5251 size = ((w+3)/4) * ((h+3)/4) * blockSize;
5252 if (size > available)
5253 break;
5254 glCompressedTexImage2D(GL_TEXTURE_2D, i, format, w, h, 0,
5255 size, pixels + offset);
5256 offset += size;
5257 available -= size;
5258
5259 // half size for each mip-map level
5260 w = w/2;
5261 h = h/2;
5262 }
5263
5264 // DDS images are not inverted.
5265 options &= ~QGLContext::InvertedYBindOption;
5266
5267 return QSize(ddsHeader->dwWidth, ddsHeader->dwHeight);
5268}
5269
5270QSize QGLTexture::bindCompressedTexturePVR(const char *buf, int len)
5271{
5272 // We only support 2D texture loading at present. Cube maps later.
5273 if (target != GL_TEXTURE_2D)
5274 return QSize();
5275
5276 // Determine which texture format we will be loading.
5277 const PvrHeader *pvrHeader = reinterpret_cast<const PvrHeader *>(buf);
5278 GLenum textureFormat;
5279 quint32 minWidth, minHeight;
5280 switch (pvrHeader->flags & PVR_FORMAT_MASK) {
5281 case PVR_FORMAT_PVRTC2:
5282 if (pvrHeader->alphaMask)
5283 textureFormat = GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
5284 else
5285 textureFormat = GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
5286 minWidth = 16;
5287 minHeight = 8;
5288 break;
5289
5290 case PVR_FORMAT_PVRTC4:
5291 if (pvrHeader->alphaMask)
5292 textureFormat = GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
5293 else
5294 textureFormat = GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
5295 minWidth = 8;
5296 minHeight = 8;
5297 break;
5298
5299 case PVR_FORMAT_ETC1:
5300 textureFormat = GL_ETC1_RGB8_OES;
5301 minWidth = 4;
5302 minHeight = 4;
5303 break;
5304
5305 default:
5306 qWarning("QGLContext::bindTexture(): PVR image format 0x%x not supported.", int(pvrHeader->flags & PVR_FORMAT_MASK));
5307 return QSize();
5308 }
5309
5310 // Bail out if the necessary extension is not present.
5311 if (textureFormat == GL_ETC1_RGB8_OES) {
5312 if (!(QGLExtensions::glExtensions &
5313 QGLExtensions::ETC1TextureCompression)) {
5314 qWarning("QGLContext::bindTexture(): ETC1 texture compression is not supported.");
5315 return QSize();
5316 }
5317 } else {
5318 if (!(QGLExtensions::glExtensions &
5319 QGLExtensions::PVRTCTextureCompression)) {
5320 qWarning("QGLContext::bindTexture(): PVRTC texture compression is not supported.");
5321 return QSize();
5322 }
5323 }
5324
5325 // Boundary check on the buffer size.
5326 quint32 bufferSize = pvrHeader->headerSize + pvrHeader->dataSize;
5327 if (bufferSize > quint32(len)) {
5328 qWarning("QGLContext::bindTexture(): PVR image size is not valid.");
5329 return QSize();
5330 }
5331
5332 // Create the texture.
5333 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
5334 glGenTextures(1, &id);
5335 glBindTexture(GL_TEXTURE_2D, id);
5336 if (pvrHeader->mipMapCount) {
5337 if ((options & QGLContext::LinearFilteringBindOption) != 0) {
5338 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
5339 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
5340 } else {
5341 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5342 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
5343 }
5344 } else if ((options & QGLContext::LinearFilteringBindOption) != 0) {
5345 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
5346 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5347 } else {
5348 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5349 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5350 }
5351
5352 // Load the compressed mipmap levels.
5353 const GLubyte *buffer =
5354 reinterpret_cast<const GLubyte *>(buf + pvrHeader->headerSize);
5355 bufferSize = pvrHeader->dataSize;
5356 quint32 level = 0;
5357 quint32 width = pvrHeader->width;
5358 quint32 height = pvrHeader->height;
5359 while (bufferSize > 0 && level < pvrHeader->mipMapCount) {
5360 quint32 size =
5361 (qMax(width, minWidth) * qMax(height, minHeight) *
5362 pvrHeader->bitsPerPixel) / 8;
5363 if (size > bufferSize)
5364 break;
5365 glCompressedTexImage2D(GL_TEXTURE_2D, GLint(level), textureFormat,
5366 GLsizei(width), GLsizei(height), 0,
5367 GLsizei(size), buffer);
5368 width /= 2;
5369 height /= 2;
5370 buffer += size;
5371 ++level;
5372 }
5373
5374 // Restore the default pixel alignment for later texture uploads.
5375 glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
5376
5377 // Set the invert flag for the texture. The "vertical flip"
5378 // flag in PVR is the opposite sense to our sense of inversion.
5379 if ((pvrHeader->flags & PVR_VERTICAL_FLIP) != 0)
5380 options &= ~QGLContext::InvertedYBindOption;
5381 else
5382 options |= QGLContext::InvertedYBindOption;
5383
5384 return QSize(pvrHeader->width, pvrHeader->height);
5385}
5386
5387#undef ctx
5388
5389QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.