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