1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtOpenGL module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "qapplication.h"
43 #include "qplatformdefs.h"
46 #include <qglfunctions.h>
49 #include "private/qt_x11_p.h"
50 #include "private/qpixmap_x11_p.h"
51 #define INT32 dummy_INT32
52 #define INT8 dummy_INT8
58 #include "qx11info_x11.h"
59 #elif defined(Q_WS_MAC)
60 # include <private/qt_mac_p.h>
63 #include <qdatetime.h>
65 #include <stdlib.h> // malloc
71 #if !defined(QT_OPENGL_ES_1)
72 #include "gl2paintengineex/qpaintengineex_opengl2_p.h"
73 #include <private/qwindowsurface_gl_p.h>
76 #ifndef QT_OPENGL_ES_2
77 #include <private/qpaintengine_opengl_p.h>
81 #include <private/qglwindowsurface_qws_p.h>
85 #include <QtGui/QPlatformGLContext>
88 #include <qglpixelbuffer.h>
89 #include <qglframebufferobject.h>
91 #include <private/qimage_p.h>
92 #include <private/qpixmapdata_p.h>
93 #include <private/qpixmapdata_gl_p.h>
94 #include <private/qglpixelbuffer_p.h>
95 #include <private/qimagepixmapcleanuphooks_p.h>
96 #include "qcolormap.h"
101 #if defined(QT_OPENGL_ES) && !defined(QT_NO_EGL)
104 #ifdef QGL_USE_TEXTURE_POOL
105 #include <private/qgltexturepool_p.h>
108 // #define QT_GL_CONTEXT_RESOURCE_DEBUG
112 #if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_SYMBIAN)
113 QGLExtensionFuncs QGLContextPrivate::qt_extensionFuncs;
117 extern const QX11Info *qt_x11Info(const QPaintDevice *pd);
120 struct QGLThreadContext {
121 ~QGLThreadContext() {
123 context->doneCurrent();
129 static QThreadStorage<QGLThreadContext *> qgl_context_storage;
132 Q_GLOBAL_STATIC(QGLFormat, qgl_default_format)
134 class QGLDefaultOverlayFormat: public QGLFormat
137 inline QGLDefaultOverlayFormat()
139 setOption(QGL::FormatOption(0xffff << 16)); // turn off all options
140 setOption(QGL::DirectRendering);
144 Q_GLOBAL_STATIC(QGLDefaultOverlayFormat, defaultOverlayFormatInstance)
146 Q_GLOBAL_STATIC(QGLSignalProxy, theSignalProxy)
147 QGLSignalProxy *QGLSignalProxy::instance()
149 QGLSignalProxy *proxy = theSignalProxy();
150 if (proxy && proxy->thread() != qApp->thread()) {
151 if (proxy->thread() == QThread::currentThread())
152 proxy->moveToThread(qApp->thread());
158 class QGLEngineSelector
161 QGLEngineSelector() : engineType(QPaintEngine::MaxUser)
165 void setPreferredPaintEngine(QPaintEngine::Type type) {
166 if (type == QPaintEngine::OpenGL || type == QPaintEngine::OpenGL2)
170 QPaintEngine::Type preferredPaintEngine() {
172 // The ATI X1600 driver for Mac OS X does not support return
173 // values from functions in GLSL. Since working around this in
174 // the GL2 engine would require a big, ugly rewrite, we're
175 // falling back to the GL 1 engine..
176 static bool mac_x1600_check_done = false;
177 if (!mac_x1600_check_done) {
178 QGLTemporaryContext *tmp = 0;
179 if (!QGLContext::currentContext())
180 tmp = new QGLTemporaryContext();
181 if (strstr((char *) glGetString(GL_RENDERER), "X1600"))
182 engineType = QPaintEngine::OpenGL;
185 mac_x1600_check_done = true;
188 if (engineType == QPaintEngine::MaxUser) {
189 // No user-set engine - use the defaults
190 #if defined(QT_OPENGL_ES_2)
191 engineType = QPaintEngine::OpenGL2;
193 // We can't do this in the constructor for this object because it
194 // needs to be called *before* the QApplication constructor.
195 // Also check for the FragmentShader extension in conjunction with
196 // the 2.0 version flag, to cover the case where we export the display
197 // from an old GL 1.1 server to a GL 2.x client. In that case we can't
199 if ((QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_2_0)
200 && (QGLExtensions::glExtensions() & QGLExtensions::FragmentShader)
201 && qgetenv("QT_GL_USE_OPENGL1ENGINE").isEmpty())
202 engineType = QPaintEngine::OpenGL2;
204 engineType = QPaintEngine::OpenGL;
211 QPaintEngine::Type engineType;
214 Q_GLOBAL_STATIC(QGLEngineSelector, qgl_engine_selector)
217 bool qt_gl_preferGL2Engine()
219 return qgl_engine_selector()->preferredPaintEngine() == QPaintEngine::OpenGL2;
227 \brief The QGL namespace specifies miscellaneous identifiers used
228 in the Qt OpenGL module.
234 \enum QGL::FormatOption
236 This enum specifies the format options that can be used to configure an OpenGL
237 context. These are set using QGLFormat::setOption().
239 \value DoubleBuffer Specifies the use of double buffering.
240 \value DepthBuffer Enables the use of a depth buffer.
241 \value Rgba Specifies that the context should use RGBA as its pixel format.
242 \value AlphaChannel Enables the use of an alpha channel.
243 \value AccumBuffer Enables the use of an accumulation buffer.
244 \value StencilBuffer Enables the use of a stencil buffer.
245 \value StereoBuffers Enables the use of a stereo buffers for use with visualization hardware.
246 \value DirectRendering Specifies that the context is used for direct rendering to a display.
247 \value HasOverlay Enables the use of an overlay.
248 \value SampleBuffers Enables the use of sample buffers.
249 \value DeprecatedFunctions Enables the use of deprecated functionality for OpenGL 3.x
250 contexts. A context with deprecated functionality enabled is
251 called a full context in the OpenGL specification.
252 \value SingleBuffer Specifies the use of a single buffer, as opposed to double buffers.
253 \value NoDepthBuffer Disables the use of a depth buffer.
254 \value ColorIndex Specifies that the context should use a color index as its pixel format.
255 \value NoAlphaChannel Disables the use of an alpha channel.
256 \value NoAccumBuffer Disables the use of an accumulation buffer.
257 \value NoStencilBuffer Disables the use of a stencil buffer.
258 \value NoStereoBuffers Disables the use of stereo buffers.
259 \value IndirectRendering Specifies that the context is used for indirect rendering to a buffer.
260 \value NoOverlay Disables the use of an overlay.
261 \value NoSampleBuffers Disables the use of sample buffers.
262 \value NoDeprecatedFunctions Disables the use of deprecated functionality for OpenGL 3.x
263 contexts. A context with deprecated functionality disabled is
264 called a forward compatible context in the OpenGL specification.
266 \sa {Sample Buffers Example}
270 \fn void QGL::setPreferredPaintEngine(QPaintEngine::Type engineType)
274 Sets the preferred OpenGL paint engine that is used to draw onto
275 QGLWidget, QGLPixelBuffer and QGLFramebufferObject targets with QPainter
278 The \a engineType parameter specifies which of the GL engines to
279 use. Only \c QPaintEngine::OpenGL and \c QPaintEngine::OpenGL2 are
280 valid parameters to this function. All other values are ignored.
282 By default, the \c QPaintEngine::OpenGL2 engine is used if GL/GLES
283 version 2.0 is available, otherwise \c QPaintEngine::OpenGL is
286 \warning This function must be called before the QApplication
287 constructor is called.
289 void QGL::setPreferredPaintEngine(QPaintEngine::Type engineType)
291 qgl_engine_selector()->setPreferredPaintEngine(engineType);
295 /*****************************************************************************
296 QGLFormat implementation
297 *****************************************************************************/
302 \brief The QGLFormat class specifies the display format of an OpenGL
307 A display format has several characteristics:
309 \i \link setDoubleBuffer() Double or single buffering.\endlink
310 \i \link setDepth() Depth buffer.\endlink
311 \i \link setRgba() RGBA or color index mode.\endlink
312 \i \link setAlpha() Alpha channel.\endlink
313 \i \link setAccum() Accumulation buffer.\endlink
314 \i \link setStencil() Stencil buffer.\endlink
315 \i \link setStereo() Stereo buffers.\endlink
316 \i \link setDirectRendering() Direct rendering.\endlink
317 \i \link setOverlay() Presence of an overlay.\endlink
318 \i \link setPlane() Plane of an overlay.\endlink
319 \i \link setSampleBuffers() Multisample buffers.\endlink
322 You can also specify preferred bit depths for the color buffer,
323 depth buffer, alpha buffer, accumulation buffer and the stencil
324 buffer with the functions: setRedBufferSize(), setGreenBufferSize(),
325 setBlueBufferSize(), setDepthBufferSize(), setAlphaBufferSize(),
326 setAccumBufferSize() and setStencilBufferSize().
328 Note that even if you specify that you prefer a 32 bit depth
329 buffer (e.g. with setDepthBufferSize(32)), the format that is
330 chosen may not have a 32 bit depth buffer, even if there is a
331 format available with a 32 bit depth buffer. The main reason for
332 this is how the system dependant picking algorithms work on the
333 different platforms, and some format options may have higher
334 precedence than others.
336 You create and tell a QGLFormat object what rendering options you
337 want from an OpenGL rendering context.
339 OpenGL drivers or accelerated hardware may or may not support
340 advanced features such as alpha channel or stereographic viewing.
341 If you request some features that the driver/hardware does not
342 provide when you create a QGLWidget, you will get a rendering
343 context with the nearest subset of features.
345 There are different ways to define the display characteristics of
346 a rendering context. One is to create a QGLFormat and make it the
347 default for the entire application:
348 \snippet doc/src/snippets/code/src_opengl_qgl.cpp 0
350 Or you can specify the desired format when creating an object of
351 your QGLWidget subclass:
352 \snippet doc/src/snippets/code/src_opengl_qgl.cpp 1
354 After the widget has been created, you can find out which of the
355 requested features the system was able to provide:
356 \snippet doc/src/snippets/code/src_opengl_qgl.cpp 2
359 OpenGL is a trademark of Silicon Graphics, Inc. in the
360 United States and other countries.
363 \sa QGLContext, QGLWidget
368 static inline void transform_point(GLdouble out[4], const GLdouble m[16], const GLdouble in[4])
370 #define M(row,col) m[col*4+row]
372 M(0, 0) * in[0] + M(0, 1) * in[1] + M(0, 2) * in[2] + M(0, 3) * in[3];
374 M(1, 0) * in[0] + M(1, 1) * in[1] + M(1, 2) * in[2] + M(1, 3) * in[3];
376 M(2, 0) * in[0] + M(2, 1) * in[1] + M(2, 2) * in[2] + M(2, 3) * in[3];
378 M(3, 0) * in[0] + M(3, 1) * in[1] + M(3, 2) * in[2] + M(3, 3) * in[3];
382 static inline GLint qgluProject(GLdouble objx, GLdouble objy, GLdouble objz,
383 const GLdouble model[16], const GLdouble proj[16],
384 const GLint viewport[4],
385 GLdouble * winx, GLdouble * winy, GLdouble * winz)
387 GLdouble in[4], out[4];
393 transform_point(out, model, in);
394 transform_point(in, proj, out);
403 *winx = viewport[0] + (1 + in[0]) * viewport[2] / 2;
404 *winy = viewport[1] + (1 + in[1]) * viewport[3] / 2;
406 *winz = (1 + in[2]) / 2;
410 #endif // !QT_OPENGL_ES
413 Constructs a QGLFormat object with the following default settings:
415 \i \link setDoubleBuffer() Double buffer:\endlink Enabled.
416 \i \link setDepth() Depth buffer:\endlink Enabled.
417 \i \link setRgba() RGBA:\endlink Enabled (i.e., color index disabled).
418 \i \link setAlpha() Alpha channel:\endlink Disabled.
419 \i \link setAccum() Accumulator buffer:\endlink Disabled.
420 \i \link setStencil() Stencil buffer:\endlink Enabled.
421 \i \link setStereo() Stereo:\endlink Disabled.
422 \i \link setDirectRendering() Direct rendering:\endlink Enabled.
423 \i \link setOverlay() Overlay:\endlink Disabled.
424 \i \link setPlane() Plane:\endlink 0 (i.e., normal plane).
425 \i \link setSampleBuffers() Multisample buffers:\endlink Disabled.
429 QGLFormat::QGLFormat()
431 d = new QGLFormatPrivate;
436 Creates a QGLFormat object that is a copy of the current
439 If \a options is not 0, the default format is modified by the
440 specified format options. The \a options parameter should be
441 QGL::FormatOption values OR'ed together.
443 This constructor makes it easy to specify a certain desired format
444 in classes derived from QGLWidget, for example:
445 \snippet doc/src/snippets/code/src_opengl_qgl.cpp 3
447 Note that there are QGL::FormatOption values to turn format settings
448 both on and off, e.g. QGL::DepthBuffer and QGL::NoDepthBuffer,
449 QGL::DirectRendering and QGL::IndirectRendering, etc.
451 The \a plane parameter defaults to 0 and is the plane which this
452 format should be associated with. Not all OpenGL implementations
453 supports overlay/underlay rendering planes.
455 \sa defaultFormat(), setOption(), setPlane()
458 QGLFormat::QGLFormat(QGL::FormatOptions options, int plane)
460 d = new QGLFormatPrivate;
461 QGL::FormatOptions newOpts = options;
462 d->opts = defaultFormat().d->opts;
463 d->opts |= (newOpts & 0xffff);
464 d->opts &= ~(newOpts >> 16);
471 void QGLFormat::detach()
474 QGLFormatPrivate *newd = new QGLFormatPrivate(d);
482 Constructs a copy of \a other.
485 QGLFormat::QGLFormat(const QGLFormat &other)
492 Assigns \a other to this object.
495 QGLFormat &QGLFormat::operator=(const QGLFormat &other)
507 Destroys the QGLFormat.
509 QGLFormat::~QGLFormat()
516 \fn bool QGLFormat::doubleBuffer() const
518 Returns true if double buffering is enabled; otherwise returns
519 false. Double buffering is enabled by default.
521 \sa setDoubleBuffer()
525 If \a enable is true sets double buffering; otherwise sets single
528 Double buffering is enabled by default.
530 Double buffering is a technique where graphics are rendered on an
531 off-screen buffer and not directly to the screen. When the drawing
532 has been completed, the program calls a swapBuffers() function to
533 exchange the screen contents with the buffer. The result is
534 flicker-free drawing and often better performance.
536 Note that single buffered contexts are currently not supported
539 \sa doubleBuffer(), QGLContext::swapBuffers(),
540 QGLWidget::swapBuffers()
543 void QGLFormat::setDoubleBuffer(bool enable)
545 setOption(enable ? QGL::DoubleBuffer : QGL::SingleBuffer);
550 \fn bool QGLFormat::depth() const
552 Returns true if the depth buffer is enabled; otherwise returns
553 false. The depth buffer is enabled by default.
555 \sa setDepth(), setDepthBufferSize()
559 If \a enable is true enables the depth buffer; otherwise disables
562 The depth buffer is enabled by default.
564 The purpose of a depth buffer (or Z-buffering) is to remove hidden
565 surfaces. Pixels are assigned Z values based on the distance to
566 the viewer. A pixel with a high Z value is closer to the viewer
567 than a pixel with a low Z value. This information is used to
568 decide whether to draw a pixel or not.
570 \sa depth(), setDepthBufferSize()
573 void QGLFormat::setDepth(bool enable)
575 setOption(enable ? QGL::DepthBuffer : QGL::NoDepthBuffer);
580 \fn bool QGLFormat::rgba() const
582 Returns true if RGBA color mode is set. Returns false if color
583 index mode is set. The default color mode is RGBA.
589 If \a enable is true sets RGBA mode. If \a enable is false sets
592 The default color mode is RGBA.
594 RGBA is the preferred mode for most OpenGL applications. In RGBA
595 color mode you specify colors as red + green + blue + alpha
598 In color index mode you specify an index into a color lookup
604 void QGLFormat::setRgba(bool enable)
606 setOption(enable ? QGL::Rgba : QGL::ColorIndex);
611 \fn bool QGLFormat::alpha() const
613 Returns true if the alpha buffer in the framebuffer is enabled;
614 otherwise returns false. The alpha buffer is disabled by default.
616 \sa setAlpha(), setAlphaBufferSize()
620 If \a enable is true enables the alpha buffer; otherwise disables
623 The alpha buffer is disabled by default.
625 The alpha buffer is typically used for implementing transparency
626 or translucency. The A in RGBA specifies the transparency of a
629 \sa alpha(), setAlphaBufferSize()
632 void QGLFormat::setAlpha(bool enable)
634 setOption(enable ? QGL::AlphaChannel : QGL::NoAlphaChannel);
639 \fn bool QGLFormat::accum() const
641 Returns true if the accumulation buffer is enabled; otherwise
642 returns false. The accumulation buffer is disabled by default.
644 \sa setAccum(), setAccumBufferSize()
648 If \a enable is true enables the accumulation buffer; otherwise
649 disables the accumulation buffer.
651 The accumulation buffer is disabled by default.
653 The accumulation buffer is used to create blur effects and
656 \sa accum(), setAccumBufferSize()
659 void QGLFormat::setAccum(bool enable)
661 setOption(enable ? QGL::AccumBuffer : QGL::NoAccumBuffer);
666 \fn bool QGLFormat::stencil() const
668 Returns true if the stencil buffer is enabled; otherwise returns
669 false. The stencil buffer is enabled by default.
671 \sa setStencil(), setStencilBufferSize()
675 If \a enable is true enables the stencil buffer; otherwise
676 disables the stencil buffer.
678 The stencil buffer is enabled by default.
680 The stencil buffer masks certain parts of the drawing area so that
681 masked parts are not drawn on.
683 \sa stencil(), setStencilBufferSize()
686 void QGLFormat::setStencil(bool enable)
688 setOption(enable ? QGL::StencilBuffer: QGL::NoStencilBuffer);
693 \fn bool QGLFormat::stereo() const
695 Returns true if stereo buffering is enabled; otherwise returns
696 false. Stereo buffering is disabled by default.
702 If \a enable is true enables stereo buffering; otherwise disables
705 Stereo buffering is disabled by default.
707 Stereo buffering provides extra color buffers to generate left-eye
708 and right-eye images.
713 void QGLFormat::setStereo(bool enable)
715 setOption(enable ? QGL::StereoBuffers : QGL::NoStereoBuffers);
720 \fn bool QGLFormat::directRendering() const
722 Returns true if direct rendering is enabled; otherwise returns
725 Direct rendering is enabled by default.
727 \sa setDirectRendering()
731 If \a enable is true enables direct rendering; otherwise disables
734 Direct rendering is enabled by default.
736 Enabling this option will make OpenGL bypass the underlying window
737 system and render directly from hardware to the screen, if this is
738 supported by the system.
740 \sa directRendering()
743 void QGLFormat::setDirectRendering(bool enable)
745 setOption(enable ? QGL::DirectRendering : QGL::IndirectRendering);
749 \fn bool QGLFormat::sampleBuffers() const
751 Returns true if multisample buffer support is enabled; otherwise
754 The multisample buffer is disabled by default.
756 \sa setSampleBuffers()
760 If \a enable is true, a GL context with multisample buffer support
761 is picked; otherwise ignored.
763 \sa sampleBuffers(), setSamples(), samples()
765 void QGLFormat::setSampleBuffers(bool enable)
767 setOption(enable ? QGL::SampleBuffers : QGL::NoSampleBuffers);
771 Returns the number of samples per pixel when multisampling is
772 enabled. By default, the highest number of samples that is
775 \sa setSampleBuffers(), sampleBuffers(), setSamples()
777 int QGLFormat::samples() const
779 return d->numSamples;
783 Set the preferred number of samples per pixel when multisampling
784 is enabled to \a numSamples. By default, the highest number of
785 samples available is used.
787 \sa setSampleBuffers(), sampleBuffers(), samples()
789 void QGLFormat::setSamples(int numSamples)
792 if (numSamples < 0) {
793 qWarning("QGLFormat::setSamples: Cannot have negative number of samples per pixel %d", numSamples);
796 d->numSamples = numSamples;
797 setSampleBuffers(numSamples > 0);
803 Set the preferred swap interval. This can be used to sync the GL
804 drawing into a system window to the vertical refresh of the screen.
805 Setting an \a interval value of 0 will turn the vertical refresh syncing
806 off, any value higher than 0 will turn the vertical syncing on.
808 Under Windows and under X11, where the \c{WGL_EXT_swap_control}
809 and \c{GLX_SGI_video_sync} extensions are used, the \a interval
810 parameter can be used to set the minimum number of video frames
811 that are displayed before a buffer swap will occur. In effect,
812 setting the \a interval to 10, means there will be 10 vertical
813 retraces between every buffer swap.
815 Under Windows the \c{WGL_EXT_swap_control} extension has to be present,
816 and under X11 the \c{GLX_SGI_video_sync} extension has to be present.
818 void QGLFormat::setSwapInterval(int interval)
821 d->swapInterval = interval;
827 Returns the currently set swap interval. -1 is returned if setting
828 the swap interval isn't supported in the system GL implementation.
830 int QGLFormat::swapInterval() const
832 return d->swapInterval;
836 \fn bool QGLFormat::hasOverlay() const
838 Returns true if overlay plane is enabled; otherwise returns false.
840 Overlay is disabled by default.
846 If \a enable is true enables an overlay plane; otherwise disables
849 Enabling the overlay plane will cause QGLWidget to create an
850 additional context in an overlay plane. See the QGLWidget
851 documentation for further information.
856 void QGLFormat::setOverlay(bool enable)
858 setOption(enable ? QGL::HasOverlay : QGL::NoOverlay);
862 Returns the plane of this format. The default for normal formats
863 is 0, which means the normal plane. The default for overlay
864 formats is 1, which is the first overlay plane.
866 \sa setPlane(), defaultOverlayFormat()
868 int QGLFormat::plane() const
874 Sets the requested plane to \a plane. 0 is the normal plane, 1 is
875 the first overlay plane, 2 is the second overlay plane, etc.; -1,
876 -2, etc. are underlay planes.
878 Note that in contrast to other format specifications, the plane
879 specifications will be matched exactly. This means that if you
880 specify a plane that the underlying OpenGL system cannot provide,
881 an \link QGLWidget::isValid() invalid\endlink QGLWidget will be
886 void QGLFormat::setPlane(int plane)
893 Sets the format option to \a opt.
898 void QGLFormat::setOption(QGL::FormatOptions opt)
904 d->opts &= ~(opt >> 16);
910 Returns true if format option \a opt is set; otherwise returns false.
915 bool QGLFormat::testOption(QGL::FormatOptions opt) const
918 return (d->opts & opt) != 0;
920 return (d->opts & (opt >> 16)) == 0;
924 Set the minimum depth buffer size to \a size.
926 \sa depthBufferSize(), setDepth(), depth()
928 void QGLFormat::setDepthBufferSize(int size)
932 qWarning("QGLFormat::setDepthBufferSize: Cannot set negative depth buffer size %d", size);
940 Returns the depth buffer size.
942 \sa depth(), setDepth(), setDepthBufferSize()
944 int QGLFormat::depthBufferSize() const
952 Set the preferred red buffer size to \a size.
954 \sa setGreenBufferSize(), setBlueBufferSize(), setAlphaBufferSize()
956 void QGLFormat::setRedBufferSize(int size)
960 qWarning("QGLFormat::setRedBufferSize: Cannot set negative red buffer size %d", size);
969 Returns the red buffer size.
971 \sa setRedBufferSize()
973 int QGLFormat::redBufferSize() const
981 Set the preferred green buffer size to \a size.
983 \sa setRedBufferSize(), setBlueBufferSize(), setAlphaBufferSize()
985 void QGLFormat::setGreenBufferSize(int size)
989 qWarning("QGLFormat::setGreenBufferSize: Cannot set negative green buffer size %d", size);
998 Returns the green buffer size.
1000 \sa setGreenBufferSize()
1002 int QGLFormat::greenBufferSize() const
1004 return d->greenSize;
1010 Set the preferred blue buffer size to \a size.
1012 \sa setRedBufferSize(), setGreenBufferSize(), setAlphaBufferSize()
1014 void QGLFormat::setBlueBufferSize(int size)
1018 qWarning("QGLFormat::setBlueBufferSize: Cannot set negative blue buffer size %d", size);
1027 Returns the blue buffer size.
1029 \sa setBlueBufferSize()
1031 int QGLFormat::blueBufferSize() const
1037 Set the preferred alpha buffer size to \a size.
1038 This function implicitly enables the alpha channel.
1040 \sa setRedBufferSize(), setGreenBufferSize(), alphaBufferSize()
1042 void QGLFormat::setAlphaBufferSize(int size)
1046 qWarning("QGLFormat::setAlphaBufferSize: Cannot set negative alpha buffer size %d", size);
1049 d->alphaSize = size;
1054 Returns the alpha buffer size.
1056 \sa alpha(), setAlpha(), setAlphaBufferSize()
1058 int QGLFormat::alphaBufferSize() const
1060 return d->alphaSize;
1064 Set the preferred accumulation buffer size, where \a size is the
1065 bit depth for each RGBA component.
1067 \sa accum(), setAccum(), accumBufferSize()
1069 void QGLFormat::setAccumBufferSize(int size)
1073 qWarning("QGLFormat::setAccumBufferSize: Cannot set negative accumulate buffer size %d", size);
1076 d->accumSize = size;
1081 Returns the accumulation buffer size.
1083 \sa setAccumBufferSize(), accum(), setAccum()
1085 int QGLFormat::accumBufferSize() const
1087 return d->accumSize;
1091 Set the preferred stencil buffer size to \a size.
1093 \sa stencilBufferSize(), setStencil(), stencil()
1095 void QGLFormat::setStencilBufferSize(int size)
1099 qWarning("QGLFormat::setStencilBufferSize: Cannot set negative stencil buffer size %d", size);
1102 d->stencilSize = size;
1103 setStencil(size > 0);
1107 Returns the stencil buffer size.
1109 \sa stencil(), setStencil(), setStencilBufferSize()
1111 int QGLFormat::stencilBufferSize() const
1113 return d->stencilSize;
1119 Set the OpenGL version to the \a major and \a minor numbers. If a
1120 context compatible with the requested OpenGL version cannot be
1121 created, a context compatible with version 1.x is created instead.
1123 \sa majorVersion(), minorVersion()
1125 void QGLFormat::setVersion(int major, int minor)
1127 if (major < 1 || minor < 0) {
1128 qWarning("QGLFormat::setVersion: Cannot set zero or negative version number %d.%d", major, minor);
1132 d->majorVersion = major;
1133 d->minorVersion = minor;
1139 Returns the OpenGL major version.
1141 \sa setVersion(), minorVersion()
1143 int QGLFormat::majorVersion() const
1145 return d->majorVersion;
1151 Returns the OpenGL minor version.
1153 \sa setVersion(), majorVersion()
1155 int QGLFormat::minorVersion() const
1157 return d->minorVersion;
1161 \enum QGLFormat::OpenGLContextProfile
1164 This enum describes the OpenGL context profiles that can be
1165 specified for contexts implementing OpenGL version 3.2 or
1166 higher. These profiles are different from OpenGL ES profiles.
1168 \value NoProfile OpenGL version is lower than 3.2.
1169 \value CoreProfile Functionality deprecated in OpenGL version 3.0 is not available.
1170 \value CompatibilityProfile Functionality from earlier OpenGL versions is available.
1176 Set the OpenGL context profile to \a profile. The \a profile is
1177 ignored if the requested OpenGL version is less than 3.2.
1181 void QGLFormat::setProfile(OpenGLContextProfile profile)
1184 d->profile = profile;
1190 Returns the OpenGL context profile.
1194 QGLFormat::OpenGLContextProfile QGLFormat::profile() const
1201 \fn bool QGLFormat::hasOpenGL()
1203 Returns true if the window system has any OpenGL support;
1204 otherwise returns false.
1206 \warning This function must not be called until the QApplication
1207 object has been created.
1213 \fn bool QGLFormat::hasOpenGLOverlays()
1215 Returns true if the window system supports OpenGL overlays;
1216 otherwise returns false.
1218 \warning This function must not be called until the QApplication
1219 object has been created.
1222 QGLFormat::OpenGLVersionFlags Q_AUTOTEST_EXPORT qOpenGLVersionFlagsFromString(const QString &versionString)
1224 QGLFormat::OpenGLVersionFlags versionFlags = QGLFormat::OpenGL_Version_None;
1226 if (versionString.startsWith(QLatin1String("OpenGL ES"))) {
1227 QStringList parts = versionString.split(QLatin1Char(' '));
1228 if (parts.size() >= 3) {
1229 if (parts[2].startsWith(QLatin1String("1."))) {
1230 if (parts[1].endsWith(QLatin1String("-CM"))) {
1231 versionFlags |= QGLFormat::OpenGL_ES_Common_Version_1_0 |
1232 QGLFormat::OpenGL_ES_CommonLite_Version_1_0;
1233 if (parts[2].startsWith(QLatin1String("1.1")))
1234 versionFlags |= QGLFormat::OpenGL_ES_Common_Version_1_1 |
1235 QGLFormat::OpenGL_ES_CommonLite_Version_1_1;
1237 // Not -CM, must be CL, CommonLite
1238 versionFlags |= QGLFormat::OpenGL_ES_CommonLite_Version_1_0;
1239 if (parts[2].startsWith(QLatin1String("1.1")))
1240 versionFlags |= QGLFormat::OpenGL_ES_CommonLite_Version_1_1;
1243 // OpenGL ES version 2.0 or higher
1244 versionFlags |= QGLFormat::OpenGL_ES_Version_2_0;
1247 // if < 3 parts to the name, it is an unrecognised OpenGL ES
1248 qWarning("Unrecognised OpenGL ES version");
1251 // not ES, regular OpenGL, the version numbers are first in the string
1252 if (versionString.startsWith(QLatin1String("1."))) {
1253 switch (versionString[2].toAscii()) {
1255 versionFlags |= QGLFormat::OpenGL_Version_1_5;
1257 versionFlags |= QGLFormat::OpenGL_Version_1_4;
1259 versionFlags |= QGLFormat::OpenGL_Version_1_3;
1261 versionFlags |= QGLFormat::OpenGL_Version_1_2;
1263 versionFlags |= QGLFormat::OpenGL_Version_1_1;
1267 } else if (versionString.startsWith(QLatin1String("2."))) {
1268 versionFlags |= QGLFormat::OpenGL_Version_1_1 |
1269 QGLFormat::OpenGL_Version_1_2 |
1270 QGLFormat::OpenGL_Version_1_3 |
1271 QGLFormat::OpenGL_Version_1_4 |
1272 QGLFormat::OpenGL_Version_1_5 |
1273 QGLFormat::OpenGL_Version_2_0;
1274 if (versionString[2].toAscii() == '1')
1275 versionFlags |= QGLFormat::OpenGL_Version_2_1;
1276 } else if (versionString.startsWith(QLatin1String("3."))) {
1277 versionFlags |= QGLFormat::OpenGL_Version_1_1 |
1278 QGLFormat::OpenGL_Version_1_2 |
1279 QGLFormat::OpenGL_Version_1_3 |
1280 QGLFormat::OpenGL_Version_1_4 |
1281 QGLFormat::OpenGL_Version_1_5 |
1282 QGLFormat::OpenGL_Version_2_0 |
1283 QGLFormat::OpenGL_Version_2_1 |
1284 QGLFormat::OpenGL_Version_3_0;
1285 switch (versionString[2].toAscii()) {
1287 versionFlags |= QGLFormat::OpenGL_Version_3_3;
1289 versionFlags |= QGLFormat::OpenGL_Version_3_2;
1291 versionFlags |= QGLFormat::OpenGL_Version_3_1;
1295 versionFlags |= QGLFormat::OpenGL_Version_3_1 |
1296 QGLFormat::OpenGL_Version_3_2 |
1297 QGLFormat::OpenGL_Version_3_3;
1300 } else if (versionString.startsWith(QLatin1String("4."))) {
1301 versionFlags |= QGLFormat::OpenGL_Version_1_1 |
1302 QGLFormat::OpenGL_Version_1_2 |
1303 QGLFormat::OpenGL_Version_1_3 |
1304 QGLFormat::OpenGL_Version_1_4 |
1305 QGLFormat::OpenGL_Version_1_5 |
1306 QGLFormat::OpenGL_Version_2_0 |
1307 QGLFormat::OpenGL_Version_2_1 |
1308 QGLFormat::OpenGL_Version_3_0 |
1309 QGLFormat::OpenGL_Version_3_1 |
1310 QGLFormat::OpenGL_Version_3_2 |
1311 QGLFormat::OpenGL_Version_3_3 |
1312 QGLFormat::OpenGL_Version_4_0;
1314 versionFlags |= QGLFormat::OpenGL_Version_1_1 |
1315 QGLFormat::OpenGL_Version_1_2 |
1316 QGLFormat::OpenGL_Version_1_3 |
1317 QGLFormat::OpenGL_Version_1_4 |
1318 QGLFormat::OpenGL_Version_1_5 |
1319 QGLFormat::OpenGL_Version_2_0 |
1320 QGLFormat::OpenGL_Version_2_1 |
1321 QGLFormat::OpenGL_Version_3_0 |
1322 QGLFormat::OpenGL_Version_3_1 |
1323 QGLFormat::OpenGL_Version_3_2 |
1324 QGLFormat::OpenGL_Version_3_3 |
1325 QGLFormat::OpenGL_Version_4_0;
1328 return versionFlags;
1332 \enum QGLFormat::OpenGLVersionFlag
1335 This enum describes the various OpenGL versions that are
1336 recognized by Qt. Use the QGLFormat::openGLVersionFlags() function
1337 to identify which versions that are supported at runtime.
1339 \value OpenGL_Version_None If no OpenGL is present or if no OpenGL context is current.
1341 \value OpenGL_Version_1_1 OpenGL version 1.1 or higher is present.
1343 \value OpenGL_Version_1_2 OpenGL version 1.2 or higher is present.
1345 \value OpenGL_Version_1_3 OpenGL version 1.3 or higher is present.
1347 \value OpenGL_Version_1_4 OpenGL version 1.4 or higher is present.
1349 \value OpenGL_Version_1_5 OpenGL version 1.5 or higher is present.
1351 \value OpenGL_Version_2_0 OpenGL version 2.0 or higher is present.
1352 Note that version 2.0 supports all the functionality of version 1.5.
1354 \value OpenGL_Version_2_1 OpenGL version 2.1 or higher is present.
1356 \value OpenGL_Version_3_0 OpenGL version 3.0 or higher is present.
1358 \value OpenGL_Version_3_1 OpenGL version 3.1 or higher is present.
1359 Note that OpenGL version 3.1 or higher does not necessarily support all the features of
1360 version 3.0 and lower.
1362 \value OpenGL_Version_3_2 OpenGL version 3.2 or higher is present.
1364 \value OpenGL_Version_3_3 OpenGL version 3.3 or higher is present.
1366 \value OpenGL_Version_4_0 OpenGL version 4.0 or higher is present.
1368 \value OpenGL_ES_CommonLite_Version_1_0 OpenGL ES version 1.0 Common Lite or higher is present.
1370 \value OpenGL_ES_Common_Version_1_0 OpenGL ES version 1.0 Common or higher is present.
1371 The Common profile supports all the features of Common Lite.
1373 \value OpenGL_ES_CommonLite_Version_1_1 OpenGL ES version 1.1 Common Lite or higher is present.
1375 \value OpenGL_ES_Common_Version_1_1 OpenGL ES version 1.1 Common or higher is present.
1376 The Common profile supports all the features of Common Lite.
1378 \value OpenGL_ES_Version_2_0 OpenGL ES version 2.0 or higher is present.
1379 Note that OpenGL ES version 2.0 does not support all the features of OpenGL ES 1.x.
1380 So if OpenGL_ES_Version_2_0 is returned, none of the ES 1.x flags are returned.
1382 See also \l{http://www.opengl.org} for more information about the different
1383 revisions of OpenGL.
1385 \sa openGLVersionFlags()
1391 Identifies, at runtime, which OpenGL versions that are supported
1392 by the current platform.
1394 Note that if OpenGL version 1.5 is supported, its predecessors
1395 (i.e., version 1.4 and lower) are also supported. To identify the
1396 support of a particular feature, like multi texturing, test for
1397 the version in which the feature was first introduced (i.e.,
1398 version 1.3 in the case of multi texturing) to adapt to the largest
1399 possible group of runtime platforms.
1401 This function needs a valid current OpenGL context to work;
1402 otherwise it will return OpenGL_Version_None.
1404 \sa hasOpenGL(), hasOpenGLOverlays()
1406 QGLFormat::OpenGLVersionFlags QGLFormat::openGLVersionFlags()
1408 static bool cachedDefault = false;
1409 static OpenGLVersionFlags defaultVersionFlags = OpenGL_Version_None;
1410 QGLContext *currentCtx = const_cast<QGLContext *>(QGLContext::currentContext());
1411 QGLTemporaryContext *tmpContext = 0;
1413 if (currentCtx && currentCtx->d_func()->version_flags_cached)
1414 return currentCtx->d_func()->version_flags;
1417 if (cachedDefault) {
1418 return defaultVersionFlags;
1421 return defaultVersionFlags;
1422 tmpContext = new QGLTemporaryContext;
1423 cachedDefault = true;
1427 QString versionString(QLatin1String(reinterpret_cast<const char*>(glGetString(GL_VERSION))));
1428 OpenGLVersionFlags versionFlags = qOpenGLVersionFlagsFromString(versionString);
1430 currentCtx->d_func()->version_flags_cached = true;
1431 currentCtx->d_func()->version_flags = versionFlags;
1434 defaultVersionFlags = versionFlags;
1438 return versionFlags;
1443 Returns the default QGLFormat for the application. All QGLWidget
1444 objects that are created use this format unless another format is
1445 specified, e.g. when they are constructed.
1447 If no special default format has been set using
1448 setDefaultFormat(), the default format is the same as that created
1451 \sa setDefaultFormat()
1454 QGLFormat QGLFormat::defaultFormat()
1456 return *qgl_default_format();
1460 Sets a new default QGLFormat for the application to \a f. For
1461 example, to set single buffering as the default instead of double
1462 buffering, your main() might contain code like this:
1463 \snippet doc/src/snippets/code/src_opengl_qgl.cpp 4
1468 void QGLFormat::setDefaultFormat(const QGLFormat &f)
1470 *qgl_default_format() = f;
1475 Returns the default QGLFormat for overlay contexts.
1477 The default overlay format is:
1479 \i \link setDoubleBuffer() Double buffer:\endlink Disabled.
1480 \i \link setDepth() Depth buffer:\endlink Disabled.
1481 \i \link setRgba() RGBA:\endlink Disabled (i.e., color index enabled).
1482 \i \link setAlpha() Alpha channel:\endlink Disabled.
1483 \i \link setAccum() Accumulator buffer:\endlink Disabled.
1484 \i \link setStencil() Stencil buffer:\endlink Disabled.
1485 \i \link setStereo() Stereo:\endlink Disabled.
1486 \i \link setDirectRendering() Direct rendering:\endlink Enabled.
1487 \i \link setOverlay() Overlay:\endlink Disabled.
1488 \i \link setSampleBuffers() Multisample buffers:\endlink Disabled.
1489 \i \link setPlane() Plane:\endlink 1 (i.e., first overlay plane).
1492 \sa setDefaultFormat()
1495 QGLFormat QGLFormat::defaultOverlayFormat()
1497 return *defaultOverlayFormatInstance();
1501 Sets a new default QGLFormat for overlay contexts to \a f. This
1502 format is used whenever a QGLWidget is created with a format that
1503 hasOverlay() enabled.
1505 For example, to get a double buffered overlay context (if
1506 available), use code like this:
1508 \snippet doc/src/snippets/code/src_opengl_qgl.cpp 5
1510 As usual, you can find out after widget creation whether the
1511 underlying OpenGL system was able to provide the requested
1514 \snippet doc/src/snippets/code/src_opengl_qgl.cpp 6
1516 \sa defaultOverlayFormat()
1519 void QGLFormat::setDefaultOverlayFormat(const QGLFormat &f)
1521 QGLFormat *defaultFormat = defaultOverlayFormatInstance();
1523 // Make sure the user doesn't request that the overlays themselves
1524 // have overlays, since it is unlikely that the system supports
1525 // infinitely many planes...
1526 defaultFormat->setOverlay(false);
1531 Returns true if all the options of the two QGLFormat objects
1532 \a a and \a b are equal; otherwise returns false.
1537 bool operator==(const QGLFormat& a, const QGLFormat& b)
1539 return (a.d == b.d) || ((int) a.d->opts == (int) b.d->opts
1540 && a.d->pln == b.d->pln
1541 && a.d->alphaSize == b.d->alphaSize
1542 && a.d->accumSize == b.d->accumSize
1543 && a.d->stencilSize == b.d->stencilSize
1544 && a.d->depthSize == b.d->depthSize
1545 && a.d->redSize == b.d->redSize
1546 && a.d->greenSize == b.d->greenSize
1547 && a.d->blueSize == b.d->blueSize
1548 && a.d->numSamples == b.d->numSamples
1549 && a.d->swapInterval == b.d->swapInterval
1550 && a.d->majorVersion == b.d->majorVersion
1551 && a.d->minorVersion == b.d->minorVersion
1552 && a.d->profile == b.d->profile);
1555 #ifndef QT_NO_DEBUG_STREAM
1556 QDebug operator<<(QDebug dbg, const QGLFormat &f)
1558 const QGLFormatPrivate * const d = f.d;
1560 dbg.nospace() << "QGLFormat("
1561 << "options " << d->opts
1562 << ", plane " << d->pln
1563 << ", depthBufferSize " << d->depthSize
1564 << ", accumBufferSize " << d->accumSize
1565 << ", stencilBufferSize " << d->stencilSize
1566 << ", redBufferSize " << d->redSize
1567 << ", greenBufferSize " << d->greenSize
1568 << ", blueBufferSize " << d->blueSize
1569 << ", alphaBufferSize " << d->alphaSize
1570 << ", samples " << d->numSamples
1571 << ", swapInterval " << d->swapInterval
1572 << ", majorVersion " << d->majorVersion
1573 << ", minorVersion " << d->minorVersion
1574 << ", profile " << d->profile
1583 Returns false if all the options of the two QGLFormat objects
1584 \a a and \a b are equal; otherwise returns true.
1589 bool operator!=(const QGLFormat& a, const QGLFormat& b)
1594 struct QGLContextGroupList {
1595 void append(QGLContextGroup *group) {
1596 QMutexLocker locker(&m_mutex);
1597 m_list.append(group);
1600 void remove(QGLContextGroup *group) {
1601 QMutexLocker locker(&m_mutex);
1602 m_list.removeOne(group);
1605 QList<QGLContextGroup *> m_list;
1609 Q_GLOBAL_STATIC(QGLContextGroupList, qt_context_groups)
1611 /*****************************************************************************
1612 QGLContext implementation
1613 *****************************************************************************/
1615 QGLContextGroup::QGLContextGroup(const QGLContext *context)
1616 : m_context(context), m_guards(0), m_refs(1)
1618 qt_context_groups()->append(this);
1621 QGLContextGroup::~QGLContextGroup()
1623 // Clear any remaining QGLSharedResourceGuard objects on the group.
1624 QGLSharedResourceGuard *guard = m_guards;
1625 while (guard != 0) {
1628 guard = guard->m_next;
1630 qt_context_groups()->remove(this);
1633 void QGLContextGroup::addGuard(QGLSharedResourceGuard *guard)
1636 m_guards->m_prev = guard;
1637 guard->m_next = m_guards;
1642 void QGLContextGroup::removeGuard(QGLSharedResourceGuard *guard)
1645 guard->m_next->m_prev = guard->m_prev;
1647 guard->m_prev->m_next = guard->m_next;
1649 m_guards = guard->m_next;
1652 const QGLContext *qt_gl_transfer_context(const QGLContext *ctx)
1656 QList<const QGLContext *> shares
1657 (QGLContextPrivate::contextGroup(ctx)->shares());
1658 if (shares.size() >= 2)
1659 return (ctx == shares.at(0)) ? shares.at(1) : shares.at(0);
1664 QGLContextPrivate::QGLContextPrivate(QGLContext *context)
1665 : internal_context(false)
1669 group = new QGLContextGroup(context);
1670 texture_destroyer = new QGLTextureDestroyer;
1671 texture_destroyer->moveToThread(qApp->thread());
1674 QGLContextPrivate::~QGLContextPrivate()
1678 if (!group->m_refs.deref()) {
1679 Q_ASSERT(group->context() == q_ptr);
1683 delete texture_destroyer;
1686 void QGLContextPrivate::init(QPaintDevice *dev, const QGLFormat &format)
1689 glFormat = reqFormat = format;
1692 #if defined(Q_WS_X11)
1696 screen = QX11Info::appScreen();
1698 #if defined(Q_WS_WIN)
1707 #if defined(Q_WS_MAC)
1708 # ifndef QT_MAC_USE_COCOA
1713 #if defined(Q_WS_QPA)
1714 platformContext = 0;
1716 #if !defined(QT_NO_EGL)
1717 ownsEglContext = false;
1719 eglSurface = EGL_NO_SURFACE;
1725 max_texture_size = -1;
1726 version_flags_cached = false;
1727 version_flags = QGLFormat::OpenGL_Version_None;
1728 extension_flags_cached = false;
1729 extension_flags = 0;
1733 workaround_needsFullClearOnEveryFrame = false;
1734 workaround_brokenFBOReadBack = false;
1735 workaround_brokenTexSubImage = false;
1736 workaroundsCached = false;
1738 workaround_brokenTextureFromPixmap = false;
1739 workaround_brokenTextureFromPixmap_init = false;
1741 workaround_brokenAlphaTexSubImage = false;
1742 workaround_brokenAlphaTexSubImage_init = false;
1744 for (int i = 0; i < QT_GL_VERTEX_ARRAY_TRACKED_COUNT; ++i)
1745 vertexAttributeArraysEnabledState[i] = false;
1748 QGLContext* QGLContext::currentCtx = 0;
1751 Read back the contents of the currently bound framebuffer, used in
1752 QGLWidget::grabFrameBuffer(), QGLPixelbuffer::toImage() and
1753 QGLFramebufferObject::toImage()
1756 static void convertFromGLImage(QImage &img, int w, int h, bool alpha_format, bool include_alpha)
1758 if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
1759 // OpenGL gives RGBA; Qt wants ARGB
1760 uint *p = (uint*)img.bits();
1761 uint *end = p + w*h;
1762 if (alpha_format && include_alpha) {
1769 // This is an old legacy fix for PowerPC based Macs, which
1770 // we shouldn't remove
1772 *p = 0xff000000 | (*p>>8);
1777 // OpenGL gives ABGR (i.e. RGBA backwards); Qt wants ARGB
1778 for (int y = 0; y < h; y++) {
1779 uint *q = (uint*)img.scanLine(y);
1780 for (int x=0; x < w; ++x) {
1781 const uint pixel = *q;
1782 if (alpha_format && include_alpha) {
1783 *q = ((pixel << 16) & 0xff0000) | ((pixel >> 16) & 0xff)
1784 | (pixel & 0xff00ff00);
1786 *q = 0xff000000 | ((pixel << 16) & 0xff0000)
1787 | ((pixel >> 16) & 0xff) | (pixel & 0x00ff00);
1795 img = img.mirrored();
1798 Q_OPENGL_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha)
1800 QImage img(size, (alpha_format && include_alpha) ? QImage::Format_ARGB32_Premultiplied
1801 : QImage::Format_RGB32);
1802 int w = size.width();
1803 int h = size.height();
1804 glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, img.bits());
1805 convertFromGLImage(img, w, h, alpha_format, include_alpha);
1809 QImage qt_gl_read_texture(const QSize &size, bool alpha_format, bool include_alpha)
1811 QImage img(size, alpha_format ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32);
1812 int w = size.width();
1813 int h = size.height();
1814 #if !defined(QT_OPENGL_ES_2) && !defined(QT_OPENGL_ES_1)
1815 //### glGetTexImage not in GL ES 2.0, need to do something else here!
1816 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, img.bits());
1818 convertFromGLImage(img, w, h, alpha_format, include_alpha);
1822 // returns the highest number closest to v, which is a power of 2
1823 // NB! assumes 32 bit ints
1824 int qt_next_power_of_two(int v)
1836 typedef void (*_qt_pixmap_cleanup_hook_64)(qint64);
1837 typedef void (*_qt_image_cleanup_hook_64)(qint64);
1839 extern Q_GUI_EXPORT _qt_pixmap_cleanup_hook_64 qt_pixmap_cleanup_hook_64;
1840 extern Q_GUI_EXPORT _qt_image_cleanup_hook_64 qt_image_cleanup_hook_64;
1843 Q_GLOBAL_STATIC(QGLTextureCache, qt_gl_texture_cache)
1845 QGLTextureCache::QGLTextureCache()
1846 : m_cache(64*1024) // cache ~64 MB worth of textures - this is not accurate though
1848 QImagePixmapCleanupHooks::instance()->addPixmapDataModificationHook(cleanupTexturesForPixampData);
1849 QImagePixmapCleanupHooks::instance()->addPixmapDataDestructionHook(cleanupBeforePixmapDestruction);
1850 QImagePixmapCleanupHooks::instance()->addImageHook(cleanupTexturesForCacheKey);
1853 QGLTextureCache::~QGLTextureCache()
1855 QImagePixmapCleanupHooks::instance()->removePixmapDataModificationHook(cleanupTexturesForPixampData);
1856 QImagePixmapCleanupHooks::instance()->removePixmapDataDestructionHook(cleanupBeforePixmapDestruction);
1857 QImagePixmapCleanupHooks::instance()->removeImageHook(cleanupTexturesForCacheKey);
1860 void QGLTextureCache::insert(QGLContext* ctx, qint64 key, QGLTexture* texture, int cost)
1862 QWriteLocker locker(&m_lock);
1863 const QGLTextureCacheKey cacheKey = {key, QGLContextPrivate::contextGroup(ctx)};
1864 m_cache.insert(cacheKey, texture, cost);
1867 void QGLTextureCache::remove(qint64 key)
1869 QWriteLocker locker(&m_lock);
1870 QMutexLocker groupLocker(&qt_context_groups()->m_mutex);
1871 QList<QGLContextGroup *>::const_iterator it = qt_context_groups()->m_list.constBegin();
1872 while (it != qt_context_groups()->m_list.constEnd()) {
1873 const QGLTextureCacheKey cacheKey = {key, *it};
1874 m_cache.remove(cacheKey);
1879 bool QGLTextureCache::remove(QGLContext* ctx, GLuint textureId)
1881 QWriteLocker locker(&m_lock);
1882 QList<QGLTextureCacheKey> keys = m_cache.keys();
1883 for (int i = 0; i < keys.size(); ++i) {
1884 QGLTexture *tex = m_cache.object(keys.at(i));
1885 if (tex->id == textureId && tex->context == ctx) {
1886 tex->options |= QGLContext::MemoryManagedBindOption; // forces a glDeleteTextures() call
1887 m_cache.remove(keys.at(i));
1894 void QGLTextureCache::removeContextTextures(QGLContext* ctx)
1896 QWriteLocker locker(&m_lock);
1897 QList<QGLTextureCacheKey> keys = m_cache.keys();
1898 for (int i = 0; i < keys.size(); ++i) {
1899 const QGLTextureCacheKey &key = keys.at(i);
1900 if (m_cache.object(key)->context == ctx)
1901 m_cache.remove(key);
1906 a hook that removes textures from the cache when a pixmap/image
1909 void QGLTextureCache::cleanupTexturesForCacheKey(qint64 cacheKey)
1911 qt_gl_texture_cache()->remove(cacheKey);
1915 void QGLTextureCache::cleanupTexturesForPixampData(QPixmapData* pmd)
1917 cleanupTexturesForCacheKey(pmd->cacheKey());
1920 void QGLTextureCache::cleanupBeforePixmapDestruction(QPixmapData* pmd)
1922 // Remove any bound textures first:
1923 cleanupTexturesForPixampData(pmd);
1925 #if defined(Q_WS_X11)
1926 if (pmd->classId() == QPixmapData::X11Class) {
1927 Q_ASSERT(pmd->ref == 0); // Make sure reference counting isn't broken
1928 QGLContextPrivate::destroyGlSurfaceForPixmap(pmd);
1933 QGLTextureCache *QGLTextureCache::instance()
1935 return qt_gl_texture_cache();
1938 // DDS format structure
1944 quint32 dwLinearSize;
1946 quint32 dwMipMapCount;
1955 // compressed texture pixel formats
1956 #define FOURCC_DXT1 0x31545844
1957 #define FOURCC_DXT2 0x32545844
1958 #define FOURCC_DXT3 0x33545844
1959 #define FOURCC_DXT4 0x34545844
1960 #define FOURCC_DXT5 0x35545844
1962 #ifndef GL_COMPRESSED_RGB_S3TC_DXT1_EXT
1963 #define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
1964 #define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
1965 #define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2
1966 #define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3
1969 #ifndef GL_GENERATE_MIPMAP_SGIS
1970 #define GL_GENERATE_MIPMAP_SGIS 0x8191
1971 #define GL_GENERATE_MIPMAP_HINT_SGIS 0x8192
1976 \brief The QGLContext class encapsulates an OpenGL rendering context.
1978 \ingroup painting-3D
1980 An OpenGL rendering context is a complete set of OpenGL state
1981 variables. The rendering context's \l {QGL::FormatOption} {format}
1982 is set in the constructor, but it can also be set later with
1983 setFormat(). The format options that are actually set are returned
1984 by format(); the options you asked for are returned by
1985 requestedFormat(). Note that after a QGLContext object has been
1986 constructed, the actual OpenGL context must be created by
1987 explicitly calling the \link create() create()\endlink
1988 function. The makeCurrent() function makes this context the
1989 current rendering context. You can make \e no context current
1990 using doneCurrent(). The reset() function will reset the context
1991 and make it invalid.
1993 You can examine properties of the context with, e.g. isValid(),
1994 isSharing(), initialized(), windowCreated() and
1995 overlayTransparentColor().
1997 If you're using double buffering you can swap the screen contents
1998 with the off-screen buffer using swapBuffers().
2000 Please note that QGLContext is not thread safe.
2004 \enum QGLContext::BindOption
2007 A set of options to decide how to bind a texture using bindTexture().
2009 \value NoBindOption Don't do anything, pass the texture straight
2012 \value InvertedYBindOption Specifies that the texture should be flipped
2013 over the X axis so that the texture coordinate 0,0 corresponds to
2014 the top left corner. Inverting the texture implies a deep copy
2017 \value MipmapBindOption Specifies that bindTexture() should try
2018 to generate mipmaps. If the GL implementation supports the \c
2019 GL_SGIS_generate_mipmap extension, mipmaps will be automatically
2020 generated for the texture. Mipmap generation is only supported for
2021 the \c GL_TEXTURE_2D target.
2023 \value PremultipliedAlphaBindOption Specifies that the image should be
2024 uploaded with premultiplied alpha and does a conversion accordingly.
2026 \value LinearFilteringBindOption Specifies that the texture filtering
2027 should be set to GL_LINEAR. Default is GL_NEAREST. If mipmap is
2028 also enabled, filtering will be set to GL_LINEAR_MIPMAP_LINEAR.
2030 \value DefaultBindOption In Qt 4.5 and earlier, bindTexture()
2031 would mirror the image and automatically generate mipmaps. This
2032 option helps preserve this default behavior.
2034 \omitvalue CanFlipNativePixmapBindOption Used by x11 from pixmap to choose
2035 whether or not it can bind the pixmap upside down or not.
2037 \omitvalue MemoryManagedBindOption Used by paint engines to
2038 indicate that the pixmap should be memory managed along side with
2039 the pixmap/image that it stems from, e.g. installing destruction
2042 \omitvalue TemporarilyCachedBindOption Used by paint engines on some
2043 platforms to indicate that the pixmap or image texture is possibly
2044 cached only temporarily and must be destroyed immediately after the use.
2046 \omitvalue InternalBindOption
2052 Constructs an OpenGL context for the given paint \a device, which
2053 can be a widget or a pixmap. The \a format specifies several
2054 display options for the context.
2056 If the underlying OpenGL/Window system cannot satisfy all the
2057 features requested in \a format, the nearest subset of features
2058 will be used. After creation, the format() method will return the
2059 actual format obtained.
2061 Note that after a QGLContext object has been constructed, \l
2062 create() must be called explicitly to create the actual OpenGL
2063 context. The context will be \l {isValid()}{invalid} if it was not
2064 possible to obtain a GL context at all.
2067 QGLContext::QGLContext(const QGLFormat &format, QPaintDevice *device)
2068 : d_ptr(new QGLContextPrivate(this))
2071 d->init(device, format);
2075 Constructs an OpenGL context with the given \a format which
2076 specifies several display options for the context.
2078 If the underlying OpenGL/Window system cannot satisfy all the
2079 features requested in \a format, the nearest subset of features
2080 will be used. After creation, the format() method will return the
2081 actual format obtained.
2083 Note that after a QGLContext object has been constructed, \l
2084 create() must be called explicitly to create the actual OpenGL
2085 context. The context will be \l {isValid()}{invalid} if it was not
2086 possible to obtain a GL context at all.
2088 \sa format(), isValid()
2090 QGLContext::QGLContext(const QGLFormat &format)
2091 : d_ptr(new QGLContextPrivate(this))
2098 Destroys the OpenGL context and frees its resources.
2101 QGLContext::~QGLContext()
2103 // remove any textures cached in this context
2104 QGLTextureCache::instance()->removeContextTextures(this);
2106 // clean up resources specific to this context
2108 // clean up resources belonging to this context's group
2109 d_ptr->group->cleanupResources(this);
2111 QGLSignalProxy::instance()->emitAboutToDestroyContext(this);
2115 void QGLContextPrivate::cleanup()
2117 QHash<QGLContextResourceBase *, void *>::ConstIterator it;
2118 for (it = m_resources.begin(); it != m_resources.end(); ++it)
2119 it.key()->freeResource(it.value());
2120 m_resources.clear();
2124 void QGLContextPrivate::setVertexAttribArrayEnabled(int arrayIndex, bool enabled)
2126 Q_ASSERT(arrayIndex < QT_GL_VERTEX_ARRAY_TRACKED_COUNT);
2127 #ifdef glEnableVertexAttribArray
2128 Q_ASSERT(glEnableVertexAttribArray);
2131 if (vertexAttributeArraysEnabledState[arrayIndex] && !enabled)
2132 glDisableVertexAttribArray(arrayIndex);
2134 if (!vertexAttributeArraysEnabledState[arrayIndex] && enabled)
2135 glEnableVertexAttribArray(arrayIndex);
2137 vertexAttributeArraysEnabledState[arrayIndex] = enabled;
2140 void QGLContextPrivate::syncGlState()
2142 #ifdef glEnableVertexAttribArray
2143 Q_ASSERT(glEnableVertexAttribArray);
2145 for (int i = 0; i < QT_GL_VERTEX_ARRAY_TRACKED_COUNT; ++i) {
2146 if (vertexAttributeArraysEnabledState[i])
2147 glEnableVertexAttribArray(i);
2149 glDisableVertexAttribArray(i);
2156 void QGLContextPrivate::swapRegion(const QRegion &)
2166 Reads the compressed texture file \a fileName and generates a 2D GL
2169 This function can load DirectDrawSurface (DDS) textures in the
2170 DXT1, DXT3 and DXT5 DDS formats if the \c GL_ARB_texture_compression
2171 and \c GL_EXT_texture_compression_s3tc extensions are supported.
2173 Since 4.6.1, textures in the ETC1 format can be loaded if the
2174 \c GL_OES_compressed_ETC1_RGB8_texture extension is supported
2175 and the ETC1 texture has been encapsulated in the PVR container format.
2176 Also, textures in the PVRTC2 and PVRTC4 formats can be loaded
2177 if the \c GL_IMG_texture_compression_pvrtc extension is supported.
2182 GLuint QGLContext::bindTexture(const QString &fileName)
2184 QGLTexture texture(this);
2185 QSize size = texture.bindCompressedTexture(fileName);
2186 if (!size.isValid())
2191 static inline QRgb qt_gl_convertToGLFormatHelper(QRgb src_pixel, GLenum texture_format)
2193 if (texture_format == GL_BGRA) {
2194 if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
2195 return ((src_pixel << 24) & 0xff000000)
2196 | ((src_pixel >> 24) & 0x000000ff)
2197 | ((src_pixel << 8) & 0x00ff0000)
2198 | ((src_pixel >> 8) & 0x0000ff00);
2203 if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
2204 return (src_pixel << 8) | ((src_pixel >> 24) & 0xff);
2206 return ((src_pixel << 16) & 0xff0000)
2207 | ((src_pixel >> 16) & 0xff)
2208 | (src_pixel & 0xff00ff00);
2213 QRgb qt_gl_convertToGLFormat(QRgb src_pixel, GLenum texture_format)
2215 return qt_gl_convertToGLFormatHelper(src_pixel, texture_format);
2218 static void convertToGLFormatHelper(QImage &dst, const QImage &img, GLenum texture_format)
2220 Q_ASSERT(dst.depth() == 32);
2221 Q_ASSERT(img.depth() == 32);
2223 if (dst.size() != img.size()) {
2224 int target_width = dst.width();
2225 int target_height = dst.height();
2226 qreal sx = target_width / qreal(img.width());
2227 qreal sy = target_height / qreal(img.height());
2229 quint32 *dest = (quint32 *) dst.scanLine(0); // NB! avoid detach here
2230 uchar *srcPixels = (uchar *) img.scanLine(img.height() - 1);
2231 int sbpl = img.bytesPerLine();
2232 int dbpl = dst.bytesPerLine();
2234 int ix = int(0x00010000 / sx);
2235 int iy = int(0x00010000 / sy);
2237 quint32 basex = int(0.5 * ix);
2238 quint32 srcy = int(0.5 * iy);
2240 // scale, swizzle and mirror in one loop
2241 while (target_height--) {
2242 const uint *src = (const quint32 *) (srcPixels - (srcy >> 16) * sbpl);
2244 for (int x=0; x<target_width; ++x) {
2245 dest[x] = qt_gl_convertToGLFormatHelper(src[srcx >> 16], texture_format);
2248 dest = (quint32 *)(((uchar *) dest) + dbpl);
2252 const int width = img.width();
2253 const int height = img.height();
2254 const uint *p = (const uint*) img.scanLine(img.height() - 1);
2255 uint *q = (uint*) dst.scanLine(0);
2257 if (texture_format == GL_BGRA) {
2258 if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
2260 for (int i=0; i < height; ++i) {
2261 const uint *end = p + width;
2263 *q = ((*p << 24) & 0xff000000)
2264 | ((*p >> 24) & 0x000000ff)
2265 | ((*p << 8) & 0x00ff0000)
2266 | ((*p >> 8) & 0x0000ff00);
2273 const uint bytesPerLine = img.bytesPerLine();
2274 for (int i=0; i < height; ++i) {
2275 memcpy(q, p, bytesPerLine);
2281 if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
2282 for (int i=0; i < height; ++i) {
2283 const uint *end = p + width;
2285 *q = (*p << 8) | ((*p >> 24) & 0xff);
2292 for (int i=0; i < height; ++i) {
2293 const uint *end = p + width;
2295 *q = ((*p << 16) & 0xff0000) | ((*p >> 16) & 0xff) | (*p & 0xff00ff00);
2306 #if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_SYMBIAN)
2307 QGLExtensionFuncs& QGLContextPrivate::extensionFuncs(const QGLContext *)
2309 return qt_extensionFuncs;
2313 QImage QGLContextPrivate::convertToGLFormat(const QImage &image, bool force_premul,
2314 GLenum texture_format)
2316 QImage::Format target_format = image.format();
2317 if (force_premul || image.format() != QImage::Format_ARGB32)
2318 target_format = QImage::Format_ARGB32_Premultiplied;
2320 QImage result(image.width(), image.height(), target_format);
2321 convertToGLFormatHelper(result, image.convertToFormat(target_format), texture_format);
2326 QGLTexture *QGLContextPrivate::bindTexture(const QImage &image, GLenum target, GLint format,
2327 QGLContext::BindOptions options)
2331 const qint64 key = image.cacheKey();
2332 QGLTexture *texture = textureCacheLookup(key, target);
2334 if (image.paintingActive()) {
2335 // A QPainter is active on the image - take the safe route and replace the texture.
2336 q->deleteTexture(texture->id);
2339 glBindTexture(target, texture->id);
2345 texture = bindTexture(image, target, format, key, options);
2346 // NOTE: bindTexture(const QImage&, GLenum, GLint, const qint64, bool) should never return null
2349 // Enable the cleanup hooks for this image so that the texture cache entry is removed when the
2350 // image gets deleted:
2351 QImagePixmapCleanupHooks::enableCleanupHooks(image);
2356 // #define QGL_BIND_TEXTURE_DEBUG
2358 // map from Qt's ARGB endianness-dependent format to GL's big-endian RGBA layout
2359 static inline void qgl_byteSwapImage(QImage &img, GLenum pixel_type)
2361 const int width = img.width();
2362 const int height = img.height();
2364 if (pixel_type == GL_UNSIGNED_INT_8_8_8_8_REV
2365 || (pixel_type == GL_UNSIGNED_BYTE && QSysInfo::ByteOrder == QSysInfo::LittleEndian))
2367 for (int i = 0; i < height; ++i) {
2368 uint *p = (uint *) img.scanLine(i);
2369 for (int x = 0; x < width; ++x)
2370 p[x] = ((p[x] << 16) & 0xff0000) | ((p[x] >> 16) & 0xff) | (p[x] & 0xff00ff00);
2373 for (int i = 0; i < height; ++i) {
2374 uint *p = (uint *) img.scanLine(i);
2375 for (int x = 0; x < width; ++x)
2376 p[x] = (p[x] << 8) | ((p[x] >> 24) & 0xff);
2381 QGLTexture* QGLContextPrivate::bindTexture(const QImage &image, GLenum target, GLint internalFormat,
2382 const qint64 key, QGLContext::BindOptions options)
2386 #ifdef QGL_BIND_TEXTURE_DEBUG
2387 printf("QGLContextPrivate::bindTexture(), imageSize=(%d,%d), internalFormat =0x%x, options=%x, key=%llx\n",
2388 image.width(), image.height(), internalFormat, int(options), key);
2394 // Reset the gl error stack...git
2395 while (glGetError() != GL_NO_ERROR) ;
2398 // Scale the pixmap if needed. GL textures needs to have the
2399 // dimensions 2^n+2(border) x 2^m+2(border), unless we're using GL
2400 // 2.0 or use the GL_TEXTURE_RECTANGLE texture target
2401 int tx_w = qt_next_power_of_two(image.width());
2402 int tx_h = qt_next_power_of_two(image.height());
2406 if (!(QGLExtensions::glExtensions() & QGLExtensions::NPOTTextures)
2407 && !(QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_ES_Version_2_0)
2408 && (target == GL_TEXTURE_2D && (tx_w != image.width() || tx_h != image.height())))
2410 img = img.scaled(tx_w, tx_h);
2411 #ifdef QGL_BIND_TEXTURE_DEBUG
2412 printf(" - upscaled to %dx%d (%d ms)\n", tx_w, tx_h, time.elapsed());
2417 GLuint filtering = options & QGLContext::LinearFilteringBindOption ? GL_LINEAR : GL_NEAREST;
2420 glGenTextures(1, &tx_id);
2421 glBindTexture(target, tx_id);
2422 glTexParameterf(target, GL_TEXTURE_MAG_FILTER, filtering);
2424 #if defined(QT_OPENGL_ES_2)
2425 bool genMipmap = false;
2427 if (glFormat.directRendering()
2428 && (QGLExtensions::glExtensions() & QGLExtensions::GenerateMipmap)
2429 && target == GL_TEXTURE_2D
2430 && (options & QGLContext::MipmapBindOption))
2432 #if !defined(QT_OPENGL_ES_2)
2433 glHint(GL_GENERATE_MIPMAP_HINT_SGIS, GL_NICEST);
2434 #ifndef QT_OPENGL_ES
2435 glTexParameteri(target, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
2437 glTexParameterf(target, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
2440 glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST);
2443 glTexParameterf(target, GL_TEXTURE_MIN_FILTER, options & QGLContext::LinearFilteringBindOption
2444 ? GL_LINEAR_MIPMAP_LINEAR : GL_NEAREST_MIPMAP_NEAREST);
2445 #ifdef QGL_BIND_TEXTURE_DEBUG
2446 printf(" - generating mipmaps (%d ms)\n", time.elapsed());
2449 glTexParameterf(target, GL_TEXTURE_MIN_FILTER, filtering);
2452 QImage::Format target_format = img.format();
2453 bool premul = options & QGLContext::PremultipliedAlphaBindOption;
2454 GLenum externalFormat;
2456 if (QGLExtensions::glExtensions() & QGLExtensions::BGRATextureFormat) {
2457 externalFormat = GL_BGRA;
2458 if (QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_1_2)
2459 pixel_type = GL_UNSIGNED_INT_8_8_8_8_REV;
2461 pixel_type = GL_UNSIGNED_BYTE;
2463 externalFormat = GL_RGBA;
2464 pixel_type = GL_UNSIGNED_BYTE;
2467 switch (target_format) {
2468 case QImage::Format_ARGB32:
2470 img = img.convertToFormat(target_format = QImage::Format_ARGB32_Premultiplied);
2471 #ifdef QGL_BIND_TEXTURE_DEBUG
2472 printf(" - converted ARGB32 -> ARGB32_Premultiplied (%d ms) \n", time.elapsed());
2476 case QImage::Format_ARGB32_Premultiplied:
2478 img = img.convertToFormat(target_format = QImage::Format_ARGB32);
2479 #ifdef QGL_BIND_TEXTURE_DEBUG
2480 printf(" - converted ARGB32_Premultiplied -> ARGB32 (%d ms)\n", time.elapsed());
2484 case QImage::Format_RGB16:
2485 pixel_type = GL_UNSIGNED_SHORT_5_6_5;
2486 externalFormat = GL_RGB;
2487 internalFormat = GL_RGB;
2489 case QImage::Format_RGB32:
2492 if (img.hasAlphaChannel()) {
2493 img = img.convertToFormat(premul
2494 ? QImage::Format_ARGB32_Premultiplied
2495 : QImage::Format_ARGB32);
2496 #ifdef QGL_BIND_TEXTURE_DEBUG
2497 printf(" - converted to 32-bit alpha format (%d ms)\n", time.elapsed());
2500 img = img.convertToFormat(QImage::Format_RGB32);
2501 #ifdef QGL_BIND_TEXTURE_DEBUG
2502 printf(" - converted to 32-bit (%d ms)\n", time.elapsed());
2507 if (options & QGLContext::InvertedYBindOption) {
2508 if (img.isDetached()) {
2509 int ipl = img.bytesPerLine() / 4;
2510 int h = img.height();
2511 for (int y=0; y<h/2; ++y) {
2512 int *a = (int *) img.scanLine(y);
2513 int *b = (int *) img.scanLine(h - y - 1);
2514 for (int x=0; x<ipl; ++x)
2518 // Create a new image and copy across. If we use the
2519 // above in-place code then a full copy of the image is
2520 // made before the lines are swapped, which processes the
2521 // data twice. This version should only do it once.
2522 img = img.mirrored();
2524 #ifdef QGL_BIND_TEXTURE_DEBUG
2525 printf(" - flipped bits over y (%d ms)\n", time.elapsed());
2529 if (externalFormat == GL_RGBA) {
2530 // The only case where we end up with a depth different from
2531 // 32 in the switch above is for the RGB16 case, where we set
2532 // the format to GL_RGB
2533 Q_ASSERT(img.depth() == 32);
2534 qgl_byteSwapImage(img, pixel_type);
2535 #ifdef QGL_BIND_TEXTURE_DEBUG
2536 printf(" - did byte swapping (%d ms)\n", time.elapsed());
2540 // OpenGL/ES requires that the internal and external formats be
2542 internalFormat = externalFormat;
2544 #ifdef QGL_BIND_TEXTURE_DEBUG
2545 printf(" - uploading, image.format=%d, externalFormat=0x%x, internalFormat=0x%x, pixel_type=0x%x\n",
2546 img.format(), externalFormat, internalFormat, pixel_type);
2549 const QImage &constRef = img; // to avoid detach in bits()...
2550 #ifdef QGL_USE_TEXTURE_POOL
2551 QGLTexturePool::instance()->createPermanentTexture(tx_id,
2554 img.width(), img.height(),
2559 glTexImage2D(target, 0, internalFormat, img.width(), img.height(), 0, externalFormat,
2560 pixel_type, constRef.bits());
2562 #if defined(QT_OPENGL_ES_2)
2564 glGenerateMipmap(target);
2567 GLenum error = glGetError();
2568 if (error != GL_NO_ERROR) {
2569 qWarning(" - texture upload failed, error code 0x%x, enum: %d (%x)\n", error, target, target);
2573 #ifdef QGL_BIND_TEXTURE_DEBUG
2574 static int totalUploadTime = 0;
2575 totalUploadTime += time.elapsed();
2576 printf(" - upload done in %d ms, (accumulated: %d ms)\n", time.elapsed(), totalUploadTime);
2580 // this assumes the size of a texture is always smaller than the max cache size
2581 int cost = img.width()*img.height()*4/1024;
2582 QGLTexture *texture = new QGLTexture(q, tx_id, target, options);
2583 QGLTextureCache::instance()->insert(q, key, texture, cost);
2588 QGLTexture *QGLContextPrivate::textureCacheLookup(const qint64 key, GLenum target)
2591 QGLTexture *texture = QGLTextureCache::instance()->getTexture(q, key);
2592 if (texture && texture->target == target
2593 && (texture->context == q || QGLContext::areSharing(q, texture->context)))
2601 QGLTexture *QGLContextPrivate::bindTexture(const QPixmap &pixmap, GLenum target, GLint format, QGLContext::BindOptions options)
2604 QPixmapData *pd = pixmap.pixmapData();
2605 #if !defined(QT_OPENGL_ES_1)
2606 if (target == GL_TEXTURE_2D && pd->classId() == QPixmapData::OpenGLClass) {
2607 const QGLPixmapData *data = static_cast<const QGLPixmapData *>(pd);
2609 if (data->isValidContext(q)) {
2611 return data->texture();
2618 const qint64 key = pixmap.cacheKey();
2619 QGLTexture *texture = textureCacheLookup(key, target);
2621 if (pixmap.paintingActive()) {
2622 // A QPainter is active on the pixmap - take the safe route and replace the texture.
2623 q->deleteTexture(texture->id);
2626 glBindTexture(target, texture->id);
2631 #if defined(Q_WS_X11)
2632 // Try to use texture_from_pixmap
2633 const QX11Info *xinfo = qt_x11Info(paintDevice);
2634 if (pd->classId() == QPixmapData::X11Class && pd->pixelType() == QPixmapData::PixmapType
2635 && xinfo && xinfo->screen() == pixmap.x11Info().screen()
2636 && target == GL_TEXTURE_2D
2637 && QApplication::instance()->thread() == QThread::currentThread())
2639 if (!workaround_brokenTextureFromPixmap_init) {
2640 workaround_brokenTextureFromPixmap_init = true;
2642 const QByteArray versionString(reinterpret_cast<const char*>(glGetString(GL_VERSION)));
2643 const int pos = versionString.indexOf("NVIDIA ");
2646 const QByteArray nvidiaVersionString = versionString.mid(pos + strlen("NVIDIA "));
2648 if (nvidiaVersionString.startsWith("195") || nvidiaVersionString.startsWith("256"))
2649 workaround_brokenTextureFromPixmap = true;
2653 if (!workaround_brokenTextureFromPixmap) {
2654 texture = bindTextureFromNativePixmap(const_cast<QPixmap*>(&pixmap), key, options);
2656 texture->options |= QGLContext::MemoryManagedBindOption;
2657 texture->boundPixmap = pd;
2658 boundPixmaps.insert(pd, QPixmap(pixmap));
2665 QImage image = pixmap.toImage();
2666 // If the system depth is 16 and the pixmap doesn't have an alpha channel
2667 // then we convert it to RGB16 in the hope that it gets uploaded as a 16
2668 // bit texture which is much faster to access than a 32-bit one.
2669 if (pixmap.depth() == 16 && !image.hasAlphaChannel() )
2670 image = image.convertToFormat(QImage::Format_RGB16);
2671 texture = bindTexture(image, target, format, key, options);
2673 // NOTE: bindTexture(const QImage&, GLenum, GLint, const qint64, bool) should never return null
2676 if (texture->id > 0)
2677 QImagePixmapCleanupHooks::enableCleanupHooks(pixmap);
2683 int QGLContextPrivate::maxTextureSize()
2685 if (max_texture_size != -1)
2686 return max_texture_size;
2688 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size);
2690 #if defined(QT_OPENGL_ES)
2691 return max_texture_size;
2693 GLenum proxy = GL_PROXY_TEXTURE_2D;
2697 glTexImage2D(proxy, 0, GL_RGBA, next, next, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
2698 glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &size);
2700 return max_texture_size;
2706 if (next > max_texture_size)
2708 glTexImage2D(proxy, 0, GL_RGBA, next, next, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
2709 glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &next);
2710 } while (next > size);
2712 max_texture_size = size;
2713 return max_texture_size;
2718 Returns a QGLFunctions object that is initialized for this context.
2720 QGLFunctions *QGLContext::functions() const
2722 QGLContextPrivate *d = const_cast<QGLContextPrivate *>(d_func());
2723 if (!d->functions) {
2724 d->functions = new QGLFunctions(this);
2725 d->functions->initializeGLFunctions(this);
2727 return d->functions;
2731 Generates and binds a 2D GL texture to the current context, based
2732 on \a image. The generated texture id is returned and can be used in
2733 later \c glBindTexture() calls.
2737 GLuint QGLContext::bindTexture(const QImage &image, GLenum target, GLint format)
2743 QGLTexture *texture = d->bindTexture(image, target, format, DefaultBindOption);
2750 Generates and binds a 2D GL texture to the current context, based
2751 on \a image. The generated texture id is returned and can be used
2752 in later \c glBindTexture() calls.
2754 The \a target parameter specifies the texture target. The default
2755 target is \c GL_TEXTURE_2D.
2757 The \a format parameter sets the internal format for the
2758 texture. The default format is \c GL_RGBA.
2760 The binding \a options are a set of options used to decide how to
2761 bind the texture to the context.
2763 The texture that is generated is cached, so multiple calls to
2764 bindTexture() with the same QImage will return the same texture
2767 Note that we assume default values for the glPixelStore() and
2768 glPixelTransfer() parameters.
2772 GLuint QGLContext::bindTexture(const QImage &image, GLenum target, GLint format, BindOptions options)
2778 QGLTexture *texture = d->bindTexture(image, target, format, options);
2782 #ifdef Q_MAC_COMPAT_GL_FUNCTIONS
2784 GLuint QGLContext::bindTexture(const QImage &image, QMacCompatGLenum target, QMacCompatGLint format)
2790 QGLTexture *texture = d->bindTexture(image, GLenum(target), GLint(format), DefaultBindOption);
2795 GLuint QGLContext::bindTexture(const QImage &image, QMacCompatGLenum target, QMacCompatGLint format,
2796 BindOptions options)
2802 QGLTexture *texture = d->bindTexture(image, GLenum(target), GLint(format), options);
2809 Generates and binds a 2D GL texture based on \a pixmap.
2811 GLuint QGLContext::bindTexture(const QPixmap &pixmap, GLenum target, GLint format)
2813 if (pixmap.isNull())
2817 QGLTexture *texture = d->bindTexture(pixmap, target, format, DefaultBindOption);
2825 Generates and binds a 2D GL texture to the current context, based
2828 GLuint QGLContext::bindTexture(const QPixmap &pixmap, GLenum target, GLint format, BindOptions options)
2830 if (pixmap.isNull())
2834 QGLTexture *texture = d->bindTexture(pixmap, target, format, options);
2838 #ifdef Q_MAC_COMPAT_GL_FUNCTIONS
2840 GLuint QGLContext::bindTexture(const QPixmap &pixmap, QMacCompatGLenum target, QMacCompatGLint format)
2842 if (pixmap.isNull())
2846 QGLTexture *texture = d->bindTexture(pixmap, GLenum(target), GLint(format), DefaultBindOption);
2850 GLuint QGLContext::bindTexture(const QPixmap &pixmap, QMacCompatGLenum target, QMacCompatGLint format,
2851 BindOptions options)
2853 if (pixmap.isNull())
2857 QGLTexture *texture = d->bindTexture(pixmap, GLenum(target), GLint(format), options);
2863 Removes the texture identified by \a id from the texture cache,
2864 and calls glDeleteTextures() to delete the texture from the
2869 void QGLContext::deleteTexture(GLuint id)
2871 if (QGLTextureCache::instance()->remove(this, id))
2873 glDeleteTextures(1, &id);
2876 #ifdef Q_MAC_COMPAT_GL_FUNCTIONS
2878 void QGLContext::deleteTexture(QMacCompatGLuint id)
2880 return deleteTexture(GLuint(id));
2884 void qt_add_rect_to_array(const QRectF &r, GLfloat *array)
2886 qreal left = r.left();
2887 qreal right = r.right();
2888 qreal top = r.top();
2889 qreal bottom = r.bottom();
2901 void qt_add_texcoords_to_array(qreal x1, qreal y1, qreal x2, qreal y2, GLfloat *array)
2913 #if !defined(QT_OPENGL_ES_2)
2915 static void qDrawTextureRect(const QRectF &target, GLint textureWidth, GLint textureHeight, GLenum textureTarget)
2921 Q_UNUSED(textureWidth);
2922 Q_UNUSED(textureHeight);
2923 Q_UNUSED(textureTarget);
2925 if (textureTarget != GL_TEXTURE_2D) {
2926 if (textureWidth == -1 || textureHeight == -1) {
2927 glGetTexLevelParameteriv(textureTarget, 0, GL_TEXTURE_WIDTH, &textureWidth);
2928 glGetTexLevelParameteriv(textureTarget, 0, GL_TEXTURE_HEIGHT, &textureHeight);
2931 tx = GLfloat(textureWidth);
2932 ty = GLfloat(textureHeight);
2936 GLfloat texCoordArray[4*2] = {
2937 0, ty, tx, ty, tx, 0, 0, 0
2940 GLfloat vertexArray[4*2];
2941 qt_add_rect_to_array(target, vertexArray);
2943 glVertexPointer(2, GL_FLOAT, 0, vertexArray);
2944 glTexCoordPointer(2, GL_FLOAT, 0, texCoordArray);
2946 glEnableClientState(GL_VERTEX_ARRAY);
2947 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
2948 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
2950 glDisableClientState(GL_VERTEX_ARRAY);
2951 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
2954 #endif // !QT_OPENGL_ES_2
2959 This function supports the following use cases:
2962 \i On OpenGL and OpenGL ES 1.x it draws the given texture, \a textureId,
2963 to the given target rectangle, \a target, in OpenGL model space. The
2964 \a textureTarget should be a 2D texture target.
2965 \i On OpenGL and OpenGL ES 2.x, if a painter is active, not inside a
2966 beginNativePainting / endNativePainting block, and uses the
2967 engine with type QPaintEngine::OpenGL2, the function will draw the given
2968 texture, \a textureId, to the given target rectangle, \a target,
2969 respecting the current painter state. This will let you draw a texture
2970 with the clip, transform, render hints, and composition mode set by the
2971 painter. Note that the texture target needs to be GL_TEXTURE_2D for this
2972 use case, and that this is the only supported use case under OpenGL ES 2.x.
2976 void QGLContext::drawTexture(const QRectF &target, GLuint textureId, GLenum textureTarget)
2978 #if !defined(QT_OPENGL_ES) || defined(QT_OPENGL_ES_2)
2979 if (d_ptr->active_engine &&
2980 d_ptr->active_engine->type() == QPaintEngine::OpenGL2) {
2981 QGL2PaintEngineEx *eng = static_cast<QGL2PaintEngineEx*>(d_ptr->active_engine);
2982 if (!eng->isNativePaintingActive()) {
2983 QRectF src(0, 0, target.width(), target.height());
2984 QSize size(target.width(), target.height());
2985 if (eng->drawTexture(target, textureId, size, src))
2991 #ifndef QT_OPENGL_ES_2
2993 if (textureTarget != GL_TEXTURE_2D) {
2994 qWarning("QGLContext::drawTexture(): texture target must be GL_TEXTURE_2D on OpenGL ES");
2998 const bool wasEnabled = glIsEnabled(GL_TEXTURE_2D);
3000 glGetIntegerv(GL_TEXTURE_BINDING_2D, &oldTexture);
3003 glEnable(textureTarget);
3004 glBindTexture(textureTarget, textureId);
3006 qDrawTextureRect(target, -1, -1, textureTarget);
3009 glDisable(textureTarget);
3012 glDisable(textureTarget);
3013 glBindTexture(textureTarget, oldTexture);
3017 Q_UNUSED(textureId);
3018 Q_UNUSED(textureTarget);
3019 qWarning("drawTexture() with OpenGL ES 2.0 requires an active OpenGL2 paint engine");
3023 #ifdef Q_MAC_COMPAT_GL_FUNCTIONS
3025 void QGLContext::drawTexture(const QRectF &target, QMacCompatGLuint textureId, QMacCompatGLenum textureTarget)
3027 drawTexture(target, GLuint(textureId), GLenum(textureTarget));
3034 This function supports the following use cases:
3037 \i By default it draws the given texture, \a textureId,
3038 at the given \a point in OpenGL model space. The
3039 \a textureTarget should be a 2D texture target.
3040 \i If a painter is active, not inside a
3041 beginNativePainting / endNativePainting block, and uses the
3042 engine with type QPaintEngine::OpenGL2, the function will draw the given
3043 texture, \a textureId, at the given \a point,
3044 respecting the current painter state. This will let you draw a texture
3045 with the clip, transform, render hints, and composition mode set by the
3046 painter. Note that the texture target needs to be GL_TEXTURE_2D for this
3050 \note This function is not supported under any version of OpenGL ES.
3052 void QGLContext::drawTexture(const QPointF &point, GLuint textureId, GLenum textureTarget)
3056 Q_UNUSED(textureId);
3057 Q_UNUSED(textureTarget);
3058 qWarning("drawTexture(const QPointF &point, GLuint textureId, GLenum textureTarget) not supported with OpenGL ES, use rect version instead");
3061 const bool wasEnabled = glIsEnabled(GL_TEXTURE_2D);
3063 glGetIntegerv(GL_TEXTURE_BINDING_2D, &oldTexture);
3065 glEnable(textureTarget);
3066 glBindTexture(textureTarget, textureId);
3069 GLint textureHeight;
3071 glGetTexLevelParameteriv(textureTarget, 0, GL_TEXTURE_WIDTH, &textureWidth);
3072 glGetTexLevelParameteriv(textureTarget, 0, GL_TEXTURE_HEIGHT, &textureHeight);
3074 if (d_ptr->active_engine &&
3075 d_ptr->active_engine->type() == QPaintEngine::OpenGL2) {
3076 QGL2PaintEngineEx *eng = static_cast<QGL2PaintEngineEx*>(d_ptr->active_engine);
3077 if (!eng->isNativePaintingActive()) {
3078 QRectF dest(point, QSizeF(textureWidth, textureHeight));
3079 QRectF src(0, 0, textureWidth, textureHeight);
3080 QSize size(textureWidth, textureHeight);
3081 if (eng->drawTexture(dest, textureId, size, src))
3086 qDrawTextureRect(QRectF(point, QSizeF(textureWidth, textureHeight)), textureWidth, textureHeight, textureTarget);
3089 glDisable(textureTarget);
3090 glBindTexture(textureTarget, oldTexture);
3094 #ifdef Q_MAC_COMPAT_GL_FUNCTIONS
3096 void QGLContext::drawTexture(const QPointF &point, QMacCompatGLuint textureId, QMacCompatGLenum textureTarget)
3098 drawTexture(point, GLuint(textureId), GLenum(textureTarget));
3104 This function sets the limit for the texture cache to \a size,
3105 expressed in kilobytes.
3107 By default, the cache limit is approximately 64 MB.
3109 \sa textureCacheLimit()
3111 void QGLContext::setTextureCacheLimit(int size)
3113 QGLTextureCache::instance()->setMaxCost(size);
3117 Returns the current texture cache limit in kilobytes.
3119 \sa setTextureCacheLimit()
3121 int QGLContext::textureCacheLimit()
3123 return QGLTextureCache::instance()->maxCost();
3128 \fn QGLFormat QGLContext::format() const
3130 Returns the frame buffer format that was obtained (this may be a
3131 subset of what was requested).
3133 \sa requestedFormat()
3137 \fn QGLFormat QGLContext::requestedFormat() const
3139 Returns the frame buffer format that was originally requested in
3140 the constructor or setFormat().
3146 Sets a \a format for this context. The context is \link reset()
3149 Call create() to create a new GL context that tries to match the
3152 \snippet doc/src/snippets/code/src_opengl_qgl.cpp 7
3154 \sa format(), reset(), create()
3157 void QGLContext::setFormat(const QGLFormat &format)
3161 d->glFormat = d->reqFormat = format;
3167 void QGLContext::setDevice(QPaintDevice *pDev)
3172 d->paintDevice = pDev;
3173 if (d->paintDevice && (d->paintDevice->devType() != QInternal::Widget
3174 && d->paintDevice->devType() != QInternal::Pixmap
3175 && d->paintDevice->devType() != QInternal::Pbuffer)) {
3176 qWarning("QGLContext: Unsupported paint device type");
3181 \fn bool QGLContext::isValid() const
3183 Returns true if a GL rendering context has been successfully
3184 created; otherwise returns false.
3188 \fn void QGLContext::setValid(bool valid)
3191 Forces the GL rendering context to be valid.
3195 \fn bool QGLContext::isSharing() const
3197 Returns true if this context is sharing its GL context with
3198 another QGLContext, otherwise false is returned. Note that context
3199 sharing might not be supported between contexts with different
3204 Returns true if \a context1 and \a context2 are sharing their
3205 GL resources such as textures, shader programs, etc;
3206 otherwise returns false.
3210 bool QGLContext::areSharing(const QGLContext *context1, const QGLContext *context2)
3212 if (!context1 || !context2)
3214 return context1->d_ptr->group == context2->d_ptr->group;
3218 \fn bool QGLContext::deviceIsPixmap() const
3220 Returns true if the paint device of this context is a pixmap;
3221 otherwise returns false.
3225 \fn bool QGLContext::windowCreated() const
3227 Returns true if a window has been created for this context;
3228 otherwise returns false.
3230 \sa setWindowCreated()
3234 \fn void QGLContext::setWindowCreated(bool on)
3236 If \a on is true the context has had a window created for it. If
3237 \a on is false no window has been created for the context.
3243 \fn uint QGLContext::colorIndex(const QColor& c) const
3247 Returns a colormap index for the color c, in ColorIndex mode. Used
3248 by qglColor() and qglClearColor().
3253 \fn bool QGLContext::initialized() const
3255 Returns true if this context has been initialized, i.e. if
3256 QGLWidget::initializeGL() has been performed on it; otherwise
3259 \sa setInitialized()
3263 \fn void QGLContext::setInitialized(bool on)
3265 If \a on is true the context has been initialized, i.e.
3266 QGLContext::setInitialized() has been called on it. If \a on is
3267 false the context has not been initialized.
3273 \fn const QGLContext* QGLContext::currentContext()
3275 Returns the current context, i.e. the context to which any OpenGL
3276 commands will currently be directed. Returns 0 if no context is
3283 \fn QColor QGLContext::overlayTransparentColor() const
3285 If this context is a valid context in an overlay plane, returns
3286 the plane's transparent color. Otherwise returns an \link
3287 QColor::isValid() invalid \endlink color.
3289 The returned color's \link QColor::pixel() pixel \endlink value is
3290 the index of the transparent color in the colormap of the overlay
3291 plane. (Naturally, the color's RGB values are meaningless.)
3293 The returned QColor object will generally work as expected only
3294 when passed as the argument to QGLWidget::qglColor() or
3295 QGLWidget::qglClearColor(). Under certain circumstances it can
3296 also be used to draw transparent graphics with a QPainter. See the
3297 examples/opengl/overlay_x11 example for details.
3302 Creates the GL context. Returns true if it was successful in
3303 creating a valid GL rendering context on the paint device
3304 specified in the constructor; otherwise returns false (i.e. the
3305 context is invalid).
3307 After successful creation, format() returns the set of features of
3308 the created GL rendering context.
3310 If \a shareContext points to a valid QGLContext, this method will
3311 try to establish OpenGL display list and texture object sharing
3312 between this context and the \a shareContext. Note that this may
3313 fail if the two contexts have different \l {format()} {formats}.
3314 Use isSharing() to see if sharing is in effect.
3316 \warning Implementation note: initialization of C++ class
3317 members usually takes place in the class constructor. QGLContext
3318 is an exception because it must be simple to customize. The
3319 virtual functions chooseContext() (and chooseVisual() for X11) can
3320 be reimplemented in a subclass to select a particular context. The
3321 problem is that virtual functions are not properly called during
3322 construction (even though this is correct C++) because C++
3323 constructs class hierarchies from the bottom up. For this reason
3324 we need a create() function.
3326 \sa chooseContext(), format(), isValid()
3329 bool QGLContext::create(const QGLContext* shareContext)
3333 if (!d->paintDevice && !d->platformContext)
3335 if (!d->paintDevice)
3340 d->valid = chooseContext(shareContext);
3341 if (d->valid && d->paintDevice && d->paintDevice->devType() == QInternal::Widget) {
3342 QWidgetPrivate *wd = qt_widget_private(static_cast<QWidget *>(d->paintDevice));
3343 wd->usesDoubleBufferedGLContext = d->glFormat.doubleBuffer();
3345 #ifndef Q_WS_QPA //We do this in choose context->setupSharing()
3346 if (d->sharing) // ok, we managed to share
3347 QGLContextGroup::addShare(this, shareContext);
3352 bool QGLContext::isValid() const
3354 Q_D(const QGLContext);
3358 void QGLContext::setValid(bool valid)
3364 bool QGLContext::isSharing() const
3366 Q_D(const QGLContext);
3367 return d->group->isSharing();
3370 QGLFormat QGLContext::format() const
3372 Q_D(const QGLContext);
3376 QGLFormat QGLContext::requestedFormat() const
3378 Q_D(const QGLContext);
3379 return d->reqFormat;
3382 QPaintDevice* QGLContext::device() const
3384 Q_D(const QGLContext);
3385 return d->paintDevice;
3388 bool QGLContext::deviceIsPixmap() const
3390 Q_D(const QGLContext);
3391 return d->paintDevice->devType() == QInternal::Pixmap;
3395 bool QGLContext::windowCreated() const
3397 Q_D(const QGLContext);
3402 void QGLContext::setWindowCreated(bool on)
3408 bool QGLContext::initialized() const
3410 Q_D(const QGLContext);
3414 void QGLContext::setInitialized(bool on)
3420 const QGLContext* QGLContext::currentContext()
3423 if (const QPlatformGLContext *threadContext = QPlatformGLContext::currentContext()) {
3424 return QGLContext::fromPlatformGLContext(const_cast<QPlatformGLContext *>(threadContext));
3428 QGLThreadContext *threadContext = qgl_context_storage.localData();
3430 return threadContext->context;
3435 void QGLContextPrivate::setCurrentContext(QGLContext *context)
3440 QGLThreadContext *threadContext = qgl_context_storage.localData();
3441 if (!threadContext) {
3442 if (!QThread::currentThread()) {
3443 // We don't have a current QThread, so just set the static.
3444 QGLContext::currentCtx = context;
3447 threadContext = new QGLThreadContext;
3448 qgl_context_storage.setLocalData(threadContext);
3450 threadContext->context = context;
3451 QGLContext::currentCtx = context; // XXX: backwards-compat, not thread-safe
3456 \fn bool QGLContext::chooseContext(const QGLContext* shareContext = 0)
3458 This semi-internal function is called by create(). It creates a
3459 system-dependent OpenGL handle that matches the format() of \a
3460 shareContext as closely as possible, returning true if successful
3461 or false if a suitable handle could not be found.
3463 On Windows, it calls the virtual function choosePixelFormat(),
3464 which finds a matching pixel format identifier. On X11, it calls
3465 the virtual function chooseVisual() which finds an appropriate X
3466 visual. On other platforms it may work differently.
3469 /*! \fn int QGLContext::choosePixelFormat(void* dummyPfd, HDC pdc)
3471 \bold{Win32 only:} This virtual function chooses a pixel format
3472 that matches the OpenGL \link setFormat() format\endlink.
3473 Reimplement this function in a subclass if you need a custom
3476 \warning The \a dummyPfd pointer and \a pdc are used as a \c
3477 PIXELFORMATDESCRIPTOR*. We use \c void to avoid using
3478 Windows-specific types in our header files.
3483 /*! \fn void *QGLContext::chooseVisual()
3485 \bold{X11 only:} This virtual function tries to find a visual that
3486 matches the format, reducing the demands if the original request
3489 The algorithm for reducing the demands of the format is quite
3490 simple-minded, so override this method in your subclass if your
3491 application has spcific requirements on visual selection.
3496 /*! \fn void *QGLContext::tryVisual(const QGLFormat& f, int bufDepth)
3499 \bold{X11 only:} This virtual function chooses a visual that matches
3500 the OpenGL \link format() format\endlink. Reimplement this function
3501 in a subclass if you need a custom visual.
3507 \fn void QGLContext::reset()
3509 Resets the context and makes it invalid.
3511 \sa create(), isValid()
3516 \fn void QGLContext::makeCurrent()
3518 Makes this context the current OpenGL rendering context. All GL
3519 functions you call operate on this context until another context
3522 In some very rare cases the underlying call may fail. If this
3523 occurs an error message is output to stderr.
3528 \fn void QGLContext::swapBuffers() const
3530 Swaps the screen contents with an off-screen buffer. Only works if
3531 the context is in double buffer mode.
3533 \sa QGLFormat::setDoubleBuffer()
3538 \fn void QGLContext::doneCurrent()
3540 Makes no GL context the current context. Normally, you do not need
3541 to call this function; QGLContext calls it as necessary.
3546 \fn QPaintDevice* QGLContext::device() const
3548 Returns the paint device set for this context.
3550 \sa QGLContext::QGLContext()
3555 \fn void QGLContext::generateFontDisplayLists(const QFont& font, int listBase)
3557 Generates a set of 256 display lists for the 256 first characters
3558 in the font \a font. The first list will start at index \a listBase.
3560 \sa QGLWidget::renderText()
3565 /*****************************************************************************
3566 QGLWidget implementation
3567 *****************************************************************************/
3572 \brief The QGLWidget class is a widget for rendering OpenGL graphics.
3574 \ingroup painting-3D
3577 QGLWidget provides functionality for displaying OpenGL graphics
3578 integrated into a Qt application. It is very simple to use. You
3579 inherit from it and use the subclass like any other QWidget,
3580 except that you have the choice between using QPainter and
3581 standard OpenGL rendering commands.
3583 QGLWidget provides three convenient virtual functions that you can
3584 reimplement in your subclass to perform the typical OpenGL tasks:
3587 \i paintGL() - Renders the OpenGL scene. Gets called whenever the widget
3588 needs to be updated.
3589 \i resizeGL() - Sets up the OpenGL viewport, projection, etc. Gets
3590 called whenever the widget has been resized (and also when it
3591 is shown for the first time because all newly created widgets get a
3592 resize event automatically).
3593 \i initializeGL() - Sets up the OpenGL rendering context, defines display
3594 lists, etc. Gets called once before the first time resizeGL() or
3595 paintGL() is called.
3598 Here is a rough outline of how a QGLWidget subclass might look:
3600 \snippet doc/src/snippets/code/src_opengl_qgl.cpp 8
3602 If you need to trigger a repaint from places other than paintGL()
3603 (a typical example is when using \link QTimer timers\endlink to
3604 animate scenes), you should call the widget's updateGL() function.
3606 Your widget's OpenGL rendering context is made current when
3607 paintGL(), resizeGL(), or initializeGL() is called. If you need to
3608 call the standard OpenGL API functions from other places (e.g. in
3609 your widget's constructor or in your own paint functions), you
3610 must call makeCurrent() first.
3612 QGLWidget provides functions for requesting a new display \link
3613 QGLFormat format\endlink and you can also create widgets with
3614 customized rendering \link QGLContext contexts\endlink.
3616 You can also share OpenGL display lists between QGLWidget objects (see
3617 the documentation of the QGLWidget constructors for details).
3619 Note that under Windows, the QGLContext belonging to a QGLWidget
3620 has to be recreated when the QGLWidget is reparented. This is
3621 necessary due to limitations on the Windows platform. This will
3622 most likely cause problems for users that have subclassed and
3623 installed their own QGLContext on a QGLWidget. It is possible to
3624 work around this issue by putting the QGLWidget inside a dummy
3625 widget and then reparenting the dummy widget, instead of the
3626 QGLWidget. This will side-step the issue altogether, and is what
3627 we recommend for users that need this kind of functionality.
3629 On Mac OS X, when Qt is built with Cocoa support, a QGLWidget
3630 can't have any sibling widgets placed ontop of itself. This is due
3631 to limitations in the Cocoa API and is not supported by Apple.
3635 The QGLWidget creates a GL overlay context in addition to the
3636 normal context if overlays are supported by the underlying system.
3638 If you want to use overlays, you specify it in the \link QGLFormat
3639 format\endlink. (Note: Overlay must be requested in the format
3640 passed to the QGLWidget constructor.) Your GL widget should also
3641 implement some or all of these virtual methods:
3645 \i resizeOverlayGL()
3646 \i initializeOverlayGL()
3649 These methods work in the same way as the normal paintGL() etc.
3650 functions, except that they will be called when the overlay
3651 context is made current. You can explicitly make the overlay
3652 context current by using makeOverlayCurrent(), and you can access
3653 the overlay context directly (e.g. to ask for its transparent
3654 color) by calling overlayContext().
3656 On X servers in which the default visual is in an overlay plane,
3657 non-GL Qt windows can also be used for overlays.
3659 \section1 Painting Techniques
3661 As described above, subclass QGLWidget to render pure 3D content in the
3665 \o Reimplement the QGLWidget::initializeGL() and QGLWidget::resizeGL() to
3666 set up the OpenGL state and provide a perspective transformation.
3667 \o Reimplement QGLWidget::paintGL() to paint the 3D scene, calling only
3668 OpenGL functions to draw on the widget.
3671 It is also possible to draw 2D graphics onto a QGLWidget subclass, it is necessary
3672 to reimplement QGLWidget::paintEvent() and do the following:
3675 \o Construct a QPainter object.
3676 \o Initialize it for use on the widget with the QPainter::begin() function.
3677 \o Draw primitives using QPainter's member functions.
3678 \o Call QPainter::end() to finish painting.
3681 Overpainting 2D content on top of 3D content takes a little more effort.
3682 One approach to doing this is shown in the
3683 \l{Overpainting Example}{Overpainting} example.
3687 As of Qt version 4.8, support for doing threaded GL rendering has
3688 been improved. There are three scenarios that we currently support:
3690 \o 1. Buffer swapping in a thread.
3692 Swapping buffers in a double buffered context may be a
3693 synchronous, locking call that may be a costly operation in some
3694 GL implementations. Especially so on embedded devices. It's not
3695 optimal to have the CPU idling while the GPU is doing a buffer
3696 swap. In those cases it is possible to do the rendering in the
3697 main thread and do the actual buffer swap in a separate
3698 thread. This can be done with the following steps:
3700 1. Call doneCurrent() in the main thread when the rendering is
3703 2. Notify the swapping thread that it can grab the context.
3705 3. Make the rendering context current in the swapping thread with
3706 makeCurrent() and then call swapBuffers().
3708 4. Call doneCurrent() in the swapping thread and notify the main
3709 thread that swapping is done.
3711 Doing this will free up the main thread so that it can continue
3712 with, for example, handling UI events or network requests. Even if
3713 there is a context swap involved, it may be preferable compared to
3714 having the main thread wait while the GPU finishes the swap
3715 operation. Note that this is highly implementation dependent.
3717 \o 2. Texture uploading in a thread.
3719 Doing texture uploads in a thread may be very useful for
3720 applications handling large amounts of images that needs to be
3721 displayed, like for instance a photo gallery application. This is
3722 supported in Qt through the existing bindTexture() API. A simple
3723 way of doing this is to create two sharing QGLWidgets. One is made
3724 current in the main GUI thread, while the other is made current in
3725 the texture upload thread. The widget in the uploading thread is
3726 never shown, it is only used for sharing textures with the main
3727 thread. For each texture that is bound via bindTexture(), notify
3728 the main thread so that it can start using the texture.
3730 \o 3. Using QPainter to draw into a QGLWidget in a thread.
3732 In Qt 4.8, it is possible to draw into a QGLWidget using a
3733 QPainter in a separate thread. Note that this is also possible for
3734 QGLPixelBuffers and QGLFramebufferObjects. Since this is only
3735 supported in the GL 2 paint engine, OpenGL 2.0 or OpenGL ES 2.0 is
3738 QGLWidgets can only be created in the main GUI thread. This means
3739 a call to doneCurrent() is necessary to release the GL context
3740 from the main thread, before the widget can be drawn into by
3741 another thread. Also, the main GUI thread will dispatch resize and
3742 paint events to a QGLWidget when the widget is resized, or parts
3743 of it becomes exposed or needs redrawing. It is therefore
3744 necessary to handle those events because the default
3745 implementations inside QGLWidget will try to make the QGLWidget's
3746 context current, which again will interfere with any threads
3747 rendering into the widget. Reimplement QGLWidget::paintEvent() and
3748 QGLWidget::resizeEvent() to notify the rendering thread that a
3749 resize or update is necessary, and be careful not to call the base
3750 class implementation. If you are rendering an animation, it might
3751 not be necessary to handle the paint event at all since the
3752 rendering thread is doing regular updates. Then it would be enough
3753 to reimplement QGLWidget::paintEvent() to do nothing.
3757 As a general rule when doing threaded rendering: be aware that
3758 binding and releasing contexts in different threads have to be
3759 synchronized by the user. A GL rendering context can only be
3760 current in one thread at any time. If you try to open a QPainter
3761 on a QGLWidget and the widget's rendering context is current in
3762 another thread, it will fail.
3764 Note that under X11 it is necessary to set the
3765 Qt::AA_X11InitThreads application attribute to make the X11
3766 library and GLX calls thread safe, otherwise the above scenarios
3769 In addition to this, rendering using raw GL calls in a separate
3770 thread is supported.
3772 \e{OpenGL is a trademark of Silicon Graphics, Inc. in the United States and other
3775 \sa QGLPixelBuffer, {Hello GL Example}, {2D Painting Example}, {Overpainting Example},
3780 Constructs an OpenGL widget with a \a parent widget.
3782 The \link QGLFormat::defaultFormat() default format\endlink is
3783 used. The widget will be \link isValid() invalid\endlink if the
3784 system has no \link QGLFormat::hasOpenGL() OpenGL support\endlink.
3786 The \a parent and widget flag, \a f, arguments are passed
3787 to the QWidget constructor.
3789 If \a shareWidget is a valid QGLWidget, this widget will share
3790 OpenGL display lists and texture objects with \a shareWidget. But
3791 if \a shareWidget and this widget have different \l {format()}
3792 {formats}, sharing might not be possible. You can check whether
3793 sharing is in effect by calling isSharing().
3795 The initialization of OpenGL rendering state, etc. should be done
3796 by overriding the initializeGL() function, rather than in the
3797 constructor of your QGLWidget subclass.
3799 \sa QGLFormat::defaultFormat(), {Textures Example}
3802 QGLWidget::QGLWidget(QWidget *parent, const QGLWidget* shareWidget, Qt::WindowFlags f)
3803 : QWidget(*(new QGLWidgetPrivate), parent, f | Qt::MSWindowsOwnDC)
3806 setAttribute(Qt::WA_PaintOnScreen);
3807 setAttribute(Qt::WA_NoSystemBackground);
3808 setAutoFillBackground(true); // for compatibility
3809 d->init(new QGLContext(QGLFormat::defaultFormat(), this), shareWidget);
3815 QGLWidget::QGLWidget(QGLWidgetPrivate &dd, const QGLFormat &format, QWidget *parent, const QGLWidget *shareWidget, Qt::WindowFlags f)
3816 : QWidget(dd, parent, f | Qt::MSWindowsOwnDC)
3819 setAttribute(Qt::WA_PaintOnScreen);
3820 setAttribute(Qt::WA_NoSystemBackground);
3821 setAutoFillBackground(true); // for compatibility
3822 d->init(new QGLContext(format, this), shareWidget);
3828 Constructs an OpenGL widget with parent \a parent.
3830 The \a format argument specifies the desired \link QGLFormat
3831 rendering options \endlink. If the underlying OpenGL/Window system
3832 cannot satisfy all the features requested in \a format, the
3833 nearest subset of features will be used. After creation, the
3834 format() method will return the actual format obtained.
3836 The widget will be \link isValid() invalid\endlink if the system
3837 has no \link QGLFormat::hasOpenGL() OpenGL support\endlink.
3839 The \a parent and widget flag, \a f, arguments are passed
3840 to the QWidget constructor.
3842 If \a shareWidget is a valid QGLWidget, this widget will share
3843 OpenGL display lists and texture objects with \a shareWidget. But
3844 if \a shareWidget and this widget have different \l {format()}
3845 {formats}, sharing might not be possible. You can check whether
3846 sharing is in effect by calling isSharing().
3848 The initialization of OpenGL rendering state, etc. should be done
3849 by overriding the initializeGL() function, rather than in the
3850 constructor of your QGLWidget subclass.
3852 \sa QGLFormat::defaultFormat(), isValid()
3855 QGLWidget::QGLWidget(const QGLFormat &format, QWidget *parent, const QGLWidget* shareWidget,
3857 : QWidget(*(new QGLWidgetPrivate), parent, f | Qt::MSWindowsOwnDC)
3860 setAttribute(Qt::WA_PaintOnScreen);
3861 setAttribute(Qt::WA_NoSystemBackground);
3862 setAutoFillBackground(true); // for compatibility
3863 d->init(new QGLContext(format, this), shareWidget);
3867 Constructs an OpenGL widget with parent \a parent.
3869 The \a context argument is a pointer to the QGLContext that
3870 you wish to be bound to this widget. This allows you to pass in
3871 your own QGLContext sub-classes.
3873 The widget will be \link isValid() invalid\endlink if the system
3874 has no \link QGLFormat::hasOpenGL() OpenGL support\endlink.
3876 The \a parent and widget flag, \a f, arguments are passed
3877 to the QWidget constructor.
3879 If \a shareWidget is a valid QGLWidget, this widget will share
3880 OpenGL display lists and texture objects with \a shareWidget. But
3881 if \a shareWidget and this widget have different \l {format()}
3882 {formats}, sharing might not be possible. You can check whether
3883 sharing is in effect by calling isSharing().
3885 The initialization of OpenGL rendering state, etc. should be done
3886 by overriding the initializeGL() function, rather than in the
3887 constructor of your QGLWidget subclass.
3889 \sa QGLFormat::defaultFormat(), isValid()
3891 QGLWidget::QGLWidget(QGLContext *context, QWidget *parent, const QGLWidget *shareWidget,
3893 : QWidget(*(new QGLWidgetPrivate), parent, f | Qt::MSWindowsOwnDC)
3896 setAttribute(Qt::WA_PaintOnScreen);
3897 setAttribute(Qt::WA_NoSystemBackground);
3898 setAutoFillBackground(true); // for compatibility
3899 d->init(context, shareWidget);
3903 Destroys the widget.
3906 QGLWidget::~QGLWidget()
3909 #if defined(GLX_MESA_release_buffers) && defined(QGL_USE_MESA_EXT)
3910 bool doRelease = (glcx && glcx->windowCreated());
3914 #if defined(Q_WS_WIN)
3918 #if defined(GLX_MESA_release_buffers) && defined(QGL_USE_MESA_EXT)
3920 glXReleaseBuffersMESA(x11Display(), winId());
3922 d->cleanupColormaps();
3925 QWidget *current = parentWidget();
3927 qt_widget_private(current)->glWidgets.removeAll(QWidgetPrivate::GlWidgetInfo(this));
3928 if (current->isWindow())
3930 current = current->parentWidget();
3936 \fn QGLFormat QGLWidget::format() const
3938 Returns the format of the contained GL rendering context.
3942 \fn bool QGLWidget::doubleBuffer() const
3944 Returns true if the contained GL rendering context has double
3945 buffering; otherwise returns false.
3947 \sa QGLFormat::doubleBuffer()
3951 \fn void QGLWidget::setAutoBufferSwap(bool on)
3953 If \a on is true automatic GL buffer swapping is switched on;
3954 otherwise it is switched off.
3956 If \a on is true and the widget is using a double-buffered format,
3957 the background and foreground GL buffers will automatically be
3958 swapped after each paintGL() call.
3960 The buffer auto-swapping is on by default.
3962 \sa autoBufferSwap(), doubleBuffer(), swapBuffers()
3966 \fn bool QGLWidget::autoBufferSwap() const
3968 Returns true if the widget is doing automatic GL buffer swapping;
3969 otherwise returns false.
3971 \sa setAutoBufferSwap()
3975 \fn void *QGLContext::getProcAddress(const QString &proc) const
3977 Returns a function pointer to the GL extension function passed in
3978 \a proc. 0 is returned if a pointer to the function could not be
3983 \fn bool QGLWidget::isValid() const
3985 Returns true if the widget has a valid GL rendering context;
3986 otherwise returns false. A widget will be invalid if the system
3987 has no \link QGLFormat::hasOpenGL() OpenGL support\endlink.
3990 bool QGLWidget::isValid() const
3992 Q_D(const QGLWidget);
3993 return d->glcx && d->glcx->isValid();
3997 \fn bool QGLWidget::isSharing() const
3999 Returns true if this widget's GL context is shared with another GL
4000 context, otherwise false is returned. Context sharing might not be
4001 possible if the widgets use different formats.
4006 bool QGLWidget::isSharing() const
4008 Q_D(const QGLWidget);
4009 return d->glcx->isSharing();
4013 \fn void QGLWidget::makeCurrent()
4015 Makes this widget the current widget for OpenGL operations, i.e.
4016 makes the widget's rendering context the current OpenGL rendering
4020 void QGLWidget::makeCurrent()
4023 d->glcx->makeCurrent();
4027 \fn void QGLWidget::doneCurrent()
4029 Makes no GL context the current context. Normally, you do not need
4030 to call this function; QGLContext calls it as necessary. However,
4031 it may be useful in multithreaded environments.
4034 void QGLWidget::doneCurrent()
4037 d->glcx->doneCurrent();
4041 \fn void QGLWidget::swapBuffers()
4043 Swaps the screen contents with an off-screen buffer. This only
4044 works if the widget's format specifies double buffer mode.
4046 Normally, there is no need to explicitly call this function
4047 because it is done automatically after each widget repaint, i.e.
4048 each time after paintGL() has been executed.
4050 \sa doubleBuffer(), setAutoBufferSwap(), QGLFormat::setDoubleBuffer()
4053 void QGLWidget::swapBuffers()
4056 d->glcx->swapBuffers();
4061 \fn const QGLContext* QGLWidget::overlayContext() const
4063 Returns the overlay context of this widget, or 0 if this widget
4072 \fn void QGLWidget::makeOverlayCurrent()
4074 Makes the overlay context of this widget current. Use this if you
4075 need to issue OpenGL commands to the overlay context outside of
4076 initializeOverlayGL(), resizeOverlayGL(), and paintOverlayGL().
4078 Does nothing if this widget has no overlay.
4087 Sets a new format for this widget.
4089 If the underlying OpenGL/Window system cannot satisfy all the
4090 features requested in \a format, the nearest subset of features will
4091 be used. After creation, the format() method will return the actual
4092 rendering context format obtained.
4094 The widget will be assigned a new QGLContext, and the initializeGL()
4095 function will be executed for this new context before the first
4096 resizeGL() or paintGL().
4098 This method will try to keep display list and texture object sharing
4099 in effect with other QGLWidget objects, but changing the format might make
4100 sharing impossible. Use isSharing() to see if sharing is still in
4103 \sa format(), isSharing(), isValid()
4106 void QGLWidget::setFormat(const QGLFormat &format)
4108 setContext(new QGLContext(format,this));
4115 \fn const QGLContext *QGLWidget::context() const
4117 Returns the context of this widget.
4119 It is possible that the context is not valid (see isValid()), for
4120 example, if the underlying hardware does not support the format
4121 attributes that were requested.
4125 \fn void QGLWidget::setContext(QGLContext *context,
4126 const QGLContext* shareContext,
4127 bool deleteOldContext)
4130 Sets a new context for this widget. The QGLContext \a context must
4131 be created using \e new. QGLWidget will delete \a context when
4132 another context is set or when the widget is destroyed.
4134 If \a context is invalid, QGLContext::create() is performed on
4135 it. The initializeGL() function will then be executed for the new
4136 context before the first resizeGL() or paintGL().
4138 If \a context is invalid, this method will try to keep display list
4139 and texture object sharing in effect, or (if \a shareContext points
4140 to a valid context) start display list and texture object sharing
4141 with that context, but sharing might be impossible if the two
4142 contexts have different \l {format()} {formats}. Use isSharing() to
4143 see whether sharing is in effect.
4145 If \a deleteOldContext is true (the default), the existing context
4146 will be deleted. You may use false here if you have kept a pointer
4147 to the old context (as returned by context()), and want to restore
4150 \sa context(), isSharing()
4156 \fn void QGLWidget::updateGL()
4158 Updates the widget by calling glDraw().
4161 void QGLWidget::updateGL()
4163 if (updatesEnabled())
4169 \fn void QGLWidget::updateOverlayGL()
4171 Updates the widget's overlay (if any). Will cause the virtual
4172 function paintOverlayGL() to be executed.
4174 The widget's rendering context will become the current context and
4175 initializeGL() will be called if it hasn't already been called.
4180 This virtual function is called once before the first call to
4181 paintGL() or resizeGL(), and then once whenever the widget has
4182 been assigned a new QGLContext. Reimplement it in a subclass.
4184 This function should set up any required OpenGL context rendering
4185 flags, defining display lists, etc.
4187 There is no need to call makeCurrent() because this has already
4188 been done when this function is called.
4191 void QGLWidget::initializeGL()
4197 This virtual function is called whenever the widget needs to be
4198 painted. Reimplement it in a subclass.
4200 There is no need to call makeCurrent() because this has already
4201 been done when this function is called.
4204 void QGLWidget::paintGL()
4210 \fn void QGLWidget::resizeGL(int width , int height)
4212 This virtual function is called whenever the widget has been
4213 resized. The new size is passed in \a width and \a height.
4214 Reimplement it in a subclass.
4216 There is no need to call makeCurrent() because this has already
4217 been done when this function is called.
4220 void QGLWidget::resizeGL(int, int)
4227 This virtual function is used in the same manner as initializeGL()
4228 except that it operates on the widget's overlay context instead of
4229 the widget's main context. This means that initializeOverlayGL()
4230 is called once before the first call to paintOverlayGL() or
4231 resizeOverlayGL(). Reimplement it in a subclass.
4233 This function should set up any required OpenGL context rendering
4234 flags, defining display lists, etc. for the overlay context.
4236 There is no need to call makeOverlayCurrent() because this has
4237 already been done when this function is called.
4240 void QGLWidget::initializeOverlayGL()
4246 This virtual function is used in the same manner as paintGL()
4247 except that it operates on the widget's overlay context instead of
4248 the widget's main context. This means that paintOverlayGL() is
4249 called whenever the widget's overlay needs to be painted.
4250 Reimplement it in a subclass.
4252 There is no need to call makeOverlayCurrent() because this has
4253 already been done when this function is called.
4256 void QGLWidget::paintOverlayGL()
4262 \fn void QGLWidget::resizeOverlayGL(int width , int height)
4264 This virtual function is used in the same manner as paintGL()
4265 except that it operates on the widget's overlay context instead of
4266 the widget's main context. This means that resizeOverlayGL() is
4267 called whenever the widget has been resized. The new size is
4268 passed in \a width and \a height. Reimplement it in a subclass.
4270 There is no need to call makeOverlayCurrent() because this has
4271 already been done when this function is called.
4274 void QGLWidget::resizeOverlayGL(int, int)
4278 /*! \fn bool QGLWidget::event(QEvent *e)
4281 #if !defined(Q_OS_WINCE) && !defined(Q_WS_QWS) && !defined(Q_WS_QPA)
4282 bool QGLWidget::event(QEvent *e)
4286 if (e->type() == QEvent::Paint) {
4288 QPaintDevice *redirectedDevice = d->redirected(&offset);
4289 if (redirectedDevice && redirectedDevice->devType() == QInternal::Pixmap) {
4290 d->restoreRedirected();
4291 QPixmap pixmap = renderPixmap();
4292 d->setRedirected(redirectedDevice, offset);
4293 QPainter p(redirectedDevice);
4294 p.drawPixmap(-offset, pixmap);
4299 #if defined(Q_WS_X11)
4300 if (e->type() == QEvent::ParentChange) {
4301 // if we've reparented a window that has the current context
4302 // bound, we need to rebind that context to the new window id
4303 if (d->glcx == QGLContext::currentContext())
4306 if (d->glcx->d_func()->screen != d->xinfo.screen() || testAttribute(Qt::WA_TranslucentBackground)) {
4307 setContext(new QGLContext(d->glcx->requestedFormat(), this));
4308 // ### recreating the overlay isn't supported atm
4313 // A re-parent is likely to destroy the X11 window and re-create it. It is important
4314 // that we free the EGL surface _before_ the winID changes - otherwise we can leak.
4315 if (e->type() == QEvent::ParentAboutToChange)
4316 d->glcx->d_func()->destroyEglSurfaceForDevice();
4318 if ((e->type() == QEvent::ParentChange) || (e->type() == QEvent::WindowStateChange)) {
4319 // The window may have been re-created during re-parent or state change - if so, the EGL
4320 // surface will need to be re-created.
4321 d->recreateEglSurface();
4324 #elif defined(Q_WS_WIN)
4325 if (e->type() == QEvent::ParentChange) {
4326 QGLContext *newContext = new QGLContext(d->glcx->requestedFormat(), this);
4327 setContext(newContext, d->glcx);
4329 // the overlay needs to be recreated as well
4331 if (isValid() && context()->format().hasOverlay()) {
4332 d->olcx = new QGLContext(QGLFormat::defaultOverlayFormat(), this);
4333 if (!d->olcx->create(isSharing() ? d->glcx : 0)) {
4336 d->glcx->d_func()->glFormat.setOverlay(false);
4341 } else if (e->type() == QEvent::Show) {
4342 if (!format().rgba())
4343 d->updateColormap();
4345 #elif defined(Q_WS_MAC)
4346 if (e->type() == QEvent::MacGLWindowChange
4347 #if 0 //(MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5)
4348 && ((QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5 && isWindow())
4349 || QSysInfo::MacintoshVersion <= QSysInfo::MV_10_4)
4352 if (d->needWindowChange) {
4353 d->needWindowChange = false;
4354 d->glcx->updatePaintDevice();
4358 # if defined(QT_MAC_USE_COCOA)
4359 } else if (e->type() == QEvent::MacGLClearDrawable) {
4360 d->glcx->d_ptr->clearDrawable();
4363 #elif defined(Q_OS_SYMBIAN)
4364 // prevents errors on some systems, where we get a flush to a
4366 if (e->type() == QEvent::Hide) {
4370 } else if (e->type() == QEvent::ParentChange) {
4371 // if we've reparented a window that has the current context
4372 // bound, we need to rebind that context to the new window id
4373 if (d->glcx == QGLContext::currentContext())
4376 if (testAttribute(Qt::WA_TranslucentBackground))
4377 setContext(new QGLContext(d->glcx->requestedFormat(), this));
4380 // A re-parent is likely to destroy the Symbian window and re-create it. It is important
4381 // that we free the EGL surface _before_ the winID changes - otherwise we can leak.
4382 if (e->type() == QEvent::ParentAboutToChange)
4383 d->glcx->d_func()->destroyEglSurfaceForDevice();
4385 if ((e->type() == QEvent::ParentChange) || (e->type() == QEvent::WindowStateChange)) {
4386 // The window may have been re-created during re-parent or state change - if so, the EGL
4387 // surface will need to be re-created.
4388 d->recreateEglSurface();
4393 return QWidget::event(e);
4398 \fn void QGLWidget::paintEvent(QPaintEvent *event)
4400 Handles paint events passed in the \a event parameter. Will cause
4401 the virtual paintGL() function to be called.
4403 The widget's rendering context will become the current context and
4404 initializeGL() will be called if it hasn't already been called.
4407 void QGLWidget::paintEvent(QPaintEvent *)
4409 if (updatesEnabled()) {
4417 \fn void QGLWidget::resizeEvent(QResizeEvent *event)
4419 Handles resize events that are passed in the \a event parameter.
4420 Calls the virtual function resizeGL().
4425 \fn void QGLWidget::setMouseTracking(bool enable)
4427 If \a enable is true then mouse tracking is enabled; otherwise it
4433 Renders the current scene on a pixmap and returns the pixmap.
4435 You can use this method on both visible and invisible QGLWidget objects.
4437 This method will create a pixmap and a temporary QGLContext to
4438 render on the pixmap. It will then call initializeGL(),
4439 resizeGL(), and paintGL() on this context. Finally, the widget's
4440 original GL context is restored.
4442 The size of the pixmap will be \a w pixels wide and \a h pixels
4443 high unless one of these parameters is 0 (the default), in which
4444 case the pixmap will have the same size as the widget.
4446 If \a useContext is true, this method will try to be more
4447 efficient by using the existing GL context to render the pixmap.
4448 The default is false. Only use true if you understand the risks.
4449 Note that under Windows a temporary context has to be created
4450 and usage of the \e useContext parameter is not supported.
4452 Overlays are not rendered onto the pixmap.
4454 If the GL rendering context and the desktop have different bit
4455 depths, the result will most likely look surprising.
4457 Note that the creation of display lists, modifications of the view
4458 frustum etc. should be done from within initializeGL(). If this is
4459 not done, the temporary QGLContext will not be initialized
4460 properly, and the rendered pixmap may be incomplete/corrupted.
4463 QPixmap QGLWidget::renderPixmap(int w, int h, bool useContext)
4467 if ((w > 0) && (h > 0))
4470 #if defined(Q_WS_X11)
4471 extern int qt_x11_preferred_pixmap_depth;
4472 int old_depth = qt_x11_preferred_pixmap_depth;
4473 qt_x11_preferred_pixmap_depth = x11Info().depth();
4475 QPixmapData *data = new QX11PixmapData(QPixmapData::PixmapType);
4476 data->resize(sz.width(), sz.height());
4478 qt_x11_preferred_pixmap_depth = old_depth;
4479 QX11Info xinfo = x11Info();
4481 // make sure we use a pixmap with the same depth/visual as the widget
4482 if (xinfo.visual() != QX11Info::appVisual()) {
4483 QX11InfoData* xd = pm.x11Info().getX11Data(true);
4484 xd->depth = xinfo.depth();
4485 xd->visual = static_cast<Visual *>(xinfo.visual());
4486 const_cast<QX11Info &>(pm.x11Info()).setX11Data(xd);
4493 d->glcx->doneCurrent();
4495 bool success = true;
4497 if (useContext && isValid() && d->renderCxPm(&pm))
4500 QGLFormat fmt = d->glcx->requestedFormat();
4501 fmt.setDirectRendering(false); // Direct is unlikely to work
4502 fmt.setDoubleBuffer(false); // We don't need dbl buf
4503 #ifdef Q_WS_MAC // crash prevention on the Mac - it's unlikely to work anyway
4504 fmt.setSampleBuffers(false);
4507 QGLContext* ocx = d->glcx;
4509 d->glcx = new QGLContext(fmt, &pm);
4512 if (d->glcx->isValid())
4523 #if defined(Q_WS_X11)
4524 if (xinfo.visual() != QX11Info::appVisual()) {
4525 QImage image = pm.toImage();
4526 QPixmap p = QPixmap::fromImage(image);
4536 Returns an image of the frame buffer. If \a withAlpha is true the
4537 alpha channel is included.
4539 Depending on your hardware, you can explicitly select which color
4540 buffer to grab with a glReadBuffer() call before calling this
4543 QImage QGLWidget::grabFrameBuffer(bool withAlpha)
4549 if (format().rgba()) {
4550 res = qt_gl_read_framebuffer(QSize(w, h), format().alpha(), withAlpha);
4552 #if defined (Q_WS_WIN) && !defined(QT_OPENGL_ES)
4553 res = QImage(w, h, QImage::Format_Indexed8);
4554 glReadPixels(0, 0, w, h, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, res.bits());
4555 const QVector<QColor> pal = QColormap::instance().colormap();
4557 res.setColorCount(pal.size());
4558 for (int i = 0; i < pal.size(); i++)
4559 res.setColor(i, pal.at(i).rgb());
4561 res = res.mirrored();
4571 Initializes OpenGL for this widget's context. Calls the virtual
4572 function initializeGL().
4575 void QGLWidget::glInit()
4582 d->glcx->setInitialized(true);
4587 Executes the virtual function paintGL().
4589 The widget's rendering context will become the current context and
4590 initializeGL() will be called if it hasn't already been called.
4593 void QGLWidget::glDraw()
4599 // Crashes on Symbian if trying to render to invisible surfaces
4600 if (!isVisible() && d->glcx->device()->devType() == QInternal::Widget)
4604 #ifndef QT_OPENGL_ES
4605 if (d->glcx->deviceIsPixmap())
4606 glDrawBuffer(GL_FRONT);
4608 if (!d->glcx->initialized()) {
4610 resizeGL(d->glcx->device()->width(), d->glcx->device()->height()); // New context needs this "resize"
4613 if (doubleBuffer()) {
4622 Convenience function for specifying a drawing color to OpenGL.
4623 Calls glColor4 (in RGBA mode) or glIndex (in color-index mode)
4624 with the color \a c. Applies to this widgets GL context.
4626 \note This function is not supported on OpenGL/ES 2.0 systems.
4628 \sa qglClearColor(), QGLContext::currentContext(), QColor
4631 void QGLWidget::qglColor(const QColor& c) const
4633 #if !defined(QT_OPENGL_ES_2)
4635 glColor4f(c.redF(), c.greenF(), c.blueF(), c.alphaF());
4637 Q_D(const QGLWidget);
4638 const QGLContext *ctx = QGLContext::currentContext();
4640 if (ctx->format().rgba())
4641 glColor4f(c.redF(), c.greenF(), c.blueF(), c.alphaF());
4642 else if (!d->cmap.isEmpty()) { // QGLColormap in use?
4643 int i = d->cmap.find(c.rgb());
4645 i = d->cmap.findNearest(c.rgb());
4648 glIndexi(ctx->colorIndex(c));
4650 #endif //QT_OPENGL_ES
4653 #endif //QT_OPENGL_ES_2
4657 Convenience function for specifying the clearing color to OpenGL.
4658 Calls glClearColor (in RGBA mode) or glClearIndex (in color-index
4659 mode) with the color \a c. Applies to this widgets GL context.
4661 \sa qglColor(), QGLContext::currentContext(), QColor
4664 void QGLWidget::qglClearColor(const QColor& c) const
4667 glClearColor(c.redF(), c.greenF(), c.blueF(), c.alphaF());
4669 Q_D(const QGLWidget);
4670 const QGLContext *ctx = QGLContext::currentContext();
4672 if (ctx->format().rgba())
4673 glClearColor(c.redF(), c.greenF(), c.blueF(), c.alphaF());
4674 else if (!d->cmap.isEmpty()) { // QGLColormap in use?
4675 int i = d->cmap.find(c.rgb());
4677 i = d->cmap.findNearest(c.rgb());
4680 glClearIndex(ctx->colorIndex(c));
4687 Converts the image \a img into the unnamed format expected by
4688 OpenGL functions such as glTexImage2D(). The returned image is not
4689 usable as a QImage, but QImage::width(), QImage::height() and
4690 QImage::bits() may be used with OpenGL. The GL format used is
4695 \l opengl/texture example
4696 The following few lines are from the texture example. Most of the
4697 code is irrelevant, so we just quote the relevant bits:
4699 \quotefromfile opengl/texture/gltexobj.cpp
4702 \printline gllogo.bmp
4704 We create \e tex1 (and another variable) for OpenGL, and load a real
4707 \skipto convertToGLFormat
4708 \printline convertToGLFormat
4710 A few lines later, we convert \e buf into OpenGL format and store it
4713 \skipto glTexImage2D
4714 \printline glTexImage2D
4715 \printline tex1.bits
4717 Note the dimension restrictions for texture images as described in
4718 the glTexImage2D() documentation. The width must be 2^m + 2*border
4719 and the height 2^n + 2*border where m and n are integers and
4720 border is either 0 or 1.
4722 Another function in the same example uses \e tex1 with OpenGL.
4727 QImage QGLWidget::convertToGLFormat(const QImage& img)
4729 QImage res(img.size(), QImage::Format_ARGB32);
4730 convertToGLFormatHelper(res, img.convertToFormat(QImage::Format_ARGB32), GL_RGBA);
4736 \fn QGLColormap & QGLWidget::colormap() const
4738 Returns the colormap for this widget.
4740 Usually it is only top-level widgets that can have different
4741 colormaps installed. Asking for the colormap of a child widget
4742 will return the colormap for the child's top-level widget.
4744 If no colormap has been set for this widget, the QGLColormap
4745 returned will be empty.
4747 \sa setColormap(), QGLColormap::isEmpty()
4751 \fn void QGLWidget::setColormap(const QGLColormap & cmap)
4753 Set the colormap for this widget to \a cmap. Usually it is only
4754 top-level widgets that can have colormaps installed.
4763 Returns the value of the first display list that is generated for
4764 the characters in the given \a font. \a listBase indicates the base
4765 value used when generating the display lists for the font. The
4766 default value is 2000.
4768 \note This function is not supported on OpenGL/ES systems.
4770 int QGLWidget::fontDisplayListBase(const QFont & font, int listBase)
4772 #ifndef QT_OPENGL_ES
4776 if (!d->glcx) { // this can't happen unless we run out of mem
4780 // always regenerate font disp. lists for pixmaps - hw accelerated
4781 // contexts can't handle this otherwise
4782 bool regenerate = d->glcx->deviceIsPixmap();
4783 #ifndef QT_NO_FONTCONFIG
4784 // font color needs to be part of the font cache key when using
4785 // antialiased fonts since one set of glyphs needs to be generated
4786 // for each font color
4788 if (font.styleStrategy() != QFont::NoAntialias) {
4790 glGetFloatv(GL_CURRENT_COLOR, color);
4791 color_key.sprintf("%f_%f_%f",color[0], color[1], color[2]);
4793 QString key = font.key() + color_key + QString::number((int) regenerate);
4795 QString key = font.key() + QString::number((int) regenerate);
4797 if (!regenerate && (d->displayListCache.find(key) != d->displayListCache.end())) {
4798 base = d->displayListCache[key];
4800 int maxBase = listBase - 256;
4801 QMap<QString,int>::ConstIterator it;
4802 for (it = d->displayListCache.constBegin(); it != d->displayListCache.constEnd(); ++it) {
4803 if (maxBase < it.value()) {
4804 maxBase = it.value();
4808 d->glcx->generateFontDisplayLists(font, maxBase);
4809 d->displayListCache[key] = maxBase;
4813 #else // QT_OPENGL_ES
4820 #ifndef QT_OPENGL_ES
4822 static void qt_save_gl_state()
4824 glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS);
4825 glPushAttrib(GL_ALL_ATTRIB_BITS);
4826 glMatrixMode(GL_TEXTURE);
4829 glMatrixMode(GL_PROJECTION);
4831 glMatrixMode(GL_MODELVIEW);
4834 glShadeModel(GL_FLAT);
4835 glDisable(GL_CULL_FACE);
4836 glDisable(GL_LIGHTING);
4837 glDisable(GL_STENCIL_TEST);
4838 glDisable(GL_DEPTH_TEST);
4840 glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
4843 static void qt_restore_gl_state()
4845 glMatrixMode(GL_TEXTURE);
4847 glMatrixMode(GL_PROJECTION);
4849 glMatrixMode(GL_MODELVIEW);
4852 glPopClientAttrib();
4855 static void qt_gl_draw_text(QPainter *p, int x, int y, const QString &str,
4859 glGetFloatv(GL_CURRENT_COLOR, &color[0]);
4862 col.setRgbF(color[0], color[1], color[2],color[3]);
4863 QPen old_pen = p->pen();
4864 QFont old_font = p->font();
4868 p->drawText(x, y, str);
4871 p->setFont(old_font);
4874 #endif // !QT_OPENGL_ES
4877 Renders the string \a str into the GL context of this widget.
4879 \a x and \a y are specified in window coordinates, with the origin
4880 in the upper left-hand corner of the window. If \a font is not
4881 specified, the currently set application font will be used to
4882 render the string. To change the color of the rendered text you can
4883 use the glColor() call (or the qglColor() convenience function),
4884 just before the renderText() call.
4886 The \a listBase parameter is obsolete and will be removed in a
4887 future version of Qt.
4889 \note This function clears the stencil buffer.
4891 \note This function is not supported on OpenGL/ES systems.
4893 \note This function temporarily disables depth-testing when the
4896 \note This function can only be used inside a
4897 QPainter::beginNativePainting()/QPainter::endNativePainting() block
4898 if the default OpenGL paint engine is QPaintEngine::OpenGL. To make
4899 QPaintEngine::OpenGL the default GL engine, call
4900 QGL::setPreferredPaintEngine(QPaintEngine::OpenGL) before the
4901 QApplication constructor.
4903 \l{Overpainting Example}{Overpaint} with QPainter::drawText() instead.
4906 void QGLWidget::renderText(int x, int y, const QString &str, const QFont &font, int)
4908 #ifndef QT_OPENGL_ES
4910 if (str.isEmpty() || !isValid())
4914 bool use_scissor_testing = glIsEnabled(GL_SCISSOR_TEST);
4915 if (!use_scissor_testing)
4916 glGetIntegerv(GL_VIEWPORT, &view[0]);
4917 int width = d->glcx->device()->width();
4918 int height = d->glcx->device()->height();
4919 bool auto_swap = autoBufferSwap();
4921 QPaintEngine::Type oldEngineType = qgl_engine_selector()->preferredPaintEngine();
4923 QPaintEngine *engine = paintEngine();
4924 if (engine && (oldEngineType == QPaintEngine::OpenGL2) && engine->isActive()) {
4925 qWarning("QGLWidget::renderText(): Calling renderText() while a GL 2 paint engine is"
4926 " active on the same device is not allowed.");
4930 // this changes what paintEngine() returns
4931 qgl_engine_selector()->setPreferredPaintEngine(QPaintEngine::OpenGL);
4932 engine = paintEngine();
4934 bool reuse_painter = false;
4935 if (engine->isActive()) {
4936 reuse_painter = true;
4937 p = engine->painter();
4940 glDisable(GL_DEPTH_TEST);
4941 glViewport(0, 0, width, height);
4942 glMatrixMode(GL_PROJECTION);
4944 glOrtho(0, width, height, 0, 0, 1);
4945 glMatrixMode(GL_MODELVIEW);
4949 setAutoBufferSwap(false);
4950 // disable glClear() as a result of QPainter::begin()
4951 d->disable_clear_on_painter_begin = true;
4952 p = new QPainter(this);
4955 QRect viewport(view[0], view[1], view[2], view[3]);
4956 if (!use_scissor_testing && viewport != rect()) {
4957 // if the user hasn't set a scissor box, we set one that
4958 // covers the current viewport
4959 glScissor(view[0], view[1], view[2], view[3]);
4960 glEnable(GL_SCISSOR_TEST);
4961 } else if (use_scissor_testing) {
4962 // use the scissor box set by the user
4963 glEnable(GL_SCISSOR_TEST);
4966 qt_gl_draw_text(p, x, y, str, font);
4968 if (reuse_painter) {
4969 qt_restore_gl_state();
4973 setAutoBufferSwap(auto_swap);
4974 d->disable_clear_on_painter_begin = false;
4976 qgl_engine_selector()->setPreferredPaintEngine(oldEngineType);
4977 #else // QT_OPENGL_ES
4982 qWarning("QGLWidget::renderText is not supported under OpenGL/ES");
4988 \a x, \a y and \a z are specified in scene or object coordinates
4989 relative to the currently set projection and model matrices. This
4990 can be useful if you want to annotate models with text labels and
4991 have the labels move with the model as it is rotated etc.
4993 \note This function is not supported on OpenGL/ES systems.
4995 \note If depth testing is enabled before this function is called,
4996 then the drawn text will be depth-tested against the models that
4997 have already been drawn in the scene. Use \c{glDisable(GL_DEPTH_TEST)}
4998 before calling this function to annotate the models without
4999 depth-testing the text.
5001 \l{Overpainting Example}{Overpaint} with QPainter::drawText() instead.
5003 void QGLWidget::renderText(double x, double y, double z, const QString &str, const QFont &font, int)
5005 #ifndef QT_OPENGL_ES
5007 if (str.isEmpty() || !isValid())
5010 bool auto_swap = autoBufferSwap();
5012 int width = d->glcx->device()->width();
5013 int height = d->glcx->device()->height();
5014 GLdouble model[4][4], proj[4][4];
5016 glGetDoublev(GL_MODELVIEW_MATRIX, &model[0][0]);
5017 glGetDoublev(GL_PROJECTION_MATRIX, &proj[0][0]);
5018 glGetIntegerv(GL_VIEWPORT, &view[0]);
5019 GLdouble win_x = 0, win_y = 0, win_z = 0;
5020 qgluProject(x, y, z, &model[0][0], &proj[0][0], &view[0],
5021 &win_x, &win_y, &win_z);
5022 win_y = height - win_y; // y is inverted
5024 QPaintEngine::Type oldEngineType = qgl_engine_selector()->preferredPaintEngine();
5025 QPaintEngine *engine = paintEngine();
5027 if (engine && (oldEngineType == QPaintEngine::OpenGL2) && engine->isActive()) {
5028 qWarning("QGLWidget::renderText(): Calling renderText() while a GL 2 paint engine is"
5029 " active on the same device is not allowed.");
5033 // this changes what paintEngine() returns
5034 qgl_engine_selector()->setPreferredPaintEngine(QPaintEngine::OpenGL);
5035 engine = paintEngine();
5037 bool reuse_painter = false;
5038 bool use_depth_testing = glIsEnabled(GL_DEPTH_TEST);
5039 bool use_scissor_testing = glIsEnabled(GL_SCISSOR_TEST);
5041 if (engine->isActive()) {
5042 reuse_painter = true;
5043 p = engine->painter();
5046 setAutoBufferSwap(false);
5047 // disable glClear() as a result of QPainter::begin()
5048 d->disable_clear_on_painter_begin = true;
5049 p = new QPainter(this);
5052 QRect viewport(view[0], view[1], view[2], view[3]);
5053 if (!use_scissor_testing && viewport != rect()) {
5054 glScissor(view[0], view[1], view[2], view[3]);
5055 glEnable(GL_SCISSOR_TEST);
5056 } else if (use_scissor_testing) {
5057 glEnable(GL_SCISSOR_TEST);
5059 glMatrixMode(GL_PROJECTION);
5061 glViewport(0, 0, width, height);
5062 glOrtho(0, width, height, 0, 0, 1);
5063 glMatrixMode(GL_MODELVIEW);
5065 glAlphaFunc(GL_GREATER, 0.0);
5066 glEnable(GL_ALPHA_TEST);
5067 if (use_depth_testing)
5068 glEnable(GL_DEPTH_TEST);
5069 glTranslated(0, 0, -win_z);
5070 qt_gl_draw_text(p, qRound(win_x), qRound(win_y), str, font);
5072 if (reuse_painter) {
5073 qt_restore_gl_state();
5077 setAutoBufferSwap(auto_swap);
5078 d->disable_clear_on_painter_begin = false;
5080 qgl_engine_selector()->setPreferredPaintEngine(oldEngineType);
5081 #else // QT_OPENGL_ES
5087 qWarning("QGLWidget::renderText is not supported under OpenGL/ES");
5091 QGLFormat QGLWidget::format() const
5093 Q_D(const QGLWidget);
5094 return d->glcx->format();
5097 const QGLContext *QGLWidget::context() const
5099 Q_D(const QGLWidget);
5103 bool QGLWidget::doubleBuffer() const
5105 Q_D(const QGLWidget);
5106 return d->glcx->d_ptr->glFormat.testOption(QGL::DoubleBuffer);
5109 void QGLWidget::setAutoBufferSwap(bool on)
5115 bool QGLWidget::autoBufferSwap() const
5117 Q_D(const QGLWidget);
5122 Calls QGLContext:::bindTexture(\a image, \a target, \a format) on the currently
5127 GLuint QGLWidget::bindTexture(const QImage &image, GLenum target, GLint format)
5133 return d->glcx->bindTexture(image, target, format, QGLContext::DefaultBindOption);
5140 The binding \a options are a set of options used to decide how to
5141 bind the texture to the context.
5143 GLuint QGLWidget::bindTexture(const QImage &image, GLenum target, GLint format, QGLContext::BindOptions options)
5149 return d->glcx->bindTexture(image, target, format, options);
5153 #ifdef Q_MAC_COMPAT_GL_FUNCTIONS
5155 GLuint QGLWidget::bindTexture(const QImage &image, QMacCompatGLenum target, QMacCompatGLint format)
5161 return d->glcx->bindTexture(image, GLenum(target), GLint(format), QGLContext::DefaultBindOption);
5164 GLuint QGLWidget::bindTexture(const QImage &image, QMacCompatGLenum target, QMacCompatGLint format,
5165 QGLContext::BindOptions options)
5171 return d->glcx->bindTexture(image, GLenum(target), GLint(format), options);
5176 Calls QGLContext:::bindTexture(\a pixmap, \a target, \a format) on the currently
5181 GLuint QGLWidget::bindTexture(const QPixmap &pixmap, GLenum target, GLint format)
5183 if (pixmap.isNull())
5187 return d->glcx->bindTexture(pixmap, target, format, QGLContext::DefaultBindOption);
5194 Generates and binds a 2D GL texture to the current context, based
5195 on \a pixmap. The generated texture id is returned and can be used in
5197 The binding \a options are a set of options used to decide how to
5198 bind the texture to the context.
5200 GLuint QGLWidget::bindTexture(const QPixmap &pixmap, GLenum target, GLint format,
5201 QGLContext::BindOptions options)
5204 return d->glcx->bindTexture(pixmap, target, format, options);
5207 #ifdef Q_MAC_COMPAT_GL_FUNCTIONS
5209 GLuint QGLWidget::bindTexture(const QPixmap &pixmap, QMacCompatGLenum target, QMacCompatGLint format)
5212 return d->glcx->bindTexture(pixmap, target, format, QGLContext::DefaultBindOption);
5215 GLuint QGLWidget::bindTexture(const QPixmap &pixmap, QMacCompatGLenum target, QMacCompatGLint format,
5216 QGLContext::BindOptions options)
5219 return d->glcx->bindTexture(pixmap, target, format, options);
5226 Calls QGLContext::bindTexture(\a fileName) on the currently set context.
5230 GLuint QGLWidget::bindTexture(const QString &fileName)
5233 return d->glcx->bindTexture(fileName);
5237 Calls QGLContext::deleteTexture(\a id) on the currently set
5242 void QGLWidget::deleteTexture(GLuint id)
5245 d->glcx->deleteTexture(id);
5248 #ifdef Q_MAC_COMPAT_GL_FUNCTIONS
5250 void QGLWidget::deleteTexture(QMacCompatGLuint id)
5253 d->glcx->deleteTexture(GLuint(id));
5260 Calls the corresponding QGLContext::drawTexture() with
5261 \a target, \a textureId, and \a textureTarget for this
5264 void QGLWidget::drawTexture(const QRectF &target, GLuint textureId, GLenum textureTarget)
5267 d->glcx->drawTexture(target, textureId, textureTarget);
5270 #ifdef Q_MAC_COMPAT_GL_FUNCTIONS
5272 void QGLWidget::drawTexture(const QRectF &target, QMacCompatGLuint textureId, QMacCompatGLenum textureTarget)
5275 d->glcx->drawTexture(target, GLint(textureId), GLenum(textureTarget));
5282 Calls the corresponding QGLContext::drawTexture() with
5283 \a point, \a textureId, and \a textureTarget for this
5286 void QGLWidget::drawTexture(const QPointF &point, GLuint textureId, GLenum textureTarget)
5289 d->glcx->drawTexture(point, textureId, textureTarget);
5292 #ifdef Q_MAC_COMPAT_GL_FUNCTIONS
5294 void QGLWidget::drawTexture(const QPointF &point, QMacCompatGLuint textureId, QMacCompatGLenum textureTarget)
5297 d->glcx->drawTexture(point, GLuint(textureId), GLenum(textureTarget));
5301 #ifndef QT_OPENGL_ES_1
5302 Q_GLOBAL_STATIC(QGLEngineThreadStorage<QGL2PaintEngineEx>, qt_gl_2_engine)
5305 #ifndef QT_OPENGL_ES_2
5306 Q_GLOBAL_STATIC(QGLEngineThreadStorage<QOpenGLPaintEngine>, qt_gl_engine)
5309 Q_OPENGL_EXPORT QPaintEngine* qt_qgl_paint_engine()
5311 #if defined(QT_OPENGL_ES_1)
5312 return qt_gl_engine()->engine();
5313 #elif defined(QT_OPENGL_ES_2)
5314 return qt_gl_2_engine()->engine();
5316 if (qt_gl_preferGL2Engine())
5317 return qt_gl_2_engine()->engine();
5319 return qt_gl_engine()->engine();
5326 Returns the GL widget's paint engine. This is normally a
5329 QPaintEngine *QGLWidget::paintEngine() const
5331 return qt_qgl_paint_engine();
5339 QGLWidget::QGLWidget(QWidget *parent, const char *name,
5340 const QGLWidget* shareWidget, Qt::WindowFlags f)
5341 : QWidget(*(new QGLWidgetPrivate), parent, f | Qt::MSWindowsOwnDC)
5345 setObjectName(QString::fromAscii(name));
5346 setAttribute(Qt::WA_PaintOnScreen);
5347 setAttribute(Qt::WA_NoSystemBackground);
5348 setAutoFillBackground(true); // for compatibility
5349 d->init(new QGLContext(QGLFormat::defaultFormat(), this), shareWidget);
5356 QGLWidget::QGLWidget(const QGLFormat &format, QWidget *parent,
5357 const char *name, const QGLWidget* shareWidget,
5359 : QWidget(*(new QGLWidgetPrivate), parent, f | Qt::MSWindowsOwnDC)
5363 setObjectName(QString::fromAscii(name));
5364 setAttribute(Qt::WA_PaintOnScreen);
5365 setAttribute(Qt::WA_NoSystemBackground);
5366 setAutoFillBackground(true); // for compatibility
5367 d->init(new QGLContext(format, this), shareWidget);
5374 QGLWidget::QGLWidget(QGLContext *context, QWidget *parent,
5375 const char *name, const QGLWidget *shareWidget, Qt::WindowFlags f)
5376 : QWidget(*(new QGLWidgetPrivate), parent, f | Qt::MSWindowsOwnDC)
5380 setObjectName(QString::fromAscii(name));
5381 setAttribute(Qt::WA_PaintOnScreen);
5382 setAttribute(Qt::WA_NoSystemBackground);
5383 setAutoFillBackground(true); // for compatibility
5384 d->init(context, shareWidget);
5387 #endif // QT3_SUPPORT
5389 typedef GLubyte * (*qt_glGetStringi)(GLenum, GLuint);
5391 #ifndef GL_NUM_EXTENSIONS
5392 #define GL_NUM_EXTENSIONS 0x821D
5395 QGLExtensionMatcher::QGLExtensionMatcher(const char *str)
5400 QGLExtensionMatcher::QGLExtensionMatcher()
5402 const char *extensionStr = reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS));
5407 // clear error state
5408 while (glGetError()) {}
5410 const QGLContext *ctx = QGLContext::currentContext();
5412 qt_glGetStringi glGetStringi = (qt_glGetStringi)ctx->getProcAddress(QLatin1String("glGetStringi"));
5414 GLint numExtensions;
5415 glGetIntegerv(GL_NUM_EXTENSIONS, &numExtensions);
5417 for (int i = 0; i < numExtensions; ++i) {
5418 const char *str = reinterpret_cast<const char *>(glGetStringi(GL_EXTENSIONS, i));
5420 m_offsets << m_extensions.size();
5423 m_extensions.append(*str++);
5424 m_extensions.append(' ');
5430 void QGLExtensionMatcher::init(const char *str)
5434 // make sure extension string ends with a space
5435 if (!m_extensions.endsWith(' '))
5436 m_extensions.append(' ');
5440 while ((next = m_extensions.indexOf(' ', index)) >= 0) {
5447 Returns the GL extensions for the current context.
5449 QGLExtensions::Extensions QGLExtensions::currentContextExtensions()
5451 QGLExtensionMatcher extensions;
5452 Extensions glExtensions;
5454 if (extensions.match("GL_ARB_texture_rectangle"))
5455 glExtensions |= TextureRectangle;
5456 if (extensions.match("GL_ARB_multisample"))
5457 glExtensions |= SampleBuffers;
5458 if (extensions.match("GL_SGIS_generate_mipmap"))
5459 glExtensions |= GenerateMipmap;
5460 if (extensions.match("GL_ARB_texture_compression"))
5461 glExtensions |= TextureCompression;
5462 if (extensions.match("GL_EXT_texture_compression_s3tc"))
5463 glExtensions |= DDSTextureCompression;
5464 if (extensions.match("GL_OES_compressed_ETC1_RGB8_texture"))
5465 glExtensions |= ETC1TextureCompression;
5466 if (extensions.match("GL_IMG_texture_compression_pvrtc"))
5467 glExtensions |= PVRTCTextureCompression;
5468 if (extensions.match("GL_ARB_fragment_program"))
5469 glExtensions |= FragmentProgram;
5470 if (extensions.match("GL_ARB_fragment_shader"))
5471 glExtensions |= FragmentShader;
5472 if (extensions.match("GL_ARB_shader_objects"))
5473 glExtensions |= FragmentShader;
5474 if (extensions.match("GL_ARB_texture_mirrored_repeat"))
5475 glExtensions |= MirroredRepeat;
5476 if (extensions.match("GL_EXT_framebuffer_object"))
5477 glExtensions |= FramebufferObject;
5478 if (extensions.match("GL_EXT_stencil_two_side"))
5479 glExtensions |= StencilTwoSide;
5480 if (extensions.match("GL_EXT_stencil_wrap"))
5481 glExtensions |= StencilWrap;
5482 if (extensions.match("GL_EXT_packed_depth_stencil"))
5483 glExtensions |= PackedDepthStencil;
5484 if (extensions.match("GL_NV_float_buffer"))
5485 glExtensions |= NVFloatBuffer;
5486 if (extensions.match("GL_ARB_pixel_buffer_object"))
5487 glExtensions |= PixelBufferObject;
5488 if (extensions.match("GL_IMG_texture_format_BGRA8888"))
5489 glExtensions |= BGRATextureFormat;
5490 #if defined(QT_OPENGL_ES_2)
5491 glExtensions |= FramebufferObject;
5492 glExtensions |= GenerateMipmap;
5493 glExtensions |= FragmentShader;
5495 #if defined(QT_OPENGL_ES_1)
5496 if (extensions.match("GL_OES_framebuffer_object"))
5497 glExtensions |= FramebufferObject;
5499 #if defined(QT_OPENGL_ES)
5500 if (extensions.match("GL_OES_packed_depth_stencil"))
5501 glExtensions |= PackedDepthStencil;
5502 if (extensions.match("GL_OES_element_index_uint"))
5503 glExtensions |= ElementIndexUint;
5504 if (extensions.match("GL_OES_depth24"))
5505 glExtensions |= Depth24;
5507 glExtensions |= ElementIndexUint;
5509 if (extensions.match("GL_ARB_framebuffer_object")) {
5510 // ARB_framebuffer_object also includes EXT_framebuffer_blit.
5511 glExtensions |= FramebufferObject;
5512 glExtensions |= FramebufferBlit;
5515 if (extensions.match("GL_EXT_framebuffer_blit"))
5516 glExtensions |= FramebufferBlit;
5518 if (extensions.match("GL_ARB_texture_non_power_of_two"))
5519 glExtensions |= NPOTTextures;
5521 if (extensions.match("GL_EXT_bgra"))
5522 glExtensions |= BGRATextureFormat;
5525 GLboolean srgbCapableFramebuffers;
5526 glGetBooleanv(FRAMEBUFFER_SRGB_CAPABLE_EXT, &srgbCapableFramebuffers);
5527 if (srgbCapableFramebuffers)
5528 glExtensions |= SRGBFrameBuffer;
5531 return glExtensions;
5535 class QGLDefaultExtensions
5538 QGLDefaultExtensions() {
5539 QGLTemporaryContext tempContext;
5540 extensions = QGLExtensions::currentContextExtensions();
5543 QGLExtensions::Extensions extensions;
5546 Q_GLOBAL_STATIC(QGLDefaultExtensions, qtDefaultExtensions)
5549 Returns the GL extensions for the current QGLContext. If there is no
5550 current QGLContext, a default context will be created and the extensions
5551 for that context will be returned instead.
5553 QGLExtensions::Extensions QGLExtensions::glExtensions()
5555 Extensions extensionFlags = 0;
5556 QGLContext *currentCtx = const_cast<QGLContext *>(QGLContext::currentContext());
5558 if (currentCtx && currentCtx->d_func()->extension_flags_cached)
5559 return currentCtx->d_func()->extension_flags;
5562 extensionFlags = qtDefaultExtensions()->extensions;
5564 extensionFlags = currentContextExtensions();
5565 currentCtx->d_func()->extension_flags_cached = true;
5566 currentCtx->d_func()->extension_flags = extensionFlags;
5568 return extensionFlags;
5572 This is the shared initialization for all platforms. Called from QGLWidgetPrivate::init()
5574 void QGLWidgetPrivate::initContext(QGLContext *context, const QGLWidget* shareWidget)
5578 glDevice.setWidget(q);
5583 if (context && !context->device())
5584 context->setDevice(q);
5585 q->setContext(context, shareWidget ? shareWidget->context() : 0);
5588 glcx = new QGLContext(QGLFormat::defaultFormat(), q);
5591 #if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS) || defined(Q_WS_QPA)
5592 Q_GLOBAL_STATIC(QString, qt_gl_lib_name)
5594 Q_OPENGL_EXPORT void qt_set_gl_library_name(const QString& name)
5596 qt_gl_lib_name()->operator=(name);
5599 Q_OPENGL_EXPORT const QString qt_gl_library_name()
5601 if (qt_gl_lib_name()->isNull()) {
5603 return QLatin1String("/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib");
5605 # if defined(QT_OPENGL_ES_1)
5606 return QLatin1String("GLES_CM");
5607 # elif defined(QT_OPENGL_ES_2)
5608 return QLatin1String("GLESv2");
5610 return QLatin1String("GL");
5612 #endif // defined Q_WS_MAC
5614 return *qt_gl_lib_name();
5618 void QGLContextGroup::addShare(const QGLContext *context, const QGLContext *share) {
5619 Q_ASSERT(context && share);
5620 if (context->d_ptr->group == share->d_ptr->group)
5623 // Make sure 'context' is not already shared with another group of contexts.
5624 Q_ASSERT(context->d_ptr->group->m_refs == 1);
5626 // Free 'context' group resources and make it use the same resources as 'share'.
5627 QGLContextGroup *group = share->d_ptr->group;
5628 delete context->d_ptr->group;
5629 context->d_ptr->group = group;
5630 group->m_refs.ref();
5632 // Maintain a list of all the contexts in each group of sharing contexts.
5633 // The list is empty if the "share" context wasn't sharing already.
5634 if (group->m_shares.isEmpty())
5635 group->m_shares.append(share);
5636 group->m_shares.append(context);
5639 void QGLContextGroup::removeShare(const QGLContext *context) {
5640 // Remove the context from the group.
5641 QGLContextGroup *group = context->d_ptr->group;
5642 if (group->m_shares.isEmpty())
5644 group->m_shares.removeAll(context);
5646 // Update context group representative.
5647 Q_ASSERT(group->m_shares.size() != 0);
5648 if (group->m_context == context)
5649 group->m_context = group->m_shares[0];
5651 // If there is only one context left, then make the list empty.
5652 if (group->m_shares.size() == 1)
5653 group->m_shares.clear();
5656 QGLContextGroupResourceBase::QGLContextGroupResourceBase()
5659 #ifdef QT_GL_CONTEXT_RESOURCE_DEBUG
5660 qDebug("Creating context group resource object %p.", this);
5664 QGLContextGroupResourceBase::~QGLContextGroupResourceBase()
5666 #ifdef QT_GL_CONTEXT_RESOURCE_DEBUG
5667 qDebug("Deleting context group resource %p. Group size: %d.", this, m_groups.size());
5669 for (int i = 0; i < m_groups.size(); ++i) {
5670 m_groups.at(i)->m_resources.remove(this);
5675 qWarning("QtOpenGL: Resources are still available at program shutdown.\n"
5676 " This is possibly caused by a leaked QGLWidget, \n"
5677 " QGLFramebufferObject or QGLPixelBuffer.");
5682 void QGLContextGroupResourceBase::insert(const QGLContext *context, void *value)
5684 #ifdef QT_GL_CONTEXT_RESOURCE_DEBUG
5685 qDebug("Inserting context group resource %p for context %p, managed by %p.", value, context, this);
5687 QGLContextGroup *group = QGLContextPrivate::contextGroup(context);
5688 Q_ASSERT(!group->m_resources.contains(this));
5689 group->m_resources.insert(this, value);
5690 m_groups.append(group);
5694 void *QGLContextGroupResourceBase::value(const QGLContext *context)
5696 QGLContextGroup *group = QGLContextPrivate::contextGroup(context);
5697 return group->m_resources.value(this, 0);
5700 void QGLContextGroupResourceBase::cleanup(const QGLContext *ctx)
5702 void *resource = value(ctx);
5704 if (resource != 0) {
5705 QGLShareContextScope scope(ctx);
5706 freeResource(resource);
5708 QGLContextGroup *group = QGLContextPrivate::contextGroup(ctx);
5709 group->m_resources.remove(this);
5710 m_groups.removeOne(group);
5715 void QGLContextGroupResourceBase::cleanup(const QGLContext *ctx, void *value)
5717 #ifdef QT_GL_CONTEXT_RESOURCE_DEBUG
5718 qDebug("Cleaning up context group resource %p, for context %p in thread %p.", this, ctx, QThread::currentThread());
5720 QGLShareContextScope scope(ctx);
5721 freeResource(value);
5724 QGLContextGroup *group = QGLContextPrivate::contextGroup(ctx);
5725 m_groups.removeOne(group);
5728 void QGLContextGroup::cleanupResources(const QGLContext *context)
5730 // If there are still shares, then no cleanup to be done yet.
5731 if (m_shares.size() > 1)
5734 // Iterate over all resources and free each in turn.
5735 QHash<QGLContextGroupResourceBase *, void *>::ConstIterator it;
5736 for (it = m_resources.begin(); it != m_resources.end(); ++it)
5737 it.key()->cleanup(context, it.value());
5740 QGLSharedResourceGuard::~QGLSharedResourceGuard()
5743 m_group->removeGuard(this);
5746 void QGLSharedResourceGuard::setContext(const QGLContext *context)
5749 m_group->removeGuard(this);
5751 m_group = QGLContextPrivate::contextGroup(context);
5752 m_group->addGuard(this);
5758 QSize QGLTexture::bindCompressedTexture
5759 (const QString& fileName, const char *format)
5761 QFile file(fileName);
5762 if (!file.open(QIODevice::ReadOnly))
5764 QByteArray contents = file.readAll();
5766 return bindCompressedTexture
5767 (contents.constData(), contents.size(), format);
5770 // PVR header format for container files that store textures compressed
5771 // with the ETC1, PVRTC2, and PVRTC4 encodings. Format information from the
5772 // PowerVR SDK at http://www.imgtec.com/powervr/insider/powervr-sdk.asp
5773 // "PVRTexTool Reference Manual, version 1.11f".
5779 quint32 mipMapCount;
5782 quint32 bitsPerPixel;
5788 quint32 surfaceCount;
5791 #define PVR_MAGIC 0x21525650 // "PVR!" in little-endian
5793 #define PVR_FORMAT_MASK 0x000000FF
5794 #define PVR_FORMAT_PVRTC2 0x00000018
5795 #define PVR_FORMAT_PVRTC4 0x00000019
5796 #define PVR_FORMAT_ETC1 0x00000036
5798 #define PVR_HAS_MIPMAPS 0x00000100
5799 #define PVR_TWIDDLED 0x00000200
5800 #define PVR_NORMAL_MAP 0x00000400
5801 #define PVR_BORDER_ADDED 0x00000800
5802 #define PVR_CUBE_MAP 0x00001000
5803 #define PVR_FALSE_COLOR_MIPMAPS 0x00002000
5804 #define PVR_VOLUME_TEXTURE 0x00004000
5805 #define PVR_ALPHA_IN_TEXTURE 0x00008000
5806 #define PVR_VERTICAL_FLIP 0x00010000
5808 #ifndef GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
5809 #define GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG 0x8C00
5810 #define GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG 0x8C01
5811 #define GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG 0x8C02
5812 #define GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG 0x8C03
5815 #ifndef GL_ETC1_RGB8_OES
5816 #define GL_ETC1_RGB8_OES 0x8D64
5819 bool QGLTexture::canBindCompressedTexture
5820 (const char *buf, int len, const char *format, bool *hasAlpha)
5822 if (QSysInfo::ByteOrder != QSysInfo::LittleEndian) {
5823 // Compressed texture loading only supported on little-endian
5824 // systems such as x86 and ARM at the moment.
5828 // Auto-detect the format from the header.
5829 if (len >= 4 && !qstrncmp(buf, "DDS ", 4)) {
5832 } else if (len >= 52 && !qstrncmp(buf + 44, "PVR!", 4)) {
5833 const PvrHeader *pvrHeader =
5834 reinterpret_cast<const PvrHeader *>(buf);
5835 *hasAlpha = (pvrHeader->alphaMask != 0);
5839 // Validate the format against the header.
5840 if (!qstricmp(format, "DDS")) {
5841 if (len >= 4 && !qstrncmp(buf, "DDS ", 4)) {
5845 } else if (!qstricmp(format, "PVR") || !qstricmp(format, "ETC1")) {
5846 if (len >= 52 && !qstrncmp(buf + 44, "PVR!", 4)) {
5847 const PvrHeader *pvrHeader =
5848 reinterpret_cast<const PvrHeader *>(buf);
5849 *hasAlpha = (pvrHeader->alphaMask != 0);
5857 #define ctx QGLContext::currentContext()
5859 QSize QGLTexture::bindCompressedTexture
5860 (const char *buf, int len, const char *format)
5862 if (QSysInfo::ByteOrder != QSysInfo::LittleEndian) {
5863 // Compressed texture loading only supported on little-endian
5864 // systems such as x86 and ARM at the moment.
5867 #if !defined(QT_OPENGL_ES)
5868 if (!glCompressedTexImage2D) {
5869 if (!(QGLExtensions::glExtensions() & QGLExtensions::TextureCompression)) {
5870 qWarning("QGLContext::bindTexture(): The GL implementation does "
5871 "not support texture compression extensions.");
5874 glCompressedTexImage2D = (_glCompressedTexImage2DARB) ctx->getProcAddress(QLatin1String("glCompressedTexImage2DARB"));
5875 if (!glCompressedTexImage2D) {
5876 qWarning("QGLContext::bindTexture(): could not resolve "
5877 "glCompressedTexImage2DARB.");
5883 // Auto-detect the format from the header.
5884 if (len >= 4 && !qstrncmp(buf, "DDS ", 4))
5885 return bindCompressedTextureDDS(buf, len);
5886 else if (len >= 52 && !qstrncmp(buf + 44, "PVR!", 4))
5887 return bindCompressedTexturePVR(buf, len);
5889 // Validate the format against the header.
5890 if (!qstricmp(format, "DDS")) {
5891 if (len >= 4 && !qstrncmp(buf, "DDS ", 4))
5892 return bindCompressedTextureDDS(buf, len);
5893 } else if (!qstricmp(format, "PVR") || !qstricmp(format, "ETC1")) {
5894 if (len >= 52 && !qstrncmp(buf + 44, "PVR!", 4))
5895 return bindCompressedTexturePVR(buf, len);
5901 QSize QGLTexture::bindCompressedTextureDDS(const char *buf, int len)
5903 // We only support 2D texture loading at present.
5904 if (target != GL_TEXTURE_2D)
5907 // Bail out if the necessary extension is not present.
5908 if (!(QGLExtensions::glExtensions() & QGLExtensions::DDSTextureCompression)) {
5909 qWarning("QGLContext::bindTexture(): DDS texture compression is not supported.");
5913 const DDSFormat *ddsHeader = reinterpret_cast<const DDSFormat *>(buf + 4);
5914 if (!ddsHeader->dwLinearSize) {
5915 qWarning("QGLContext::bindTexture(): DDS image size is not valid.");
5922 switch(ddsHeader->ddsPixelFormat.dwFourCC) {
5924 format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
5928 format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
5931 format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
5934 qWarning("QGLContext::bindTexture(): DDS image format not supported.");
5938 const GLubyte *pixels =
5939 reinterpret_cast<const GLubyte *>(buf + ddsHeader->dwSize + 4);
5941 glGenTextures(1, &id);
5942 glBindTexture(GL_TEXTURE_2D, id);
5943 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
5944 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5948 int available = len - int(ddsHeader->dwSize + 4);
5949 int w = ddsHeader->dwWidth;
5950 int h = ddsHeader->dwHeight;
5953 for(int i = 0; i < (int) ddsHeader->dwMipMapCount; ++i) {
5957 size = ((w+3)/4) * ((h+3)/4) * blockSize;
5958 if (size > available)
5960 glCompressedTexImage2D(GL_TEXTURE_2D, i, format, w, h, 0,
5961 size, pixels + offset);
5965 // half size for each mip-map level
5970 // DDS images are not inverted.
5971 options &= ~QGLContext::InvertedYBindOption;
5973 return QSize(ddsHeader->dwWidth, ddsHeader->dwHeight);
5976 QSize QGLTexture::bindCompressedTexturePVR(const char *buf, int len)
5978 // We only support 2D texture loading at present. Cube maps later.
5979 if (target != GL_TEXTURE_2D)
5982 // Determine which texture format we will be loading.
5983 const PvrHeader *pvrHeader = reinterpret_cast<const PvrHeader *>(buf);
5984 GLenum textureFormat;
5985 quint32 minWidth, minHeight;
5986 switch (pvrHeader->flags & PVR_FORMAT_MASK) {
5987 case PVR_FORMAT_PVRTC2:
5988 if (pvrHeader->alphaMask)
5989 textureFormat = GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
5991 textureFormat = GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
5996 case PVR_FORMAT_PVRTC4:
5997 if (pvrHeader->alphaMask)
5998 textureFormat = GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
6000 textureFormat = GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
6005 case PVR_FORMAT_ETC1:
6006 textureFormat = GL_ETC1_RGB8_OES;
6012 qWarning("QGLContext::bindTexture(): PVR image format 0x%x not supported.", int(pvrHeader->flags & PVR_FORMAT_MASK));
6016 // Bail out if the necessary extension is not present.
6017 if (textureFormat == GL_ETC1_RGB8_OES) {
6018 if (!(QGLExtensions::glExtensions() &
6019 QGLExtensions::ETC1TextureCompression)) {
6020 qWarning("QGLContext::bindTexture(): ETC1 texture compression is not supported.");
6024 if (!(QGLExtensions::glExtensions() &
6025 QGLExtensions::PVRTCTextureCompression)) {
6026 qWarning("QGLContext::bindTexture(): PVRTC texture compression is not supported.");
6031 // Boundary check on the buffer size.
6032 quint32 bufferSize = pvrHeader->headerSize + pvrHeader->dataSize;
6033 if (bufferSize > quint32(len)) {
6034 qWarning("QGLContext::bindTexture(): PVR image size is not valid.");
6038 // Create the texture.
6039 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
6040 glGenTextures(1, &id);
6041 glBindTexture(GL_TEXTURE_2D, id);
6042 if (pvrHeader->mipMapCount) {
6043 if ((options & QGLContext::LinearFilteringBindOption) != 0) {
6044 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6045 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
6047 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6048 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
6050 } else if ((options & QGLContext::LinearFilteringBindOption) != 0) {
6051 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6052 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6054 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6055 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6058 // Load the compressed mipmap levels.
6059 const GLubyte *buffer =
6060 reinterpret_cast<const GLubyte *>(buf + pvrHeader->headerSize);
6061 bufferSize = pvrHeader->dataSize;
6063 quint32 width = pvrHeader->width;
6064 quint32 height = pvrHeader->height;
6065 while (bufferSize > 0 && level <= pvrHeader->mipMapCount) {
6067 (qMax(width, minWidth) * qMax(height, minHeight) *
6068 pvrHeader->bitsPerPixel) / 8;
6069 if (size > bufferSize)
6071 glCompressedTexImage2D(GL_TEXTURE_2D, GLint(level), textureFormat,
6072 GLsizei(width), GLsizei(height), 0,
6073 GLsizei(size), buffer);
6080 // Restore the default pixel alignment for later texture uploads.
6081 glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
6083 // Set the invert flag for the texture. The "vertical flip"
6084 // flag in PVR is the opposite sense to our sense of inversion.
6085 if ((pvrHeader->flags & PVR_VERTICAL_FLIP) != 0)
6086 options &= ~QGLContext::InvertedYBindOption;
6088 options |= QGLContext::InvertedYBindOption;
6090 return QSize(pvrHeader->width, pvrHeader->height);