src/opengl/qgl.cpp
changeset 30 5dc02b23752f
parent 23 89e065397ea6
child 33 3e2da88830cd
--- a/src/opengl/qgl.cpp	Wed Jun 23 19:07:03 2010 +0300
+++ b/src/opengl/qgl.cpp	Tue Jul 06 15:10:48 2010 +0300
@@ -49,7 +49,7 @@
 #include "private/qpixmap_x11_p.h"
 #define INT32 dummy_INT32
 #define INT8 dummy_INT8
-#if !defined(QT_OPENGL_ES)
+#ifdef QT_NO_EGL
 # include <GL/glx.h>
 #endif
 #undef INT32
@@ -67,7 +67,7 @@
 #include "qimage.h"
 #include "qgl_p.h"
 
-#if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
+#if !defined(QT_OPENGL_ES_1)
 #include "gl2paintengineex/qpaintengineex_opengl2_p.h"
 #endif
 
@@ -95,11 +95,6 @@
 
 QT_BEGIN_NAMESPACE
 
-#ifdef QT_OPENGL_ES_1_CL
-#include "qgl_cl_p.h"
-#endif
-
-
 #if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS)
 QGLExtensionFuncs QGLContextPrivate::qt_extensionFuncs;
 #endif
@@ -226,6 +221,9 @@
     \value DirectRendering   Specifies that the context is used for direct rendering to a display.
     \value HasOverlay        Enables the use of an overlay.
     \value SampleBuffers     Enables the use of sample buffers.
+    \value DeprecatedFunctions      Enables the use of deprecated functionality for OpenGL 3.x
+                                    contexts. A context with deprecated functionality enabled is
+                                    called a full context in the OpenGL specification.
     \value SingleBuffer      Specifies the use of a single buffer, as opposed to double buffers.
     \value NoDepthBuffer     Disables the use of a depth buffer.
     \value ColorIndex        Specifies that the context should use a color index as its pixel format.
@@ -236,6 +234,9 @@
     \value IndirectRendering Specifies that the context is used for indirect rendering to a buffer.
     \value NoOverlay         Disables the use of an overlay.
     \value NoSampleBuffers   Disables the use of sample buffers.
+    \value NoDeprecatedFunctions    Disables the use of deprecated functionality for OpenGL 3.x
+                                    contexts. A context with deprecated functionality disabled is
+                                    called a forward compatible context in the OpenGL specification.
 
     \sa {Sample Buffers Example}
 */
@@ -765,6 +766,7 @@
         return;
     }
     d->numSamples = numSamples;
