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

Last change on this file since 1050 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 175.6 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtOpenGL module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qapplication.h"
43#include "qplatformdefs.h"
44#include "qgl.h"
45#include <qdebug.h>
46
47#if defined(Q_WS_X11)
48#include "private/qt_x11_p.h"
49#include "private/qpixmap_x11_p.h"
50#define INT32 dummy_INT32
51#define INT8 dummy_INT8
52#ifdef QT_NO_EGL
53# include <GL/glx.h>
54#endif
55#undef INT32
56#undef INT8
57#include "qx11info_x11.h"
58#elif defined(Q_WS_MAC)
59# include <private/qt_mac_p.h>
60#endif
61
62#include <qdatetime.h>
63
64#include <stdlib.h> // malloc
65
66#include "qpixmap.h"
67#include "qimage.h"
68#include "qgl_p.h"
69
70#if !defined(QT_OPENGL_ES_1)
71#include "gl2paintengineex/qpaintengineex_opengl2_p.h"
72#endif
73
74#ifndef QT_OPENGL_ES_2
75#include <private/qpaintengine_opengl_p.h>
76#endif
77
78#ifdef Q_WS_QWS
79#include <private/qglwindowsurface_qws_p.h>
80#endif
81
82#include <qglpixelbuffer.h>
83#include <qglframebufferobject.h>
84
85#include <private/qimage_p.h>
86#include <private/qpixmapdata_p.h>
87#include <private/qpixmapdata_gl_p.h>
88#include <private/qglpixelbuffer_p.h>
89#include <private/qwindowsurface_gl_p.h>
90#include <private/qimagepixmapcleanuphooks_p.h>
91#include "qcolormap.h"
92#include "qfile.h"
93#include "qlibrary.h"
94#include <qmutex.h>
95
96
97QT_BEGIN_NAMESPACE
98
99#if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)
100QGLExtensionFuncs QGLContextPrivate::qt_extensionFuncs;
101#endif
102
103#ifdef Q_WS_X11
104extern const QX11Info *qt_x11Info(const QPaintDevice *pd);
105#endif
106
107struct QGLThreadContext {
108 QGLContext *context;
109};
110
111static QThreadStorage<QGLThreadContext *> qgl_context_storage;
112
113Q_GLOBAL_STATIC(QGLFormat, qgl_default_format)
114
115class QGLDefaultOverlayFormat: public QGLFormat
116{
117public:
118 inline QGLDefaultOverlayFormat()
119 {
120 setOption(QGL::FormatOption(0xffff << 16)); // turn off all options
121 setOption(QGL::DirectRendering);
122 setPlane(1);
123 }
124};
125Q_GLOBAL_STATIC(QGLDefaultOverlayFormat, defaultOverlayFormatInstance)
126
127Q_GLOBAL_STATIC(QGLSignalProxy, theSignalProxy)
128QGLSignalProxy *QGLSignalProxy::instance()
129{
130 QGLSignalProxy *proxy = theSignalProxy();
131 if (proxy && proxy->thread() != qApp->thread()) {
132 if (proxy->thread() == QThread::currentThread())
133 proxy->moveToThread(qApp->thread());
134 }
135 return proxy;
136}
137
138
139class QGLEngineSelector
140{
141public:
142 QGLEngineSelector() : engineType(QPaintEngine::MaxUser)
143 {
144 }
145
146 void setPreferredPaintEngine(QPaintEngine::Type type) {
147 if (type == QPaintEngine::OpenGL || type == QPaintEngine::OpenGL2)
148 engineType = type;
149 }
150
151 QPaintEngine::Type preferredPaintEngine() {
152#ifdef Q_WS_MAC
153 // The ATI X1600 driver for Mac OS X does not support return
154 // values from functions in GLSL. Since working around this in
155 // the GL2 engine would require a big, ugly rewrite, we're
156 // falling back to the GL 1 engine..
157 static bool mac_x1600_check_done = false;
158 if (!mac_x1600_check_done) {
159 QGLTemporaryContext *tmp = 0;
160 if (!QGLContext::currentContext())
161 tmp = new QGLTemporaryContext();
162 if (strstr((char *) glGetString(GL_RENDERER), "X1600"))
163 engineType = QPaintEngine::OpenGL;
164 if (tmp)
165 delete tmp;
166 mac_x1600_check_done = true;
167 }
168#endif
169 if (engineType == QPaintEngine::MaxUser) {
170 // No user-set engine - use the defaults
171#if defined(QT_OPENGL_ES_2)
172 engineType = QPaintEngine::OpenGL2;
173#else
174 // We can't do this in the constructor for this object because it
175 // needs to be called *before* the QApplication constructor.
176 // Also check for the FragmentShader extension in conjunction with
177 // the 2.0 version flag, to cover the case where we export the display
178 // from an old GL 1.1 server to a GL 2.x client. In that case we can't
179 // use GL 2.0.
180 if ((QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_2_0)
181 && (QGLExtensions::glExtensions() & QGLExtensions::FragmentShader)
182 && qgetenv("QT_GL_USE_OPENGL1ENGINE").isEmpty())
183 engineType = QPaintEngine::OpenGL2;
184 else
185 engineType = QPaintEngine::OpenGL;
186#endif
187 }
188 return engineType;
189 }
190
191private:
192 QPaintEngine::Type engineType;
193};
194
195Q_GLOBAL_STATIC(QGLEngineSelector, qgl_engine_selector)
196
197
198bool qt_gl_preferGL2Engine()
199{
200 return qgl_engine_selector()->preferredPaintEngine() == QPaintEngine::OpenGL2;
201}
202
203
204/*!
205 \namespace QGL
206 \inmodule QtOpenGL
207
208 \brief The QGL namespace specifies miscellaneous identifiers used
209 in the Qt OpenGL module.
210
211 \ingroup painting-3D
212*/
213
214/*!
215 \enum QGL::FormatOption
216
217 This enum specifies the format options that can be used to configure an OpenGL
218 context. These are set using QGLFormat::setOption().
219
220 \value DoubleBuffer Specifies the use of double buffering.
221 \value DepthBuffer Enables the use of a depth buffer.
222 \value Rgba Specifies that the context should use RGBA as its pixel format.
223 \value AlphaChannel Enables the use of an alpha channel.
224 \value AccumBuffer Enables the use of an accumulation buffer.
225 \value StencilBuffer Enables the use of a stencil buffer.
226 \value StereoBuffers Enables the use of a stereo buffers for use with visualization hardware.
227 \value DirectRendering Specifies that the context is used for direct rendering to a display.
228 \value HasOverlay Enables the use of an overlay.
229 \value SampleBuffers Enables the use of sample buffers.
230 \value DeprecatedFunctions Enables the use of deprecated functionality for OpenGL 3.x
231 contexts. A context with deprecated functionality enabled is
232 called a full context in the OpenGL specification.
233 \value SingleBuffer Specifies the use of a single buffer, as opposed to double buffers.
234 \value NoDepthBuffer Disables the use of a depth buffer.
235 \value ColorIndex Specifies that the context should use a color index as its pixel format.
236 \value NoAlphaChannel Disables the use of an alpha channel.
237 \value NoAccumBuffer Disables the use of an accumulation buffer.
238 \value NoStencilBuffer Disables the use of a stencil buffer.
239 \value NoStereoBuffers Disables the use of stereo buffers.
240 \value IndirectRendering Specifies that the context is used for indirect rendering to a buffer.
241 \value NoOverlay Disables the use of an overlay.
242 \value NoSampleBuffers Disables the use of sample buffers.
243 \value NoDeprecatedFunctions Disables the use of deprecated functionality for OpenGL 3.x
244 contexts. A context with deprecated functionality disabled is
245 called a forward compatible context in the OpenGL specification.
246
247 \sa {Sample Buffers Example}
248*/
249
250/*!
251 \fn void QGL::setPreferredPaintEngine(QPaintEngine::Type engineType)
252
253 \since 4.6
254
255 Sets the preferred OpenGL paint engine that is used to draw onto
256 QGLWidget, QGLPixelBuffer and QGLFramebufferObject targets with QPainter
257 in Qt.
258
259 The \a engineType parameter specifies which of the GL engines to
260 use. Only \c QPaintEngine::OpenGL and \c QPaintEngine::OpenGL2 are
261 valid parameters to this function. All other values are ignored.
262
263 By default, the \c QPaintEngine::OpenGL2 engine is used if GL/GLES
264 version 2.0 is available, otherwise \c QPaintEngine::OpenGL is
265 used.
266
267 \warning This function must be called before the QApplication
268 constructor is called.
269*/
270void QGL::setPreferredPaintEngine(QPaintEngine::Type engineType)
271{
272 qgl_engine_selector()->setPreferredPaintEngine(engineType);
273}
274
275
276/*****************************************************************************
277 QGLFormat implementation
278 *****************************************************************************/
279
280
281/*!
282 \class QGLFormat
283 \brief The QGLFormat class specifies the display format of an OpenGL
284 rendering context.
285
286 \ingroup painting-3D
287
288 A display format has several characteristics:
289 \list
290 \i \link setDoubleBuffer() Double or single buffering.\endlink
291 \i \link setDepth() Depth buffer.\endlink
292 \i \link setRgba() RGBA or color index mode.\endlink
293 \i \link setAlpha() Alpha channel.\endlink
294 \i \link setAccum() Accumulation buffer.\endlink
295 \i \link setStencil() Stencil buffer.\endlink
296 \i \link setStereo() Stereo buffers.\endlink
297 \i \link setDirectRendering() Direct rendering.\endlink
298 \i \link setOverlay() Presence of an overlay.\endlink
299 \i \link setPlane() Plane of an overlay.\endlink
300 \i \link setSampleBuffers() Multisample buffers.\endlink
301 \endlist
302
303 You can also specify preferred bit depths for the color buffer,
304 depth buffer, alpha buffer, accumulation buffer and the stencil
305 buffer with the functions: setRedBufferSize(), setGreenBufferSize(),
306 setBlueBufferSize(), setDepthBufferSize(), setAlphaBufferSize(),
307 setAccumBufferSize() and setStencilBufferSize().
308
309 Note that even if you specify that you prefer a 32 bit depth
310 buffer (e.g. with setDepthBufferSize(32)), the format that is
311 chosen may not have a 32 bit depth buffer, even if there is a
312 format available with a 32 bit depth buffer. The main reason for
313 this is how the system dependant picking algorithms work on the
314 different platforms, and some format options may have higher
315 precedence than others.
316
317 You create and tell a QGLFormat object what rendering options you
318 want from an OpenGL rendering context.
319
320 OpenGL drivers or accelerated hardware may or may not support
321 advanced features such as alpha channel or stereographic viewing.
322 If you request some features that the driver/hardware does not
323 provide when you create a QGLWidget, you will get a rendering
324 context with the nearest subset of features.
325
326 There are different ways to define the display characteristics of
327 a rendering context. One is to create a QGLFormat and make it the
328 default for the entire application:
329 \snippet doc/src/snippets/code/src_opengl_qgl.cpp 0
330
331 Or you can specify the desired format when creating an object of
332 your QGLWidget subclass:
333 \snippet doc/src/snippets/code/src_opengl_qgl.cpp 1
334
335 After the widget has been created, you can find out which of the
336 requested features the system was able to provide:
337 \snippet doc/src/snippets/code/src_opengl_qgl.cpp 2
338
339 \legalese
340 OpenGL is a trademark of Silicon Graphics, Inc. in the
341 United States and other countries.
342 \endlegalese
343
344 \sa QGLContext, QGLWidget
345*/
346
347#ifndef QT_OPENGL_ES
348
349static inline void transform_point(GLdouble out[4], const GLdouble m[16], const GLdouble in[4])
350{
351#define M(row,col) m[col*4+row]
352 out[0] =
353 M(0, 0) * in[0] + M(0, 1) * in[1] + M(0, 2) * in[2] + M(0, 3) * in[3];
354 out[1] =
355 M(1, 0) * in[0] + M(1, 1) * in[1] + M(1, 2) * in[2] + M(1, 3) * in[3];
356 out[2] =
357 M(2, 0) * in[0] + M(2, 1) * in[1] + M(2, 2) * in[2] + M(2, 3) * in[3];
358 out[3] =
359 M(3, 0) * in[0] + M(3, 1) * in[1] + M(3, 2) * in[2] + M(3, 3) * in[3];
360#undef M
361}
362
363static inline GLint qgluProject(GLdouble objx, GLdouble objy, GLdouble objz,
364 const GLdouble model[16], const GLdouble proj[16],
365 const GLint viewport[4],
366 GLdouble * winx, GLdouble * winy, GLdouble * winz)
367{
368 GLdouble in[4], out[4];
369
370 in[0] = objx;
371 in[1] = objy;
372 in[2] = objz;
373 in[3] = 1.0;
374 transform_point(out, model, in);
375 transform_point(in, proj, out);
376
377 if (in[3] == 0.0)
378 return GL_FALSE;
379
380 in[0] /= in[3];
381 in[1] /= in[3];
382 in[2] /= in[3];
383
384 *winx = viewport[0] + (1 + in[0]) * viewport[2] / 2;
385 *winy = viewport[1] + (1 + in[1]) * viewport[3] / 2;
386
387 *winz = (1 + in[2]) / 2;
388 return GL_TRUE;
389}
390
391#endif // !QT_OPENGL_ES
392
393/*!
394 Constructs a QGLFormat object with the following default settings:
395 \list
396 \i \link setDoubleBuffer() Double buffer:\endlink Enabled.
397 \i \link setDepth() Depth buffer:\endlink Enabled.
398 \i \link setRgba() RGBA:\endlink Enabled (i.e., color index disabled).
399 \i \link setAlpha() Alpha channel:\endlink Disabled.
400 \i \link setAccum() Accumulator buffer:\endlink Disabled.
401 \i \link setStencil() Stencil buffer:\endlink Enabled.
402 \i \link setStereo() Stereo:\endlink Disabled.
403 \i \link setDirectRendering() Direct rendering:\endlink Enabled.
404 \i \link setOverlay() Overlay:\endlink Disabled.
405 \i \link setPlane() Plane:\endlink 0 (i.e., normal plane).
406 \i \link setSampleBuffers() Multisample buffers:\endlink Disabled.
407 \endlist
408*/
409
410QGLFormat::QGLFormat()
411{
412 d = new QGLFormatPrivate;
413}
414
415
416/*!
417 Creates a QGLFormat object that is a copy of the current
418 defaultFormat().
419
420 If \a options is not 0, the default format is modified by the
421 specified format options. The \a options parameter should be
422 QGL::FormatOption values OR'ed together.
423
424 This constructor makes it easy to specify a certain desired format
425 in classes derived from QGLWidget, for example:
426 \snippet doc/src/snippets/code/src_opengl_qgl.cpp 3
427
428 Note that there are QGL::FormatOption values to turn format settings
429 both on and off, e.g. QGL::DepthBuffer and QGL::NoDepthBuffer,
430 QGL::DirectRendering and QGL::IndirectRendering, etc.
431
432 The \a plane parameter defaults to 0 and is the plane which this
433 format should be associated with. Not all OpenGL implementations
434 supports overlay/underlay rendering planes.
435
436 \sa defaultFormat(), setOption(), setPlane()
437*/
438
439QGLFormat::QGLFormat(QGL::FormatOptions options, int plane)
440{
441 d = new QGLFormatPrivate;
442 QGL::FormatOptions newOpts = options;
443 d->opts = defaultFormat().d->opts;
444 d->opts |= (newOpts & 0xffff);
445 d->opts &= ~(newOpts >> 16);
446 d->pln = plane;
447}
448
449/*!
450 \internal
451*/
452void QGLFormat::detach()
453{
454 if (d->ref != 1) {
455 QGLFormatPrivate *newd = new QGLFormatPrivate(d);
456 if (!d->ref.deref())
457 delete d;
458 d = newd;
459 }
460}
461
462/*!
463 Constructs a copy of \a other.
464*/
465
466QGLFormat::QGLFormat(const QGLFormat &other)
467{
468 d = other.d;
469 d->ref.ref();
470}
471
472/*!
473 Assigns \a other to this object.
474*/
475
476QGLFormat &QGLFormat::operator=(const QGLFormat &other)
477{
478 if (d != other.d) {
479 other.d->ref.ref();
480 if (!d->ref.deref())
481 delete d;
482 d = other.d;
483 }
484 return *this;
485}
486
487/*!
488 Destroys the QGLFormat.
489*/
490QGLFormat::~QGLFormat()
491{
492 if (!d->ref.deref())
493 delete d;
494}
495
496/*!
497 \fn bool QGLFormat::doubleBuffer() const
498
499 Returns true if double buffering is enabled; otherwise returns
500 false. Double buffering is enabled by default.
501
502 \sa setDoubleBuffer()
503*/
504
505/*!
506 If \a enable is true sets double buffering; otherwise sets single
507 buffering.
508
509 Double buffering is enabled by default.
510
511 Double buffering is a technique where graphics are rendered on an
512 off-screen buffer and not directly to the screen. When the drawing
513 has been completed, the program calls a swapBuffers() function to
514 exchange the screen contents with the buffer. The result is
515 flicker-free drawing and often better performance.
516
517 Note that single buffered contexts are currently not supported
518 with EGL.
519
520 \sa doubleBuffer(), QGLContext::swapBuffers(),
521 QGLWidget::swapBuffers()
522*/
523
524void QGLFormat::setDoubleBuffer(bool enable)
525{
526 setOption(enable ? QGL::DoubleBuffer : QGL::SingleBuffer);
527}
528
529
530/*!
531 \fn bool QGLFormat::depth() const
532
533 Returns true if the depth buffer is enabled; otherwise returns
534 false. The depth buffer is enabled by default.
535
536 \sa setDepth(), setDepthBufferSize()
537*/
538
539/*!
540 If \a enable is true enables the depth buffer; otherwise disables
541 the depth buffer.
542
543 The depth buffer is enabled by default.
544
545 The purpose of a depth buffer (or Z-buffering) is to remove hidden
546 surfaces. Pixels are assigned Z values based on the distance to
547 the viewer. A pixel with a high Z value is closer to the viewer
548 than a pixel with a low Z value. This information is used to
549 decide whether to draw a pixel or not.
550
551 \sa depth(), setDepthBufferSize()
552*/
553
554void QGLFormat::setDepth(bool enable)
555{
556 setOption(enable ? QGL::DepthBuffer : QGL::NoDepthBuffer);
557}
558
559
560/*!
561 \fn bool QGLFormat::rgba() const
562
563 Returns true if RGBA color mode is set. Returns false if color
564 index mode is set. The default color mode is RGBA.
565
566 \sa setRgba()
567*/
568
569/*!
570 If \a enable is true sets RGBA mode. If \a enable is false sets
571 color index mode.
572
573 The default color mode is RGBA.
574
575 RGBA is the preferred mode for most OpenGL applications. In RGBA
576 color mode you specify colors as red + green + blue + alpha
577 quadruplets.
578
579 In color index mode you specify an index into a color lookup
580 table.
581
582 \sa rgba()
583*/
584
585void QGLFormat::setRgba(bool enable)
586{
587 setOption(enable ? QGL::Rgba : QGL::ColorIndex);
588}
589
590
591/*!
592 \fn bool QGLFormat::alpha() const
593
594 Returns true if the alpha buffer in the framebuffer is enabled;
595 otherwise returns false. The alpha buffer is disabled by default.
596
597 \sa setAlpha(), setAlphaBufferSize()
598*/
599
600/*!
601 If \a enable is true enables the alpha buffer; otherwise disables
602 the alpha buffer.
603
604 The alpha buffer is disabled by default.
605
606 The alpha buffer is typically used for implementing transparency
607 or translucency. The A in RGBA specifies the transparency of a
608 pixel.
609
610 \sa alpha(), setAlphaBufferSize()
611*/
612
613void QGLFormat::setAlpha(bool enable)
614{
615 setOption(enable ? QGL::AlphaChannel : QGL::NoAlphaChannel);
616}
617
618
619/*!
620 \fn bool QGLFormat::accum() const
621
622 Returns true if the accumulation buffer is enabled; otherwise
623 returns false. The accumulation buffer is disabled by default.
624
625 \sa setAccum(), setAccumBufferSize()
626*/
627
628/*!
629 If \a enable is true enables the accumulation buffer; otherwise
630 disables the accumulation buffer.
631
632 The accumulation buffer is disabled by default.
633
634 The accumulation buffer is used to create blur effects and
635 multiple exposures.
636
637 \sa accum(), setAccumBufferSize()
638*/
639
640void QGLFormat::setAccum(bool enable)
641{
642 setOption(enable ? QGL::AccumBuffer : QGL::NoAccumBuffer);
643}
644
645
646/*!
647 \fn bool QGLFormat::stencil() const
648
649 Returns true if the stencil buffer is enabled; otherwise returns
650 false. The stencil buffer is enabled by default.
651
652 \sa setStencil(), setStencilBufferSize()
653*/
654
655/*!
656 If \a enable is true enables the stencil buffer; otherwise
657 disables the stencil buffer.
658
659 The stencil buffer is enabled by default.
660
661 The stencil buffer masks certain parts of the drawing area so that
662 masked parts are not drawn on.
663
664 \sa stencil(), setStencilBufferSize()
665*/
666
667void QGLFormat::setStencil(bool enable)
668{
669 setOption(enable ? QGL::StencilBuffer: QGL::NoStencilBuffer);
670}
671
672
673/*!
674 \fn bool QGLFormat::stereo() const
675
676 Returns true if stereo buffering is enabled; otherwise returns
677 false. Stereo buffering is disabled by default.
678
679 \sa setStereo()
680*/
681
682/*!
683 If \a enable is true enables stereo buffering; otherwise disables
684 stereo buffering.
685
686 Stereo buffering is disabled by default.
687
688 Stereo buffering provides extra color buffers to generate left-eye
689 and right-eye images.
690
691 \sa stereo()
692*/
693
694void QGLFormat::setStereo(bool enable)
695{
696 setOption(enable ? QGL::StereoBuffers : QGL::NoStereoBuffers);
697}
698
699
700/*!
701 \fn bool QGLFormat::directRendering() const
702
703 Returns true if direct rendering is enabled; otherwise returns
704 false.
705
706 Direct rendering is enabled by default.
707
708 \sa setDirectRendering()
709*/
710
711/*!
712 If \a enable is true enables direct rendering; otherwise disables
713 direct rendering.
714
715 Direct rendering is enabled by default.
716
717 Enabling this option will make OpenGL bypass the underlying window
718 system and render directly from hardware to the screen, if this is
719 supported by the system.
720
721 \sa directRendering()
722*/
723
724void QGLFormat::setDirectRendering(bool enable)
725{
726 setOption(enable ? QGL::DirectRendering : QGL::IndirectRendering);
727}
728
729/*!
730 \fn bool QGLFormat::sampleBuffers() const
731
732 Returns true if multisample buffer support is enabled; otherwise
733 returns false.
734
735 The multisample buffer is disabled by default.
736
737 \sa setSampleBuffers()
738*/
739
740/*!
741 If \a enable is true, a GL context with multisample buffer support
742 is picked; otherwise ignored.
743
744 \sa sampleBuffers(), setSamples(), samples()
745*/
746void QGLFormat::setSampleBuffers(bool enable)
747{
748 setOption(enable ? QGL::SampleBuffers : QGL::NoSampleBuffers);
749}
750
751/*!
752 Returns the number of samples per pixel when multisampling is
753 enabled. By default, the highest number of samples that is
754 available is used.
755
756 \sa setSampleBuffers(), sampleBuffers(), setSamples()
757*/
758int QGLFormat::samples() const
759{
760 return d->numSamples;
761}
762
763/*!
764 Set the preferred number of samples per pixel when multisampling
765 is enabled to \a numSamples. By default, the highest number of
766 samples available is used.
767
768 \sa setSampleBuffers(), sampleBuffers(), samples()
769*/
770void QGLFormat::setSamples(int numSamples)
771{
772 detach();
773 if (numSamples < 0) {
774 qWarning("QGLFormat::setSamples: Cannot have negative number of samples per pixel %d", numSamples);
775 return;
776 }
777 d->numSamples = numSamples;
778 setSampleBuffers(numSamples > 0);
779}
780
781/*!
782 \since 4.2
783
784 Set the preferred swap interval. This can be used to sync the GL
785 drawing into a system window to the vertical refresh of the screen.
786 Setting an \a interval value of 0 will turn the vertical refresh syncing
787 off, any value higher than 0 will turn the vertical syncing on.
788
789 Under Windows and under X11, where the \c{WGL_EXT_swap_control}
790 and \c{GLX_SGI_video_sync} extensions are used, the \a interval
791 parameter can be used to set the minimum number of video frames
792 that are displayed before a buffer swap will occur. In effect,
793 setting the \a interval to 10, means there will be 10 vertical
794 retraces between every buffer swap.
795
796 Under Windows the \c{WGL_EXT_swap_control} extension has to be present,
797 and under X11 the \c{GLX_SGI_video_sync} extension has to be present.
798*/
799void QGLFormat::setSwapInterval(int interval)
800{
801 detach();
802 d->swapInterval = interval;
803}
804
805/*!
806 \since 4.2
807
808 Returns the currently set swap interval. -1 is returned if setting
809 the swap interval isn't supported in the system GL implementation.
810*/
811int QGLFormat::swapInterval() const
812{
813 return d->swapInterval;
814}
815
816/*!
817 \fn bool QGLFormat::hasOverlay() const
818
819 Returns true if overlay plane is enabled; otherwise returns false.
820
821 Overlay is disabled by default.
822
823 \sa setOverlay()
824*/
825
826/*!
827 If \a enable is true enables an overlay plane; otherwise disables
828 the overlay plane.
829
830 Enabling the overlay plane will cause QGLWidget to create an
831 additional context in an overlay plane. See the QGLWidget
832 documentation for further information.
833
834 \sa hasOverlay()
835*/
836
837void QGLFormat::setOverlay(bool enable)
838{
839 setOption(enable ? QGL::HasOverlay : QGL::NoOverlay);
840}
841
842/*!
843 Returns the plane of this format. The default for normal formats
844 is 0, which means the normal plane. The default for overlay
845 formats is 1, which is the first overlay plane.
846
847 \sa setPlane(), defaultOverlayFormat()
848*/
849int QGLFormat::plane() const
850{
851 return d->pln;
852}
853
854/*!
855 Sets the requested plane to \a plane. 0 is the normal plane, 1 is
856 the first overlay plane, 2 is the second overlay plane, etc.; -1,
857 -2, etc. are underlay planes.
858
859 Note that in contrast to other format specifications, the plane
860 specifications will be matched exactly. This means that if you
861 specify a plane that the underlying OpenGL system cannot provide,
862 an \link QGLWidget::isValid() invalid\endlink QGLWidget will be
863 created.
864
865 \sa plane()
866*/
867void QGLFormat::setPlane(int plane)
868{
869 detach();
870 d->pln = plane;
871}
872
873/*!
874 Sets the format option to \a opt.
875
876 \sa testOption()
877*/
878
879void QGLFormat::setOption(QGL::FormatOptions opt)
880{
881 detach();
882 if (opt & 0xffff)
883 d->opts |= opt;
884 else
885 d->opts &= ~(opt >> 16);
886}
887
888
889
890/*!
891 Returns true if format option \a opt is set; otherwise returns false.
892
893 \sa setOption()
894*/
895
896bool QGLFormat::testOption(QGL::FormatOptions opt) const
897{
898 if (opt & 0xffff)
899 return (d->opts & opt) != 0;
900 else
901 return (d->opts & (opt >> 16)) == 0;
902}
903
904/*!
905 Set the minimum depth buffer size to \a size.
906
907 \sa depthBufferSize(), setDepth(), depth()
908*/
909void QGLFormat::setDepthBufferSize(int size)
910{
911 detach();
912 if (size < 0) {
913 qWarning("QGLFormat::setDepthBufferSize: Cannot set negative depth buffer size %d", size);
914 return;
915 }
916 d->depthSize = size;
917 setDepth(size > 0);
918}
919
920/*!
921 Returns the depth buffer size.
922
923 \sa depth(), setDepth(), setDepthBufferSize()
924*/
925int QGLFormat::depthBufferSize() const
926{
927 return d->depthSize;
928}
929
930/*!
931 \since 4.2
932
933 Set the preferred red buffer size to \a size.
934
935 \sa setGreenBufferSize(), setBlueBufferSize(), setAlphaBufferSize()
936*/
937void QGLFormat::setRedBufferSize(int size)
938{
939 detach();
940 if (size < 0) {
941 qWarning("QGLFormat::setRedBufferSize: Cannot set negative red buffer size %d", size);
942 return;
943 }
944 d->redSize = size;
945}
946
947/*!
948 \since 4.2
949
950 Returns the red buffer size.
951
952 \sa setRedBufferSize()
953*/
954int QGLFormat::redBufferSize() const
955{
956 return d->redSize;
957}
958
959/*!
960 \since 4.2
961
962 Set the preferred green buffer size to \a size.
963
964 \sa setRedBufferSize(), setBlueBufferSize(), setAlphaBufferSize()
965*/
966void QGLFormat::setGreenBufferSize(int size)
967{
968 detach();
969 if (size < 0) {
970 qWarning("QGLFormat::setGreenBufferSize: Cannot set negative green buffer size %d", size);
971 return;
972 }
973 d->greenSize = size;
974}
975
976/*!
977 \since 4.2
978
979 Returns the green buffer size.
980
981 \sa setGreenBufferSize()
982*/
983int QGLFormat::greenBufferSize() const
984{
985 return d->greenSize;
986}
987
988/*!
989 \since 4.2
990
991 Set the preferred blue buffer size to \a size.
992
993 \sa setRedBufferSize(), setGreenBufferSize(), setAlphaBufferSize()
994*/
995void QGLFormat::setBlueBufferSize(int size)
996{
997 detach();
998 if (size < 0) {
999 qWarning("QGLFormat::setBlueBufferSize: Cannot set negative blue buffer size %d", size);
1000 return;
1001 }
1002 d->blueSize = size;
1003}
1004
1005/*!
1006 \since 4.2
1007
1008 Returns the blue buffer size.
1009
1010 \sa setBlueBufferSize()
1011*/
1012int QGLFormat::blueBufferSize() const
1013{
1014 return d->blueSize;
1015}
1016
1017/*!
1018 Set the preferred alpha buffer size to \a size.
1019 This function implicitly enables the alpha channel.
1020
1021 \sa setRedBufferSize(), setGreenBufferSize(), alphaBufferSize()
1022*/
1023void QGLFormat::setAlphaBufferSize(int size)
1024{
1025 detach();
1026 if (size < 0) {
1027 qWarning("QGLFormat::setAlphaBufferSize: Cannot set negative alpha buffer size %d", size);
1028 return;
1029 }
1030 d->alphaSize = size;
1031 setAlpha(size > 0);
1032}
1033
1034/*!
1035 Returns the alpha buffer size.
1036
1037 \sa alpha(), setAlpha(), setAlphaBufferSize()
1038*/
1039int QGLFormat::alphaBufferSize() const
1040{
1041 return d->alphaSize;
1042}
1043
1044/*!
1045 Set the preferred accumulation buffer size, where \a size is the
1046 bit depth for each RGBA component.
1047
1048 \sa accum(), setAccum(), accumBufferSize()
1049*/
1050void QGLFormat::setAccumBufferSize(int size)
1051{
1052 detach();
1053 if (size < 0) {
1054 qWarning("QGLFormat::setAccumBufferSize: Cannot set negative accumulate buffer size %d", size);
1055 return;
1056 }
1057 d->accumSize = size;
1058 setAccum(size > 0);
1059}
1060
1061/*!
1062 Returns the accumulation buffer size.
1063
1064 \sa setAccumBufferSize(), accum(), setAccum()
1065*/
1066int QGLFormat::accumBufferSize() const
1067{
1068 return d->accumSize;
1069}
1070
1071/*!
1072 Set the preferred stencil buffer size to \a size.
1073
1074 \sa stencilBufferSize(), setStencil(), stencil()
1075*/
1076void QGLFormat::setStencilBufferSize(int size)
1077{
1078 detach();
1079 if (size < 0) {
1080 qWarning("QGLFormat::setStencilBufferSize: Cannot set negative stencil buffer size %d", size);
1081 return;
1082 }
1083 d->stencilSize = size;
1084 setStencil(size > 0);
1085}
1086
1087/*!
1088 Returns the stencil buffer size.
1089
1090 \sa stencil(), setStencil(), setStencilBufferSize()
1091*/
1092int QGLFormat::stencilBufferSize() const
1093{
1094 return d->stencilSize;
1095}
1096
1097/*!
1098 \since 4.7
1099
1100 Set the OpenGL version to the \a major and \a minor numbers. If a
1101 context compatible with the requested OpenGL version cannot be
1102 created, a context compatible with version 1.x is created instead.
1103
1104 \sa majorVersion(), minorVersion()
1105*/
1106void QGLFormat::setVersion(int major, int minor)
1107{
1108 if (major < 1 || minor < 0) {
1109 qWarning("QGLFormat::setVersion: Cannot set zero or negative version number %d.%d", major, minor);
1110 return;
1111 }
1112 detach();
1113 d->majorVersion = major;
1114 d->minorVersion = minor;
1115}
1116
1117/*!
1118 \since 4.7
1119
1120 Returns the OpenGL major version.
1121
1122 \sa setVersion(), minorVersion()
1123*/
1124int QGLFormat::majorVersion() const
1125{
1126 return d->majorVersion;
1127}
1128
1129/*!
1130 \since 4.7
1131
1132 Returns the OpenGL minor version.
1133
1134 \sa setVersion(), majorVersion()
1135*/
1136int QGLFormat::minorVersion() const
1137{
1138 return d->minorVersion;
1139}
1140
1141/*!
1142 \enum QGLFormat::OpenGLContextProfile
1143 \since 4.7
1144
1145 This enum describes the OpenGL context profiles that can be
1146 specified for contexts implementing OpenGL version 3.2 or
1147 higher. These profiles are different from OpenGL ES profiles.
1148
1149 \value NoProfile OpenGL version is lower than 3.2.
1150 \value CoreProfile Functionality deprecated in OpenGL version 3.0 is not available.
1151 \value CompatibilityProfile Functionality from earlier OpenGL versions is available.
1152*/
1153
1154/*!
1155 \since 4.7
1156
1157 Set the OpenGL context profile to \a profile. The \a profile is
1158 ignored if the requested OpenGL version is less than 3.2.
1159
1160 \sa profile()
1161*/
1162void QGLFormat::setProfile(OpenGLContextProfile profile)
1163{
1164 detach();
1165 d->profile = profile;
1166}
1167
1168/*!
1169 \since 4.7
1170
1171 Returns the OpenGL context profile.
1172
1173 \sa setProfile()
1174*/
1175QGLFormat::OpenGLContextProfile QGLFormat::profile() const
1176{
1177 return d->profile;
1178}
1179
1180
1181/*!
1182 \fn bool QGLFormat::hasOpenGL()
1183
1184 Returns true if the window system has any OpenGL support;
1185 otherwise returns false.
1186
1187 \warning This function must not be called until the QApplication
1188 object has been created.
1189*/
1190
1191
1192
1193/*!
1194 \fn bool QGLFormat::hasOpenGLOverlays()
1195
1196 Returns true if the window system supports OpenGL overlays;
1197 otherwise returns false.
1198
1199 \warning This function must not be called until the QApplication
1200 object has been created.
1201*/
1202
1203QGLFormat::OpenGLVersionFlags Q_AUTOTEST_EXPORT qOpenGLVersionFlagsFromString(const QString &versionString)
1204{
1205 QGLFormat::OpenGLVersionFlags versionFlags = QGLFormat::OpenGL_Version_None;
1206
1207 if (versionString.startsWith(QLatin1String("OpenGL ES"))) {
1208 QStringList parts = versionString.split(QLatin1Char(' '));
1209 if (parts.size() >= 3) {
1210 if (parts[2].startsWith(QLatin1String("1."))) {
1211 if (parts[1].endsWith(QLatin1String("-CM"))) {
1212 versionFlags |= QGLFormat::OpenGL_ES_Common_Version_1_0 |
1213 QGLFormat::OpenGL_ES_CommonLite_Version_1_0;
1214 if (parts[2].startsWith(QLatin1String("1.1")))
1215 versionFlags |= QGLFormat::OpenGL_ES_Common_Version_1_1 |
1216 QGLFormat::OpenGL_ES_CommonLite_Version_1_1;
1217 } else {
1218 // Not -CM, must be CL, CommonLite
1219 versionFlags |= QGLFormat::OpenGL_ES_CommonLite_Version_1_0;
1220 if (parts[2].startsWith(QLatin1String("1.1")))
1221 versionFlags |= QGLFormat::OpenGL_ES_CommonLite_Version_1_1;
1222 }
1223 } else {
1224 // OpenGL ES version 2.0 or higher
1225 versionFlags |= QGLFormat::OpenGL_ES_Version_2_0;
1226 }
1227 } else {
1228 // if < 3 parts to the name, it is an unrecognised OpenGL ES
1229 qWarning("Unrecognised OpenGL ES version");
1230 }
1231 } else {
1232 // not ES, regular OpenGL, the version numbers are first in the string
1233 if (versionString.startsWith(QLatin1String("1."))) {
1234 switch (versionString[2].toAscii()) {
1235 case '5':
1236 versionFlags |= QGLFormat::OpenGL_Version_1_5;
1237 case '4':
1238 versionFlags |= QGLFormat::OpenGL_Version_1_4;
1239 case '3':
1240 versionFlags |= QGLFormat::OpenGL_Version_1_3;
1241 case '2':
1242 versionFlags |= QGLFormat::OpenGL_Version_1_2;
1243 case '1':
1244 versionFlags |= QGLFormat::OpenGL_Version_1_1;
1245 default:
1246 break;
1247 }
1248 } else if (versionString.startsWith(QLatin1String("2."))) {
1249 versionFlags |= QGLFormat::OpenGL_Version_1_1 |
1250 QGLFormat::OpenGL_Version_1_2 |
1251 QGLFormat::OpenGL_Version_1_3 |
1252 QGLFormat::OpenGL_Version_1_4 |
1253 QGLFormat::OpenGL_Version_1_5 |
1254 QGLFormat::OpenGL_Version_2_0;
1255 if (versionString[2].toAscii() == '1')
1256 versionFlags |= QGLFormat::OpenGL_Version_2_1;
1257 } else if (versionString.startsWith(QLatin1String("3."))) {
1258 versionFlags |= QGLFormat::OpenGL_Version_1_1 |
1259 QGLFormat::OpenGL_Version_1_2 |
1260 QGLFormat::OpenGL_Version_1_3 |
1261 QGLFormat::OpenGL_Version_1_4 |
1262 QGLFormat::OpenGL_Version_1_5 |
1263 QGLFormat::OpenGL_Version_2_0 |
1264 QGLFormat::OpenGL_Version_2_1 |
1265 QGLFormat::OpenGL_Version_3_0;
1266 switch (versionString[2].toAscii()) {
1267 case '3':
1268 versionFlags |= QGLFormat::OpenGL_Version_3_3;
1269 case '2':
1270 versionFlags |= QGLFormat::OpenGL_Version_3_2;
1271 case '1':
1272 versionFlags |= QGLFormat::OpenGL_Version_3_1;
1273 case '0':
1274 break;
1275 default:
1276 versionFlags |= QGLFormat::OpenGL_Version_3_1 |
1277 QGLFormat::OpenGL_Version_3_2 |
1278 QGLFormat::OpenGL_Version_3_3;
1279 break;
1280 }
1281 } else if (versionString.startsWith(QLatin1String("4."))) {
1282 versionFlags |= QGLFormat::OpenGL_Version_1_1 |
1283 QGLFormat::OpenGL_Version_1_2 |
1284 QGLFormat::OpenGL_Version_1_3 |
1285 QGLFormat::OpenGL_Version_1_4 |
1286 QGLFormat::OpenGL_Version_1_5 |
1287 QGLFormat::OpenGL_Version_2_0 |
1288 QGLFormat::OpenGL_Version_2_1 |
1289 QGLFormat::OpenGL_Version_3_0 |
1290 QGLFormat::OpenGL_Version_3_1 |
1291 QGLFormat::OpenGL_Version_3_2 |
1292 QGLFormat::OpenGL_Version_3_3 |
1293 QGLFormat::OpenGL_Version_4_0;
1294 } else {
1295 versionFlags |= QGLFormat::OpenGL_Version_1_1 |
1296 QGLFormat::OpenGL_Version_1_2 |
1297 QGLFormat::OpenGL_Version_1_3 |
1298 QGLFormat::OpenGL_Version_1_4 |
1299 QGLFormat::OpenGL_Version_1_5 |
1300 QGLFormat::OpenGL_Version_2_0 |
1301 QGLFormat::OpenGL_Version_2_1 |
1302 QGLFormat::OpenGL_Version_3_0 |
1303 QGLFormat::OpenGL_Version_3_1 |
1304 QGLFormat::OpenGL_Version_3_2 |
1305 QGLFormat::OpenGL_Version_3_3 |
1306 QGLFormat::OpenGL_Version_4_0;
1307 }
1308 }
1309 return versionFlags;
1310}
1311
1312/*!
1313 \enum QGLFormat::OpenGLVersionFlag
1314 \since 4.2
1315
1316 This enum describes the various OpenGL versions that are
1317 recognized by Qt. Use the QGLFormat::openGLVersionFlags() function
1318 to identify which versions that are supported at runtime.
1319
1320 \value OpenGL_Version_None If no OpenGL is present or if no OpenGL context is current.
1321
1322 \value OpenGL_Version_1_1 OpenGL version 1.1 or higher is present.
1323
1324 \value OpenGL_Version_1_2 OpenGL version 1.2 or higher is present.
1325
1326 \value OpenGL_Version_1_3 OpenGL version 1.3 or higher is present.
1327
1328 \value OpenGL_Version_1_4 OpenGL version 1.4 or higher is present.
1329
1330 \value OpenGL_Version_1_5 OpenGL version 1.5 or higher is present.
1331
1332 \value OpenGL_Version_2_0 OpenGL version 2.0 or higher is present.
1333 Note that version 2.0 supports all the functionality of version 1.5.
1334
1335 \value OpenGL_Version_2_1 OpenGL version 2.1 or higher is present.
1336
1337 \value OpenGL_Version_3_0 OpenGL version 3.0 or higher is present.
1338
1339 \value OpenGL_Version_3_1 OpenGL version 3.1 or higher is present.
1340 Note that OpenGL version 3.1 or higher does not necessarily support all the features of
1341 version 3.0 and lower.
1342
1343 \value OpenGL_Version_3_2 OpenGL version 3.2 or higher is present.
1344
1345 \value OpenGL_Version_3_3 OpenGL version 3.3 or higher is present.
1346
1347 \value OpenGL_Version_4_0 OpenGL version 4.0 or higher is present.
1348
1349 \value OpenGL_ES_CommonLite_Version_1_0 OpenGL ES version 1.0 Common Lite or higher is present.
1350
1351 \value OpenGL_ES_Common_Version_1_0 OpenGL ES version 1.0 Common or higher is present.
1352 The Common profile supports all the features of Common Lite.
1353
1354 \value OpenGL_ES_CommonLite_Version_1_1 OpenGL ES version 1.1 Common Lite or higher is present.
1355
1356 \value OpenGL_ES_Common_Version_1_1 OpenGL ES version 1.1 Common or higher is present.
1357 The Common profile supports all the features of Common Lite.
1358
1359 \value OpenGL_ES_Version_2_0 OpenGL ES version 2.0 or higher is present.
1360 Note that OpenGL ES version 2.0 does not support all the features of OpenGL ES 1.x.
1361 So if OpenGL_ES_Version_2_0 is returned, none of the ES 1.x flags are returned.
1362
1363 See also \l{http://www.opengl.org} for more information about the different
1364 revisions of OpenGL.
1365
1366 \sa openGLVersionFlags()
1367*/
1368
1369/*!
1370 \since 4.2
1371
1372 Identifies, at runtime, which OpenGL versions that are supported
1373 by the current platform.
1374
1375 Note that if OpenGL version 1.5 is supported, its predecessors
1376 (i.e., version 1.4 and lower) are also supported. To identify the
1377 support of a particular feature, like multi texturing, test for
1378 the version in which the feature was first introduced (i.e.,
1379 version 1.3 in the case of multi texturing) to adapt to the largest
1380 possible group of runtime platforms.
1381
1382 This function needs a valid current OpenGL context to work;
1383 otherwise it will return OpenGL_Version_None.
1384
1385 \sa hasOpenGL(), hasOpenGLOverlays()
1386*/
1387QGLFormat::OpenGLVersionFlags QGLFormat::openGLVersionFlags()
1388{
1389 static bool cachedDefault = false;
1390 static OpenGLVersionFlags defaultVersionFlags = OpenGL_Version_None;
1391 QGLContext *currentCtx = const_cast<QGLContext *>(QGLContext::currentContext());
1392 QGLTemporaryContext *tmpContext = 0;
1393
1394 if (currentCtx && currentCtx->d_func()->version_flags_cached)
1395 return currentCtx->d_func()->version_flags;
1396
1397 if (!currentCtx) {
1398 if (cachedDefault) {
1399 return defaultVersionFlags;
1400 } else {
1401 if (!hasOpenGL())
1402 return defaultVersionFlags;
1403 tmpContext = new QGLTemporaryContext;
1404 cachedDefault = true;
1405 }
1406 }
1407
1408 QString versionString(QLatin1String(reinterpret_cast<const char*>(glGetString(GL_VERSION))));
1409 OpenGLVersionFlags versionFlags = qOpenGLVersionFlagsFromString(versionString);
1410 if (currentCtx) {
1411 currentCtx->d_func()->version_flags_cached = true;
1412 currentCtx->d_func()->version_flags = versionFlags;
1413 }
1414 if (tmpContext) {
1415 defaultVersionFlags = versionFlags;
1416 delete tmpContext;
1417 }
1418
1419 return versionFlags;
1420}
1421
1422
1423/*!
1424 Returns the default QGLFormat for the application. All QGLWidget
1425 objects that are created use this format unless another format is
1426 specified, e.g. when they are constructed.
1427
1428 If no special default format has been set using
1429 setDefaultFormat(), the default format is the same as that created
1430 with QGLFormat().
1431
1432 \sa setDefaultFormat()
1433*/
1434
1435QGLFormat QGLFormat::defaultFormat()
1436{
1437 return *qgl_default_format();
1438}
1439
1440/*!
1441 Sets a new default QGLFormat for the application to \a f. For
1442 example, to set single buffering as the default instead of double
1443 buffering, your main() might contain code like this:
1444 \snippet doc/src/snippets/code/src_opengl_qgl.cpp 4
1445
1446 \sa defaultFormat()
1447*/
1448
1449void QGLFormat::setDefaultFormat(const QGLFormat &f)
1450{
1451 *qgl_default_format() = f;
1452}
1453
1454
1455/*!
1456 Returns the default QGLFormat for overlay contexts.
1457
1458 The default overlay format is:
1459 \list
1460 \i \link setDoubleBuffer() Double buffer:\endlink Disabled.
1461 \i \link setDepth() Depth buffer:\endlink Disabled.
1462 \i \link setRgba() RGBA:\endlink Disabled (i.e., color index enabled).
1463 \i \link setAlpha() Alpha channel:\endlink Disabled.
1464 \i \link setAccum() Accumulator buffer:\endlink Disabled.
1465 \i \link setStencil() Stencil buffer:\endlink Disabled.
1466 \i \link setStereo() Stereo:\endlink Disabled.
1467 \i \link setDirectRendering() Direct rendering:\endlink Enabled.
1468 \i \link setOverlay() Overlay:\endlink Disabled.
1469 \i \link setSampleBuffers() Multisample buffers:\endlink Disabled.
1470 \i \link setPlane() Plane:\endlink 1 (i.e., first overlay plane).
1471 \endlist
1472
1473 \sa setDefaultFormat()
1474*/
1475
1476QGLFormat QGLFormat::defaultOverlayFormat()
1477{
1478 return *defaultOverlayFormatInstance();
1479}
1480
1481/*!
1482 Sets a new default QGLFormat for overlay contexts to \a f. This
1483 format is used whenever a QGLWidget is created with a format that
1484 hasOverlay() enabled.
1485
1486 For example, to get a double buffered overlay context (if
1487 available), use code like this:
1488
1489 \snippet doc/src/snippets/code/src_opengl_qgl.cpp 5
1490
1491 As usual, you can find out after widget creation whether the
1492 underlying OpenGL system was able to provide the requested
1493 specification:
1494
1495 \snippet doc/src/snippets/code/src_opengl_qgl.cpp 6
1496
1497 \sa defaultOverlayFormat()
1498*/
1499
1500void QGLFormat::setDefaultOverlayFormat(const QGLFormat &f)
1501{
1502 QGLFormat *defaultFormat = defaultOverlayFormatInstance();
1503 *defaultFormat = f;
1504 // Make sure the user doesn't request that the overlays themselves
1505 // have overlays, since it is unlikely that the system supports
1506 // infinitely many planes...
1507 defaultFormat->setOverlay(false);
1508}
1509
1510
1511/*!
1512 Returns true if all the options of the two QGLFormat objects
1513 \a a and \a b are equal; otherwise returns false.
1514
1515 \relates QGLFormat
1516*/
1517
1518bool operator==(const QGLFormat& a, const QGLFormat& b)
1519{
1520 return (a.d == b.d) || ((int) a.d->opts == (int) b.d->opts
1521 && a.d->pln == b.d->pln
1522 && a.d->alphaSize == b.d->alphaSize
1523 && a.d->accumSize == b.d->accumSize
1524 && a.d->stencilSize == b.d->stencilSize
1525 && a.d->depthSize == b.d->depthSize
1526 && a.d->redSize == b.d->redSize
1527 && a.d->greenSize == b.d->greenSize
1528 && a.d->blueSize == b.d->blueSize
1529 && a.d->numSamples == b.d->numSamples
1530 && a.d->swapInterval == b.d->swapInterval
1531 && a.d->majorVersion == b.d->majorVersion
1532 && a.d->minorVersion == b.d->minorVersion
1533 && a.d->profile == b.d->profile);
1534}
1535
1536#ifndef QT_NO_DEBUG_STREAM
1537QDebug operator<<(QDebug dbg, const QGLFormat &f)
1538{
1539 const QGLFormatPrivate * const d = f.d;
1540
1541 dbg.nospace() << "QGLFormat("
1542 << "options " << d->opts
1543 << ", plane " << d->pln
1544 << ", depthBufferSize " << d->depthSize
1545 << ", accumBufferSize " << d->accumSize
1546 << ", stencilBufferSize " << d->stencilSize
1547 << ", redBufferSize " << d->redSize
1548 << ", greenBufferSize " << d->greenSize
1549 << ", blueBufferSize " << d->blueSize
1550 << ", alphaBufferSize " << d->alphaSize
1551 << ", samples " << d->numSamples
1552 << ", swapInterval " << d->swapInterval
1553 << ", majorVersion " << d->majorVersion
1554 << ", minorVersion " << d->minorVersion
1555 << ", profile " << d->profile
1556 << ')';
1557
1558 return dbg.space();
1559}
1560#endif
1561
1562
1563/*!
1564 Returns false if all the options of the two QGLFormat objects
1565 \a a and \a b are equal; otherwise returns true.
1566
1567 \relates QGLFormat
1568*/
1569
1570bool operator!=(const QGLFormat& a, const QGLFormat& b)
1571{
1572 return !(a == b);
1573}
1574
1575struct QGLContextGroupList {
1576 void append(QGLContextGroup *group) {
1577 QMutexLocker locker(&m_mutex);
1578 m_list.append(group);
1579 }
1580
1581 void remove(QGLContextGroup *group) {
1582 QMutexLocker locker(&m_mutex);
1583 m_list.removeOne(group);
1584 }
1585
1586 QList<QGLContextGroup *> m_list;
1587 QMutex m_mutex;
1588};
1589
1590Q_GLOBAL_STATIC(QGLContextGroupList, qt_context_groups)
1591
1592/*****************************************************************************
1593 QGLContext implementation
1594 *****************************************************************************/
1595
1596QGLContextGroup::QGLContextGroup(const QGLContext *context)
1597 : m_context(context), m_guards(0), m_refs(1)
1598{
1599 qt_context_groups()->append(this);
1600}
1601
1602QGLContextGroup::~QGLContextGroup()
1603{
1604 // Clear any remaining QGLSharedResourceGuard objects on the group.
1605 QGLSharedResourceGuard *guard = m_guards;
1606 while (guard != 0) {
1607 guard->m_group = 0;
1608 guard->m_id = 0;
1609 guard = guard->m_next;
1610 }
1611 qt_context_groups()->remove(this);
1612}
1613
1614void QGLContextGroup::addGuard(QGLSharedResourceGuard *guard)
1615{
1616 if (m_guards)
1617 m_guards->m_prev = guard;
1618 guard->m_next = m_guards;
1619 guard->m_prev = 0;
1620 m_guards = guard;
1621}
1622
1623void QGLContextGroup::removeGuard(QGLSharedResourceGuard *guard)
1624{
1625 if (guard->m_next)
1626 guard->m_next->m_prev = guard->m_prev;
1627 if (guard->m_prev)
1628 guard->m_prev->m_next = guard->m_next;
1629 else
1630 m_guards = guard->m_next;
1631}
1632
1633const QGLContext *qt_gl_transfer_context(const QGLContext *ctx)
1634{
1635 if (!ctx)
1636 return 0;
1637 QList<const QGLContext *> shares
1638 (QGLContextPrivate::contextGroup(ctx)->shares());
1639 if (shares.size() >= 2)
1640 return (ctx == shares.at(0)) ? shares.at(1) : shares.at(0);
1641 else
1642 return 0;
1643}
1644
1645QGLContextPrivate::QGLContextPrivate(QGLContext *context)
1646 : internal_context(false)
1647 , q_ptr(context)
1648{
1649 group = new QGLContextGroup(context);
1650 texture_destroyer = new QGLTextureDestroyer;
1651 texture_destroyer->moveToThread(qApp->thread());
1652}
1653
1654QGLContextPrivate::~QGLContextPrivate()
1655{
1656 if (!group->m_refs.deref()) {
1657 Q_ASSERT(group->context() == q_ptr);
1658 delete group;
1659 }
1660
1661 delete texture_destroyer;
1662}
1663
1664void QGLContextPrivate::init(QPaintDevice *dev, const QGLFormat &format)
1665{
1666 Q_Q(QGLContext);
1667 glFormat = reqFormat = format;
1668 valid = false;
1669 q->setDevice(dev);
1670#if defined(Q_WS_X11)
1671 pbuf = 0;
1672 gpm = 0;
1673 vi = 0;
1674 screen = QX11Info::appScreen();
1675#endif
1676#if defined(Q_WS_WIN)
1677 dc = 0;
1678 win = 0;
1679 pixelFormatId = 0;
1680 cmap = 0;
1681 hbitmap = 0;
1682 hbitmap_hdc = 0;
1683#endif
1684#if defined(Q_WS_MAC)
1685# ifndef QT_MAC_USE_COCOA
1686 update = false;
1687# endif
1688 vi = 0;
1689#endif
1690#ifndef QT_NO_EGL
1691 ownsEglContext = false;
1692 eglContext = 0;
1693 eglSurface = EGL_NO_SURFACE;
1694#endif
1695 fbo = 0;
1696 crWin = false;
1697 initDone = false;
1698 sharing = false;
1699 max_texture_size = -1;
1700 version_flags_cached = false;
1701 version_flags = QGLFormat::OpenGL_Version_None;
1702 extension_flags_cached = false;
1703 extension_flags = 0;
1704 current_fbo = 0;
1705 default_fbo = 0;
1706 active_engine = 0;
1707 workaround_needsFullClearOnEveryFrame = false;
1708 workaround_brokenFBOReadBack = false;
1709 workaround_brokenTexSubImage = false;
1710 workaroundsCached = false;
1711
1712 workaround_brokenTextureFromPixmap = false;
1713 workaround_brokenTextureFromPixmap_init = false;
1714
1715 for (int i = 0; i < QT_GL_VERTEX_ARRAY_TRACKED_COUNT; ++i)
1716 vertexAttributeArraysEnabledState[i] = false;
1717}
1718
1719QGLContext* QGLContext::currentCtx = 0;
1720
1721/*
1722 Read back the contents of the currently bound framebuffer, used in
1723 QGLWidget::grabFrameBuffer(), QGLPixelbuffer::toImage() and
1724 QGLFramebufferObject::toImage()
1725*/
1726
1727static void convertFromGLImage(QImage &img, int w, int h, bool alpha_format, bool include_alpha)
1728{
1729 if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
1730 // OpenGL gives RGBA; Qt wants ARGB
1731 uint *p = (uint*)img.bits();
1732 uint *end = p + w*h;
1733 if (alpha_format && include_alpha) {
1734 while (p < end) {
1735 uint a = *p << 24;
1736 *p = (*p >> 8) | a;
1737 p++;
1738 }
1739 } else {
1740 // This is an old legacy fix for PowerPC based Macs, which
1741 // we shouldn't remove
1742 while (p < end) {
1743 *p = 0xff000000 | (*p>>8);
1744 ++p;
1745 }
1746 }
1747 } else {
1748 // OpenGL gives ABGR (i.e. RGBA backwards); Qt wants ARGB
1749 for (int y = 0; y < h; y++) {
1750 uint *q = (uint*)img.scanLine(y);
1751 for (int x=0; x < w; ++x) {
1752 const uint pixel = *q;
1753 if (alpha_format && include_alpha) {
1754 *q = ((pixel << 16) & 0xff0000) | ((pixel >> 16) & 0xff)
1755 | (pixel & 0xff00ff00);
1756 } else {
1757 *q = 0xff000000 | ((pixel << 16) & 0xff0000)
1758 | ((pixel >> 16) & 0xff) | (pixel & 0x00ff00);
1759 }
1760
1761 q++;
1762 }
1763 }
1764
1765 }
1766 img = img.mirrored();
1767}
1768
1769QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha)
1770{
1771 QImage img(size, (alpha_format && include_alpha) ? QImage::Format_ARGB32
1772 : QImage::Format_RGB32);
1773 int w = size.width();
1774 int h = size.height();
1775 glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, img.bits());
1776 convertFromGLImage(img, w, h, alpha_format, include_alpha);
1777 return img;
1778}
1779
1780QImage qt_gl_read_texture(const QSize &size, bool alpha_format, bool include_alpha)
1781{
1782 QImage img(size, alpha_format ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32);
1783 int w = size.width();
1784 int h = size.height();
1785#if !defined(QT_OPENGL_ES_2) && !defined(QT_OPENGL_ES_1)
1786 //### glGetTexImage not in GL ES 2.0, need to do something else here!
1787 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, img.bits());
1788#endif
1789 convertFromGLImage(img, w, h, alpha_format, include_alpha);
1790 return img;
1791}
1792
1793// returns the highest number closest to v, which is a power of 2
1794// NB! assumes 32 bit ints
1795int qt_next_power_of_two(int v)
1796{
1797 v--;
1798 v |= v >> 1;
1799 v |= v >> 2;
1800 v |= v >> 4;
1801 v |= v >> 8;
1802 v |= v >> 16;
1803 ++v;
1804 return v;
1805}
1806
1807typedef void (*_qt_pixmap_cleanup_hook_64)(qint64);
1808typedef void (*_qt_image_cleanup_hook_64)(qint64);
1809
1810extern Q_GUI_EXPORT _qt_pixmap_cleanup_hook_64 qt_pixmap_cleanup_hook_64;
1811extern Q_GUI_EXPORT _qt_image_cleanup_hook_64 qt_image_cleanup_hook_64;
1812
1813
1814Q_GLOBAL_STATIC(QGLTextureCache, qt_gl_texture_cache)
1815
1816QGLTextureCache::QGLTextureCache()
1817 : m_cache(64*1024) // cache ~64 MB worth of textures - this is not accurate though
1818{
1819 QImagePixmapCleanupHooks::instance()->addPixmapDataModificationHook(cleanupTexturesForPixampData);
1820 QImagePixmapCleanupHooks::instance()->addPixmapDataDestructionHook(cleanupBeforePixmapDestruction);
1821 QImagePixmapCleanupHooks::instance()->addImageHook(cleanupTexturesForCacheKey);
1822}
1823
1824QGLTextureCache::~QGLTextureCache()
1825{
1826 QImagePixmapCleanupHooks::instance()->removePixmapDataModificationHook(cleanupTexturesForPixampData);
1827 QImagePixmapCleanupHooks::instance()->removePixmapDataDestructionHook(cleanupBeforePixmapDestruction);
1828 QImagePixmapCleanupHooks::instance()->removeImageHook(cleanupTexturesForCacheKey);
1829}
1830
1831void QGLTextureCache::insert(QGLContext* ctx, qint64 key, QGLTexture* texture, int cost)
1832{
1833 QWriteLocker locker(&m_lock);
1834 if (m_cache.totalCost() + cost > m_cache.maxCost()) {
1835 // the cache is full - make an attempt to remove something
1836 const QList<QGLTextureCacheKey> keys = m_cache.keys();
1837 int i = 0;
1838 while (i < m_cache.count()
1839 && (m_cache.totalCost() + cost > m_cache.maxCost())) {
1840 QGLTexture *tex = m_cache.object(keys.at(i));
1841 if (tex->context == ctx)
1842 m_cache.remove(keys.at(i));
1843 ++i;
1844 }
1845 }
1846 const QGLTextureCacheKey cacheKey = {key, QGLContextPrivate::contextGroup(ctx)};
1847 m_cache.insert(cacheKey, texture, cost);
1848}
1849
1850void QGLTextureCache::remove(qint64 key)
1851{
1852 QWriteLocker locker(&m_lock);
1853 QMutexLocker groupLocker(&qt_context_groups()->m_mutex);
1854 QList<QGLContextGroup *>::const_iterator it = qt_context_groups()->m_list.constBegin();
1855 while (it != qt_context_groups()->m_list.constEnd()) {
1856 const QGLTextureCacheKey cacheKey = {key, *it};
1857 m_cache.remove(cacheKey);
1858 ++it;
1859 }
1860}
1861
1862bool QGLTextureCache::remove(QGLContext* ctx, GLuint textureId)
1863{
1864 QWriteLocker locker(&m_lock);
1865 QList<QGLTextureCacheKey> keys = m_cache.keys();
1866 for (int i = 0; i < keys.size(); ++i) {
1867 QGLTexture *tex = m_cache.object(keys.at(i));
1868 if (tex->id == textureId && tex->context == ctx) {
1869 tex->options |= QGLContext::MemoryManagedBindOption; // forces a glDeleteTextures() call
1870 m_cache.remove(keys.at(i));
1871 return true;
1872 }
1873 }
1874 return false;
1875}
1876
1877void QGLTextureCache::removeContextTextures(QGLContext* ctx)
1878{
1879 QWriteLocker locker(&m_lock);
1880 QList<QGLTextureCacheKey> keys = m_cache.keys();
1881 for (int i = 0; i < keys.size(); ++i) {
1882 const QGLTextureCacheKey &key = keys.at(i);
1883 if (m_cache.object(key)->context == ctx)
1884 m_cache.remove(key);
1885 }
1886}
1887
1888/*
1889 a hook that removes textures from the cache when a pixmap/image
1890 is deref'ed
1891*/
1892void QGLTextureCache::cleanupTexturesForCacheKey(qint64 cacheKey)
1893{
1894 qt_gl_texture_cache()->remove(cacheKey);
1895}
1896
1897
1898void QGLTextureCache::cleanupTexturesForPixampData(QPixmapData* pmd)
1899{
1900 cleanupTexturesForCacheKey(pmd->cacheKey());
1901}
1902
1903void QGLTextureCache::cleanupBeforePixmapDestruction(QPixmapData* pmd)
1904{
1905 // Remove any bound textures first:
1906 cleanupTexturesForPixampData(pmd);
1907
1908#if defined(Q_WS_X11)
1909 if (pmd->classId() == QPixmapData::X11Class) {
1910 Q_ASSERT(pmd->ref == 0); // Make sure reference counting isn't broken
1911 QGLContextPrivate::destroyGlSurfaceForPixmap(pmd);
1912 }
1913#endif
1914}
1915
1916QGLTextureCache *QGLTextureCache::instance()
1917{
1918 return qt_gl_texture_cache();
1919}
1920
1921// DDS format structure
1922struct DDSFormat {
1923 quint32 dwSize;
1924 quint32 dwFlags;
1925 quint32 dwHeight;
1926 quint32 dwWidth;
1927 quint32 dwLinearSize;
1928 quint32 dummy1;
1929 quint32 dwMipMapCount;
1930 quint32 dummy2[11];
1931 struct {
1932 quint32 dummy3[2];
1933 quint32 dwFourCC;
1934 quint32 dummy4[5];
1935 } ddsPixelFormat;
1936};
1937
1938// compressed texture pixel formats
1939#define FOURCC_DXT1 0x31545844
1940#define FOURCC_DXT2 0x32545844
1941#define FOURCC_DXT3 0x33545844
1942#define FOURCC_DXT4 0x34545844
1943#define FOURCC_DXT5 0x35545844
1944
1945#ifndef GL_COMPRESSED_RGB_S3TC_DXT1_EXT
1946#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
1947#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
1948#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2
1949#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3
1950#endif
1951
1952#ifndef GL_GENERATE_MIPMAP_SGIS
1953#define GL_GENERATE_MIPMAP_SGIS 0x8191
1954#define GL_GENERATE_MIPMAP_HINT_SGIS 0x8192
1955#endif
1956
1957/*!
1958 \class QGLContext
1959 \brief The QGLContext class encapsulates an OpenGL rendering context.
1960
1961 \ingroup painting-3D
1962
1963 An OpenGL rendering context is a complete set of OpenGL state
1964 variables. The rendering context's \l {QGL::FormatOption} {format}
1965 is set in the constructor, but it can also be set later with
1966 setFormat(). The format options that are actually set are returned
1967 by format(); the options you asked for are returned by
1968 requestedFormat(). Note that after a QGLContext object has been
1969 constructed, the actual OpenGL context must be created by
1970 explicitly calling the \link create() create()\endlink
1971 function. The makeCurrent() function makes this context the
1972 current rendering context. You can make \e no context current
1973 using doneCurrent(). The reset() function will reset the context
1974 and make it invalid.
1975
1976 You can examine properties of the context with, e.g. isValid(),
1977 isSharing(), initialized(), windowCreated() and
1978 overlayTransparentColor().
1979
1980 If you're using double buffering you can swap the screen contents
1981 with the off-screen buffer using swapBuffers().
1982
1983 Please note that QGLContext is not thread safe.
1984*/
1985
1986/*!
1987 \enum QGLContext::BindOption
1988 \since 4.6
1989
1990 A set of options to decide how to bind a texture using bindTexture().
1991
1992 \value NoBindOption Don't do anything, pass the texture straight
1993 through.
1994
1995 \value InvertedYBindOption Specifies that the texture should be flipped
1996 over the X axis so that the texture coordinate 0,0 corresponds to
1997 the top left corner. Inverting the texture implies a deep copy
1998 prior to upload.
1999
2000 \value MipmapBindOption Specifies that bindTexture() should try
2001 to generate mipmaps. If the GL implementation supports the \c
2002 GL_SGIS_generate_mipmap extension, mipmaps will be automatically
2003 generated for the texture. Mipmap generation is only supported for
2004 the \c GL_TEXTURE_2D target.
2005
2006 \value PremultipliedAlphaBindOption Specifies that the image should be
2007 uploaded with premultiplied alpha and does a conversion accordingly.
2008
2009 \value LinearFilteringBindOption Specifies that the texture filtering
2010 should be set to GL_LINEAR. Default is GL_NEAREST. If mipmap is
2011 also enabled, filtering will be set to GL_LINEAR_MIPMAP_LINEAR.
2012
2013 \value DefaultBindOption In Qt 4.5 and earlier, bindTexture()
2014 would mirror the image and automatically generate mipmaps. This
2015 option helps preserve this default behavior.
2016
2017 \omitvalue CanFlipNativePixmapBindOption Used by x11 from pixmap to choose
2018 whether or not it can bind the pixmap upside down or not.
2019
2020 \omitvalue MemoryManagedBindOption Used by paint engines to
2021 indicate that the pixmap should be memory managed along side with
2022 the pixmap/image that it stems from, e.g. installing destruction
2023 hooks in them.
2024
2025 \omitvalue InternalBindOption
2026*/
2027
2028/*!
2029 \obsolete
2030
2031 Constructs an OpenGL context for the given paint \a device, which
2032 can be a widget or a pixmap. The \a format specifies several
2033 display options for the context.
2034
2035 If the underlying OpenGL/Window system cannot satisfy all the
2036 features requested in \a format, the nearest subset of features
2037 will be used. After creation, the format() method will return the
2038 actual format obtained.
2039
2040 Note that after a QGLContext object has been constructed, \l
2041 create() must be called explicitly to create the actual OpenGL
2042 context. The context will be \l {isValid()}{invalid} if it was not
2043 possible to obtain a GL context at all.
2044*/
2045
2046QGLContext::QGLContext(const QGLFormat &format, QPaintDevice *device)
2047 : d_ptr(new QGLContextPrivate(this))
2048{
2049 Q_D(QGLContext);
2050 d->init(device, format);
2051}
2052
2053/*!
2054 Constructs an OpenGL context with the given \a format which
2055 specifies several display options for the context.
2056
2057 If the underlying OpenGL/Window system cannot satisfy all the
2058 features requested in \a format, the nearest subset of features
2059 will be used. After creation, the format() method will return the
2060 actual format obtained.
2061
2062 Note that after a QGLContext object has been constructed, \l
2063 create() must be called explicitly to create the actual OpenGL
2064 context. The context will be \l {isValid()}{invalid} if it was not
2065 possible to obtain a GL context at all.
2066
2067 \sa format(), isValid()
2068*/
2069QGLContext::QGLContext(const QGLFormat &format)
2070 : d_ptr(new QGLContextPrivate(this))
2071{
2072 Q_D(QGLContext);
2073 d->init(0, format);
2074}
2075
2076/*!
2077 Destroys the OpenGL context and frees its resources.
2078*/
2079
2080QGLContext::~QGLContext()
2081{
2082 // remove any textures cached in this context
2083 QGLTextureCache::instance()->removeContextTextures(this);
2084
2085 d_ptr->group->cleanupResources(this);
2086
2087 QGLSignalProxy::instance()->emitAboutToDestroyContext(this);
2088 reset();
2089}
2090
2091void QGLContextPrivate::cleanup()
2092{
2093}
2094
2095#define ctx q_ptr
2096void QGLContextPrivate::setVertexAttribArrayEnabled(int arrayIndex, bool enabled)
2097{
2098 Q_ASSERT(arrayIndex < QT_GL_VERTEX_ARRAY_TRACKED_COUNT);
2099#ifdef glEnableVertexAttribArray
2100 Q_ASSERT(glEnableVertexAttribArray);
2101#endif
2102
2103 if (vertexAttributeArraysEnabledState[arrayIndex] && !enabled)
2104 glDisableVertexAttribArray(arrayIndex);
2105
2106 if (!vertexAttributeArraysEnabledState[arrayIndex] && enabled)
2107 glEnableVertexAttribArray(arrayIndex);
2108
2109 vertexAttributeArraysEnabledState[arrayIndex] = enabled;
2110}
2111
2112void QGLContextPrivate::syncGlState()
2113{
2114#ifdef glEnableVertexAttribArray
2115 Q_ASSERT(glEnableVertexAttribArray);
2116#endif
2117 for (int i = 0; i < QT_GL_VERTEX_ARRAY_TRACKED_COUNT; ++i) {
2118 if (vertexAttributeArraysEnabledState[i])
2119 glEnableVertexAttribArray(i);
2120 else
2121 glDisableVertexAttribArray(i);
2122 }
2123
2124}
2125#undef ctx
2126
2127#ifdef QT_NO_EGL
2128void QGLContextPrivate::swapRegion(const QRegion &)
2129{
2130 Q_Q(QGLContext);
2131 q->swapBuffers();
2132}
2133#endif
2134
2135/*!
2136 \overload
2137
2138 Reads the compressed texture file \a fileName and generates a 2D GL
2139 texture from it.
2140
2141 This function can load DirectDrawSurface (DDS) textures in the
2142 DXT1, DXT3 and DXT5 DDS formats if the \c GL_ARB_texture_compression
2143 and \c GL_EXT_texture_compression_s3tc extensions are supported.
2144
2145 Since 4.6.1, textures in the ETC1 format can be loaded if the
2146 \c GL_OES_compressed_ETC1_RGB8_texture extension is supported
2147 and the ETC1 texture has been encapsulated in the PVR container format.
2148 Also, textures in the PVRTC2 and PVRTC4 formats can be loaded
2149 if the \c GL_IMG_texture_compression_pvrtc extension is supported.
2150
2151 \sa deleteTexture()
2152*/
2153
2154GLuint QGLContext::bindTexture(const QString &fileName)
2155{
2156 Q_D(QGLContext);
2157 QGLDDSCache *dds_cache = &(d->group->m_dds_cache);
2158 QGLDDSCache::const_iterator it = dds_cache->constFind(fileName);
2159 if (it != dds_cache->constEnd()) {
2160 glBindTexture(GL_TEXTURE_2D, it.value());
2161 return it.value();
2162 }
2163
2164 QGLTexture texture(this);
2165 QSize size = texture.bindCompressedTexture(fileName);
2166 if (!size.isValid())
2167 return 0;
2168
2169 dds_cache->insert(fileName, texture.id);
2170 return texture.id;
2171}
2172
2173static inline QRgb qt_gl_convertToGLFormatHelper(QRgb src_pixel, GLenum texture_format)
2174{
2175 if (texture_format == GL_BGRA) {
2176 if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
2177 return ((src_pixel << 24) & 0xff000000)
2178 | ((src_pixel >> 24) & 0x000000ff)
2179 | ((src_pixel << 8) & 0x00ff0000)
2180 | ((src_pixel >> 8) & 0x0000ff00);
2181 } else {
2182 return src_pixel;
2183 }
2184 } else { // GL_RGBA
2185 if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
2186 return (src_pixel << 8) | ((src_pixel >> 24) & 0xff);
2187 } else {
2188 return ((src_pixel << 16) & 0xff0000)
2189 | ((src_pixel >> 16) & 0xff)
2190 | (src_pixel & 0xff00ff00);
2191 }
2192 }
2193}
2194
2195QRgb qt_gl_convertToGLFormat(QRgb src_pixel, GLenum texture_format)
2196{
2197 return qt_gl_convertToGLFormatHelper(src_pixel, texture_format);
2198}
2199
2200static void convertToGLFormatHelper(QImage &dst, const QImage &img, GLenum texture_format)
2201{
2202 Q_ASSERT(dst.depth() == 32);
2203 Q_ASSERT(img.depth() == 32);
2204
2205 if (dst.size() != img.size()) {
2206 int target_width = dst.width();
2207 int target_height = dst.height();
2208 qreal sx = target_width / qreal(img.width());
2209 qreal sy = target_height / qreal(img.height());
2210
2211 quint32 *dest = (quint32 *) dst.scanLine(0); // NB! avoid detach here
2212 uchar *srcPixels = (uchar *) img.scanLine(img.height() - 1);
2213 int sbpl = img.bytesPerLine();
2214 int dbpl = dst.bytesPerLine();
2215
2216 int ix = int(0x00010000 / sx);
2217 int iy = int(0x00010000 / sy);
2218
2219 quint32 basex = int(0.5 * ix);
2220 quint32 srcy = int(0.5 * iy);
2221
2222 // scale, swizzle and mirror in one loop
2223 while (target_height--) {
2224 const uint *src = (const quint32 *) (srcPixels - (srcy >> 16) * sbpl);
2225 int srcx = basex;
2226 for (int x=0; x<target_width; ++x) {
2227 dest[x] = qt_gl_convertToGLFormatHelper(src[srcx >> 16], texture_format);
2228 srcx += ix;
2229 }
2230 dest = (quint32 *)(((uchar *) dest) + dbpl);
2231 srcy += iy;
2232 }
2233 } else {
2234 const int width = img.width();
2235 const int height = img.height();
2236 const uint *p = (const uint*) img.scanLine(img.height() - 1);
2237 uint *q = (uint*) dst.scanLine(0);
2238
2239 if (texture_format == GL_BGRA) {
2240 if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
2241 // mirror + swizzle
2242 for (int i=0; i < height; ++i) {
2243 const uint *end = p + width;
2244 while (p < end) {
2245 *q = ((*p << 24) & 0xff000000)
2246 | ((*p >> 24) & 0x000000ff)
2247 | ((*p << 8) & 0x00ff0000)
2248 | ((*p >> 8) & 0x0000ff00);
2249 p++;
2250 q++;
2251 }
2252 p -= 2 * width;
2253 }
2254 } else {
2255 const uint bytesPerLine = img.bytesPerLine();
2256 for (int i=0; i < height; ++i) {
2257 memcpy(q, p, bytesPerLine);
2258 q += width;
2259 p -= width;
2260 }
2261 }
2262 } else {
2263 if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
2264 for (int i=0; i < height; ++i) {
2265 const uint *end = p + width;
2266 while (p < end) {
2267 *q = (*p << 8) | ((*p >> 24) & 0xff);
2268 p++;
2269 q++;
2270 }
2271 p -= 2 * width;
2272 }
2273 } else {
2274 for (int i=0; i < height; ++i) {
2275 const uint *end = p + width;
2276 while (p < end) {
2277 *q = ((*p << 16) & 0xff0000) | ((*p >> 16) & 0xff) | (*p & 0xff00ff00);
2278 p++;
2279 q++;
2280 }
2281 p -= 2 * width;
2282 }
2283 }
2284 }
2285 }
2286}
2287
2288#if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)
2289QGLExtensionFuncs& QGLContextPrivate::extensionFuncs(const QGLContext *)
2290{
2291 return qt_extensionFuncs;
2292}
2293#endif
2294
2295QImage QGLContextPrivate::convertToGLFormat(const QImage &image, bool force_premul,
2296 GLenum texture_format)
2297{
2298 QImage::Format target_format = image.format();
2299 if (force_premul || image.format() != QImage::Format_ARGB32)
2300 target_format = QImage::Format_ARGB32_Premultiplied;
2301
2302 QImage result(image.width(), image.height(), target_format);
2303 convertToGLFormatHelper(result, image.convertToFormat(target_format), texture_format);
2304 return result;
2305}
2306
2307/*! \internal */
2308QGLTexture *QGLContextPrivate::bindTexture(const QImage &image, GLenum target, GLint format,
2309 QGLContext::BindOptions options)
2310{
2311 Q_Q(QGLContext);
2312
2313 const qint64 key = image.cacheKey();
2314 QGLTexture *texture = textureCacheLookup(key, target);
2315 if (texture) {
2316 if (image.paintingActive()) {
2317 // A QPainter is active on the image - take the safe route and replace the texture.
2318 q->deleteTexture(texture->id);
2319 texture = 0;
2320 } else {
2321 glBindTexture(target, texture->id);
2322 return texture;
2323 }
2324 }
2325
2326 if (!texture)
2327 texture = bindTexture(image, target, format, key, options);
2328 // NOTE: bindTexture(const QImage&, GLenum, GLint, const qint64, bool) should never return null
2329 Q_ASSERT(texture);
2330
2331 // Enable the cleanup hooks for this image so that the texture cache entry is removed when the
2332 // image gets deleted:
2333 QImagePixmapCleanupHooks::enableCleanupHooks(image);
2334
2335 return texture;
2336}
2337
2338// #define QGL_BIND_TEXTURE_DEBUG
2339
2340// map from Qt's ARGB endianness-dependent format to GL's big-endian RGBA layout
2341static inline void qgl_byteSwapImage(QImage &img, GLenum pixel_type)
2342{
2343 const int width = img.width();
2344 const int height = img.height();
2345
2346 if (pixel_type == GL_UNSIGNED_INT_8_8_8_8_REV
2347 || (pixel_type == GL_UNSIGNED_BYTE && QSysInfo::ByteOrder == QSysInfo::LittleEndian))
2348 {
2349 for (int i = 0; i < height; ++i) {
2350 uint *p = (uint *) img.scanLine(i);
2351 for (int x = 0; x < width; ++x)
2352 p[x] = ((p[x] << 16) & 0xff0000) | ((p[x] >> 16) & 0xff) | (p[x] & 0xff00ff00);
2353 }
2354 } else {
2355 for (int i = 0; i < height; ++i) {
2356 uint *p = (uint *) img.scanLine(i);
2357 for (int x = 0; x < width; ++x)
2358 p[x] = (p[x] << 8) | ((p[x] >> 24) & 0xff);
2359 }
2360 }
2361}
2362
2363QGLTexture* QGLContextPrivate::bindTexture(const QImage &image, GLenum target, GLint internalFormat,
2364 const qint64 key, QGLContext::BindOptions options)
2365{
2366 Q_Q(QGLContext);
2367
2368#ifdef QGL_BIND_TEXTURE_DEBUG
2369 printf("QGLContextPrivate::bindTexture(), imageSize=(%d,%d), internalFormat =0x%x, options=%x, key=%llx\n",
2370 image.width(), image.height(), internalFormat, int(options), key);
2371 QTime time;
2372 time.start();
2373#endif
2374
2375#ifndef QT_NO_DEBUG
2376 // Reset the gl error stack...git
2377 while (glGetError() != GL_NO_ERROR) ;
2378#endif
2379
2380 // Scale the pixmap if needed. GL textures needs to have the
2381 // dimensions 2^n+2(border) x 2^m+2(border), unless we're using GL
2382 // 2.0 or use the GL_TEXTURE_RECTANGLE texture target
2383 int tx_w = qt_next_power_of_two(image.width());
2384 int tx_h = qt_next_power_of_two(image.height());
2385
2386 QImage img = image;
2387
2388 if (!(QGLExtensions::glExtensions() & QGLExtensions::NPOTTextures)
2389 && !(QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_ES_Version_2_0)
2390 && (target == GL_TEXTURE_2D && (tx_w != image.width() || tx_h != image.height())))
2391 {
2392 img = img.scaled(tx_w, tx_h);
2393#ifdef QGL_BIND_TEXTURE_DEBUG
2394 printf(" - upscaled to %dx%d (%d ms)\n", tx_w, tx_h, time.elapsed());
2395
2396#endif
2397 }
2398
2399 GLuint filtering = options & QGLContext::LinearFilteringBindOption ? GL_LINEAR : GL_NEAREST;
2400
2401 GLuint tx_id;
2402 glGenTextures(1, &tx_id);
2403 glBindTexture(target, tx_id);
2404 glTexParameterf(target, GL_TEXTURE_MAG_FILTER, filtering);
2405
2406#if defined(QT_OPENGL_ES_2)
2407 bool genMipmap = false;
2408#endif
2409 if (glFormat.directRendering()
2410 && (QGLExtensions::glExtensions() & QGLExtensions::GenerateMipmap)
2411 && target == GL_TEXTURE_2D
2412 && (options & QGLContext::MipmapBindOption))
2413 {
2414#if !defined(QT_OPENGL_ES_2)
2415 glHint(GL_GENERATE_MIPMAP_HINT_SGIS, GL_NICEST);
2416#ifndef QT_OPENGL_ES
2417 glTexParameteri(target, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
2418#else
2419 glTexParameterf(target, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
2420#endif
2421#else
2422 glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST);
2423 genMipmap = true;
2424#endif
2425 glTexParameterf(target, GL_TEXTURE_MIN_FILTER, options & QGLContext::LinearFilteringBindOption
2426 ? GL_LINEAR_MIPMAP_LINEAR : GL_NEAREST_MIPMAP_NEAREST);
2427#ifdef QGL_BIND_TEXTURE_DEBUG
2428 printf(" - generating mipmaps (%d ms)\n", time.elapsed());
2429#endif
2430 } else {
2431 glTexParameterf(target, GL_TEXTURE_MIN_FILTER, filtering);
2432 }
2433
2434 QImage::Format target_format = img.format();
2435 bool premul = options & QGLContext::PremultipliedAlphaBindOption;
2436 GLenum externalFormat;
2437 GLuint pixel_type;
2438 if (QGLExtensions::glExtensions() & QGLExtensions::BGRATextureFormat) {
2439 externalFormat = GL_BGRA;
2440 if (QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_1_2)
2441 pixel_type = GL_UNSIGNED_INT_8_8_8_8_REV;
2442 else
2443 pixel_type = GL_UNSIGNED_BYTE;
2444 } else {
2445 externalFormat = GL_RGBA;
2446 pixel_type = GL_UNSIGNED_BYTE;
2447 }
2448
2449 switch (target_format) {
2450 case QImage::Format_ARGB32:
2451 if (premul) {
2452 img = img.convertToFormat(target_format = QImage::Format_ARGB32_Premultiplied);
2453#ifdef QGL_BIND_TEXTURE_DEBUG
2454 printf(" - converted ARGB32 -> ARGB32_Premultiplied (%d ms) \n", time.elapsed());
2455#endif
2456 }
2457 break;
2458 case QImage::Format_ARGB32_Premultiplied:
2459 if (!premul) {
2460 img = img.convertToFormat(target_format = QImage::Format_ARGB32);
2461#ifdef QGL_BIND_TEXTURE_DEBUG
2462 printf(" - converted ARGB32_Premultiplied -> ARGB32 (%d ms)\n", time.elapsed());
2463#endif
2464 }
2465 break;
2466 case QImage::Format_RGB16:
2467 pixel_type = GL_UNSIGNED_SHORT_5_6_5;
2468 externalFormat = GL_RGB;
2469 internalFormat = GL_RGB;
2470 break;
2471 case QImage::Format_RGB32:
2472 break;
2473 default:
2474 if (img.hasAlphaChannel()) {
2475 img = img.convertToFormat(premul
2476 ? QImage::Format_ARGB32_Premultiplied
2477 : QImage::Format_ARGB32);
2478#ifdef QGL_BIND_TEXTURE_DEBUG
2479 printf(" - converted to 32-bit alpha format (%d ms)\n", time.elapsed());
2480#endif
2481 } else {
2482 img = img.convertToFormat(QImage::Format_RGB32);
2483#ifdef QGL_BIND_TEXTURE_DEBUG
2484 printf(" - converted to 32-bit (%d ms)\n", time.elapsed());
2485#endif
2486 }
2487 }
2488
2489 if (options & QGLContext::InvertedYBindOption) {
2490 if (img.isDetached()) {
2491 int ipl = img.bytesPerLine() / 4;
2492 int h = img.height();
2493 for (int y=0; y<h/2; ++y) {
2494 int *a = (int *) img.scanLine(y);
2495 int *b = (int *) img.scanLine(h - y - 1);
2496 for (int x=0; x<ipl; ++x)
2497 qSwap(a[x], b[x]);
2498 }
2499 } else {
2500 // Create a new image and copy across. If we use the
2501 // above in-place code then a full copy of the image is
2502 // made before the lines are swapped, which processes the
2503 // data twice. This version should only do it once.
2504 img = img.mirrored();
2505 }
2506#ifdef QGL_BIND_TEXTURE_DEBUG
2507 printf(" - flipped bits over y (%d ms)\n", time.elapsed());
2508#endif
2509 }
2510
2511 if (externalFormat == GL_RGBA) {
2512 // The only case where we end up with a depth different from
2513 // 32 in the switch above is for the RGB16 case, where we set
2514 // the format to GL_RGB
2515 Q_ASSERT(img.depth() == 32);
2516 qgl_byteSwapImage(img, pixel_type);
2517#ifdef QGL_BIND_TEXTURE_DEBUG
2518 printf(" - did byte swapping (%d ms)\n", time.elapsed());
2519#endif
2520 }
2521#ifdef QT_OPENGL_ES
2522 // OpenGL/ES requires that the internal and external formats be
2523 // identical.
2524 internalFormat = externalFormat;
2525#endif
2526#ifdef QGL_BIND_TEXTURE_DEBUG
2527 printf(" - uploading, image.format=%d, externalFormat=0x%x, internalFormat=0x%x, pixel_type=0x%x\n",
2528 img.format(), externalFormat, internalFormat, pixel_type);
2529#endif
2530
2531 const QImage &constRef = img; // to avoid detach in bits()...
2532 glTexImage2D(target, 0, internalFormat, img.width(), img.height(), 0, externalFormat,
2533 pixel_type, constRef.bits());
2534#if defined(QT_OPENGL_ES_2)
2535 if (genMipmap)
2536 glGenerateMipmap(target);
2537#endif
2538#ifndef QT_NO_DEBUG
2539 GLenum error = glGetError();
2540 if (error != GL_NO_ERROR) {
2541 qWarning(" - texture upload failed, error code 0x%x, enum: %d (%x)\n", error, target, target);
2542 }
2543#endif
2544
2545#ifdef QGL_BIND_TEXTURE_DEBUG
2546 static int totalUploadTime = 0;
2547 totalUploadTime += time.elapsed();
2548 printf(" - upload done in %d ms, (accumulated: %d ms)\n", time.elapsed(), totalUploadTime);
2549#endif
2550
2551
2552 // this assumes the size of a texture is always smaller than the max cache size
2553 int cost = img.width()*img.height()*4/1024;
2554 QGLTexture *texture = new QGLTexture(q, tx_id, target, options);
2555 QGLTextureCache::instance()->insert(q, key, texture, cost);
2556
2557 return texture;
2558}
2559
2560QGLTexture *QGLContextPrivate::textureCacheLookup(const qint64 key, GLenum target)
2561{
2562 Q_Q(QGLContext);
2563 QGLTexture *texture = QGLTextureCache::instance()->getTexture(q, key);
2564 if (texture && texture->target == target
2565 && (texture->context == q || QGLContext::areSharing(q, texture->context)))
2566 {
2567 return texture;
2568 }
2569 return 0;
2570}
2571
2572
2573/*! \internal */
2574QGLTexture *QGLContextPrivate::bindTexture(const QPixmap &pixmap, GLenum target, GLint format, QGLContext::BindOptions options)
2575{
2576 Q_Q(QGLContext);
2577 QPixmapData *pd = pixmap.pixmapData();
2578#if !defined(QT_OPENGL_ES_1)
2579 if (target == GL_TEXTURE_2D && pd->classId() == QPixmapData::OpenGLClass) {
2580 const QGLPixmapData *data = static_cast<const QGLPixmapData *>(pd);
2581
2582 if (data->isValidContext(q)) {
2583 data->bind();
2584 return data->texture();
2585 }
2586 }
2587#else
2588 Q_UNUSED(pd);
2589#endif
2590
2591 const qint64 key = pixmap.cacheKey();
2592 QGLTexture *texture = textureCacheLookup(key, target);
2593 if (texture) {
2594 if (pixmap.paintingActive()) {
2595 // A QPainter is active on the pixmap - take the safe route and replace the texture.
2596 q->deleteTexture(texture->id);
2597 texture = 0;
2598 } else {
2599 glBindTexture(target, texture->id);
2600 return texture;
2601 }
2602 }
2603
2604#if defined(Q_WS_X11)
2605 // Try to use texture_from_pixmap
2606 const QX11Info *xinfo = qt_x11Info(paintDevice);
2607 if (pd->classId() == QPixmapData::X11Class && pd->pixelType() == QPixmapData::PixmapType
2608 && xinfo && xinfo->screen() == pixmap.x11Info().screen()
2609 && target == GL_TEXTURE_2D)
2610 {
2611 if (!workaround_brokenTextureFromPixmap_init) {
2612 workaround_brokenTextureFromPixmap_init = true;
2613
2614 const QByteArray versionString(reinterpret_cast<const char*>(glGetString(GL_VERSION)));
2615 const int pos = versionString.indexOf("NVIDIA ");
2616
2617 if (pos >= 0) {
2618 const QByteArray nvidiaVersionString = versionString.mid(pos + strlen("NVIDIA "));
2619
2620 if (nvidiaVersionString.startsWith("195") || nvidiaVersionString.startsWith("256"))
2621 workaround_brokenTextureFromPixmap = true;
2622 }
2623 }
2624
2625 if (!workaround_brokenTextureFromPixmap) {
2626 texture = bindTextureFromNativePixmap(const_cast<QPixmap*>(&pixmap), key, options);
2627 if (texture) {
2628 texture->options |= QGLContext::MemoryManagedBindOption;
2629 texture->boundPixmap = pd;
2630 boundPixmaps.insert(pd, QPixmap(pixmap));
2631 }
2632 }
2633 }
2634#endif
2635
2636 if (!texture) {
2637 QImage image = pixmap.toImage();
2638 // If the system depth is 16 and the pixmap doesn't have an alpha channel
2639 // then we convert it to RGB16 in the hope that it gets uploaded as a 16
2640 // bit texture which is much faster to access than a 32-bit one.
2641 if (pixmap.depth() == 16 && !image.hasAlphaChannel() )
2642 image = image.convertToFormat(QImage::Format_RGB16);
2643 texture = bindTexture(image, target, format, key, options);
2644 }
2645 // NOTE: bindTexture(const QImage&, GLenum, GLint, const qint64, bool) should never return null
2646 Q_ASSERT(texture);
2647
2648 if (texture->id > 0)
2649 QImagePixmapCleanupHooks::enableCleanupHooks(pixmap);
2650
2651 return texture;
2652}
2653
2654/*! \internal */
2655int QGLContextPrivate::maxTextureSize()
2656{
2657 if (max_texture_size != -1)
2658 return max_texture_size;
2659
2660 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size);
2661
2662#if defined(QT_OPENGL_ES)
2663 return max_texture_size;
2664#else
2665 GLenum proxy = GL_PROXY_TEXTURE_2D;
2666
2667 GLint size;
2668 GLint next = 64;
2669 glTexImage2D(proxy, 0, GL_RGBA, next, next, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
2670 glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &size);
2671 if (size == 0) {
2672 return max_texture_size;
2673 }
2674 do {
2675 size = next;
2676 next = size * 2;
2677
2678 if (next > max_texture_size)
2679 break;
2680 glTexImage2D(proxy, 0, GL_RGBA, next, next, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
2681 glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &next);
2682 } while (next > size);
2683
2684 max_texture_size = size;
2685 return max_texture_size;
2686#endif
2687}
2688
2689/*!
2690 Generates and binds a 2D GL texture to the current context, based
2691 on \a image. The generated texture id is returned and can be used in
2692 later \c glBindTexture() calls.
2693
2694 \overload
2695*/
2696GLuint QGLContext::bindTexture(const QImage &image, GLenum target, GLint format)
2697{
2698 if (image.isNull())
2699 return 0;
2700
2701 Q_D(QGLContext);
2702 QGLTexture *texture = d->bindTexture(image, target, format, DefaultBindOption);
2703 return texture->id;
2704}
2705
2706/*!
2707 \since 4.6
2708
2709 Generates and binds a 2D GL texture to the current context, based
2710 on \a image. The generated texture id is returned and can be used
2711 in later \c glBindTexture() calls.
2712
2713 The \a target parameter specifies the texture target. The default
2714 target is \c GL_TEXTURE_2D.
2715
2716 The \a format parameter sets the internal format for the
2717 texture. The default format is \c GL_RGBA.
2718
2719 The binding \a options are a set of options used to decide how to
2720 bind the texture to the context.
2721
2722 The texture that is generated is cached, so multiple calls to
2723 bindTexture() with the same QImage will return the same texture
2724 id.
2725
2726 Note that we assume default values for the glPixelStore() and
2727 glPixelTransfer() parameters.
2728
2729 \sa deleteTexture()
2730*/
2731GLuint QGLContext::bindTexture(const QImage &image, GLenum target, GLint format, BindOptions options)
2732{
2733 if (image.isNull())
2734 return 0;
2735
2736 Q_D(QGLContext);
2737 QGLTexture *texture = d->bindTexture(image, target, format, options);
2738 return texture->id;
2739}
2740
2741#ifdef Q_MAC_COMPAT_GL_FUNCTIONS
2742/*! \internal */
2743GLuint QGLContext::bindTexture(const QImage &image, QMacCompatGLenum target, QMacCompatGLint format)
2744{
2745 if (image.isNull())
2746 return 0;
2747
2748 Q_D(QGLContext);
2749 QGLTexture *texture = d->bindTexture(image, GLenum(target), GLint(format), DefaultBindOption);
2750 return texture->id;
2751}
2752
2753/*! \internal */
2754GLuint QGLContext::bindTexture(const QImage &image, QMacCompatGLenum target, QMacCompatGLint format,
2755 BindOptions options)
2756{
2757 if (image.isNull())
2758 return 0;
2759
2760 Q_D(QGLContext);
2761 QGLTexture *texture = d->bindTexture(image, GLenum(target), GLint(format), options);
2762 return texture->id;
2763}
2764#endif
2765
2766/*! \overload
2767
2768 Generates and binds a 2D GL texture based on \a pixmap.
2769*/
2770GLuint QGLContext::bindTexture(const QPixmap &pixmap, GLenum target, GLint format)
2771{
2772 if (pixmap.isNull())
2773 return 0;
2774
2775 Q_D(QGLContext);
2776 QGLTexture *texture = d->bindTexture(pixmap, target, format, DefaultBindOption);
2777 return texture->id;
2778}
2779
2780/*!
2781 \overload
2782 \since 4.6
2783
2784 Generates and binds a 2D GL texture to the current context, based
2785 on \a pixmap.
2786*/
2787GLuint QGLContext::bindTexture(const QPixmap &pixmap, GLenum target, GLint format, BindOptions options)
2788{
2789 if (pixmap.isNull())
2790 return 0;
2791
2792 Q_D(QGLContext);
2793 QGLTexture *texture = d->bindTexture(pixmap, target, format, options);
2794 return texture->id;
2795}
2796
2797#ifdef Q_MAC_COMPAT_GL_FUNCTIONS
2798/*! \internal */
2799GLuint QGLContext::bindTexture(const QPixmap &pixmap, QMacCompatGLenum target, QMacCompatGLint format)
2800{
2801 if (pixmap.isNull())
2802 return 0;
2803
2804 Q_D(QGLContext);
2805 QGLTexture *texture = d->bindTexture(pixmap, GLenum(target), GLint(format), DefaultBindOption);
2806 return texture->id;
2807}
2808/*! \internal */
2809GLuint QGLContext::bindTexture(const QPixmap &pixmap, QMacCompatGLenum target, QMacCompatGLint format,
2810 BindOptions options)
2811{
2812 if (pixmap.isNull())
2813 return 0;
2814
2815 Q_D(QGLContext);
2816 QGLTexture *texture = d->bindTexture(pixmap, GLenum(target), GLint(format), options);
2817 return texture->id;
2818}