Re-apply change 353dcfd307853da289fdd245410e2e07358624a0 by Friedemann Kleint
[qt-netbsd.git] / src / opengl / qgl.cpp
bloba9f8ede7abac108b4df43be3a2f832744555a965
1 /****************************************************************************
2 **
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: Nokia Corporation (qt-info@nokia.com)
5 **
6 ** This file is part of the QtOpenGL module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** No Commercial Usage
10 ** This file contains pre-release code and may not be distributed.
11 ** You may use this file in accordance with the terms and conditions
12 ** contained in the either Technology Preview License Agreement or the
13 ** Beta Release License Agreement.
15 ** GNU Lesser General Public License Usage
16 ** Alternatively, this file may be used under the terms of the GNU Lesser
17 ** General Public License version 2.1 as published by the Free Software
18 ** Foundation and appearing in the file LICENSE.LGPL included in the
19 ** packaging of this file. Please review the following information to
20 ** ensure the GNU Lesser General Public License version 2.1 requirements
21 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23 ** In addition, as a special exception, Nokia gives you certain
24 ** additional rights. These rights are described in the Nokia Qt LGPL
25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26 ** package.
28 ** GNU General Public License Usage
29 ** Alternatively, this file may be used under the terms of the GNU
30 ** General Public License version 3.0 as published by the Free Software
31 ** Foundation and appearing in the file LICENSE.GPL included in the
32 ** packaging of this file. Please review the following information to
33 ** ensure the GNU General Public License version 3.0 requirements will be
34 ** met: http://www.gnu.org/copyleft/gpl.html.
36 ** If you are unsure which license is appropriate for your use, please
37 ** contact the sales department at http://www.qtsoftware.com/contact.
38 ** $QT_END_LICENSE$
40 ****************************************************************************/
42 #include "qapplication.h"
43 #include "qplatformdefs.h"
44 #include "qgl.h"
45 #include <qdebug.h>
47 #if defined(Q_WS_X11)
48 #include "private/qt_x11_p.h"
49 #include "private/qpixmap_x11_p.h"
50 #define INT32 dummy_INT32
51 #define INT8 dummy_INT8
52 #if !defined(QT_OPENGL_ES)
53 # include <GL/glx.h>
54 #endif
55 #undef INT32
56 #undef INT8
57 #include "qx11info_x11.h"
58 #elif defined(Q_WS_MAC)
59 # include <private/qt_mac_p.h>
60 #endif
62 #include <stdlib.h> // malloc
64 #include "qpixmap.h"
65 #include "qimage.h"
66 #include "qgl_p.h"
68 #if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
69 #include "gl2paintengineex/qpaintengineex_opengl2_p.h"
70 #endif
72 #ifndef QT_OPENGL_ES_2
73 #include <private/qpaintengine_opengl_p.h>
74 #endif
76 #ifdef Q_WS_QWS
77 #include <private/qglpaintdevice_qws_p.h>
78 #include <private/qglwindowsurface_qws_p.h>
79 #endif
81 #include <qglpixelbuffer.h>
82 #include <qglframebufferobject.h>
84 #include <private/qimage_p.h>
85 #include <private/qpixmapdata_p.h>
86 #include <private/qpixmapdata_gl_p.h>
87 #include <private/qglpixelbuffer_p.h>
88 #include <private/qwindowsurface_gl_p.h>
89 #include "qcolormap.h"
90 #include "qcache.h"
91 #include "qfile.h"
92 #include "qlibrary.h"
95 QT_BEGIN_NAMESPACE
97 #ifdef QT_OPENGL_ES_1_CL
98 #include "qgl_cl_p.h"
99 #endif
102 #if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS)
103 QGLExtensionFuncs QGLContextPrivate::qt_extensionFuncs;
104 #endif
106 QThreadStorage<QGLThreadContext *> qgl_context_storage;
108 Q_GLOBAL_STATIC(QGLFormat, qgl_default_format)
110 class QGLDefaultOverlayFormat: public QGLFormat
112 public:
113 inline QGLDefaultOverlayFormat()
115 setOption(QGL::FormatOption(0xffff << 16)); // turn off all options
116 setOption(QGL::DirectRendering);
117 setPlane(1);
120 Q_GLOBAL_STATIC(QGLDefaultOverlayFormat, defaultOverlayFormatInstance)
122 QGLExtensions::Extensions QGLExtensions::glExtensions = 0;
123 bool QGLExtensions::nvidiaFboNeedsFinish = false;
125 #ifndef APIENTRY
126 # define APIENTRY
127 #endif
128 typedef void (APIENTRY *pfn_glCompressedTexImage2DARB) (GLenum, GLint, GLenum, GLsizei,
129 GLsizei, GLint, GLsizei, const GLvoid *);
130 static pfn_glCompressedTexImage2DARB qt_glCompressedTexImage2DARB = 0;
133 #ifndef APIENTRY
134 #define APIENTRY
135 #endif
137 Q_GLOBAL_STATIC(QGLSignalProxy, theSignalProxy)
138 QGLSignalProxy *QGLSignalProxy::instance()
140 return theSignalProxy();
144 \namespace QGL
146 \brief The QGL namespace specifies miscellaneous identifiers used
147 in the Qt OpenGL module.
149 \ingroup multimedia
153 \enum QGL::FormatOption
155 This enum specifies the format options that can be used to configure an OpenGL
156 context. These are set using QGLFormat::setOption().
158 \value DoubleBuffer Specifies the use of double buffering.
159 \value DepthBuffer Enables the use of a depth buffer.
160 \value Rgba Specifies that the context should use RGBA as its pixel format.
161 \value AlphaChannel Enables the use of an alpha channel.
162 \value AccumBuffer Enables the use of an accumulation buffer.
163 \value StencilBuffer Enables the use of a stencil buffer.
164 \value StereoBuffers Enables the use of a stereo buffers for use with visualization hardware.
165 \value DirectRendering Specifies that the context is used for direct rendering to a display.
166 \value HasOverlay Enables the use of an overlay.
167 \value SampleBuffers Enables the use of sample buffers.
168 \value SingleBuffer Specifies the use of a single buffer, as opposed to double buffers.
169 \value NoDepthBuffer Disables the use of a depth buffer.
170 \value ColorIndex Specifies that the context should use a color index as its pixel format.
171 \value NoAlphaChannel Disables the use of an alpha channel.
172 \value NoAccumBuffer Disables the use of an accumulation buffer.
173 \value NoStencilBuffer Disables the use of a stencil buffer.
174 \value NoStereoBuffers Disables the use of stereo buffers.
175 \value IndirectRendering Specifies that the context is used for indirect rendering to a buffer.
176 \value NoOverlay Disables the use of an overlay.
177 \value NoSampleBuffers Disables the use of sample buffers.
179 \sa {Sample Buffers Example}
182 /*****************************************************************************
183 QGLFormat implementation
184 *****************************************************************************/
188 \class QGLFormat
189 \brief The QGLFormat class specifies the display format of an OpenGL
190 rendering context.
192 \ingroup multimedia
194 A display format has several characteristics:
195 \list
196 \i \link setDoubleBuffer() Double or single buffering.\endlink
197 \i \link setDepth() Depth buffer.\endlink
198 \i \link setRgba() RGBA or color index mode.\endlink
199 \i \link setAlpha() Alpha channel.\endlink
200 \i \link setAccum() Accumulation buffer.\endlink
201 \i \link setStencil() Stencil buffer.\endlink
202 \i \link setStereo() Stereo buffers.\endlink
203 \i \link setDirectRendering() Direct rendering.\endlink
204 \i \link setOverlay() Presence of an overlay.\endlink
205 \i \link setPlane() The plane of an overlay format.\endlink
206 \i \link setSampleBuffers() Multisample buffers.\endlink
207 \endlist
209 You can also specify preferred bit depths for the depth buffer,
210 alpha buffer, accumulation buffer and the stencil buffer with the
211 functions: setDepthBufferSize(), setAlphaBufferSize(),
212 setAccumBufferSize() and setStencilBufferSize().
214 Note that even if you specify that you prefer a 32 bit depth
215 buffer (e.g. with setDepthBufferSize(32)), the format that is
216 chosen may not have a 32 bit depth buffer, even if there is a
217 format available with a 32 bit depth buffer. The main reason for
218 this is how the system dependant picking algorithms work on the
219 different platforms, and some format options may have higher
220 precedence than others.
222 You create and tell a QGLFormat object what rendering options you
223 want from an OpenGL rendering context.
225 OpenGL drivers or accelerated hardware may or may not support
226 advanced features such as alpha channel or stereographic viewing.
227 If you request some features that the driver/hardware does not
228 provide when you create a QGLWidget, you will get a rendering
229 context with the nearest subset of features.
231 There are different ways to define the display characteristics of
232 a rendering context. One is to create a QGLFormat and make it the
233 default for the entire application:
234 \snippet doc/src/snippets/code/src_opengl_qgl.cpp 0
236 Or you can specify the desired format when creating an object of
237 your QGLWidget subclass:
238 \snippet doc/src/snippets/code/src_opengl_qgl.cpp 1
240 After the widget has been created, you can find out which of the
241 requested features the system was able to provide:
242 \snippet doc/src/snippets/code/src_opengl_qgl.cpp 2
244 \legalese
245 OpenGL is a trademark of Silicon Graphics, Inc. in the
246 United States and other countries.
247 \endlegalese
249 \sa QGLContext, QGLWidget
252 static inline void transform_point(GLdouble out[4], const GLdouble m[16], const GLdouble in[4])
254 #define M(row,col) m[col*4+row]
255 out[0] =
256 M(0, 0) * in[0] + M(0, 1) * in[1] + M(0, 2) * in[2] + M(0, 3) * in[3];
257 out[1] =
258 M(1, 0) * in[0] + M(1, 1) * in[1] + M(1, 2) * in[2] + M(1, 3) * in[3];
259 out[2] =
260 M(2, 0) * in[0] + M(2, 1) * in[1] + M(2, 2) * in[2] + M(2, 3) * in[3];
261 out[3] =
262 M(3, 0) * in[0] + M(3, 1) * in[1] + M(3, 2) * in[2] + M(3, 3) * in[3];
263 #undef M
266 static inline GLint qgluProject(GLdouble objx, GLdouble objy, GLdouble objz,
267 const GLdouble model[16], const GLdouble proj[16],
268 const GLint viewport[4],
269 GLdouble * winx, GLdouble * winy, GLdouble * winz)
271 GLdouble in[4], out[4];
273 in[0] = objx;
274 in[1] = objy;
275 in[2] = objz;
276 in[3] = 1.0;
277 transform_point(out, model, in);
278 transform_point(in, proj, out);
280 if (in[3] == 0.0)
281 return GL_FALSE;
283 in[0] /= in[3];
284 in[1] /= in[3];
285 in[2] /= in[3];
287 *winx = viewport[0] + (1 + in[0]) * viewport[2] / 2;
288 *winy = viewport[1] + (1 + in[1]) * viewport[3] / 2;
290 *winz = (1 + in[2]) / 2;
291 return GL_TRUE;
295 Constructs a QGLFormat object with the factory default settings:
296 \list
297 \i \link setDoubleBuffer() Double buffer:\endlink Enabled.
298 \i \link setDepth() Depth buffer:\endlink Enabled.
299 \i \link setRgba() RGBA:\endlink Enabled (i.e., color index disabled).
300 \i \link setAlpha() Alpha channel:\endlink Disabled.
301 \i \link setAccum() Accumulator buffer:\endlink Disabled.
302 \i \link setStencil() Stencil buffer:\endlink Disabled.
303 \i \link setStereo() Stereo:\endlink Disabled.
304 \i \link setDirectRendering() Direct rendering:\endlink Enabled.
305 \i \link setOverlay() Overlay:\endlink Disabled.
306 \i \link setPlane() Plane:\endlink 0 (i.e., normal plane).
307 \i \link setSampleBuffers() Multisample buffers:\endlink Disabled.
308 \endlist
311 QGLFormat::QGLFormat()
313 d = new QGLFormatPrivate;
318 Creates a QGLFormat object that is a copy of the current \link
319 defaultFormat() application default format\endlink.
321 If \a options is not 0, this copy is modified by these format
322 options. The \a options parameter should be \c FormatOption values
323 OR'ed together.
325 This constructor makes it easy to specify a certain desired format
326 in classes derived from QGLWidget, for example:
327 \snippet doc/src/snippets/code/src_opengl_qgl.cpp 3
329 Note that there are \c FormatOption values to turn format settings
330 both on and off, e.g. \c DepthBuffer and \c NoDepthBuffer,
331 \c DirectRendering and \c IndirectRendering, etc.
333 The \a plane parameter defaults to 0 and is the plane which this
334 format should be associated with. Not all OpenGL implementations
335 supports overlay/underlay rendering planes.
337 \sa defaultFormat(), setOption()
340 QGLFormat::QGLFormat(QGL::FormatOptions options, int plane)
342 d = new QGLFormatPrivate;
343 QGL::FormatOptions newOpts = options;
344 d->opts = defaultFormat().d->opts;
345 d->opts |= (newOpts & 0xffff);
346 d->opts &= ~(newOpts >> 16);
347 d->pln = plane;
351 Constructs a copy of \a other.
354 QGLFormat::QGLFormat(const QGLFormat &other)
356 d = new QGLFormatPrivate;
357 *d = *other.d;
361 Assigns \a other to this object.
364 QGLFormat &QGLFormat::operator=(const QGLFormat &other)
366 *d = *other.d;
367 return *this;
371 Destroys the QGLFormat.
373 QGLFormat::~QGLFormat()
375 delete d;
379 \fn bool QGLFormat::doubleBuffer() const
381 Returns true if double buffering is enabled; otherwise returns
382 false. Double buffering is enabled by default.
384 \sa setDoubleBuffer()
388 If \a enable is true sets double buffering; otherwise sets single
389 buffering.
391 Double buffering is enabled by default.
393 Double buffering is a technique where graphics are rendered on an
394 off-screen buffer and not directly to the screen. When the drawing
395 has been completed, the program calls a swapBuffers() function to
396 exchange the screen contents with the buffer. The result is
397 flicker-free drawing and often better performance.
399 \sa doubleBuffer(), QGLContext::swapBuffers(),
400 QGLWidget::swapBuffers()
403 void QGLFormat::setDoubleBuffer(bool enable)
405 setOption(enable ? QGL::DoubleBuffer : QGL::SingleBuffer);
410 \fn bool QGLFormat::depth() const
412 Returns true if the depth buffer is enabled; otherwise returns
413 false. The depth buffer is enabled by default.
415 \sa setDepth(), setDepthBufferSize()
419 If \a enable is true enables the depth buffer; otherwise disables
420 the depth buffer.
422 The depth buffer is enabled by default.
424 The purpose of a depth buffer (or Z-buffering) is to remove hidden
425 surfaces. Pixels are assigned Z values based on the distance to
426 the viewer. A pixel with a high Z value is closer to the viewer
427 than a pixel with a low Z value. This information is used to
428 decide whether to draw a pixel or not.
430 \sa depth(), setDepthBufferSize()
433 void QGLFormat::setDepth(bool enable)
435 setOption(enable ? QGL::DepthBuffer : QGL::NoDepthBuffer);
440 \fn bool QGLFormat::rgba() const
442 Returns true if RGBA color mode is set. Returns false if color
443 index mode is set. The default color mode is RGBA.
445 \sa setRgba()
449 If \a enable is true sets RGBA mode. If \a enable is false sets
450 color index mode.
452 The default color mode is RGBA.
454 RGBA is the preferred mode for most OpenGL applications. In RGBA
455 color mode you specify colors as red + green + blue + alpha
456 quadruplets.
458 In color index mode you specify an index into a color lookup
459 table.
461 \sa rgba()
464 void QGLFormat::setRgba(bool enable)
466 setOption(enable ? QGL::Rgba : QGL::ColorIndex);
471 \fn bool QGLFormat::alpha() const
473 Returns true if the alpha buffer in the framebuffer is enabled;
474 otherwise returns false. The alpha buffer is disabled by default.
476 \sa setAlpha(), setAlphaBufferSize()
480 If \a enable is true enables the alpha buffer; otherwise disables
481 the alpha buffer.
483 The alpha buffer is disabled by default.
485 The alpha buffer is typically used for implementing transparency
486 or translucency. The A in RGBA specifies the transparency of a
487 pixel.
489 \sa alpha(), setAlphaBufferSize()
492 void QGLFormat::setAlpha(bool enable)
494 setOption(enable ? QGL::AlphaChannel : QGL::NoAlphaChannel);
499 \fn bool QGLFormat::accum() const
501 Returns true if the accumulation buffer is enabled; otherwise
502 returns false. The accumulation buffer is disabled by default.
504 \sa setAccum(), setAccumBufferSize()
508 If \a enable is true enables the accumulation buffer; otherwise
509 disables the accumulation buffer.
511 The accumulation buffer is disabled by default.
513 The accumulation buffer is used to create blur effects and
514 multiple exposures.
516 \sa accum(), setAccumBufferSize()
519 void QGLFormat::setAccum(bool enable)
521 setOption(enable ? QGL::AccumBuffer : QGL::NoAccumBuffer);
526 \fn bool QGLFormat::stencil() const
528 Returns true if the stencil buffer is enabled; otherwise returns
529 false. The stencil buffer is disabled by default.
531 \sa setStencil(), setStencilBufferSize()
535 If \a enable is true enables the stencil buffer; otherwise
536 disables the stencil buffer.
538 The stencil buffer is disabled by default.
540 The stencil buffer masks certain parts of the drawing area so that
541 masked parts are not drawn on.
543 \sa stencil(), setStencilBufferSize()
546 void QGLFormat::setStencil(bool enable)
548 setOption(enable ? QGL::StencilBuffer: QGL::NoStencilBuffer);
553 \fn bool QGLFormat::stereo() const
555 Returns true if stereo buffering is enabled; otherwise returns
556 false. Stereo buffering is disabled by default.
558 \sa setStereo()
562 If \a enable is true enables stereo buffering; otherwise disables
563 stereo buffering.
565 Stereo buffering is disabled by default.
567 Stereo buffering provides extra color buffers to generate left-eye
568 and right-eye images.
570 \sa stereo()
573 void QGLFormat::setStereo(bool enable)
575 setOption(enable ? QGL::StereoBuffers : QGL::NoStereoBuffers);
580 \fn bool QGLFormat::directRendering() const
582 Returns true if direct rendering is enabled; otherwise returns
583 false.
585 Direct rendering is enabled by default.
587 \sa setDirectRendering()
591 If \a enable is true enables direct rendering; otherwise disables
592 direct rendering.
594 Direct rendering is enabled by default.
596 Enabling this option will make OpenGL bypass the underlying window
597 system and render directly from hardware to the screen, if this is
598 supported by the system.
600 \sa directRendering()
603 void QGLFormat::setDirectRendering(bool enable)
605 setOption(enable ? QGL::DirectRendering : QGL::IndirectRendering);
609 \fn bool QGLFormat::sampleBuffers() const
611 Returns true if multisample buffer support is enabled; otherwise
612 returns false.
614 The multisample buffer is disabled by default.
616 \sa setSampleBuffers()
620 If \a enable is true, a GL context with multisample buffer support
621 is picked; otherwise ignored.
623 \sa sampleBuffers(), setSamples(), samples()
625 void QGLFormat::setSampleBuffers(bool enable)
627 setOption(enable ? QGL::SampleBuffers : QGL::NoSampleBuffers);
631 Returns the number of samples per pixel when multisampling is
632 enabled. By default, the highest number of samples that is
633 available is used.
635 \sa setSampleBuffers(), sampleBuffers(), setSamples()
637 int QGLFormat::samples() const
639 return d->numSamples;
643 Set the preferred number of samples per pixel when multisampling
644 is enabled to \a numSamples. By default, the highest number of
645 samples available is used.
647 \sa setSampleBuffers(), sampleBuffers(), samples()
649 void QGLFormat::setSamples(int numSamples)
651 if (numSamples < 0) {
652 qWarning("QGLFormat::setSamples: Cannot have negative number of samples per pixel %d", numSamples);
653 return;
655 d->numSamples = numSamples;
659 \since 4.2
661 Set the preferred swap interval. This can be used to sync the GL
662 drawing into a system window to the vertical refresh of the screen.
663 Setting an \a interval value of 0 will turn the vertical refresh syncing
664 off, any value higher than 0 will turn the vertical syncing on.
666 Under Windows and under X11, where the \c{WGL_EXT_swap_control}
667 and \c{GLX_SGI_video_sync} extensions are used, the \a interval
668 parameter can be used to set the minimum number of video frames
669 that are displayed before a buffer swap will occur. In effect,
670 setting the \a interval to 10, means there will be 10 vertical
671 retraces between every buffer swap.
673 Under Windows the \c{WGL_EXT_swap_control} extension has to be present,
674 and under X11 the \c{GLX_SGI_video_sync} extension has to be present.
676 void QGLFormat::setSwapInterval(int interval)
678 d->swapInterval = interval;
682 \since 4.2
684 Returns the currently set swap interval. -1 is returned if setting
685 the swap interval isn't supported in the system GL implementation.
687 int QGLFormat::swapInterval() const
689 return d->swapInterval;
693 \fn bool QGLFormat::hasOverlay() const
695 Returns true if overlay plane is enabled; otherwise returns false.
697 Overlay is disabled by default.
699 \sa setOverlay()
703 If \a enable is true enables an overlay plane; otherwise disables
704 the overlay plane.
706 Enabling the overlay plane will cause QGLWidget to create an
707 additional context in an overlay plane. See the QGLWidget
708 documentation for further information.
710 \sa hasOverlay()
713 void QGLFormat::setOverlay(bool enable)
715 setOption(enable ? QGL::HasOverlay : QGL::NoOverlay);
719 Returns the plane of this format. The default for normal formats
720 is 0, which means the normal plane. The default for overlay
721 formats is 1, which is the first overlay plane.
723 \sa setPlane()
725 int QGLFormat::plane() const
727 return d->pln;
731 Sets the requested plane to \a plane. 0 is the normal plane, 1 is
732 the first overlay plane, 2 is the second overlay plane, etc.; -1,
733 -2, etc. are underlay planes.
735 Note that in contrast to other format specifications, the plane
736 specifications will be matched exactly. This means that if you
737 specify a plane that the underlying OpenGL system cannot provide,
738 an \link QGLWidget::isValid() invalid\endlink QGLWidget will be
739 created.
741 \sa plane()
743 void QGLFormat::setPlane(int plane)
745 d->pln = plane;
749 Sets the format option to \a opt.
751 \sa testOption()
754 void QGLFormat::setOption(QGL::FormatOptions opt)
756 if (opt & 0xffff)
757 d->opts |= opt;
758 else
759 d->opts &= ~(opt >> 16);
765 Returns true if format option \a opt is set; otherwise returns false.
767 \sa setOption()
770 bool QGLFormat::testOption(QGL::FormatOptions opt) const
772 if (opt & 0xffff)
773 return (d->opts & opt) != 0;
774 else
775 return (d->opts & (opt >> 16)) == 0;
779 Set the minimum depth buffer size to \a size.
781 \sa depthBufferSize(), setDepth(), depth()
783 void QGLFormat::setDepthBufferSize(int size)
785 if (size < 0) {
786 qWarning("QGLFormat::setDepthBufferSize: Cannot set negative depth buffer size %d", size);
787 return;
789 d->depthSize = size;
793 Returns the depth buffer size.
795 \sa depth(), setDepth(), setDepthBufferSize()
797 int QGLFormat::depthBufferSize() const
799 return d->depthSize;
803 \since 4.2
805 Set the preferred red buffer size to \a size.
807 \sa setGreenBufferSize(), setBlueBufferSize(), setAlphaBufferSize()
809 void QGLFormat::setRedBufferSize(int size)
811 if (size < 0) {
812 qWarning("QGLFormat::setRedBufferSize: Cannot set negative red buffer size %d", size);
813 return;
815 d->redSize = size;
819 \since 4.2
821 Returns the red buffer size.
823 \sa setRedBufferSize()
825 int QGLFormat::redBufferSize() const
827 return d->redSize;
831 \since 4.2
833 Set the preferred green buffer size to \a size.
835 \sa setRedBufferSize(), setBlueBufferSize(), setAlphaBufferSize()
837 void QGLFormat::setGreenBufferSize(int size)
839 if (size < 0) {
840 qWarning("QGLFormat::setGreenBufferSize: Cannot set negative green buffer size %d", size);
841 return;
843 d->greenSize = size;
847 \since 4.2
849 Returns the green buffer size.
851 \sa setGreenBufferSize()
853 int QGLFormat::greenBufferSize() const
855 return d->greenSize;
859 \since 4.2
861 Set the preferred blue buffer size to \a size.
863 \sa setRedBufferSize(), setGreenBufferSize(), setAlphaBufferSize()
865 void QGLFormat::setBlueBufferSize(int size)
867 if (size < 0) {
868 qWarning("QGLFormat::setBlueBufferSize: Cannot set negative blue buffer size %d", size);
869 return;
871 d->blueSize = size;
875 \since 4.2
877 Returns the blue buffer size.
879 \sa setBlueBufferSize()
881 int QGLFormat::blueBufferSize() const
883 return d->blueSize;
887 Set the preferred alpha buffer size to \a size.
888 This function implicitly enables the alpha channel.
890 \sa setRedBufferSize(), setGreenBufferSize(), alphaBufferSize()
892 void QGLFormat::setAlphaBufferSize(int size)
894 if (size < 0) {
895 qWarning("QGLFormat::setAlphaBufferSize: Cannot set negative alpha buffer size %d", size);
896 return;
898 d->alphaSize = size;
899 setOption(QGL::AlphaChannel);
903 Returns the alpha buffer size.
905 \sa alpha(), setAlpha(), setAlphaBufferSize()
907 int QGLFormat::alphaBufferSize() const
909 return d->alphaSize;
913 Set the preferred accumulation buffer size, where \a size is the
914 bit depth for each RGBA component.
916 \sa accum(), setAccum(), accumBufferSize()
918 void QGLFormat::setAccumBufferSize(int size)
920 if (size < 0) {
921 qWarning("QGLFormat::setAccumBufferSize: Cannot set negative accumulate buffer size %d", size);
922 return;
924 d->accumSize = size;
928 Returns the accumulation buffer size.
930 \sa setAccumBufferSize(), accum(), setAccum()
932 int QGLFormat::accumBufferSize() const
934 return d->accumSize;
938 Set the preferred stencil buffer size to \a size.
940 \sa stencilBufferSize(), setStencil(), stencil()
942 void QGLFormat::setStencilBufferSize(int size)
944 if (size < 0) {
945 qWarning("QGLFormat::setStencilBufferSize: Cannot set negative stencil buffer size %d", size);
946 return;
948 d->stencilSize = size;
952 Returns the stencil buffer size.
954 \sa stencil(), setStencil(), setStencilBufferSize()
956 int QGLFormat::stencilBufferSize() const
958 return d->stencilSize;
962 \fn bool QGLFormat::hasOpenGL()
964 Returns true if the window system has any OpenGL support;
965 otherwise returns false.
967 \warning This function must not be called until the QApplication
968 object has been created.
974 \fn bool QGLFormat::hasOpenGLOverlays()
976 Returns true if the window system supports OpenGL overlays;
977 otherwise returns false.
979 \warning This function must not be called until the QApplication
980 object has been created.
983 QGLFormat::OpenGLVersionFlags Q_AUTOTEST_EXPORT qOpenGLVersionFlagsFromString(const QString &versionString)
985 QGLFormat::OpenGLVersionFlags versionFlags = QGLFormat::OpenGL_Version_None;
987 if (versionString.startsWith(QLatin1String("OpenGL ES"))) {
988 QStringList parts = versionString.split(QLatin1Char(' '));
989 if (parts.size() >= 3) {
990 if (parts[2].startsWith(QLatin1String("1."))) {
991 if (parts[1].endsWith(QLatin1String("-CM"))) {
992 versionFlags |= QGLFormat::OpenGL_ES_Common_Version_1_0 |
993 QGLFormat::OpenGL_ES_CommonLite_Version_1_0;
994 if (parts[2].startsWith(QLatin1String("1.1")))
995 versionFlags |= QGLFormat::OpenGL_ES_Common_Version_1_1 |
996 QGLFormat::OpenGL_ES_CommonLite_Version_1_1;
998 else {
999 // Not -CM, must be CL, CommonLite
1000 versionFlags |= QGLFormat::OpenGL_ES_CommonLite_Version_1_0;
1001 if (parts[2].startsWith(QLatin1String("1.1")))
1002 versionFlags |= QGLFormat::OpenGL_ES_CommonLite_Version_1_1;
1005 else {
1006 // OpenGL ES version 2.0 or higher
1007 versionFlags |= QGLFormat::OpenGL_ES_Version_2_0;
1010 else {
1011 // if < 3 parts to the name, it is an unrecognised OpenGL ES
1012 qWarning("Unrecognised OpenGL ES version");
1015 else {
1016 // not ES, regular OpenGL, the version numbers are first in the string
1017 if (versionString.startsWith(QLatin1String("1."))) {
1018 switch (versionString[2].toAscii()) {
1019 case '5':
1020 versionFlags |= QGLFormat::OpenGL_Version_1_5;
1021 case '4':
1022 versionFlags |= QGLFormat::OpenGL_Version_1_4;
1023 case '3':
1024 versionFlags |= QGLFormat::OpenGL_Version_1_3;
1025 case '2':
1026 versionFlags |= QGLFormat::OpenGL_Version_1_2;
1027 case '1':
1028 versionFlags |= QGLFormat::OpenGL_Version_1_1;
1029 default:
1030 break;
1033 else if (versionString.startsWith(QLatin1String("2."))) {
1034 versionFlags |= QGLFormat::OpenGL_Version_1_1 |
1035 QGLFormat::OpenGL_Version_1_2 |
1036 QGLFormat::OpenGL_Version_1_3 |
1037 QGLFormat::OpenGL_Version_1_4 |
1038 QGLFormat::OpenGL_Version_1_5 |
1039 QGLFormat::OpenGL_Version_2_0;
1040 QString minorVersion = versionString.section(QLatin1Char(' '), 0, 0).section(QLatin1Char('.'), 1, 1);
1041 if (minorVersion == QChar(QLatin1Char('1')))
1042 versionFlags |= QGLFormat::OpenGL_Version_2_1;
1044 else if (versionString.startsWith(QLatin1String("3."))) {
1045 versionFlags |= QGLFormat::OpenGL_Version_1_1 |
1046 QGLFormat::OpenGL_Version_1_2 |
1047 QGLFormat::OpenGL_Version_1_3 |
1048 QGLFormat::OpenGL_Version_1_4 |
1049 QGLFormat::OpenGL_Version_1_5 |
1050 QGLFormat::OpenGL_Version_2_0 |
1051 QGLFormat::OpenGL_Version_2_1 |
1052 QGLFormat::OpenGL_Version_3_0;
1054 else
1055 qWarning("Unrecognised OpenGL version");
1057 return versionFlags;
1061 \enum QGLFormat::OpenGLVersionFlag
1062 \since 4.2
1064 This enum describes the various OpenGL versions that are
1065 recognized by Qt. Use the QGLFormat::openGLVersionFlags() function
1066 to identify which versions that are supported at runtime.
1068 \value OpenGL_Version_None If no OpenGL is present or if no OpenGL context is current.
1070 \value OpenGL_Version_1_1 OpenGL version 1.1 or higher is present.
1072 \value OpenGL_Version_1_2 OpenGL version 1.2 or higher is present.
1074 \value OpenGL_Version_1_3 OpenGL version 1.3 or higher is present.
1076 \value OpenGL_Version_1_4 OpenGL version 1.4 or higher is present.
1078 \value OpenGL_Version_1_5 OpenGL version 1.5 or higher is present.
1080 \value OpenGL_Version_2_0 OpenGL version 2.0 or higher is present.
1081 Note that version 2.0 supports all the functionality of version 1.5.
1083 \value OpenGL_Version_2_1 OpenGL version 2.1 or higher is present.
1085 \value OpenGL_Version_3_0 OpenGL version 3.0 or higher is present.
1087 \value OpenGL_ES_CommonLite_Version_1_0 OpenGL ES version 1.0 Common Lite or higher is present.
1089 \value OpenGL_ES_Common_Version_1_0 OpenGL ES version 1.0 Common or higher is present.
1090 The Common profile supports all the features of Common Lite.
1092 \value OpenGL_ES_CommonLite_Version_1_1 OpenGL ES version 1.1 Common Lite or higher is present.
1094 \value OpenGL_ES_Common_Version_1_1 OpenGL ES version 1.1 Common or higher is present.
1095 The Common profile supports all the features of Common Lite.
1097 \value OpenGL_ES_Version_2_0 OpenGL ES version 2.0 or higher is present.
1098 Note that OpenGL ES version 2.0 does not support all the features of OpenGL ES 1.x.
1099 So if OpenGL_ES_Version_2_0 is returned, none of the ES 1.x flags are returned.
1101 See also \l{http://www.opengl.org} for more information about the different
1102 revisions of OpenGL.
1104 \sa openGLVersionFlags()
1108 \since 4.2
1110 Identifies, at runtime, which OpenGL versions that are supported
1111 by the current platform.
1113 Note that if OpenGL version 1.5 is supported, its predecessors
1114 (i.e., version 1.4 and lower) are also supported. To identify the
1115 support of a particular feature, like multi texturing, test for
1116 the version in which the feature was first introduced (i.e.,
1117 version 1.3 in the case of multi texturing) to adapt to the largest
1118 possible group of runtime platforms.
1120 This function needs a valid current OpenGL context to work;
1121 otherwise it will return OpenGL_Version_None.
1123 \sa hasOpenGL(), hasOpenGLOverlays()
1125 QGLFormat::OpenGLVersionFlags QGLFormat::openGLVersionFlags()
1127 static bool cachedDefault = false;
1128 static OpenGLVersionFlags defaultVersionFlags = OpenGL_Version_None;
1129 QGLContext *currentCtx = const_cast<QGLContext *>(QGLContext::currentContext());
1130 QGLWidget *dummy = 0;
1132 if (currentCtx && currentCtx->d_func()->version_flags_cached)
1133 return currentCtx->d_func()->version_flags;
1135 if (!currentCtx) {
1136 if (cachedDefault) {
1137 return defaultVersionFlags;
1138 } else {
1139 cachedDefault = true;
1140 if (!hasOpenGL())
1141 return defaultVersionFlags;
1142 dummy = new QGLWidget;
1143 dummy->makeCurrent(); // glGetString() needs a current context
1147 QString versionString(QLatin1String(reinterpret_cast<const char*>(glGetString(GL_VERSION))));
1148 OpenGLVersionFlags versionFlags = qOpenGLVersionFlagsFromString(versionString);
1149 if (currentCtx) {
1150 currentCtx->d_func()->version_flags_cached = true;
1151 currentCtx->d_func()->version_flags = versionFlags;
1153 if (dummy) {
1154 defaultVersionFlags = versionFlags;
1155 delete dummy;
1158 return versionFlags;
1163 Returns the default QGLFormat for the application. All QGLWidgets
1164 that are created use this format unless another format is
1165 specified, e.g. when they are constructed.
1167 If no special default format has been set using
1168 setDefaultFormat(), the default format is the same as that created
1169 with QGLFormat().
1171 \sa setDefaultFormat()
1174 QGLFormat QGLFormat::defaultFormat()
1176 return *qgl_default_format();
1180 Sets a new default QGLFormat for the application to \a f. For
1181 example, to set single buffering as the default instead of double
1182 buffering, your main() might contain code like this:
1183 \snippet doc/src/snippets/code/src_opengl_qgl.cpp 4
1185 \sa defaultFormat()
1188 void QGLFormat::setDefaultFormat(const QGLFormat &f)
1190 *qgl_default_format() = f;
1195 Returns the default QGLFormat for overlay contexts.
1197 The factory default overlay format is:
1198 \list
1199 \i \link setDoubleBuffer() Double buffer:\endlink Disabled.
1200 \i \link setDepth() Depth buffer:\endlink Disabled.
1201 \i \link setRgba() RGBA:\endlink Disabled (i.e., color index enabled).
1202 \i \link setAlpha() Alpha channel:\endlink Disabled.
1203 \i \link setAccum() Accumulator buffer:\endlink Disabled.
1204 \i \link setStencil() Stencil buffer:\endlink Disabled.
1205 \i \link setStereo() Stereo:\endlink Disabled.
1206 \i \link setDirectRendering() Direct rendering:\endlink Enabled.
1207 \i \link setOverlay() Overlay:\endlink Disabled.
1208 \i \link setPlane() Plane:\endlink 1 (i.e., first overlay plane).
1209 \endlist
1211 \sa setDefaultFormat()
1214 QGLFormat QGLFormat::defaultOverlayFormat()
1216 return *defaultOverlayFormatInstance();
1220 Sets a new default QGLFormat for overlay contexts to \a f. This
1221 format is used whenever a QGLWidget is created with a format that
1222 hasOverlay() enabled.
1224 For example, to get a double buffered overlay context (if
1225 available), use code like this:
1227 \snippet doc/src/snippets/code/src_opengl_qgl.cpp 5
1229 As usual, you can find out after widget creation whether the
1230 underlying OpenGL system was able to provide the requested
1231 specification:
1233 \snippet doc/src/snippets/code/src_opengl_qgl.cpp 6
1235 \sa defaultOverlayFormat()
1238 void QGLFormat::setDefaultOverlayFormat(const QGLFormat &f)
1240 QGLFormat *defaultFormat = defaultOverlayFormatInstance();
1241 *defaultFormat = f;
1242 // Make sure the user doesn't request that the overlays themselves
1243 // have overlays, since it is unlikely that the system supports
1244 // infinitely many planes...
1245 defaultFormat->setOverlay(false);
1250 Returns true if all the options of the two QGLFormats are equal;
1251 otherwise returns false.
1254 bool operator==(const QGLFormat& a, const QGLFormat& b)
1256 return (int) a.d->opts == (int) b.d->opts && a.d->pln == b.d->pln && a.d->alphaSize == b.d->alphaSize
1257 && a.d->accumSize == b.d->accumSize && a.d->stencilSize == b.d->stencilSize
1258 && a.d->depthSize == b.d->depthSize;
1263 Returns false if all the options of the two QGLFormats are equal;
1264 otherwise returns true.
1267 bool operator!=(const QGLFormat& a, const QGLFormat& b)
1269 return !(a == b);
1272 /*****************************************************************************
1273 QGLContext implementation
1274 *****************************************************************************/
1275 void QGLContextPrivate::init(QPaintDevice *dev, const QGLFormat &format)
1277 Q_Q(QGLContext);
1278 glFormat = reqFormat = format;
1279 valid = false;
1280 q->setDevice(dev);
1281 #if defined(Q_WS_X11)
1282 pbuf = 0;
1283 gpm = 0;
1284 vi = 0;
1285 screen = QX11Info::appScreen();
1286 #endif
1287 #if defined(Q_WS_WIN)
1288 dc = 0;
1289 win = 0;
1290 pixelFormatId = 0;
1291 cmap = 0;
1292 hbitmap = 0;
1293 hbitmap_hdc = 0;
1294 #endif
1295 #if defined(Q_WS_MAC)
1296 # ifndef QT_MAC_USE_COCOA
1297 update = false;
1298 # endif
1299 vi = 0;
1300 #endif
1301 #if defined(QT_OPENGL_ES)
1302 eglContext = 0;
1303 #endif
1304 pbo = 0;
1305 fbo = 0;
1306 crWin = false;
1307 initDone = false;
1308 sharing = false;
1309 clear_on_painter_begin = true;
1310 max_texture_size = -1;
1311 version_flags_cached = false;
1312 version_flags = QGLFormat::OpenGL_Version_None;
1313 current_fbo = 0;
1314 active_engine = 0;
1317 QGLContext* QGLContext::currentCtx = 0;
1320 Read back the contents of the currently bound framebuffer, used in
1321 QGLWidget::grabFrameBuffer(), QGLPixelbuffer::toImage() and
1322 QGLFramebufferObject::toImage()
1325 static void convertFromGLImage(QImage &img, int w, int h, bool alpha_format, bool include_alpha)
1327 if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
1328 // OpenGL gives RGBA; Qt wants ARGB
1329 uint *p = (uint*)img.bits();
1330 uint *end = p + w*h;
1331 if (alpha_format && include_alpha) {
1332 while (p < end) {
1333 uint a = *p << 24;
1334 *p = (*p >> 8) | a;
1335 p++;
1337 } else {
1338 // This is an old legacy fix for PowerPC based Macs, which
1339 // we shouldn't remove
1340 while (p < end) {
1341 *p = 0xff000000 | (*p>>8);
1342 ++p;
1345 } else {
1346 // OpenGL gives ABGR (i.e. RGBA backwards); Qt wants ARGB
1347 for (int y = 0; y < h; y++) {
1348 uint *q = (uint*)img.scanLine(y);
1349 for (int x=0; x < w; ++x) {
1350 const uint pixel = *q;
1351 *q = ((pixel << 16) & 0xff0000) | ((pixel >> 16) & 0xff) | (pixel & 0xff00ff00);
1352 q++;
1357 img = img.mirrored();
1360 QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha)
1362 QImage img(size, alpha_format ? QImage::Format_ARGB32 : QImage::Format_RGB32);
1363 int w = size.width();
1364 int h = size.height();
1365 glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, img.bits());
1366 convertFromGLImage(img, w, h, alpha_format, include_alpha);
1367 return img;
1370 QImage qt_gl_read_texture(const QSize &size, bool alpha_format, bool include_alpha)
1372 QImage img(size, alpha_format ? QImage::Format_ARGB32 : QImage::Format_RGB32);
1373 int w = size.width();
1374 int h = size.height();
1375 #if !defined(QT_OPENGL_ES_2) && !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
1376 //### glGetTexImage not in GL ES 2.0, need to do something else here!
1377 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, img.bits());
1378 #endif
1379 convertFromGLImage(img, w, h, alpha_format, include_alpha);
1380 return img;
1383 // returns the highest number closest to v, which is a power of 2
1384 // NB! assumes 32 bit ints
1385 int qt_next_power_of_two(int v)
1387 v--;
1388 v |= v >> 1;
1389 v |= v >> 2;
1390 v |= v >> 4;
1391 v |= v >> 8;
1392 v |= v >> 16;
1393 ++v;
1394 return v;
1397 class QGLTexture {
1398 public:
1399 QGLTexture(const QGLContext *ctx, GLuint tx_id, GLenum tx_target, bool _clean = false)
1400 : context(ctx), id(tx_id), target(tx_target), clean(_clean) {}
1401 ~QGLTexture() {
1402 if (clean) {
1403 QGLContext *current = const_cast<QGLContext *>(QGLContext::currentContext());
1404 QGLContext *ctx = const_cast<QGLContext *>(context);
1405 bool switch_context = current && current != ctx && !qgl_share_reg()->checkSharing(current, ctx);
1406 if (switch_context)
1407 ctx->makeCurrent();
1408 glDeleteTextures(1, &id);
1409 if (switch_context)
1410 current->makeCurrent();
1414 const QGLContext *context;
1415 GLuint id;
1416 GLenum target;
1417 bool clean;
1420 typedef QCache<qint64, QGLTexture> QGLTextureCache;
1421 static int qt_tex_cache_limit = 64*1024; // cache ~64 MB worth of textures - this is not accurate though
1422 static QGLTextureCache *qt_tex_cache = 0;
1424 typedef void (*_qt_pixmap_cleanup_hook_64)(qint64);
1425 typedef void (*_qt_image_cleanup_hook_64)(qint64);
1427 extern Q_GUI_EXPORT _qt_pixmap_cleanup_hook_64 qt_pixmap_cleanup_hook_64;
1428 extern Q_GUI_EXPORT _qt_image_cleanup_hook_64 qt_image_cleanup_hook_64;
1430 // DDS format structure
1431 struct DDSFormat {
1432 quint32 dwSize;
1433 quint32 dwFlags;
1434 quint32 dwHeight;
1435 quint32 dwWidth;
1436 quint32 dwLinearSize;
1437 quint32 dummy1;
1438 quint32 dwMipMapCount;
1439 quint32 dummy2[11];
1440 struct {
1441 quint32 dummy3[2];
1442 quint32 dwFourCC;
1443 quint32 dummy4[5];
1444 } ddsPixelFormat;
1447 // compressed texture pixel formats
1448 #define FOURCC_DXT1 0x31545844
1449 #define FOURCC_DXT2 0x32545844
1450 #define FOURCC_DXT3 0x33545844
1451 #define FOURCC_DXT4 0x34545844
1452 #define FOURCC_DXT5 0x35545844
1454 #ifndef GL_COMPRESSED_RGB_S3TC_DXT1_EXT
1455 #define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
1456 #define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
1457 #define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2
1458 #define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3
1459 #endif
1461 #ifndef GL_GENERATE_MIPMAP_SGIS
1462 #define GL_GENERATE_MIPMAP_SGIS 0x8191
1463 #define GL_GENERATE_MIPMAP_HINT_SGIS 0x8192
1464 #endif
1466 Q_GLOBAL_STATIC(QGLShareRegister, _qgl_share_reg)
1467 Q_OPENGL_EXPORT QGLShareRegister* qgl_share_reg()
1469 return _qgl_share_reg();
1473 \class QGLContext
1474 \brief The QGLContext class encapsulates an OpenGL rendering context.
1476 \ingroup multimedia
1478 An OpenGL rendering context is a complete set of OpenGL state
1479 variables. The rendering context's \l {QGL::FormatOption} {format}
1480 is set in the constructor, but it can also be set later with
1481 setFormat(). The format options that are actually set are returned
1482 by format(); the options you asked for are returned by
1483 requestedFormat(). Note that after a QGLContext object has been
1484 constructed, the actual OpenGL context must be created by
1485 explicitly calling the \link create() create()\endlink
1486 function. The makeCurrent() function makes this context the
1487 current rendering context. You can make \e no context current
1488 using doneCurrent(). The reset() function will reset the context
1489 and make it invalid.
1491 You can examine properties of the context with, e.g. isValid(),
1492 isSharing(), initialized(), windowCreated() and
1493 overlayTransparentColor().
1495 If you're using double buffering you can swap the screen contents
1496 with the off-screen buffer using swapBuffers().
1498 Please note that QGLContext is not thread safe.
1503 \obsolete
1505 Constructs an OpenGL context for the given paint \a device, which
1506 can be a widget or a pixmap. The \a format specifies several
1507 display options for the context.
1509 If the underlying OpenGL/Window system cannot satisfy all the
1510 features requested in \a format, the nearest subset of features
1511 will be used. After creation, the format() method will return the
1512 actual format obtained.
1514 Note that after a QGLContext object has been constructed, \l
1515 create() must be called explicitly to create the actual OpenGL
1516 context. The context will be \l {isValid()}{invalid} if it was not
1517 possible to obtain a GL context at all.
1520 QGLContext::QGLContext(const QGLFormat &format, QPaintDevice *device)
1522 d_ptr = new QGLContextPrivate(this);
1523 Q_D(QGLContext);
1524 d->init(device, format);
1528 Constructs an OpenGL context with the given \a format which
1529 specifies several display options for the context.
1531 If the underlying OpenGL/Window system cannot satisfy all the
1532 features requested in \a format, the nearest subset of features
1533 will be used. After creation, the format() method will return the
1534 actual format obtained.
1536 Note that after a QGLContext object has been constructed, \l
1537 create() must be called explicitly to create the actual OpenGL
1538 context. The context will be \l {isValid()}{invalid} if it was not
1539 possible to obtain a GL context at all.
1541 \sa format(), isValid()
1543 QGLContext::QGLContext(const QGLFormat &format)
1545 d_ptr = new QGLContextPrivate(this);
1546 Q_D(QGLContext);
1547 d->init(0, format);
1551 Destroys the OpenGL context and frees its resources.
1554 QGLContext::~QGLContext()
1556 Q_D(QGLContext);
1557 // remove any textures cached in this context
1558 if (qt_tex_cache) {
1559 QList<qint64> keys = qt_tex_cache->keys();
1560 for (int i = 0; i < keys.size(); ++i) {
1561 const qint64 &key = keys.at(i);
1562 if (qt_tex_cache->object(key)->context == this)
1563 qt_tex_cache->remove(key);
1565 // ### thread safety
1566 if (qt_tex_cache->size() == 0) {
1567 qt_pixmap_cleanup_hook_64 = 0;
1568 qt_image_cleanup_hook_64 = 0;
1569 delete qt_tex_cache;
1570 qt_tex_cache = 0;
1574 QGLSignalProxy::instance()->emitAboutToDestroyContext(this);
1575 reset();
1576 delete d;
1579 void QGLContextPrivate::cleanup()
1581 Q_Q(QGLContext);
1582 if (pbo) {
1583 QGLContext *ctx = q;
1584 glDeleteBuffers(1, &pbo);
1585 pbo = 0;
1589 typedef QHash<QString, GLuint> QGLDDSCache;
1590 Q_GLOBAL_STATIC(QGLDDSCache, qgl_dds_cache)
1593 \overload
1595 Reads the DirectDrawSurface (DDS) compressed file \a fileName and
1596 generates a 2D GL texture from it.
1598 Only the DXT1, DXT3 and DXT5 DDS formats are supported.
1600 Note that this will only work if the implementation supports the
1601 \c GL_ARB_texture_compression and \c GL_EXT_texture_compression_s3tc
1602 extensions.
1604 \sa deleteTexture()
1607 GLuint QGLContext::bindTexture(const QString &fileName)
1609 if (!qt_glCompressedTexImage2DARB) {
1610 qWarning("QGLContext::bindTexture(): The GL implementation does not support texture"
1611 "compression extensions.");
1612 return 0;
1615 QGLDDSCache::const_iterator it = qgl_dds_cache()->constFind(fileName);
1616 if (it != qgl_dds_cache()->constEnd()) {
1617 glBindTexture(GL_TEXTURE_2D, it.value());
1618 return it.value();
1621 QFile f(fileName);
1622 f.open(QIODevice::ReadOnly);
1624 char tag[4];
1625 f.read(&tag[0], 4);
1626 if (strncmp(tag,"DDS ", 4) != 0) {
1627 qWarning("QGLContext::bindTexture(): not a DDS image file.");
1628 return 0;
1631 DDSFormat ddsHeader;
1632 f.read((char *) &ddsHeader, sizeof(DDSFormat));
1634 if (!ddsHeader.dwLinearSize) {
1635 qWarning("QGLContext::bindTexture() DDS image size is not valid.");
1636 return 0;
1639 int factor = 4;
1640 int bufferSize = 0;
1641 int blockSize = 16;
1642 GLenum format;
1644 switch(ddsHeader.ddsPixelFormat.dwFourCC) {
1645 case FOURCC_DXT1:
1646 format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
1647 factor = 2;
1648 blockSize = 8;
1649 break;
1650 case FOURCC_DXT3:
1651 format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
1652 break;
1653 case FOURCC_DXT5:
1654 format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
1655 break;
1656 default:
1657 qWarning("QGLContext::bindTexture() DDS image format not supported.");
1658 return 0;
1661 if (ddsHeader.dwMipMapCount > 1)
1662 bufferSize = ddsHeader.dwLinearSize * factor;
1663 else
1664 bufferSize = ddsHeader.dwLinearSize;
1666 GLubyte *pixels = (GLubyte *) malloc(bufferSize*sizeof(GLubyte));
1667 f.seek(ddsHeader.dwSize + 4);
1668 f.read((char *) pixels, bufferSize);
1669 f.close();
1671 GLuint tx_id;
1672 glGenTextures(1, &tx_id);
1673 glBindTexture(GL_TEXTURE_2D, tx_id);
1674 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1675 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1677 int size;
1678 int offset = 0;
1679 int w = ddsHeader.dwWidth;
1680 int h = ddsHeader.dwHeight;
1682 // load mip-maps
1683 for(int i = 0; i < (int) ddsHeader.dwMipMapCount; ++i) {
1684 if (w == 0) w = 1;
1685 if (h == 0) h = 1;
1687 size = ((w+3)/4) * ((h+3)/4) * blockSize;
1688 qt_glCompressedTexImage2DARB(GL_TEXTURE_2D, i, format, w, h, 0,
1689 size, pixels + offset);
1690 offset += size;
1692 // half size for each mip-map level
1693 w = w/2;
1694 h = h/2;
1697 free(pixels);
1699 qgl_dds_cache()->insert(fileName, tx_id);
1700 return tx_id;
1704 a hook that removes textures from the cache when a pixmap/image
1705 is deref'ed
1707 static void qt_gl_clean_cache(qint64 cacheKey)
1709 // ### remove when the GL texture cache becomes thread-safe
1710 if (qApp->thread() != QThread::currentThread())
1711 return;
1712 if (qt_tex_cache) {
1713 QGLTexture *texture = qt_tex_cache->object(cacheKey);
1714 if (texture && texture->clean)
1715 qt_tex_cache->remove(cacheKey);
1719 static void convertToGLFormatHelper(QImage &dst, const QImage &img, GLenum texture_format)
1721 Q_ASSERT(dst.depth() == 32);
1722 Q_ASSERT(img.depth() == 32);
1724 if (dst.size() != img.size()) {
1725 int target_width = dst.width();
1726 int target_height = dst.height();
1727 qreal sx = target_width / qreal(img.width());
1728 qreal sy = target_height / qreal(img.height());
1730 quint32 *dest = (quint32 *) dst.scanLine(0); // NB! avoid detach here
1731 uchar *srcPixels = (uchar *) img.scanLine(img.height() - 1);
1732 int sbpl = img.bytesPerLine();
1733 int dbpl = dst.bytesPerLine();
1735 int ix = 0x00010000 / sx;
1736 int iy = 0x00010000 / sy;
1738 quint32 basex = int(0.5 * ix);
1739 quint32 srcy = int(0.5 * iy);
1741 // scale, swizzle and mirror in one loop
1742 while (target_height--) {
1743 const uint *src = (const quint32 *) (srcPixels - (srcy >> 16) * sbpl);
1744 int srcx = basex;
1745 for (int x=0; x<target_width; ++x) {
1746 uint src_pixel = src[srcx >> 16];
1747 if (texture_format == GL_BGRA) {
1748 if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
1749 dest[x] = ((src_pixel << 24) & 0xff000000)
1750 | ((src_pixel >> 24) & 0x000000ff)
1751 | ((src_pixel << 8) & 0x00ff0000)
1752 | ((src_pixel >> 8) & 0x0000ff00);
1753 } else {
1754 dest[x] = src_pixel;
1756 } else { // GL_RGBA
1757 if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
1758 dest[x] = (src_pixel << 8) | ((src_pixel >> 24) & 0xff);
1759 } else {
1760 dest[x] = ((src_pixel << 16) & 0xff0000)
1761 | ((src_pixel >> 16) & 0xff)
1762 | (src_pixel & 0xff00ff00);
1765 srcx += ix;
1767 dest = (quint32 *)(((uchar *) dest) + dbpl);
1768 srcy += iy;
1770 } else {
1771 const int width = img.width();
1772 const int height = img.height();
1773 const uint *p = (const uint*) img.scanLine(img.height() - 1);
1774 uint *q = (uint*) dst.scanLine(0);
1776 if (texture_format == GL_BGRA) {
1777 if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
1778 // mirror + swizzle
1779 for (int i=0; i < height; ++i) {
1780 const uint *end = p + width;
1781 while (p < end) {
1782 *q = ((*p << 24) & 0xff000000)
1783 | ((*p >> 24) & 0x000000ff)
1784 | ((*p << 8) & 0x00ff0000)
1785 | ((*p >> 8) & 0x0000ff00);
1786 p++;
1787 q++;
1789 p -= 2 * width;
1791 } else {
1792 const uint bytesPerLine = img.bytesPerLine();
1793 for (int i=0; i < height; ++i) {
1794 memcpy(q, p, bytesPerLine);
1795 q += width;
1796 p -= width;
1799 } else {
1800 if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
1801 for (int i=0; i < height; ++i) {
1802 const uint *end = p + width;
1803 while (p < end) {
1804 *q = (*p << 8) | ((*p >> 24) & 0xff);
1805 p++;
1806 q++;
1808 p -= 2 * width;
1810 } else {
1811 for (int i=0; i < height; ++i) {
1812 const uint *end = p + width;
1813 while (p < end) {
1814 *q = ((*p << 16) & 0xff0000) | ((*p >> 16) & 0xff) | (*p & 0xff00ff00);
1815 p++;
1816 q++;
1818 p -= 2 * width;
1825 QImage QGLContextPrivate::convertToGLFormat(const QImage &image, bool force_premul,
1826 GLenum texture_format)
1828 QImage::Format target_format = image.format();
1829 if (force_premul || image.format() != QImage::Format_ARGB32)
1830 target_format = QImage::Format_ARGB32_Premultiplied;
1832 QImage result(image.width(), image.height(), target_format);
1833 convertToGLFormatHelper(result, image.convertToFormat(target_format), texture_format);
1834 return result;
1837 GLuint QGLContextPrivate::bindTexture(const QImage &image, GLenum target, GLint format,
1838 const qint64 key, bool clean)
1840 Q_Q(QGLContext);
1842 QGLContext *ctx = q;
1844 bool use_pbo = false;
1845 if (QGLExtensions::glExtensions & QGLExtensions::PixelBufferObject) {
1847 use_pbo = qt_resolve_buffer_extensions(ctx);
1848 if (use_pbo && pbo == 0)
1849 glGenBuffers(1, &pbo);
1852 // the GL_BGRA format is only present in GL version >= 1.2
1853 GLenum texture_format = (QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_1_2)
1854 ? GL_BGRA : GL_RGBA;
1855 if (!qt_tex_cache) {
1856 qt_tex_cache = new QGLTextureCache(qt_tex_cache_limit);
1857 qt_pixmap_cleanup_hook_64 = qt_gl_clean_cache;
1858 qt_image_cleanup_hook_64 = qt_gl_clean_cache;
1861 // Scale the pixmap if needed. GL textures needs to have the
1862 // dimensions 2^n+2(border) x 2^m+2(border), unless we're using GL
1863 // 2.0 or use the GL_TEXTURE_RECTANGLE texture target
1864 int tx_w = qt_next_power_of_two(image.width());
1865 int tx_h = qt_next_power_of_two(image.height());
1866 bool scale = false;
1868 QImage img = image;
1869 if (( !(QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_2_0) &&
1870 !(QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_ES_Version_2_0) )
1871 && (target == GL_TEXTURE_2D && (tx_w != image.width() || tx_h != image.height())))
1873 scale = true;
1876 GLuint tx_id;
1877 glGenTextures(1, &tx_id);
1878 glBindTexture(target, tx_id);
1879 glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1880 if (glFormat.directRendering()
1881 && QGLExtensions::glExtensions & QGLExtensions::GenerateMipmap
1882 && target == GL_TEXTURE_2D && !clean)
1884 glHint(GL_GENERATE_MIPMAP_HINT_SGIS, GL_NICEST);
1885 #ifndef QT_OPENGL_ES
1886 glTexParameteri(target, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
1887 #else
1888 glTexParameterf(target, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
1889 #endif
1890 glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
1892 // Mipmap generation causes huge slowdown with PBO's for some reason
1893 use_pbo = false;
1894 } else {
1895 glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1898 uchar *ptr = 0;
1899 if (use_pbo) {
1900 glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, pbo);
1901 glBufferData(GL_PIXEL_UNPACK_BUFFER_ARB, img.width() * img.height() * 4, 0, GL_STREAM_DRAW_ARB);
1902 ptr = reinterpret_cast<uchar *>(glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY_ARB));
1905 QImage::Format target_format = img.format();
1906 // Note: the clean param is only true when a texture is bound
1907 // from the QOpenGLPaintEngine - in that case we have to force
1908 // a premultiplied texture format
1909 if (clean || img.format() != QImage::Format_ARGB32)
1910 target_format = QImage::Format_ARGB32_Premultiplied;
1911 if (img.format() != target_format)
1912 img = img.convertToFormat(target_format);
1914 if (ptr) {
1915 QImage buffer(ptr, img.width(), img.height(), target_format);
1916 convertToGLFormatHelper(buffer, img, texture_format);
1917 glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB);
1918 glTexImage2D(target, 0, format, img.width(), img.height(), 0, texture_format,
1919 GL_UNSIGNED_BYTE, 0);
1920 } else {
1921 QImage tx(scale ? QSize(tx_w, tx_h) : img.size(), target_format);
1922 convertToGLFormatHelper(tx, img, texture_format);
1923 glTexImage2D(target, 0, format, tx.width(), tx.height(), 0, texture_format,
1924 GL_UNSIGNED_BYTE, tx.bits());
1927 if (use_pbo)
1928 glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
1930 // this assumes the size of a texture is always smaller than the max cache size
1931 int cost = img.width()*img.height()*4/1024;
1932 if (qt_tex_cache->totalCost() + cost > qt_tex_cache->maxCost()) {
1933 // the cache is full - make an attempt to remove something
1934 const QList<qint64> keys = qt_tex_cache->keys();
1935 int i = 0;
1936 while (i < qt_tex_cache->count()
1937 && (qt_tex_cache->totalCost() + cost > qt_tex_cache->maxCost())) {
1938 QGLTexture *tex = qt_tex_cache->object(keys.at(i));
1939 if (tex->context == q)
1940 qt_tex_cache->remove(keys.at(i));
1941 ++i;
1944 qt_tex_cache->insert(key, new QGLTexture(q, tx_id, target, clean), cost);
1945 return tx_id;
1948 bool QGLContextPrivate::textureCacheLookup(const qint64 key, GLenum target, GLuint *id)
1950 Q_Q(QGLContext);
1951 if (qt_tex_cache) {
1952 QGLTexture *texture = qt_tex_cache->object(key);
1953 if (texture && texture->target == target
1954 && (texture->context == q || qgl_share_reg()->checkSharing(q, texture->context)))
1956 *id = texture->id;
1957 return true;
1960 return false;
1963 /*! \internal */
1964 GLuint QGLContextPrivate::bindTexture(const QImage &image, GLenum target, GLint format, bool clean)
1966 const qint64 key = image.cacheKey();
1967 GLuint id;
1968 if (textureCacheLookup(key, target, &id)) {
1969 glBindTexture(target, id);
1970 return id;
1972 GLuint cached = bindTexture(image, target, format, key, clean);
1973 const_cast<QImage &>(image).data_ptr()->is_cached = (cached > 0);
1974 return cached;
1977 /*! \internal */
1978 GLuint QGLContextPrivate::bindTexture(const QPixmap &pixmap, GLenum target, GLint format, bool clean)
1980 Q_Q(QGLContext);
1981 QPixmapData *pd = pixmap.pixmapData();
1982 #if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
1983 if (target == GL_TEXTURE_2D && pd->classId() == QPixmapData::OpenGLClass) {
1984 const QGLPixmapData *data = static_cast<const QGLPixmapData *>(pd);
1986 if (data->isValidContext(q))
1987 return data->bind();
1989 #endif
1991 const qint64 key = pixmap.cacheKey();
1992 GLuint id;
1993 if (textureCacheLookup(key, target, &id)) {
1994 glBindTexture(target, id);
1995 return id;
1997 GLuint cached = bindTexture(pixmap.toImage(), target, format, key, clean);
1998 const_cast<QPixmap &>(pixmap).data_ptr()->is_cached = (cached > 0);
1999 return cached;
2002 /*! \internal */
2003 int QGLContextPrivate::maxTextureSize()
2005 if (max_texture_size != -1)
2006 return max_texture_size;
2008 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size);
2010 #if defined(QT_OPENGL_ES)
2011 return max_texture_size;
2012 #else
2013 GLenum proxy = GL_PROXY_TEXTURE_2D;
2015 GLint size;
2016 GLint next = 64;
2017 glTexImage2D(proxy, 0, GL_RGBA, next, next, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
2018 glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &size);
2019 if (size == 0) {
2020 return max_texture_size;
2022 do {
2023 size = next;
2024 next = size * 2;
2026 if (next > max_texture_size)
2027 break;
2028 glTexImage2D(proxy, 0, GL_RGBA, next, next, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
2029 glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &next);
2030 } while (next > size);
2032 max_texture_size = size;
2033 return max_texture_size;
2034 #endif
2038 Generates and binds a 2D GL texture to the current context, based
2039 on \a image. The generated texture id is returned and can be used
2040 in later \c glBindTexture() calls.
2042 The \a target parameter specifies the texture target. The default
2043 target is \c GL_TEXTURE_2D.
2045 The \a format parameter sets the internal format for the
2046 texture. The default format is \c GL_RGBA8.
2048 If the GL implementation supports the \c GL_SGIS_generate_mipmap
2049 extension, mipmaps will be automatically generated for the
2050 texture. Mipmap generation is only supported for the \c
2051 GL_TEXTURE_2D target.
2053 The texture that is generated is cached, so multiple calls to
2054 bindTexture() with the same QImage will return the same texture
2057 Note that we assume default values for the glPixelStore() and
2058 glPixelTransfer() parameters.
2060 \sa deleteTexture()
2062 GLuint QGLContext::bindTexture(const QImage &image, GLenum target, GLint format)
2064 Q_D(QGLContext);
2065 return d->bindTexture(image, target, format, false);
2068 #ifdef Q_MAC_COMPAT_GL_FUNCTIONS
2069 /*! \internal */
2070 GLuint QGLContext::bindTexture(const QImage &image, QMacCompatGLenum target, QMacCompatGLint format)
2072 Q_D(QGLContext);
2073 return d->bindTexture(image, GLenum(target), GLint(format), false);
2075 #endif
2077 /*! \overload
2079 Generates and binds a 2D GL texture based on \a pixmap.
2081 GLuint QGLContext::bindTexture(const QPixmap &pixmap, GLenum target, GLint format)
2083 Q_D(QGLContext);
2084 return d->bindTexture(pixmap, target, format, false);
2087 #ifdef Q_MAC_COMPAT_GL_FUNCTIONS
2088 /*! \internal */
2089 GLuint QGLContext::bindTexture(const QPixmap &pixmap, QMacCompatGLenum target, QMacCompatGLint format)
2091 Q_D(QGLContext);
2092 return d->bindTexture(pixmap, GLenum(target), GLint(format), false);
2094 #endif
2097 Removes the texture identified by \a id from the texture cache,
2098 and calls glDeleteTextures() to delete the texture from the
2099 context.
2101 \sa bindTexture()
2103 void QGLContext::deleteTexture(GLuint id)
2105 if (qt_tex_cache) {
2106 QList<qint64> keys = qt_tex_cache->keys();
2107 for (int i = 0; i < keys.size(); ++i) {
2108 QGLTexture *tex = qt_tex_cache->object(keys.at(i));
2109 if (tex->id == id && tex->context == this) {
2110 tex->clean = true; // forces a glDeleteTextures() call
2111 qt_tex_cache->remove(keys.at(i));
2112 return;
2117 // check the DDS cache if the texture wasn't found in the pixmap/image
2118 // cache
2119 QList<QString> ddsKeys = qgl_dds_cache()->keys();
2120 for (int i = 0; i < ddsKeys.size(); ++i) {
2121 GLuint texture = qgl_dds_cache()->value(ddsKeys.at(i));
2122 if (id == texture) {
2123 glDeleteTextures(1, &texture);
2124 qgl_dds_cache()->remove(ddsKeys.at(i));
2125 return;
2130 #ifdef Q_MAC_COMPAT_GL_FUNCTIONS
2131 /*! \internal */
2132 void QGLContext::deleteTexture(QMacCompatGLuint id)
2134 return deleteTexture(GLuint(id));
2136 #endif
2138 void qt_add_rect_to_array(const QRectF &r, q_vertexType *array)
2140 qreal left = r.left();
2141 qreal right = r.right();
2142 qreal top = r.top();
2143 qreal bottom = r.bottom();
2145 array[0] = f2vt(left);
2146 array[1] = f2vt(top);
2147 array[2] = f2vt(right);
2148 array[3] = f2vt(top);
2149 array[4] = f2vt(right);
2150 array[5] = f2vt(bottom);
2151 array[6] = f2vt(left);
2152 array[7] = f2vt(bottom);
2155 void qt_add_texcoords_to_array(qreal x1, qreal y1, qreal x2, qreal y2, q_vertexType *array)
2157 array[0] = f2vt(x1);
2158 array[1] = f2vt(y1);
2159 array[2] = f2vt(x2);
2160 array[3] = f2vt(y1);
2161 array[4] = f2vt(x2);
2162 array[5] = f2vt(y2);
2163 array[6] = f2vt(x1);
2164 array[7] = f2vt(y2);
2167 static void qDrawTextureRect(const QRectF &target, GLint textureWidth, GLint textureHeight, GLenum textureTarget)
2169 q_vertexType tx = f2vt(1);
2170 q_vertexType ty = f2vt(1);
2172 #ifdef QT_OPENGL_ES
2173 Q_UNUSED(textureWidth);
2174 Q_UNUSED(textureHeight);
2175 Q_UNUSED(textureTarget);
2176 #else
2177 if (textureTarget != GL_TEXTURE_2D) {
2178 if (textureWidth == -1 || textureHeight == -1) {
2179 glGetTexLevelParameteriv(textureTarget, 0, GL_TEXTURE_WIDTH, &textureWidth);
2180 glGetTexLevelParameteriv(textureTarget, 0, GL_TEXTURE_HEIGHT, &textureHeight);
2183 tx = f2vt(textureWidth);
2184 ty = f2vt(textureHeight);
2186 #endif
2188 q_vertexType texCoordArray[4*2] = {
2189 0, ty, tx, ty, tx, 0, 0, 0
2192 q_vertexType vertexArray[4*2];
2193 qt_add_rect_to_array(target, vertexArray);
2195 #if !defined(QT_OPENGL_ES_2)
2196 glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray);
2197 glTexCoordPointer(2, q_vertexTypeEnum, 0, texCoordArray);
2199 glEnableClientState(GL_VERTEX_ARRAY);
2200 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
2201 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
2203 glDisableClientState(GL_VERTEX_ARRAY);
2204 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
2205 #endif
2209 \since 4.4
2211 Draws the given texture, \a textureId, to the given target rectangle,
2212 \a target, in OpenGL model space. The \a textureTarget should be a 2D
2213 texture target.
2215 Equivalent to the corresponding QGLContext::drawTexture().
2217 void QGLContext::drawTexture(const QRectF &target, GLuint textureId, GLenum textureTarget)
2219 #ifdef QT_OPENGL_ES
2220 if (textureTarget != GL_TEXTURE_2D) {
2221 qWarning("QGLContext::drawTexture(): texture target must be GL_TEXTURE_2D on OpenGL ES");
2222 return;
2224 #else
2225 const bool wasEnabled = glIsEnabled(GL_TEXTURE_2D);
2226 GLint oldTexture;
2227 glGetIntegerv(GL_TEXTURE_BINDING_2D, &oldTexture);
2228 #endif
2230 glEnable(textureTarget);
2231 glBindTexture(textureTarget, textureId);
2233 qDrawTextureRect(target, -1, -1, textureTarget);
2235 #ifdef QT_OPENGL_ES
2236 glDisable(textureTarget);
2237 #else
2238 if (!wasEnabled)
2239 glDisable(textureTarget);
2240 glBindTexture(textureTarget, oldTexture);
2241 #endif
2244 #ifdef Q_MAC_COMPAT_GL_FUNCTIONS
2245 /*! \internal */
2246 void QGLContext::drawTexture(const QRectF &target, QMacCompatGLuint textureId, QMacCompatGLenum textureTarget)
2248 drawTexture(target, GLuint(textureId), GLenum(textureTarget));
2250 #endif
2253 \since 4.4
2255 Draws the given texture at the given \a point in OpenGL model
2256 space. The \a textureTarget should be a 2D texture target.
2258 Equivalent to the corresponding QGLContext::drawTexture().
2260 void QGLContext::drawTexture(const QPointF &point, GLuint textureId, GLenum textureTarget)
2262 // this would be ok on OpenGL ES 2.0, but currently we don't have a define for that
2263 #ifdef QT_OPENGL_ES
2264 Q_UNUSED(point);
2265 Q_UNUSED(textureId);
2266 Q_UNUSED(textureTarget);
2267 qWarning("drawTexture(const QPointF &point, GLuint textureId, GLenum textureTarget) not supported with OpenGL ES, use rect version instead");
2268 #else
2269 const bool wasEnabled = glIsEnabled(GL_TEXTURE_2D);
2270 GLint oldTexture;
2271 glGetIntegerv(GL_TEXTURE_BINDING_2D, &oldTexture);
2273 glEnable(textureTarget);
2274 glBindTexture(textureTarget, textureId);
2276 GLint textureWidth;
2277 GLint textureHeight;
2279 glGetTexLevelParameteriv(textureTarget, 0, GL_TEXTURE_WIDTH, &textureWidth);
2280 glGetTexLevelParameteriv(textureTarget, 0, GL_TEXTURE_HEIGHT, &textureHeight);
2282 qDrawTextureRect(QRectF(point, QSizeF(textureWidth, textureHeight)), textureWidth, textureHeight, textureTarget);
2284 if (!wasEnabled)
2285 glDisable(textureTarget);
2286 glBindTexture(textureTarget, oldTexture);
2287 #endif
2290 #ifdef Q_MAC_COMPAT_GL_FUNCTIONS
2291 /*! \internal */
2292 void QGLContext::drawTexture(const QPointF &point, QMacCompatGLuint textureId, QMacCompatGLenum textureTarget)
2294 drawTexture(point, GLuint(textureId), GLenum(textureTarget));
2296 #endif
2300 This function sets the limit for the texture cache to \a size,
2301 expressed in kilobytes.
2303 By default, the cache limit is approximately 64 MB.
2305 \sa textureCacheLimit()
2307 void QGLContext::setTextureCacheLimit(int size)
2309 qt_tex_cache_limit = size;
2310 if (qt_tex_cache)
2311 qt_tex_cache->setMaxCost(qt_tex_cache_limit);
2315 Returns the current texture cache limit in kilobytes.
2317 \sa setTextureCacheLimit()
2319 int QGLContext::textureCacheLimit()
2321 return qt_tex_cache_limit;
2326 \fn QGLFormat QGLContext::format() const
2328 Returns the frame buffer format that was obtained (this may be a
2329 subset of what was requested).
2331 \sa requestedFormat()
2335 \fn QGLFormat QGLContext::requestedFormat() const
2337 Returns the frame buffer format that was originally requested in
2338 the constructor or setFormat().
2340 \sa format()
2344 Sets a \a format for this context. The context is \link reset()
2345 reset\endlink.
2347 Call create() to create a new GL context that tries to match the
2348 new format.
2350 \snippet doc/src/snippets/code/src_opengl_qgl.cpp 7
2352 \sa format(), reset(), create()
2355 void QGLContext::setFormat(const QGLFormat &format)
2357 Q_D(QGLContext);
2358 reset();
2359 d->glFormat = d->reqFormat = format;
2363 \internal
2365 void QGLContext::setDevice(QPaintDevice *pDev)
2367 Q_D(QGLContext);
2368 if (isValid())
2369 reset();
2370 d->paintDevice = pDev;
2371 if (d->paintDevice && (d->paintDevice->devType() != QInternal::Widget
2372 && d->paintDevice->devType() != QInternal::Pixmap
2373 && d->paintDevice->devType() != QInternal::Pbuffer)) {
2374 qWarning("QGLContext: Unsupported paint device type");
2379 \fn bool QGLContext::isValid() const
2381 Returns true if a GL rendering context has been successfully
2382 created; otherwise returns false.
2386 \fn void QGLContext::setValid(bool valid)
2387 \internal
2389 Forces the GL rendering context to be valid.
2393 \fn bool QGLContext::isSharing() const
2395 Returns true if this context is sharing its GL context with
2396 another QGLContext, otherwise false is returned. Note that context
2397 sharing might not be supported between contexts with different
2398 formats.
2402 \fn bool QGLContext::deviceIsPixmap() const
2404 Returns true if the paint device of this context is a pixmap;
2405 otherwise returns false.
2409 \fn bool QGLContext::windowCreated() const
2411 Returns true if a window has been created for this context;
2412 otherwise returns false.
2414 \sa setWindowCreated()
2418 \fn void QGLContext::setWindowCreated(bool on)
2420 If \a on is true the context has had a window created for it. If
2421 \a on is false no window has been created for the context.
2423 \sa windowCreated()
2427 \fn uint QGLContext::colorIndex(const QColor& c) const
2429 \internal
2431 Returns a colormap index for the color c, in ColorIndex mode. Used
2432 by qglColor() and qglClearColor().
2437 \fn bool QGLContext::initialized() const
2439 Returns true if this context has been initialized, i.e. if
2440 QGLWidget::initializeGL() has been performed on it; otherwise
2441 returns false.
2443 \sa setInitialized()
2447 \fn void QGLContext::setInitialized(bool on)
2449 If \a on is true the context has been initialized, i.e.
2450 QGLContext::setInitialized() has been called on it. If \a on is
2451 false the context has not been initialized.
2453 \sa initialized()
2457 \fn const QGLContext* QGLContext::currentContext()
2459 Returns the current context, i.e. the context to which any OpenGL
2460 commands will currently be directed. Returns 0 if no context is
2461 current.
2463 \sa makeCurrent()
2467 \fn QColor QGLContext::overlayTransparentColor() const
2469 If this context is a valid context in an overlay plane, returns
2470 the plane's transparent color. Otherwise returns an \link
2471 QColor::isValid() invalid \endlink color.
2473 The returned color's \link QColor::pixel() pixel \endlink value is
2474 the index of the transparent color in the colormap of the overlay
2475 plane. (Naturally, the color's RGB values are meaningless.)
2477 The returned QColor object will generally work as expected only
2478 when passed as the argument to QGLWidget::qglColor() or
2479 QGLWidget::qglClearColor(). Under certain circumstances it can
2480 also be used to draw transparent graphics with a QPainter. See the
2481 examples/opengl/overlay_x11 example for details.
2486 Creates the GL context. Returns true if it was successful in
2487 creating a valid GL rendering context on the paint device
2488 specified in the constructor; otherwise returns false (i.e. the
2489 context is invalid).
2491 After successful creation, format() returns the set of features of
2492 the created GL rendering context.
2494 If \a shareContext points to a valid QGLContext, this method will
2495 try to establish OpenGL display list and texture object sharing
2496 between this context and the \a shareContext. Note that this may
2497 fail if the two contexts have different \l {format()} {formats}.
2498 Use isSharing() to see if sharing is in effect.
2500 \warning Implementation note: initialization of C++ class
2501 members usually takes place in the class constructor. QGLContext
2502 is an exception because it must be simple to customize. The
2503 virtual functions chooseContext() (and chooseVisual() for X11) can
2504 be reimplemented in a subclass to select a particular context. The
2505 problem is that virtual functions are not properly called during
2506 construction (even though this is correct C++) because C++
2507 constructs class hierarchies from the bottom up. For this reason
2508 we need a create() function.
2510 \sa chooseContext(), format(), isValid()
2513 bool QGLContext::create(const QGLContext* shareContext)
2515 Q_D(QGLContext);
2516 if (!d->paintDevice)
2517 return false;
2518 reset();
2519 d->valid = chooseContext(shareContext);
2520 if (d->valid && d->paintDevice->devType() == QInternal::Widget) {
2521 QWidgetPrivate *wd = qt_widget_private(static_cast<QWidget *>(d->paintDevice));
2522 wd->usesDoubleBufferedGLContext = d->glFormat.doubleBuffer();
2524 if (d->sharing) // ok, we managed to share
2525 qgl_share_reg()->addShare(this, shareContext);
2526 return d->valid;
2529 bool QGLContext::isValid() const
2531 Q_D(const QGLContext);
2532 return d->valid;
2535 void QGLContext::setValid(bool valid)
2537 Q_D(QGLContext);
2538 d->valid = valid;
2541 bool QGLContext::isSharing() const
2543 Q_D(const QGLContext);
2544 return d->sharing;
2547 QGLFormat QGLContext::format() const
2549 Q_D(const QGLContext);
2550 return d->glFormat;
2553 QGLFormat QGLContext::requestedFormat() const
2555 Q_D(const QGLContext);
2556 return d->reqFormat;
2559 QPaintDevice* QGLContext::device() const
2561 Q_D(const QGLContext);
2562 return d->paintDevice;
2565 bool QGLContext::deviceIsPixmap() const
2567 Q_D(const QGLContext);
2568 return d->paintDevice->devType() == QInternal::Pixmap;
2572 bool QGLContext::windowCreated() const
2574 Q_D(const QGLContext);
2575 return d->crWin;
2579 void QGLContext::setWindowCreated(bool on)
2581 Q_D(QGLContext);
2582 d->crWin = on;
2585 bool QGLContext::initialized() const
2587 Q_D(const QGLContext);
2588 return d->initDone;
2591 void QGLContext::setInitialized(bool on)
2593 Q_D(QGLContext);
2594 d->initDone = on;
2597 const QGLContext* QGLContext::currentContext()
2599 if (qgl_context_storage.hasLocalData())
2600 return qgl_context_storage.localData()->context;
2601 return 0;
2605 \fn bool QGLContext::chooseContext(const QGLContext* shareContext = 0)
2607 This semi-internal function is called by create(). It creates a
2608 system-dependent OpenGL handle that matches the format() of \a
2609 shareContext as closely as possible, returning true if successful
2610 or false if a suitable handle could not be found.
2612 On Windows, it calls the virtual function choosePixelFormat(),
2613 which finds a matching pixel format identifier. On X11, it calls
2614 the virtual function chooseVisual() which finds an appropriate X
2615 visual. On other platforms it may work differently.
2618 /*! \fn int QGLContext::choosePixelFormat(void* dummyPfd, HDC pdc)
2620 \bold{Win32 only:} This virtual function chooses a pixel format
2621 that matches the OpenGL \link setFormat() format\endlink.
2622 Reimplement this function in a subclass if you need a custom
2623 context.
2625 \warning The \a dummyPfd pointer and \a pdc are used as a \c
2626 PIXELFORMATDESCRIPTOR*. We use \c void to avoid using
2627 Windows-specific types in our header files.
2629 \sa chooseContext()
2632 /*! \fn void *QGLContext::chooseVisual()
2634 \bold{X11 only:} This virtual function tries to find a visual that
2635 matches the format, reducing the demands if the original request
2636 cannot be met.
2638 The algorithm for reducing the demands of the format is quite
2639 simple-minded, so override this method in your subclass if your
2640 application has spcific requirements on visual selection.
2642 \sa chooseContext()
2645 /*! \fn void *QGLContext::tryVisual(const QGLFormat& f, int bufDepth)
2646 \internal
2648 \bold{X11 only:} This virtual function chooses a visual that matches
2649 the OpenGL \link format() format\endlink. Reimplement this function
2650 in a subclass if you need a custom visual.
2652 \sa chooseContext()
2656 \fn void QGLContext::reset()
2658 Resets the context and makes it invalid.
2660 \sa create(), isValid()
2665 \fn void QGLContext::makeCurrent()
2667 Makes this context the current OpenGL rendering context. All GL
2668 functions you call operate on this context until another context
2669 is made current.
2671 In some very rare cases the underlying call may fail. If this
2672 occurs an error message is output to stderr.
2677 \fn void QGLContext::swapBuffers() const
2679 Swaps the screen contents with an off-screen buffer. Only works if
2680 the context is in double buffer mode.
2682 \sa QGLFormat::setDoubleBuffer()
2687 \fn void QGLContext::doneCurrent()
2689 Makes no GL context the current context. Normally, you do not need
2690 to call this function; QGLContext calls it as necessary.
2695 \fn QPaintDevice* QGLContext::device() const
2697 Returns the paint device set for this context.
2699 \sa QGLContext::QGLContext()
2703 \obsolete
2704 \fn void QGLContext::generateFontDisplayLists(const QFont& font, int listBase)
2706 Generates a set of 256 display lists for the 256 first characters
2707 in the font \a font. The first list will start at index \a listBase.
2709 \sa QGLWidget::renderText()
2713 /*****************************************************************************
2714 QGLWidget implementation
2715 *****************************************************************************/
2719 \class QGLWidget
2720 \brief The QGLWidget class is a widget for rendering OpenGL graphics.
2722 \ingroup multimedia
2723 \mainclass
2725 QGLWidget provides functionality for displaying OpenGL graphics
2726 integrated into a Qt application. It is very simple to use. You
2727 inherit from it and use the subclass like any other QWidget,
2728 except that you have the choice between using QPainter and
2729 standard OpenGL rendering commands.
2731 QGLWidget provides three convenient virtual functions that you can
2732 reimplement in your subclass to perform the typical OpenGL tasks:
2734 \list
2735 \i paintGL() - Renders the OpenGL scene. Gets called whenever the widget
2736 needs to be updated.
2737 \i resizeGL() - Sets up the OpenGL viewport, projection, etc. Gets
2738 called whenever the widget has been resized (and also when it
2739 is shown for the first time because all newly created widgets get a
2740 resize event automatically).
2741 \i initializeGL() - Sets up the OpenGL rendering context, defines display
2742 lists, etc. Gets called once before the first time resizeGL() or
2743 paintGL() is called.
2744 \endlist
2746 Here is a rough outline of how a QGLWidget subclass might look:
2748 \snippet doc/src/snippets/code/src_opengl_qgl.cpp 8
2750 If you need to trigger a repaint from places other than paintGL()
2751 (a typical example is when using \link QTimer timers\endlink to
2752 animate scenes), you should call the widget's updateGL() function.
2754 Your widget's OpenGL rendering context is made current when
2755 paintGL(), resizeGL(), or initializeGL() is called. If you need to
2756 call the standard OpenGL API functions from other places (e.g. in
2757 your widget's constructor or in your own paint functions), you
2758 must call makeCurrent() first.
2760 QGLWidget provides functions for requesting a new display \link
2761 QGLFormat format\endlink and you can also create widgets with
2762 customized rendering \link QGLContext contexts\endlink.
2764 You can also share OpenGL display lists between QGLWidgets (see
2765 the documentation of the QGLWidget constructors for details).
2767 Note that under Windows, the QGLContext belonging to a QGLWidget
2768 has to be recreated when the QGLWidget is reparented. This is
2769 necessary due to limitations on the Windows platform. This will
2770 most likely cause problems for users that have subclassed and
2771 installed their own QGLContext on a QGLWidget. It is possible to
2772 work around this issue by putting the QGLWidget inside a dummy
2773 widget and then reparenting the dummy widget, instead of the
2774 QGLWidget. This will side-step the issue altogether, and is what
2775 we recommend for users that need this kind of functionality.
2777 On Mac OS X, when Qt is built with Cocoa support, a QGLWidget
2778 can't have any sibling widgets placed ontop of itself. This is due
2779 to limitations in the Cocoa API and is not supported by Apple.
2781 \section1 Overlays
2783 The QGLWidget creates a GL overlay context in addition to the
2784 normal context if overlays are supported by the underlying system.
2786 If you want to use overlays, you specify it in the \link QGLFormat
2787 format\endlink. (Note: Overlay must be requested in the format
2788 passed to the QGLWidget constructor.) Your GL widget should also
2789 implement some or all of these virtual methods:
2791 \list
2792 \i paintOverlayGL()
2793 \i resizeOverlayGL()
2794 \i initializeOverlayGL()
2795 \endlist
2797 These methods work in the same way as the normal paintGL() etc.
2798 functions, except that they will be called when the overlay
2799 context is made current. You can explicitly make the overlay
2800 context current by using makeOverlayCurrent(), and you can access
2801 the overlay context directly (e.g. to ask for its transparent
2802 color) by calling overlayContext().
2804 On X servers in which the default visual is in an overlay plane,
2805 non-GL Qt windows can also be used for overlays.
2807 \section1 Painting Techniques
2809 As described above, subclass QGLWidget to render pure 3D content in the
2810 following way:
2812 \list
2813 \o Reimplement the QGLWidget::initializeGL() and QGLWidget::resizeGL() to
2814 set up the OpenGL state and provide a perspective transformation.
2815 \o Reimplement QGLWidget::paintGL() to paint the 3D scene, calling only
2816 OpenGL functions to draw on the widget.
2817 \endlist
2819 It is also possible to draw 2D graphics onto a QGLWidget subclass, it is necessary
2820 to reimplement QGLWidget::paintEvent() and do the following:
2822 \list
2823 \o Construct a QPainter object.
2824 \o Initialize it for use on the widget with the QPainter::begin() function.
2825 \o Draw primitives using QPainter's member functions.
2826 \o Call QPainter::end() to finish painting.
2827 \endlist
2829 Overpainting 2D content on top of 3D content takes a little more effort.
2830 One approach to doing this is shown in the
2831 \l{Overpainting Example}{Overpainting} example.
2833 \e{OpenGL is a trademark of Silicon Graphics, Inc. in the United States and other
2834 countries.}
2836 \sa QGLPixelBuffer, {Hello GL Example}, {2D Painting Example}, {Overpainting Example},
2837 {Grabber Example}
2841 Constructs an OpenGL widget with a \a parent widget.
2843 The \link QGLFormat::defaultFormat() default format\endlink is
2844 used. The widget will be \link isValid() invalid\endlink if the
2845 system has no \link QGLFormat::hasOpenGL() OpenGL support\endlink.
2847 The \a parent and widget flag, \a f, arguments are passed
2848 to the QWidget constructor.
2850 If \a shareWidget is a valid QGLWidget, this widget will share
2851 OpenGL display lists and texture objects with \a shareWidget. But
2852 if \a shareWidget and this widget have different \l {format()}
2853 {formats}, sharing might not be possible. You can check whether
2854 sharing is in effect by calling isSharing().
2856 The initialization of OpenGL rendering state, etc. should be done
2857 by overriding the initializeGL() function, rather than in the
2858 constructor of your QGLWidget subclass.
2860 \sa QGLFormat::defaultFormat(), {Textures Example}
2863 QGLWidget::QGLWidget(QWidget *parent, const QGLWidget* shareWidget, Qt::WindowFlags f)
2864 : QWidget(*(new QGLWidgetPrivate), parent, f | Qt::MSWindowsOwnDC)
2866 Q_D(QGLWidget);
2867 setAttribute(Qt::WA_PaintOnScreen);
2868 setAttribute(Qt::WA_NoSystemBackground);
2869 setAutoFillBackground(true); // for compatibility
2870 d->init(new QGLContext(QGLFormat::defaultFormat(), this), shareWidget);
2875 Constructs an OpenGL widget with parent \a parent.
2877 The \a format argument specifies the desired \link QGLFormat
2878 rendering options \endlink. If the underlying OpenGL/Window system
2879 cannot satisfy all the features requested in \a format, the
2880 nearest subset of features will be used. After creation, the
2881 format() method will return the actual format obtained.
2883 The widget will be \link isValid() invalid\endlink if the system
2884 has no \link QGLFormat::hasOpenGL() OpenGL support\endlink.
2886 The \a parent and widget flag, \a f, arguments are passed
2887 to the QWidget constructor.
2889 If \a shareWidget is a valid QGLWidget, this widget will share
2890 OpenGL display lists and texture objects with \a shareWidget. But
2891 if \a shareWidget and this widget have different \l {format()}
2892 {formats}, sharing might not be possible. You can check whether
2893 sharing is in effect by calling isSharing().
2895 The initialization of OpenGL rendering state, etc. should be done
2896 by overriding the initializeGL() function, rather than in the
2897 constructor of your QGLWidget subclass.
2899 \sa QGLFormat::defaultFormat(), isValid()
2902 QGLWidget::QGLWidget(const QGLFormat &format, QWidget *parent, const QGLWidget* shareWidget,
2903 Qt::WindowFlags f)
2904 : QWidget(*(new QGLWidgetPrivate), parent, f | Qt::MSWindowsOwnDC)
2906 Q_D(QGLWidget);
2907 setAttribute(Qt::WA_PaintOnScreen);
2908 setAttribute(Qt::WA_NoSystemBackground);
2909 setAutoFillBackground(true); // for compatibility
2910 d->init(new QGLContext(format, this), shareWidget);
2914 Constructs an OpenGL widget with parent \a parent.
2916 The \a context argument is a pointer to the QGLContext that
2917 you wish to be bound to this widget. This allows you to pass in
2918 your own QGLContext sub-classes.
2920 The widget will be \link isValid() invalid\endlink if the system
2921 has no \link QGLFormat::hasOpenGL() OpenGL support\endlink.
2923 The \a parent and widget flag, \a f, arguments are passed
2924 to the QWidget constructor.
2926 If \a shareWidget is a valid QGLWidget, this widget will share
2927 OpenGL display lists and texture objects with \a shareWidget. But
2928 if \a shareWidget and this widget have different \l {format()}
2929 {formats}, sharing might not be possible. You can check whether
2930 sharing is in effect by calling isSharing().
2932 The initialization of OpenGL rendering state, etc. should be done
2933 by overriding the initializeGL() function, rather than in the
2934 constructor of your QGLWidget subclass.
2936 \sa QGLFormat::defaultFormat(), isValid()
2938 QGLWidget::QGLWidget(QGLContext *context, QWidget *parent, const QGLWidget *shareWidget,
2939 Qt::WindowFlags f)
2940 : QWidget(*(new QGLWidgetPrivate), parent, f | Qt::MSWindowsOwnDC)
2942 Q_D(QGLWidget);
2943 setAttribute(Qt::WA_PaintOnScreen);
2944 setAttribute(Qt::WA_NoSystemBackground);
2945 setAutoFillBackground(true); // for compatibility
2946 d->init(context, shareWidget);
2950 Destroys the widget.
2953 QGLWidget::~QGLWidget()
2955 Q_D(QGLWidget);
2956 #if defined(GLX_MESA_release_buffers) && defined(QGL_USE_MESA_EXT)
2957 bool doRelease = (glcx && glcx->windowCreated());
2958 #endif
2959 delete d->glcx;
2960 #if defined(Q_WGL)
2961 delete d->olcx;
2962 #endif
2963 #if defined(GLX_MESA_release_buffers) && defined(QGL_USE_MESA_EXT)
2964 if (doRelease)
2965 glXReleaseBuffersMESA(x11Display(), winId());
2966 #endif
2967 d->cleanupColormaps();
2969 #ifdef Q_WS_MAC
2970 QWidget *current = parentWidget();
2971 while (current) {
2972 qt_widget_private(current)->glWidgets.removeAll(QWidgetPrivate::GlWidgetInfo(this));
2973 if (current->isWindow())
2974 break;
2975 current = current->parentWidget();
2977 #endif
2981 \fn QGLFormat QGLWidget::format() const
2983 Returns the format of the contained GL rendering context.
2987 \fn bool QGLWidget::doubleBuffer() const
2989 Returns true if the contained GL rendering context has double
2990 buffering; otherwise returns false.
2992 \sa QGLFormat::doubleBuffer()
2996 \fn void QGLWidget::setAutoBufferSwap(bool on)
2998 If \a on is true automatic GL buffer swapping is switched on;
2999 otherwise it is switched off.
3001 If \a on is true and the widget is using a double-buffered format,
3002 the background and foreground GL buffers will automatically be
3003 swapped after each paintGL() call.
3005 The buffer auto-swapping is on by default.
3007 \sa autoBufferSwap(), doubleBuffer(), swapBuffers()
3011 \fn bool QGLWidget::autoBufferSwap() const
3013 Returns true if the widget is doing automatic GL buffer swapping;
3014 otherwise returns false.
3016 \sa setAutoBufferSwap()
3020 \fn void *QGLContext::getProcAddress(const QString &proc) const
3022 Returns a function pointer to the GL extension function passed in
3023 \a proc. 0 is returned if a pointer to the function could not be
3024 obtained.
3028 \fn bool QGLWidget::isValid() const
3030 Returns true if the widget has a valid GL rendering context;
3031 otherwise returns false. A widget will be invalid if the system
3032 has no \link QGLFormat::hasOpenGL() OpenGL support\endlink.
3035 bool QGLWidget::isValid() const
3037 Q_D(const QGLWidget);
3038 return d->glcx && d->glcx->isValid();
3042 \fn bool QGLWidget::isSharing() const
3044 Returns true if this widget's GL context is shared with another GL
3045 context, otherwise false is returned. Context sharing might not be
3046 possible if the QGLWidgets use different formats.
3048 \sa format()
3051 bool QGLWidget::isSharing() const
3053 Q_D(const QGLWidget);
3054 return d->glcx->isSharing();
3058 \fn void QGLWidget::makeCurrent()
3060 Makes this widget the current widget for OpenGL operations, i.e.
3061 makes the widget's rendering context the current OpenGL rendering
3062 context.
3065 void QGLWidget::makeCurrent()
3067 Q_D(QGLWidget);
3068 d->glcx->makeCurrent();
3072 \fn void QGLWidget::doneCurrent()
3074 Makes no GL context the current context. Normally, you do not need
3075 to call this function; QGLContext calls it as necessary. However,
3076 it may be useful in multithreaded environments.
3079 void QGLWidget::doneCurrent()
3081 Q_D(QGLWidget);
3082 d->glcx->doneCurrent();
3086 \fn void QGLWidget::swapBuffers()
3088 Swaps the screen contents with an off-screen buffer. This only
3089 works if the widget's format specifies double buffer mode.
3091 Normally, there is no need to explicitly call this function
3092 because it is done automatically after each widget repaint, i.e.
3093 each time after paintGL() has been executed.
3095 \sa doubleBuffer(), setAutoBufferSwap(), QGLFormat::setDoubleBuffer()
3098 void QGLWidget::swapBuffers()
3100 Q_D(QGLWidget);
3101 d->glcx->swapBuffers();
3106 \fn const QGLContext* QGLWidget::overlayContext() const
3108 Returns the overlay context of this widget, or 0 if this widget
3109 has no overlay.
3111 \sa context()
3117 \fn void QGLWidget::makeOverlayCurrent()
3119 Makes the overlay context of this widget current. Use this if you
3120 need to issue OpenGL commands to the overlay context outside of
3121 initializeOverlayGL(), resizeOverlayGL(), and paintOverlayGL().
3123 Does nothing if this widget has no overlay.
3125 \sa makeCurrent()
3130 \obsolete
3132 Sets a new format for this widget.
3134 If the underlying OpenGL/Window system cannot satisfy all the
3135 features requested in \a format, the nearest subset of features will
3136 be used. After creation, the format() method will return the actual
3137 rendering context format obtained.
3139 The widget will be assigned a new QGLContext, and the initializeGL()
3140 function will be executed for this new context before the first
3141 resizeGL() or paintGL().
3143 This method will try to keep display list and texture object sharing
3144 in effect with other QGLWidgets, but changing the format might make
3145 sharing impossible. Use isSharing() to see if sharing is still in
3146 effect.
3148 \sa format(), isSharing(), isValid()
3151 void QGLWidget::setFormat(const QGLFormat &format)
3153 setContext(new QGLContext(format,this));
3160 \fn const QGLContext *QGLWidget::context() const
3162 Returns the context of this widget.
3164 It is possible that the context is not valid (see isValid()), for
3165 example, if the underlying hardware does not support the format
3166 attributes that were requested.
3170 \fn void QGLWidget::setContext(QGLContext *context,
3171 const QGLContext* shareContext,
3172 bool deleteOldContext)
3173 \obsolete
3175 Sets a new context for this widget. The QGLContext \a context must
3176 be created using \e new. QGLWidget will delete \a context when
3177 another context is set or when the widget is destroyed.
3179 If \a context is invalid, QGLContext::create() is performed on
3180 it. The initializeGL() function will then be executed for the new
3181 context before the first resizeGL() or paintGL().
3183 If \a context is invalid, this method will try to keep display list
3184 and texture object sharing in effect, or (if \a shareContext points
3185 to a valid context) start display list and texture object sharing
3186 with that context, but sharing might be impossible if the two
3187 contexts have different \l {format()} {formats}. Use isSharing() to
3188 see whether sharing is in effect.
3190 If \a deleteOldContext is true (the default), the existing context
3191 will be deleted. You may use false here if you have kept a pointer
3192 to the old context (as returned by context()), and want to restore
3193 that context later.
3195 \sa context(), isSharing()
3201 \fn void QGLWidget::updateGL()
3203 Updates the widget by calling glDraw().
3206 void QGLWidget::updateGL()
3208 if (updatesEnabled())
3209 glDraw();
3214 \fn void QGLWidget::updateOverlayGL()
3216 Updates the widget's overlay (if any). Will cause the virtual
3217 function paintOverlayGL() to be executed.
3219 The widget's rendering context will become the current context and
3220 initializeGL() will be called if it hasn't already been called.
3225 This virtual function is called once before the first call to
3226 paintGL() or resizeGL(), and then once whenever the widget has
3227 been assigned a new QGLContext. Reimplement it in a subclass.
3229 This function should set up any required OpenGL context rendering
3230 flags, defining display lists, etc.
3232 There is no need to call makeCurrent() because this has already
3233 been done when this function is called.
3236 void QGLWidget::initializeGL()
3242 This virtual function is called whenever the widget needs to be
3243 painted. Reimplement it in a subclass.
3245 There is no need to call makeCurrent() because this has already
3246 been done when this function is called.
3249 void QGLWidget::paintGL()
3255 \fn void QGLWidget::resizeGL(int width , int height)
3257 This virtual function is called whenever the widget has been
3258 resized. The new size is passed in \a width and \a height.
3259 Reimplement it in a subclass.
3261 There is no need to call makeCurrent() because this has already
3262 been done when this function is called.
3265 void QGLWidget::resizeGL(int, int)
3272 This virtual function is used in the same manner as initializeGL()
3273 except that it operates on the widget's overlay context instead of
3274 the widget's main context. This means that initializeOverlayGL()
3275 is called once before the first call to paintOverlayGL() or
3276 resizeOverlayGL(). Reimplement it in a subclass.
3278 This function should set up any required OpenGL context rendering
3279 flags, defining display lists, etc. for the overlay context.
3281 There is no need to call makeOverlayCurrent() because this has
3282 already been done when this function is called.
3285 void QGLWidget::initializeOverlayGL()
3291 This virtual function is used in the same manner as paintGL()
3292 except that it operates on the widget's overlay context instead of
3293 the widget's main context. This means that paintOverlayGL() is
3294 called whenever the widget's overlay needs to be painted.
3295 Reimplement it in a subclass.
3297 There is no need to call makeOverlayCurrent() because this has
3298 already been done when this function is called.
3301 void QGLWidget::paintOverlayGL()
3307 \fn void QGLWidget::resizeOverlayGL(int width , int height)
3309 This virtual function is used in the same manner as paintGL()
3310 except that it operates on the widget's overlay context instead of
3311 the widget's main context. This means that resizeOverlayGL() is
3312 called whenever the widget has been resized. The new size is
3313 passed in \a width and \a height. Reimplement it in a subclass.
3315 There is no need to call makeOverlayCurrent() because this has
3316 already been done when this function is called.
3319 void QGLWidget::resizeOverlayGL(int, int)
3323 /*! \fn bool QGLWidget::event(QEvent *e)
3324 \reimp
3326 #if !defined(Q_OS_WINCE) && !defined(Q_WS_QWS)
3327 bool QGLWidget::event(QEvent *e)
3329 Q_D(QGLWidget);
3331 if (e->type() == QEvent::Paint) {
3332 QPoint offset;
3333 QPaintDevice *redirectedDevice = d->redirected(&offset);
3334 if (redirectedDevice && redirectedDevice->devType() == QInternal::Pixmap) {
3335 d->restoreRedirected();
3336 QPixmap pixmap = renderPixmap();
3337 d->setRedirected(redirectedDevice, offset);
3338 QPainter p(redirectedDevice);
3339 p.drawPixmap(-offset, pixmap);
3340 return true;
3344 #if defined(Q_WS_X11)
3345 // prevents X errors on some systems, where we get a flush to a
3346 // hidden widget
3347 if (e->type() == QEvent::Hide) {
3348 makeCurrent();
3349 glFinish();
3350 doneCurrent();
3351 } else if (e->type() == QEvent::ParentChange) {
3352 if (d->glcx->d_func()->screen != d->xinfo.screen() || testAttribute(Qt::WA_TranslucentBackground)) {
3353 setContext(new QGLContext(d->glcx->requestedFormat(), this));
3354 // ### recreating the overlay isn't supported atm
3356 #if defined(QT_OPENGL_ES)
3357 // The window may have been re-created during re-parent - if so, the EGL
3358 // surface will need to be re-created.
3359 d->recreateEglSurface(false);
3360 #endif
3362 #elif defined(Q_WS_WIN)
3363 if (e->type() == QEvent::ParentChange) {
3364 QGLContext *newContext = new QGLContext(d->glcx->requestedFormat(), this);
3365 qgl_share_reg()->replaceShare(d->glcx, newContext);
3366 setContext(newContext);
3367 // the overlay needs to be recreated as well
3368 delete d->olcx;
3369 if (isValid() && context()->format().hasOverlay()) {
3370 d->olcx = new QGLContext(QGLFormat::defaultOverlayFormat(), this);
3371 if (!d->olcx->create(isSharing() ? d->glcx : 0)) {
3372 delete d->olcx;
3373 d->olcx = 0;
3374 d->glcx->d_func()->glFormat.setOverlay(false);
3376 } else {
3377 d->olcx = 0;
3379 } else if (e->type() == QEvent::Show) {
3380 if (!format().rgba())
3381 d->updateColormap();
3383 #elif defined(Q_WS_MAC)
3384 if (e->type() == QEvent::MacGLWindowChange
3385 #if 0 //(MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5)
3386 && ((QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5 && isWindow())
3387 || QSysInfo::MacintoshVersion <= QSysInfo::MV_10_4)
3388 #endif
3390 if (d->needWindowChange) {
3391 d->needWindowChange = false;
3392 d->glcx->updatePaintDevice();
3393 update();
3395 return true;
3396 # if defined(QT_MAC_USE_COCOA)
3397 } else if (e->type() == QEvent::MacGLClearDrawable) {
3398 d->glcx->d_ptr->clearDrawable();
3399 # endif
3401 #endif
3403 return QWidget::event(e);
3405 #endif
3408 \fn void QGLWidget::paintEvent(QPaintEvent *event)
3410 Handles paint events passed in the \a event parameter. Will cause
3411 the virtual paintGL() function to be called.
3413 The widget's rendering context will become the current context and
3414 initializeGL() will be called if it hasn't already been called.
3417 void QGLWidget::paintEvent(QPaintEvent *)
3419 if (updatesEnabled()) {
3420 glDraw();
3421 updateOverlayGL();
3427 \fn void QGLWidget::resizeEvent(QResizeEvent *event)
3429 Handles resize events that are passed in the \a event parameter.
3430 Calls the virtual function resizeGL().
3435 \fn void QGLWidget::setMouseTracking(bool enable)
3437 If \a enable is true then mouse tracking is enabled; otherwise it
3438 is disabled.
3443 Renders the current scene on a pixmap and returns the pixmap.
3445 You can use this method on both visible and invisible QGLWidgets.
3447 This method will create a pixmap and a temporary QGLContext to
3448 render on the pixmap. It will then call initializeGL(),
3449 resizeGL(), and paintGL() on this context. Finally, the widget's
3450 original GL context is restored.
3452 The size of the pixmap will be \a w pixels wide and \a h pixels
3453 high unless one of these parameters is 0 (the default), in which
3454 case the pixmap will have the same size as the widget.
3456 If \a useContext is true, this method will try to be more
3457 efficient by using the existing GL context to render the pixmap.
3458 The default is false. Only use true if you understand the risks.
3459 Note that under Windows a temporary context has to be created
3460 and usage of the \e useContext parameter is not supported.
3462 Overlays are not rendered onto the pixmap.
3464 If the GL rendering context and the desktop have different bit
3465 depths, the result will most likely look surprising.
3467 Note that the creation of display lists, modifications of the view
3468 frustum etc. should be done from within initializeGL(). If this is
3469 not done, the temporary QGLContext will not be initialized
3470 properly, and the rendered pixmap may be incomplete/corrupted.
3473 QPixmap QGLWidget::renderPixmap(int w, int h, bool useContext)
3475 Q_D(QGLWidget);
3476 QSize sz = size();
3477 if ((w > 0) && (h > 0))
3478 sz = QSize(w, h);
3480 #if defined(Q_WS_X11)
3481 extern int qt_x11_preferred_pixmap_depth;
3482 int old_depth = qt_x11_preferred_pixmap_depth;
3483 qt_x11_preferred_pixmap_depth = x11Info().depth();
3485 QPixmapData *data = new QX11PixmapData(QPixmapData::PixmapType);
3486 data->resize(sz.width(), sz.height());
3487 QPixmap pm(data);
3488 qt_x11_preferred_pixmap_depth = old_depth;
3489 QX11Info xinfo = x11Info();
3491 // make sure we use a pixmap with the same depth/visual as the widget
3492 if (xinfo.visual() != QX11Info::appVisual()) {
3493 QX11InfoData* xd = pm.x11Info().getX11Data(true);
3494 xd->depth = xinfo.depth();
3495 xd->visual = static_cast<Visual *>(xinfo.visual());
3496 const_cast<QX11Info &>(pm.x11Info()).setX11Data(xd);
3499 #else
3500 QPixmap pm(sz);
3501 #endif
3503 d->glcx->doneCurrent();
3505 bool success = true;
3507 if (useContext && isValid() && d->renderCxPm(&pm))
3508 return pm;
3510 QGLFormat fmt = d->glcx->requestedFormat();
3511 fmt.setDirectRendering(false); // Direct is unlikely to work
3512 fmt.setDoubleBuffer(false); // We don't need dbl buf
3513 #ifdef Q_WS_MAC // crash prevention on the Mac - it's unlikely to work anyway
3514 fmt.setSampleBuffers(false);
3515 #endif
3517 QGLContext* ocx = d->glcx;
3518 ocx->doneCurrent();
3519 d->glcx = new QGLContext(fmt, &pm);
3520 d->glcx->create();
3522 if (d->glcx->isValid())
3523 updateGL();
3524 else
3525 success = false;
3527 delete d->glcx;
3528 d->glcx = ocx;
3530 ocx->makeCurrent();
3532 if (success) {
3533 #if defined(Q_WS_X11)
3534 if (xinfo.visual() != QX11Info::appVisual()) {
3535 QImage image = pm.toImage();
3536 QPixmap p = QPixmap::fromImage(image);
3537 return p;
3539 #endif
3540 return pm;
3542 return QPixmap();
3546 Returns an image of the frame buffer. If \a withAlpha is true the
3547 alpha channel is included.
3549 Depending on your hardware, you can explicitly select which color
3550 buffer to grab with a glReadBuffer() call before calling this
3551 function.
3553 QImage QGLWidget::grabFrameBuffer(bool withAlpha)
3555 makeCurrent();
3556 QImage res;
3557 int w = width();
3558 int h = height();
3559 if (format().rgba()) {
3560 res = qt_gl_read_framebuffer(QSize(w, h), format().alpha(), withAlpha);
3561 } else {
3562 #if defined (Q_WS_WIN) && !defined(QT_OPENGL_ES)
3563 res = QImage(w, h, QImage::Format_Indexed8);
3564 glReadPixels(0, 0, w, h, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, res.bits());
3565 const QVector<QColor> pal = QColormap::instance().colormap();
3566 if (pal.size()) {
3567 res.setNumColors(pal.size());
3568 for (int i = 0; i < pal.size(); i++)
3569 res.setColor(i, pal.at(i).rgb());
3571 res = res.mirrored();
3572 #endif
3575 return res;
3581 Initializes OpenGL for this widget's context. Calls the virtual
3582 function initializeGL().
3585 void QGLWidget::glInit()
3587 Q_D(QGLWidget);
3588 if (!isValid())
3589 return;
3590 makeCurrent();
3591 initializeGL();
3592 d->glcx->setInitialized(true);
3597 Executes the virtual function paintGL().
3599 The widget's rendering context will become the current context and
3600 initializeGL() will be called if it hasn't already been called.
3603 void QGLWidget::glDraw()
3605 Q_D(QGLWidget);
3606 if (!isValid())
3607 return;
3608 makeCurrent();
3609 #ifndef QT_OPENGL_ES
3610 if (d->glcx->deviceIsPixmap())
3611 glDrawBuffer(GL_FRONT);
3612 #endif
3613 if (!d->glcx->initialized()) {
3614 glInit();
3615 resizeGL(d->glcx->device()->width(), d->glcx->device()->height()); // New context needs this "resize"
3617 paintGL();
3618 if (doubleBuffer()) {
3619 if (d->autoSwap)
3620 swapBuffers();
3621 } else {
3622 glFlush();
3627 Convenience function for specifying a drawing color to OpenGL.
3628 Calls glColor4 (in RGBA mode) or glIndex (in color-index mode)
3629 with the color \a c. Applies to this widgets GL context.
3631 \sa qglClearColor(), QGLContext::currentContext(), QColor
3634 void QGLWidget::qglColor(const QColor& c) const
3636 #if !defined(QT_OPENGL_ES_2)
3637 #ifdef QT_OPENGL_ES
3638 glColor4f(c.red()/255.0, c.green()/255.0, c.blue()/255.0, c.alpha()/255.0);
3639 #else
3640 Q_D(const QGLWidget);
3641 const QGLContext *ctx = QGLContext::currentContext();
3642 if (ctx) {
3643 if (ctx->format().rgba())
3644 glColor4ub(c.red(), c.green(), c.blue(), c.alpha());
3645 else if (!d->cmap.isEmpty()) { // QGLColormap in use?
3646 int i = d->cmap.find(c.rgb());
3647 if (i < 0)
3648 i = d->cmap.findNearest(c.rgb());
3649 glIndexi(i);
3650 } else
3651 glIndexi(ctx->colorIndex(c));
3653 #endif //QT_OPENGL_ES
3654 #endif //QT_OPENGL_ES_2
3658 Convenience function for specifying the clearing color to OpenGL.
3659 Calls glClearColor (in RGBA mode) or glClearIndex (in color-index
3660 mode) with the color \a c. Applies to this widgets GL context.
3662 \sa qglColor(), QGLContext::currentContext(), QColor
3665 void QGLWidget::qglClearColor(const QColor& c) const
3667 #ifdef QT_OPENGL_ES
3668 glClearColor((GLfloat)c.red() / 255.0, (GLfloat)c.green() / 255.0,
3669 (GLfloat)c.blue() / 255.0, (GLfloat) c.alpha() / 255.0);
3670 #else
3671 Q_D(const QGLWidget);
3672 const QGLContext *ctx = QGLContext::currentContext();
3673 if (ctx) {
3674 if (ctx->format().rgba())
3675 glClearColor((GLfloat)c.red() / 255.0, (GLfloat)c.green() / 255.0,
3676 (GLfloat)c.blue() / 255.0, (GLfloat) c.alpha() / 255.0);
3677 else if (!d->cmap.isEmpty()) { // QGLColormap in use?
3678 int i = d->cmap.find(c.rgb());
3679 if (i < 0)
3680 i = d->cmap.findNearest(c.rgb());
3681 glClearIndex(i);
3682 } else
3683 glClearIndex(ctx->colorIndex(c));
3685 #endif
3690 Converts the image \a img into the unnamed format expected by
3691 OpenGL functions such as glTexImage2D(). The returned image is not
3692 usable as a QImage, but QImage::width(), QImage::height() and
3693 QImage::bits() may be used with OpenGL. The GL format used is
3694 \c GL_RGBA.
3696 \omit ###
3698 \l opengl/texture example
3699 The following few lines are from the texture example. Most of the
3700 code is irrelevant, so we just quote the relevant bits:
3702 \quotefromfile opengl/texture/gltexobj.cpp
3703 \skipto tex1
3704 \printline tex1
3705 \printline gllogo.bmp
3707 We create \e tex1 (and another variable) for OpenGL, and load a real
3708 image into \e buf.
3710 \skipto convertToGLFormat
3711 \printline convertToGLFormat
3713 A few lines later, we convert \e buf into OpenGL format and store it
3714 in \e tex1.
3716 \skipto glTexImage2D
3717 \printline glTexImage2D
3718 \printline tex1.bits
3720 Note the dimension restrictions for texture images as described in
3721 the glTexImage2D() documentation. The width must be 2^m + 2*border
3722 and the height 2^n + 2*border where m and n are integers and
3723 border is either 0 or 1.
3725 Another function in the same example uses \e tex1 with OpenGL.
3727 \endomit
3730 QImage QGLWidget::convertToGLFormat(const QImage& img)
3732 QImage res(img.size(), QImage::Format_ARGB32);
3733 convertToGLFormatHelper(res, img.convertToFormat(QImage::Format_ARGB32), GL_RGBA);
3734 return res;
3739 \fn QGLColormap & QGLWidget::colormap() const
3741 Returns the colormap for this widget.
3743 Usually it is only top-level widgets that can have different
3744 colormaps installed. Asking for the colormap of a child widget
3745 will return the colormap for the child's top-level widget.
3747 If no colormap has been set for this widget, the QColormap
3748 returned will be empty.
3750 \sa setColormap()
3754 \fn void QGLWidget::setColormap(const QGLColormap & cmap)
3756 Set the colormap for this widget to \a cmap. Usually it is only
3757 top-level widgets that can have colormaps installed.
3759 \sa colormap()
3764 \obsolete
3766 Returns the value of the first display list that is generated for
3767 the characters in the given \a font. \a listBase indicates the base
3768 value used when generating the display lists for the font. The
3769 default value is 2000.
3771 int QGLWidget::fontDisplayListBase(const QFont & font, int listBase)
3773 Q_D(QGLWidget);
3774 int base;
3776 if (!d->glcx) { // this can't happen unless we run out of mem
3777 return 0;
3780 // always regenerate font disp. lists for pixmaps - hw accelerated
3781 // contexts can't handle this otherwise
3782 bool regenerate = d->glcx->deviceIsPixmap();
3783 #ifndef QT_NO_FONTCONFIG
3784 // font color needs to be part of the font cache key when using
3785 // antialiased fonts since one set of glyphs needs to be generated
3786 // for each font color
3787 QString color_key;
3788 if (font.styleStrategy() != QFont::NoAntialias) {
3789 GLfloat color[4];
3790 #ifndef QT_OPENGL_ES
3791 glGetFloatv(GL_CURRENT_COLOR, color);
3792 #endif
3793 color_key.sprintf("%f_%f_%f",color[0], color[1], color[2]);
3795 QString key = font.key() + color_key + QString::number((int) regenerate);
3796 #else
3797 QString key = font.key() + QString::number((int) regenerate);
3798 #endif
3799 if (!regenerate && (d->displayListCache.find(key) != d->displayListCache.end())) {
3800 base = d->displayListCache[key];
3801 } else {
3802 int maxBase = listBase - 256;
3803 QMap<QString,int>::ConstIterator it;
3804 for (it = d->displayListCache.constBegin(); it != d->displayListCache.constEnd(); ++it) {
3805 if (maxBase < it.value()) {
3806 maxBase = it.value();
3809 maxBase += 256;
3810 d->glcx->generateFontDisplayLists(font, maxBase);
3811 d->displayListCache[key] = maxBase;
3812 base = maxBase;
3814 return base;
3817 static void qt_save_gl_state()
3819 #ifndef QT_OPENGL_ES
3820 glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS);
3821 glPushAttrib(GL_ALL_ATTRIB_BITS);
3822 #endif
3823 #if !defined(QT_OPENGL_ES_2)
3824 glMatrixMode(GL_TEXTURE);
3825 glPushMatrix();
3826 glLoadIdentity();
3827 glMatrixMode(GL_PROJECTION);
3828 glPushMatrix();
3829 glMatrixMode(GL_MODELVIEW);
3830 glPushMatrix();
3832 glShadeModel(GL_FLAT);
3833 glDisable(GL_CULL_FACE);
3834 glDisable(GL_LIGHTING);
3835 glDisable(GL_STENCIL_TEST);
3836 glEnable(GL_BLEND);
3837 glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
3838 #endif // !defined(QT_OPENGL_ES_2)
3841 static void qt_restore_gl_state()
3843 #if !defined(QT_OPENGL_ES_2)
3844 glMatrixMode(GL_TEXTURE);
3845 glPopMatrix();
3846 glMatrixMode(GL_PROJECTION);
3847 glPopMatrix();
3848 glMatrixMode(GL_MODELVIEW);
3849 glPopMatrix();
3850 #endif // !defined(QT_OPENGL_ES_2)
3851 #ifndef QT_OPENGL_ES
3852 glPopAttrib();
3853 glPopClientAttrib();
3854 #endif
3857 static void qt_gl_draw_text(QPainter *p, int x, int y, const QString &str,
3858 const QFont &font)
3860 GLfloat color[4];
3861 #ifndef QT_OPENGL_ES
3862 glGetFloatv(GL_CURRENT_COLOR, &color[0]);
3863 #endif
3865 QColor col;
3866 col.setRgbF(color[0], color[1], color[2],color[3]);
3867 QPen old_pen = p->pen();
3868 QFont old_font = p->font();
3870 p->setPen(col);
3871 p->setFont(font);
3872 p->drawText(x, y, str);
3874 p->setPen(old_pen);
3875 p->setFont(old_font);
3879 Renders the string \a str into the GL context of this widget.
3881 \a x and \a y are specified in window coordinates, with the origin
3882 in the upper left-hand corner of the window. If \a font is not
3883 specified, the currently set application font will be used to
3884 render the string. To change the color of the rendered text you can
3885 use the glColor() call (or the qglColor() convenience function),
3886 just before the renderText() call.
3888 The \a listBase parameter is obsolete and will be removed in a
3889 future version of Qt.
3891 \note This function clears the stencil buffer.
3894 void QGLWidget::renderText(int x, int y, const QString &str, const QFont &font, int)
3896 Q_D(QGLWidget);
3897 if (str.isEmpty() || !isValid())
3898 return;
3900 GLint view[4];
3901 #ifndef QT_OPENGL_ES
3902 bool use_scissor_testing = glIsEnabled(GL_SCISSOR_TEST);
3903 if (!use_scissor_testing)
3904 glGetIntegerv(GL_VIEWPORT, &view[0]);
3905 #else
3906 bool use_scissor_testing = false;
3907 #endif
3908 int width = d->glcx->device()->width();
3909 int height = d->glcx->device()->height();
3910 bool auto_swap = autoBufferSwap();
3912 QPaintEngine *engine = paintEngine();
3913 QPainter *p;
3914 bool reuse_painter = false;
3915 if (engine->isActive()) {
3916 reuse_painter = true;
3917 p = engine->painter();
3918 qt_save_gl_state();
3920 #if !defined(QT_OPENGL_ES_2)
3921 glDisable(GL_DEPTH_TEST);
3922 glViewport(0, 0, width, height);
3923 glMatrixMode(GL_PROJECTION);
3924 glLoadIdentity();
3925 #ifndef QT_OPENGL_ES
3926 glOrtho(0, width, height, 0, 0, 1);
3927 #else
3928 glOrthof(0, width, height, 0, 0, 1);
3929 #endif
3930 glMatrixMode(GL_MODELVIEW);
3932 glLoadIdentity();
3933 #endif // !defined(QT_OPENGL_ES_2)
3934 } else {
3935 setAutoBufferSwap(false);
3936 // disable glClear() as a result of QPainter::begin()
3937 d->glcx->d_func()->clear_on_painter_begin = false;
3938 p = new QPainter(this);
3941 QRect viewport(view[0], view[1], view[2], view[3]);
3942 if (!use_scissor_testing && viewport != rect()) {
3943 // if the user hasn't set a scissor box, we set one that
3944 // covers the current viewport
3945 glScissor(view[0], view[1], view[2], view[3]);
3946 glEnable(GL_SCISSOR_TEST);
3947 } else if (use_scissor_testing) {
3948 // use the scissor box set by the user
3949 glEnable(GL_SCISSOR_TEST);
3952 qt_gl_draw_text(p, x, y, str, font);
3954 if (reuse_painter) {
3955 qt_restore_gl_state();
3956 } else {
3957 p->end();
3958 delete p;
3959 setAutoBufferSwap(auto_swap);
3960 d->glcx->d_func()->clear_on_painter_begin = true;
3964 /*! \overload
3966 \a x, \a y and \a z are specified in scene or object coordinates
3967 relative to the currently set projection and model matrices. This
3968 can be useful if you want to annotate models with text labels and
3969 have the labels move with the model as it is rotated etc.
3971 void QGLWidget::renderText(double x, double y, double z, const QString &str, const QFont &font, int)
3973 Q_D(QGLWidget);
3974 if (str.isEmpty() || !isValid())
3975 return;
3977 bool auto_swap = autoBufferSwap();
3979 int width = d->glcx->device()->width();
3980 int height = d->glcx->device()->height();
3981 GLdouble model[4][4], proj[4][4];
3982 GLint view[4];
3983 #ifndef QT_OPENGL_ES
3984 glGetDoublev(GL_MODELVIEW_MATRIX, &model[0][0]);
3985 glGetDoublev(GL_PROJECTION_MATRIX, &proj[0][0]);
3986 glGetIntegerv(GL_VIEWPORT, &view[0]);
3987 #endif
3988 GLdouble win_x = 0, win_y = 0, win_z = 0;
3989 qgluProject(x, y, z, &model[0][0], &proj[0][0], &view[0],
3990 &win_x, &win_y, &win_z);
3991 win_y = height - win_y; // y is inverted
3993 QPaintEngine *engine = paintEngine();
3994 QPainter *p;
3995 bool reuse_painter = false;
3996 #ifndef QT_OPENGL_ES
3997 bool use_depth_testing = glIsEnabled(GL_DEPTH_TEST);
3998 bool use_scissor_testing = glIsEnabled(GL_SCISSOR_TEST);
3999 #else
4000 bool use_depth_testing = false;
4001 bool use_scissor_testing = false;
4002 #endif
4004 if (engine->isActive()) {
4005 reuse_painter = true;
4006 p = engine->painter();
4007 qt_save_gl_state();
4008 } else {
4009 setAutoBufferSwap(false);
4010 // disable glClear() as a result of QPainter::begin()
4011 d->glcx->d_func()->clear_on_painter_begin = false;
4012 p = new QPainter(this);
4015 QRect viewport(view[0], view[1], view[2], view[3]);
4016 if (!use_scissor_testing && viewport != rect()) {
4017 glScissor(view[0], view[1], view[2], view[3]);
4018 glEnable(GL_SCISSOR_TEST);
4019 } else if (use_scissor_testing) {
4020 glEnable(GL_SCISSOR_TEST);
4022 #if !defined(QT_OPENGL_ES_2)
4023 glMatrixMode(GL_PROJECTION);
4024 glLoadIdentity();
4025 glViewport(0, 0, width, height);
4026 #ifndef QT_OPENGL_ES
4027 glOrtho(0, width, height, 0, 0, 1);
4028 #else
4029 glOrthof(0, width, height, 0, 0, 1);
4030 #endif
4031 glMatrixMode(GL_MODELVIEW);
4032 glLoadIdentity();
4033 glAlphaFunc(GL_GREATER, 0.0);
4034 glEnable(GL_ALPHA_TEST);
4035 if (use_depth_testing)
4036 glEnable(GL_DEPTH_TEST);
4037 #ifndef QT_OPENGL_ES
4038 glTranslated(0, 0, -win_z);
4039 #else
4040 glTranslatef(0, 0, -win_z);
4041 #endif
4042 #endif // !defined(QT_OPENGL_ES_2)
4043 qt_gl_draw_text(p, qRound(win_x), qRound(win_y), str, font);
4045 if (reuse_painter) {
4046 qt_restore_gl_state();
4047 } else {
4048 p->end();
4049 delete p;
4050 setAutoBufferSwap(auto_swap);
4051 d->glcx->d_func()->clear_on_painter_begin = true;
4055 QGLFormat QGLWidget::format() const
4057 Q_D(const QGLWidget);
4058 return d->glcx->format();
4061 const QGLContext *QGLWidget::context() const
4063 Q_D(const QGLWidget);
4064 return d->glcx;
4067 bool QGLWidget::doubleBuffer() const
4069 Q_D(const QGLWidget);
4070 return d->glcx->d_ptr->glFormat.testOption(QGL::DoubleBuffer);
4073 void QGLWidget::setAutoBufferSwap(bool on)
4075 Q_D(QGLWidget);
4076 d->autoSwap = on;
4079 bool QGLWidget::autoBufferSwap() const
4081 Q_D(const QGLWidget);
4082 return d->autoSwap;
4086 Calls QGLContext:::bindTexture(\a image, \a target, \a format) on the currently
4087 set context.
4089 \sa deleteTexture()
4091 GLuint QGLWidget::bindTexture(const QImage &image, GLenum target, GLint format)
4093 Q_D(QGLWidget);
4094 return d->glcx->bindTexture(image, target, format);
4097 #ifdef Q_MAC_COMPAT_GL_FUNCTIONS
4098 /*! \internal */
4099 GLuint QGLWidget::bindTexture(const QImage &image, QMacCompatGLenum target, QMacCompatGLint format)
4101 Q_D(QGLWidget);
4102 return d->glcx->bindTexture(image, GLenum(target), GLint(format));
4104 #endif
4107 Calls QGLContext:::bindTexture(\a pixmap, \a target, \a format) on the currently
4108 set context.
4110 \sa deleteTexture()
4112 GLuint QGLWidget::bindTexture(const QPixmap &pixmap, GLenum target, GLint format)
4114 Q_D(QGLWidget);
4115 return d->glcx->bindTexture(pixmap, target, format);
4118 #ifdef Q_MAC_COMPAT_GL_FUNCTIONS
4119 /*! \internal */
4120 GLuint QGLWidget::bindTexture(const QPixmap &pixmap, QMacCompatGLenum target, QMacCompatGLint format)
4122 Q_D(QGLWidget);
4123 return d->glcx->bindTexture(pixmap, target, format);
4125 #endif
4128 /*! \overload
4130 Calls QGLContext::bindTexture(\a fileName) on the currently set context.
4132 \sa deleteTexture()
4134 GLuint QGLWidget::bindTexture(const QString &fileName)
4136 Q_D(QGLWidget);
4137 return d->glcx->bindTexture(fileName);
4141 Calls QGLContext::deleteTexture(\a id) on the currently set
4142 context.
4144 \sa bindTexture()
4146 void QGLWidget::deleteTexture(GLuint id)
4148 Q_D(QGLWidget);
4149 d->glcx->deleteTexture(id);
4152 #ifdef Q_MAC_COMPAT_GL_FUNCTIONS
4153 /*! \internal */
4154 void QGLWidget::deleteTexture(QMacCompatGLuint id)
4156 Q_D(QGLWidget);
4157 d->glcx->deleteTexture(GLuint(id));
4159 #endif
4162 \since 4.4
4164 Draws the given texture, \a textureId to the given target rectangle,
4165 \a target, in OpenGL model space. The \a textureTarget should be a 2D
4166 texture target.
4168 Equivalent to the corresponding QGLContext::drawTexture().
4170 void QGLWidget::drawTexture(const QRectF &target, GLuint textureId, GLenum textureTarget)
4172 Q_D(QGLWidget);
4173 d->glcx->drawTexture(target, textureId, textureTarget);
4176 #ifdef Q_MAC_COMPAT_GL_FUNCTIONS
4177 /*! \internal */
4178 void QGLWidget::drawTexture(const QRectF &target, QMacCompatGLuint textureId, QMacCompatGLenum textureTarget)
4180 Q_D(QGLWidget);
4181 d->glcx->drawTexture(target, GLint(textureId), GLenum(textureTarget));
4183 #endif
4186 \since 4.4
4188 Draws the given texture, \a textureId, at the given \a point in OpenGL
4189 model space. The \a textureTarget should be a 2D texture target.
4191 Equivalent to the corresponding QGLContext::drawTexture().
4193 void QGLWidget::drawTexture(const QPointF &point, GLuint textureId, GLenum textureTarget)
4195 Q_D(QGLWidget);
4196 d->glcx->drawTexture(point, textureId, textureTarget);
4199 #ifdef Q_MAC_COMPAT_GL_FUNCTIONS
4200 /*! \internal */
4201 void QGLWidget::drawTexture(const QPointF &point, QMacCompatGLuint textureId, QMacCompatGLenum textureTarget)
4203 Q_D(QGLWidget);
4204 d->glcx->drawTexture(point, GLuint(textureId), GLenum(textureTarget));
4206 #endif
4208 #if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
4209 Q_GLOBAL_STATIC(QGL2PaintEngineEx, qt_gl_2_engine)
4210 #endif
4212 #ifndef QT_OPENGL_ES_2
4213 Q_GLOBAL_STATIC(QOpenGLPaintEngine, qt_gl_engine)
4214 #endif
4216 #ifdef Q_WS_QWS
4217 Q_OPENGL_EXPORT QPaintEngine* qt_qgl_paint_engine()
4219 #if !defined(QT_OPENGL_ES_2)
4220 return qt_gl_engine();
4221 #else
4222 return 0; // XXX
4223 #endif
4225 #endif
4228 \internal
4230 Returns the GL widget's paint engine. This is normally a
4231 QOpenGLPaintEngine.
4233 QPaintEngine *QGLWidget::paintEngine() const
4235 #if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_1_CL)
4236 return qt_gl_engine();
4237 #elif defined(QT_OPENGL_ES_2)
4238 return qt_gl_2_engine();
4239 #else
4240 if (!qt_gl_preferGL2Engine())
4241 return qt_gl_engine();
4242 else
4243 return qt_gl_2_engine();
4244 #endif
4247 #ifdef QT3_SUPPORT
4249 \overload
4250 \obsolete
4252 QGLWidget::QGLWidget(QWidget *parent, const char *name,
4253 const QGLWidget* shareWidget, Qt::WindowFlags f)
4254 : QWidget(*(new QGLWidgetPrivate), parent, f | Qt::MSWindowsOwnDC)
4256 Q_D(QGLWidget);
4257 if (name)
4258 setObjectName(QString::fromAscii(name));
4259 setAttribute(Qt::WA_PaintOnScreen);
4260 setAttribute(Qt::WA_NoSystemBackground);
4261 setAutoFillBackground(true); // for compatibility
4262 d->init(new QGLContext(QGLFormat::defaultFormat(), this), shareWidget);
4266 \overload
4267 \obsolete
4269 QGLWidget::QGLWidget(const QGLFormat &format, QWidget *parent,
4270 const char *name, const QGLWidget* shareWidget,
4271 Qt::WindowFlags f)
4272 : QWidget(*(new QGLWidgetPrivate), parent, f | Qt::MSWindowsOwnDC)
4274 Q_D(QGLWidget);
4275 if (name)
4276 setObjectName(QString::fromAscii(name));
4277 setAttribute(Qt::WA_PaintOnScreen);
4278 setAttribute(Qt::WA_NoSystemBackground);
4279 setAutoFillBackground(true); // for compatibility
4280 d->init(new QGLContext(format, this), shareWidget);
4284 \overload
4285 \obsolete
4287 QGLWidget::QGLWidget(QGLContext *context, QWidget *parent,
4288 const char *name, const QGLWidget *shareWidget, Qt::WindowFlags f)
4289 : QWidget(*(new QGLWidgetPrivate), parent, f | Qt::MSWindowsOwnDC)
4291 Q_D(QGLWidget);
4292 if (name)
4293 setObjectName(QString::fromAscii(name));
4294 setAttribute(Qt::WA_PaintOnScreen);
4295 setAttribute(Qt::WA_NoSystemBackground);
4296 setAutoFillBackground(true); // for compatibility
4297 d->init(context, shareWidget);
4300 #endif // QT3_SUPPORT
4302 void QGLExtensions::init_extensions()
4304 QString extensions = QLatin1String(reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS)));
4305 if (extensions.contains(QLatin1String("texture_rectangle")))
4306 glExtensions |= TextureRectangle;
4307 if (extensions.contains(QLatin1String("multisample")))
4308 glExtensions |= SampleBuffers;
4309 if (extensions.contains(QLatin1String("generate_mipmap")))
4310 glExtensions |= GenerateMipmap;
4311 if (extensions.contains(QLatin1String("texture_compression_s3tc")))
4312 glExtensions |= TextureCompression;
4313 if (extensions.contains(QLatin1String("ARB_fragment_program")))
4314 glExtensions |= FragmentProgram;
4315 if (extensions.contains(QLatin1String("mirrored_repeat")))
4316 glExtensions |= MirroredRepeat;
4317 if (extensions.contains(QLatin1String("EXT_framebuffer_object")))
4318 glExtensions |= FramebufferObject;
4319 if (extensions.contains(QLatin1String("EXT_stencil_two_side")))
4320 glExtensions |= StencilTwoSide;
4321 if (extensions.contains(QLatin1String("EXT_stencil_wrap")))
4322 glExtensions |= StencilWrap;
4323 if (extensions.contains(QLatin1String("EXT_packed_depth_stencil")))
4324 glExtensions |= PackedDepthStencil;
4325 if (extensions.contains(QLatin1String("GL_NV_float_buffer")))
4326 glExtensions |= NVFloatBuffer;
4327 if (extensions.contains(QLatin1String("ARB_pixel_buffer_object")))
4328 glExtensions |= PixelBufferObject;
4329 #if defined(QT_OPENGL_ES_2)
4330 glExtensions |= FramebufferObject;
4331 glExtensions |= GenerateMipmap;
4332 #endif
4333 if (extensions.contains(QLatin1String("EXT_framebuffer_blit")))
4334 glExtensions |= FramebufferBlit;
4336 QGLContext cx(QGLFormat::defaultFormat());
4337 if (glExtensions & TextureCompression) {
4338 qt_glCompressedTexImage2DARB = (pfn_glCompressedTexImage2DARB) cx.getProcAddress(QLatin1String("glCompressedTexImage2DARB"));
4343 This is the shared initialization for all platforms. Called from QGLWidgetPrivate::init()
4345 void QGLWidgetPrivate::initContext(QGLContext *context, const QGLWidget* shareWidget)
4347 Q_Q(QGLWidget);
4349 QGLExtensions::init();
4350 glcx = 0;
4351 autoSwap = true;
4353 if (context && !context->device())
4354 context->setDevice(q);
4355 q->setContext(context, shareWidget ? shareWidget->context() : 0);
4357 if (!glcx)
4358 glcx = new QGLContext(QGLFormat::defaultFormat(), q);
4360 q->setAttribute(Qt::WA_NoSystemBackground);
4363 #if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS)
4364 Q_GLOBAL_STATIC(QString, qt_gl_lib_name)
4366 Q_OPENGL_EXPORT void qt_set_gl_library_name(const QString& name)
4368 qt_gl_lib_name()->operator=(name);
4371 Q_OPENGL_EXPORT const QString qt_gl_library_name()
4373 if (qt_gl_lib_name()->isNull()) {
4374 #if defined(Q_WS_X11) || defined(Q_WS_QWS)
4375 return QLatin1String("GL");
4376 #else // Q_WS_MAC
4377 return QLatin1String("/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib");
4378 #endif
4380 return *qt_gl_lib_name();
4382 #endif
4384 void QGLDrawable::setDevice(QPaintDevice *pdev)
4386 wasBound = false;
4387 widget = 0;
4388 buffer = 0;
4389 fbo = 0;
4390 #ifdef Q_WS_QWS
4391 wsurf = 0;
4392 #endif
4394 #if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
4395 if (pdev->devType() == QInternal::Pixmap) {
4396 QPixmapData *data = static_cast<QPixmap *>(pdev)->pixmapData();
4397 Q_ASSERT(data->classId() == QPixmapData::OpenGLClass);
4398 pixmapData = static_cast<QGLPixmapData *>(data);
4400 fbo = pixmapData->fbo();
4402 #else
4403 Q_ASSERT(pdev->devType() != QInternal::Pixmap);
4404 #endif
4406 if (pdev->devType() == QInternal::Widget)
4407 widget = static_cast<QGLWidget *>(pdev);
4408 else if (pdev->devType() == QInternal::Pbuffer)
4409 buffer = static_cast<QGLPixelBuffer *>(pdev);
4410 else if (pdev->devType() == QInternal::FramebufferObject)
4411 fbo = static_cast<QGLFramebufferObject *>(pdev);
4412 #ifdef Q_WS_QWS
4413 else if (pdev->devType() == QInternal::UnknownDevice)
4414 wsurf = static_cast<QWSGLPaintDevice*>(pdev)->windowSurface();
4415 #elif !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
4416 else if (pdev->devType() == QInternal::UnknownDevice)
4417 wsurf = static_cast<QGLWindowSurface *>(pdev);
4418 #endif
4421 void QGLDrawable::swapBuffers()
4423 if (widget) {
4424 if (widget->autoBufferSwap())
4425 widget->swapBuffers();
4426 #if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
4427 } else if (pixmapData) {
4428 pixmapData->swapBuffers();
4429 #endif
4430 } else {
4431 glFlush();
4435 void QGLDrawable::makeCurrent()
4437 previous_fbo = 0;
4438 #if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
4439 if (!pixmapData && !fbo) {
4440 #else
4441 if (!fbo) {
4442 #endif
4443 QGLContext *ctx = context();
4444 previous_fbo = ctx->d_ptr->current_fbo;
4445 ctx->d_ptr->current_fbo = 0;
4446 if (previous_fbo)
4447 glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
4450 if (widget)
4451 widget->makeCurrent();
4452 #if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
4453 else if (pixmapData)
4454 pixmapData->makeCurrent();
4455 #endif
4456 else if (buffer)
4457 buffer->makeCurrent();
4458 #if defined(Q_WS_QWS) || (!defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL))
4459 else if (wsurf)
4460 wsurf->context()->makeCurrent();
4461 #endif
4462 else if (fbo) {
4463 wasBound = fbo->isBound();
4464 if (!wasBound)
4465 fbo->bind();
4469 #if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
4470 QGLPixmapData *QGLDrawable::copyOnBegin() const
4472 if (!pixmapData || pixmapData->isUninitialized())
4473 return 0;
4474 return pixmapData;
4476 #endif
4478 void QGLDrawable::doneCurrent()
4480 #if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
4481 if (pixmapData) {
4482 pixmapData->doneCurrent();
4483 return;
4485 #endif
4487 if (previous_fbo) {
4488 QGLContext *ctx = context();
4489 ctx->d_ptr->current_fbo = previous_fbo;
4490 glBindFramebuffer(GL_FRAMEBUFFER_EXT, previous_fbo);
4493 if (fbo && !wasBound)
4494 fbo->release();
4497 QSize QGLDrawable::size() const
4499 if (widget) {
4500 return QSize(widget->d_func()->glcx->device()->width(),
4501 widget->d_func()->glcx->device()->height());
4502 #if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
4503 } else if (pixmapData) {
4504 return pixmapData->size();
4505 #endif
4506 } else if (buffer) {
4507 return buffer->size();
4508 } else if (fbo) {
4509 return fbo->size();
4511 #ifdef Q_WS_QWS
4512 else if (wsurf)
4513 return wsurf->window()->frameSize();
4514 #elif !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
4515 else if (wsurf)
4516 return QSize(wsurf->width(), wsurf->height());
4517 #endif
4518 return QSize();
4521 QGLFormat QGLDrawable::format() const
4523 if (widget)
4524 return widget->format();
4525 else if (buffer)
4526 return buffer->format();
4527 #if defined(Q_WS_QWS) || (!defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL))
4528 else if (wsurf)
4529 return wsurf->context()->format();
4530 #endif
4531 else if (fbo && QGLContext::currentContext()) {
4532 QGLFormat fmt = QGLContext::currentContext()->format();
4533 fmt.setStencil(fbo->attachment() == QGLFramebufferObject::CombinedDepthStencil);
4534 fmt.setDepth(fbo->attachment() != QGLFramebufferObject::NoAttachment);
4535 return fmt;
4538 return QGLFormat();
4541 GLuint QGLDrawable::bindTexture(const QImage &image, GLenum target, GLint format)
4543 if (widget)
4544 return widget->d_func()->glcx->d_func()->bindTexture(image, target, format, true);
4545 else if (buffer)
4546 return buffer->d_func()->qctx->d_func()->bindTexture(image, target, format, true);
4547 else if (fbo && QGLContext::currentContext())
4548 return const_cast<QGLContext *>(QGLContext::currentContext())->d_func()->bindTexture(image, target, format, true);
4549 #if defined(Q_WS_QWS) || (!defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL))
4550 else if (wsurf)
4551 return wsurf->context()->d_func()->bindTexture(image, target, format, true);
4552 #endif
4553 return 0;
4556 GLuint QGLDrawable::bindTexture(const QPixmap &pixmap, GLenum target, GLint format)
4558 if (widget)
4559 return widget->d_func()->glcx->d_func()->bindTexture(pixmap, target, format, true);
4560 else if (buffer)
4561 return buffer->d_func()->qctx->d_func()->bindTexture(pixmap, target, format, true);
4562 else if (fbo && QGLContext::currentContext())
4563 return const_cast<QGLContext *>(QGLContext::currentContext())->d_func()->bindTexture(pixmap, target, format, true);
4564 #if defined(Q_WS_QWS) || (!defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL))
4565 else if (wsurf)
4566 return wsurf->context()->d_func()->bindTexture(pixmap, target, format, true);
4567 #endif
4568 return 0;
4571 QColor QGLDrawable::backgroundColor() const
4573 if (widget)
4574 return widget->palette().brush(widget->backgroundRole()).color();
4575 #if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
4576 else if (pixmapData)
4577 return pixmapData->fillColor();
4578 #endif
4579 return QApplication::palette().brush(QPalette::Background).color();
4582 bool QGLDrawable::hasTransparentBackground() const
4584 return widget && widget->testAttribute(Qt::WA_TranslucentBackground);
4587 QGLContext *QGLDrawable::context() const
4589 if (widget)
4590 return widget->d_func()->glcx;
4591 else if (buffer)
4592 return buffer->d_func()->qctx;
4593 else if (fbo)
4594 return const_cast<QGLContext *>(QGLContext::currentContext());
4595 #if defined(Q_WS_QWS) || (!defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL))
4596 else if (wsurf)
4597 return wsurf->context();
4598 #endif
4599 return 0;
4602 bool QGLDrawable::autoFillBackground() const
4604 if (widget)
4605 return widget->autoFillBackground();
4606 #if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
4607 else if (pixmapData)
4608 return pixmapData->needsFill();
4609 #endif
4610 else
4611 return false;
4614 QT_END_NAMESPACE