diff --git a/src/declarative/items/qquicktext.cpp b/src/declarative/items/qquicktext.cpp
index 4a3308626af1ac5371a48aba4e1ead9b593ac937..e11e4be0891b391f2582b4c5bfdc66f8047f67da 100644
--- a/src/declarative/items/qquicktext.cpp
+++ b/src/declarative/items/qquicktext.cpp
@@ -42,7 +42,6 @@
 #include "qquicktext_p.h"
 #include "qquicktext_p_p.h"
 
-#include <private/qsgdistancefieldglyphcache_p.h>
 #include <private/qsgcontext_p.h>
 #include <private/qsgadaptationlayer_p.h>
 #include "qquicktextnode_p.h"
diff --git a/src/declarative/items/qquicktextedit.cpp b/src/declarative/items/qquicktextedit.cpp
index 18d2cb8edeb6a1d678ce3027f795abe7b1f0fa10..c5b2f5750b11fde9e0490d1cea7302ebb5c3df8e 100644
--- a/src/declarative/items/qquicktextedit.cpp
+++ b/src/declarative/items/qquicktextedit.cpp
@@ -56,7 +56,6 @@
 #include <private/qdeclarativeglobal_p.h>
 #include <private/qtextcontrol_p.h>
 #include <private/qtextengine_p.h>
-#include <private/qsgdistancefieldglyphcache_p.h>
 #include <private/qsgtexture_p.h>
 #include <private/qsgadaptationlayer_p.h>
 
diff --git a/src/declarative/items/qquicktextinput.cpp b/src/declarative/items/qquicktextinput.cpp
index 69f699446a6bd85ff6ae864d80ee775a6fc24fe5..218a313a17ff724370379e56b7398e298a7689aa 100644
--- a/src/declarative/items/qquicktextinput.cpp
+++ b/src/declarative/items/qquicktextinput.cpp
@@ -44,7 +44,6 @@
 #include "qquickcanvas.h"
 
 #include <private/qdeclarativeglobal_p.h>
-#include <private/qsgdistancefieldglyphcache_p.h>
 
 #include <QtDeclarative/qdeclarativeinfo.h>
 #include <QtGui/qevent.h>
diff --git a/src/declarative/items/qquicktextnode.cpp b/src/declarative/items/qquicktextnode.cpp
index 5cc372f9e117513be79aabf72df67806e5235f0b..56c3b54cd7ad337c3983de026a5c3a13d8ef5319 100644
--- a/src/declarative/items/qquicktextnode.cpp
+++ b/src/declarative/items/qquicktextnode.cpp
@@ -42,7 +42,6 @@
 #include "qquicktextnode_p.h"
 #include "qsgsimplerectnode.h"
 #include <private/qsgadaptationlayer_p.h>
-#include <private/qsgdistancefieldglyphcache_p.h>
 #include <private/qsgdistancefieldglyphnode_p.h>
 
 #include <private/qsgcontext_p.h>
diff --git a/src/declarative/scenegraph/qsgadaptationlayer.cpp b/src/declarative/scenegraph/qsgadaptationlayer.cpp
index e573e5f3444c99b31bb18cdd8b0f0ccc66f0edf4..966a24acd3d2cb02ae6399a463836cea0a7900cc 100644
--- a/src/declarative/scenegraph/qsgadaptationlayer.cpp
+++ b/src/declarative/scenegraph/qsgadaptationlayer.cpp
@@ -40,3 +40,276 @@
 ****************************************************************************/
 
 #include "qsgadaptationlayer_p.h"
+
+#include <qmath.h>
+#include <private/qsgdistancefieldutil_p.h>
+#include <private/qsgdistancefieldglyphnode_p.h>
+#include <private/qrawfont_p.h>
+#include <QtGui/qguiapplication.h>
+#include <qdir.h>
+
+QT_BEGIN_NAMESPACE
+
+
+QHash<QString, QOpenGLMultiGroupSharedResource> QSGDistanceFieldGlyphCache::m_caches_data;
+
+QSGDistanceFieldGlyphCache::QSGDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, QOpenGLContext *c, const QRawFont &font)
+    : ctx(c)
+    , m_manager(man)
+{
+    Q_ASSERT(font.isValid());
+    m_font = font;
+
+    m_cacheData = cacheData();
+
+    QRawFontPrivate *fontD = QRawFontPrivate::get(m_font);
+    m_glyphCount = fontD->fontEngine->glyphCount();
+
+    m_cacheData->doubleGlyphResolution = qt_fontHasNarrowOutlines(font) && m_glyphCount < QT_DISTANCEFIELD_HIGHGLYPHCOUNT;
+
+    m_referenceFont = m_font;
+    m_referenceFont.setPixelSize(QT_DISTANCEFIELD_BASEFONTSIZE(m_cacheData->doubleGlyphResolution));
+    Q_ASSERT(m_referenceFont.isValid());
+}
+
+QSGDistanceFieldGlyphCache::~QSGDistanceFieldGlyphCache()
+{
+}
+
+QSGDistanceFieldGlyphCache::GlyphCacheData *QSGDistanceFieldGlyphCache::cacheData()
+{
+    QString key = QString::fromLatin1("%1_%2_%3_%4")
+            .arg(m_font.familyName())
+            .arg(m_font.styleName())
+            .arg(m_font.weight())
+            .arg(m_font.style());
+    return m_caches_data[key].value<QSGDistanceFieldGlyphCache::GlyphCacheData>(ctx);
+}
+
+qreal QSGDistanceFieldGlyphCache::fontScale() const
+{
+    return qreal(m_font.pixelSize()) / QT_DISTANCEFIELD_BASEFONTSIZE(m_cacheData->doubleGlyphResolution);
+}
+
+int QSGDistanceFieldGlyphCache::distanceFieldRadius() const
+{
+    return QT_DISTANCEFIELD_DEFAULT_RADIUS / QT_DISTANCEFIELD_SCALE(m_cacheData->doubleGlyphResolution);
+}
+
+QSGDistanceFieldGlyphCache::Metrics QSGDistanceFieldGlyphCache::glyphMetrics(glyph_t glyph)
+{
+    QHash<glyph_t, Metrics>::iterator metric = m_metrics.find(glyph);
+    if (metric == m_metrics.end()) {
+        QPainterPath path = m_font.pathForGlyph(glyph);
+        QRectF br = path.boundingRect();
+
+        Metrics m;
+        m.width = br.width();
+        m.height = br.height();
+        m.baselineX = br.x();
+        m.baselineY = -br.y();
+
+        metric = m_metrics.insert(glyph, m);
+    }
+
+    return metric.value();
+}
+
+QSGDistanceFieldGlyphCache::TexCoord QSGDistanceFieldGlyphCache::glyphTexCoord(glyph_t glyph) const
+{
+    return m_cacheData->texCoords.value(glyph);
+}
+
+static QSGDistanceFieldGlyphCache::Texture g_emptyTexture;
+
+const QSGDistanceFieldGlyphCache::Texture *QSGDistanceFieldGlyphCache::glyphTexture(glyph_t glyph) const
+{
+    QHash<glyph_t, Texture*>::const_iterator it = m_cacheData->glyphTextures.find(glyph);
+    if (it == m_cacheData->glyphTextures.constEnd())
+        return &g_emptyTexture;
+    return it.value();
+}
+
+void QSGDistanceFieldGlyphCache::populate(const QVector<glyph_t> &glyphs)
+{
+    QSet<glyph_t> newGlyphs;
+    int count = glyphs.count();
+    for (int i = 0; i < count; ++i) {
+        glyph_t glyphIndex = glyphs.at(i);
+        if ((int) glyphIndex >= glyphCount()) {
+            qWarning("Warning: distance-field glyph is not available with index %d", glyphIndex);
+            continue;
+        }
+
+        if (m_cacheData->texCoords.contains(glyphIndex) || newGlyphs.contains(glyphIndex))
+            continue;
+
+        QPainterPath path = m_referenceFont.pathForGlyph(glyphIndex);
+        m_cacheData->glyphPaths.insert(glyphIndex, path);
+        if (path.isEmpty()) {
+            TexCoord c;
+            c.width = 0;
+            c.height = 0;
+            m_cacheData->texCoords.insert(glyphIndex, c);
+            continue;
+        }
+
+        newGlyphs.insert(glyphIndex);
+    }
+
+    if (newGlyphs.isEmpty())
+        return;
+
+    QVector<glyph_t> glyphsVec;
+    QSet<glyph_t>::const_iterator it = newGlyphs.constBegin();
+    while (it != newGlyphs.constEnd()) {
+        glyphsVec.append(*it);
+        ++it;
+    }
+    requestGlyphs(glyphsVec);
+}
+
+void QSGDistanceFieldGlyphCache::release(const QVector<glyph_t> &glyphs)
+{
+    releaseGlyphs(glyphs);
+}
+
+void QSGDistanceFieldGlyphCache::update()
+{
+    if (m_cacheData->pendingGlyphs.isEmpty())
+        return;
+
+    QHash<glyph_t, QImage> distanceFields;
+
+    // ### Remove before final release
+    static bool cacheDistanceFields = QGuiApplication::arguments().contains(QLatin1String("--cache-distance-fields"));
+
+    QString tmpPath = QString::fromLatin1("%1/.qt/").arg(QDir::tempPath());
+    QString keyBase = QString::fromLatin1("%1%2%3_%4_%5_%6.fontblob")
+            .arg(tmpPath)
+            .arg(m_font.familyName())
+            .arg(m_font.styleName())
+            .arg(m_font.weight())
+            .arg(m_font.style());
+
+    if (cacheDistanceFields && !QFile::exists(tmpPath))
+        QDir(tmpPath).mkpath(tmpPath);
+
+    for (int i = 0; i < m_cacheData->pendingGlyphs.size(); ++i) {
+        glyph_t glyphIndex = m_cacheData->pendingGlyphs.at(i);
+
+        if (cacheDistanceFields) {
+            QString key = keyBase.arg(glyphIndex);
+            QFile file(key);
+            if (file.open(QFile::ReadOnly)) {
+                int fileSize = file.size();
+                int dim = sqrt(float(fileSize));
+                QByteArray blob = file.readAll();
+                QImage df(dim, dim, QImage::Format_Indexed8);
+                memcpy(df.bits(), blob.constData(), fileSize);
+                distanceFields.insert(glyphIndex, df);
+                continue;
+            }
+        }
+
+        QImage distanceField = qt_renderDistanceFieldGlyph(m_font, glyphIndex, m_cacheData->doubleGlyphResolution);
+        distanceFields.insert(glyphIndex, distanceField);
+
+        if (cacheDistanceFields) {
+            QString key = keyBase.arg(glyphIndex);
+            QFile file(key);
+            file.open(QFile::WriteOnly);
+            file.write((const char *) distanceField.constBits(), distanceField.width() * distanceField.height());
+        }
+    }
+
+    m_cacheData->pendingGlyphs.reset();
+
+    storeGlyphs(distanceFields);
+}
+
+void QSGDistanceFieldGlyphCache::addGlyphPositions(const QList<GlyphPosition> &glyphs)
+{
+    int count = glyphs.count();
+    for (int i = 0; i < count; ++i) {
+        GlyphPosition glyph = glyphs.at(i);
+
+        QPainterPath path = m_cacheData->glyphPaths.value(glyph.glyph);
+        QRectF br = path.boundingRect();
+        TexCoord c;
+        c.xMargin = QT_DISTANCEFIELD_RADIUS(m_cacheData->doubleGlyphResolution) / qreal(QT_DISTANCEFIELD_SCALE(m_cacheData->doubleGlyphResolution));
+        c.yMargin = QT_DISTANCEFIELD_RADIUS(m_cacheData->doubleGlyphResolution) / qreal(QT_DISTANCEFIELD_SCALE(m_cacheData->doubleGlyphResolution));
+        c.x = glyph.position.x();
+        c.y = glyph.position.y();
+        c.width = br.width();
+        c.height = br.height();
+
+        m_cacheData->texCoords.insert(glyph.glyph, c);
+    }
+}
+
+void QSGDistanceFieldGlyphCache::addGlyphTextures(const QVector<glyph_t> &glyphs, const Texture &tex)
+{
+    int i = m_cacheData->textures.indexOf(tex);
+    if (i == -1) {
+        m_cacheData->textures.append(tex);
+        i = m_cacheData->textures.size() - 1;
+    } else {
+        m_cacheData->textures[i].size = tex.size;
+    }
+    Texture *texture = &(m_cacheData->textures[i]);
+
+    int count = glyphs.count();
+    for (int j = 0; j < count; ++j)
+        m_cacheData->glyphTextures.insert(glyphs.at(j), texture);
+
+    QLinkedList<QSGDistanceFieldGlyphNode *>::iterator it = m_cacheData->m_registeredNodes.begin();
+    while (it != m_cacheData->m_registeredNodes.end()) {
+        (*it)->updateGeometry();
+        ++it;
+    }
+}
+
+void QSGDistanceFieldGlyphCache::markGlyphsToRender(const QVector<glyph_t> &glyphs)
+{
+    int count = glyphs.count();
+    for (int i = 0; i < count; ++i)
+        m_cacheData->pendingGlyphs.add(glyphs.at(i));
+}
+
+void QSGDistanceFieldGlyphCache::removeGlyph(glyph_t glyph)
+{
+    m_cacheData->texCoords.remove(glyph);
+    m_cacheData->glyphTextures.remove(glyph);
+}
+
+void QSGDistanceFieldGlyphCache::updateTexture(GLuint oldTex, GLuint newTex, const QSize &newTexSize)
+{
+    int count = m_cacheData->textures.count();
+    for (int i = 0; i < count; ++i) {
+        Texture &tex = m_cacheData->textures[i];
+        if (tex.textureId == oldTex) {
+            tex.textureId = newTex;
+            tex.size = newTexSize;
+            return;
+        }
+    }
+}
+
+bool QSGDistanceFieldGlyphCache::containsGlyph(glyph_t glyph) const
+{
+    return m_cacheData->texCoords.contains(glyph);
+}
+
+void QSGDistanceFieldGlyphCache::registerGlyphNode(QSGDistanceFieldGlyphNode *node)
+{
+    m_cacheData->m_registeredNodes.append(node);
+}
+
+void QSGDistanceFieldGlyphCache::unregisterGlyphNode(QSGDistanceFieldGlyphNode *node)
+{
+    m_cacheData->m_registeredNodes.removeOne(node);
+}
+
+
+QT_END_NAMESPACE
diff --git a/src/declarative/scenegraph/qsgadaptationlayer_p.h b/src/declarative/scenegraph/qsgadaptationlayer_p.h
index 0ad60913b3cf7d98a4fa6beca0dd9a922276c509..82e0c7cf42a13aaedf9234d0fc128b6b56be59b1 100644
--- a/src/declarative/scenegraph/qsgadaptationlayer_p.h
+++ b/src/declarative/scenegraph/qsgadaptationlayer_p.h
@@ -51,6 +51,9 @@
 #include <QtCore/qsharedpointer.h>
 #include <QtGui/qglyphrun.h>
 #include <QtCore/qurl.h>
