qt 4.6.0: backport a few patches from git, mainly QGL related
authorKoen Kooi <koen@openembedded.org>
Mon, 4 Jan 2010 15:38:25 +0000 (16:38 +0100)
committerKoen Kooi <koen@openembedded.org>
Tue, 5 Jan 2010 09:07:58 +0000 (10:07 +0100)
33 files changed:
recipes/qt4/qt-4.6.0.inc
recipes/qt4/qt-4.6.0/0838-Fixed-the-GL2-engine-stroker-to-handle-Qt-SvgMiterJo.patch [new file with mode: 0644]
recipes/qt4/qt-4.6.0/0860-Added-caching-of-vectorpaths-to-the-GL-paint-engine.patch [new file with mode: 0644]
recipes/qt4/qt-4.6.0/0917-Better-check-for-EGL-extension-strings.patch [new file with mode: 0644]
recipes/qt4/qt-4.6.0/0919-Rebind-window-surface-fbo-after-native-GL-rendering.patch [new file with mode: 0644]
recipes/qt4/qt-4.6.0/0943-Fixed-OpenGL-graphicssystem-issues-for-OpenGL-ES-2.0.patch [new file with mode: 0644]
recipes/qt4/qt-4.6.0/0945-Add-EGL_BUFFER_SIZE-to-QEglProperties-reduceConfigur.patch [new file with mode: 0644]
recipes/qt4/qt-4.6.0/0946-Fix-WA_TranslucentBackground-for-QGLWidgets-on-X11-E.patch [new file with mode: 0644]
recipes/qt4/qt-4.6.0/0947-Compressed-texture-binding-for-QtOpenGL-ETC1-and-PVR.patch [new file with mode: 0644]
recipes/qt4/qt-4.6.0/0951-Detect-GL2-paint-engine-based-on-fragment-shaders-no.patch [new file with mode: 0644]
recipes/qt4/qt-4.6.0/0971-Fix-GL_BGRA-formats-under-OpenGL-ES-systems.patch [new file with mode: 0644]
recipes/qt4/qt-4.6.0/0991-QGtkStyle-support-for-the-inner-border-property-in-G.patch [new file with mode: 0644]
recipes/qt4/qt-4.6.0/0992-Make-sure-a-context-is-current-when-loading-compress.patch [new file with mode: 0644]
recipes/qt4/qt-4.6.0/0993-Fix-upside-down-PVR-compressed-textures.patch [new file with mode: 0644]
recipes/qt4/qt-4.6.0/0996-Export-QGLShareRegister-because-qgl_share_reg-is-exp.patch [new file with mode: 0644]
recipes/qt4/qt-4.6.0/0998-Set-stacking-class-for-stays-on-top-windows-in-DFB.patch [new file with mode: 0644]
recipes/qt4/qt-4.6.0/0999-Enable-customizing-of-DirectFB-layer-to-use.patch [new file with mode: 0644]
recipes/qt4/qt-4.6.0/1008-GLES-2-should-not-use-a-multisampled-format-by-defau.patch [new file with mode: 0644]
recipes/qt4/qt-4.6.0/1115-Fix-QGLWidgets-created-with-an-alpha-channel-on-X11-.patch [new file with mode: 0644]
recipes/qt4/qt-4.6.0/1118-Fix-EGL-surface-leaks-when-re-parenting-QGLWidget-on.patch [new file with mode: 0644]
recipes/qt4/qt-4.6.0/1136-Disable-depth-testing-during-the-2D-QGLWidget-render.patch [new file with mode: 0644]
recipes/qt4/qt-4.6.0/1149-GL2Engine-Don-t-mark-brush-as-dirty-if-it-hasn-t-cha.patch [new file with mode: 0644]
recipes/qt4/qt-4.6.0/1157-Align-GL_RGB-lines-on-a-4-byte-boundary-when-uploadi.patch [new file with mode: 0644]
recipes/qt4/qt-4.6.0/1165-NEON-configure-detection-and-initial-blend-function-.patch [new file with mode: 0644]
recipes/qt4/qt-4.6.0/1175-Fix-memory-leak-of-QGLGlyphCoord-objects-in-the-Open.patch [new file with mode: 0644]
recipes/qt4/qt-4.6.0/1196-Fix-build-with-neon-instructions-enabled-but-not-set.patch [new file with mode: 0644]
recipes/qt4/qt-4.6.0/1197-Add-GLfloat-2-2-GLfloat-3-3-uniform-setters-to-QGLSh.patch [new file with mode: 0644]
recipes/qt4/qt-4.6.0/1198-Handle-broken-shaders-better-in-the-GL2-engine-s-sha.patch [new file with mode: 0644]
recipes/qt4/qt-4.6.0/1205-Fix-text-rendering-on-GL2-paint-engine.patch [new file with mode: 0644]
recipes/qt4/qt4-embedded-gles_4.6.0.bb
recipes/qt4/qt4-embedded.inc
recipes/qt4/qt4-x11-free-gles_4.6.0.bb
recipes/qt4/qt4-x11-free.inc

index b29b708..91565f7 100644 (file)
@@ -1,5 +1,7 @@
 DEFAULT_PREFERENCE = "-1"
 
+FILESPATHPKG .= ":qt-${PV}"
+
 SRC_URI = "ftp://ftp.trolltech.com/qt/source/qt-everywhere-opensource-src-${PV}.tar.gz \
            file://0001-cross-compile.patch;patch=1 \
            file://0002-fix-resinit-declaration.patch;patch=1 \
@@ -12,6 +14,37 @@ SRC_URI = "ftp://ftp.trolltech.com/qt/source/qt-everywhere-opensource-src-${PV}.
            file://g++.conf \
            file://linux.conf \
            "