+    setSampleBuffers(numSamples > 0);
 }
 
 /*!
@@ -903,6 +905,7 @@
         return;
     }
     d->depthSize = size;
+    setDepth(size > 0);
 }
 
 /*!
@@ -1016,7 +1019,7 @@
         return;
     }
     d->alphaSize = size;
-    setOption(QGL::AlphaChannel);
+    setAlpha(size > 0);
 }
 
 /*!
@@ -1043,6 +1046,7 @@
         return;
     }
     d->accumSize = size;
+    setAccum(size > 0);
 }
 
 /*!
@@ -1068,6 +1072,7 @@
         return;
     }
     d->stencilSize = size;
+    setStencil(size > 0);
 }
 
 /*!
@@ -1081,6 +1086,90 @@
 }
 
 /*!
+    \since 4.7
+
+    Set the OpenGL version to the \a major and \a minor numbers. If a
+    context compatible with the requested OpenGL version cannot be
+    created, a context compatible with version 1.x is created instead.
+
+    \sa majorVersion(), minorVersion()
+*/
+void QGLFormat::setVersion(int major, int minor)
+{
+    if (major < 1 || minor < 0) {
+        qWarning("QGLFormat::setVersion: Cannot set zero or negative version number %d.%d", major, minor);
+        return;
+    }
+    detach();
+    d->majorVersion = major;
+    d->minorVersion = minor;
+}
+
+/*!
+    \since 4.7
+
+    Returns the OpenGL major version.
+
+    \sa setVersion(), minorVersion()
+*/
+int QGLFormat::majorVersion() const
+{
+    return d->majorVersion;
+}
+
+/*!
+    \since 4.7
+
+    Returns the OpenGL minor version.
+
+    \sa setVersion(), majorVersion()
+*/
+int QGLFormat::minorVersion() const
+{
+    return d->minorVersion;
+}
+
+/*!
+    \enum QGLFormat::OpenGLContextProfile
+    \since 4.7
+
+    This enum describes the OpenGL context profiles that can be
+    specified for contexts implementing OpenGL version 3.2 or
+    higher. These profiles are different from OpenGL ES profiles.
+
+    \value NoProfile            OpenGL version is lower than 3.2.
+    \value CoreProfile          Functionality deprecated in OpenGL version 3.0 is not available.
+    \value CompatibilityProfile Functionality from earlier OpenGL versions is available.
+*/
+
+/*!
+    \since 4.7
+
+    Set the OpenGL context profile to \a profile. The \a profile is
+    ignored if the requested OpenGL version is less than 3.2.
+
+    \sa profile()
+*/
+void QGLFormat::setProfile(OpenGLContextProfile profile)
+{
+    detach();
+    d->profile = profile;
+}
+
+/*!
+    \since 4.7
+
+    Returns the OpenGL context profile.
+
+    \sa setProfile()
+*/
+QGLFormat::OpenGLContextProfile QGLFormat::profile() const
+{
+    return d->profile;
+}
+
+
+/*!
     \fn bool QGLFormat::hasOpenGL()
 
     Returns true if the window system has any OpenGL support;
@@ -1116,25 +1205,21 @@
                     if (parts[2].startsWith(QLatin1String("1.1")))
                         versionFlags |= QGLFormat::OpenGL_ES_Common_Version_1_1 |
                                         QGLFormat::OpenGL_ES_CommonLite_Version_1_1;
-                }
-                else {
+                } else {
                     // Not -CM, must be CL, CommonLite
                     versionFlags |= QGLFormat::OpenGL_ES_CommonLite_Version_1_0;
                     if (parts[2].startsWith(QLatin1String("1.1")))
                         versionFlags |= QGLFormat::OpenGL_ES_CommonLite_Version_1_1;
                 }
-            }
-            else {
+            } else {
                 // OpenGL ES version 2.0 or higher
                 versionFlags |= QGLFormat::OpenGL_ES_Version_2_0;
             }
-        }
-        else {
+        } else {
             // if < 3 parts to the name, it is an unrecognised OpenGL ES
             qWarning("Unrecognised OpenGL ES version");
         }
-    }
-    else {
+    } else {
         // not ES, regular OpenGL, the version numbers are first in the string
         if (versionString.startsWith(QLatin1String("1."))) {
             switch (versionString[2].toAscii()) {
@@ -1151,30 +1236,48 @@
             default:
                 break;
             }
-        }
-        else if (versionString.startsWith(QLatin1String("2."))) {
+        } else if (versionString.startsWith(QLatin1String("2."))) {
             versionFlags |= QGLFormat::OpenGL_Version_1_1 |
                             QGLFormat::OpenGL_Version_1_2 |
                             QGLFormat::OpenGL_Version_1_3 |
                             QGLFormat::OpenGL_Version_1_4 |
                             QGLFormat::OpenGL_Version_1_5 |
                             QGLFormat::OpenGL_Version_2_0;
-            QString minorVersion = versionString.section(QLatin1Char(' '), 0, 0).section(QLatin1Char('.'), 1, 1);
-            if (minorVersion == QChar(QLatin1Char('1')))
+            if (versionString[2].toAscii() == '1')
                 versionFlags |= QGLFormat::OpenGL_Version_2_1;
+        } else if (versionString.startsWith(QLatin1String("3."))) {
+            versionFlags |= QGLFormat::OpenGL_Version_1_1 |
+                            QGLFormat::OpenGL_Version_1_2 |
+                            QGLFormat::OpenGL_Version_1_3 |
+                            QGLFormat::OpenGL_Version_1_4 |
+                            QGLFormat::OpenGL_Version_1_5 |
+                            QGLFormat::OpenGL_Version_2_0 |
+                            QGLFormat::OpenGL_Version_2_1 |
+                            QGLFormat::OpenGL_Version_3_0;
+            switch (versionString[2].toAscii()) {
+            case '2':
+                versionFlags |= QGLFormat::OpenGL_Version_3_2;
+            case '1':
+                versionFlags |= QGLFormat::OpenGL_Version_3_1;
+            case '0':
+                break;
+            default:
+                versionFlags |= QGLFormat::OpenGL_Version_3_1 |
+                                QGLFormat::OpenGL_Version_3_2;
+                break;
+            }
+        } else {
+            versionFlags |= QGLFormat::OpenGL_Version_1_1 |
+                            QGLFormat::OpenGL_Version_1_2 |
+                            QGLFormat::OpenGL_Version_1_3 |
+                            QGLFormat::OpenGL_Version_1_4 |
+                            QGLFormat::OpenGL_Version_1_5 |
+                            QGLFormat::OpenGL_Version_2_0 |
+                            QGLFormat::OpenGL_Version_2_1 |
+                            QGLFormat::OpenGL_Version_3_0 |
+                            QGLFormat::OpenGL_Version_3_1 |
+                            QGLFormat::OpenGL_Version_3_2;
         }
-        else if (versionString.startsWith(QLatin1String("3."))) {
-         versionFlags |= QGLFormat::OpenGL_Version_1_1 |
-                         QGLFormat::OpenGL_Version_1_2 |
-                         QGLFormat::OpenGL_Version_1_3 |
-                         QGLFormat::OpenGL_Version_1_4 |
-                         QGLFormat::OpenGL_Version_1_5 |
-                         QGLFormat::OpenGL_Version_2_0 |
-                         QGLFormat::OpenGL_Version_2_1 |
-                         QGLFormat::OpenGL_Version_3_0;
-        }
-        else
-            qWarning("Unrecognised OpenGL version");
     }
     return versionFlags;
 }
@@ -1206,6 +1309,12 @@
 
     \value OpenGL_Version_3_0  OpenGL version 3.0 or higher is present.
 
+    \value OpenGL_Version_3_1  OpenGL version 3.1 or higher is present.
+    Note that OpenGL version 3.1 or higher does not necessarily support all the features of
+    version 3.0 and lower.
+
+    \value OpenGL_Version_3_2  OpenGL version 3.2 or higher is present.
+
     \value OpenGL_ES_CommonLite_Version_1_0  OpenGL ES version 1.0 Common Lite or higher is present.
 
     \value OpenGL_ES_Common_Version_1_0  OpenGL ES version 1.0 Common or higher is present.
@@ -1377,14 +1486,20 @@
 
 bool operator==(const QGLFormat& a, const QGLFormat& b)
 {
-    return (int) a.d->opts == (int) b.d->opts && a.d->pln == b.d->pln && a.d->alphaSize == b.d->alphaSize
-        && a.d->accumSize == b.d->accumSize && a.d->stencilSize == b.d->stencilSize
+    return (a.d == b.d) || ((int) a.d->opts == (int) b.d->opts
+        && a.d->pln == b.d->pln
+        && a.d->alphaSize == b.d->alphaSize
+        && a.d->accumSize == b.d->accumSize
+        && a.d->stencilSize == b.d->stencilSize
         && a.d->depthSize == b.d->depthSize
         && a.d->redSize == b.d->redSize
         && a.d->greenSize == b.d->greenSize
         && a.d->blueSize == b.d->blueSize
         && a.d->numSamples == b.d->numSamples
-        && a.d->swapInterval == b.d->swapInterval;
+        && a.d->swapInterval == b.d->swapInterval
+        && a.d->majorVersion == b.d->majorVersion
+        && a.d->minorVersion == b.d->minorVersion
+        && a.d->profile == b.d->profile);
 }
 
 
@@ -1480,7 +1595,8 @@
 #  endif
     vi = 0;
 #endif
-#if defined(QT_OPENGL_ES)
+#ifndef QT_NO_EGL
+    ownsEglContext = false;
     eglContext = 0;
     eglSurface = EGL_NO_SURFACE;
 #endif
@@ -1496,6 +1612,9 @@
     current_fbo = 0;
     default_fbo = 0;
     active_engine = 0;
+    workaround_needsFullClearOnEveryFrame = false;
+    workaround_brokenFBOReadBack = false;
+    workaroundsCached = false;
     for (int i = 0; i < QT_GL_VERTEX_ARRAY_TRACKED_COUNT; ++i)
         vertexAttributeArraysEnabledState[i] = false;
 }
@@ -1566,7 +1685,7 @@
     QImage img(size, alpha_format ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32);
     int w = size.width();
     int h = size.height();
-#if !defined(QT_OPENGL_ES_2) && !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
+#if !defined(QT_OPENGL_ES_2) && !defined(QT_OPENGL_ES_1)
     //### glGetTexImage not in GL ES 2.0, need to do something else here!
     glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, img.bits());
 #endif
@@ -1594,14 +1713,12 @@
 extern Q_GUI_EXPORT _qt_pixmap_cleanup_hook_64 qt_pixmap_cleanup_hook_64;
 extern Q_GUI_EXPORT _qt_image_cleanup_hook_64 qt_image_cleanup_hook_64;
 
-static QGLTextureCache *qt_gl_texture_cache = 0;
+
+Q_GLOBAL_STATIC(QGLTextureCache, qt_gl_texture_cache)
 
 QGLTextureCache::QGLTextureCache()
     : m_cache(64*1024) // cache ~64 MB worth of textures - this is not accurate though
 {
-    Q_ASSERT(qt_gl_texture_cache == 0);
-    qt_gl_texture_cache = this;
-
     QImagePixmapCleanupHooks::instance()->addPixmapDataModificationHook(cleanupTexturesForPixampData);
     QImagePixmapCleanupHooks::instance()->addPixmapDataDestructionHook(cleanupBeforePixmapDestruction);
     QImagePixmapCleanupHooks::instance()->addImageHook(cleanupTexturesForCacheKey);
@@ -1609,8 +1726,6 @@
 
 QGLTextureCache::~QGLTextureCache()
 {
-    qt_gl_texture_cache = 0;
-
     QImagePixmapCleanupHooks::instance()->removePixmapDataModificationHook(cleanupTexturesForPixampData);
     QImagePixmapCleanupHooks::instance()->removePixmapDataDestructionHook(cleanupBeforePixmapDestruction);
     QImagePixmapCleanupHooks::instance()->removeImageHook(cleanupTexturesForCacheKey);
@@ -1618,6 +1733,7 @@
 
 void QGLTextureCache::insert(QGLContext* ctx, qint64 key, QGLTexture* texture, int cost)
 {
+    QWriteLocker locker(&m_lock);
     if (m_cache.totalCost() + cost > m_cache.maxCost()) {
         // the cache is full - make an attempt to remove something
         const QList<qint64> keys = m_cache.keys();
@@ -1635,6 +1751,7 @@
 
 bool QGLTextureCache::remove(QGLContext* ctx, GLuint textureId)
 {
+    QWriteLocker locker(&m_lock);
     QList<qint64> keys = m_cache.keys();
     for (int i = 0; i < keys.size(); ++i) {
         QGLTexture *tex = m_cache.object(keys.at(i));
@@ -1649,6 +1766,7 @@
 
 void QGLTextureCache::removeContextTextures(QGLContext* ctx)
 {
+    QWriteLocker locker(&m_lock);
     QList<qint64> keys = m_cache.keys();
     for (int i = 0; i < keys.size(); ++i) {
         const qint64 &key = keys.at(i);
@@ -1657,25 +1775,14 @@
     }
 }
 
-QGLTextureCache* QGLTextureCache::instance()
-{
-    if (!qt_gl_texture_cache)
-        qt_gl_texture_cache = new QGLTextureCache;
-
-    return qt_gl_texture_cache;
-}
-
 /*
   a hook that removes textures from the cache when a pixmap/image
   is deref'ed
 */
 void QGLTextureCache::cleanupTexturesForCacheKey(qint64 cacheKey)
 {
-    // ### remove when the GL texture cache becomes thread-safe
-    if (qApp->thread() == QThread::currentThread()) {
-        instance()->remove(cacheKey);
-        Q_ASSERT(instance()->getTexture(cacheKey) == 0);
-    }
+    qt_gl_texture_cache()->remove(cacheKey);
+    Q_ASSERT(qt_gl_texture_cache()->getTexture(cacheKey) == 0);
 }
 
 