+#include <private/qfontengine_p.h>
+#include <QtGui/private/qdatabuffer_p.h>
+#include <private/qopenglcontext_p.h>
 
 // ### remove
 #include <private/qquicktext_p.h>
@@ -64,6 +67,8 @@ QT_MODULE(Declarative)
 class QSGNode;
 class QImage;
 class TextureReference;
+class QSGDistanceFieldGlyphCacheManager;
+class QSGDistanceFieldGlyphNode;
 
 // TODO: Rename from XInterface to AbstractX.
 class Q_DECLARATIVE_EXPORT QSGRectangleNode : public QSGGeometryNode
@@ -124,6 +129,126 @@ protected:
     QRectF m_bounding_rect;
 };
 
+class Q_DECLARATIVE_EXPORT QSGDistanceFieldGlyphCache
+{
+public:
+    QSGDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, QOpenGLContext *c, const QRawFont &font);
+    virtual ~QSGDistanceFieldGlyphCache();
+
+    struct Metrics {
+        qreal width;
+        qreal height;
+        qreal baselineX;
+        qreal baselineY;
+
+        bool isNull() const { return width == 0 || height == 0; }
+    };
+
+    struct TexCoord {
+        qreal x;
+        qreal y;
+        qreal width;
+        qreal height;
+        qreal xMargin;
+        qreal yMargin;
+
+        TexCoord() : x(0), y(0), width(-1), height(-1), xMargin(0), yMargin(0) { }
+
+        bool isNull() const { return width <= 0 || height <= 0; }
+        bool isValid() const { return width >= 0 && height >= 0; }
+    };
+
+    struct Texture {
+        GLuint textureId;
+        QSize size;
+
+        Texture() : textureId(0), size(QSize()) { }
+        bool operator == (const Texture &other) const { return textureId == other.textureId; }
+    };
+
+    const QSGDistanceFieldGlyphCacheManager *manager() const { return m_manager; }
+
+    const QRawFont &font() const { return m_font; }
+
+    qreal fontScale() const;
+    int distanceFieldRadius() const;
+    int glyphCount() const { return m_glyphCount; }
+    bool doubleGlyphResolution() const { return m_cacheData->doubleGlyphResolution; }
+
+    Metrics glyphMetrics(glyph_t glyph);
+    TexCoord glyphTexCoord(glyph_t glyph) const;
+    const Texture *glyphTexture(glyph_t glyph) const;
+
+    void populate(const QVector<glyph_t> &glyphs);
+    void release(const QVector<glyph_t> &glyphs);
+
+    void update();
+
+    void registerGlyphNode(QSGDistanceFieldGlyphNode *node);
+    void unregisterGlyphNode(QSGDistanceFieldGlyphNode *node);
+
+protected:
+    struct GlyphPosition {
+        glyph_t glyph;
+        QPointF position;
+    };
+
+    virtual void requestGlyphs(const QVector<glyph_t> &glyphs) = 0;
+    virtual void storeGlyphs(const QHash<glyph_t, QImage> &glyphs) = 0;
+    virtual void releaseGlyphs(const QVector<glyph_t> &glyphs) = 0;
+
+    void addGlyphPositions(const QList<GlyphPosition> &glyphs);
+    void addGlyphTextures(const QVector<glyph_t> &glyphs, const Texture &tex);
+    void markGlyphsToRender(const QVector<glyph_t> &glyphs);
+    void removeGlyph(glyph_t glyph);
+
+    void updateTexture(GLuint oldTex, GLuint newTex, const QSize &newTexSize);
+
+    bool containsGlyph(glyph_t glyph) const;
+
+    QOpenGLContext *ctx;
+
+private:
+    struct GlyphCacheData : public QOpenGLSharedResource {
+        QList<Texture> textures;
+        QHash<glyph_t, Texture*> glyphTextures;
+        QHash<glyph_t, TexCoord> texCoords;
+        QDataBuffer<glyph_t> pendingGlyphs;
+        QHash<glyph_t, QPainterPath> glyphPaths;
+        bool doubleGlyphResolution;
+        QLinkedList<QSGDistanceFieldGlyphNode*> m_registeredNodes;
+
+        GlyphCacheData(QOpenGLContext *ctx)
+            : QOpenGLSharedResource(ctx->shareGroup())
+            , pendingGlyphs(64)
+            , doubleGlyphResolution(false)
+        {}
+
+        void invalidateResource()
+        {
+            textures.clear();
+            glyphTextures.clear();
+            texCoords.clear();
+        }
+
+        void freeResource(QOpenGLContext *)
+        {
+        }
+    };
+
+    QSGDistanceFieldGlyphCacheManager *m_manager;
+
+    QRawFont m_font;
+    QRawFont m_referenceFont;
+
+    int m_glyphCount;
+    QHash<glyph_t, Metrics> m_metrics;
+
+    GlyphCacheData *cacheData();
+    GlyphCacheData *m_cacheData;
+    static QHash<QString, QOpenGLMultiGroupSharedResource> m_caches_data;
+};
+
 
 QT_END_NAMESPACE
 
diff --git a/src/declarative/scenegraph/qsgcontext.cpp b/src/declarative/scenegraph/qsgcontext.cpp
index f995f9e76e465246d5d3fed94b46aae94cb2a94e..87beb72b5b36ed8951aff6ecc575315fafbd465e 100644
--- a/src/declarative/scenegraph/qsgcontext.cpp
+++ b/src/declarative/scenegraph/qsgcontext.cpp
@@ -45,11 +45,12 @@
 
 #include <private/qsgdefaultrenderer_p.h>
 
+#include <private/qsgdistancefieldutil_p.h>
+#include <private/qsgdefaultdistancefieldglyphcache_p.h>
 #include <private/qsgdefaultrectanglenode_p.h>
 #include <private/qsgdefaultimagenode_p.h>
 #include <private/qsgdefaultglyphnode_p.h>
 #include <private/qsgdistancefieldglyphnode_p.h>
-#include <private/qsgdistancefieldglyphcache_p.h>
 
 #include <private/qsgtexture_p.h>
 #include <qsgengine.h>
@@ -288,6 +289,15 @@ QSGImageNode *QSGContext::createImageNode()
     return new QSGDefaultImageNode;
 }
 
+/*!
+    Factory function for scene graph backends of the distance-field glyph cache.
+ */
+QSGDistanceFieldGlyphCache *QSGContext::createDistanceFieldGlyphCache(const QRawFont &font)
+{
+    Q_D(QSGContext);
+    return new QSGDefaultDistanceFieldGlyphCache(d->distanceFieldCacheManager, glContext(), font);
+}
+
 /*!
     Factory function for scene graph backends of the Text elements;
  */
