diff options
author | Koen Kooi <koen@openembedded.org> | 2010-01-04 16:38:25 +0100 |
---|---|---|
committer | Koen Kooi <koen@openembedded.org> | 2010-01-05 10:07:58 +0100 |
commit | 4a3a725cc558b2841959c84529389c97587eae45 (patch) | |
tree | 8985a4997feccd22c565c4ebb6f3b92d9b563570 /recipes | |
parent | 1029524234e0d6da592b946803cbd09b882acf2e (diff) |
qt 4.6.0: backport a few patches from git, mainly QGL related
Diffstat (limited to 'recipes')
33 files changed, 3766 insertions, 6 deletions
diff --git a/recipes/qt4/qt-4.6.0.inc b/recipes/qt4/qt-4.6.0.inc index b29b708d74..91565f7e0e 100644 --- a/recipes/qt4/qt-4.6.0.inc +++ b/recipes/qt4/qt-4.6.0.inc @@ -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 index 0000000000..a517d3ce41 --- /dev/null +++ b/recipes/qt4/qt-4.6.0/0838-Fixed-the-GL2-engine-stroker-to-handle-Qt-SvgMiterJo.patch @@ -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 index 0000000000..794380ab91 --- /dev/null +++ b/recipes/qt4/qt-4.6.0/0860-Added-caching-of-vectorpaths-to-the-GL-paint-engine.patch @@ -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 index 0000000000..9febe7553e --- /dev/null +++ b/recipes/qt4/qt-4.6.0/0917-Better-check-for-EGL-extension-strings.patch @@ -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 index 0000000000..f3dbdb57e7 --- /dev/null +++ b/recipes/qt4/qt-4.6.0/0919-Rebind-window-surface-fbo-after-native-GL-rendering.patch @@ -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 index 0000000000..5ef0b28822 --- /dev/null +++ b/recipes/qt4/qt-4.6.0/0943-Fixed-OpenGL-graphicssystem-issues-for-OpenGL-ES-2.0.patch @@ -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 index 0000000000..1afcee62dd --- /dev/null +++ b/recipes/qt4/qt-4.6.0/0945-Add-EGL_BUFFER_SIZE-to-QEglProperties-reduceConfigur.patch @@ -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 index 0000000000..6cdd9d13da --- /dev/null +++ b/recipes/qt4/qt-4.6.0/0946-Fix-WA_TranslucentBackground-for-QGLWidgets-on-X11-E.patch @@ -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 index 0000000000..605a913cb7 --- /dev/null +++ b/recipes/qt4/qt-4.6.0/0947-Compressed-texture-binding-for-QtOpenGL-ETC1-and-PVR.patch @@ -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 index 0000000000..787868e7c5 --- /dev/null +++ b/recipes/qt4/qt-4.6.0/0951-Detect-GL2-paint-engine-based-on-fragment-shaders-no.patch @@ -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 index 0000000000..37ac6f20c4 --- /dev/null +++ b/recipes/qt4/qt-4.6.0/0971-Fix-GL_BGRA-formats-under-OpenGL-ES-systems.patch @@ -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 index 0000000000..ee812f71f1 --- /dev/null +++ b/recipes/qt4/qt-4.6.0/0991-QGtkStyle-support-for-the-inner-border-property-in-G.patch @@ -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 index 0000000000..301fba29fd --- /dev/null +++ b/recipes/qt4/qt-4.6.0/0992-Make-sure-a-context-is-current-when-loading-compress.patch @@ -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 index 0000000000..70aeb7bbf0 --- /dev/null +++ b/recipes/qt4/qt-4.6.0/0993-Fix-upside-down-PVR-compressed-textures.patch @@ -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 index 0000000000..52303d9ed8 --- /dev/null +++ b/recipes/qt4/qt-4.6.0/0996-Export-QGLShareRegister-because-qgl_share_reg-is-exp.patch @@ -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 index 0000000000..b8687949e0 --- /dev/null +++ b/recipes/qt4/qt-4.6.0/0998-Set-stacking-class-for-stays-on-top-windows-in-DFB.patch @@ -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 index 0000000000..5dcc670845 --- /dev/null +++ b/recipes/qt4/qt-4.6.0/0999-Enable-customizing-of-DirectFB-layer-to-use.patch @@ -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 index 0000000000..f504599638 --- /dev/null +++ b/recipes/qt4/qt-4.6.0/1008-GLES-2-should-not-use-a-multisampled-format-by-defau.patch @@ -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 index 0000000000..6b3ad4e860 --- /dev/null +++ b/recipes/qt4/qt-4.6.0/1115-Fix-QGLWidgets-created-with-an-alpha-channel-on-X11-.patch @@ -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 index 0000000000..b0a2147020 --- /dev/null +++ b/recipes/qt4/qt-4.6.0/1118-Fix-EGL-surface-leaks-when-re-parenting-QGLWidget-on.patch @@ -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 index 0000000000..30abab6468 --- /dev/null +++ b/recipes/qt4/qt-4.6.0/1136-Disable-depth-testing-during-the-2D-QGLWidget-render.patch @@ -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 index 0000000000..49cd32bc07 --- /dev/null +++ b/recipes/qt4/qt-4.6.0/1149-GL2Engine-Don-t-mark-brush-as-dirty-if-it-hasn-t-cha.patch @@ -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 index 0000000000..4029d0dc33 --- /dev/null +++ b/recipes/qt4/qt-4.6.0/1157-Align-GL_RGB-lines-on-a-4-byte-boundary-when-uploadi.patch @@ -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 index 0000000000..9d2ca87654 --- /dev/null +++ b/recipes/qt4/qt-4.6.0/1165-NEON-configure-detection-and-initial-blend-function-.patch @@ -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 index 0000000000..7c79b6ba1c --- /dev/null +++ b/recipes/qt4/qt-4.6.0/1175-Fix-memory-leak-of-QGLGlyphCoord-objects-in-the-Open.patch @@ -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 index 0000000000..972e4900d5 --- /dev/null +++ b/recipes/qt4/qt-4.6.0/1196-Fix-build-with-neon-instructions-enabled-but-not-set.patch @@ -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 index 0000000000..2fe027bb3c --- /dev/null +++ b/recipes/qt4/qt-4.6.0/1197-Add-GLfloat-2-2-GLfloat-3-3-uniform-setters-to-QGLSh.patch @@ -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 index 0000000000..d81051dd9b --- /dev/null +++ b/recipes/qt4/qt-4.6.0/1198-Handle-broken-shaders-better-in-the-GL2-engine-s-sha.patch @@ -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 index 0000000000..548ed9246f --- /dev/null +++ b/recipes/qt4/qt-4.6.0/1205-Fix-text-rendering-on-GL2-paint-engine.patch @@ -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 + diff --git a/recipes/qt4/qt4-embedded-gles_4.6.0.bb b/recipes/qt4/qt4-embedded-gles_4.6.0.bb index f819c66212..04e074f9dd 100644 --- a/recipes/qt4/qt4-embedded-gles_4.6.0.bb +++ b/recipes/qt4/qt4-embedded-gles_4.6.0.bb @@ -1,5 +1,5 @@ require qt4-embedded.inc -PR = "${INC_PR}.0" +PR = "${INC_PR}.1" QT_GLFLAGS = "-opengl es2 -openvg" diff --git a/recipes/qt4/qt4-embedded.inc b/recipes/qt4/qt4-embedded.inc index 11fcd5849b..e8184e772d 100644 --- a/recipes/qt4/qt4-embedded.inc +++ b/recipes/qt4/qt4-embedded.inc @@ -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" diff --git a/recipes/qt4/qt4-x11-free-gles_4.6.0.bb b/recipes/qt4/qt4-x11-free-gles_4.6.0.bb index a74feaf0eb..089992c142 100644 --- a/recipes/qt4/qt4-x11-free-gles_4.6.0.bb +++ b/recipes/qt4/qt4-x11-free-gles_4.6.0.bb @@ -1,5 +1,5 @@ require qt4-x11-free.inc -PR = "${INC_PR}.2" +PR = "${INC_PR}.3" QT_GLFLAGS = "-opengl es2 -openvg" diff --git a/recipes/qt4/qt4-x11-free.inc b/recipes/qt4/qt4-x11-free.inc index adf3bbc6c0..ade148bab6 100644 --- a/recipes/qt4/qt4-x11-free.inc +++ b/recipes/qt4/qt4-x11-free.inc @@ -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 \ |