@@ -1697,10 +1804,9 @@
 #endif
 }
 
-void QGLTextureCache::deleteIfEmpty()
-{
-    if (instance()->size() == 0)
-        delete instance();
+QGLTextureCache *QGLTextureCache::instance()
+{
+    return qt_gl_texture_cache();
 }
 
 // DDS format structure
@@ -1866,7 +1972,6 @@
 {
     // remove any textures cached in this context
     QGLTextureCache::instance()->removeContextTextures(this);
-    QGLTextureCache::deleteIfEmpty(); // ### thread safety
 
     d_ptr->group->cleanupResources(this);
 
@@ -2126,8 +2231,8 @@
     Q_Q(QGLContext);
 
 #ifdef QGL_BIND_TEXTURE_DEBUG
-    printf("QGLContextPrivate::bindTexture(), imageSize=(%d,%d), internalFormat =0x%x, options=%x\n",
-           image.width(), image.height(), internalFormat, int(options));
+    printf("QGLContextPrivate::bindTexture(), imageSize=(%d,%d), internalFormat =0x%x, options=%x, key=%llx\n",
+           image.width(), image.height(), internalFormat, int(options), key);
     QTime time;
     time.start();
 #endif
@@ -2298,7 +2403,7 @@
 #ifndef QT_NO_DEBUG
     GLenum error = glGetError();
     if (error != GL_NO_ERROR) {
-        qWarning(" - texture upload failed, error code 0x%x\n", error);
+        qWarning(" - texture upload failed, error code 0x%x, enum: %d (%x)\n", error, target, target);
     }
 #endif
 
@@ -2335,7 +2440,7 @@
 {
     Q_Q(QGLContext);
     QPixmapData *pd = pixmap.pixmapData();
-#if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
+#if !defined(QT_OPENGL_ES_1)
     if (target == GL_TEXTURE_2D && pd->classId() == QPixmapData::OpenGLClass) {
         const QGLPixmapData *data = static_cast<const QGLPixmapData *>(pd);
 
@@ -2360,9 +2465,10 @@
     // Try to use texture_from_pixmap
     const QX11Info *xinfo = qt_x11Info(paintDevice);
     if (pd->classId() == QPixmapData::X11Class && pd->pixelType() == QPixmapData::PixmapType
-        && xinfo && xinfo->screen() == pixmap.x11Info().screen())
+        && xinfo && xinfo->screen() == pixmap.x11Info().screen()
+        && target == GL_TEXTURE_2D)
     {
-        texture = bindTextureFromNativePixmap(pd, key, options);
+        texture = bindTextureFromNativePixmap(const_cast<QPixmap*>(&pixmap), key, options);
         if (texture) {
             texture->options |= QGLContext::MemoryManagedBindOption;
             texture->boundPixmap = pd;
@@ -2371,8 +2477,15 @@
     }
 #endif
 
-    if (!texture)
-        texture = bindTexture(pixmap.toImage(), target, format, key, options);
+    if (!texture) {
+        QImage image = pixmap.toImage();
+        // If the system depth is 16 and the pixmap doesn't have an alpha channel
+        // then we convert it to RGB16 in the hope that it gets uploaded as a 16
+        // bit texture which is much faster to access than a 32-bit one.
+        if (pixmap.depth() == 16 && !image.hasAlphaChannel() )
+            image = image.convertToFormat(QImage::Format_RGB16);
+        texture = bindTexture(image, target, format, key, options);
+    }
     // NOTE: bindTexture(const QImage&, GLenum, GLint, const qint64, bool) should never return null
     Q_ASSERT(texture);
 
@@ -2465,7 +2578,7 @@
         return 0;
 
     Q_D(QGLContext);
-    QGLTexture *texture = d->bindTexture(image, target, format, false, options);
+    QGLTexture *texture = d->bindTexture(image, target, format, options);
     return texture->id;
 }
 
@@ -2477,7 +2590,7 @@
         return 0;
 
     Q_D(QGLContext);
-    QGLTexture *texture = d->bindTexture(image, GLenum(target), GLint(format), false, DefaultBindOption);
+    QGLTexture *texture = d->bindTexture(image, GLenum(target), GLint(format), DefaultBindOption);
     return texture->id;
 }
 
@@ -2489,7 +2602,7 @@
         return 0;
 
     Q_D(QGLContext);
-    QGLTexture *texture = d->bindTexture(image, GLenum(target), GLint(format), false, options);
+    QGLTexture *texture = d->bindTexture(image, GLenum(target), GLint(format), options);
     return texture->id;
 }
 #endif
@@ -2587,41 +2700,41 @@
 }
 #endif
 