@@ -304,7 +314,7 @@ QSGGlyphNode *QSGContext::createGlyphNode()
         return new QSGDefaultGlyphNode;
     } else {
         if (!d->distanceFieldCacheManager) {
-            d->distanceFieldCacheManager = new QSGDistanceFieldGlyphCacheManager(d->gl);
+            d->distanceFieldCacheManager = new QSGDistanceFieldGlyphCacheManager(this);
             if (doSubpixel)
                 d->distanceFieldCacheManager->setDefaultAntialiasingMode(QSGGlyphNode::HighQualitySubPixelAntialiasing);
             else if (doLowQualSubpixel)
diff --git a/src/declarative/scenegraph/qsgcontext_p.h b/src/declarative/scenegraph/qsgcontext_p.h
index 6fdd4aed37658cae1271972e327bc06b410f7496..328b85eb2bdc2ef7d79f85e8a40f957e729ab9b6 100644
--- a/src/declarative/scenegraph/qsgcontext_p.h
+++ b/src/declarative/scenegraph/qsgcontext_p.h
@@ -48,6 +48,8 @@
 #include <QtGui/QImage>
 #include <QtGui/QSurfaceFormat>
 
+#include <private/qrawfont_p.h>
+
 #include "qsgnode.h"
 
 QT_BEGIN_HEADER
@@ -61,6 +63,7 @@ class QSGRectangleNode;
 class QSGImageNode;
 class QSGGlyphNode;
 class QSGRenderer;
+class QSGDistanceFieldGlyphCache;
 
 class QSGTexture;
 class QSGMaterial;
@@ -95,6 +98,8 @@ public:
 
     virtual void renderNextFrame(QOpenGLFramebufferObject *fbo = 0);
 
+    virtual QSGDistanceFieldGlyphCache *createDistanceFieldGlyphCache(const QRawFont &font);
+
     virtual QSGRectangleNode *createRectangleNode();
     virtual QSGImageNode *createImageNode();
     virtual QSGGlyphNode *createGlyphNode();
diff --git a/src/declarative/scenegraph/qsgdefaultdistancefieldglyphcache.cpp b/src/declarative/scenegraph/qsgdefaultdistancefieldglyphcache.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7a03cde026075e58bf486ca8829800de4875ea12
--- /dev/null
+++ b/src/declarative/scenegraph/qsgdefaultdistancefieldglyphcache.cpp
@@ -0,0 +1,389 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsgdefaultdistancefieldglyphcache_p.h"
+
+#include <private/qsgdistancefieldutil_p.h>
+#include <qopenglshaderprogram.h>
+#include <QtGui/private/qopenglengineshadersource_p.h>
+#include <qopenglfunctions.h>
+
+
+class TextureBlitHelper
+{
+public:
+    TextureBlitHelper()
+    {
+        m_vertexCoordinateArray[0] = -1.0f;
+        m_vertexCoordinateArray[1] = -1.0f;
+        m_vertexCoordinateArray[2] =  1.0f;
+        m_vertexCoordinateArray[3] = -1.0f;
+        m_vertexCoordinateArray[4] =  1.0f;
+        m_vertexCoordinateArray[5] =  1.0f;
+        m_vertexCoordinateArray[6] = -1.0f;
+        m_vertexCoordinateArray[7] =  1.0f;
+
+        m_textureCoordinateArray[0] = 0.0f;
+        m_textureCoordinateArray[1] = 0.0f;
+        m_textureCoordinateArray[2] = 1.0f;
+        m_textureCoordinateArray[3] = 0.0f;
+        m_textureCoordinateArray[4] = 1.0f;
+        m_textureCoordinateArray[5] = 1.0f;
+        m_textureCoordinateArray[6] = 0.0f;
+        m_textureCoordinateArray[7] = 1.0f;
+
+        m_blitProgram = new QOpenGLShaderProgram;
+        {
+            QString source;
+            source.append(QLatin1String(qopenglslMainWithTexCoordsVertexShader));
+            source.append(QLatin1String(qopenglslUntransformedPositionVertexShader));
+
+            QOpenGLShader *vertexShader = new QOpenGLShader(QOpenGLShader::Vertex, m_blitProgram);
+            vertexShader->compileSourceCode(source);
+
+            m_blitProgram->addShader(vertexShader);
+        }
+        {
+            QString source;
+            source.append(QLatin1String(qopenglslMainFragmentShader));
+            source.append(QLatin1String(qopenglslImageSrcFragmentShader));
+
+            QOpenGLShader *fragmentShader = new QOpenGLShader(QOpenGLShader::Fragment, m_blitProgram);
+            fragmentShader->compileSourceCode(source);
+
+            m_blitProgram->addShader(fragmentShader);
+        }
+        m_blitProgram->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR);
+        m_blitProgram->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR);
+        m_blitProgram->link();
+    }
+
+    ~TextureBlitHelper()
+    {
+        delete m_blitProgram;
+    }
+
+    QOpenGLShaderProgram *blitProgram() { return m_blitProgram; }
+    const GLfloat *blitVertexArray() const { return &m_vertexCoordinateArray[0]; }
+    const GLfloat *blitTextureArray() const { return &m_textureCoordinateArray[0]; }
+
+private:
+    QOpenGLShaderProgram *m_blitProgram;
+    GLfloat m_vertexCoordinateArray[8];
+    GLfloat m_textureCoordinateArray[8];
+};
+
+static TextureBlitHelper *g_textureBlitHelper = 0;
+
+QHash<QString, QOpenGLMultiGroupSharedResource> QSGDefaultDistanceFieldGlyphCache::m_textures_data;
+
+QSGDefaultDistanceFieldGlyphCache::DistanceFieldTextureData *QSGDefaultDistanceFieldGlyphCache::textureData()
+{
+    QString key = QString::fromLatin1("%1_%2_%3_%4")
+            .arg(font().familyName())
+            .arg(font().styleName())
+            .arg(font().weight())
+            .arg(font().style());
+    return m_textures_data[key].value<QSGDefaultDistanceFieldGlyphCache::DistanceFieldTextureData>(QOpenGLContext::currentContext());
+}
+
+QSGDefaultDistanceFieldGlyphCache::QSGDefaultDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, QOpenGLContext *c, const QRawFont &font)
+    : QSGDistanceFieldGlyphCache(man, c, font)
+    , m_maxTextureSize(0)
+{
+    m_textureData = textureData();
+}
+
+void QSGDefaultDistanceFieldGlyphCache::requestGlyphs(const QVector<glyph_t> &glyphs)
+{
+    int count = glyphs.count();
+
+    // Avoid useless and costly glyph re-generation
+    if (cacheIsFull() && !m_textureData->unusedGlyphs.isEmpty()) {
+        for (int i = 0; i < count; ++i) {
+            glyph_t glyphIndex = glyphs.at(i);
+            if (containsGlyph(glyphIndex) && m_textureData->unusedGlyphs.contains(glyphIndex))
+                m_textureData->unusedGlyphs.remove(glyphIndex);
+        }
+    }
+
+    QList<GlyphPosition> glyphPositions;
+    QVector<glyph_t> glyphsToRender;
+
+    for (int i = 0; i < count; ++i) {
+        glyph_t glyphIndex = glyphs.at(i);
+
+        if (++m_textureData->glyphRefCount[glyphIndex] == 1)
+            m_textureData->unusedGlyphs.remove(glyphIndex);
+
+        if (cacheIsFull() && m_textureData->unusedGlyphs.isEmpty())
+            continue;
+
+        GlyphPosition p;
+        p.glyph = glyphIndex;
+        p.position = QPointF(m_textureData->currX, m_textureData->currY);
+
+        if (!cacheIsFull()) {
+            m_textureData->currX += QT_DISTANCEFIELD_TILESIZE(doubleGlyphResolution());
+            if (m_textureData->currX >= maxTextureSize()) {
+                m_textureData->currX = 0;
+                m_textureData->currY += QT_DISTANCEFIELD_TILESIZE(doubleGlyphResolution());
+            }
+        } else {
+            // Recycle glyphs
+            if (!m_textureData->unusedGlyphs.isEmpty()) {
+                glyph_t unusedGlyph = *m_textureData->unusedGlyphs.constBegin();
+                TexCoord unusedCoord = glyphTexCoord(unusedGlyph);
+                p.position = QPointF(unusedCoord.x, unusedCoord.y);
+                m_textureData->unusedGlyphs.remove(unusedGlyph);
+                removeGlyph(unusedGlyph);
+            }
+        }
+
+        if (p.position.y() < maxTextureSize()) {
+            glyphPositions.append(p);
+            glyphsToRender.append(glyphIndex);
+        }
+    }
+
+    addGlyphPositions(glyphPositions);
+    markGlyphsToRender(glyphsToRender);
+}
+
+void QSGDefaultDistanceFieldGlyphCache::storeGlyphs(const QHash<glyph_t, QImage> &glyphs)
+{
+    int requiredWidth = maxTextureSize();
+    int rows = 128 / (requiredWidth / QT_DISTANCEFIELD_TILESIZE(doubleGlyphResolution())); // Enough rows to fill the latin1 set by default..
+    int requiredHeight = qMin(maxTextureSize(),
+                              qMax(m_textureData->currY + QT_DISTANCEFIELD_TILESIZE(doubleGlyphResolution()),
+                                   QT_DISTANCEFIELD_TILESIZE(doubleGlyphResolution()) * rows));
+
+    resizeTexture((requiredWidth), (requiredHeight));
+    glBindTexture(GL_TEXTURE_2D, m_textureData->texture);
+
+    QVector<glyph_t> glyphTextures;
+
+    QHash<glyph_t, QImage>::const_iterator it;
+    for (it = glyphs.constBegin(); it != glyphs.constEnd(); ++it) {
+        glyph_t glyphIndex = it.key();
+        TexCoord c = glyphTexCoord(glyphIndex);
+
+        glyphTextures.append(glyphIndex);
+
+        QImage glyph = it.value();
+
+        if (useWorkaroundBrokenFBOReadback()) {
+            uchar *inBits = glyph.scanLine(0);
+            uchar *outBits = m_textureData->image.scanLine(int(c.y)) + int(c.x);
+            for (int y = 0; y < glyph.height(); ++y) {
+                qMemCopy(outBits, inBits, glyph.width());
+                inBits += glyph.bytesPerLine();
+                outBits += m_textureData->image.bytesPerLine();
+            }
+        }
+
+        glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, glyph.width(), glyph.height(), GL_ALPHA, GL_UNSIGNED_BYTE, glyph.constBits());
+    }
+
+    Texture t;
+    t.textureId = m_textureData->texture;
+    t.size = m_textureData->size;
+    addGlyphTextures(glyphTextures, t);
+}
+
+void QSGDefaultDistanceFieldGlyphCache::releaseGlyphs(const QVector<glyph_t> &glyphs)
+{
+    int count = glyphs.count();
+    for (int i = 0; i < count; ++i) {
+        glyph_t glyphIndex = glyphs.at(i);
+        if (--m_textureData->glyphRefCount[glyphIndex] == 0 && !glyphTexCoord(glyphIndex).isNull())
+            m_textureData->unusedGlyphs.insert(glyphIndex);
+    }
+}
+
+void QSGDefaultDistanceFieldGlyphCache::createTexture(int width, int height)
+{
+    if (useWorkaroundBrokenFBOReadback() && m_textureData->image.isNull())
+        m_textureData->image = QImage(width, height, QImage::Format_Indexed8);
+
+    while (glGetError() != GL_NO_ERROR) { }
+
+    glGenTextures(1, &m_textureData->texture);
+    glBindTexture(GL_TEXTURE_2D, m_textureData->texture);
+
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, 0);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+    m_textureData->size = QSize(width, height);
+
+    GLuint error = glGetError();
+    if (error != GL_NO_ERROR) {
+        glBindTexture(GL_TEXTURE_2D, 0);
+        glDeleteTextures(1, &m_textureData->texture);
+        m_textureData->texture = 0;
+    }
+
+}
+
+void QSGDefaultDistanceFieldGlyphCache::resizeTexture(int width, int height)
+{
+    int oldWidth = m_textureData->size.width();
+    int oldHeight = m_textureData->size.height();
+    if (width == oldWidth && height == oldHeight)
+        return;
+
+    GLuint oldTexture = m_textureData->texture;
+    createTexture(width, height);
+
+    if (!oldTexture)
+        return;
+
+    updateTexture(oldTexture, m_textureData->texture, m_textureData->size);
+
+    if (useWorkaroundBrokenFBOReadback()) {
+        glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, oldWidth, oldHeight, GL_ALPHA, GL_UNSIGNED_BYTE, m_textureData->image.constBits());
+        m_textureData->image = m_textureData->image.copy(0, 0, width, height);
+        glDeleteTextures(1, &oldTexture);
+        return;
+    }
+
+    if (!g_textureBlitHelper)
+        g_textureBlitHelper = new TextureBlitHelper;
+
+    if (!m_textureData->fbo)
+        ctx->functions()->glGenFramebuffers(1, &m_textureData->fbo);
+    ctx->functions()->glBindFramebuffer(GL_FRAMEBUFFER, m_textureData->fbo);
+
+    GLuint tmp_texture;
+    glGenTextures(1, &tmp_texture);
+    glBindTexture(GL_TEXTURE_2D, tmp_texture);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, oldWidth, oldHeight, 0,
+                 GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+    glBindTexture(GL_TEXTURE_2D, 0);
+    ctx->functions()->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+                                             GL_TEXTURE_2D, tmp_texture, 0);
+
+    ctx->functions()->glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D, oldTexture);
+
+    // save current render states
+    GLboolean stencilTestEnabled;
+    GLboolean depthTestEnabled;
+    GLboolean scissorTestEnabled;
+    GLboolean blendEnabled;
+    GLint viewport[4];
+    GLint oldProgram;
+    glGetBooleanv(GL_STENCIL_TEST, &stencilTestEnabled);
+    glGetBooleanv(GL_DEPTH_TEST, &depthTestEnabled);
+    glGetBooleanv(GL_SCISSOR_TEST, &scissorTestEnabled);
+    glGetBooleanv(GL_BLEND, &blendEnabled);
+    glGetIntegerv(GL_VIEWPORT, &viewport[0]);
+    glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram);
+
+    glDisable(GL_STENCIL_TEST);
+    glDisable(GL_DEPTH_TEST);
+    glDisable(GL_SCISSOR_TEST);
+    glDisable(GL_BLEND);
+
+    glViewport(0, 0, oldWidth, oldHeight);
+
+    ctx->functions()->glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, g_textureBlitHelper->blitVertexArray());
+    ctx->functions()->glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, g_textureBlitHelper->blitTextureArray());
+
+    g_textureBlitHelper->blitProgram()->bind();
+    g_textureBlitHelper->blitProgram()->enableAttributeArray(int(QT_VERTEX_COORDS_ATTR));
+    g_textureBlitHelper->blitProgram()->enableAttributeArray(int(QT_TEXTURE_COORDS_ATTR));
+    g_textureBlitHelper->blitProgram()->disableAttributeArray(int(QT_OPACITY_ATTR));
+    g_textureBlitHelper->blitProgram()->setUniformValue("imageTexture", GLuint(0));
+
+    glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+    glBindTexture(GL_TEXTURE_2D, m_textureData->texture);
+
+    glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, oldWidth, oldHeight);
+
+    ctx->functions()->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+                                                GL_RENDERBUFFER, 0);
+    glDeleteTextures(1, &tmp_texture);
+    glDeleteTextures(1, &oldTexture);
+
+    ctx->functions()->glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+    // restore render states
+    if (stencilTestEnabled)
+        glEnable(GL_STENCIL_TEST);
+    if (depthTestEnabled)
+        glEnable(GL_DEPTH_TEST);
+    if (scissorTestEnabled)
+        glEnable(GL_SCISSOR_TEST);
+    if (blendEnabled)
+        glEnable(GL_BLEND);
+    glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
+    ctx->functions()->glUseProgram(oldProgram);
+}
+
+bool QSGDefaultDistanceFieldGlyphCache::useWorkaroundBrokenFBOReadback() const
+{
+    static bool set = false;
+    static bool useWorkaround = false;
+    if (!set) {
+        QOpenGLContextPrivate *ctx_p = static_cast<QOpenGLContextPrivate *>(QOpenGLContextPrivate::get(ctx));
+        useWorkaround = ctx_p->workaround_brokenFBOReadBack;
+        set = true;
+    }
+    return useWorkaround;
+}
+
+int QSGDefaultDistanceFieldGlyphCache::maxTextureSize() const
+{
+    if (!m_maxTextureSize)
+        glGetIntegerv(GL_MAX_TEXTURE_SIZE, &m_maxTextureSize);
+    return m_maxTextureSize;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/scenegraph/qsgdefaultdistancefieldglyphcache_p.h b/src/declarative/scenegraph/qsgdefaultdistancefieldglyphcache_p.h
new file mode 100644
index 0000000000000000000000000000000000000000..aed8d72174f53d741df24ade3fcb244eb66c4395
--- /dev/null
+++ b/src/declarative/scenegraph/qsgdefaultdistancefieldglyphcache_p.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSGDEFAULTDISTANCEFIELDGLYPHCACHE_H
+#define QSGDEFAULTDISTANCEFIELDGLYPHCACHE_H
+
+#include <QtGui/qopenglfunctions.h>
+#include <private/qsgadaptationlayer_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_DECLARATIVE_EXPORT QSGDefaultDistanceFieldGlyphCache : public QSGDistanceFieldGlyphCache
+{
+public:
+    QSGDefaultDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, QOpenGLContext *c, const QRawFont &font);
+
+    void requestGlyphs(const QVector<glyph_t> &glyphs);
+    void storeGlyphs(const QHash<glyph_t, QImage> &glyphs);
+    void releaseGlyphs(const QVector<glyph_t> &glyphs);
+
+    bool cacheIsFull() const { return m_textureData->currY >= maxTextureSize(); }
+    bool useWorkaroundBrokenFBOReadback() const;
+    int maxTextureSize() const;
+
+private:
+    void createTexture(int width, int height);
+    void resizeTexture(int width, int height);
+
+    mutable int m_maxTextureSize;
+
+    struct DistanceFieldTextureData : public QOpenGLSharedResource {
+        GLuint texture;
+        GLuint fbo;
+        QSize size;
+        QHash<glyph_t, quint32> glyphRefCount;
+        QSet<glyph_t> unusedGlyphs;
+        int currX;
+        int currY;
+        QImage image;
+
+        DistanceFieldTextureData(QOpenGLContext *ctx)
+            : QOpenGLSharedResource(ctx->shareGroup())
+            , texture(0)
+            , fbo(0)
+            , currX(0)
+            , currY(0)
+        {}
+
+        void invalidateResource()
+        {
+            texture = 0;
+            fbo = 0;
+            size = QSize();
+        }
+
+        void freeResource(QOpenGLContext *ctx)
+        {
+            glDeleteTextures(1, &texture);
+            ctx->functions()->glDeleteFramebuffers(1, &fbo);
+        }
+    };
+
+    DistanceFieldTextureData *textureData();
+    DistanceFieldTextureData *m_textureData;
+    static QHash<QString, QOpenGLMultiGroupSharedResource> m_textures_data;
+};
+
+QT_END_NAMESPACE
+
+#endif // QSGDEFAULTDISTANCEFIELDGLYPHCACHE_H
diff --git a/src/declarative/scenegraph/qsgdistancefieldglyphcache_p.h b/src/declarative/scenegraph/qsgdistancefieldglyphcache_p.h
deleted file mode 100644
index aea7c5952f1741939624dfe98a9bd88123e0f967..0000000000000000000000000000000000000000
--- a/src/declarative/scenegraph/qsgdistancefieldglyphcache_p.h
+++ /dev/null
@@ -1,210 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the QtDeclarative module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** GNU Lesser General Public License Usage
-** 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.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef DISTANCEFIELDGLYPHCACHE_H
-#define DISTANCEFIELDGLYPHCACHE_H
-
-#include <qopengl.h>
-#include <qrawfont.h>
-#include <private/qopenglcontext_p.h>
-#include <QtGui/qopenglfunctions.h>
-#include <private/qfont_p.h>
-#include <private/qfontengine_p.h>
-#include <QtGui/private/qdatabuffer_p.h>
-#include <private/qsgadaptationlayer_p.h>
-
-QT_BEGIN_NAMESPACE
-
-typedef float (*ThresholdFunc)(float glyphScale);
-typedef float (*AntialiasingSpreadFunc)(float glyphScale);
-
-class QOpenGLShaderProgram;
-class QSGDistanceFieldGlyphCache;
-
-class Q_DECLARATIVE_EXPORT QSGDistanceFieldGlyphCacheManager
-{
-public:
-    QSGDistanceFieldGlyphCacheManager(QOpenGLContext *c);
-    ~QSGDistanceFieldGlyphCacheManager();
-
-    QSGDistanceFieldGlyphCache *cache(const QRawFont &font);
-
-    QSGGlyphNode::AntialiasingMode defaultAntialiasingMode() const { return m_defaultAntialiasingMode; }
-    void setDefaultAntialiasingMode(QSGGlyphNode::AntialiasingMode mode) { m_defaultAntialiasingMode = mode; }
-
-    ThresholdFunc thresholdFunc() const { return m_threshold_func; }
-    void setThresholdFunc(ThresholdFunc func) { m_threshold_func = func; }
-
-    AntialiasingSpreadFunc antialiasingSpreadFunc() const { return m_antialiasingSpread_func; }
-    void setAntialiasingSpreadFunc(AntialiasingSpreadFunc func) { m_antialiasingSpread_func = func; }
-
-    QOpenGLShaderProgram *blitProgram() { return m_blitProgram; }
-    const GLfloat *blitVertexArray() const { return &m_vertexCoordinateArray[0]; }
-    const GLfloat *blitTextureArray() const { return &m_textureCoordinateArray[0]; }
-
-    int maxTextureSize() const;
-
-private:
-    QHash<QFontEngine *, QSGDistanceFieldGlyphCache *> m_caches;
-
-    QOpenGLContext *ctx;
-
-    QSGGlyphNode::AntialiasingMode m_defaultAntialiasingMode;
-    ThresholdFunc m_threshold_func;
-    AntialiasingSpreadFunc m_antialiasingSpread_func;
-
-    mutable int m_maxTextureSize;
-
-    QOpenGLShaderProgram *m_blitProgram;
-    GLfloat m_vertexCoordinateArray[8];
-    GLfloat m_textureCoordinateArray[8];
-};
-
-class Q_DECLARATIVE_EXPORT QSGDistanceFieldGlyphCache
-{
-public:
-    ~QSGDistanceFieldGlyphCache();
-
-    struct Metrics {
-        qreal width;
-        qreal height;
-        qreal baselineX;
-        qreal baselineY;
-
-        bool isNull() const { return width == 0 || height == 0; }
-    };
-    Metrics glyphMetrics(glyph_t glyph);
-
-    struct TexCoord {
-        qreal x;
-        qreal y;
-        qreal width;
-        qreal height;
-        qreal xMargin;
-        qreal yMargin;
-
-        TexCoord() : x(0), y(0), width(0), height(0), xMargin(0), yMargin(0) { }
-
-        bool isNull() const { return width == 0 || height == 0; }
-    };
-    TexCoord glyphTexCoord(glyph_t glyph);
-
-    const QSGDistanceFieldGlyphCacheManager *manager() const { return m_manager; }
-
-    GLuint texture();
-    QSize textureSize() const;
-    qreal fontScale() const;
-    int distanceFieldRadius() const;
-    QImage renderDistanceFieldGlyph(glyph_t glyph) const;
-
-    int glyphCount() const;
-
-    void populate(int count, const glyph_t *glyphs);
-    void derefGlyphs(int count, const glyph_t *glyphs);
-    void updateCache();
-
-    bool cacheIsFull() const { return m_textureData->currY >= m_manager->maxTextureSize(); }
-
-    bool useWorkaroundBrokenFBOReadback() const;
-
-private:
-    QSGDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, QOpenGLContext *c, const QRawFont &font);
-
-    void createTexture(int width, int height);
-    void resizeTexture(int width, int height);
-
-    QSGDistanceFieldGlyphCacheManager *m_manager;
-
-    QOpenGLContext *ctx;
-
-    QRawFont m_font;
-    QRawFont m_referenceFont;
-
-    int m_glyphCount;
-    QHash<glyph_t, Metrics> m_metrics;
-
-    struct DistanceFieldTextureData : public QOpenGLSharedResource {
-        GLuint texture;
-        GLuint fbo;
-        QSize size;
-        QHash<glyph_t, TexCoord> texCoords;
-        QDataBuffer<glyph_t> pendingGlyphs;
-        QHash<glyph_t, quint32> glyphRefCount;
-        QSet<glyph_t> unusedGlyphs;
-        int currX;
-        int currY;
-        QImage image;
-        bool doubleGlyphResolution;
-
-        DistanceFieldTextureData(QOpenGLContext *ctx)
-            : QOpenGLSharedResource(ctx->shareGroup())
-            , texture(0)
-            , fbo(0)
-            , pendingGlyphs(64)
-            , currX(0)
-            , currY(0)
-            , doubleGlyphResolution(false)
-        {}
-
-        void invalidateResource()
-        {
-            texture = 0;
-            fbo = 0;
-            size = QSize();
-        }
-
-        void freeResource(QOpenGLContext *ctx)
-        {
-            glDeleteTextures(1, &texture);
-            ctx->functions()->glDeleteFramebuffers(1, &fbo);
-        }
-    };
-
-    DistanceFieldTextureData *textureData();
-    DistanceFieldTextureData *m_textureData;
-    static QHash<QString, QOpenGLMultiGroupSharedResource> m_textures_data;
-
-    friend class QSGDistanceFieldGlyphCacheManager;
-};
-
-QT_END_NAMESPACE
-
-#endif // DISTANCEFIELDGLYPHCACHE_H
diff --git a/src/declarative/scenegraph/qsgdistancefieldglyphnode.cpp b/src/declarative/scenegraph/qsgdistancefieldglyphnode.cpp
index e25b1520a1e9595eba8985eba78e1b7e8a592606..e4a39e484bd433b0d805689616195b407026cc7a 100644
--- a/src/declarative/scenegraph/qsgdistancefieldglyphnode.cpp
+++ b/src/declarative/scenegraph/qsgdistancefieldglyphnode.cpp
@@ -41,7 +41,7 @@
 
 #include "qsgdistancefieldglyphnode_p.h"
 #include "qsgdistancefieldglyphnode_p_p.h"