+
+# Patches for '4.6' qt branch
+SRC_URI += "\
+           file://0860-Added-caching-of-vectorpaths-to-the-GL-paint-engine.patch;patch=1 \
+           file://0917-Better-check-for-EGL-extension-strings.patch;patch=1 \
+           file://0919-Rebind-window-surface-fbo-after-native-GL-rendering.patch;patch=1 \
+           file://0943-Fixed-OpenGL-graphicssystem-issues-for-OpenGL-ES-2.0.patch;patch=1 \
+           file://0945-Add-EGL_BUFFER_SIZE-to-QEglProperties-reduceConfigur.patch;patch=1 \
+           file://0946-Fix-WA_TranslucentBackground-for-QGLWidgets-on-X11-E.patch;patch=1 \
+           file://0947-Compressed-texture-binding-for-QtOpenGL-ETC1-and-PVR.patch;patch=1 \
+           file://0951-Detect-GL2-paint-engine-based-on-fragment-shaders-no.patch;patch=1 \
+           file://0971-Fix-GL_BGRA-formats-under-OpenGL-ES-systems.patch;patch=1 \
+           file://0991-QGtkStyle-support-for-the-inner-border-property-in-G.patch;patch=1 \
+           file://0992-Make-sure-a-context-is-current-when-loading-compress.patch;patch=1 \
+           file://0993-Fix-upside-down-PVR-compressed-textures.patch;patch=1 \
+           file://0996-Export-QGLShareRegister-because-qgl_share_reg-is-exp.patch;patch=1 \
+           file://0998-Set-stacking-class-for-stays-on-top-windows-in-DFB.patch;patch=1 \
+           file://0999-Enable-customizing-of-DirectFB-layer-to-use.patch;patch=1 \
+           file://1008-GLES-2-should-not-use-a-multisampled-format-by-defau.patch;patch=1 \
+           file://1115-Fix-QGLWidgets-created-with-an-alpha-channel-on-X11-.patch;patch=1 \
+           file://1118-Fix-EGL-surface-leaks-when-re-parenting-QGLWidget-on.patch;patch=1 \
+           file://1136-Disable-depth-testing-during-the-2D-QGLWidget-render.patch;patch=1 \
+           file://1149-GL2Engine-Don-t-mark-brush-as-dirty-if-it-hasn-t-cha.patch;patch=1 \
+           file://1157-Align-GL_RGB-lines-on-a-4-byte-boundary-when-uploadi.patch;patch=1 \
+#           file://1165-NEON-configure-detection-and-initial-blend-function-.patch;patch=1 \
+           file://1175-Fix-memory-leak-of-QGLGlyphCoord-objects-in-the-Open.patch;patch=1 \
+           file://1197-Add-GLfloat-2-2-GLfloat-3-3-uniform-setters-to-QGLSh.patch;patch=1 \
+           file://1198-Handle-broken-shaders-better-in-the-GL2-engine-s-sha.patch;patch=1 \
+           file://1205-Fix-text-rendering-on-GL2-paint-engine.patch;patch=1 \
+"
+
 S = "${WORKDIR}/qt-everywhere-opensource-src-${PV}"
 
 do_configure_prepend() {
@@ -22,8 +55,6 @@ do_configure_prepend() {
     -e /QMAKE_UIC3\ /d \
     -e /QMAKE_RCC\ /d \
     ${S}/configure
-
-#      sed -i /tools.pro/d ${S}/src/src.pro
 }
 
 QT_GLFLAGS ?= ""
diff --git a/recipes/qt4/qt-4.6.0/0838-Fixed-the-GL2-engine-stroker-to-handle-Qt-SvgMiterJo.patch b/recipes/qt4/qt-4.6.0/0838-Fixed-the-GL2-engine-stroker-to-handle-Qt-SvgMiterJo.patch
new file mode 100644 (file)
index 0000000..a517d3c
--- /dev/null
@@ -0,0 +1,25 @@
+From 0f61a0f1ce02bb0248cb87055240a8a474dce452 Mon Sep 17 00:00:00 2001
+From: Kim Motoyoshi Kalland <kim.kalland@nokia.com>
+Date: Fri, 27 Nov 2009 16:17:25 +0100
+Subject: [PATCH 0838/1244] Fixed the GL2 engine stroker to handle Qt::SvgMiterJoin.
+
+Reviewed-by: Trond
+---
+ .../gl2paintengineex/qtriangulatingstroker.cpp     |    1 +
+ 1 files changed, 1 insertions(+), 0 deletions(-)
+
+diff --git a/src/opengl/gl2paintengineex/qtriangulatingstroker.cpp b/src/opengl/gl2paintengineex/qtriangulatingstroker.cpp
+index c78f73f..6082f49 100644
+--- a/src/opengl/gl2paintengineex/qtriangulatingstroker.cpp
++++ b/src/opengl/gl2paintengineex/qtriangulatingstroker.cpp
+@@ -313,6 +313,7 @@ void QTriangulatingStroker::join(const qreal *pts)
+     switch (m_join_style) {
+     case Qt::BevelJoin:
+         break;
++    case Qt::SvgMiterJoin:
+     case Qt::MiterJoin: {
+         // Find out on which side the join should be.
+         int count = m_vertices.size();
+-- 
+1.6.5
+
diff --git a/recipes/qt4/qt-4.6.0/0860-Added-caching-of-vectorpaths-to-the-GL-paint-engine.patch b/recipes/qt4/qt-4.6.0/0860-Added-caching-of-vectorpaths-to-the-GL-paint-engine.patch
new file mode 100644 (file)
index 0000000..794380a
--- /dev/null
@@ -0,0 +1,317 @@
+From dbfdfdb1bc37dd18dd1b723b5d5b0b65c37f3f41 Mon Sep 17 00:00:00 2001
+From: Gunnar Sletta <gunnar@trolltech.com>
+Date: Tue, 1 Dec 2009 09:18:47 +0100
+Subject: [PATCH 0860/1244] Added caching of vectorpaths to the GL paint engine.
+
+The first time a path is drawn we call makeCachable on the path, which
+means that if it is drawn again, we start caching it. This is a bit of
+a trick to avoid caching paths that are drawn once and discared while
+at the same time cache paths that are reused automatically.
+
+The GL engine owns the vertex information and is responsible for cleaning
+it up. If the vectorpath is destroyed first, it will call the cleanup function.
+if the engine dies first, we still require some hooks to clean up the cache
+in the path. More to come. When VBO's are used, these will be a leaked if the
+path is destroyed after the engine.
+
+Reviewed-by: Samuel
+---
+ src/gui/painting/qpaintengineex.cpp                |   16 +++-
+ src/gui/painting/qvectorpath_p.h                   |   13 ++-
+ src/opengl/gl2paintengineex/qgl2pexvertexarray_p.h |    2 +
+ .../gl2paintengineex/qpaintengineex_opengl2.cpp    |  115 +++++++++++++++++++-
+ .../gl2paintengineex/qpaintengineex_opengl2_p.h    |    4 +
+ 5 files changed, 139 insertions(+), 11 deletions(-)
+
+diff --git a/src/gui/painting/qpaintengineex.cpp b/src/gui/painting/qpaintengineex.cpp
+index 7d1c109..9a0e319 100644
+--- a/src/gui/painting/qpaintengineex.cpp
++++ b/src/gui/painting/qpaintengineex.cpp
+@@ -56,6 +56,20 @@ QT_BEGIN_NAMESPACE
+  * class QVectorPath
+  *
+  */
++QVectorPath::~QVectorPath()
++{
++    if (m_hints & ShouldUseCacheHint) {
++        CacheEntry *e = m_cache;
++        while (e) {
++            if (e->data)
++                e->cleanup(e->engine, e->data);
++            CacheEntry *n = e->next;
++            delete e;
++            e = n;
++        }
++    }
++}
++
+ QRectF QVectorPath::controlPointRect() const
+ {
+@@ -94,7 +108,7 @@ QRectF QVectorPath::controlPointRect() const
+ QVectorPath::CacheEntry *QVectorPath::addCacheData(QPaintEngineEx *engine, void *data,
+-                                                   qvectorpath_cache_cleanup cleanup) {
++                                                   qvectorpath_cache_cleanup cleanup) const{
+     Q_ASSERT(!lookupCacheData(engine));
+     if ((m_hints & IsCachedHint) == 0) {
+         m_cache = 0;
+diff --git a/src/gui/painting/qvectorpath_p.h b/src/gui/painting/qvectorpath_p.h
+index ec27970..5eaddf4 100644
+--- a/src/gui/painting/qvectorpath_p.h
++++ b/src/gui/painting/qvectorpath_p.h
+@@ -68,7 +68,7 @@ QT_MODULE(Gui)
+ class QPaintEngineEx;
+-typedef void (*qvectorpath_cache_cleanup)(void *data);
++typedef void (*qvectorpath_cache_cleanup)(QPaintEngineEx *engine, void *data);
+ struct QRealRect {
+     qreal x1, y1, x2, y2;
+@@ -118,6 +118,8 @@ public:
+     {
+     }
++    ~QVectorPath();
++
+     QRectF controlPointRect() const;
+     inline Hint shape() const { return (Hint) (m_hints & ShapeMask); }
+@@ -128,6 +130,7 @@ public:
+     inline bool hasImplicitClose() const { return m_hints & ImplicitClose; }
+     inline bool hasWindingFill() const { return m_hints & WindingFill; }
++    inline void makeCacheable() const { m_hints |= ShouldUseCacheHint; m_cache = 0; }
+     inline uint hints() const { return m_hints; }
+     inline const QPainterPath::ElementType *elements() const { return m_elements; }
+@@ -146,9 +149,9 @@ public:
+         CacheEntry *next;
+     };
+-    CacheEntry *addCacheData(QPaintEngineEx *engine, void *data, qvectorpath_cache_cleanup cleanup);
++    CacheEntry *addCacheData(QPaintEngineEx *engine, void *data, qvectorpath_cache_cleanup cleanup) const;
+     inline CacheEntry *lookupCacheData(QPaintEngineEx *engine) const {
+-        Q_ASSERT(m_hints & IsCachedHint);
++        Q_ASSERT(m_hints & ShouldUseCacheHint);
+         CacheEntry *e = m_cache;
+         while (e) {
+             if (e->engine == engine)
+@@ -162,14 +165,14 @@ public:
+ private:
+     Q_DISABLE_COPY(QVectorPath)
+-    CacheEntry *m_cache;
+-
+     const QPainterPath::ElementType *m_elements;
+     const qreal *m_points;
+     const int m_count;
+     mutable uint m_hints;
+     mutable QRealRect m_cp_rect;
++
++    mutable CacheEntry *m_cache;
+ };
+ Q_GUI_EXPORT const QVectorPath &qtVectorPathForPath(const QPainterPath &path);
+diff --git a/src/opengl/gl2paintengineex/qgl2pexvertexarray_p.h b/src/opengl/gl2paintengineex/qgl2pexvertexarray_p.h
+index 03aec17..98eaa91 100644
+--- a/src/opengl/gl2paintengineex/qgl2pexvertexarray_p.h
++++ b/src/opengl/gl2paintengineex/qgl2pexvertexarray_p.h
+@@ -112,6 +112,8 @@ public:
+     int stopCount() const { return vertexArrayStops.size(); }
+     QGLRect         boundingRect() const;
++    int vertexCount() const { return vertexArray.size(); }
++
+     void lineToArray(const GLfloat x, const GLfloat y);
+ private:
+diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
+index 6a708b4..3fce384 100644
+--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
++++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
+@@ -62,6 +62,8 @@
+     and use the correct program when we really need it.
+ */
++// #define QT_OPENGL_CACHE_AS_VBOS
++
+ #include "qpaintengineex_opengl2_p.h"
+ #include <string.h> //for memcpy
+@@ -344,6 +346,13 @@ extern QImage qt_imageForBrush(int brushStyle, bool invert);
+ QGL2PaintEngineExPrivate::~QGL2PaintEngineExPrivate()
+ {
+     delete shaderManager;
++
++    while (pathCaches.size()) {
++        QVectorPath::CacheEntry *e = *(pathCaches.constBegin());
++        e->cleanup(e->engine, e->data);
++        e->data = 0;
++        e->engine = 0;
++    }
+ }
+ void QGL2PaintEngineExPrivate::updateTextureFilter(GLenum target, GLenum wrapMode, bool smoothPixmapTransform, GLuint id)
+@@ -846,6 +855,30 @@ void QGL2PaintEngineExPrivate::transferMode(EngineMode newMode)
+     mode = newMode;
+ }
++struct QGL2PEVectorPathCache
++{
++#ifdef QT_OPENGL_CACHE_AS_VBOS
++    GLuint vbo;
++#else
++    float *vertices;
++#endif
++    int vertexCount;
++    GLenum primitiveType;
++    qreal iscale;
++};
++
++void qopengl2paintengine_cleanup_vectorpath(QPaintEngineEx *engine, void *data)
++{
++    QGL2PEVectorPathCache *c = (QGL2PEVectorPathCache *) data;
++#ifdef QT_OPENGL_CACHE_AS_VBOS
++    QGL2PaintEngineExPrivate *d = QGL2PaintEngineExPrivate::getData((QGL2PaintEngineEx *) engine);
++    d->unusedVBOSToClean << c->vbo;
++#else
++    qFree(c->vertices);
++#endif
++    delete c;
++}
++
+ // Assumes everything is configured for the brush you want to use
+ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path)
+ {
+@@ -863,10 +896,74 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path)
+         prepareForDraw(currentBrush->isOpaque());
+         composite(rect);
+     } else if (path.isConvex()) {
+-        vertexCoordinateArray.clear();
+-        vertexCoordinateArray.addPath(path, inverseScale, false);
+-        prepareForDraw(currentBrush->isOpaque());
+-        drawVertexArrays(vertexCoordinateArray, GL_TRIANGLE_FAN);
++
++        if (path.isCacheable()) {
++            QVectorPath::CacheEntry *data = path.lookupCacheData(q);
++            QGL2PEVectorPathCache *cache;
++
++            if (data) {
++                cache = (QGL2PEVectorPathCache *) data->data;
++                // Check if scale factor is exceeded for curved paths and generate curves if so...
++                if (path.isCurved()) {
++                    qreal scaleFactor = cache->iscale / inverseScale;
++                    if (scaleFactor < 0.5 || scaleFactor > 2.0) {
++#ifdef QT_OPENGL_CACHE_AS_VBOS
++                        glDeleteBuffers(1, &cache->vbo);
++                        cache->vbo = 0;
++#else
++                        qFree(cache->vertices);
++#endif
++                        cache->vertexCount = 0;
++                    }
++                }
++            } else {
++                cache = new QGL2PEVectorPathCache;
++                cache->vertexCount = 0;
++                data = const_cast<QVectorPath &>(path).addCacheData(q, cache, qopengl2paintengine_cleanup_vectorpath);
++            }
++
++            // Flatten the path at the current scale factor and fill it into the cache struct.
++            if (!cache->vertexCount) {
++                vertexCoordinateArray.clear();
++                vertexCoordinateArray.addPath(path, inverseScale, false);
++                int vertexCount = vertexCoordinateArray.vertexCount();
++                int floatSizeInBytes = vertexCount * 2 * sizeof(float);
++                cache->vertexCount = vertexCount;
++                cache->primitiveType = GL_TRIANGLE_FAN;
++                cache->iscale = inverseScale;               
++#ifdef QT_OPENGL_CACHE_AS_VBOS
++                glGenBuffers(1, &cache->vbo);
++                glBindBuffer(GL_ARRAY_BUFFER, cache->vbo);
++                glBufferData(GL_ARRAY_BUFFER, floatSizeInBytes, vertexCoordinateArray.data(), GL_STATIC_DRAW);
++#else
++                cache->vertices = (float *) qMalloc(floatSizeInBytes);
++                memcpy(cache->vertices, vertexCoordinateArray.data(), floatSizeInBytes);
++#endif
++            }
++
++            prepareForDraw(currentBrush->isOpaque());
++            glEnableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
++#ifdef QT_OPENGL_CACHE_AS_VBOS
++            glBindBuffer(GL_ARRAY_BUFFER, cache->vbo);
++            glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, false, 0, 0);
++#else
++            glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, false, 0, cache->vertices);
++#endif
++            glDrawArrays(cache->primitiveType, 0, cache->vertexCount);
++
++        } else {
++      //        printf(" - Marking path as cachable...\n");
++            // Tag it for later so that if the same path is drawn twice, it is assumed to be static and thus cachable
++            // ### Remove before release...
++            static bool do_vectorpath_cache = qgetenv("QT_OPENGL_NO_PATH_CACHE").isEmpty();
++            if (do_vectorpath_cache)
++                path.makeCacheable();
++            vertexCoordinateArray.clear();
++            vertexCoordinateArray.addPath(path, inverseScale, false);
++            prepareForDraw(currentBrush->isOpaque());
++            drawVertexArrays(vertexCoordinateArray, GL_TRIANGLE_FAN);
++        }
++
+     } else {
+         // The path is too complicated & needs the stencil technique
+         vertexCoordinateArray.clear();
+@@ -1756,7 +1853,8 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev)
+     d->device->beginPaint();
+ #if !defined(QT_OPENGL_ES_2)
+-    bool success = qt_resolve_version_2_0_functions(d->ctx);
++    bool success = qt_resolve_version_2_0_functions(d->ctx)
++                   && qt_resolve_buffer_extensions(d->ctx);
+     Q_ASSERT(success);
+     Q_UNUSED(success);
+ #endif
+@@ -1817,6 +1915,13 @@ bool QGL2PaintEngineEx::end()
+     delete d->shaderManager;
+     d->shaderManager = 0;
++#ifdef QT_OPENGL_CACHE_AS_VBOS
++    if (!d->unusedVBOSToClean.isEmpty()) {
++        glDeleteBuffers(d->unusedVBOSToClean.size(), d->unusedVBOSToClean.constData());
++        d->unusedVBOSToClean.clear();
++    }
++#endif
++
+     return false;
+ }
+diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
+index b554f6d..0084476 100644
+--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
++++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
+@@ -221,6 +221,7 @@ public:
+     void restoreDepthRangeForRenderText();
+     static QGLEngineShaderManager* shaderManagerForEngine(QGL2PaintEngineEx *engine) { return engine->d_func()->shaderManager; }
++    static QGL2PaintEngineExPrivate *getData(QGL2PaintEngineEx *engine) { return engine->d_func(); }
+     QGL2PaintEngineEx* q;
+     QGLPaintDevice* device;
+@@ -294,6 +295,9 @@ public:
+     QScopedPointer<QPixmapFilter> fastBlurFilter;
+     QScopedPointer<QPixmapFilter> dropShadowFilter;
+     QScopedPointer<QPixmapFilter> fastDropShadowFilter;
++
++    QSet<QVectorPath::CacheEntry *> pathCaches;
++    QVector<GLuint> unusedVBOSToClean;
+ };
+ QT_END_NAMESPACE
+-- 
+1.6.5
+
diff --git a/recipes/qt4/qt-4.6.0/0917-Better-check-for-EGL-extension-strings.patch b/recipes/qt4/qt-4.6.0/0917-Better-check-for-EGL-extension-strings.patch
new file mode 100644 (file)
index 0000000..9febe75
--- /dev/null
@@ -0,0 +1,34 @@
+From 108ab335537d20bc74aa9115d46cf91243223c4e Mon Sep 17 00:00:00 2001
+From: Rhys Weatherley <rhys.weatherley@nokia.com>
+Date: Fri, 4 Dec 2009 17:03:41 +1000
+Subject: [PATCH 0917/1244] Better check for EGL extension strings
+
+The previous code might have failed if the desired extension name
+was a prefix of another name: "EGL_foo" member of "EGL_foo_bar".
+This change introduces a more precise check.
+
+Task-number: QTBUG-6454
+Reviewed-by: Sarah Smith
+---
+ src/gui/egl/qegl.cpp |    5 ++++-
+ 1 files changed, 4 insertions(+), 1 deletions(-)
+
+diff --git a/src/gui/egl/qegl.cpp b/src/gui/egl/qegl.cpp
+index cf28dc4..6ee4bfc 100644
+--- a/src/gui/egl/qegl.cpp
++++ b/src/gui/egl/qegl.cpp
+@@ -429,7 +429,10 @@ QString QEglContext::extensions()
+ bool QEglContext::hasExtension(const char* extensionName)
+ {
+-    return extensions().contains(QLatin1String(extensionName));
++    QList<QByteArray> extensions =
++        QByteArray(reinterpret_cast<const char *>
++            (eglQueryString(QEglContext::defaultDisplay(0), EGL_EXTENSIONS))).split(' ');
++    return extensions.contains(extensionName);
+ }
+ QEglContext *QEglContext::currentContext(QEgl::API api)
+-- 
+1.6.5
+
diff --git a/recipes/qt4/qt-4.6.0/0919-Rebind-window-surface-fbo-after-native-GL-rendering.patch b/recipes/qt4/qt-4.6.0/0919-Rebind-window-surface-fbo-after-native-GL-rendering.patch
new file mode 100644 (file)
index 0000000..f3dbdb5
--- /dev/null
@@ -0,0 +1,95 @@
+From c0b81480b2909b18ac15bdd124a562ae005c2f41 Mon Sep 17 00:00:00 2001
+From: Rhys Weatherley <rhys.weatherley@nokia.com>
+Date: Fri, 4 Dec 2009 17:17:00 +1000
+Subject: [PATCH 0919/1244] Rebind window surface fbo after native GL rendering
+
+If the user called QGLFramebufferObject::bind()/release() during a
+beginNativePainting() callout, the release() would reset the context's
+fbo to zero, not the actual window surface fbo.
+
+Task-number: QTBUG-6204
+Reviewed-by: Tom
+---
+ src/opengl/qgl.cpp                  |    1 +
+ src/opengl/qgl_p.h                  |    1 +
+ src/opengl/qglframebufferobject.cpp |    4 ++--
+ src/opengl/qglpaintdevice.cpp       |   10 ++++++++++
+ 4 files changed, 14 insertions(+), 2 deletions(-)
+
+diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp
+index 5ada125..94b8aa5 100644
+--- a/src/opengl/qgl.cpp
++++ b/src/opengl/qgl.cpp
+@@ -1495,6 +1495,7 @@ void QGLContextPrivate::init(QPaintDevice *dev, const QGLFormat &format)
+     version_flags_cached = false;
+     version_flags = QGLFormat::OpenGL_Version_None;
+     current_fbo = 0;
++    default_fbo = 0;
+     active_engine = 0;
+ }
+diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h
+index 8e472e5..ab72c9c 100644
+--- a/src/opengl/qgl_p.h
++++ b/src/opengl/qgl_p.h
+@@ -328,6 +328,7 @@ public:
+     GLint max_texture_size;
+     GLuint current_fbo;
++    GLuint default_fbo;
+     QPaintEngine *active_engine;
+     static inline QGLContextGroup *contextGroup(const QGLContext *ctx) { return ctx->d_ptr->group; }
+diff --git a/src/opengl/qglframebufferobject.cpp b/src/opengl/qglframebufferobject.cpp
+index d79283e..d0297c9 100644
+--- a/src/opengl/qglframebufferobject.cpp
++++ b/src/opengl/qglframebufferobject.cpp
+@@ -899,8 +899,8 @@ bool QGLFramebufferObject::release()
+ #endif
+     if (current) {
+-        current->d_ptr->current_fbo = 0;
+-        glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
++        current->d_ptr->current_fbo = current->d_ptr->default_fbo;
++        glBindFramebuffer(GL_FRAMEBUFFER_EXT, current->d_ptr->default_fbo);
+     }
+     return true;
+diff --git a/src/opengl/qglpaintdevice.cpp b/src/opengl/qglpaintdevice.cpp
+index 2867de5..bcd90a5 100644
+--- a/src/opengl/qglpaintdevice.cpp
++++ b/src/opengl/qglpaintdevice.cpp
+@@ -89,6 +89,12 @@ void QGLPaintDevice::beginPaint()
+         ctx->d_ptr->current_fbo = m_thisFBO;
+         glBindFramebuffer(GL_FRAMEBUFFER_EXT, m_thisFBO);
+     }
++
++    // Set the default fbo for the context to m_thisFBO so that
++    // if some raw GL code between beginNativePainting() and
++    // endNativePainting() calls QGLFramebufferObject::release(),
++    // painting will revert to the window surface's fbo.
++    ctx->d_ptr->default_fbo = m_thisFBO;
+ }
+ void QGLPaintDevice::ensureActiveTarget()
+@@ -101,6 +107,8 @@ void QGLPaintDevice::ensureActiveTarget()
+         ctx->d_ptr->current_fbo = m_thisFBO;
+         glBindFramebuffer(GL_FRAMEBUFFER_EXT, m_thisFBO);
+     }
++
++    ctx->d_ptr->default_fbo = m_thisFBO;
+ }
+ void QGLPaintDevice::endPaint()
+@@ -111,6 +119,8 @@ void QGLPaintDevice::endPaint()
+         ctx->d_ptr->current_fbo = m_previousFBO;
+         glBindFramebuffer(GL_FRAMEBUFFER_EXT, m_previousFBO);
+     }
++
++    ctx->d_ptr->default_fbo = 0;
+ }
+ QGLFormat QGLPaintDevice::format() const
+-- 
+1.6.5
+
diff --git a/recipes/qt4/qt-4.6.0/0943-Fixed-OpenGL-graphicssystem-issues-for-OpenGL-ES-2.0.patch b/recipes/qt4/qt-4.6.0/0943-Fixed-OpenGL-graphicssystem-issues-for-OpenGL-ES-2.0.patch
new file mode 100644 (file)
index 0000000..5ef0b28
--- /dev/null
@@ -0,0 +1,146 @@
+From 60be72310c0f9469b3201b250b257473184ccf2a Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Samuel=20R=C3=B8dal?= <sroedal@trolltech.com>
+Date: Thu, 3 Dec 2009 11:53:31 +0100
+Subject: [PATCH 0943/1244] Fixed OpenGL graphicssystem issues for OpenGL ES 2.0 platforms.
+
+The format and internal_format parameters to glTexImage2D need to always
+match on OpenGL ES 2.0.
+
+Reviewed-by: Tom Cooksey
+---
+ src/opengl/qgl_p.h               |    3 ++-
+ src/opengl/qpixmapdata_gl.cpp    |   38 ++++++++++++++++++++++++++++++--------
+ src/opengl/qwindowsurface_gl.cpp |    9 ++++-----
+ 3 files changed, 36 insertions(+), 14 deletions(-)
+
+diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h
+index ab72c9c..b2407ba 100644
+--- a/src/opengl/qgl_p.h
++++ b/src/opengl/qgl_p.h
+@@ -518,7 +518,8 @@ bool qt_gl_preferGL2Engine();
+ inline GLenum qt_gl_preferredTextureFormat()
+ {
+-    return QSysInfo::ByteOrder == QSysInfo::BigEndian ? GL_RGBA : GL_BGRA;
++    return (QGLExtensions::glExtensions & QGLExtensions::BGRATextureFormat) && QSysInfo::ByteOrder == QSysInfo::LittleEndian
++        ? GL_BGRA : GL_RGBA;
+ }
+ inline GLenum qt_gl_preferredTextureTarget()
+diff --git a/src/opengl/qpixmapdata_gl.cpp b/src/opengl/qpixmapdata_gl.cpp
+index fb55097..ab17789 100644
+--- a/src/opengl/qpixmapdata_gl.cpp
++++ b/src/opengl/qpixmapdata_gl.cpp
+@@ -321,25 +321,47 @@ void QGLPixmapData::ensureCreated() const
+     QGLShareContextScope ctx(qt_gl_share_widget()->context());
+     m_ctx = ctx;
+-    const GLenum format = qt_gl_preferredTextureFormat();
++    const GLenum internal_format = m_hasAlpha ? GL_RGBA : GL_RGB;
++#ifdef QT_OPENGL_ES_2
++    const GLenum external_format = internal_format;
++#else
++    const GLenum external_format = qt_gl_preferredTextureFormat();
++#endif
+     const GLenum target = GL_TEXTURE_2D;
+     if (!m_texture.id) {
+         glGenTextures(1, &m_texture.id);
+         glBindTexture(target, m_texture.id);
+-        GLenum format = m_hasAlpha ? GL_RGBA : GL_RGB;
+-        glTexImage2D(target, 0, format, w, h, 0,
+-                GL_RGBA, GL_UNSIGNED_BYTE, 0);
++        glTexImage2D(target, 0, internal_format, w, h, 0, external_format, GL_UNSIGNED_BYTE, 0);
+         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+     }
+     if (!m_source.isNull()) {
+-        const QImage tx = ctx->d_func()->convertToGLFormat(m_source, true, format);
++        if (external_format == GL_RGB) {
++            QImage tx = m_source.convertToFormat(QImage::Format_RGB32);
++
++            QVector<uchar> pixelData(w * h * 3);
++            uchar *p = &pixelData[0];
++            QRgb *src = (QRgb *)tx.bits();
++
++            for (int i = 0; i < w * h; ++i) {
++                *p++ = qRed(*src);
++                *p++ = qGreen(*src);
++                *p++ = qBlue(*src);
++                ++src;
++            }
+-        glBindTexture(target, m_texture.id);
+-        glTexSubImage2D(target, 0, 0, 0, w, h, format,
+-                        GL_UNSIGNED_BYTE, tx.bits());
++            glBindTexture(target, m_texture.id);
++            glTexSubImage2D(target, 0, 0, 0, w, h, external_format,
++                            GL_UNSIGNED_BYTE, &pixelData[0]);
++        } else {
++            const QImage tx = ctx->d_func()->convertToGLFormat(m_source, true, external_format);
++
++            glBindTexture(target, m_texture.id);
++            glTexSubImage2D(target, 0, 0, 0, w, h, external_format,
++                            GL_UNSIGNED_BYTE, tx.bits());
++        }
+         if (useFramebufferObjects())
+             m_source = QImage();
+diff --git a/src/opengl/qwindowsurface_gl.cpp b/src/opengl/qwindowsurface_gl.cpp
+index e353f5d..7194f9d 100644
+--- a/src/opengl/qwindowsurface_gl.cpp
++++ b/src/opengl/qwindowsurface_gl.cpp
+@@ -493,7 +493,6 @@ void QGLWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint &
+             }
+ #endif
+             d_ptr->paintedRegion = QRegion();
+-
+             context()->swapBuffers();
+         } else {
+             glFlush();
+@@ -688,11 +687,13 @@ void QGLWindowSurface::updateGeometry() {
+     d_ptr->size = rect.size();
+     if (d_ptr->ctx) {
++#ifndef QT_OPENGL_ES_2
+         if (d_ptr->destructive_swap_buffers) {
+             glBindTexture(target, d_ptr->tex_id);
+             glTexImage2D(target, 0, GL_RGBA, rect.width(), rect.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
+             glBindTexture(target, 0);
+         }
++#endif
+         return;
+     }
+@@ -756,11 +757,7 @@ void QGLWindowSurface::updateGeometry() {
+             glMatrixMode(GL_PROJECTION);
+             glLoadIdentity();
+-#ifndef QT_OPENGL_ES
+             glOrtho(0, d_ptr->pb->width(), d_ptr->pb->height(), 0, -999999, 999999);
+-#else
+-            glOrthof(0, d_ptr->pb->width(), d_ptr->pb->height(), 0, -999999, 999999);
+-#endif
+             d_ptr->pb->d_ptr->qctx->d_func()->internal_context = true;
+             return;
+@@ -774,6 +771,7 @@ void QGLWindowSurface::updateGeometry() {
+     ctx->makeCurrent();
++#ifndef QT_OPENGL_ES_2
+     if (d_ptr->destructive_swap_buffers) {
+         glGenTextures(1, &d_ptr->tex_id);
+         glBindTexture(target, d_ptr->tex_id);
+@@ -783,6 +781,7 @@ void QGLWindowSurface::updateGeometry() {
+         glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+         glBindTexture(target, 0);
+     }
++#endif
+     qDebug() << "QGLWindowSurface: Using plain widget as window surface" << this;;
+     d_ptr->ctx = ctx;
+-- 
+1.6.5
+
diff --git a/recipes/qt4/qt-4.6.0/0945-Add-EGL_BUFFER_SIZE-to-QEglProperties-reduceConfigur.patch b/recipes/qt4/qt-4.6.0/0945-Add-EGL_BUFFER_SIZE-to-QEglProperties-reduceConfigur.patch
new file mode 100644 (file)
index 0000000..1afcee6
--- /dev/null
@@ -0,0 +1,33 @@
+From 92e9fcc25c62870c383c8558d576abc509a8c683 Mon Sep 17 00:00:00 2001
+From: Tom Cooksey <thomas.cooksey@nokia.com>
+Date: Fri, 4 Dec 2009 19:42:07 +0100
+Subject: [PATCH 0945/1244] Add EGL_BUFFER_SIZE to QEglProperties::reduceConfiguration()
+
+Reviewed-by: Trustme
+---
+ src/gui/egl/qeglproperties.cpp |    9 +++++++++
+ 1 files changed, 9 insertions(+), 0 deletions(-)
+
+diff --git a/src/gui/egl/qeglproperties.cpp b/src/gui/egl/qeglproperties.cpp
+index 2d37edb..4d4410a 100644
+--- a/src/gui/egl/qeglproperties.cpp
++++ b/src/gui/egl/qeglproperties.cpp
+@@ -229,6 +229,15 @@ void QEglProperties::setRenderableType(QEgl::API api)
+ // reductions in complexity are possible.
+ bool QEglProperties::reduceConfiguration()
+ {
++    // EGL chooses configs with the highest color depth over
++    // those with smaller (but faster) lower color depths. One
++    // way around this is to set EGL_BUFFER_SIZE to 16, which
++    // trumps the others. Of course, there may not be a 16-bit
++    // config avaliable, so it's the first restraint we remove.
++    if (value(EGL_BUFFER_SIZE) == 16) {
++        removeValue(EGL_BUFFER_SIZE);
++        return true;
++    }
+     if (removeValue(EGL_SAMPLE_BUFFERS)) {
+         removeValue(EGL_SAMPLES);
+         return true;
+-- 
+1.6.5
+
diff --git a/recipes/qt4/qt-4.6.0/0946-Fix-WA_TranslucentBackground-for-QGLWidgets-on-X11-E.patch b/recipes/qt4/qt-4.6.0/0946-Fix-WA_TranslucentBackground-for-QGLWidgets-on-X11-E.patch
new file mode 100644 (file)
index 0000000..6cdd9d1
--- /dev/null
@@ -0,0 +1,180 @@
+From 76c415b586991d978d46a888fb40c631513407dc Mon Sep 17 00:00:00 2001
+From: Tom Cooksey <thomas.cooksey@nokia.com>
+Date: Fri, 4 Dec 2009 20:48:53 +0100
+Subject: [PATCH 0946/1244] Fix WA_TranslucentBackground for QGLWidgets on X11/EGL
+
+Also check for existing QEglContext before creating a new one and
+leaking a context.
+
+Reviewed-by: TrustMe
+---
+ src/opengl/qgl_x11egl.cpp |  118 ++++++++++++++++++++++++++++-----------------
+ 1 files changed, 73 insertions(+), 45 deletions(-)
+
+diff --git a/src/opengl/qgl_x11egl.cpp b/src/opengl/qgl_x11egl.cpp
+index b51c239..a868e83 100644
+--- a/src/opengl/qgl_x11egl.cpp
++++ b/src/opengl/qgl_x11egl.cpp
+@@ -63,6 +63,7 @@ void qt_egl_add_platform_config(QEglProperties& props, QPaintDevice *device)
+         props.setPixelFormat(static_cast<QImage *>(device)->format());
+ }
++// Chooses the EGL config and creates the EGL context
+ bool QGLContext::chooseContext(const QGLContext* shareContext)
+ {
+     Q_D(QGLContext);
+@@ -73,56 +74,74 @@ bool QGLContext::chooseContext(const QGLContext* shareContext)
+     int devType = device()->devType();
+     // Get the display and initialize it.
+-    d->eglContext = new QEglContext();
+-    d->eglContext->setApi(QEgl::OpenGL);
+-    if (!d->eglContext->openDisplay(device())) {
+-        delete d->eglContext;
+-        d->eglContext = 0;
+-        return false;
+-    }
++    if (d->eglContext == 0) {
++        d->eglContext = new QEglContext();
++        d->eglContext->setApi(QEgl::OpenGL);
++        if (!d->eglContext->openDisplay(device())) {
++            delete d->eglContext;
++            d->eglContext = 0;
++            return false;
++        }
+-    // Construct the configuration we need for this surface.
+-    QEglProperties configProps;
+-    qt_egl_set_format(configProps, devType, d->glFormat);
+-    qt_egl_add_platform_config(configProps, device());
+-    configProps.setRenderableType(QEgl::OpenGL);
+-
+-    QEgl::PixelFormatMatch matchType = QEgl::BestPixelFormat;
+-    if (device()->depth() == 16) {
+-        configProps.setValue(EGL_RED_SIZE, 5);
+-        configProps.setValue(EGL_GREEN_SIZE, 6);
+-        configProps.setValue(EGL_BLUE_SIZE, 5);
+-        configProps.setValue(EGL_ALPHA_SIZE, 0);
+-        matchType = QEgl::ExactPixelFormat;
+-    }
+-    configProps.setRenderableType(QEgl::OpenGL);
++        // Construct the configuration we need for this surface.
++        QEglProperties configProps;
++        qt_egl_set_format(configProps, devType, d->glFormat);
++        qt_egl_add_platform_config(configProps, device());
++        configProps.setRenderableType(QEgl::OpenGL);
++
++#if We_have_an_EGL_library_which_bothers_to_check_EGL_BUFFER_SIZE
++        if (device()->depth() == 16 && configProps.value(EGL_ALPHA_SIZE) <= 0) {
++            qDebug("Setting EGL_BUFFER_SIZE to 16");
++            configProps.setValue(EGL_BUFFER_SIZE, 16);
++            configProps.setValue(EGL_ALPHA_SIZE, 0);
++        }
+-    // Search for a matching configuration, reducing the complexity
+-    // each time until we get something that matches.
+-    if (!d->eglContext->chooseConfig(configProps, matchType)) {
+-        delete d->eglContext;
+-        d->eglContext = 0;
+-        return false;
+-    }
++        if (!d->eglContext->chooseConfig(configProps, QEgl::BestPixelFormat)) {
++            delete d->eglContext;
++            d->eglContext = 0;
++            return false;
++        }
++#else
++        QEgl::PixelFormatMatch matchType = QEgl::BestPixelFormat;
++        if ((device()->depth() == 16) && configProps.value(EGL_ALPHA_SIZE) == 0) {
++            configProps.setValue(EGL_RED_SIZE, 5);
++            configProps.setValue(EGL_GREEN_SIZE, 6);
++            configProps.setValue(EGL_BLUE_SIZE, 5);
++            configProps.setValue(EGL_ALPHA_SIZE, 0);
++            matchType = QEgl::ExactPixelFormat;
++        }
+-    // Inform the higher layers about the actual format properties.
+-    qt_egl_update_format(*(d->eglContext), d->glFormat);
++        // Search for a matching configuration, reducing the complexity
++        // each time until we get something that matches.
++        if (!d->eglContext->chooseConfig(configProps, matchType)) {
++            delete d->eglContext;
++            d->eglContext = 0;
++            return false;
++        }
++#endif
+-    // Create a new context for the configuration.
+-    if (!d->eglContext->createContext
+-            (shareContext ? shareContext->d_func()->eglContext : 0)) {
+-        delete d->eglContext;
+-        d->eglContext = 0;
+-        return false;
+-    }
+-    d->sharing = d->eglContext->isSharing();
+-    if (d->sharing && shareContext)
+-        const_cast<QGLContext *>(shareContext)->d_func()->sharing = true;
++//        qDebug("QGLContext::chooseContext() - using EGL config %d:", d->eglContext->config());
++//        qDebug() << QEglProperties(d->eglContext->config()).toString();
++
++        // Create a new context for the configuration.
++        if (!d->eglContext->createContext
++                (shareContext ? shareContext->d_func()->eglContext : 0)) {
++            delete d->eglContext;
++            d->eglContext = 0;
++            return false;
++        }
++        d->sharing = d->eglContext->isSharing();
++        if (d->sharing && shareContext)
++            const_cast<QGLContext *>(shareContext)->d_func()->sharing = true;
+ #if defined(EGL_VERSION_1_1)
+-    if (d->glFormat.swapInterval() != -1 && devType == QInternal::Widget)
+-        eglSwapInterval(d->eglContext->display(), d->glFormat.swapInterval());
++        if (d->glFormat.swapInterval() != -1 && devType == QInternal::Widget)
++            eglSwapInterval(d->eglContext->display(), d->glFormat.swapInterval());
+ #endif
++    }
++
++    // Inform the higher layers about the actual format properties.
++    qt_egl_update_format(*(d->eglContext), d->glFormat);
+     return true;
+ }
+@@ -160,6 +179,9 @@ bool qt_egl_setup_x11_visual(XVisualInfo &vi, EGLDisplay display, EGLConfig conf
+     memset(&vi, 0, sizeof(XVisualInfo));
++    EGLint eglConfigColorSize;
++    eglGetConfigAttrib(display, config, EGL_BUFFER_SIZE, &eglConfigColorSize);
++
+     // Check to see if EGL is suggesting an appropriate visual id:
+     EGLint nativeVisualId;
+     eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &nativeVisualId);
+@@ -189,8 +211,12 @@ bool qt_egl_setup_x11_visual(XVisualInfo &vi, EGLDisplay display, EGLConfig conf
+             } else
+ #endif
+             {
+-//                qDebug("Using opaque X Visual ID (%d) provided by EGL", (int)vi.visualid);
+-                vi = *chosenVisualInfo;
++                if (eglConfigColorSize == chosenVisualInfo->depth) {
++//                    qDebug("Using opaque X Visual ID (%d) provided by EGL", (int)vi.visualid);
++                    vi = *chosenVisualInfo;
++                } else
++                    qWarning("Warning: EGL suggested using X visual ID %d (%d bpp) for config %d (%d bpp), but the depths do not match!",
++                             nativeVisualId, chosenVisualInfo->depth, (int)config, eglConfigColorSize);
+             }
+             XFree(chosenVisualInfo);
+         }
+@@ -300,6 +326,8 @@ void QGLWidget::setContext(QGLContext *context, const QGLContext* shareContext,
+     bool createFailed = false;
+     if (!d->glcx->isValid()) {
++        // Create the QGLContext here, which in turn chooses the EGL config
++        // and creates the EGL context:
+         if (!d->glcx->create(shareContext ? shareContext : oldcx))
+             createFailed = true;
+     }
+-- 
+1.6.5
+
diff --git a/recipes/qt4/qt-4.6.0/0947-Compressed-texture-binding-for-QtOpenGL-ETC1-and-PVR.patch b/recipes/qt4/qt-4.6.0/0947-Compressed-texture-binding-for-QtOpenGL-ETC1-and-PVR.patch
new file mode 100644 (file)
index 0000000..605a913
--- /dev/null
@@ -0,0 +1,771 @@
+From 147195bccfdf90924a1525398e9c7b3119c1e278 Mon Sep 17 00:00:00 2001
+From: Rhys Weatherley <rhys.weatherley@nokia.com>
+Date: Thu, 3 Dec 2009 10:07:22 +1000
+Subject: [PATCH 0947/1244] Compressed texture binding for QtOpenGL: ETC1 and PVRTC
+
+The QGLContext::bindTexture(QString) function has been augmented
+with support for ETC1, PVRTC2, and PVRTC4 compressed textures,
+in addition to the existing DDS support.
+
+The QGLPixmapData class has also been modified to recognize
+compressed texture formats in fromFile() and fromData().
+
+This change also fixes a bug in bindTexture() that prevented
+the same compressed texture file from being bound in multiple
+contexts.  There is now a separate file cache for each context group.
+
+Task-number: QT-2547
+Reviewed-by: Trond
+---
+ src/opengl/qgl.cpp            |  485 +++++++++++++++++++++++++++++++----------
+ src/opengl/qgl_p.h            |   16 ++-
+ src/opengl/qglextensions_p.h  |   17 ++
+ src/opengl/qpixmapdata_gl.cpp |   57 +++++
+ src/opengl/qpixmapdata_gl_p.h |    4 +
+ 5 files changed, 461 insertions(+), 118 deletions(-)
+
+diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp
+index 94b8aa5..b376901 100644
+--- a/src/opengl/qgl.cpp
++++ b/src/opengl/qgl.cpp
+@@ -127,18 +127,6 @@ Q_GLOBAL_STATIC(QGLDefaultOverlayFormat, defaultOverlayFormatInstance)
+ QGLExtensions::Extensions QGLExtensions::glExtensions = 0;
+ bool QGLExtensions::nvidiaFboNeedsFinish = false;
+-#ifndef APIENTRY
+-# define APIENTRY
+-#endif
+-typedef void (APIENTRY *pfn_glCompressedTexImage2DARB) (GLenum, GLint, GLenum, GLsizei,
+-                                                        GLsizei, GLint, GLsizei, const GLvoid *);
+-static pfn_glCompressedTexImage2DARB qt_glCompressedTexImage2DARB = 0;
+-
+-
+-#ifndef APIENTRY
+-#define APIENTRY
+-#endif
+-
+ Q_GLOBAL_STATIC(QGLSignalProxy, theSignalProxy)
+ QGLSignalProxy *QGLSignalProxy::instance()
+ {
+@@ -1887,118 +1875,42 @@ void QGLContextPrivate::cleanup()
+ {
+ }
+-typedef QHash<QString, GLuint> QGLDDSCache;
+-Q_GLOBAL_STATIC(QGLDDSCache, qgl_dds_cache)
+-
+ /*!
+     \overload
+-    Reads the DirectDrawSurface (DDS) compressed file \a fileName and
+-    generates a 2D GL texture from it.
++    Reads the compressed texture file \a fileName and generates a 2D GL
++    texture from it.
+-    Only the DXT1, DXT3 and DXT5 DDS formats are supported.
++    This function can load DirectDrawSurface (DDS) textures in the
++    DXT1, DXT3 and DXT5 DDS formats if the \c GL_ARB_texture_compression
++    and \c GL_EXT_texture_compression_s3tc extensions are supported.
+-    Note that this will only work if the implementation supports the
+-    \c GL_ARB_texture_compression and \c GL_EXT_texture_compression_s3tc
+-    extensions.
++    Since 4.6.1, textures in the ETC1 format can be loaded if the
++    \c GL_OES_compressed_ETC1_RGB8_texture extension is supported
++    and the ETC1 texture has been encapsulated in the PVR container format.
++    Also, textures in the PVRTC2 and PVRTC4 formats can be loaded
++    if the \c GL_IMG_texture_compression_pvrtc extension is supported.
+     \sa deleteTexture()
+ */
+ GLuint QGLContext::bindTexture(const QString &fileName)
+ {
+-    if (!qt_glCompressedTexImage2DARB) {
+-        qWarning("QGLContext::bindTexture(): The GL implementation does not support texture"
+-                 "compression extensions.");
+-        return 0;
+-    }
+-
+-    QGLDDSCache::const_iterator it = qgl_dds_cache()->constFind(fileName);
+-    if (it != qgl_dds_cache()->constEnd()) {
++    Q_D(QGLContext);
++    QGLDDSCache *dds_cache = &(d->group->m_dds_cache);
++    QGLDDSCache::const_iterator it = dds_cache->constFind(fileName);
++    if (it != dds_cache->constEnd()) {
+         glBindTexture(GL_TEXTURE_2D, it.value());
+         return it.value();
+     }
+-    QFile f(fileName);
+-    f.open(QIODevice::ReadOnly);
+-
+-    char tag[4];
+-    f.read(&tag[0], 4);
+-    if (strncmp(tag,"DDS ", 4) != 0) {
+-        qWarning("QGLContext::bindTexture(): not a DDS image file.");
+-        return 0;
+-    }
+-
+-    DDSFormat ddsHeader;
+-    f.read((char *) &ddsHeader, sizeof(DDSFormat));
+-
+-    if (!ddsHeader.dwLinearSize) {
+-        qWarning("QGLContext::bindTexture() DDS image size is not valid.");
+-        return 0;
+-    }
+-
+-    int factor = 4;
+-    int bufferSize = 0;
+-    int blockSize = 16;
+-    GLenum format;
+-
+-    switch(ddsHeader.ddsPixelFormat.dwFourCC) {
+-    case FOURCC_DXT1:
+-        format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
+-        factor = 2;
+-        blockSize = 8;
+-        break;
+-    case FOURCC_DXT3:
+-        format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
+-        break;
+-    case FOURCC_DXT5:
+-        format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
+-        break;
+-    default:
+-        qWarning("QGLContext::bindTexture() DDS image format not supported.");
++    QGLTexture texture(this);
++    QSize size = texture.bindCompressedTexture(fileName);
++    if (!size.isValid())
+         return 0;
+-    }
+-
+-    if (ddsHeader.dwMipMapCount > 1)
+-        bufferSize = ddsHeader.dwLinearSize * factor;
+-    else
+-        bufferSize = ddsHeader.dwLinearSize;
+-
+-    GLubyte *pixels = (GLubyte *) malloc(bufferSize*sizeof(GLubyte));
+-    f.seek(ddsHeader.dwSize + 4);
+-    f.read((char *) pixels, bufferSize);
+-    f.close();
+-
+-    GLuint tx_id;
+-    glGenTextures(1, &tx_id);
+-    glBindTexture(GL_TEXTURE_2D, tx_id);
+-    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+-    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+-
+-    int size;
+-    int offset = 0;
+-    int w = ddsHeader.dwWidth;
+-    int h = ddsHeader.dwHeight;
+-    // load mip-maps
+-    for(int i = 0; i < (int) ddsHeader.dwMipMapCount; ++i) {
+-        if (w == 0) w = 1;
+-        if (h == 0) h = 1;
+-
+-        size = ((w+3)/4) * ((h+3)/4) * blockSize;
+-        qt_glCompressedTexImage2DARB(GL_TEXTURE_2D, i, format, w, h, 0,
+-                                     size, pixels + offset);
+-        offset += size;
+-
+-        // half size for each mip-map level
+-        w = w/2;
+-        h = h/2;
+-    }
+-
+-    free(pixels);
+-
+-    qgl_dds_cache()->insert(fileName, tx_id);
+-    return tx_id;
++    dds_cache->insert(fileName, texture.id);
++    return texture.id;
+ }
+ static inline QRgb qt_gl_convertToGLFormatHelper(QRgb src_pixel, GLenum texture_format)
+@@ -2593,17 +2505,20 @@ GLuint QGLContext::bindTexture(const QPixmap &pixmap, QMacCompatGLenum target, Q
+ */
+ void QGLContext::deleteTexture(GLuint id)
+ {
++    Q_D(QGLContext);
++
+     if (QGLTextureCache::instance()->remove(this, id))
+         return;
+     // check the DDS cache if the texture wasn't found in the pixmap/image
+     // cache
+-    QList<QString> ddsKeys = qgl_dds_cache()->keys();
++    QGLDDSCache *dds_cache = &(d->group->m_dds_cache);
++    QList<QString> ddsKeys = dds_cache->keys();
+     for (int i = 0; i < ddsKeys.size(); ++i) {
+-        GLuint texture = qgl_dds_cache()->value(ddsKeys.at(i));
++        GLuint texture = dds_cache->value(ddsKeys.at(i));
+         if (id == texture) {
+             glDeleteTextures(1, &texture);
+-            qgl_dds_cache()->remove(ddsKeys.at(i));
++            dds_cache->remove(ddsKeys.at(i));
+             return;
+         }
+     }
+@@ -4907,8 +4822,14 @@ void QGLExtensions::init_extensions()
+         glExtensions |= SampleBuffers;
+     if (extensions.contains("GL_SGIS_generate_mipmap"))
+         glExtensions |= GenerateMipmap;
+-    if (extensions.contains("GL_EXT_texture_compression_s3tc"))
++    if (extensions.contains("GL_ARB_texture_compression"))
+         glExtensions |= TextureCompression;
++    if (extensions.contains("GL_EXT_texture_compression_s3tc"))
++        glExtensions |= DDSTextureCompression;
++    if (extensions.contains("GL_OES_compressed_ETC1_RGB8_texture"))
++        glExtensions |= ETC1TextureCompression;
++    if (extensions.contains("GL_IMG_texture_compression_pvrtc"))
++        glExtensions |= PVRTCTextureCompression;
+     if (extensions.contains("GL_ARB_fragment_program"))
+         glExtensions |= FragmentProgram;
+     if (extensions.contains("GL_ARB_texture_mirrored_repeat"))
+@@ -4951,12 +4872,6 @@ void QGLExtensions::init_extensions()
+     if (extensions.contains("GL_EXT_bgra"))
+         glExtensions |= BGRATextureFormat;
+-
+-
+-    QGLContext cx(QGLFormat::defaultFormat());
+-    if (glExtensions & TextureCompression) {
+-        qt_glCompressedTexImage2DARB = (pfn_glCompressedTexImage2DARB) cx.getProcAddress(QLatin1String("glCompressedTexImage2DARB"));
+-    }
+ }
+ /*
+@@ -5112,4 +5027,340 @@ void QGLSharedResourceGuard::setContext(const QGLContext *context)
+     }
+ }
++QSize QGLTexture::bindCompressedTexture
++    (const QString& fileName, const char *format)
++{
++    QFile file(fileName);
++    if (!file.open(QIODevice::ReadOnly))
++        return QSize();
++    QByteArray contents = file.readAll();
++    file.close();
++    return bindCompressedTexture
++        (contents.constData(), contents.size(), format);
++}
++
++// PVR header format for container files that store textures compressed
++// with the ETC1, PVRTC2, and PVRTC4 encodings.  Format information from the
++// PowerVR SDK at http://www.imgtec.com/powervr/insider/powervr-sdk.asp
++// "PVRTexTool Reference Manual, version 1.11f".
++struct PvrHeader
++{
++    quint32 headerSize;
++    quint32 height;
++    quint32 width;
++    quint32 mipMapCount;
++    quint32 flags;
++    quint32 dataSize;
++    quint32 bitsPerPixel;
++    quint32 redMask;
++    quint32 greenMask;
++    quint32 blueMask;
++    quint32 alphaMask;
++    quint32 magic;
++    quint32 surfaceCount;
++};
++
++#define PVR_MAGIC               0x21525650      // "PVR!" in little-endian
++
++#define PVR_FORMAT_MASK         0x000000FF
++#define PVR_FORMAT_PVRTC2       0x00000018
++#define PVR_FORMAT_PVRTC4       0x00000019
++#define PVR_FORMAT_ETC1         0x00000036
++
++#define PVR_HAS_MIPMAPS         0x00000100
++#define PVR_TWIDDLED            0x00000200
++#define PVR_NORMAL_MAP          0x00000400
++#define PVR_BORDER_ADDED        0x00000800
++#define PVR_CUBE_MAP            0x00001000
++#define PVR_FALSE_COLOR_MIPMAPS 0x00002000
++#define PVR_VOLUME_TEXTURE      0x00004000
++#define PVR_ALPHA_IN_TEXTURE    0x00008000
++#define PVR_VERTICAL_FLIP       0x00010000
++
++#ifndef GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
++#define GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG      0x8C00
++#define GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG      0x8C01
++#define GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG     0x8C02
++#define GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG     0x8C03
++#endif
++
++#ifndef GL_ETC1_RGB8_OES
++#define GL_ETC1_RGB8_OES                        0x8D64
++#endif
++
++bool QGLTexture::canBindCompressedTexture
++    (const char *buf, int len, const char *format, bool *hasAlpha)
++{
++    if (QSysInfo::ByteOrder != QSysInfo::LittleEndian) {
++        // Compressed texture loading only supported on little-endian
++        // systems such as x86 and ARM at the moment.
++        return false;
++    }
++    if (!format) {
++        // Auto-detect the format from the header.
++        if (len >= 4 && !qstrncmp(buf, "DDS ", 4)) {
++            *hasAlpha = true;
++            return true;
++        } else if (len >= 52 && !qstrncmp(buf + 44, "PVR!", 4)) {
++            const PvrHeader *pvrHeader =
++                reinterpret_cast<const PvrHeader *>(buf);
++            *hasAlpha = (pvrHeader->alphaMask != 0);
++            return true;
++        }
++    } else {
++        // Validate the format against the header.
++        if (!qstricmp(format, "DDS")) {
++            if (len >= 4 && !qstrncmp(buf, "DDS ", 4)) {
++                *hasAlpha = true;
++                return true;
++            }
++        } else if (!qstricmp(format, "PVR") || !qstricmp(format, "ETC1")) {
++            if (len >= 52 && !qstrncmp(buf + 44, "PVR!", 4)) {
++                const PvrHeader *pvrHeader =
++                    reinterpret_cast<const PvrHeader *>(buf);
++                *hasAlpha = (pvrHeader->alphaMask != 0);
++                return true;
++            }
++        }
++    }
++    return false;
++}
++
++#define ctx QGLContext::currentContext()
++
++QSize QGLTexture::bindCompressedTexture
++    (const char *buf, int len, const char *format)
++{
++    if (QSysInfo::ByteOrder != QSysInfo::LittleEndian) {
++        // Compressed texture loading only supported on little-endian
++        // systems such as x86 and ARM at the moment.
++        return QSize();
++    }
++#if !defined(QT_OPENGL_ES)
++    if (!glCompressedTexImage2D) {
++        if (!(QGLExtensions::glExtensions & QGLExtensions::TextureCompression)) {
++            qWarning("QGLContext::bindTexture(): The GL implementation does "
++                     "not support texture compression extensions.");
++            return QSize();
++        }
++        glCompressedTexImage2D = (_glCompressedTexImage2DARB) ctx->getProcAddress(QLatin1String("glCompressedTexImage2DARB"));
++        if (!glCompressedTexImage2D) {
++            qWarning("QGLContext::bindTexture(): could not resolve "
++                     "glCompressedTexImage2DARB.");
++            return QSize();
++        }
++    }
++#endif
++    if (!format) {
++        // Auto-detect the format from the header.
++        if (len >= 4 && !qstrncmp(buf, "DDS ", 4))
++            return bindCompressedTextureDDS(buf, len);
++        else if (len >= 52 && !qstrncmp(buf + 44, "PVR!", 4))
++            return bindCompressedTexturePVR(buf, len);
++    } else {
++        // Validate the format against the header.
++        if (!qstricmp(format, "DDS")) {
++            if (len >= 4 && !qstrncmp(buf, "DDS ", 4))
++                return bindCompressedTextureDDS(buf, len);
++        } else if (!qstricmp(format, "PVR") || !qstricmp(format, "ETC1")) {
++            if (len >= 52 && !qstrncmp(buf + 44, "PVR!", 4))
++                return bindCompressedTexturePVR(buf, len);
++        }
++    }
++    return QSize();
++}
++
++QSize QGLTexture::bindCompressedTextureDDS(const char *buf, int len)
++{
++    // We only support 2D texture loading at present.
++    if (target != GL_TEXTURE_2D)
++        return QSize();
++
++    // Bail out if the necessary extension is not present.
++    if (!(QGLExtensions::glExtensions & QGLExtensions::DDSTextureCompression)) {
++        qWarning("QGLContext::bindTexture(): DDS texture compression is not supported.");
++        return QSize();
++    }
++
++    const DDSFormat *ddsHeader = reinterpret_cast<const DDSFormat *>(buf + 4);
++    if (!ddsHeader->dwLinearSize) {
++        qWarning("QGLContext::bindTexture(): DDS image size is not valid.");
++        return QSize();
++    }
++
++    int blockSize = 16;
++    GLenum format;
++
++    switch(ddsHeader->ddsPixelFormat.dwFourCC) {
++    case FOURCC_DXT1:
++        format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
++        blockSize = 8;
++        break;
++    case FOURCC_DXT3:
++        format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
++        break;
++    case FOURCC_DXT5:
++        format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
++        break;
++    default:
++        qWarning("QGLContext::bindTexture(): DDS image format not supported.");
++        return QSize();
++    }
++
++    const GLubyte *pixels =
++        reinterpret_cast<const GLubyte *>(buf + ddsHeader->dwSize + 4);
++
++    glGenTextures(1, &id);
++    glBindTexture(GL_TEXTURE_2D, id);
++    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
++    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
++
++    int size;
++    int offset = 0;
++    int available = len - int(ddsHeader->dwSize + 4);
++    int w = ddsHeader->dwWidth;
++    int h = ddsHeader->dwHeight;
++
++    // load mip-maps
++    for(int i = 0; i < (int) ddsHeader->dwMipMapCount; ++i) {
++        if (w == 0) w = 1;
++        if (h == 0) h = 1;
++
++        size = ((w+3)/4) * ((h+3)/4) * blockSize;
++        if (size > available)
++            break;
++        glCompressedTexImage2D(GL_TEXTURE_2D, i, format, w, h, 0,
++                               size, pixels + offset);
++        offset += size;
++        available -= size;
++
++        // half size for each mip-map level
++        w = w/2;
++        h = h/2;
++    }
++
++    // DDS images are not inverted.
++    options &= ~QGLContext::InvertedYBindOption;
++
++    return QSize(ddsHeader->dwWidth, ddsHeader->dwHeight);
++}
++
++QSize QGLTexture::bindCompressedTexturePVR(const char *buf, int len)
++{
++    // We only support 2D texture loading at present.  Cube maps later.
++    if (target != GL_TEXTURE_2D)
++        return QSize();
++
++    // Determine which texture format we will be loading.
++    const PvrHeader *pvrHeader = reinterpret_cast<const PvrHeader *>(buf);
++    GLenum textureFormat;
++    quint32 minWidth, minHeight;
++    switch (pvrHeader->flags & PVR_FORMAT_MASK) {
++    case PVR_FORMAT_PVRTC2:
++        if (pvrHeader->alphaMask)
++            textureFormat = GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
++        else
++            textureFormat = GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
++        minWidth = 16;
++        minHeight = 8;
++        break;
++
++    case PVR_FORMAT_PVRTC4:
++        if (pvrHeader->alphaMask)
++            textureFormat = GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
++        else
++            textureFormat = GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
++        minWidth = 8;
++        minHeight = 8;
++        break;
++
++    case PVR_FORMAT_ETC1:
++        textureFormat = GL_ETC1_RGB8_OES;
++        minWidth = 4;
++        minHeight = 4;
++        break;
++
++    default:
++        qWarning("QGLContext::bindTexture(): PVR image format 0x%x not supported.", int(pvrHeader->flags & PVR_FORMAT_MASK));
++        return QSize();
++    }
++
++    // Bail out if the necessary extension is not present.
++    if (textureFormat == GL_ETC1_RGB8_OES) {
++        if (!(QGLExtensions::glExtensions &
++                    QGLExtensions::ETC1TextureCompression)) {
++            qWarning("QGLContext::bindTexture(): ETC1 texture compression is not supported.");
++            return QSize();
++        }
++    } else {
++        if (!(QGLExtensions::glExtensions &
++                    QGLExtensions::PVRTCTextureCompression)) {
++            qWarning("QGLContext::bindTexture(): PVRTC texture compression is not supported.");
++            return QSize();
++        }
++    }
++
++    // Boundary check on the buffer size.
++    quint32 bufferSize = pvrHeader->headerSize + pvrHeader->dataSize;
++    if (bufferSize > quint32(len)) {
++        qWarning("QGLContext::bindTexture(): PVR image size is not valid.");
++        return QSize();
++    }
++
++    // Create the texture.
++    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
++    glGenTextures(1, &id);
++    glBindTexture(GL_TEXTURE_2D, id);
++    if (pvrHeader->mipMapCount) {
++        if ((options & QGLContext::LinearFilteringBindOption) != 0) {
++            glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
++            glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
++        } else {
++            glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
++            glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
++        }
++    } else if ((options & QGLContext::LinearFilteringBindOption) != 0) {
++        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
++        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
++    } else {
++        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
++        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
++    }
++
++    // Load the compressed mipmap levels.
++    const GLubyte *buffer =
++        reinterpret_cast<const GLubyte *>(buf + pvrHeader->headerSize);
++    bufferSize = pvrHeader->dataSize;
++    quint32 level = 0;
++    quint32 width = pvrHeader->width;
++    quint32 height = pvrHeader->height;
++    while (bufferSize > 0 && level < pvrHeader->mipMapCount) {
++        quint32 size =
++            (qMax(width, minWidth) * qMax(height, minHeight) *
++             pvrHeader->bitsPerPixel) / 8;
++        if (size > bufferSize)
++            break;
++        glCompressedTexImage2D(GL_TEXTURE_2D, GLint(level), textureFormat,
++                               GLsizei(width), GLsizei(height), 0,
++                               GLsizei(size), buffer);
++        width /= 2;
++        height /= 2;
++        buffer += size;
++        ++level;
++    }
++
++    // Restore the default pixel alignment for later texture uploads.
++    glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
++
++    // Set the invert flag for the texture.
++    if ((pvrHeader->flags & PVR_VERTICAL_FLIP) != 0)
++        options |= QGLContext::InvertedYBindOption;
++    else
++        options &= ~QGLContext::InvertedYBindOption;
++
++    return QSize(pvrHeader->width, pvrHeader->height);
++}
++
++#undef ctx
++
+ QT_END_NAMESPACE
+diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h
+index b2407ba..0f785a5 100644
+--- a/src/opengl/qgl_p.h
++++ b/src/opengl/qgl_p.h
+@@ -222,6 +222,8 @@ public:
+ class QGLContextResource;
+ class QGLSharedResourceGuard;
++typedef QHash<QString, GLuint> QGLDDSCache;
++
+ // QGLContextPrivate has the responsibility of creating context groups.
+ // QGLContextPrivate and QGLShareRegister will both maintain the reference counter and destroy
+ // context groups when needed.
+@@ -246,6 +248,7 @@ private:
+     QHash<QGLContextResource *, void *> m_resources;
+     QGLSharedResourceGuard *m_guards; // double-linked list of active guards.
+     QAtomicInt m_refs;
++    QGLDDSCache m_dds_cache;
+     void cleanupResources(const QGLContext *ctx);
+@@ -377,7 +380,10 @@ public:
+         PixelBufferObject       = 0x00000800,
+         FramebufferBlit         = 0x00001000,
+         NPOTTextures            = 0x00002000,
+-        BGRATextureFormat       = 0x00004000
++        BGRATextureFormat       = 0x00004000,
++        DDSTextureCompression   = 0x00008000,
++        ETC1TextureCompression  = 0x00010000,
++        PVRTCTextureCompression = 0x00020000
+     };
+     Q_DECLARE_FLAGS(Extensions, Extension)
+@@ -482,6 +488,14 @@ public:
+     QPixmapData* boundPixmap;
+ #endif
++    bool canBindCompressedTexture
++        (const char *buf, int len, const char *format, bool *hasAlpha);
++    QSize bindCompressedTexture
++        (const QString& fileName, const char *format = 0);
++    QSize bindCompressedTexture
++        (const char *buf, int len, const char *format = 0);
++    QSize bindCompressedTextureDDS(const char *buf, int len);
++    QSize bindCompressedTexturePVR(const char *buf, int len);
+ };
+ class QGLTextureCache {
+diff --git a/src/opengl/qglextensions_p.h b/src/opengl/qglextensions_p.h
+index 3510765..62e216c 100644
+--- a/src/opengl/qglextensions_p.h
++++ b/src/opengl/qglextensions_p.h
+@@ -184,6 +184,10 @@ typedef void (APIENTRY *_glBlitFramebufferEXT) (int srcX0, int srcY0, int srcX1,
+ typedef void (APIENTRY *_glRenderbufferStorageMultisampleEXT) (GLenum target, GLsizei samples,
+                                                                GLenum internalformat, GLsizei width, GLsizei height);
++// ARB_texture_compression
++typedef void (APIENTRY *_glCompressedTexImage2DARB) (GLenum, GLint, GLenum, GLsizei,
++                                                     GLsizei, GLint, GLsizei, const GLvoid *);
++
+ QT_BEGIN_NAMESPACE
+ struct QGLExtensionFuncs
+@@ -289,6 +293,11 @@ struct QGLExtensionFuncs
+ #endif
+         qt_glMapBufferARB = 0;
+         qt_glUnmapBufferARB = 0;
++
++#if !defined(QT_OPENGL_ES)
++        // Texture compression
++        qt_glCompressedTexImage2DARB = 0;
++#endif
+     }
+@@ -397,6 +406,10 @@ struct QGLExtensionFuncs
+     _glMapBufferARB qt_glMapBufferARB;
+     _glUnmapBufferARB qt_glUnmapBufferARB;
++#if !defined(QT_OPENGL_ES)
++    // Texture compression
++    _glCompressedTexImage2DARB qt_glCompressedTexImage2DARB;
++#endif
+ };
+@@ -732,6 +745,10 @@ struct QGLExtensionFuncs
+ #define glClearDepth glClearDepthf
+ #endif
++#if !defined(QT_OPENGL_ES)
++#define glCompressedTexImage2D QGLContextPrivate::extensionFuncs(ctx).qt_glCompressedTexImage2DARB
++#endif
++
+ extern bool qt_resolve_framebufferobject_extensions(QGLContext *ctx);
+ bool qt_resolve_buffer_extensions(QGLContext *ctx);
+diff --git a/src/opengl/qpixmapdata_gl.cpp b/src/opengl/qpixmapdata_gl.cpp
+index ab17789..0299cea 100644
+--- a/src/opengl/qpixmapdata_gl.cpp
++++ b/src/opengl/qpixmapdata_gl.cpp
+@@ -53,6 +53,8 @@
+ #include <private/qpaintengineex_opengl2_p.h>
+ #include <qdesktopwidget.h>
++#include <qfile.h>
++#include <qimagereader.h>
+ QT_BEGIN_NAMESPACE
+@@ -407,6 +409,61 @@ void QGLPixmapData::fromImage(const QImage &image,
+     }
+ }
++bool QGLPixmapData::fromFile(const QString &filename, const char *format,
++                             Qt::ImageConversionFlags flags)
++{
++    if (pixelType() == QPixmapData::BitmapType)
++        return QPixmapData::fromFile(filename, format, flags);
++    QFile file(filename);
++    if (!file.open(QIODevice::ReadOnly))
++        return false;
++    QByteArray data = file.peek(64);
++    bool alpha;
++    if (m_texture.canBindCompressedTexture
++            (data.constData(), data.size(), format, &alpha)) {
++        resize(0, 0);
++        data = file.readAll();
++        file.close();
++        QSize size = m_texture.bindCompressedTexture
++            (data.constData(), data.size(), format);
++        if (!size.isEmpty()) {
++            w = size.width();
++            h = size.height();
++            is_null = false;
++            d = 32;
++            m_hasAlpha = alpha;
++            m_source = QImage();
++            m_dirty = isValid();
++            return true;
++        }
++        return false;
++    }
++    fromImage(QImageReader(&file, format).read(), flags);
++    return !isNull();
++}
++
++bool QGLPixmapData::fromData(const uchar *buffer, uint len, const char *format,
++                             Qt::ImageConversionFlags flags)
++{
++    bool alpha;
++    const char *buf = reinterpret_cast<const char *>(buffer);
++    if (m_texture.canBindCompressedTexture(buf, int(len), format, &alpha)) {
++        resize(0, 0);
++        QSize size = m_texture.bindCompressedTexture(buf, int(len), format);
++        if (!size.isEmpty()) {
++            w = size.width();
++            h = size.height();
++            is_null = false;
++            d = 32;
++            m_hasAlpha = alpha;
++            m_source = QImage();
++            m_dirty = isValid();
++            return true;
++        }
++    }
++    return QPixmapData::fromData(buffer, len, format, flags);
++}
++
+ bool QGLPixmapData::scroll(int dx, int dy, const QRect &rect)
+ {
+     Q_UNUSED(dx);
+diff --git a/src/opengl/qpixmapdata_gl_p.h b/src/opengl/qpixmapdata_gl_p.h
+index 8a13e03..007c52a 100644
+--- a/src/opengl/qpixmapdata_gl_p.h
++++ b/src/opengl/qpixmapdata_gl_p.h
+@@ -106,6 +106,10 @@ public:
+     // Re-implemented from QPixmapData:
+     void resize(int width, int height);
+     void fromImage(const QImage &image, Qt::ImageConversionFlags flags);
++    bool fromFile(const QString &filename, const char *format,
++                  Qt::ImageConversionFlags flags);
++    bool fromData(const uchar *buffer, uint len, const char *format,
++                  Qt::ImageConversionFlags flags);
+     void copy(const QPixmapData *data, const QRect &rect);
+     bool scroll(int dx, int dy, const QRect &rect);
+     void fill(const QColor &color);
+-- 
+1.6.5
+
diff --git a/recipes/qt4/qt-4.6.0/0951-Detect-GL2-paint-engine-based-on-fragment-shaders-no.patch b/recipes/qt4/qt-4.6.0/0951-Detect-GL2-paint-engine-based-on-fragment-shaders-no.patch
new file mode 100644 (file)
index 0000000..787868e
--- /dev/null
@@ -0,0 +1,68 @@
+From 8fea31ca0ab98ef6fed7bb2d87d97f4f425b2078 Mon Sep 17 00:00:00 2001
+From: Rhys Weatherley <rhys.weatherley@nokia.com>
+Date: Mon, 7 Dec 2009 10:07:13 +1000
+Subject: [PATCH 0951/1244] Detect GL2 paint engine based on fragment shaders, not programs
+
+The auto-detect logic was looking for fragment programs to check
+for OpenGL2 support.  It should have been looking for fragment shaders.
+
+Task-number: QTBUG-5638
+Reviewed-by: Sarah Smith
+---
+ src/opengl/qgl.cpp |    7 +++++--
+ src/opengl/qgl_p.h |    3 ++-
+ 2 files changed, 7 insertions(+), 3 deletions(-)
+
+diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp
+index b376901..1ff102f 100644
+--- a/src/opengl/qgl.cpp
++++ b/src/opengl/qgl.cpp
+@@ -173,12 +173,12 @@ public:
+ #else
+             // We can't do this in the constructor for this object because it
+             // needs to be called *before* the QApplication constructor.
+-            // Also check for the FragmentProgram extension in conjunction with
++            // Also check for the FragmentShader extension in conjunction with
+             // the 2.0 version flag, to cover the case where we export the display
+             // from an old GL 1.1 server to a GL 2.x client. In that case we can't
+             // use GL 2.0.
+             if ((QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_2_0)
+-                && (QGLExtensions::glExtensions & QGLExtensions::FragmentProgram)
++                && (QGLExtensions::glExtensions & QGLExtensions::FragmentShader)
+                 && qgetenv("QT_GL_USE_OPENGL1ENGINE").isEmpty())
+                 engineType = QPaintEngine::OpenGL2;
+             else
+@@ -4832,6 +4832,8 @@ void QGLExtensions::init_extensions()
+         glExtensions |= PVRTCTextureCompression;
+     if (extensions.contains("GL_ARB_fragment_program"))
+         glExtensions |= FragmentProgram;
++    if (extensions.contains("GL_ARB_fragment_shader"))
++        glExtensions |= FragmentShader;
+     if (extensions.contains("GL_ARB_texture_mirrored_repeat"))
+         glExtensions |= MirroredRepeat;
+     if (extensions.contains("GL_EXT_framebuffer_object"))
+@@ -4849,6 +4851,7 @@ void QGLExtensions::init_extensions()
+ #if defined(QT_OPENGL_ES_2)
+     glExtensions |= FramebufferObject;
+     glExtensions |= GenerateMipmap;
++    glExtensions |= FragmentShader;
+ #endif
+ #if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_1_CL)
+     if (extensions.contains("GL_OES_framebuffer_object"))
+diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h
+index 0f785a5..179d69a 100644
+--- a/src/opengl/qgl_p.h
++++ b/src/opengl/qgl_p.h
+@@ -383,7 +383,8 @@ public:
+         BGRATextureFormat       = 0x00004000,
+         DDSTextureCompression   = 0x00008000,
+         ETC1TextureCompression  = 0x00010000,
+-        PVRTCTextureCompression = 0x00020000
++        PVRTCTextureCompression = 0x00020000,
++        FragmentShader          = 0x00040000
+     };
+     Q_DECLARE_FLAGS(Extensions, Extension)
+-- 
+1.6.5
+
diff --git a/recipes/qt4/qt-4.6.0/0971-Fix-GL_BGRA-formats-under-OpenGL-ES-systems.patch b/recipes/qt4/qt-4.6.0/0971-Fix-GL_BGRA-formats-under-OpenGL-ES-systems.patch
new file mode 100644 (file)
index 0000000..37ac6f2
--- /dev/null
@@ -0,0 +1,40 @@
+From 05d4b4c72a5089885c1515833e34177607c2c511 Mon Sep 17 00:00:00 2001
+From: Rhys Weatherley <rhys.weatherley@nokia.com>
+Date: Tue, 8 Dec 2009 11:02:46 +1000
+Subject: [PATCH 0971/1244] Fix GL_BGRA formats under OpenGL/ES systems
+
+OpenGL/ES requires that the internal and external formats be the
+same when calling glTexImage2D().  This caused problems with
+devices that had the GL_EXT_bgra extension.
+
+This change makes the formats the same just before the upload and
+also makes sure that the pixel type is GL_UNSIGNED_BYTE when
+GL_BGRA is used.  No change for desktop systems.
+
+Reviewed-by: Donald Carr
+---
+ src/opengl/qgl.cpp |    8 ++++++++
+ 1 files changed, 8 insertions(+), 0 deletions(-)
+
+diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp
+index 1ff102f..967ba48 100644
+--- a/src/opengl/qgl.cpp
++++ b/src/opengl/qgl.cpp
+@@ -2234,6 +2234,14 @@ QGLTexture* QGLContextPrivate::bindTexture(const QImage &image, GLenum target, G
+             }
+         }
+     }
++#ifdef QT_OPENGL_ES
++    // OpenGL/ES requires that the internal and external formats be identical.
++    // This is typically used to convert GL_RGBA into GL_BGRA.
++    // Also, we need to use GL_UNSIGNED_BYTE when the format is GL_BGRA.
++    internalFormat = externalFormat;
++    if (pixel_type == GL_UNSIGNED_INT_8_8_8_8_REV)
++        pixel_type = GL_UNSIGNED_BYTE;
++#endif
+ #ifdef QGL_BIND_TEXTURE_DEBUG
+     printf(" - uploading, image.format=%d, externalFormat=0x%x, internalFormat=0x%x, pixel_type=0x%x\n",
+            img.format(), externalFormat, internalFormat, pixel_type);
+-- 
+1.6.5
+
diff --git a/recipes/qt4/qt-4.6.0/0991-QGtkStyle-support-for-the-inner-border-property-in-G.patch b/recipes/qt4/qt-4.6.0/0991-QGtkStyle-support-for-the-inner-border-property-in-G.patch
new file mode 100644 (file)
index 0000000..ee812f7
--- /dev/null
@@ -0,0 +1,92 @@
+From f3c37838ab149a8a570b7f1df987705815ae45c0 Mon Sep 17 00:00:00 2001
+From: Robert Griebl <rgriebl@trolltech.com>
+Date: Tue, 8 Dec 2009 17:10:57 +0100
+Subject: [PATCH 0991/1244] QGtkStyle: support for the inner-border property in GtkButtons
+
+This additional padding was not taken into account up to now. It didn't
+matter for desktop themes, but Maemo5 uses a large (8pix) padding that can
+not be ignored.
+
+Reviewed-by: jbache
+---
+ src/gui/styles/qgtkstyle.cpp   |   16 ++++++++++++++++
+ src/gui/styles/qgtkstyle_p.cpp |    2 ++
+ src/gui/styles/qgtkstyle_p.h   |    2 ++
+ 3 files changed, 20 insertions(+), 0 deletions(-)
+
+diff --git a/src/gui/styles/qgtkstyle.cpp b/src/gui/styles/qgtkstyle.cpp
+index afa3325..097a2b5 100644
+--- a/src/gui/styles/qgtkstyle.cpp
++++ b/src/gui/styles/qgtkstyle.cpp
+@@ -3375,12 +3375,28 @@ QIcon QGtkStyle::standardIconImplementation(StandardPixmap standardIcon,
+ /*! \reimp */
+ QRect QGtkStyle::subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const
+ {
++    Q_D(const QGtkStyle);
++
+     QRect r = QCleanlooksStyle::subElementRect(element, option, widget);
+     switch (element) {
+     case SE_ProgressBarLabel:
+     case SE_ProgressBarContents:
+     case SE_ProgressBarGroove:
+         return option->rect;
++    case SE_PushButtonContents:
++        if (!d->gtk_check_version(2, 10, 0)) {
++            GtkWidget *gtkButton = d->gtkWidget(QLS("GtkButton"));
++            GtkBorder *border = 0;
++            d->gtk_widget_style_get(gtkButton, "inner-border", &border, NULL);
++            if (border) {
++                r = option->rect.adjusted(border->left, border->top, -border->right, -border->top);
++                d->gtk_border_free(border);
++            } else {
++                r = option->rect.adjusted(1, 1, -1, -1);
++            }
++            r = visualRect(option->direction, option->rect, r);
++        }
++        break;
+     default:
+         break;
+     }
+diff --git a/src/gui/styles/qgtkstyle_p.cpp b/src/gui/styles/qgtkstyle_p.cpp
+index 22dfc62..a644a5b 100644
+--- a/src/gui/styles/qgtkstyle_p.cpp
++++ b/src/gui/styles/qgtkstyle_p.cpp
+@@ -158,6 +158,7 @@ Ptr_gtk_window_get_type QGtkStylePrivate::gtk_window_get_type = 0;
+ Ptr_gtk_widget_get_type QGtkStylePrivate::gtk_widget_get_type = 0;
+ Ptr_gtk_rc_get_style_by_paths QGtkStylePrivate::gtk_rc_get_style_by_paths = 0;
+ Ptr_gtk_check_version QGtkStylePrivate::gtk_check_version = 0;
++Ptr_gtk_border_free QGtkStylePrivate::gtk_border_free = 0;
+ Ptr_pango_font_description_get_size QGtkStylePrivate::pango_font_description_get_size = 0;
+ Ptr_pango_font_description_get_weight QGtkStylePrivate::pango_font_description_get_weight = 0;
+@@ -416,6 +417,7 @@ void QGtkStylePrivate::resolveGtk() const
+     gtk_widget_get_type =(Ptr_gtk_widget_get_type)libgtk.resolve("gtk_widget_get_type");
+     gtk_rc_get_style_by_paths =(Ptr_gtk_rc_get_style_by_paths)libgtk.resolve("gtk_rc_get_style_by_paths");
+     gtk_check_version =(Ptr_gtk_check_version)libgtk.resolve("gtk_check_version");
++    gtk_border_free =(Ptr_gtk_border_free)libgtk.resolve("gtk_border_free");
+     pango_font_description_get_size = (Ptr_pango_font_description_get_size)libgtk.resolve("pango_font_description_get_size");
+     pango_font_description_get_weight = (Ptr_pango_font_description_get_weight)libgtk.resolve("pango_font_description_get_weight");
+     pango_font_description_get_family = (Ptr_pango_font_description_get_family)libgtk.resolve("pango_font_description_get_family");
+diff --git a/src/gui/styles/qgtkstyle_p.h b/src/gui/styles/qgtkstyle_p.h
+index f6ab8a3..c27308f 100644
+--- a/src/gui/styles/qgtkstyle_p.h
++++ b/src/gui/styles/qgtkstyle_p.h
+@@ -176,6 +176,7 @@ typedef GtkWidget* (*Ptr_gtk_file_chooser_dialog_new)(const gchar *title,
+ typedef void (*Ptr_gtk_file_chooser_set_current_name) (GtkFileChooser *, const gchar *);
+ typedef gboolean (*Ptr_gtk_file_chooser_set_filename) (GtkFileChooser *chooser, const gchar *name);
+ typedef gint (*Ptr_gtk_dialog_run) (GtkDialog*);
++typedef void (*Ptr_gtk_border_free)(GtkBorder *);
+ typedef guchar* (*Ptr_gdk_pixbuf_get_pixels) (const GdkPixbuf *pixbuf);
+ typedef int (*Ptr_gdk_pixbuf_get_width) (const GdkPixbuf *pixbuf);
+@@ -371,6 +372,7 @@ public:
+     static Ptr_gtk_widget_get_type gtk_widget_get_type;
+     static Ptr_gtk_rc_get_style_by_paths gtk_rc_get_style_by_paths;
+     static Ptr_gtk_check_version gtk_check_version;
++    static Ptr_gtk_border_free gtk_border_free;
+     static Ptr_pango_font_description_get_size pango_font_description_get_size;
+     static Ptr_pango_font_description_get_weight pango_font_description_get_weight;
+-- 
+1.6.5
+
diff --git a/recipes/qt4/qt-4.6.0/0992-Make-sure-a-context-is-current-when-loading-compress.patch b/recipes/qt4/qt-4.6.0/0992-Make-sure-a-context-is-current-when-loading-compress.patch
new file mode 100644 (file)
index 0000000..301fba2
--- /dev/null
@@ -0,0 +1,33 @@
+From 51297287f1be5c31337203cbf5a0e3eae6047a88 Mon Sep 17 00:00:00 2001
+From: Rhys Weatherley <rhys.weatherley@nokia.com>
+Date: Wed, 9 Dec 2009 08:46:37 +1000
+Subject: [PATCH 0992/1244] Make sure a context is current when loading compressed textures.
+
+Reviewed-by: trustme
+---
+ src/opengl/qpixmapdata_gl.cpp |    2 ++
+ 1 files changed, 2 insertions(+), 0 deletions(-)
+
+diff --git a/src/opengl/qpixmapdata_gl.cpp b/src/opengl/qpixmapdata_gl.cpp
+index 0299cea..4e1d50d 100644
+--- a/src/opengl/qpixmapdata_gl.cpp
++++ b/src/opengl/qpixmapdata_gl.cpp
+@@ -424,6 +424,7 @@ bool QGLPixmapData::fromFile(const QString &filename, const char *format,
+         resize(0, 0);
+         data = file.readAll();
+         file.close();
++        QGLShareContextScope ctx(qt_gl_share_widget()->context());
+         QSize size = m_texture.bindCompressedTexture
+             (data.constData(), data.size(), format);
+         if (!size.isEmpty()) {
+@@ -449,6 +450,7 @@ bool QGLPixmapData::fromData(const uchar *buffer, uint len, const char *format,
+     const char *buf = reinterpret_cast<const char *>(buffer);
+     if (m_texture.canBindCompressedTexture(buf, int(len), format, &alpha)) {
+         resize(0, 0);
++        QGLShareContextScope ctx(qt_gl_share_widget()->context());
+         QSize size = m_texture.bindCompressedTexture(buf, int(len), format);
+         if (!size.isEmpty()) {
+             w = size.width();
+-- 
+1.6.5
+
diff --git a/recipes/qt4/qt-4.6.0/0993-Fix-upside-down-PVR-compressed-textures.patch b/recipes/qt4/qt-4.6.0/0993-Fix-upside-down-PVR-compressed-textures.patch
new file mode 100644 (file)
index 0000000..70aeb7b
--- /dev/null
@@ -0,0 +1,36 @@
+From 62fac41edfff5e42e4c3308376cb08e5d9a10afe Mon Sep 17 00:00:00 2001
+From: Rhys Weatherley <rhys.weatherley@nokia.com>
+Date: Wed, 9 Dec 2009 09:10:11 +1000
+Subject: [PATCH 0993/1244] Fix upside down PVR compressed textures.
+
+The "vertical flip" flag in the PVR format is the inverse of the
+"inverted y" state that we use in Qt.
+
+Reviewed-by: trustme
+---
+ src/opengl/qgl.cpp |    7 ++++---
+ 1 files changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp
+index 967ba48..8003a29 100644
+--- a/src/opengl/qgl.cpp
++++ b/src/opengl/qgl.cpp
+@@ -5363,11 +5363,12 @@ QSize QGLTexture::bindCompressedTexturePVR(const char *buf, int len)
+     // Restore the default pixel alignment for later texture uploads.
+     glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+-    // Set the invert flag for the texture.
++    // Set the invert flag for the texture.  The "vertical flip"
++    // flag in PVR is the opposite sense to our sense of inversion.
+     if ((pvrHeader->flags & PVR_VERTICAL_FLIP) != 0)
+-        options |= QGLContext::InvertedYBindOption;
+-    else
+         options &= ~QGLContext::InvertedYBindOption;
++    else
++        options |= QGLContext::InvertedYBindOption;
+     return QSize(pvrHeader->width, pvrHeader->height);
+ }
+-- 
+1.6.5
+
diff --git a/recipes/qt4/qt-4.6.0/0996-Export-QGLShareRegister-because-qgl_share_reg-is-exp.patch b/recipes/qt4/qt-4.6.0/0996-Export-QGLShareRegister-because-qgl_share_reg-is-exp.patch
new file mode 100644 (file)
index 0000000..52303d9
--- /dev/null
@@ -0,0 +1,26 @@
+From f59908d4a6edcd333a156d4c94ddbd9b30f7e810 Mon Sep 17 00:00:00 2001
+From: Rhys Weatherley <rhys.weatherley@nokia.com>
+Date: Wed, 9 Dec 2009 11:06:30 +1000
+Subject: [PATCH 0996/1244] Export QGLShareRegister because qgl_share_reg() is exported
+
+Reviewed-by: trustme
+---
+ src/opengl/qgl_p.h |    2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h
+index 179d69a..615fb60 100644
+--- a/src/opengl/qgl_p.h
++++ b/src/opengl/qgl_p.h
+@@ -397,7 +397,7 @@ public:
+ Q_DECLARE_OPERATORS_FOR_FLAGS(QGLExtensions::Extensions)
+-class Q_AUTOTEST_EXPORT QGLShareRegister
++class Q_OPENGL_EXPORT QGLShareRegister
+ {
+ public:
+     QGLShareRegister() {}
+-- 
+1.6.5
+
diff --git a/recipes/qt4/qt-4.6.0/0998-Set-stacking-class-for-stays-on-top-windows-in-DFB.patch b/recipes/qt4/qt-4.6.0/0998-Set-stacking-class-for-stays-on-top-windows-in-DFB.patch
new file mode 100644 (file)
index 0000000..b868794
--- /dev/null
@@ -0,0 +1,39 @@
+From 472c13edc85a6c7efef1e3b904333d0c9a5f9da6 Mon Sep 17 00:00:00 2001
+From: Anders Bakken <anders.bakken@nokia.com>
+Date: Thu, 3 Dec 2009 08:55:20 -0800
+Subject: [PATCH 0998/1244] Set stacking class for stays-on-top windows in DFB
+
+For better compatibility with non-QWS DirectFB apps running in the same
+session we should set the stacking class of Windows that have the
+StaysOnTop flag set. This corresponds nicely to DWSC_UPPER.
+
+Reviewed-by: Jervey Kong <jervey.kong@nokia.com>
+---
+ .../gfxdrivers/directfb/qdirectfbwindowsurface.cpp |    4 +++-
+ 1 files changed, 3 insertions(+), 1 deletions(-)
+
+diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp
+index 021d52e..b79418a 100644
+--- a/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp
++++ b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp
+@@ -128,7 +128,6 @@ IDirectFBWindow *QDirectFBWindowSurface::directFBWindow() const
+     return (dfbWindow ? dfbWindow : (sibling ? sibling->dfbWindow : 0));
+ }
+-
+ void QDirectFBWindowSurface::createWindow(const QRect &rect)
+ {
+     IDirectFBDisplayLayer *layer = screen->dfbDisplayLayer();
+@@ -169,6 +168,9 @@ void QDirectFBWindowSurface::createWindow(const QRect &rect)
+         DirectFBErrorFatal("QDirectFBWindowSurface::createWindow", result);
+     if (window()) {
++        if (window()->windowFlags() & Qt::WindowStaysOnTopHint) {
++            dfbWindow->SetStackingClass(dfbWindow, DWSC_UPPER);
++        }
+         DFBWindowID winid;
+         result = dfbWindow->GetID(dfbWindow, &winid);
+         if (result != DFB_OK) {
+-- 
+1.6.5
+
diff --git a/recipes/qt4/qt-4.6.0/0999-Enable-customizing-of-DirectFB-layer-to-use.patch b/recipes/qt4/qt-4.6.0/0999-Enable-customizing-of-DirectFB-layer-to-use.patch
new file mode 100644 (file)
index 0000000..5dcc670
--- /dev/null
@@ -0,0 +1,41 @@
+From 941c6637a83f765c028f40973bb7bcca0ecbafb5 Mon Sep 17 00:00:00 2001
+From: Anders Bakken <anders.bakken@nokia.com>
+Date: Tue, 8 Dec 2009 08:19:58 -0800
+Subject: [PATCH 0999/1244] Enable customizing of DirectFB layer to use
+
+This patch enables you to use a different layer for Qt apps by
+specifying:
+
+E.g.
+
+QWS_DISPLAY=directfb:layerid=2
+
+Reviewed-by: Donald Carr <donald.carr@nokia.com>
+---
+ .../gfxdrivers/directfb/qdirectfbscreen.cpp        |    7 +++++--
+ 1 files changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp
+index 4cb0184..d3fe183 100644
+--- a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp
++++ b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp
+@@ -1259,11 +1259,14 @@ bool QDirectFBScreen::connect(const QString &displaySpec)
+     setIntOption(displayArgs, QLatin1String("height"), &h);
+ #ifndef QT_NO_DIRECTFB_LAYER
+-    result = d_ptr->dfb->GetDisplayLayer(d_ptr->dfb, DLID_PRIMARY,
++    int layerId = DLID_PRIMARY;
++    setIntOption(displayArgs, QLatin1String("layerid"), &layerId);
++
++    result = d_ptr->dfb->GetDisplayLayer(d_ptr->dfb, static_cast<DFBDisplayLayerID>(layerId),
+                                          &d_ptr->dfbLayer);
+     if (result != DFB_OK) {
+         DirectFBError("QDirectFBScreen::connect: "
+-                      "Unable to get primary display layer!", result);
++                      "Unable to get display layer!", result);
+         return false;
+     }
+     result = d_ptr->dfbLayer->GetScreen(d_ptr->dfbLayer, &d_ptr->dfbScreen);
+-- 
+1.6.5
+
diff --git a/recipes/qt4/qt-4.6.0/1008-GLES-2-should-not-use-a-multisampled-format-by-defau.patch b/recipes/qt4/qt-4.6.0/1008-GLES-2-should-not-use-a-multisampled-format-by-defau.patch
new file mode 100644 (file)
index 0000000..f504599
--- /dev/null
@@ -0,0 +1,46 @@
+From c4d66e27ea69b84bf280209fc72239132924930d Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Trond=20Kjern=C3=A5sen?= <trond@trolltech.com>
+Date: Wed, 9 Dec 2009 12:14:58 +0100
+Subject: [PATCH 1008/1244] GLES 2 should *not* use a multisampled format by default.
+
+This is a platform regression and should never have been there in the
+first place. Having this as the default format on embedded devices
+may drop the framerates with as much as 30% on selected HW.
+
+Reviewed-by: Tom Cooksey
+---
+ src/opengl/qgl.cpp |    3 +--
+ src/opengl/qgl_p.h |    3 ---
+ 2 files changed, 1 insertions(+), 5 deletions(-)
+
+diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp
+index 25285b5..dcf8c00 100644
+--- a/src/opengl/qgl.cpp
++++ b/src/opengl/qgl.cpp
+@@ -397,8 +397,7 @@ static inline GLint qgluProject(GLdouble objx, GLdouble objy, GLdouble objz,
+     \i \link setDirectRendering() Direct rendering:\endlink Enabled.
+     \i \link setOverlay() Overlay:\endlink Disabled.
+     \i \link setPlane() Plane:\endlink 0 (i.e., normal plane).
+-    \i \link setSampleBuffers() Multisample buffers:\endlink Enabled on
+-       OpenGL/ES 2.0, disabled on other platforms.
++    \i \link setSampleBuffers() Multisample buffers:\endlink Disabled.
+     \endlist
+ */
+diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h
+index 615fb60..8a0b31f 100644
+--- a/src/opengl/qgl_p.h
++++ b/src/opengl/qgl_p.h
+@@ -133,9 +133,6 @@ public:
+         : ref(1)
+     {
+         opts = QGL::DoubleBuffer | QGL::DepthBuffer | QGL::Rgba | QGL::DirectRendering | QGL::StencilBuffer;
+-#if defined(QT_OPENGL_ES_2)
+-        opts |= QGL::SampleBuffers;
+-#endif
+         pln = 0;
+         depthSize = accumSize = stencilSize = redSize = greenSize = blueSize = alphaSize = -1;
+         numSamples = -1;
+-- 
+1.6.5
+
diff --git a/recipes/qt4/qt-4.6.0/1115-Fix-QGLWidgets-created-with-an-alpha-channel-on-X11-.patch b/recipes/qt4/qt-4.6.0/1115-Fix-QGLWidgets-created-with-an-alpha-channel-on-X11-.patch
new file mode 100644 (file)
index 0000000..6b3ad4e
--- /dev/null
@@ -0,0 +1,30 @@
+From 6b29466ed7b5328ee61c1751bd4efb72f70946d3 Mon Sep 17 00:00:00 2001
+From: Tom Cooksey <thomas.cooksey@nokia.com>
+Date: Tue, 15 Dec 2009 17:26:37 +0100
+Subject: [PATCH 1115/1244] Fix QGLWidgets created with an alpha channel on X11/EGL
+
+If the QGLWidget's QGLFormat says it should have an alpha
+channel, try to find an ARGB Visual.
+
+Reviewed-By: Trond
+Task-number: QT-2602
+---
+ src/opengl/qgl_x11egl.cpp |    2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/src/opengl/qgl_x11egl.cpp b/src/opengl/qgl_x11egl.cpp
+index b10e7e9..19026b3 100644
+--- a/src/opengl/qgl_x11egl.cpp
++++ b/src/opengl/qgl_x11egl.cpp
+@@ -336,7 +336,7 @@ void QGLWidget::setContext(QGLContext *context, const QGLContext* shareContext,
+     // If the application has set WA_TranslucentBackground and not explicitly set
+     // the alpha buffer size to zero, modify the format so it have an alpha channel
+     QGLFormat& fmt = d->glcx->d_func()->glFormat;
+-    const bool tryArgbVisual = testAttribute(Qt::WA_TranslucentBackground);
++    const bool tryArgbVisual = testAttribute(Qt::WA_TranslucentBackground) || fmt.alpha();
+     if (tryArgbVisual && fmt.alphaBufferSize() == -1)
+         fmt.setAlphaBufferSize(1);
+-- 
+1.6.5
+
diff --git a/recipes/qt4/qt-4.6.0/1118-Fix-EGL-surface-leaks-when-re-parenting-QGLWidget-on.patch b/recipes/qt4/qt-4.6.0/1118-Fix-EGL-surface-leaks-when-re-parenting-QGLWidget-on.patch
new file mode 100644 (file)
index 0000000..b0a2147
--- /dev/null
@@ -0,0 +1,116 @@
+From 9f3ae04fae52cd37855b135a0f2f519d1c5b969c Mon Sep 17 00:00:00 2001
+From: Tom Cooksey <thomas.cooksey@nokia.com>
+Date: Tue, 15 Dec 2009 18:11:05 +0100
+Subject: [PATCH 1118/1244] Fix EGL surface leaks when re-parenting QGLWidget on X11/EGL
+
+When a QGLWidget is re-parented, it's native X11 window usually
+gets destroyed and re-created. This also happens when you set a
+window attribute or flag. On EGL, we must destroy the surface
+for the window before destroying the window itself, otherwise
+we can leak the surface. This also fixes lots of BadDrawable
+errors when running the autotests (which were due to surface
+leaks!).
+
+Reviewed-By: TrustMe
+---
+ src/opengl/qgl.cpp     |    5 +++++
+ src/opengl/qgl.h       |    1 +
+ src/opengl/qgl_egl.cpp |   34 +++++++++++++++++++++-------------
+ src/opengl/qgl_p.h     |    1 +
+ 4 files changed, 28 insertions(+), 13 deletions(-)
+
+diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp
+index 2a3ce54..32534aa 100644
+--- a/src/opengl/qgl.cpp
++++ b/src/opengl/qgl.cpp
+@@ -3810,6 +3810,11 @@ bool QGLWidget::event(QEvent *e)
+     }
+ #if defined(QT_OPENGL_ES)
++    // 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)
++        d->glcx->d_func()->destroyEglSurfaceForDevice();
++
+     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.
+diff --git a/src/opengl/qgl.h b/src/opengl/qgl.h
+index 079953f..2076c46 100644
+--- a/src/opengl/qgl.h
++++ b/src/opengl/qgl.h
+@@ -546,6 +546,7 @@ private:
+     friend class QGLPixelBuffer;
+     friend class QGLPixelBufferPrivate;
+     friend class QGLContext;
++    friend class QGLContextPrivate;
+     friend class QGLOverlayWidget;
+     friend class QOpenGLPaintEngine;
+     friend class QGLPaintDevice;
+diff --git a/src/opengl/qgl_egl.cpp b/src/opengl/qgl_egl.cpp
+index fbf0349..839e8eb 100644
+--- a/src/opengl/qgl_egl.cpp
++++ b/src/opengl/qgl_egl.cpp
+@@ -142,19 +142,7 @@ void QGLContext::reset()
+     d->cleanup();
+     doneCurrent();
+     if (d->eglContext) {
+-        if (d->eglSurface != EGL_NO_SURFACE) {
+-#ifdef Q_WS_X11
+-            // Make sure we don't call eglDestroySurface on a surface which
+-            // was created for a different winId:
+-            if (d->paintDevice->devType() == QInternal::Widget) {
+-                QGLWidget* w = static_cast<QGLWidget*>(d->paintDevice);
+-
+-                if (w->d_func()->eglSurfaceWindowId == w->winId())
+-                    eglDestroySurface(d->eglContext->display(), d->eglSurface);
+-            } else
+-#endif
+-                eglDestroySurface(d->eglContext->display(), d->eglSurface);
+-        }
++        d->destroyEglSurfaceForDevice();
+         delete d->eglContext;
+     }
+     d->eglContext = 0;
+@@ -198,6 +186,26 @@ void QGLContext::swapBuffers() const
+     d->eglContext->swapBuffers(d->eglSurface);
+ }
++void QGLContextPrivate::destroyEglSurfaceForDevice()
++{
++    if (eglSurface != EGL_NO_SURFACE) {
++#ifdef Q_WS_X11
++        // Make sure we don't call eglDestroySurface on a surface which
++        // was created for a different winId:
++        if (paintDevice->devType() == QInternal::Widget) {
++            QGLWidget* w = static_cast<QGLWidget*>(paintDevice);
++
++            if (w->d_func()->eglSurfaceWindowId == w->winId())
++                eglDestroySurface(eglContext->display(), eglSurface);
++            else
++                qWarning("WARNING: Potential EGL surface leak!");
++        } else
++#endif
++            eglDestroySurface(eglContext->display(), eglSurface);
++        eglSurface = EGL_NO_SURFACE;
++    }
++}
++
+ void QGLWidget::setMouseTracking(bool enable)
+ {
+     QWidget::setMouseTracking(enable);
+diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h
+index 11770d3..99c0f33 100644
+--- a/src/opengl/qgl_p.h
++++ b/src/opengl/qgl_p.h
+@@ -288,6 +288,7 @@ public:
+ #if defined(QT_OPENGL_ES)
+     QEglContext *eglContext;
+     EGLSurface eglSurface;
++    void destroyEglSurfaceForDevice();
+ #elif defined(Q_WS_X11) || defined(Q_WS_MAC)
+     void* cx;
+ #endif
+-- 
+1.6.5
+
diff --git a/recipes/qt4/qt-4.6.0/1136-Disable-depth-testing-during-the-2D-QGLWidget-render.patch b/recipes/qt4/qt-4.6.0/1136-Disable-depth-testing-during-the-2D-QGLWidget-render.patch
new file mode 100644 (file)
index 0000000..30abab6
--- /dev/null
@@ -0,0 +1,54 @@
+From 7371d787d9b2667132c0caadb9964189b1d8c9fc Mon Sep 17 00:00:00 2001
+From: Rhys Weatherley <rhys.weatherley@nokia.com>
+Date: Thu, 17 Dec 2009 11:17:11 +1000
+Subject: [PATCH 1136/1244] Disable depth testing during the 2D QGLWidget::renderText()
+
+Also document the depth testing conditions for the 2D and 3D
+versions of the function.
+
+Task-number: QTBUG-5041
+Reviewed-by: Daniel Pope
+---
+ src/opengl/qgl.cpp |   12 ++++++++++++
+ 1 files changed, 12 insertions(+), 0 deletions(-)
+
+diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp
+index 32534aa..466e851 100644
+--- a/src/opengl/qgl.cpp
++++ b/src/opengl/qgl.cpp
+@@ -4302,6 +4302,7 @@ static void qt_save_gl_state()
+     glDisable(GL_CULL_FACE);
+     glDisable(GL_LIGHTING);
+     glDisable(GL_STENCIL_TEST);
++    glDisable(GL_DEPTH_TEST);
+     glEnable(GL_BLEND);
+     glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ }
+@@ -4355,6 +4356,10 @@ static void qt_gl_draw_text(QPainter *p, int x, int y, const QString &str,
+    \note This function clears the stencil buffer.
+    \note This function is not supported on OpenGL/ES systems.
++
++   \note This function temporarily disables depth-testing when the
++   text is drawn.
++
+    \l{Overpainting Example}{Overpaint} with QPainter::drawText() instead.
+ */
+@@ -4445,6 +4450,13 @@ void QGLWidget::renderText(int x, int y, const QString &str, const QFont &font,
+     have the labels move with the model as it is rotated etc.
+     \note This function is not supported on OpenGL/ES systems.
++
++    \note If depth testing is enabled before this function is called,
++    then the drawn text will be depth-tested against the models that
++    have already been drawn in the scene.  Use \c{glDisable(GL_DEPTH_TEST)}
++    before calling this function to annotate the models without
++    depth-testing the text.
++
+     \l{Overpainting Example}{Overpaint} with QPainter::drawText() instead.
+ */
+ void QGLWidget::renderText(double x, double y, double z, const QString &str, const QFont &font, int)
+-- 
+1.6.5
+
diff --git a/recipes/qt4/qt-4.6.0/1149-GL2Engine-Don-t-mark-brush-as-dirty-if-it-hasn-t-cha.patch b/recipes/qt4/qt-4.6.0/1149-GL2Engine-Don-t-mark-brush-as-dirty-if-it-hasn-t-cha.patch
new file mode 100644 (file)
index 0000000..49cd32b
--- /dev/null
@@ -0,0 +1,307 @@
+From ca30ced65ead8e81dfcb25178f4bfb6244487356 Mon Sep 17 00:00:00 2001
+From: Tom Cooksey <thomas.cooksey@nokia.com>
+Date: Thu, 17 Dec 2009 14:34:16 +0100
+Subject: [PATCH 1149/1244] GL2Engine: Don't mark brush as dirty if it hasn't changed
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+If the same brush is used over and over again, this gives a
+huge performance boost (measured to be 25% faster on desktop
+and 73% faster on SGX).
+
+Reviewed-By: Samuel Rødal
+---
+ .../gl2paintengineex/qglengineshadermanager.cpp    |    1 +
+ .../gl2paintengineex/qpaintengineex_opengl2.cpp    |   69 +++++++++++---------
+ .../gl2paintengineex/qpaintengineex_opengl2_p.h    |    5 +-
+ 3 files changed, 41 insertions(+), 34 deletions(-)
+
+diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp
+index 8a8f483..1187c2d 100644
+--- a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp
++++ b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp
+@@ -406,6 +406,7 @@ void QGLEngineShaderManager::setDirty()
+ void QGLEngineShaderManager::setSrcPixelType(Qt::BrushStyle style)
+ {
++    Q_ASSERT(style != Qt::NoBrush);
+     if (srcPixelType == PixelSrcType(style))
+         return;
+diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
+index fb9bcb4..8ca2fd4 100644
+--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
++++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
+@@ -386,19 +386,25 @@ inline QColor qt_premultiplyColor(QColor c, GLfloat opacity)
+ }
+-void QGL2PaintEngineExPrivate::setBrush(const QBrush* brush)
++void QGL2PaintEngineExPrivate::setBrush(const QBrush& brush)
+ {
++    Q_ASSERT(brush.style() != Qt::NoBrush);
++
++    if (qbrush_fast_equals(currentBrush, brush))
++        return;
++
+     currentBrush = brush;
++
+     brushTextureDirty = true;
+     brushUniformsDirty = true;
+-    if (currentBrush->style() == Qt::TexturePattern
+-        && qHasPixmapTexture(*brush) && brush->texture().isQBitmap())
++    if (currentBrush.style() == Qt::TexturePattern
++        && qHasPixmapTexture(brush) && brush.texture().isQBitmap())
+     {
+         shaderManager->setSrcPixelType(QGLEngineShaderManager::TextureSrcWithPattern);
+     } else {
+-        shaderManager->setSrcPixelType(currentBrush->style());
++        shaderManager->setSrcPixelType(currentBrush.style());
+     }
+-    shaderManager->optimiseForBrushTransform(currentBrush->transform());
++    shaderManager->optimiseForBrushTransform(currentBrush.transform());
+ }
+@@ -420,7 +426,7 @@ void QGL2PaintEngineExPrivate::updateBrushTexture()
+ {
+     Q_Q(QGL2PaintEngineEx);
+ //     qDebug("QGL2PaintEngineExPrivate::updateBrushTexture()");
+-    Qt::BrushStyle style = currentBrush->style();
++    Qt::BrushStyle style = currentBrush.style();
+     if ( (style >= Qt::Dense1Pattern) && (style <= Qt::DiagCrossPattern) ) {
+         // Get the image data for the pattern
+@@ -433,7 +439,7 @@ void QGL2PaintEngineExPrivate::updateBrushTexture()
+     else if (style >= Qt::LinearGradientPattern && style <= Qt::ConicalGradientPattern) {
+         // Gradiant brush: All the gradiants use the same texture
+-        const QGradient* g = currentBrush->gradient();
++        const QGradient* g = currentBrush.gradient();
+         // We apply global opacity in the fragment shaders, so we always pass 1.0
+         // for opacity to the cache.
+@@ -450,7 +456,7 @@ void QGL2PaintEngineExPrivate::updateBrushTexture()
+             updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE, q->state()->renderHints & QPainter::SmoothPixmapTransform);
+     }
+     else if (style == Qt::TexturePattern) {
+-        const QPixmap& texPixmap = currentBrush->texture();
++        const QPixmap& texPixmap = currentBrush.texture();
+         glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT);
+         QGLTexture *tex = ctx->d_func()->bindTexture(texPixmap, GL_TEXTURE_2D, GL_RGBA, QGLContext::InternalBindOption);
+@@ -464,15 +470,15 @@ void QGL2PaintEngineExPrivate::updateBrushTexture()
+ void QGL2PaintEngineExPrivate::updateBrushUniforms()
+ {
+ //     qDebug("QGL2PaintEngineExPrivate::updateBrushUniforms()");
+-    Qt::BrushStyle style = currentBrush->style();
++    Qt::BrushStyle style = currentBrush.style();
+     if (style == Qt::NoBrush)
+         return;
+-    QTransform brushQTransform = currentBrush->transform();
++    QTransform brushQTransform = currentBrush.transform();
+     if (style == Qt::SolidPattern) {
+-        QColor col = qt_premultiplyColor(currentBrush->color(), (GLfloat)q->state()->opacity);
++        QColor col = qt_premultiplyColor(currentBrush.color(), (GLfloat)q->state()->opacity);
+         shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::FragmentColor), col);
+     }
+     else {
+@@ -480,7 +486,7 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms()
+         QPointF translationPoint;
+         if (style <= Qt::DiagCrossPattern) {
+-            QColor col = qt_premultiplyColor(currentBrush->color(), (GLfloat)q->state()->opacity);
++            QColor col = qt_premultiplyColor(currentBrush.color(), (GLfloat)q->state()->opacity);
+             shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::PatternColor), col);
+@@ -488,7 +494,7 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms()
+             shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::HalfViewportSize), halfViewportSize);
+         }
+         else if (style == Qt::LinearGradientPattern) {
+-            const QLinearGradient *g = static_cast<const QLinearGradient *>(currentBrush->gradient());
++            const QLinearGradient *g = static_cast<const QLinearGradient *>(currentBrush.gradient());
+             QPointF realStart = g->start();
+             QPointF realFinal = g->finalStop();
+@@ -508,7 +514,7 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms()
+             shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::HalfViewportSize), halfViewportSize);
+         }
+         else if (style == Qt::ConicalGradientPattern) {
+-            const QConicalGradient *g = static_cast<const QConicalGradient *>(currentBrush->gradient());
++            const QConicalGradient *g = static_cast<const QConicalGradient *>(currentBrush.gradient());
+             translationPoint   = g->center();
+             GLfloat angle = -(g->angle() * 2 * Q_PI) / 360.0;
+@@ -519,7 +525,7 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms()
+             shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::HalfViewportSize), halfViewportSize);
+         }
+         else if (style == Qt::RadialGradientPattern) {
+-            const QRadialGradient *g = static_cast<const QRadialGradient *>(currentBrush->gradient());
++            const QRadialGradient *g = static_cast<const QRadialGradient *>(currentBrush.gradient());
+             QPointF realCenter = g->center();
+             QPointF realFocal  = g->focalPoint();
+             qreal   realRadius = g->radius();
+@@ -537,10 +543,10 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms()
+             shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::HalfViewportSize), halfViewportSize);
+         }
+         else if (style == Qt::TexturePattern) {
+-            const QPixmap& texPixmap = currentBrush->texture();
++            const QPixmap& texPixmap = currentBrush.texture();
+-            if (qHasPixmapTexture(*currentBrush) && currentBrush->texture().isQBitmap()) {
+-                QColor col = qt_premultiplyColor(currentBrush->color(), (GLfloat)q->state()->opacity);
++            if (qHasPixmapTexture(currentBrush) && currentBrush.texture().isQBitmap()) {
++                QColor col = qt_premultiplyColor(currentBrush.color(), (GLfloat)q->state()->opacity);
+                 shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::PatternColor), col);
+             }
+@@ -561,7 +567,7 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms()
+         QTransform gl_to_qt(1, 0, 0, -1, 0, height);
+         QTransform inv_matrix;
+         if (style == Qt::TexturePattern && textureInvertedY == -1)
+-            inv_matrix = gl_to_qt * (QTransform(1, 0, 0, -1, 0, currentBrush->texture().height()) * brushQTransform * matrix).inverted() * translate;
++            inv_matrix = gl_to_qt * (QTransform(1, 0, 0, -1, 0, currentBrush.texture().height()) * brushQTransform * matrix).inverted() * translate;
+         else
+             inv_matrix = gl_to_qt * (brushQTransform * matrix).inverted() * translate;
+@@ -866,7 +872,7 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path)
+     // Check to see if there's any hints
+     if (path.shape() == QVectorPath::RectangleHint) {
+         QGLRect rect(points[0].x(), points[0].y(), points[2].x(), points[2].y());
+-        prepareForDraw(currentBrush->isOpaque());
++        prepareForDraw(currentBrush.isOpaque());
+         composite(rect);
+     } else if (path.isConvex()) {
+@@ -914,7 +920,7 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path)
+ #endif
+             }
+-            prepareForDraw(currentBrush->isOpaque());
++            prepareForDraw(currentBrush.isOpaque());
+             glEnableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
+ #ifdef QT_OPENGL_CACHE_AS_VBOS
+             glBindBuffer(GL_ARRAY_BUFFER, cache->vbo);
+@@ -933,7 +939,7 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path)
+                 path.makeCacheable();
+             vertexCoordinateArray.clear();
+             vertexCoordinateArray.addPath(path, inverseScale, false);
+-            prepareForDraw(currentBrush->isOpaque());
++            prepareForDraw(currentBrush.isOpaque());
+             drawVertexArrays(vertexCoordinateArray, GL_TRIANGLE_FAN);
+         }
+@@ -958,7 +964,7 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path)
+             glStencilFunc(GL_NOTEQUAL, 0, GL_STENCIL_HIGH_BIT);
+         }
+-        prepareForDraw(currentBrush->isOpaque());
++        prepareForDraw(currentBrush.isOpaque());
+         if (inRenderText)
+             prepareDepthRangeForRenderText();
+@@ -1155,10 +1161,10 @@ bool QGL2PaintEngineExPrivate::prepareForDraw(bool srcPixelsAreOpaque)
+                                       : QGLEngineShaderManager::NoOpacity;
+         if (stateHasOpacity && (mode != ImageDrawingMode)) {
+             // Using a brush
+-            bool brushIsPattern = (currentBrush->style() >= Qt::Dense1Pattern) &&
+-                                  (currentBrush->style() <= Qt::DiagCrossPattern);
++            bool brushIsPattern = (currentBrush.style() >= Qt::Dense1Pattern) &&
++                                  (currentBrush.style() <= Qt::DiagCrossPattern);
+-            if ((currentBrush->style() == Qt::SolidPattern) || brushIsPattern)
++            if ((currentBrush.style() == Qt::SolidPattern) || brushIsPattern)
+                 opacityMode = QGLEngineShaderManager::NoOpacity; // Global opacity handled by srcPixel shader
+         }
+     }
+@@ -1286,7 +1292,7 @@ void QGL2PaintEngineEx::fill(const QVectorPath &path, const QBrush &brush)
+         d->matrixDirty = true;
+     }
+-    d->setBrush(&brush);
++    d->setBrush(brush);
+     d->fill(path);
+     if (doOffset) {
+@@ -1325,7 +1331,7 @@ void QGL2PaintEngineEx::stroke(const QVectorPath &path, const QPen &pen)
+     }
+     bool opaque = penBrush.isOpaque() && s->opacity > 0.99;
+-    d->setBrush(&penBrush);
++    d->setBrush(penBrush);
+     d->transferMode(BrushDrawingMode);
+     // updateMatrix() is responsible for setting the inverse scale on
+@@ -1604,7 +1610,7 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(const QPointF &p, QFontEngineGly
+         glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, textureCoordinateArray.data());
+     QBrush pensBrush = q->state()->pen.brush();
+-    setBrush(&pensBrush);
++    setBrush(pensBrush);
+     if (inRenderText)
+         prepareDepthRangeForRenderText();
+@@ -1649,7 +1655,7 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(const QPointF &p, QFontEngineGly
+                 q->state()->opacity = 1;
+                 opacityUniformDirty = true;
+                 pensBrush = Qt::white;
+-                setBrush(&pensBrush);
++                setBrush(pensBrush);
+             }
+             compositionModeDirty = false; // I can handle this myself, thank you very much
+@@ -1670,7 +1676,7 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(const QPointF &p, QFontEngineGly
+                 q->state()->opacity = oldOpacity;
+                 opacityUniformDirty = true;
+                 pensBrush = q->state()->pen.brush();
+-                setBrush(&pensBrush);
++                setBrush(pensBrush);
+             }
+             compositionModeDirty = false;
+@@ -1815,6 +1821,7 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev)
+     d->opacityUniformDirty = true;
+     d->needsSync = true;
+     d->use_system_clip = !systemClip().isEmpty();
++    d->currentBrush = QBrush();
+     d->dirtyStencilRegion = QRect(0, 0, d->width, d->height);
+     d->stencilClean = true;
+diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
+index 77ca3a8..33ce24d 100644
+--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
++++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
+@@ -171,7 +171,6 @@ public:
+             q(q_ptr),
+             width(0), height(0),
+             ctx(0),
+-            currentBrush(0),
+             inverseScale(1),
+             shaderManager(0),
+             inRenderText(false)
+@@ -185,7 +184,7 @@ public:
+     void updateCompositionMode();
+     void updateTextureFilter(GLenum target, GLenum wrapMode, bool smoothPixmapTransform, GLuint id = -1);
+-    void setBrush(const QBrush* brush);
++    void setBrush(const QBrush& brush);
+     void transferMode(EngineMode newMode);
+     void resetGLState();
+@@ -244,7 +243,7 @@ public:
+     QRect currentScissorBounds;
+     uint maxClip;
+-    const QBrush*    currentBrush; // May not be the state's brush!
++    QBrush currentBrush; // May not be the state's brush!
+     GLfloat     inverseScale;
+-- 
+1.6.5
+
diff --git a/recipes/qt4/qt-4.6.0/1157-Align-GL_RGB-lines-on-a-4-byte-boundary-when-uploadi.patch b/recipes/qt4/qt-4.6.0/1157-Align-GL_RGB-lines-on-a-4-byte-boundary-when-uploadi.patch
new file mode 100644 (file)
index 0000000..4029d0d
--- /dev/null
@@ -0,0 +1,45 @@
+From 87777f7c0f4c3e338d23d2c3d368a8a484a35a6e Mon Sep 17 00:00:00 2001
+From: Rhys Weatherley <rhys.weatherley@nokia.com>
+Date: Fri, 18 Dec 2009 15:01:07 +1000
+Subject: [PATCH 1157/1244] Align GL_RGB lines on a 4-byte boundary when uploading pixmap textures
+
+Previous code was aligning lines on a 3-byte boundary.
+
+Task-number: QTBUG-6902
+Reviewed-by: Julian de Bhal
+---
+ src/opengl/qpixmapdata_gl.cpp |   15 ++-------------
+ 1 files changed, 2 insertions(+), 13 deletions(-)
+
+diff --git a/src/opengl/qpixmapdata_gl.cpp b/src/opengl/qpixmapdata_gl.cpp
+index 4e1d50d..92c990b 100644
+--- a/src/opengl/qpixmapdata_gl.cpp
++++ b/src/opengl/qpixmapdata_gl.cpp
+@@ -341,22 +341,11 @@ void QGLPixmapData::ensureCreated() const
+     if (!m_source.isNull()) {
+         if (external_format == GL_RGB) {
+-            QImage tx = m_source.convertToFormat(QImage::Format_RGB32);
+-
+-            QVector<uchar> pixelData(w * h * 3);
+-            uchar *p = &pixelData[0];
+-            QRgb *src = (QRgb *)tx.bits();
+-
+-            for (int i = 0; i < w * h; ++i) {
+-                *p++ = qRed(*src);
+-                *p++ = qGreen(*src);
+-                *p++ = qBlue(*src);
+-                ++src;
+-            }
++            const QImage tx = m_source.convertToFormat(QImage::Format_RGB888);
+             glBindTexture(target, m_texture.id);
+             glTexSubImage2D(target, 0, 0, 0, w, h, external_format,
+-                            GL_UNSIGNED_BYTE, &pixelData[0]);
++                            GL_UNSIGNED_BYTE, tx.bits());
+         } else {
+             const QImage tx = ctx->d_func()->convertToGLFormat(m_source, true, external_format);
+-- 
+1.6.5
+
diff --git a/recipes/qt4/qt-4.6.0/1165-NEON-configure-detection-and-initial-blend-function-.patch b/recipes/qt4/qt-4.6.0/1165-NEON-configure-detection-and-initial-blend-function-.patch
new file mode 100644 (file)
index 0000000..9d2ca87
--- /dev/null
@@ -0,0 +1,593 @@
+
+Adds new NEON configure test and -no-neon configure option. NEON
+implementations can also be turned off by setting the QT_NO_NEON
+environment variable.
+
+Performance improvements (in frames per second):
+- Blending ARGB32 on RGB32/ARGB32, mostly opaque: 71 %
+- Blending ARGB32 on RGB32/ARGB32, no opaque pixels: 108 %
+- Blending ARGB32 on RGB32/ARGB32, with 0.5 opacity: 158 %
+- Blending RGB32 on RGB32/ARGB32, with 0.5 opacity: 189 %
+
+Task-number: QTBUG-6684
+Reviewed-by: Gunnar Sletta
+Reviewed-by: Paul Olav Tvete
+---
+ config.tests/unix/neon/neon.cpp       |   51 +++++++
+ config.tests/unix/neon/neon.pro       |    2 +
+ configure                             |   22 +++-
+ src/gui/painting/painting.pri         |    7 +
+ src/gui/painting/qblendfunctions.cpp  |    2 +-
+ src/gui/painting/qdrawhelper.cpp      |   16 ++-
+ src/gui/painting/qdrawhelper_neon.cpp |  260 +++++++++++++++++++++++++++++++++
+ src/gui/painting/qdrawhelper_neon_p.h |   76 ++++++++++
+ 8 files changed, 432 insertions(+), 4 deletions(-)
+ create mode 100644 config.tests/unix/neon/neon.cpp
+ create mode 100644 config.tests/unix/neon/neon.pro
+ create mode 100644 src/gui/painting/qdrawhelper_neon.cpp
+ create mode 100644 src/gui/painting/qdrawhelper_neon_p.h
+
+diff --git a/config.tests/unix/neon/neon.cpp b/config.tests/unix/neon/neon.cpp
+new file mode 100644
+index 0000000..c31a9fd
+--- /dev/null
++++ b/config.tests/unix/neon/neon.cpp
+@@ -0,0 +1,51 @@
++/****************************************************************************
++**
++** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
++** All rights reserved.
++** Contact: Nokia Corporation (qt-info@nokia.com)
++**
++** This file is part of the config.tests of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:LGPL$
++** No Commercial Usage
++** This file contains pre-release code and may not be distributed.
++** You may use this file in accordance with the terms and conditions
++** contained in the Technology Preview License Agreement accompanying
++** this package.
++**
++** GNU Lesser General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU Lesser
++** General Public License version 2.1 as published by the Free Software
++** Foundation and appearing in the file LICENSE.LGPL included in the
++** packaging of this file.  Please review the following information to
++** ensure the GNU Lesser General Public License version 2.1 requirements
++** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
++**
++** In addition, as a special exception, Nokia gives you certain additional
++** rights.  These rights are described in the Nokia Qt LGPL Exception
++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
++**
++** If you have questions regarding the use of this file, please contact
++** Nokia at qt-info@nokia.com.
++**
++**
++**
++**
++**
++**
++**
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++#include <arm_neon.h>
++
++int main(int, char**)
++{
++    int32x4_t null = vdupq_n_s32(0x0);
++
++    int result;
++    vst1q_lane_s32(&result, null, 0);
++    return result;
++}
+diff --git a/config.tests/unix/neon/neon.pro b/config.tests/unix/neon/neon.pro
+new file mode 100644
+index 0000000..de20c4e
+--- /dev/null
++++ b/config.tests/unix/neon/neon.pro
+@@ -0,0 +1,2 @@
++SOURCES = neon.cpp
++CONFIG -= x11 qt
+diff --git a/configure b/configure
+index 2114863..22e6bd4 100755
+--- a/configure
++++ b/configure
+@@ -745,6 +745,7 @@ CFG_HOST_ENDIAN=auto
+ CFG_DOUBLEFORMAT=auto
+ CFG_ARMFPA=auto
+ CFG_IWMMXT=no
++CFG_NEON=auto
+ CFG_CLOCK_GETTIME=auto
+ CFG_CLOCK_MONOTONIC=auto
+ CFG_MREMAP=auto
+@@ -1604,6 +1605,13 @@ while [ "$#" -gt 0 ]; do
+     iwmmxt)
+       CFG_IWMMXT="yes"
+       ;;
++    neon)
++        if [ "$VAL" = "no" ]; then
++            CFG_NEON="$VAL"
++        else
++            UNKNOWN_OPT=yes
++        fi
++        ;;
+     reduce-relocations)
+         if [ "$VAL" = "yes" ] || [ "$VAL" = "no" ]; then
+             CFG_REDUCE_RELOCATIONS="$VAL"
+@@ -3889,6 +3897,7 @@ Qt for Embedded Linux only:
+     -iwmmxt ............ Compile using the iWMMXt instruction set
+                          (available on some XScale CPUs).
++    -no-neon ........... Do not compile with use of NEON instructions.
+ EOF
+ fi
+@@ -4509,6 +4518,15 @@ if [ "$CFG_IWMMXT" = "yes" ]; then
+     fi
+ fi
++# detect neon support
++if ([ "${CFG_ARCH}" = "arm" ] || [ "${CFG_ARCH}" = "armv6" ]) && [ "${CFG_NEON}" = "auto" ]; then
++    if "$unixtests/compile.test" "$XQMAKESPEC" "$QMAKE_CONFIG" $OPT_VERBOSE "$relpath" "$outpath" config.tests/unix/neon "neon" $L_FLAGS $I_FLAGS $l_FLAGS "-mfpu=neon"; then
++      CFG_NEON=yes
++    else
++      CFG_NEON=no
++    fi
++fi
++
+ # detect zlib
+ if [ "$CFG_ZLIB" = "no" ]; then
+     # Note: Qt no longer support builds without zlib
+@@ -6124,6 +6142,7 @@ fi
+ [ "$CFG_SSE" = "yes" ] && QMAKE_CONFIG="$QMAKE_CONFIG sse"
+ [ "$CFG_SSE2" = "yes" ] && QMAKE_CONFIG="$QMAKE_CONFIG sse2"
+ [ "$CFG_IWMMXT" = "yes" ] && QMAKE_CONFIG="$QMAKE_CONFIG iwmmxt"
++[ "$CFG_NEON" = "yes" ] && QMAKE_CONFIG="$QMAKE_CONFIG neon"
+ [ "$PLATFORM_MAC" = "yes" ] && QMAKE_CONFIG="$QMAKE_CONFIG $CFG_MAC_ARCHS"
+ if [ "$CFG_IPV6" = "yes" ]; then
+     QT_CONFIG="$QT_CONFIG ipv6"
+@@ -7416,8 +7435,9 @@ echo "Declarative module .. $CFG_DECLARATIVE"
+ echo "STL support ......... $CFG_STL"
+ echo "PCH support ......... $CFG_PRECOMPILE"
+ echo "MMX/3DNOW/SSE/SSE2..  ${CFG_MMX}/${CFG_3DNOW}/${CFG_SSE}/${CFG_SSE2}"
+-if [ "${CFG_ARCH}" = "arm" ]; then
++if [ "${CFG_ARCH}" = "arm" ] || [ "${CFG_ARCH}" = "armv6" ]; then
+     echo "iWMMXt support ...... ${CFG_IWMMXT}"
++    echo "NEON support ........ ${CFG_NEON}"
+ fi
+ [ "${PLATFORM_QWS}" != "yes" ] && echo "Graphics System ..... $CFG_GRAPHICS_SYSTEM"
+ echo "IPv6 support ........ $CFG_IPV6"
+diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri
+index 628a109..0b1e79a 100644
+--- a/src/gui/painting/painting.pri
++++ b/src/gui/painting/painting.pri
+@@ -379,6 +379,13 @@ symbian {
+         QMAKE_CXXFLAGS.ARMCC *= -O3
+ }
++neon {
++    DEFINES += QT_HAVE_NEON
++    HEADERS += painting/qdrawhelper_neon_p.h
++    SOURCES += painting/qdrawhelper_neon.cpp
++    
++}
++
+ contains(QT_CONFIG, zlib) {
+    INCLUDEPATH += ../3rdparty/zlib
+ } else:!contains(QT_CONFIG, no-zlib) {
+diff --git a/src/gui/painting/qblendfunctions.cpp b/src/gui/painting/qblendfunctions.cpp
+index 1d15dac..81d1515 100644
+--- a/src/gui/painting/qblendfunctions.cpp
++++ b/src/gui/painting/qblendfunctions.cpp
+@@ -605,7 +605,7 @@ static void qt_blend_argb32_on_argb32(uchar *destPixels, int dbpl,
+ }
+-static void qt_blend_rgb32_on_rgb32(uchar *destPixels, int dbpl,
++void qt_blend_rgb32_on_rgb32(uchar *destPixels, int dbpl,
+                              const uchar *srcPixels, int sbpl,
+                              int w, int h,
+                              int const_alpha)
+diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp
+index 23236ec..84cf5cc 100644
+--- a/src/gui/painting/qdrawhelper.cpp
++++ b/src/gui/painting/qdrawhelper.cpp
+@@ -44,6 +44,7 @@
+ #include <private/qpainter_p.h>
+ #include <private/qdrawhelper_x86_p.h>
+ #include <private/qdrawhelper_armv6_p.h>
++#include <private/qdrawhelper_neon_p.h>
+ #include <private/qmath_p.h>
+ #include <qmath.h>
+@@ -7725,7 +7726,8 @@ enum CPUFeatures {
+     SSE         = 0x10,
+     SSE2        = 0x20,
+     CMOV        = 0x40,
+-    IWMMXT      = 0x80
++    IWMMXT      = 0x80,
++    NEON        = 0x100
+ };
+ static uint detectCPUFeatures()
+@@ -7751,6 +7753,9 @@ static uint detectCPUFeatures()
+     // runtime detection only available when running as a previlegied process
+     static const bool doIWMMXT = !qgetenv("QT_NO_IWMMXT").toInt();
+     return doIWMMXT ? IWMMXT : 0;
++#elif defined(QT_HAVE_NEON)
++    static const bool doNEON = !qgetenv("QT_NO_NEON").toInt();
++    return doNEON ? NEON : 0;
+ #else
+     uint features = 0;
+ #if defined(__x86_64__) || defined(Q_OS_WIN64)
+@@ -8122,7 +8127,14 @@ void qInitDrawhelperAsm()
+         qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_armv6;
+         qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_armv6;
+         qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_armv6;
+-#endif // Q_CC_RVCT && QT_HAVE_ARMV6
++#elif defined(QT_HAVE_NEON)
++        if (features & NEON) {
++            qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_neon;
++            qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_neon;
++            qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_neon;
++            qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_neon;
++        }
++#endif
+     if (functionForModeSolidAsm) {
+         const int destinationMode = QPainter::CompositionMode_Destination;
+diff --git a/src/gui/painting/qdrawhelper_neon.cpp b/src/gui/painting/qdrawhelper_neon.cpp
+new file mode 100644
+index 0000000..7fe11bf
+--- /dev/null
++++ b/src/gui/painting/qdrawhelper_neon.cpp
+@@ -0,0 +1,260 @@
++/****************************************************************************
++**
++** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
++** All rights reserved.
++** Contact: Nokia Corporation (qt-info@nokia.com)
++**
++** This file is part of the QtGui module of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:LGPL$
++** No Commercial Usage
++** This file contains pre-release code and may not be distributed.
++** You may use this file in accordance with the terms and conditions
++** contained in the Technology Preview License Agreement accompanying
++** this package.
++**
++** GNU Lesser General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU Lesser
++** General Public License version 2.1 as published by the Free Software
++** Foundation and appearing in the file LICENSE.LGPL included in the
++** packaging of this file.  Please review the following information to
++** ensure the GNU Lesser General Public License version 2.1 requirements
++** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
++**
++** In addition, as a special exception, Nokia gives you certain additional
++** rights.  These rights are described in the Nokia Qt LGPL Exception
++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
++**
++** If you have questions regarding the use of this file, please contact
++** Nokia at qt-info@nokia.com.
++**
++**
++**
++**
++**
++**
++**
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++#include <private/qdrawhelper_p.h>
++
++#ifdef QT_HAVE_NEON
++
++#include <private/qdrawhelper_neon_p.h>
++#include <arm_neon.h>
++
++QT_BEGIN_NAMESPACE
++
++static inline int16x8_t qvdiv_255_s16(int16x8_t x, int16x8_t half)
++{
++    // result = (x + (x >> 8) + 0x80) >> 8
++
++    const int16x8_t temp = vshrq_n_s16(x, 8); // x >> 8
++    const int16x8_t sum_part = vaddq_s16(x, half); // x + 0x80
++    const int16x8_t sum = vaddq_s16(temp, sum_part);
++
++    return vreinterpretq_s16_u16(vshrq_n_u16(vreinterpretq_u16_s16(sum), 8));
++}
++
++static inline int16x8_t qvbyte_mul_s16(int16x8_t x, int16x8_t alpha, int16x8_t half)
++{
++    // t = qRound(x * alpha / 255.0)
++
++    const int16x8_t t = vmulq_s16(x, alpha); // t
++    return qvdiv_255_s16(t, half);
++}
++
++static inline int16x8_t qvinterpolate_pixel_255(int16x8_t x, int16x8_t a, int16x8_t y, int16x8_t b, int16x8_t half)
++{
++    // t = x * a + y * b
++
++    const int16x8_t ta = vmulq_s16(x, a);
++    const int16x8_t tb = vmulq_s16(y, b);
++
++    return qvdiv_255_s16(vaddq_s16(ta, tb), half);
++}
++
++static inline int16x8_t qvsource_over_s16(int16x8_t src16, int16x8_t dst16, int16x8_t half, int16x8_t full)
++{
++    const int16x4_t alpha16_high = vdup_lane_s16(vget_high_s16(src16), 3);
++    const int16x4_t alpha16_low = vdup_lane_s16(vget_low_s16(src16), 3);
++
++    const int16x8_t alpha16 = vsubq_s16(full, vcombine_s16(alpha16_low, alpha16_high));
++
++    return vaddq_s16(src16, qvbyte_mul_s16(dst16, alpha16, half));
++}
++
++void qt_blend_argb32_on_argb32_neon(uchar *destPixels, int dbpl,
++                                    const uchar *srcPixels, int sbpl,
++                                    int w, int h,
++                                    int const_alpha)
++{
++    const uint *src = (const uint *) srcPixels;
++    uint *dst = (uint *) destPixels;
++    int16x8_t half = vdupq_n_s16(0x80);
++    int16x8_t full = vdupq_n_s16(0xff);
++    if (const_alpha == 256) {
++        for (int y = 0; y < h; ++y) {
++            int x = 0;
++            for (; x < w-3; x += 4) {
++                int32x4_t src32 = vld1q_s32((int32_t *)&src[x]);
++                if ((src[x] & src[x+1] & src[x+2] & src[x+3]) >= 0xff000000) {
++                    // all opaque
++                    vst1q_s32((int32_t *)&dst[x], src32);
++                } else if (src[x] | src[x+1] | src[x+2] | src[x+3]) {
++                    int32x4_t dst32 = vld1q_s32((int32_t *)&dst[x]);
++
++                    const uint8x16_t src8 = vreinterpretq_u8_s32(src32);
++                    const uint8x16_t dst8 = vreinterpretq_u8_s32(dst32);
++
++                    const uint8x8_t src8_low = vget_low_u8(src8);
++                    const uint8x8_t dst8_low = vget_low_u8(dst8);
++
++                    const uint8x8_t src8_high = vget_high_u8(src8);
++                    const uint8x8_t dst8_high = vget_high_u8(dst8);
++
++                    const int16x8_t src16_low = vreinterpretq_s16_u16(vmovl_u8(src8_low));
++                    const int16x8_t dst16_low = vreinterpretq_s16_u16(vmovl_u8(dst8_low));
++
++                    const int16x8_t src16_high = vreinterpretq_s16_u16(vmovl_u8(src8_high));
++                    const int16x8_t dst16_high = vreinterpretq_s16_u16(vmovl_u8(dst8_high));
++
++                    const int16x8_t result16_low = qvsource_over_s16(src16_low, dst16_low, half, full);
++                    const int16x8_t result16_high = qvsource_over_s16(src16_high, dst16_high, half, full);
++
++                    const int32x2_t result32_low = vreinterpret_s32_s8(vmovn_s16(result16_low));
++                    const int32x2_t result32_high = vreinterpret_s32_s8(vmovn_s16(result16_high));
++
++                    vst1q_s32((int32_t *)&dst[x], vcombine_s32(result32_low, result32_high));
++                }
++            }
++            for (; x<w; ++x) {
++                uint s = src[x];
++                if (s >= 0xff000000)
++                    dst[x] = s;
++                else if (s != 0)
++                    dst[x] = s + BYTE_MUL(dst[x], qAlpha(~s));
++            }
++            dst = (quint32 *)(((uchar *) dst) + dbpl);
++            src = (const quint32 *)(((const uchar *) src) + sbpl);
++        }
++    } else if (const_alpha != 0) {
++        const_alpha = (const_alpha * 255) >> 8;
++        int16x8_t const_alpha16 = vdupq_n_s16(const_alpha);
++        for (int y = 0; y < h; ++y) {
++            int x = 0;
++            for (; x < w-3; x += 4) {
++                if (src[x] | src[x+1] | src[x+2] | src[x+3]) {
++                    int32x4_t src32 = vld1q_s32((int32_t *)&src[x]);
++                    int32x4_t dst32 = vld1q_s32((int32_t *)&dst[x]);
++
++                    const uint8x16_t src8 = vreinterpretq_u8_s32(src32);
++                    const uint8x16_t dst8 = vreinterpretq_u8_s32(dst32);
++
++                    const uint8x8_t src8_low = vget_low_u8(src8);
++                    const uint8x8_t dst8_low = vget_low_u8(dst8);
++
++                    const uint8x8_t src8_high = vget_high_u8(src8);
++                    const uint8x8_t dst8_high = vget_high_u8(dst8);
++
++                    const int16x8_t src16_low = vreinterpretq_s16_u16(vmovl_u8(src8_low));
++                    const int16x8_t dst16_low = vreinterpretq_s16_u16(vmovl_u8(dst8_low));
++
++                    const int16x8_t src16_high = vreinterpretq_s16_u16(vmovl_u8(src8_high));
++                    const int16x8_t dst16_high = vreinterpretq_s16_u16(vmovl_u8(dst8_high));
++
++                    const int16x8_t srcalpha16_low = qvbyte_mul_s16(src16_low, const_alpha16, half);
++                    const int16x8_t srcalpha16_high = qvbyte_mul_s16(src16_high, const_alpha16, half);
++
++                    const int16x8_t result16_low = qvsource_over_s16(srcalpha16_low, dst16_low, half, full);
++                    const int16x8_t result16_high = qvsource_over_s16(srcalpha16_high, dst16_high, half, full);
++
++                    const int32x2_t result32_low = vreinterpret_s32_s8(vmovn_s16(result16_low));
++                    const int32x2_t result32_high = vreinterpret_s32_s8(vmovn_s16(result16_high));
++
++                    vst1q_s32((int32_t *)&dst[x], vcombine_s32(result32_low, result32_high));
++                }
++            }
++            for (; x<w; ++x) {
++                uint s = src[x];
++                if (s != 0) {
++                    s = BYTE_MUL(s, const_alpha);
++                    dst[x] = s + BYTE_MUL(dst[x], qAlpha(~s));
++                }
++            }
++            dst = (quint32 *)(((uchar *) dst) + dbpl);
++            src = (const quint32 *)(((const uchar *) src) + sbpl);
++        }
++    }
++}
++
++// qblendfunctions.cpp
++void qt_blend_rgb32_on_rgb32(uchar *destPixels, int dbpl,
++                             const uchar *srcPixels, int sbpl,
++                             int w, int h,
++                             int const_alpha);
++
++void qt_blend_rgb32_on_rgb32_neon(uchar *destPixels, int dbpl,
++                                  const uchar *srcPixels, int sbpl,
++                                  int w, int h,
++                                  int const_alpha)
++{
++    if (const_alpha != 256) {
++        if (const_alpha != 0) {
++            const uint *src = (const uint *) srcPixels;
++            uint *dst = (uint *) destPixels;
++            int16x8_t half = vdupq_n_s16(0x80);
++            const_alpha = (const_alpha * 255) >> 8;
++            int one_minus_const_alpha = 255 - const_alpha;
++            int16x8_t const_alpha16 = vdupq_n_s16(const_alpha);
++            int16x8_t one_minus_const_alpha16 = vdupq_n_s16(255 - const_alpha);
++            for (int y = 0; y < h; ++y) {
++                int x = 0;
++                for (; x < w-3; x += 4) {
++                    int32x4_t src32 = vld1q_s32((int32_t *)&src[x]);
++                    int32x4_t dst32 = vld1q_s32((int32_t *)&dst[x]);
++
++                    const uint8x16_t src8 = vreinterpretq_u8_s32(src32);
++                    const uint8x16_t dst8 = vreinterpretq_u8_s32(dst32);
++
++                    const uint8x8_t src8_low = vget_low_u8(src8);
++                    const uint8x8_t dst8_low = vget_low_u8(dst8);
++
++                    const uint8x8_t src8_high = vget_high_u8(src8);
++                    const uint8x8_t dst8_high = vget_high_u8(dst8);
++
++                    const int16x8_t src16_low = vreinterpretq_s16_u16(vmovl_u8(src8_low));
++                    const int16x8_t dst16_low = vreinterpretq_s16_u16(vmovl_u8(dst8_low));
++
++                    const int16x8_t src16_high = vreinterpretq_s16_u16(vmovl_u8(src8_high));
++                    const int16x8_t dst16_high = vreinterpretq_s16_u16(vmovl_u8(dst8_high));
++
++                    const int16x8_t result16_low = qvinterpolate_pixel_255(src16_low, const_alpha16, dst16_low, one_minus_const_alpha16, half);
++                    const int16x8_t result16_high = qvinterpolate_pixel_255(src16_high, const_alpha16, dst16_high, one_minus_const_alpha16, half);
++
++                    const int32x2_t result32_low = vreinterpret_s32_s8(vmovn_s16(result16_low));
++                    const int32x2_t result32_high = vreinterpret_s32_s8(vmovn_s16(result16_high));
++
++                    vst1q_s32((int32_t *)&dst[x], vcombine_s32(result32_low, result32_high));
++                }
++                for (; x<w; ++x) {
++                    uint s = src[x];
++                    s = BYTE_MUL(s, const_alpha);
++                    dst[x] = INTERPOLATE_PIXEL_255(src[x], const_alpha, dst[x], one_minus_const_alpha);
++                }
++                dst = (quint32 *)(((uchar *) dst) + dbpl);
++                src = (const quint32 *)(((const uchar *) src) + sbpl);
++            }
++        }
++    } else {
++        qt_blend_rgb32_on_rgb32(destPixels, dbpl, srcPixels, sbpl, w, h, const_alpha);
++    }
++}
++
++QT_END_NAMESPACE
++
++#endif // QT_HAVE_NEON
++
+diff --git a/src/gui/painting/qdrawhelper_neon_p.h b/src/gui/painting/qdrawhelper_neon_p.h
+new file mode 100644
+index 0000000..cb9a0d6
+--- /dev/null
++++ b/src/gui/painting/qdrawhelper_neon_p.h
+@@ -0,0 +1,76 @@
++/****************************************************************************
++**
++** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
++** All rights reserved.
++** Contact: Nokia Corporation (qt-info@nokia.com)
++**
++** This file is part of the QtGui module of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:LGPL$
++** No Commercial Usage
++** This file contains pre-release code and may not be distributed.
++** You may use this file in accordance with the terms and conditions
++** contained in the Technology Preview License Agreement accompanying
++** this package.
++**
++** GNU Lesser General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU Lesser
++** General Public License version 2.1 as published by the Free Software
++** Foundation and appearing in the file LICENSE.LGPL included in the
++** packaging of this file.  Please review the following information to
++** ensure the GNU Lesser General Public License version 2.1 requirements
++** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
++**
++** In addition, as a special exception, Nokia gives you certain additional
++** rights.  These rights are described in the Nokia Qt LGPL Exception
++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
++**
++** If you have questions regarding the use of this file, please contact
++** Nokia at qt-info@nokia.com.
++**
++**
++**
++**
++**
++**
++**
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++#ifndef QDRAWHELPER_NEON_P_H
++#define QDRAWHELPER_NEON_P_H
++
++//
++//  W A R N I N G
++//  -------------
++//
++// This file is not part of the Qt API.  It exists purely as an
++// implementation detail.  This header file may change from version to
++// version without notice, or even be removed.
++//
++// We mean it.
++//
++
++#include <private/qdrawhelper_p.h>
++
++QT_BEGIN_NAMESPACE
++
++#ifdef QT_HAVE_NEON
++
++void qt_blend_argb32_on_argb32_neon(uchar *destPixels, int dbpl,
++                                            const uchar *srcPixels, int sbpl,
++                                            int w, int h,
++                                            int const_alpha);
++
++void qt_blend_rgb32_on_rgb32_neon(uchar *destPixels, int dbpl,
++                                  const uchar *srcPixels, int sbpl,
++                                  int w, int h,
++                                  int const_alpha);
++
++#endif // QT_HAVE_NEON
++
++QT_END_NAMESPACE
++
++#endif // QDRAWHELPER_NEON_P_H
+-- 
+1.6.5
+
diff --git a/recipes/qt4/qt-4.6.0/1175-Fix-memory-leak-of-QGLGlyphCoord-objects-in-the-Open.patch b/recipes/qt4/qt-4.6.0/1175-Fix-memory-leak-of-QGLGlyphCoord-objects-in-the-Open.patch
new file mode 100644 (file)
index 0000000..7c79b6b
--- /dev/null
@@ -0,0 +1,60 @@
+From c2dca4c9f1eb360305de5ea520a0b322737dc600 Mon Sep 17 00:00:00 2001
+From: Rhys Weatherley <rhys.weatherley@nokia.com>
+Date: Mon, 21 Dec 2009 08:35:43 +1000
+Subject: [PATCH 1175/1244] Fix memory leak of QGLGlyphCoord objects in the OpenGL1 paint engine
+
+Task-number: QTBUG-6936
+Reviewed-by: Julian de Bhal
+---
+ src/opengl/qpaintengine_opengl.cpp |   14 +++++++++++---
+ 1 files changed, 11 insertions(+), 3 deletions(-)
+
+diff --git a/src/opengl/qpaintengine_opengl.cpp b/src/opengl/qpaintengine_opengl.cpp
+index 4823408..9c15d56 100644
+--- a/src/opengl/qpaintengine_opengl.cpp
++++ b/src/opengl/qpaintengine_opengl.cpp
+@@ -4707,6 +4707,12 @@ typedef QHash<QFontEngine*, QGLGlyphHash*> QGLFontGlyphHash;
+ typedef QHash<quint64, QGLFontTexture*> QGLFontTexHash;
+ typedef QHash<const QGLContext*, QGLFontGlyphHash*> QGLContextHash;
++static inline void qt_delete_glyph_hash(QGLGlyphHash *hash)
++{
++    qDeleteAll(*hash);
++    delete hash;
++}
++
+ class QGLGlyphCache : public QObject
+ {
+     Q_OBJECT
+@@ -4747,7 +4753,7 @@ void QGLGlyphCache::fontEngineDestroyed(QObject *o)
+         if (font_cache->find(fe) != font_cache->end()) {
+             ctx = keys.at(i);
+             QGLGlyphHash *cache = font_cache->take(fe);
+-            delete cache;
++            qt_delete_glyph_hash(cache);
+             break;
+         }
+     }
+@@ -4784,7 +4790,7 @@ void QGLGlyphCache::cleanupContext(const QGLContext *ctx)
+         QList<QFontEngine *> keys = font_cache->keys();
+         for (int i=0; i < keys.size(); ++i) {
+             QFontEngine *fe = keys.at(i);
+-            delete font_cache->take(fe);
++            qt_delete_glyph_hash(font_cache->take(fe));
+             quint64 font_key = (reinterpret_cast<quint64>(ctx) << 32) | reinterpret_cast<quint64>(fe);
+             QGLFontTexture *font_tex = qt_font_textures.take(font_key);
+             if (font_tex) {
+@@ -4825,7 +4831,9 @@ void QGLGlyphCache::cleanCache()
+     QList<const QGLContext *> keys = qt_context_cache.keys();
+     for (int i=0; i < keys.size(); ++i) {
+         QGLFontGlyphHash *font_cache = qt_context_cache.value(keys.at(i));
+-        qDeleteAll(*font_cache);
++        QGLFontGlyphHash::Iterator it = font_cache->begin();
++        for (; it != font_cache->end(); ++it)
++            qt_delete_glyph_hash(it.value());
+         font_cache->clear();
+     }
+     qDeleteAll(qt_context_cache);
+-- 
+1.6.5
+
diff --git a/recipes/qt4/qt-4.6.0/1196-Fix-build-with-neon-instructions-enabled-but-not-set.patch b/recipes/qt4/qt-4.6.0/1196-Fix-build-with-neon-instructions-enabled-but-not-set.patch
new file mode 100644 (file)
index 0000000..972e490
--- /dev/null
@@ -0,0 +1,29 @@
+From b97aedb9e68c6fe610aff10792c92b2292da0b07 Mon Sep 17 00:00:00 2001
+From: Tom Cooksey <thomas.cooksey@nokia.com>
+Date: Tue, 22 Dec 2009 13:37:06 +0100
+Subject: [PATCH 1196/1244] Fix build with neon instructions enabled but not set in mkspec
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reviewed-By: Samuel Rødal
+---
+ src/gui/painting/painting.pri |    2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri
+index 0b1e79a..a6cc9c7 100644
+--- a/src/gui/painting/painting.pri
++++ b/src/gui/painting/painting.pri
+@@ -383,7 +383,7 @@ neon {
+     DEFINES += QT_HAVE_NEON
+     HEADERS += painting/qdrawhelper_neon_p.h
+     SOURCES += painting/qdrawhelper_neon.cpp
+-    QMAKE.CXXFLAGS *= -mfpu=neon
++    QMAKE_CXXFLAGS *= -mfpu=neon
+ }
+ contains(QT_CONFIG, zlib) {
+-- 
+1.6.5
+
diff --git a/recipes/qt4/qt-4.6.0/1197-Add-GLfloat-2-2-GLfloat-3-3-uniform-setters-to-QGLSh.patch b/recipes/qt4/qt-4.6.0/1197-Add-GLfloat-2-2-GLfloat-3-3-uniform-setters-to-QGLSh.patch
new file mode 100644 (file)
index 0000000..2fe027b
--- /dev/null
@@ -0,0 +1,121 @@
+From 2b4d3391fd922dfc5ac28815bbd5f36c4041b658 Mon Sep 17 00:00:00 2001
+From: Tom Cooksey <thomas.cooksey@nokia.com>
+Date: Mon, 21 Dec 2009 16:36:14 +0100
+Subject: [PATCH 1197/1244] Add GLfloat[2][2] & GLfloat[3][3] uniform setters to QGLShaderProgram
+
+Reviewed-By: Rhys Weatherley
+---
+ src/opengl/qglshaderprogram.cpp |   67 +++++++++++++++++++++++++++++++++++++++
+ src/opengl/qglshaderprogram.h   |    4 ++
+ 2 files changed, 71 insertions(+), 0 deletions(-)
+
+diff --git a/src/opengl/qglshaderprogram.cpp b/src/opengl/qglshaderprogram.cpp
+index b4191dc..f9737a5 100644
+--- a/src/opengl/qglshaderprogram.cpp
++++ b/src/opengl/qglshaderprogram.cpp
+@@ -2275,6 +2275,42 @@ void QGLShaderProgram::setUniformValue(const char *name, const QMatrix4x4& value
+     \overload
+     Sets the uniform variable at \a location in the current context
++    to a 2x2 matrix \a value.  The matrix elements must be specified
++    in column-major order.
++
++    \sa setAttributeValue()
++    \since 4.6.2
++*/
++void QGLShaderProgram::setUniformValue(int location, const GLfloat value[2][2])
++{
++    Q_D(QGLShaderProgram);
++    Q_UNUSED(d);
++    if (location != -1)
++        glUniformMatrix2fv(location, 1, GL_FALSE, value[0]);
++}
++
++/*!
++    \overload
++
++    Sets the uniform variable at \a location in the current context
++    to a 3x3 matrix \a value.  The matrix elements must be specified
++    in column-major order.
++
++    \sa setAttributeValue()
++    \since 4.6.2
++*/
++void QGLShaderProgram::setUniformValue(int location, const GLfloat value[3][3])
++{
++    Q_D(QGLShaderProgram);
++    Q_UNUSED(d);
++    if (location != -1)
++        glUniformMatrix3fv(location, 1, GL_FALSE, value[0]);
++}
++
++/*!
++    \overload
++
++    Sets the uniform variable at \a location in the current context
+     to a 4x4 matrix \a value.  The matrix elements must be specified
+     in column-major order.
+@@ -2288,6 +2324,37 @@ void QGLShaderProgram::setUniformValue(int location, const GLfloat value[4][4])
+         glUniformMatrix4fv(location, 1, GL_FALSE, value[0]);
+ }
++
++/*!
++    \overload
++
++    Sets the uniform variable called \a name in the current context
++    to a 2x2 matrix \a value.  The matrix elements must be specified
++    in column-major order.
++
++    \sa setAttributeValue()
++    \since 4.6.2
++*/
++void QGLShaderProgram::setUniformValue(const char *name, const GLfloat value[2][2])
++{
++    setUniformValue(uniformLocation(name), value);
++}
++
++/*!
++    \overload
++
++    Sets the uniform variable called \a name in the current context
++    to a 3x3 matrix \a value.  The matrix elements must be specified
++    in column-major order.
++
++    \sa setAttributeValue()
++    \since 4.6.2
++*/
++void QGLShaderProgram::setUniformValue(const char *name, const GLfloat value[3][3])
++{
++    setUniformValue(uniformLocation(name), value);
++}
++
+ /*!
+     \overload
+diff --git a/src/opengl/qglshaderprogram.h b/src/opengl/qglshaderprogram.h
+index deeaee2..4eb80dd 100644
+--- a/src/opengl/qglshaderprogram.h
++++ b/src/opengl/qglshaderprogram.h
+@@ -216,6 +216,8 @@ public:
+     void setUniformValue(int location, const QMatrix4x2& value);
+     void setUniformValue(int location, const QMatrix4x3& value);
+     void setUniformValue(int location, const QMatrix4x4& value);
++    void setUniformValue(int location, const GLfloat value[2][2]);
++    void setUniformValue(int location, const GLfloat value[3][3]);
+     void setUniformValue(int location, const GLfloat value[4][4]);
+     void setUniformValue(int location, const QTransform& value);
+@@ -242,6 +244,8 @@ public:
+     void setUniformValue(const char *name, const QMatrix4x2& value);
+     void setUniformValue(const char *name, const QMatrix4x3& value);
+     void setUniformValue(const char *name, const QMatrix4x4& value);
++    void setUniformValue(const char *name, const GLfloat value[2][2]);
++    void setUniformValue(const char *name, const GLfloat value[3][3]);
+     void setUniformValue(const char *name, const GLfloat value[4][4]);
+     void setUniformValue(const char *name, const QTransform& value);
+-- 
+1.6.5
+
diff --git a/recipes/qt4/qt-4.6.0/1198-Handle-broken-shaders-better-in-the-GL2-engine-s-sha.patch b/recipes/qt4/qt-4.6.0/1198-Handle-broken-shaders-better-in-the-GL2-engine-s-sha.patch
new file mode 100644 (file)
index 0000000..d81051d
--- /dev/null
@@ -0,0 +1,269 @@
+From b784d4991b186037ccd2b60ae3101697a2251160 Mon Sep 17 00:00:00 2001
+From: Tom Cooksey <thomas.cooksey@nokia.com>
+Date: Tue, 22 Dec 2009 09:10:14 +0100
+Subject: [PATCH 1198/1244] Handle broken shaders better in the GL2 engine's shader manager
+
+The shader manager will now a) not seg-fault and b) actually tell you
+which shader has the error.
+
+Reviewed-By: Kim
+---
+ .../gl2paintengineex/qglengineshadermanager.cpp    |  191 ++++++++++++--------
+ 1 files changed, 114 insertions(+), 77 deletions(-)
+
+diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp
+index 1187c2d..9d545b9 100644
+--- a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp
++++ b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp
+@@ -170,13 +170,15 @@ QGLEngineSharedShaders::QGLEngineSharedShaders(const QGLContext* context)
+     source.append(qShaderSnippets[MainVertexShader]);
+     source.append(qShaderSnippets[PositionOnlyVertexShader]);
+     vertexShader = new QGLShader(QGLShader::Vertex, context, this);
+-    vertexShader->compileSourceCode(source);
++    if (!vertexShader->compileSourceCode(source))
++        qWarning("Vertex shader for simpleShaderProg (MainVertexShader & PositionOnlyVertexShader) failed to compile");
+     source.clear();
+     source.append(qShaderSnippets[MainFragmentShader]);
+     source.append(qShaderSnippets[ShockingPinkSrcFragmentShader]);
+     fragShader = new QGLShader(QGLShader::Fragment, context, this);
+-    fragShader->compileSourceCode(source);
++    if (!fragShader->compileSourceCode(source))
++        qWarning("Fragment shader for simpleShaderProg (MainFragmentShader & ShockingPinkSrcFragmentShader) failed to compile");
+     simpleShaderProg = new QGLShaderProgram(context, this);
+     simpleShaderProg->addShader(vertexShader);
+@@ -193,13 +195,15 @@ QGLEngineSharedShaders::QGLEngineSharedShaders(const QGLContext* context)
+     source.append(qShaderSnippets[MainWithTexCoordsVertexShader]);
+     source.append(qShaderSnippets[UntransformedPositionVertexShader]);
+     vertexShader = new QGLShader(QGLShader::Vertex, context, this);
+-    vertexShader->compileSourceCode(source);
++    if (!vertexShader->compileSourceCode(source))
++        qWarning("Vertex shader for blitShaderProg (MainWithTexCoordsVertexShader & UntransformedPositionVertexShader) failed to compile");
+     source.clear();
+     source.append(qShaderSnippets[MainFragmentShader]);
+     source.append(qShaderSnippets[ImageSrcFragmentShader]);
+     fragShader = new QGLShader(QGLShader::Fragment, context, this);
+-    fragShader->compileSourceCode(source);
++    if (!fragShader->compileSourceCode(source))
++        qWarning("Fragment shader for blitShaderProg (MainFragmentShader & ImageSrcFragmentShader) failed to compile");
+     blitShaderProg = new QGLShaderProgram(context, this);
+     blitShaderProg->addShader(vertexShader);
+@@ -234,84 +238,95 @@ QGLEngineShaderProg *QGLEngineSharedShaders::findProgramInCache(const QGLEngineS
+         }
+     }
+-    QByteArray source;
+-    source.append(qShaderSnippets[prog.mainFragShader]);
+-    source.append(qShaderSnippets[prog.srcPixelFragShader]);
+-    if (prog.srcPixelFragShader == CustomImageSrcFragmentShader)
+-        source.append(prog.customStageSource);
+-    if (prog.compositionFragShader)
+-        source.append(qShaderSnippets[prog.compositionFragShader]);
+-    if (prog.maskFragShader)
+-        source.append(qShaderSnippets[prog.maskFragShader]);
+-    QGLShader* fragShader = new QGLShader(QGLShader::Fragment, ctxGuard.context(), this);
+-    fragShader->compileSourceCode(source);
+-
+-    source.clear();
+-    source.append(qShaderSnippets[prog.mainVertexShader]);
+-    source.append(qShaderSnippets[prog.positionVertexShader]);
+-    QGLShader* vertexShader = new QGLShader(QGLShader::Vertex, ctxGuard.context(), this);
+-    vertexShader->compileSourceCode(source);
++    QGLShader *vertexShader = 0;
++    QGLShader *fragShader = 0;
++    QGLEngineShaderProg *newProg = 0;
++    bool success = false;
++
++    do {
++        QByteArray source;
++        source.append(qShaderSnippets[prog.mainFragShader]);
++        source.append(qShaderSnippets[prog.srcPixelFragShader]);
++        if (prog.srcPixelFragShader == CustomImageSrcFragmentShader)
++            source.append(prog.customStageSource);
++        if (prog.compositionFragShader)
++            source.append(qShaderSnippets[prog.compositionFragShader]);
++        if (prog.maskFragShader)
++            source.append(qShaderSnippets[prog.maskFragShader]);
++        fragShader = new QGLShader(QGLShader::Fragment, ctxGuard.context(), this);
++        QByteArray description;
++#if defined(QT_DEBUG)
++        // Name the shader for easier debugging
++        description.append("Fragment shader: main=");
++        description.append(snippetNameStr(prog.mainFragShader));
++        description.append(", srcPixel=");
++        description.append(snippetNameStr(prog.srcPixelFragShader));
++        if (prog.compositionFragShader) {
++            description.append(", composition=");
++            description.append(snippetNameStr(prog.compositionFragShader));
++        }
++        if (prog.maskFragShader) {
++            description.append(", mask=");
++            description.append(snippetNameStr(prog.maskFragShader));
++        }
++        fragShader->setObjectName(QString::fromLatin1(description));
++#endif
++        if (!fragShader->compileSourceCode(source)) {
++            qWarning() << "Warning:" << description << "failed to compile!";
++            break;
++        }
++        source.clear();
++        source.append(qShaderSnippets[prog.mainVertexShader]);
++        source.append(qShaderSnippets[prog.positionVertexShader]);
++        vertexShader = new QGLShader(QGLShader::Vertex, ctxGuard.context(), this);
+ #if defined(QT_DEBUG)
+-    // Name the shaders for easier debugging
+-    QByteArray description;
+-    description.append("Fragment shader: main=");
+-    description.append(snippetNameStr(prog.mainFragShader));
+-    description.append(", srcPixel=");
+-    description.append(snippetNameStr(prog.srcPixelFragShader));
+-    if (prog.compositionFragShader) {
+-        description.append(", composition=");
+-        description.append(snippetNameStr(prog.compositionFragShader));
+-    }
+-    if (prog.maskFragShader) {
+-        description.append(", mask=");
+-        description.append(snippetNameStr(prog.maskFragShader));
+-    }
+-    fragShader->setObjectName(QString::fromLatin1(description));
+-
+-    description.clear();
+-    description.append("Vertex shader: main=");
+-    description.append(snippetNameStr(prog.mainVertexShader));
+-    description.append(", position=");
+-    description.append(snippetNameStr(prog.positionVertexShader));
+-    vertexShader->setObjectName(QString::fromLatin1(description));
++        // Name the shader for easier debugging
++        description.clear();
++        description.append("Vertex shader: main=");
++        description.append(snippetNameStr(prog.mainVertexShader));
++        description.append(", position=");
++        description.append(snippetNameStr(prog.positionVertexShader));
++        vertexShader->setObjectName(QString::fromLatin1(description));
+ #endif
++        if (!vertexShader->compileSourceCode(source)) {
++            qWarning() << "Warning:" << description << "failed to compile!";
++            break;
++        }
+-    QGLEngineShaderProg* newProg = new QGLEngineShaderProg(prog);
+-
+-    // If the shader program's not found in the cache, create it now.
+-    newProg->program = new QGLShaderProgram(ctxGuard.context(), this);
+-    newProg->program->addShader(vertexShader);
+-    newProg->program->addShader(fragShader);
+-
+-    // We have to bind the vertex attribute names before the program is linked:
+-    newProg->program->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR);
+-    if (newProg->useTextureCoords)
+-        newProg->program->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR);
+-    if (newProg->useOpacityAttribute)
+-        newProg->program->bindAttributeLocation("opacityArray", QT_OPACITY_ATTR);
+-
+-    newProg->program->link();
+-    if (!newProg->program->isLinked()) {
+-        QLatin1String none("none");
+-        QLatin1String br("\n");
+-        QString error;
+-        error = QLatin1String("Shader program failed to link,")
++        newProg = new QGLEngineShaderProg(prog);
++
++        // If the shader program's not found in the cache, create it now.
++        newProg->program = new QGLShaderProgram(ctxGuard.context(), this);
++        newProg->program->addShader(vertexShader);
++        newProg->program->addShader(fragShader);
++
++        // We have to bind the vertex attribute names before the program is linked:
++        newProg->program->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR);
++        if (newProg->useTextureCoords)
++            newProg->program->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR);
++        if (newProg->useOpacityAttribute)
++            newProg->program->bindAttributeLocation("opacityArray", QT_OPACITY_ATTR);
++
++        newProg->program->link();
++        if (!newProg->program->isLinked()) {
++            QLatin1String none("none");
++            QLatin1String br("\n");
++            QString error;
++            error = QLatin1String("Shader program failed to link,")
+ #if defined(QT_DEBUG)
+-            + br
+-            + QLatin1String("  Shaders Used:") + br
+-            + QLatin1String("    ") + vertexShader->objectName() + QLatin1String(": ") + br
+-            + QLatin1String(vertexShader->sourceCode()) + br
+-            + QLatin1String("    ") + fragShader->objectName() + QLatin1String(": ") + br
+-            + QLatin1String(fragShader->sourceCode()) + br
++                + br
++                + QLatin1String("  Shaders Used:") + br
++                + QLatin1String("    ") + vertexShader->objectName() + QLatin1String(": ") + br
++                + QLatin1String(vertexShader->sourceCode()) + br
++                + QLatin1String("    ") + fragShader->objectName() + QLatin1String(": ") + br
++                + QLatin1String(fragShader->sourceCode()) + br
+ #endif
+-            + QLatin1String("  Error Log:\n")
+-            + QLatin1String("    ") + newProg->program->log();
+-        qWarning() << error;
+-        delete newProg; // Deletes the QGLShaderProgram in it's destructor
+-        newProg = 0;
+-    }
+-    else {
++                + QLatin1String("  Error Log:\n")
++                + QLatin1String("    ") + newProg->program->log();
++            qWarning() << error;
++            break;
++        }
+         if (cachedPrograms.count() > 30) {
+             // The cache is full, so delete the last 5 programs in the list.
+             // These programs will be least used, as a program us bumped to
+@@ -323,6 +338,22 @@ QGLEngineShaderProg *QGLEngineSharedShaders::findProgramInCache(const QGLEngineS
+         }
+         cachedPrograms.insert(0, newProg);
++
++        success = true;
++    } while (false);
++
++    // Clean up everything if we weren't successful
++    if (!success) {
++        if (newProg) {
++            delete newProg; // Also deletes the QGLShaderProgram which in turn deletes the QGLShaders
++            newProg = 0;
++        }
++        else {
++            if (vertexShader)
++                delete vertexShader;
++            if (fragShader)
++                delete fragShader;
++        }
+     }
+     return newProg;
+@@ -364,6 +395,9 @@ QGLEngineShaderManager::~QGLEngineShaderManager()
+ uint QGLEngineShaderManager::getUniformLocation(Uniform id)
+ {
++    if (!currentShaderProg)
++        return 0;
++
+     QVector<uint> &uniformLocations = currentShaderProg->uniformLocations;
+     if (uniformLocations.isEmpty())
+         uniformLocations.fill(GLuint(-1), NumUniforms);
+@@ -468,7 +502,10 @@ void QGLEngineShaderManager::removeCustomStage()
+ QGLShaderProgram* QGLEngineShaderManager::currentProgram()
+ {
+-    return currentShaderProg->program;
++    if (currentShaderProg)
++        return currentShaderProg->program;
++    else
++        return simpleProgram();
+ }
+ QGLShaderProgram* QGLEngineShaderManager::simpleProgram()
+-- 
+1.6.5
+
diff --git a/recipes/qt4/qt-4.6.0/1205-Fix-text-rendering-on-GL2-paint-engine.patch b/recipes/qt4/qt-4.6.0/1205-Fix-text-rendering-on-GL2-paint-engine.patch
new file mode 100644 (file)
index 0000000..548ed92
--- /dev/null
@@ -0,0 +1,83 @@
+From a8c3ed1dbe209488866e687d1a63c6143a04cfe0 Mon Sep 17 00:00:00 2001
+From: Tom Cooksey <thomas.cooksey@nokia.com>
+Date: Wed, 23 Dec 2009 10:38:56 +0100
+Subject: [PATCH 1205/1244] Fix text rendering on GL2 paint engine
+
+If you draw with a brush, then draw a pixmap, then draw with the
+same brush, the GL2 engine wouldn't update the fragment shader to
+use the brush. This is because it detected the brush hadn't changed
+and so didn't need updating. To fix this, we now set the current
+brush to noBrush when drawing an image/pixmap so the engine knows
+it needs to update the GL state for the brush.
+
+Reviewed-By: Kim
+---
+ .../gl2paintengineex/qpaintengineex_opengl2.cpp    |   15 ++++++++++-----
+ .../gl2paintengineex/qpaintengineex_opengl2_p.h    |    1 +
+ 2 files changed, 11 insertions(+), 5 deletions(-)
+
+diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
+index f52ed92..32fa3dc 100644
+--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
++++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
+@@ -388,21 +388,24 @@ inline QColor qt_premultiplyColor(QColor c, GLfloat opacity)
+ void QGL2PaintEngineExPrivate::setBrush(const QBrush& brush)
+ {
+-    Q_ASSERT(brush.style() != Qt::NoBrush);
+-
+     if (qbrush_fast_equals(currentBrush, brush))
+         return;
++    const Qt::BrushStyle newStyle = qbrush_style(brush);
++    Q_ASSERT(newStyle != Qt::NoBrush);
++
+     currentBrush = brush;
++    brushUniformsDirty = true; // All brushes have at least one uniform
++
++    if (newStyle > Qt::SolidPattern)
++        brushTextureDirty = true;
+-    brushTextureDirty = true;
+-    brushUniformsDirty = true;
+     if (currentBrush.style() == Qt::TexturePattern
+         && qHasPixmapTexture(brush) && brush.texture().isQBitmap())
+     {
+         shaderManager->setSrcPixelType(QGLEngineShaderManager::TextureSrcWithPattern);
+     } else {
+-        shaderManager->setSrcPixelType(currentBrush.style());
++        shaderManager->setSrcPixelType(newStyle);
+     }
+     shaderManager->optimiseForBrushTransform(currentBrush.transform());
+ }
+@@ -700,6 +703,7 @@ static inline void setCoords(GLfloat *coords, const QGLRect &rect)
+ void QGL2PaintEngineExPrivate::drawTexture(const QGLRect& dest, const QGLRect& src, const QSize &textureSize, bool opaque, bool pattern)
+ {
+     // Setup for texture drawing
++    currentBrush = noBrush;
+     shaderManager->setSrcPixelType(pattern ? QGLEngineShaderManager::PatternSrc : QGLEngineShaderManager::ImageSrc);
+     if (prepareForDraw(opaque))
+         shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::ImageTexture), QT_IMAGE_TEXTURE_UNIT);
+@@ -1782,6 +1786,7 @@ void QGL2PaintEngineEx::drawPixmaps(const QDrawPixmaps::Data *drawingData, int d
+                            state()->renderHints & QPainter::SmoothPixmapTransform, texture->id);
+     // Setup for texture drawing
++    d->currentBrush = d->noBrush;
+     d->shaderManager->setSrcPixelType(isBitmap ? QGLEngineShaderManager::PatternSrc : QGLEngineShaderManager::ImageSrc);
+     if (d->prepareForDraw(isOpaque))
+         d->shaderManager->currentProgram()->setUniformValue(d->location(QGLEngineShaderManager::ImageTexture), QT_IMAGE_TEXTURE_UNIT);
+diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
+index f1ec6e6..8de4a82 100644
+--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
++++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
+@@ -244,6 +244,7 @@ public:
+     uint maxClip;
+     QBrush currentBrush; // May not be the state's brush!
++    const QBrush noBrush;
+     GLfloat     inverseScale;
+-- 
+1.6.5
+
index f819c66..04e074f 100644 (file)
@@ -1,5 +1,5 @@
 require qt4-embedded.inc
-PR = "${INC_PR}.0"
+PR = "${INC_PR}.1"
 
 QT_GLFLAGS = "-opengl es2 -openvg"
 
index 11fcd58..e8184e7 100644 (file)
@@ -4,7 +4,7 @@ LICENSE = "GPL QPL"
 PRIORITY = "optional"
 HOMEPAGE = "http://www.trolltech.com"
 DEPENDS += "directfb tslib"
-INC_PR = "r14"
+INC_PR = "r15"
 
 QT_BASE_NAME ?= "qt4-embedded"
 QT_BASE_LIB  ?= "libqt-embedded"
index a74feaf..089992c 100644 (file)
@@ -1,5 +1,5 @@
 require qt4-x11-free.inc
-PR = "${INC_PR}.2"
+PR = "${INC_PR}.3"
 
 QT_GLFLAGS = "-opengl es2 -openvg"
 
index adf3bbc..ade148b 100644 (file)
@@ -6,7 +6,7 @@ LICENSE = "GPL QPL"
 DEPENDS += "virtual/libx11 fontconfig xft libxext libxrender libxrandr libxcursor"
 PROVIDES = "qt4x11"
 
-INC_PR = "r13"
+INC_PR = "r14"
 
 SRC_URI = "ftp://ftp.trolltech.com/qt/source/qt-x11-opensource-src-${PV}.tar.gz \
            file://0001-cross-compile.patch;patch=1 \