-void qt_add_rect_to_array(const QRectF &r, q_vertexType *array)
+void qt_add_rect_to_array(const QRectF &r, GLfloat *array)
 {
     qreal left = r.left();
     qreal right = r.right();
     qreal top = r.top();
     qreal bottom = r.bottom();
 
-    array[0] = f2vt(left);
-    array[1] = f2vt(top);
-    array[2] = f2vt(right);
-    array[3] = f2vt(top);
-    array[4] = f2vt(right);
-    array[5] = f2vt(bottom);
-    array[6] = f2vt(left);
-    array[7] = f2vt(bottom);
-}
-
-void qt_add_texcoords_to_array(qreal x1, qreal y1, qreal x2, qreal y2, q_vertexType *array)
-{
-    array[0] = f2vt(x1);
-    array[1] = f2vt(y1);
-    array[2] = f2vt(x2);
-    array[3] = f2vt(y1);
-    array[4] = f2vt(x2);
-    array[5] = f2vt(y2);
-    array[6] = f2vt(x1);
-    array[7] = f2vt(y2);
+    array[0] = left;
+    array[1] = top;
+    array[2] = right;
+    array[3] = top;
+    array[4] = right;
+    array[5] = bottom;
+    array[6] = left;
+    array[7] = bottom;
+}
+
+void qt_add_texcoords_to_array(qreal x1, qreal y1, qreal x2, qreal y2, GLfloat *array)
+{
+    array[0] = x1;
+    array[1] = y1;
+    array[2] = x2;
+    array[3] = y1;
+    array[4] = x2;
+    array[5] = y2;
+    array[6] = x1;
+    array[7] = y2;
 }
 
 #if !defined(QT_OPENGL_ES_2)
 
 static void qDrawTextureRect(const QRectF &target, GLint textureWidth, GLint textureHeight, GLenum textureTarget)
 {
-    q_vertexType tx = f2vt(1);
-    q_vertexType ty = f2vt(1);
+    GLfloat tx = 1.0f;
+    GLfloat ty = 1.0f;
 
 #ifdef QT_OPENGL_ES
     Q_UNUSED(textureWidth);
@@ -2634,20 +2747,20 @@
             glGetTexLevelParameteriv(textureTarget, 0, GL_TEXTURE_HEIGHT, &textureHeight);
         }
 