-#include "qsgdistancefieldglyphcache_p.h"
+#include <private/qsgdistancefieldutil_p.h>
 #include <private/qsgcontext_p.h>
 
 QT_BEGIN_NAMESPACE
@@ -53,7 +53,6 @@ QSGDistanceFieldGlyphNode::QSGDistanceFieldGlyphNode(QSGDistanceFieldGlyphCacheM
     , m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 0)
     , m_style(QQuickText::Normal)
     , m_antialiasingMode(GrayAntialiasing)
-    , m_dirtyFont(false)
     , m_dirtyGeometry(false)
     , m_dirtyMaterial(false)
 {
@@ -69,8 +68,8 @@ QSGDistanceFieldGlyphNode::~QSGDistanceFieldGlyphNode()
 {
     delete m_material;
     if (m_glyph_cache) {
-        const QVector<quint32> &glyphIndexes = m_glyphs.glyphIndexes();
-        m_glyph_cache->derefGlyphs(glyphIndexes.count(), glyphIndexes.constData());
+        m_glyph_cache->release(m_glyphs.glyphIndexes());
+        m_glyph_cache->unregisterGlyphNode(this);
     }
 }
 
@@ -97,7 +96,24 @@ void QSGDistanceFieldGlyphNode::setGlyphs(const QPointF &position, const QGlyphR
     m_position = QPointF(position.x(), position.y() - font.ascent());
     m_glyphs = glyphs;
 
-    m_dirtyFont = true;
+    QSGDistanceFieldGlyphCache *oldCache = m_glyph_cache;
+    m_glyph_cache = m_glyph_cacheManager->cache(m_glyphs.rawFont());
+    if (m_glyph_cache != oldCache) {
+        if (oldCache)
+            oldCache->unregisterGlyphNode(this);
+        m_glyph_cache->registerGlyphNode(this);
+    }
+    m_glyph_cache->populate(glyphs.glyphIndexes());
+
+    const QVector<quint32> &glyphIndexes = m_glyphs.glyphIndexes();
+    const QVector<QPointF> &glyphPositions = m_glyphs.positions();
+    for (int i = 0; i < glyphIndexes.size(); ++i) {
+        GlyphInfo g;
+        g.glyphIndex = glyphIndexes.at(i);
+        g.position = glyphPositions.at(i);
+        m_glyphsToAdd.append(g);
+    }
+
     m_dirtyGeometry = true;
     m_dirtyMaterial = true;
 }
@@ -120,78 +136,74 @@ void QSGDistanceFieldGlyphNode::setStyleColor(const QColor &color)
 
 void QSGDistanceFieldGlyphNode::update()
 {
-    if (m_dirtyFont)
-        updateFont();
-    if (m_dirtyGeometry)
-        updateGeometry();
     if (m_dirtyMaterial)
         updateMaterial();
+    if (m_dirtyGeometry)
+        updateGeometry();
 }
 
 void QSGDistanceFieldGlyphNode::updateGeometry()
 {
     Q_ASSERT(m_glyph_cache);
 
-    QSGGeometry *g = geometry();
-    QRectF boundingRect;
-
-    const QVector<quint32> &glyphIndexes = m_glyphs.glyphIndexes();
+    if (m_glyphsToAdd.isEmpty())
+        return;
 
-    m_glyph_cache->populate(glyphIndexes.count(), glyphIndexes.constData());
+    QSGGeometry *g = geometry();
 
     Q_ASSERT(g->indexType() == GL_UNSIGNED_SHORT);
 
     int oldVertexCount = g->vertexCount();
     int oldIndexCount = g->indexCount();
 
-    // We could potentially move the realloc part into the QSGGeometry object as a
-    // grow() function...
+    QVector<QSGGeometry::TexturedPoint2D> vp;
+    vp.reserve(m_glyphsToAdd.size() * 4);
+    QVector<ushort> ip;
+    ip.reserve(m_glyphsToAdd.size() * 6);
 
-    void *data = 0;
-    if (oldVertexCount && oldIndexCount) {
-        int byteSize = oldVertexCount * sizeof(QSGGeometry::TexturedPoint2D)
-                     + oldIndexCount * sizeof(quint16);
-        data = qMalloc(byteSize);
-        memcpy(data, g->vertexData(), byteSize);
-    }
+    QPointF margins(2, 2);
+    QPointF texMargins = margins / m_glyph_cache->fontScale();
 
-    g->allocate(oldVertexCount + glyphIndexes.size() * 4, oldIndexCount + glyphIndexes.size() * 6);
+    const QSGDistanceFieldGlyphCache::Texture *textureToUse = 0;
 
-    if (data) {
-        memcpy(g->vertexData(), data, oldVertexCount * sizeof(QSGGeometry::TexturedPoint2D));
-        memcpy(g->indexData(), ((char *) data) + oldVertexCount * sizeof(QSGGeometry::TexturedPoint2D),
-               oldIndexCount * sizeof(quint16));
-        qFree(data);
-    }
+    QLinkedList<GlyphInfo>::iterator it = m_glyphsToAdd.begin();
+    while (it != m_glyphsToAdd.end()) {
+        quint32 glyphIndex = it->glyphIndex;
+        QSGDistanceFieldGlyphCache::TexCoord c = m_glyph_cache->glyphTexCoord(glyphIndex);
 
-    QSGGeometry::TexturedPoint2D *vp = g->vertexDataAsTexturedPoint2D() + oldVertexCount;
-    ushort *ip = g->indexDataAsUShort() + oldIndexCount;
+        if (c.isNull()) {
+            if (!c.isValid())
+                ++it;
+            else
+                it = m_glyphsToAdd.erase(it);
+            continue;
+        }
 
-    QPointF margins(2, 2);
-    QPointF texMargins = margins / m_glyph_cache->fontScale();
+        const QSGDistanceFieldGlyphCache::Texture *texture = m_glyph_cache->glyphTexture(glyphIndex);
+        if (!texture->textureId) {
+            ++it;
+            continue;
+        }
 
-    QVector<QPointF> glyphPositions = m_glyphs.positions();
-    for (int i = 0; i < glyphIndexes.size(); ++i) {
-        quint32 glyphIndex = glyphIndexes.at(i);
         QSGDistanceFieldGlyphCache::Metrics metrics = m_glyph_cache->glyphMetrics(glyphIndex);
-        QSGDistanceFieldGlyphCache::TexCoord c = m_glyph_cache->glyphTexCoord(glyphIndex);
 
-        if (!metrics.isNull() && !c.isNull()) {
-                metrics.width += margins.x() * 2;
-                metrics.height += margins.y() * 2;
-                metrics.baselineX -= margins.x();
-                metrics.baselineY += margins.y();
-                c.xMargin -= texMargins.x();
-                c.yMargin -= texMargins.y();
-                c.width += texMargins.x() * 2;
-                c.height += texMargins.y() * 2;
-        }
+        if (!textureToUse)
+            textureToUse = texture;
 
-        const QPointF &glyphPosition = glyphPositions.at(i);
+        metrics.width += margins.x() * 2;
+        metrics.height += margins.y() * 2;
+        metrics.baselineX -= margins.x();
+        metrics.baselineY += margins.y();
+        c.xMargin -= texMargins.x();
+        c.yMargin -= texMargins.y();
+        c.width += texMargins.x() * 2;
+        c.height += texMargins.y() * 2;
+
+        const QPointF &glyphPosition = it->position;
         qreal x = glyphPosition.x() + metrics.baselineX + m_position.x();
         qreal y = glyphPosition.y() - metrics.baselineY + m_position.y();
 
-        boundingRect |= QRectF(x, y, metrics.width, metrics.height);
+        m_boundingRect |= QRectF(x, y, metrics.width, metrics.height);
 
         float cx1 = x;
         float cx2 = x + metrics.width;
@@ -206,49 +218,60 @@ void QSGDistanceFieldGlyphNode::updateGeometry()
         if (m_baseLine.isNull())
             m_baseLine = glyphPosition;
 
-        int vi = i & 1 ? (glyphIndexes.size() + 1) / 2 + i / 2 : i / 2;
-        vp[4 * vi + 0].set(cx1, cy1, tx1, ty1);
-        vp[4 * vi + 1].set(cx2, cy1, tx2, ty1);
-        vp[4 * vi + 2].set(cx1, cy2, tx1, ty2);
-        vp[4 * vi + 3].set(cx2, cy2, tx2, ty2);
-
-        int o = i * 4 + oldVertexCount;
-        ip[6 * i + 0] = o + 0;
-        ip[6 * i + 1] = o + 2;
-        ip[6 * i + 2] = o + 3;
-        ip[6 * i + 3] = o + 3;
-        ip[6 * i + 4] = o + 1;
-        ip[6 * i + 5] = o + 0;
+        int i = vp.size();
+
+        QSGGeometry::TexturedPoint2D v1;
+        v1.set(cx1, cy1, tx1, ty1);
+        QSGGeometry::TexturedPoint2D v2;
+        v2.set(cx2, cy1, tx2, ty1);
+        QSGGeometry::TexturedPoint2D v3;
+        v3.set(cx1, cy2, tx1, ty2);
+        QSGGeometry::TexturedPoint2D v4;
+        v4.set(cx2, cy2, tx2, ty2);
+        vp.append(v1);
+        vp.append(v2);
+        vp.append(v3);
+        vp.append(v4);
+
+        int o = i + oldVertexCount;
+        ip.append(o + 0);
+        ip.append(o + 2);
+        ip.append(o + 3);
+        ip.append(o + 3);
+        ip.append(o + 1);
+        ip.append(o + 0);
+
+        it = m_glyphsToAdd.erase(it);
     }
 
-//    printf("Vertices:\n");
-//    for (int v=0; v<g->vertexCount(); ++v) {
-//        QSGGeometry::TexturedPoint2D *t = g->vertexDataAsTexturedPoint2D() + v;
-//        printf(" - %d -- %f %f  --  %.3f %.3f\n", v, t->x, t->y, t->tx, t->ty);
-//    }
-
-//    printf("Indices:\n");
-//    for (int i=0; i<g->indexCount();) {
-
-//        printf(" - %[ ", i);
-//        printf("%d, ", g->indexDataAsUShort()[i++]);
-//        printf("%d, ", g->indexDataAsUShort()[i++]);
-//        printf("%d, ", g->indexDataAsUShort()[i++]);
-//        printf("%d, ", g->indexDataAsUShort()[i++]);
-//        printf("%d, ", g->indexDataAsUShort()[i++]);
-//        printf("%d",   g->indexDataAsUShort()[i++]);
-//        printf(" ]\n");
-//    }
-
-    setBoundingRect(boundingRect);
+    if (vp.isEmpty())
+        return;
+
+    void *data = 0;
+    if (oldVertexCount && oldIndexCount) {
+        int byteSize = oldVertexCount * sizeof(QSGGeometry::TexturedPoint2D)
+                     + oldIndexCount * sizeof(quint16);
+        data = qMalloc(byteSize);
+        memcpy(data, g->vertexData(), byteSize);
+    }
+
+    g->allocate(oldVertexCount + vp.size(), oldIndexCount + ip.size());
+
+    if (data) {
+        memcpy(g->vertexData(), data, oldVertexCount * sizeof(QSGGeometry::TexturedPoint2D));
+        memcpy(g->indexData(), ((char *) data) + oldVertexCount * sizeof(QSGGeometry::TexturedPoint2D),
+               oldIndexCount * sizeof(quint16));
+        qFree(data);
+    }
+
+    memcpy(g->vertexDataAsTexturedPoint2D() + oldVertexCount, vp.constData(), vp.size() * sizeof(QSGGeometry::TexturedPoint2D));
+    memcpy(g->indexDataAsUShort() + oldIndexCount, ip.constData(), ip.size() * sizeof(quint16));
+
+    setBoundingRect(m_boundingRect);
     markDirty(DirtyGeometry);
     m_dirtyGeometry = false;
-}
 
-void QSGDistanceFieldGlyphNode::updateFont()
-{
-    m_glyph_cache = m_glyph_cacheManager->cache(m_glyphs.rawFont());
-    m_dirtyFont = false;
+    m_material->setTexture(textureToUse);
 }
 
 void QSGDistanceFieldGlyphNode::updateMaterial()
diff --git a/src/declarative/scenegraph/qsgdistancefieldglyphnode_p.cpp b/src/declarative/scenegraph/qsgdistancefieldglyphnode_p.cpp
index a7dbb3b7f64a4e9b92785790e16b6ebde6a76b7e..a506e23cc1c37a43844d33104c451abeb618b970 100644
--- a/src/declarative/scenegraph/qsgdistancefieldglyphnode_p.cpp
+++ b/src/declarative/scenegraph/qsgdistancefieldglyphnode_p.cpp
@@ -40,7 +40,7 @@
 ****************************************************************************/
 
 #include "qsgdistancefieldglyphnode_p_p.h"
-#include "qsgdistancefieldglyphcache_p.h"
+#include <private/qsgdistancefieldutil_p.h>
 #include <private/qsgtexture_p.h>
 #include <QtGui/qopenglfunctions.h>
 #include <qmath.h>
@@ -138,9 +138,7 @@ void QSGDistanceFieldTextMaterialShader::updateState(const RenderState &state, Q
     QSGDistanceFieldTextMaterial *material = static_cast<QSGDistanceFieldTextMaterial *>(newEffect);
     QSGDistanceFieldTextMaterial *oldMaterial = static_cast<QSGDistanceFieldTextMaterial *>(oldEffect);
 
-    bool updated = material->updateTexture();
-    if (updated && !material->glyphCache()->useWorkaroundBrokenFBOReadback())
-        activate();
+    bool updated = material->updateCache();
 
     if (oldMaterial == 0
            || material->color() != oldMaterial->color()
@@ -171,10 +169,10 @@ void QSGDistanceFieldTextMaterialShader::updateState(const RenderState &state, Q
 
     if (updated
             || oldMaterial == 0
-            || oldMaterial->glyphCache()->texture() != material->glyphCache()->texture()) {
-        program()->setUniformValue(m_textureScale_id, QVector2D(1.0 / material->glyphCache()->textureSize().width(),
-                                                               1.0 / material->glyphCache()->textureSize().height()));
-        glBindTexture(GL_TEXTURE_2D, material->glyphCache()->texture());
+            || oldMaterial->texture()->textureId != material->texture()->textureId) {
+        program()->setUniformValue(m_textureScale_id, QVector2D(1.0 / material->textureSize().width(),
+                                                                1.0 / material->textureSize().height()));
+        glBindTexture(GL_TEXTURE_2D, material->texture()->textureId);
 
         if (updated) {
             // Set the mag/min filters to be linear. We only need to do this when the texture
@@ -189,6 +187,7 @@ void QSGDistanceFieldTextMaterialShader::updateState(const RenderState &state, Q
 
 QSGDistanceFieldTextMaterial::QSGDistanceFieldTextMaterial()
     : m_glyph_cache(0)
+    , m_texture(0)
 {
    setFlag(Blending, true);
 }
@@ -208,10 +207,12 @@ QSGMaterialShader *QSGDistanceFieldTextMaterial::createShader() const
     return new QSGDistanceFieldTextMaterialShader;
 }
 
-bool QSGDistanceFieldTextMaterial::updateTexture()
+bool QSGDistanceFieldTextMaterial::updateCache()
 {
-    m_glyph_cache->updateCache();
-    QSize glyphCacheSize = m_glyph_cache->textureSize();
+    m_glyph_cache->update();
+    if (!m_texture)
+        m_texture = m_glyph_cache->glyphTexture(-1); // invalid texture
+    QSize glyphCacheSize = m_texture->size;
     if (glyphCacheSize != m_size) {
         m_size = glyphCacheSize;
 
@@ -433,7 +434,7 @@ void DistanceFieldShiftedStyleTextMaterialShader::updateState(const RenderState
     if (oldMaterial == 0
             || oldMaterial->glyphCache()->fontScale() != material->glyphCache()->fontScale()
             || oldMaterial->shift() != material->shift()
-            || oldMaterial->glyphCache()->textureSize() != material->glyphCache()->textureSize()) {
+            || oldMaterial->textureSize() != material->textureSize()) {
         updateShift(material->glyphCache(), material->shift());
     }
 }
diff --git a/src/declarative/scenegraph/qsgdistancefieldglyphnode_p.h b/src/declarative/scenegraph/qsgdistancefieldglyphnode_p.h
index 1d8bcea86868dc9da71c672ef32a938ac1aaf363..f4877b0a1df77b6840afdf863d0dfd18936b3742 100644
--- a/src/declarative/scenegraph/qsgdistancefieldglyphnode_p.h
+++ b/src/declarative/scenegraph/qsgdistancefieldglyphnode_p.h
@@ -53,7 +53,6 @@ QT_BEGIN_NAMESPACE
 
 QT_MODULE(Declarative)
 
-class QSGDistanceFieldGlyphCache;
 class QSGDistanceFieldGlyphCacheManager;
 class QSGDistanceFieldTextMaterial;
 class QSGDistanceFieldGlyphNode: public QSGGlyphNode
@@ -73,9 +72,9 @@ public:
 
     virtual void update();
 
-private:
     void updateGeometry();
-    void updateFont();
+
+private:
     void updateMaterial();
 
     QColor m_color;
@@ -89,8 +88,14 @@ private:
     QQuickText::TextStyle m_style;
     QColor m_styleColor;
     AntialiasingMode m_antialiasingMode;
+    QRectF m_boundingRect;
+
+    struct GlyphInfo {
+        quint32 glyphIndex;
+        QPointF position;
+    };
+    QLinkedList<GlyphInfo> m_glyphsToAdd;
 
-    uint m_dirtyFont: 1;
     uint m_dirtyGeometry: 1;
     uint m_dirtyMaterial: 1;
 };
diff --git a/src/declarative/scenegraph/qsgdistancefieldglyphnode_p_p.h b/src/declarative/scenegraph/qsgdistancefieldglyphnode_p_p.h
index 8733edf203d97cae39e64d1c300e6ab282ccca14..c8c73bfac0725ce9e48a08e321f5a7a7c0201509 100644
--- a/src/declarative/scenegraph/qsgdistancefieldglyphnode_p_p.h
+++ b/src/declarative/scenegraph/qsgdistancefieldglyphnode_p_p.h
@@ -44,11 +44,10 @@
 
 #include <qsgmaterial.h>
 #include "qsgdistancefieldglyphnode_p.h"
+#include "qsgadaptationlayer_p.h"
 
 QT_BEGIN_NAMESPACE
 
-class QSGDistanceFieldGlyphCache;
-
 class QSGDistanceFieldTextMaterial: public QSGMaterial
 {
 public:
@@ -65,12 +64,18 @@ public:
     void setGlyphCache(QSGDistanceFieldGlyphCache *a) { m_glyph_cache = a; }
     QSGDistanceFieldGlyphCache *glyphCache() const { return m_glyph_cache; }
 
-    bool updateTexture();
+    void setTexture(const QSGDistanceFieldGlyphCache::Texture * tex) { m_texture = tex; }
+    const QSGDistanceFieldGlyphCache::Texture * texture() const { return m_texture; }
+
+    QSize textureSize() const { return m_size; }
+
+    bool updateCache();
 
 protected:
     QSize m_size;
     QColor m_color;
     QSGDistanceFieldGlyphCache *m_glyph_cache;
+    const QSGDistanceFieldGlyphCache::Texture *m_texture;
 };
 
 class QSGDistanceFieldStyledTextMaterial : public QSGDistanceFieldTextMaterial
diff --git a/src/declarative/scenegraph/scenegraph.pri b/src/declarative/scenegraph/scenegraph.pri
index d4e0707ba3455bef71ba2dbf03d171ba7eff561d..0adc20502d0a1459b9d8e9b29cecb4c3aeeb8466 100644
--- a/src/declarative/scenegraph/scenegraph.pri
+++ b/src/declarative/scenegraph/scenegraph.pri
@@ -33,7 +33,8 @@ HEADERS += \
     $$PWD/util/qsgtexture.h \
     $$PWD/util/qsgtexture_p.h \
     $$PWD/util/qsgtextureprovider_p.h \
-    $$PWD/util/qsgpainternode_p.h
+    $$PWD/util/qsgpainternode_p.h \
+    $$PWD/util/qsgdistancefieldutil_p.h
 
 SOURCES += \
     $$PWD/util/qsgareaallocator.cpp \
@@ -45,7 +46,8 @@ SOURCES += \
     $$PWD/util/qsgvertexcolormaterial.cpp \
     $$PWD/util/qsgtexture.cpp \
     $$PWD/util/qsgtextureprovider.cpp \
-    $$PWD/util/qsgpainternode.cpp
+    $$PWD/util/qsgpainternode.cpp \
+    $$PWD/util/qsgdistancefieldutil.cpp
 
 
 # QML / Adaptations API
@@ -54,7 +56,7 @@ HEADERS += \
     $$PWD/qsgcontext_p.h \
     $$PWD/qsgcontextplugin_p.h \
     $$PWD/qsgdefaultglyphnode_p.h \
-    $$PWD/qsgdistancefieldglyphcache_p.h \
+    $$PWD/qsgdefaultdistancefieldglyphcache_p.h \
     $$PWD/qsgdistancefieldglyphnode_p.h \
     $$PWD/qsgdistancefieldglyphnode_p_p.h \
     $$PWD/qsgdefaultglyphnode_p_p.h \
@@ -69,10 +71,16 @@ SOURCES += \
     $$PWD/qsgcontextplugin.cpp \
     $$PWD/qsgdefaultglyphnode.cpp \
     $$PWD/qsgdefaultglyphnode_p.cpp \
-    $$PWD/qsgdistancefieldglyphcache.cpp \
+    $$PWD/qsgdefaultdistancefieldglyphcache.cpp \
     $$PWD/qsgdistancefieldglyphnode.cpp \
     $$PWD/qsgdistancefieldglyphnode_p.cpp \
     $$PWD/qsgdefaultimagenode.cpp \
     $$PWD/qsgdefaultrectanglenode.cpp \
     $$PWD/qsgflashnode.cpp \
     $$PWD/qsgpathsimplifier.cpp
+
+
+
+
+
+
diff --git a/src/declarative/scenegraph/qsgdistancefieldglyphcache.cpp b/src/declarative/scenegraph/util/qsgdistancefieldutil.cpp
similarity index 65%
rename from src/declarative/scenegraph/qsgdistancefieldglyphcache.cpp
rename to src/declarative/scenegraph/util/qsgdistancefieldutil.cpp
index 60e5bb77273ff33f684a3d0728f7a2deec6227e0..a74c96b8088e8a2050ff3752a56b57cac59cc31b 100644
--- a/src/declarative/scenegraph/qsgdistancefieldglyphcache.cpp
+++ b/src/declarative/scenegraph/util/qsgdistancefieldutil.cpp
@@ -39,53 +39,14 @@
 **
 ****************************************************************************/
 
-#include "qsgdistancefieldglyphcache_p.h"
+#include "qsgdistancefieldutil_p.h"
 
 #include <qmath.h>
 #include <private/qsgpathsimplifier_p.h>
-#include <private/qdeclarativeglobal_p.h>
-#include <qopenglshaderprogram.h>
+#include <private/qsgadaptationlayer_p.h>
 #include <QtGui/private/qopenglengineshadersource_p.h>
 #include <private/qsgcontext_p.h>
-#include <private/qrawfont_p.h>
-#include <qopenglfunctions.h>
-#include <qglyphrun.h>
-#include <qrawfont.h>
-#include <qdir.h>
-#include <QtGui/qguiapplication.h>
-
-QT_BEGIN_NAMESPACE
-
-#define QT_DISTANCEFIELD_DEFAULT_BASEFONTSIZE 54
-#define QT_DISTANCEFIELD_DEFAULT_TILESIZE 64
-#define QT_DISTANCEFIELD_DEFAULT_SCALE 16
-#define QT_DISTANCEFIELD_DEFAULT_RADIUS 80
-#define QT_DISTANCEFIELD_HIGHGLYPHCOUNT 2000
-
-#define QT_DISTANCEFIELD_BASEFONTSIZE \
-    (m_textureData->doubleGlyphResolution ? QT_DISTANCEFIELD_DEFAULT_BASEFONTSIZE * 2 : \
-                                           QT_DISTANCEFIELD_DEFAULT_BASEFONTSIZE)
-#define QT_DISTANCEFIELD_TILESIZE \
-    (m_textureData->doubleGlyphResolution ? QT_DISTANCEFIELD_DEFAULT_TILESIZE * 2 : \
-                                           QT_DISTANCEFIELD_DEFAULT_TILESIZE)
-#define QT_DISTANCEFIELD_SCALE \
-    (m_textureData->doubleGlyphResolution ? QT_DISTANCEFIELD_DEFAULT_SCALE / 2 : \
-                                           QT_DISTANCEFIELD_DEFAULT_SCALE)
-#define QT_DISTANCEFIELD_RADIUS \
-    (m_textureData->doubleGlyphResolution ? QT_DISTANCEFIELD_DEFAULT_RADIUS / 2 : \
-                                           QT_DISTANCEFIELD_DEFAULT_RADIUS)
-
-static inline int qt_next_power_of_two(int v)
-{
-    v--;
-    v |= v >> 1;
-    v |= v >> 2;
-    v |= v >> 4;
-    v |= v >> 8;
-    v |= v >> 16;
-    ++v;
-    return v;
-}
+
 
 static float defaultThresholdFunc(float glyphScale)
 {
@@ -748,7 +709,7 @@ static QImage makeDistanceField(int imgSize, const QPainterPath &path, int dfSca
     return image;
 }
 
-static bool fontHasNarrowOutlines(const QRawFont &f)
+bool qt_fontHasNarrowOutlines(const QRawFont &f)
 {
     QRawFont font = f;
     font.setPixelSize(QT_DISTANCEFIELD_DEFAULT_BASEFONTSIZE);
@@ -798,65 +759,36 @@ static bool fontHasNarrowOutlines(const QRawFont &f)
     return minHThick == 1 || minVThick == 1;
 }
 
-QSGDistanceFieldGlyphCacheManager::QSGDistanceFieldGlyphCacheManager(QOpenGLContext *c)
-    : ctx(c)
+QImage qt_renderDistanceFieldGlyph(const QRawFont &font, glyph_t glyph, bool doubleResolution)
+{
+    QRawFont renderFont = font;
+    renderFont.setPixelSize(QT_DISTANCEFIELD_BASEFONTSIZE(doubleResolution) * QT_DISTANCEFIELD_SCALE(doubleResolution));
+
+    QPainterPath path = renderFont.pathForGlyph(glyph);
+    path.translate(-path.boundingRect().topLeft());
+    path.setFillRule(Qt::WindingFill);
+
+    QImage im = makeDistanceField(QT_DISTANCEFIELD_TILESIZE(doubleResolution),
+                                  path,
+                                  QT_DISTANCEFIELD_SCALE(doubleResolution),
+                                  QT_DISTANCEFIELD_RADIUS(doubleResolution) / QT_DISTANCEFIELD_SCALE(doubleResolution));
+    return im;
+}
+
+QSGDistanceFieldGlyphCacheManager::QSGDistanceFieldGlyphCacheManager(QSGContext *c)
+    : sgCtx(c)
     , m_threshold_func(defaultThresholdFunc)
     , m_antialiasingSpread_func(defaultAntialiasingSpreadFunc)
-    , m_maxTextureSize(0)
 {
 #ifndef QT_OPENGL_ES
     m_defaultAntialiasingMode = QSGGlyphNode::HighQualitySubPixelAntialiasing;
 #else
     m_defaultAntialiasingMode = QSGGlyphNode::GrayAntialiasing;
 #endif
-
-    m_vertexCoordinateArray[0] = -1.0f;
-    m_vertexCoordinateArray[1] = -1.0f;
-    m_vertexCoordinateArray[2] =  1.0f;
-    m_vertexCoordinateArray[3] = -1.0f;
-    m_vertexCoordinateArray[4] =  1.0f;
-    m_vertexCoordinateArray[5] =  1.0f;
-    m_vertexCoordinateArray[6] = -1.0f;
-    m_vertexCoordinateArray[7] =  1.0f;
-
-    m_textureCoordinateArray[0] = 0.0f;
-    m_textureCoordinateArray[1] = 0.0f;
-    m_textureCoordinateArray[2] = 1.0f;
-    m_textureCoordinateArray[3] = 0.0f;
-    m_textureCoordinateArray[4] = 1.0f;
-    m_textureCoordinateArray[5] = 1.0f;
-    m_textureCoordinateArray[6] = 0.0f;
-    m_textureCoordinateArray[7] = 1.0f;
-
-    m_blitProgram = new QOpenGLShaderProgram;
-    {
-        QString source;
-        source.append(QLatin1String(qopenglslMainWithTexCoordsVertexShader));
-        source.append(QLatin1String(qopenglslUntransformedPositionVertexShader));
-
-        QOpenGLShader *vertexShader = new QOpenGLShader(QOpenGLShader::Vertex, m_blitProgram);
-        vertexShader->compileSourceCode(source);
-
-        m_blitProgram->addShader(vertexShader);
-    }
-    {
-        QString source;
-        source.append(QLatin1String(qopenglslMainFragmentShader));
-        source.append(QLatin1String(qopenglslImageSrcFragmentShader));
-
-        QOpenGLShader *fragmentShader = new QOpenGLShader(QOpenGLShader::Fragment, m_blitProgram);
-        fragmentShader->compileSourceCode(source);
-
-        m_blitProgram->addShader(fragmentShader);
-    }
-    m_blitProgram->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR);
-    m_blitProgram->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR);
-    m_blitProgram->link();
 }
 
 QSGDistanceFieldGlyphCacheManager::~QSGDistanceFieldGlyphCacheManager()
 {
-    delete m_blitProgram;
     qDeleteAll(m_caches.values());
 }
 
@@ -865,393 +797,6 @@ QSGDistanceFieldGlyphCache *QSGDistanceFieldGlyphCacheManager::cache(const QRawF
     QRawFontPrivate *fontD = QRawFontPrivate::get(font);
     QHash<QFontEngine *, QSGDistanceFieldGlyphCache *>::iterator cache = m_caches.find(fontD->fontEngine);
     if (cache == m_caches.end())
-        cache = m_caches.insert(fontD->fontEngine, new QSGDistanceFieldGlyphCache(this, ctx, font));
+        cache = m_caches.insert(fontD->fontEngine, sgCtx->createDistanceFieldGlyphCache(font));
     return cache.value();
 }
-
-int QSGDistanceFieldGlyphCacheManager::maxTextureSize() const
-{
-    if (!m_maxTextureSize)
-        glGetIntegerv(GL_MAX_TEXTURE_SIZE, &m_maxTextureSize);
-    return m_maxTextureSize;
-}
-
-
-QHash<QString, QOpenGLMultiGroupSharedResource> QSGDistanceFieldGlyphCache::m_textures_data;
-
-QSGDistanceFieldGlyphCache::DistanceFieldTextureData *QSGDistanceFieldGlyphCache::textureData()
-{
-    QString key = QString::fromLatin1("%1_%2_%3_%4")
-            .arg(m_font.familyName())
-            .arg(m_font.styleName())
-            .arg(m_font.weight())
-            .arg(m_font.style());
-    return m_textures_data[key].value<QSGDistanceFieldGlyphCache::DistanceFieldTextureData>(QOpenGLContext::currentContext());
-}
-
-QSGDistanceFieldGlyphCache::QSGDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, QOpenGLContext *c, const QRawFont &font)
-    : m_manager(man)
-    , ctx(c)
-{
-    Q_ASSERT(font.isValid());
-    m_font = font;
-
-    m_textureData = textureData();
-
-    QRawFontPrivate *fontD = QRawFontPrivate::get(m_font);
-    m_glyphCount = fontD->fontEngine->glyphCount();
-
-    m_textureData->doubleGlyphResolution = fontHasNarrowOutlines(font) && m_glyphCount < QT_DISTANCEFIELD_HIGHGLYPHCOUNT;
-
-    m_referenceFont = m_font;
-    m_referenceFont.setPixelSize(QT_DISTANCEFIELD_BASEFONTSIZE);
-    Q_ASSERT(m_referenceFont.isValid());
-}
-
-QSGDistanceFieldGlyphCache::~QSGDistanceFieldGlyphCache()
-{
-}
-
-GLuint QSGDistanceFieldGlyphCache::texture()
-{
-    return m_textureData->texture;
-}
-
-QSize QSGDistanceFieldGlyphCache::textureSize() const
-{
-    return m_textureData->size;
-}
-
-QSGDistanceFieldGlyphCache::Metrics QSGDistanceFieldGlyphCache::glyphMetrics(glyph_t glyph)
-{
-    QHash<glyph_t, Metrics>::iterator metric = m_metrics.find(glyph);
-    if (metric == m_metrics.end()) {
-        QPainterPath path = m_font.pathForGlyph(glyph);
-        QRectF br = path.boundingRect();
-
-        Metrics m;
-        m.width = br.width();
-        m.height = br.height();
-        m.baselineX = br.x();
-        m.baselineY = -br.y();
-
-        metric = m_metrics.insert(glyph, m);
-    }
-
-    return metric.value();
-}
-
-QSGDistanceFieldGlyphCache::TexCoord QSGDistanceFieldGlyphCache::glyphTexCoord(glyph_t glyph)
-{
-    return m_textureData->texCoords.value(glyph);
-}
-
-QImage QSGDistanceFieldGlyphCache::renderDistanceFieldGlyph(glyph_t glyph) const
-{
-    QRawFont renderFont = m_font;
-    renderFont.setPixelSize(QT_DISTANCEFIELD_BASEFONTSIZE * QT_DISTANCEFIELD_SCALE);
-
-    QPainterPath path = renderFont.pathForGlyph(glyph);
-    path.translate(-path.boundingRect().topLeft());
-    path.setFillRule(Qt::WindingFill);
-
-    QImage im = makeDistanceField(QT_DISTANCEFIELD_TILESIZE,
-                                  path,
-                                  QT_DISTANCEFIELD_SCALE,
-                                  QT_DISTANCEFIELD_RADIUS / QT_DISTANCEFIELD_SCALE);
-    return im;
-}
-
-qreal QSGDistanceFieldGlyphCache::fontScale() const
-{
-    return qreal(m_font.pixelSize()) / QT_DISTANCEFIELD_BASEFONTSIZE;
-}
-
-int QSGDistanceFieldGlyphCache::distanceFieldRadius() const
-{
-    return QT_DISTANCEFIELD_DEFAULT_RADIUS / QT_DISTANCEFIELD_SCALE;
-}
-
-void QSGDistanceFieldGlyphCache::populate(int count, const glyph_t *glyphs)
-{
-    // Avoid useless and costly glyph re-generation
-    if (cacheIsFull() && !m_textureData->unusedGlyphs.isEmpty()) {
-        for (int i = 0; i < count; ++i) {
-            glyph_t glyphIndex = glyphs[i];
-            if (m_textureData->texCoords.contains(glyphIndex) && m_textureData->unusedGlyphs.contains(glyphIndex))
-                m_textureData->unusedGlyphs.remove(glyphIndex);
-        }
-    }
-
-    for (int i = 0; i < count; ++i) {
-        glyph_t glyphIndex = glyphs[i];
-        if ((int) glyphIndex >= glyphCount()) {
-            qWarning("Warning: distance-field glyph is not available with index %d", glyphIndex);
-            continue;
-        }
-
-        if (++m_textureData->glyphRefCount[glyphIndex] == 1)
-            m_textureData->unusedGlyphs.remove(glyphIndex);
-
-        if (m_textureData->texCoords.contains(glyphIndex)
-                || (cacheIsFull() && m_textureData->unusedGlyphs.isEmpty()))
-            continue;
-
-        QPainterPath path = m_referenceFont.pathForGlyph(glyphIndex);
-        if (path.isEmpty()) {
-            m_textureData->texCoords.insert(glyphIndex, TexCoord());
-            continue;
-        }
-        QRectF br = path.boundingRect();
-
-        TexCoord c;
-        c.xMargin = QT_DISTANCEFIELD_RADIUS / qreal(QT_DISTANCEFIELD_SCALE);
-        c.yMargin = QT_DISTANCEFIELD_RADIUS / qreal(QT_DISTANCEFIELD_SCALE);
-        c.x = m_textureData->currX;
-        c.y = m_textureData->currY;
-        c.width = br.width();
-        c.height = br.height();
-
-        if (!cacheIsFull()) {
-            m_textureData->currX += QT_DISTANCEFIELD_TILESIZE;
-            if (m_textureData->currX >= m_manager->maxTextureSize()) {
-                m_textureData->currX = 0;
-                m_textureData->currY += QT_DISTANCEFIELD_TILESIZE;
-            }
-        } else {
-            // Recycle glyphs
-            if (!m_textureData->unusedGlyphs.isEmpty()) {
-                glyph_t unusedGlyph = *m_textureData->unusedGlyphs.constBegin();
-                TexCoord unusedCoord = glyphTexCoord(unusedGlyph);
-                c.x = unusedCoord.x;
-                c.y = unusedCoord.y;
-                m_textureData->unusedGlyphs.remove(unusedGlyph);
-                m_textureData->texCoords.remove(unusedGlyph);
-            }
-        }
-
-        if (c.y < m_manager->maxTextureSize()) {
-            m_textureData->texCoords.insert(glyphIndex, c);
-            m_textureData->pendingGlyphs.add(glyphIndex);
-        }
-    }
-}
-
-void QSGDistanceFieldGlyphCache::derefGlyphs(int count, const glyph_t *glyphs)
-{
-    for (int i = 0; i < count; ++i)
-        if (--m_textureData->glyphRefCount[glyphs[i]] == 0 && !glyphTexCoord(glyphs[i]).isNull())
-            m_textureData->unusedGlyphs.insert(glyphs[i]);
-}
-
-void QSGDistanceFieldGlyphCache::createTexture(int width, int height)
-{
-    if (ctx->d_func()->workaround_brokenFBOReadBack && m_textureData->image.isNull())
-        m_textureData->image = QImage(width, height, QImage::Format_Indexed8);
-
-    while (glGetError() != GL_NO_ERROR) { }
-
-    glGenTextures(1, &m_textureData->texture);
-    glBindTexture(GL_TEXTURE_2D, m_textureData->texture);
-
-    glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, 0);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
-    m_textureData->size = QSize(width, height);
-
-    GLuint error = glGetError();
-    if (error != GL_NO_ERROR) {
-        glBindTexture(GL_TEXTURE_2D, 0);
-        glDeleteTextures(1, &m_textureData->texture);
-        m_textureData->texture = 0;
-    }
-
-}
-
-void QSGDistanceFieldGlyphCache::resizeTexture(int width, int height)
-{
-    int oldWidth = m_textureData->size.width();
-    int oldHeight = m_textureData->size.height();
-    if (width == oldWidth && height == oldHeight)
-        return;
-
-    GLuint oldTexture = m_textureData->texture;
-    createTexture(width, height);
-
-    if (!oldTexture)
-        return;
-
-    if (ctx->d_func()->workaround_brokenFBOReadBack) {
-        m_textureData->image = m_textureData->image.copy(0, 0, width, height);
-        QImage copy = m_textureData->image.copy(0, 0, oldWidth, oldHeight);
-        glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, oldWidth, oldHeight, GL_ALPHA, GL_UNSIGNED_BYTE, copy.constBits());
-        glDeleteTextures(1, &oldTexture);
-        return;
-    }
-
-    if (!m_textureData->fbo)
-        ctx->functions()->glGenFramebuffers(1, &m_textureData->fbo);
-    ctx->functions()->glBindFramebuffer(GL_FRAMEBUFFER, m_textureData->fbo);
-
-    GLuint tmp_texture;
-    glGenTextures(1, &tmp_texture);
-    glBindTexture(GL_TEXTURE_2D, tmp_texture);
-    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, oldWidth, oldHeight, 0,
-                 GL_RGBA, GL_UNSIGNED_BYTE, NULL);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-    glBindTexture(GL_TEXTURE_2D, 0);
-    ctx->functions()->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
-                                             GL_TEXTURE_2D, tmp_texture, 0);
-
-    ctx->functions()->glActiveTexture(GL_TEXTURE0);
-    glBindTexture(GL_TEXTURE_2D, oldTexture);
-
-    // save current render states
-    GLboolean stencilTestEnabled;
-    GLboolean depthTestEnabled;
-    GLboolean scissorTestEnabled;
-    GLboolean blendEnabled;
-    GLint viewport[4];
-    glGetBooleanv(GL_STENCIL_TEST, &stencilTestEnabled);
-    glGetBooleanv(GL_DEPTH_TEST, &depthTestEnabled);
-    glGetBooleanv(GL_SCISSOR_TEST, &scissorTestEnabled);
-    glGetBooleanv(GL_BLEND, &blendEnabled);
-    glGetIntegerv(GL_VIEWPORT, &viewport[0]);
-
-    glDisable(GL_STENCIL_TEST);
-    glDisable(GL_DEPTH_TEST);
-    glDisable(GL_SCISSOR_TEST);
-    glDisable(GL_BLEND);
-
-    glViewport(0, 0, oldWidth, oldHeight);
-
-    ctx->functions()->glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, m_manager->blitVertexArray());
-    ctx->functions()->glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, m_manager->blitTextureArray());
-
-    m_manager->blitProgram()->bind();
-    m_manager->blitProgram()->enableAttributeArray(int(QT_VERTEX_COORDS_ATTR));
-    m_manager->blitProgram()->enableAttributeArray(int(QT_TEXTURE_COORDS_ATTR));
-    m_manager->blitProgram()->disableAttributeArray(int(QT_OPACITY_ATTR));
-    m_manager->blitProgram()->setUniformValue("imageTexture", GLuint(0));
-
-    glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
-
-    glBindTexture(GL_TEXTURE_2D, m_textureData->texture);
-
-    glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, oldWidth, oldHeight);
-
-    ctx->functions()->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
-                                                GL_RENDERBUFFER, 0);
-    glDeleteTextures(1, &tmp_texture);
-    glDeleteTextures(1, &oldTexture);
-
-    ctx->functions()->glBindFramebuffer(GL_FRAMEBUFFER, 0);
-
-    // restore render states
-    if (stencilTestEnabled)
-        glEnable(GL_STENCIL_TEST);
-    if (depthTestEnabled)
-        glEnable(GL_DEPTH_TEST);
-    if (scissorTestEnabled)
-        glEnable(GL_SCISSOR_TEST);
-    if (blendEnabled)
-        glEnable(GL_BLEND);
-    glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
-}
-
-void QSGDistanceFieldGlyphCache::updateCache()
-{
-    if (m_textureData->pendingGlyphs.isEmpty())
-        return;
-
-    int requiredWidth = m_manager->maxTextureSize();
-    int rows = 128 / (requiredWidth / QT_DISTANCEFIELD_TILESIZE); // Enough rows to fill the latin1 set by default..
-    int requiredHeight = qMin(m_manager->maxTextureSize(), qMax(m_textureData->currY + QT_DISTANCEFIELD_TILESIZE, QT_DISTANCEFIELD_TILESIZE * rows));
-
-    resizeTexture((requiredWidth), (requiredHeight));
-    glBindTexture(GL_TEXTURE_2D, m_textureData->texture);
-
-    // ### Remove before final release
-    static bool cacheDistanceFields = QGuiApplication::arguments().contains(QLatin1String("--cache-distance-fields"));
-
-// #define QSGDISTANCEFIELDS_TIME_CREATION
-#ifdef QSGDISTANCEFIELDS_TIME_CREATION
-    QTime time;
-    time.start();
-#endif
-
-    QString tmpPath = QString::fromLatin1("%1/.qt/").arg(QDir::tempPath());
-    QString keyBase = QString::fromLatin1("%1%2%3_%4_%5_%6.fontblob")
-            .arg(tmpPath)
-            .arg(m_font.familyName())
-            .arg(m_font.styleName())
-            .arg(m_font.weight())
-            .arg(m_font.style());
-
-    if (cacheDistanceFields && !QFile::exists(tmpPath))
-        QDir(tmpPath).mkpath(tmpPath);
-
-    for (int i = 0; i < m_textureData->pendingGlyphs.size(); ++i) {
-        glyph_t glyphIndex = m_textureData->pendingGlyphs.at(i);
-        TexCoord c = m_textureData->texCoords.value(glyphIndex);
-
-        if (cacheDistanceFields) {
-            QString key = keyBase.arg(glyphIndex);
-            QFile file(key);
-            if (file.open(QFile::ReadOnly)) {
-                int fileSize = file.size();
-                int dim = sqrt(float(fileSize));
-                QByteArray blob = file.readAll();
-                glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, dim, dim, GL_ALPHA, GL_UNSIGNED_BYTE, blob.constData());
-                continue;
-            }
-        }
-
-        QImage glyph = renderDistanceFieldGlyph(glyphIndex);
-
-        if (ctx->d_func()->workaround_brokenFBOReadBack) {
-            uchar *inBits = glyph.scanLine(0);
-            uchar *outBits = m_textureData->image.scanLine(int(c.y)) + int(c.x);
-            for (int y = 0; y < glyph.height(); ++y) {
-                qMemCopy(outBits, inBits, glyph.width());
-                inBits += glyph.bytesPerLine();
-                outBits += m_textureData->image.bytesPerLine();
-            }
-        }
-
-        glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, glyph.width(), glyph.height(), GL_ALPHA, GL_UNSIGNED_BYTE, glyph.constBits());
-
-        if (cacheDistanceFields) {
-            QString key = keyBase.arg(glyphIndex);
-            QFile file(key);
-            file.open(QFile::WriteOnly);
-            file.write((const char *) glyph.constBits(), glyph.width() * glyph.height());
-        }
-    }
-
-#ifdef QSGDISTANCEFIELDS_TIME_CREATION
-        static int totalTime;
-    totalTime += time.elapsed();
-    printf("time: %d\n", totalTime);
-#endif
-
-    m_textureData->pendingGlyphs.reset();
-}
-
-bool QSGDistanceFieldGlyphCache::useWorkaroundBrokenFBOReadback() const
-{
-    return ctx->d_func()->workaround_brokenFBOReadBack;
-}
-
-int QSGDistanceFieldGlyphCache::glyphCount() const
-{
-    return m_glyphCount;
-}
-
-QT_END_NAMESPACE
diff --git a/src/declarative/scenegraph/util/qsgdistancefieldutil_p.h b/src/declarative/scenegraph/util/qsgdistancefieldutil_p.h
new file mode 100644
index 0000000000000000000000000000000000000000..93dffab76eb78e0de08bbd048564cf8e6587b9dc
--- /dev/null
+++ b/src/declarative/scenegraph/util/qsgdistancefieldutil_p.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSGDISTANCEFIELDUTIL_H
+#define QSGDISTANCEFIELDUTIL_H
+
+#include <qrawfont.h>
+#include <private/qfontengine_p.h>
+#include <private/qsgadaptationlayer_p.h>
+
+QT_BEGIN_NAMESPACE
+
+#define QT_DISTANCEFIELD_DEFAULT_BASEFONTSIZE 54
+#define QT_DISTANCEFIELD_DEFAULT_TILESIZE 64
+#define QT_DISTANCEFIELD_DEFAULT_SCALE 16
+#define QT_DISTANCEFIELD_DEFAULT_RADIUS 80
+#define QT_DISTANCEFIELD_HIGHGLYPHCOUNT 2000
+
+#define QT_DISTANCEFIELD_BASEFONTSIZE(NarrowOutlineFont) \
+    (NarrowOutlineFont ? QT_DISTANCEFIELD_DEFAULT_BASEFONTSIZE * 2 : \
+                         QT_DISTANCEFIELD_DEFAULT_BASEFONTSIZE)
+#define QT_DISTANCEFIELD_TILESIZE(NarrowOutlineFont) \
+    (NarrowOutlineFont ? QT_DISTANCEFIELD_DEFAULT_TILESIZE * 2 : \
+                         QT_DISTANCEFIELD_DEFAULT_TILESIZE)
+#define QT_DISTANCEFIELD_SCALE(NarrowOutlineFont) \
+    (NarrowOutlineFont ? QT_DISTANCEFIELD_DEFAULT_SCALE / 2 : \
+                         QT_DISTANCEFIELD_DEFAULT_SCALE)
+#define QT_DISTANCEFIELD_RADIUS(NarrowOutlineFont) \
+    (NarrowOutlineFont ? QT_DISTANCEFIELD_DEFAULT_RADIUS / 2 : \
+                         QT_DISTANCEFIELD_DEFAULT_RADIUS)
+
+
+typedef float (*ThresholdFunc)(float glyphScale);
+typedef float (*AntialiasingSpreadFunc)(float glyphScale);
+
+bool qt_fontHasNarrowOutlines(const QRawFont &f);
+QImage qt_renderDistanceFieldGlyph(const QRawFont &font, glyph_t glyph, bool doubleResolution);
+
+
+class QOpenGLShaderProgram;
+class QSGDistanceFieldGlyphCache;
+class QSGContext;
+
+class Q_DECLARATIVE_EXPORT QSGDistanceFieldGlyphCacheManager
+{
+public:
+    QSGDistanceFieldGlyphCacheManager(QSGContext *c);
+    ~QSGDistanceFieldGlyphCacheManager();
+
+    QSGDistanceFieldGlyphCache *cache(const QRawFont &font);
+
+    QSGGlyphNode::AntialiasingMode defaultAntialiasingMode() const { return m_defaultAntialiasingMode; }
+    void setDefaultAntialiasingMode(QSGGlyphNode::AntialiasingMode mode) { m_defaultAntialiasingMode = mode; }
+
+    ThresholdFunc thresholdFunc() const { return m_threshold_func; }
+    void setThresholdFunc(ThresholdFunc func) { m_threshold_func = func; }
+
+    AntialiasingSpreadFunc antialiasingSpreadFunc() const { return m_antialiasingSpread_func; }
+    void setAntialiasingSpreadFunc(AntialiasingSpreadFunc func) { m_antialiasingSpread_func = func; }
+
+private:
+    QHash<QFontEngine *, QSGDistanceFieldGlyphCache *> m_caches;
+
+    QSGContext *sgCtx;
+
+    QSGGlyphNode::AntialiasingMode m_defaultAntialiasingMode;
+    ThresholdFunc m_threshold_func;
+    AntialiasingSpreadFunc m_antialiasingSpread_func;
+};
+
+QT_END_NAMESPACE
+
+#endif // QSGDISTANCEFIELDUTIL_H
diff --git a/tests/auto/declarative/qquicktext/tst_qquicktext.cpp b/tests/auto/declarative/qquicktext/tst_qquicktext.cpp
index 8ac3a078bc9ff34a45e5d7fba044d9c442209246..a8852fbc9f9a223564e2d1ed63a4b36532ae3a81 100644
--- a/tests/auto/declarative/qquicktext/tst_qquicktext.cpp
+++ b/tests/auto/declarative/qquicktext/tst_qquicktext.cpp
@@ -45,7 +45,6 @@
 #include <private/qquicktext_p.h>
 #include <private/qquicktext_p_p.h>
 #include <private/qdeclarativevaluetype_p.h>