-        tx = f2vt(textureWidth);
-        ty = f2vt(textureHeight);
+        tx = GLfloat(textureWidth);
+        ty = GLfloat(textureHeight);
     }
 #endif
 
-    q_vertexType texCoordArray[4*2] = {
+    GLfloat texCoordArray[4*2] = {
         0, ty, tx, ty, tx, 0, 0, 0
     };
 
-    q_vertexType vertexArray[4*2];
+    GLfloat vertexArray[4*2];
     qt_add_rect_to_array(target, vertexArray);
 
-    glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray);
-    glTexCoordPointer(2, q_vertexTypeEnum, 0, texCoordArray);
+    glVertexPointer(2, GL_FLOAT, 0, vertexArray);
+    glTexCoordPointer(2, GL_FLOAT, 0, texCoordArray);
 
     glEnableClientState(GL_VERTEX_ARRAY);
     glEnableClientState(GL_TEXTURE_COORD_ARRAY);
@@ -2662,14 +2775,38 @@
 /*!
     \since 4.4
 
-    Draws the given texture, \a textureId, to the given target rectangle,
-    \a target, in OpenGL model space. The \a textureTarget should be a 2D
-    texture target.
-
-    \note This function is not supported under OpenGL/ES 2.0.
+    This function supports the following use cases:
+
+    \list
+    \i On OpenGL and OpenGL ES 1.x it draws the given texture, \a textureId,
+    to the given target rectangle, \a target, in OpenGL model space. The
+    \a textureTarget should be a 2D texture target.
+    \i On OpenGL and OpenGL ES 2.x, if a painter is active, not inside a
+    beginNativePainting / endNativePainting block, and uses the
+    engine with type QPaintEngine::OpenGL2, the function will draw the given
+    texture, \a textureId, to the given target rectangle, \a target,
+    respecting the current painter state. This will let you draw a texture
+    with the clip, transform, render hints, and composition mode set by the
+    painter. Note that the texture target needs to be GL_TEXTURE_2D for this
+    use case, and that this is the only supported use case under OpenGL ES 2.x.
+    \endlist
+
 */
 void QGLContext::drawTexture(const QRectF &target, GLuint textureId, GLenum textureTarget)
 {
+#if !defined(QT_OPENGL_ES) || defined(QT_OPENGL_ES_2)
+     if (d_ptr->active_engine &&
+         d_ptr->active_engine->type() == QPaintEngine::OpenGL2) {
+         QGL2PaintEngineEx *eng = static_cast<QGL2PaintEngineEx*>(d_ptr->active_engine);
+         if (!eng->isNativePaintingActive()) {
+            QRectF src(0, 0, target.width(), target.height());
+            QSize size(target.width(), target.height());
+            if (eng->drawTexture(target, textureId, size, src))
+                return;
+        }
+     }
+#endif
+
 #ifndef QT_OPENGL_ES_2
 #ifdef QT_OPENGL_ES
     if (textureTarget != GL_TEXTURE_2D) {
@@ -2698,7 +2835,7 @@
     Q_UNUSED(target);
     Q_UNUSED(textureId);
     Q_UNUSED(textureTarget);
-    qWarning("drawTexture(const QRectF &target, GLuint textureId, GLenum textureTarget) not supported with OpenGL ES/2.0");
+    qWarning("drawTexture() with OpenGL ES 2.0 requires an active OpenGL2 paint engine");
 #endif
 }
 
@@ -2713,20 +2850,33 @@
 /*!
     \since 4.4
 
-    Draws the given texture at the given \a point in OpenGL model
-    space. The \a textureTarget should be a 2D texture target.
-
-    \note This function is not supported under OpenGL/ES.
+    This function supports the following use cases:
+
+    \list
+    \i By default it draws the given texture, \a textureId,
+    at the given \a point in OpenGL model space. The
+    \a textureTarget should be a 2D texture target.
+    \i If a painter is active, not inside a
+    beginNativePainting / endNativePainting block, and uses the
+    engine with type QPaintEngine::OpenGL2, the function will draw the given
+    texture, \a textureId, at the given \a point,
+    respecting the current painter state. This will let you draw a texture
+    with the clip, transform, render hints, and composition mode set by the
+    painter. Note that the texture target needs to be GL_TEXTURE_2D for this
+    use case.
+    \endlist
+
+    \note This function is not supported under any version of OpenGL ES.
 */
 void QGLContext::drawTexture(const QPointF &point, GLuint textureId, GLenum textureTarget)
 {
-    // this would be ok on OpenGL ES 2.0, but currently we don't have a define for that
 #ifdef QT_OPENGL_ES
     Q_UNUSED(point);
     Q_UNUSED(textureId);
     Q_UNUSED(textureTarget);
     qWarning("drawTexture(const QPointF &point, GLuint textureId, GLenum textureTarget) not supported with OpenGL ES, use rect version instead");
 #else
+
     const bool wasEnabled = glIsEnabled(GL_TEXTURE_2D);
     GLint oldTexture;
     glGetIntegerv(GL_TEXTURE_BINDING_2D, &oldTexture);
@@ -2740,6 +2890,18 @@
     glGetTexLevelParameteriv(textureTarget, 0, GL_TEXTURE_WIDTH, &textureWidth);
     glGetTexLevelParameteriv(textureTarget, 0, GL_TEXTURE_HEIGHT, &textureHeight);
 
+    if (d_ptr->active_engine &&
+        d_ptr->active_engine->type() == QPaintEngine::OpenGL2) {
+        QGL2PaintEngineEx *eng = static_cast<QGL2PaintEngineEx*>(d_ptr->active_engine);
+        if (!eng->isNativePaintingActive()) {
+            QRectF dest(point, QSizeF(textureWidth, textureHeight));
+            QRectF src(0, 0, textureWidth, textureHeight);
+            QSize size(textureWidth, textureHeight);
+            if (eng->drawTexture(dest, textureId, size, src))
+                return;
+        }
+    }
+
     qDrawTextureRect(QRectF(point, QSizeF(textureWidth, textureHeight)), textureWidth, textureHeight, textureTarget);
 
     if (!wasEnabled)
@@ -3200,6 +3362,7 @@
 */
 
 
+
 /*****************************************************************************
   QGLWidget implementation
  *****************************************************************************/
@@ -3320,6 +3483,15 @@
     One approach to doing this is shown in the
     \l{Overpainting Example}{Overpainting} example.
 
+    \section1 Threading
+
+    It is possible to render into a QGLWidget from another thread, but it
+    requires that all access to the GL context is safe guarded. The Qt GUI
+    thread will try to use the context in resizeEvent and paintEvent, so in
+    order for threaded rendering using a GL widget to work, these functions
+    need to be intercepted in the GUI thread and handled accordingly in the
+    application.
+
     \e{OpenGL is a trademark of Silicon Graphics, Inc. in the United States and other
     countries.}
 
@@ -3850,7 +4022,7 @@
         }
     }
 