-#include <private/qsgdistancefieldglyphcache_p.h>
 #include <QFontMetrics>
 #include <QGraphicsSceneMouseEvent>
 #include <qmath.h>
diff --git a/tests/auto/declarative/qquicktextedit/tst_qquicktextedit.cpp b/tests/auto/declarative/qquicktextedit/tst_qquicktextedit.cpp
index 693619f638b80ce429304f6dad087b133da84af6..116d6307febc067438f8b0956950bb69b02a2fda 100644
--- a/tests/auto/declarative/qquicktextedit/tst_qquicktextedit.cpp
+++ b/tests/auto/declarative/qquicktextedit/tst_qquicktextedit.cpp
@@ -51,7 +51,6 @@
 #include <QtGui/qguiapplication.h>
 #include <private/qquicktextedit_p.h>
 #include <private/qquicktextedit_p_p.h>
-#include <private/qsgdistancefieldglyphcache_p.h>
 #include <QFontMetrics>
 #include <QQuickView>
 #include <QDir>
diff --git a/tests/auto/declarative/qquicktextinput/tst_qquicktextinput.cpp b/tests/auto/declarative/qquicktextinput/tst_qquicktextinput.cpp
index bf29f88ff1d2a4ad2da9c03ca056ad3c243cd314..210099c2a46eb0df3304cdd0a0d9bcf1f65e7836 100644
--- a/tests/auto/declarative/qquicktextinput/tst_qquicktextinput.cpp
+++ b/tests/auto/declarative/qquicktextinput/tst_qquicktextinput.cpp
@@ -52,7 +52,6 @@
 #include <QDir>
 #include <QStyle>
 #include <QInputContext>
-#include <private/qsgdistancefieldglyphcache_p.h>
 #include <QtOpenGL/QGLShaderProgram>
 #include <math.h>