-#if defined(QT_OPENGL_ES)
+#ifndef QT_NO_EGL
     // A re-parent is likely to destroy the X11 window and re-create it. It is important
     // that we free the EGL surface _before_ the winID changes - otherwise we can leak.
     if (e->type() == QEvent::ParentAboutToChange)
@@ -3859,7 +4031,7 @@
     if ((e->type() == QEvent::ParentChange) || (e->type() == QEvent::WindowStateChange)) {
         // The window may have been re-created during re-parent or state change - if so, the EGL
         // surface will need to be re-created.
-        d->recreateEglSurface(false);
+        d->recreateEglSurface();
     }
 #endif
 #elif defined(Q_WS_WIN)
@@ -4765,11 +4937,8 @@
 /*!
     \since 4.4
 
-    Draws the given texture, \a textureId to the given target rectangle,
-    \a target, in OpenGL model space. The \a textureTarget should be a 2D
-    texture target.
-
-    Equivalent to the corresponding QGLContext::drawTexture().
+    Calls the corresponding QGLContext::drawTexture() on
+    this widget's context.
 */
 void QGLWidget::drawTexture(const QRectF &target, GLuint textureId, GLenum textureTarget)
 {
@@ -4789,10 +4958,8 @@
 /*!
     \since 4.4
 
-    Draws the given texture, \a textureId, at the given \a point in OpenGL
-    model space. The \a textureTarget should be a 2D texture target.
-
-    Equivalent to the corresponding QGLContext::drawTexture().
+    Calls the corresponding QGLContext::drawTexture() on
+    this widget's context.
 */
 void QGLWidget::drawTexture(const QPointF &point, GLuint textureId, GLenum textureTarget)
 {
@@ -4809,7 +4976,7 @@
 }
 #endif
 
-#if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
+#ifndef QT_OPENGL_ES_1
 Q_GLOBAL_STATIC(QGL2PaintEngineEx, qt_gl_2_engine)
 #endif
 
@@ -4819,7 +4986,7 @@
 
 Q_OPENGL_EXPORT QPaintEngine* qt_qgl_paint_engine()
 {
-#if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_1_CL)
+#if defined(QT_OPENGL_ES_1)
     return qt_gl_engine();
 #elif defined(QT_OPENGL_ES_2)
     return qt_gl_2_engine();
@@ -4942,7 +5109,7 @@
     glExtensions |= GenerateMipmap;
     glExtensions |= FragmentShader;
 #endif
-#if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_1_CL)
+#if defined(QT_OPENGL_ES_1)
     if (extensions.match("GL_OES_framebuffer_object"))
         glExtensions |= FramebufferObject;
 #endif
@@ -4968,6 +5135,20 @@
     return glExtensions;
 }
 
+
+class QGLDefaultExtensions
+{
+public:
+    QGLDefaultExtensions() {
+        QGLTemporaryContext tempContext;
+        extensions = QGLExtensions::currentContextExtensions();
+    }
+
+    QGLExtensions::Extensions extensions;
+};
+
+Q_GLOBAL_STATIC(QGLDefaultExtensions, qtDefaultExtensions)
+
 /*
     Returns the GL extensions for the current QGLContext. If there is no
     current QGLContext, a default context will be created and the extensions
@@ -4975,34 +5156,19 @@
 */
 QGLExtensions::Extensions QGLExtensions::glExtensions()
 {
-    QGLTemporaryContext *tmpContext = 0;
-    static bool cachedDefault = false;
-    static Extensions defaultExtensions = 0;
+    Extensions extensionFlags = 0;
     QGLContext *currentCtx = const_cast<QGLContext *>(QGLContext::currentContext());
 
     if (currentCtx && currentCtx->d_func()->extension_flags_cached)
         return currentCtx->d_func()->extension_flags;
 
     if (!currentCtx) {
-        if (cachedDefault) {
-            return defaultExtensions;
-        } else {
-            tmpContext = new QGLTemporaryContext;
-            cachedDefault = true;
-        }
-    }
-
-    Extensions extensionFlags = currentContextExtensions();
-    if (currentCtx) {
+        extensionFlags = qtDefaultExtensions()->extensions;
+    } else {
+        extensionFlags = currentContextExtensions();
         currentCtx->d_func()->extension_flags_cached = true;
         currentCtx->d_func()->extension_flags = extensionFlags;
-    } else {
-        defaultExtensions = extensionFlags;
     }
-
-    if (tmpContext)
-        delete tmpContext;
-
     return extensionFlags;
 }
 
@@ -5037,11 +5203,17 @@
 Q_OPENGL_EXPORT const QString qt_gl_library_name()
 {
     if (qt_gl_lib_name()->isNull()) {
-#if defined(Q_WS_X11) || defined(Q_WS_QWS)
+#ifdef Q_WS_MAC
+        return QLatin1String("/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib");
+#else
+# if defined(QT_OPENGL_ES_1)
+        return QLatin1String("GLES_CM");
+# elif defined(QT_OPENGL_ES_2)
+        return QLatin1String("GLESv2");
+# else
         return QLatin1String("GL");
-#else // Q_WS_MAC
-        return QLatin1String("/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib");
-#endif
+# endif
+#endif // defined Q_WS_MAC
     }
     return *qt_gl_lib_name();
 }