diff --git a/3rdparty b/3rdparty
index 63f1510d708ce6e90354c63655fa21bd4906e52e..9427c1a0222ebd67efef1a2c7990a0fa5c9aac84 160000
--- a/3rdparty
+++ b/3rdparty
@@ -1 +1 @@
-Subproject commit 63f1510d708ce6e90354c63655fa21bd4906e52e
+Subproject commit 9427c1a0222ebd67efef1a2c7990a0fa5c9aac84
diff --git a/examples/quick/quicknanobrowser/main.cpp b/examples/quick/quicknanobrowser/main.cpp
index 982c1eb7a481a1fe56285cf91c757577baece167..6c2f91de6dd9397800213f7e725429cc692bbc96 100644
--- a/examples/quick/quicknanobrowser/main.cpp
+++ b/examples/quick/quicknanobrowser/main.cpp
@@ -47,11 +47,19 @@ typedef QApplication Application;
 #include <QtGui/QGuiApplication>
 typedef QGuiApplication Application;
 #endif
+#include <QtQuick/private/qsgcontext_p.h>
 
 int main(int argc, char **argv)
 {
     Application app(argc, argv);
 
+    // This is currently needed by all QtWebEngine application using the HW accelerated QQuickWebView.
+    // It enables sharing between the QOpenGLContext of all QQuickWindows of the application.
+    // We have to do so until we expose a public API for it, or chose enable it by default in Qt 5.3.0.
+    QOpenGLContext shareContext;
+    shareContext.create();
+    QSGContext::setSharedOpenGLContext(&shareContext);
+
     ApplicationEngine appEngine;
 
     return app.exec();
diff --git a/examples/quick/quicknanobrowser/quicknanobrowser.pro b/examples/quick/quicknanobrowser/quicknanobrowser.pro
index c32540a71e03761f00ad6e6eeb57c53cc25454f2..2132b031aebc5a6cf329917828389093e019b7cc 100644
--- a/examples/quick/quicknanobrowser/quicknanobrowser.pro
+++ b/examples/quick/quicknanobrowser/quicknanobrowser.pro
@@ -12,6 +12,8 @@ RESOURCES += resources.qrc
 RESOURCES += ../../common/common_resources.qrc
 
 QT += qml quick
+QT_PRIVATE += quick-private gui-private core-private
+
 qtHaveModule(widgets) {
     QT += widgets # QApplication is required to get native styling with QtQuickControls
 }
diff --git a/lib/chromium_gpu_helper.cpp b/lib/chromium_gpu_helper.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3d393c25dd46d35632b3b74054aa101e12a8392d
--- /dev/null
+++ b/lib/chromium_gpu_helper.cpp
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights.  These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "chromium_gpu_helper.h"
+
+#include "content/common/gpu/gpu_channel_manager.h"
+#include "content/common/gpu/sync_point_manager.h"
+#include "content/gpu/gpu_child_thread.h"
+#include "gpu/command_buffer/service/mailbox_manager.h"
+#include "gpu/command_buffer/service/texture_manager.h"
+
+static void addSyncPointCallbackDelegate(content::SyncPointManager *syncPointManager, uint32 sync_point, const base::Closure& callback)
+{
+    syncPointManager->AddSyncPointCallback(sync_point, callback);
+}
+
+base::MessageLoop *gpu_message_loop()
+{
+    return content::GpuChildThread::instance()->message_loop();
+}
+
+content::SyncPointManager *sync_point_manager()
+{
+    content::GpuChannelManager *gpuChannelManager = content::GpuChildThread::instance()->ChannelManager();
+    return gpuChannelManager->sync_point_manager();
+}
+
+void AddSyncPointCallbackOnGpuThread(base::MessageLoop *gpuMessageLoop, content::SyncPointManager *syncPointManager, uint32 sync_point, const base::Closure& callback)
+{
+    // We need to set our callback from the GPU thread, where the SyncPointManager lives.
+    gpuMessageLoop->PostTask(FROM_HERE, base::Bind(&addSyncPointCallbackDelegate, make_scoped_refptr(syncPointManager), sync_point, callback));
+}
+
+gpu::gles2::MailboxManager *mailbox_manager()
+{
+    content::GpuChannelManager *gpuChannelManager = content::GpuChildThread::instance()->ChannelManager();
+    return gpuChannelManager->mailbox_manager();
+}
+
+gpu::gles2::Texture* ConsumeTexture(gpu::gles2::MailboxManager *mailboxManager, unsigned target, const gpu::gles2::MailboxName& name)
+{
+    return mailboxManager->ConsumeTexture(target, name);
+}
+
+unsigned int service_id(gpu::gles2::Texture *tex)
+{
+    return tex->service_id();
+}
diff --git a/lib/chromium_gpu_helper.h b/lib/chromium_gpu_helper.h
new file mode 100644
index 0000000000000000000000000000000000000000..e0ac8e2a3c04db7c001f80fa1f43c1f577ae464a
--- /dev/null
+++ b/lib/chromium_gpu_helper.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights.  These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CHROMIUM_GPU_HELPER_H
+#define CHROMIUM_GPU_HELPER_H
+
+#include "base/callback.h"
+
+namespace base {
+class MessageLoop;
+}
+
+namespace content {
+class SyncPointManager;
+}
+
+namespace gpu {
+namespace gles2 {
+class MailboxManager;
+class MailboxName;
+class Texture;
+}
+}
+
+// These functions wrap code that needs to include headers that are
+// incompatible with Qt GL headers.
+// From the outside, types from incompatible headers referenced in these
+// functions should only be forward-declared and considered as opaque types.
+
+base::MessageLoop *gpu_message_loop();
+content::SyncPointManager *sync_point_manager();
+gpu::gles2::MailboxManager *mailbox_manager();
+
+void AddSyncPointCallbackOnGpuThread(base::MessageLoop *gpuMessageLoop, content::SyncPointManager *syncPointManager, uint32 sync_point, const base::Closure& callback);
+gpu::gles2::Texture* ConsumeTexture(gpu::gles2::MailboxManager *mailboxManager, unsigned target, const gpu::gles2::MailboxName& name);
+unsigned int service_id(gpu::gles2::Texture *tex);
+
+#endif // CHROMIUM_GPU_HELPER_H
diff --git a/lib/content_browser_client_qt.cpp b/lib/content_browser_client_qt.cpp
index 4ff15d3b1906cbf1e96f040e7741d6b1b3868c0e..97d5c8e4e480aa8f7bb1ff0fd87c7742be06d6be 100644
--- a/lib/content_browser_client_qt.cpp
+++ b/lib/content_browser_client_qt.cpp
@@ -50,12 +50,17 @@
 #include "grit/net_resources.h"
 #include "net/base/net_module.h"
 #include "ui/base/resource/resource_bundle.h"
+#include "ui/gl/gl_context.h"
+#include "ui/gl/gl_implementation.h"
+#include "ui/gl/gl_share_group.h"
 
 #include "browser_context_qt.h"
 #include "dev_tools_http_handler_delegate_qt.h"
 #include "web_contents_view_qt.h"
 
-#include <QCoreApplication>
+#include <QGuiApplication>
+#include <QtQuick/private/qsgcontext_p.h>
+#include <qpa/qplatformnativeinterface.h>
 
 namespace {
 
@@ -202,6 +207,57 @@ private:
     DISALLOW_COPY_AND_ASSIGN(BrowserMainPartsQt);
 };
 
+class QtShareGLContext : public gfx::GLContext {
+public:
+    QtShareGLContext(QOpenGLContext *qtContext)
+        : gfx::GLContext(0)
+        , m_handle(0)
+    {
+        QString platform = qApp->platformName();
+        QPlatformNativeInterface *pni = QGuiApplication::platformNativeInterface();
+        if (platform == QStringLiteral("xcb")) {
+            if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
+                m_handle = pni->nativeResourceForContext(QByteArrayLiteral("eglcontext"), qtContext);
+            else
+                m_handle = pni->nativeResourceForContext(QByteArrayLiteral("glxcontext"), qtContext);
+        } else if (platform == QStringLiteral("Cocoa"))
+            m_handle = pni->nativeResourceForContext(QByteArrayLiteral("cglcontextobj"), qtContext);
+        else
+            // Add missing platforms once they work.
+            Q_UNREACHABLE();
+    }
+
+    virtual void* GetHandle() { return m_handle; }
+
+    // We don't care about the rest, this context shouldn't be used except for its handle.
+    virtual bool Initialize(gfx::GLSurface *, gfx::GpuPreference) { Q_UNREACHABLE(); return false; }
+    virtual void Destroy() { Q_UNREACHABLE(); }
+    virtual bool MakeCurrent(gfx::GLSurface *) { Q_UNREACHABLE(); return false; }
+    virtual void ReleaseCurrent(gfx::GLSurface *) { Q_UNREACHABLE(); }
+    virtual bool IsCurrent(gfx::GLSurface *) { Q_UNREACHABLE(); return false; }
+    virtual void SetSwapInterval(int) { Q_UNREACHABLE(); }
+
+private:
+    void *m_handle;
+};
+
+class ShareGroupQtQuick : public gfx::GLShareGroup {
+public:
+    virtual gfx::GLContext* GetContext() Q_DECL_OVERRIDE { return m_shareContextQtQuick.get(); }
+    virtual void AboutToAddFirstContext() Q_DECL_OVERRIDE;
+
+private:
+    scoped_refptr<QtShareGLContext> m_shareContextQtQuick;
+};
+
+void ShareGroupQtQuick::AboutToAddFirstContext()
+{
+    // This currently has to be setup by ::main in all applications using QQuickWebEngineView with delegated rendering.
+    QOpenGLContext *shareContext = QSGContext::sharedOpenGLContext();
+    Q_ASSERT(shareContext);
+    m_shareContextQtQuick = make_scoped_refptr(new QtShareGLContext(shareContext));
+}
+
 content::WebContentsViewPort* ContentBrowserClientQt::OverrideCreateWebContentsView(content::WebContents* web_contents,
                                                                                     content::RenderViewHostDelegateView** render_view_host_delegate_view)
 {
@@ -239,6 +295,12 @@ void ContentBrowserClientQt::RenderProcessHostCreated(content::RenderProcessHost
     content::ChildProcessSecurityPolicy::GetInstance()->GrantScheme(host->GetID(), chrome::kFileScheme);
 }
 
+gfx::GLShareGroup *ContentBrowserClientQt::GetInProcessGpuShareGroup()
+{
+    if (!m_shareGroupQtQuick)
+        m_shareGroupQtQuick = new ShareGroupQtQuick;
+    return m_shareGroupQtQuick.get();
+}
 
 BrowserContextQt* ContentBrowserClientQt::browser_context() {
     Q_ASSERT(m_browserMainParts);
diff --git a/lib/content_browser_client_qt.h b/lib/content_browser_client_qt.h
index f8c42e5691de90ae7a5202fd5b9d8081d819f83d..b97eaa5e1ad824b2a802892810ae661844c3a36a 100644
--- a/lib/content_browser_client_qt.h
+++ b/lib/content_browser_client_qt.h
@@ -44,6 +44,7 @@
 
 #include "base/memory/scoped_ptr.h"
 #include "content/public/browser/content_browser_client.h"
+
 #include <QtCore/qcompilerdetection.h> // Needed for Q_DECL_OVERRIDE
 
 namespace net {
@@ -60,9 +61,14 @@ class WebContents;
 struct MainFunctionParams;
 }
 
+namespace gfx {
+class GLShareGroup;
+}
+
 class BrowserContextQt;
 class BrowserMainPartsQt;
 class DevToolsHttpHandlerDelegateQt;
+class ShareGroupQtQuick;
 
 class ContentBrowserClientQt : public content::ContentBrowserClient {
 
@@ -73,6 +79,7 @@ public:
     virtual content::WebContentsViewPort* OverrideCreateWebContentsView(content::WebContents* , content::RenderViewHostDelegateView**) Q_DECL_OVERRIDE;
     virtual content::BrowserMainParts* CreateBrowserMainParts(const content::MainFunctionParams&) Q_DECL_OVERRIDE;
     virtual void RenderProcessHostCreated(content::RenderProcessHost* host) Q_DECL_OVERRIDE;
+    virtual gfx::GLShareGroup* GetInProcessGpuShareGroup() Q_DECL_OVERRIDE;
 
     BrowserContextQt* browser_context();
 
@@ -83,7 +90,7 @@ public:
 private:
     BrowserMainPartsQt* m_browserMainParts;
     scoped_ptr<DevToolsHttpHandlerDelegateQt> m_devtools;
-
+    scoped_refptr<ShareGroupQtQuick> m_shareGroupQtQuick;
 };
 
 #endif // CONTENT_BROWSER_CLIENT_QT_H
diff --git a/lib/delegated_frame_node.cpp b/lib/delegated_frame_node.cpp
index dea9605beb90d0bc80985147cffbcfe739807c81..0e3f34fffe03a276674c363a71f3c86d1b2b961a 100644
--- a/lib/delegated_frame_node.cpp
+++ b/lib/delegated_frame_node.cpp
@@ -52,8 +52,11 @@
 #define __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES 0
 #endif
 
+#include "chromium_gpu_helper.h"
 #include "type_conversion.h"
 
+#include "base/message_loop/message_loop.h"
+#include "base/bind.h"
 #include "cc/output/delegated_frame_data.h"
 #include "cc/quads/draw_quad.h"
 #include "cc/quads/render_pass_draw_quad.h"
@@ -66,6 +69,7 @@
 #include <QtQuick/private/qquickwindow_p.h>
 #include <QtQuick/private/qsgcontext_p.h>
 #include <QtQuick/private/qsgrenderer_p.h>
+#include <QtQuick/private/qsgtexture_p.h>
 
 class RenderPassTexture : public QSGTexture
 {
@@ -100,14 +104,41 @@ private:
     QSGRenderContext *m_context;
 };
 
-class RawTextureNode : public QSGSimpleTextureNode {
+class MailboxTexture : public QSGTexture {
 public:
-    RawTextureNode(GLuint textureId, const QSize &textureSize, bool hasAlpha, QQuickWindow *window);
+    MailboxTexture(const cc::TransferableResource *resource, bool hasAlpha);
+    virtual int textureId() const { return m_textureId; }
+    void setTextureSize(const QSize& size) { m_textureSize = size; }
+    virtual QSize textureSize() const { return m_textureSize; }
+    virtual bool hasAlphaChannel() const { return m_hasAlpha; }
+    virtual bool hasMipmaps() const { return false; }
+    virtual void bind();
+
+    bool needsToFetch() const { return m_resource; }
+    const cc::TransferableResource *resource() const { return m_resource; }
+    void fetchTexture(gpu::gles2::MailboxManager *mailboxManager);
 
 private:
-    QScopedPointer<QSGTexture> m_texture;
+    // This is just a pointer to the cc::DelegatedFrameData. It has to be held until DelegatedFrameNode::preprocess is done.
+    const cc::TransferableResource *m_resource;
+    int m_textureId;
+    QSize m_textureSize;
+    bool m_hasAlpha;
 };
 
+static const cc::TransferableResource *findResource(const cc::TransferableResourceArray &array, unsigned id)
+{
+    // A 0 ID means that there is no resource.
+    if (!id)
+        return 0;
+
+    for (unsigned i = 0; i < array.size(); ++i) {
+        const cc::TransferableResource &res = array.at(i);
+        if (res.id == id)
+            return &res;
+    }
+    return 0;
+}
 
 static inline QSharedPointer<RenderPassTexture> findRenderPassTexture(const cc::RenderPass::Id &id, const QList<QSharedPointer<RenderPassTexture> > &list)
 {
@@ -182,7 +213,6 @@ static QSGNode *buildLayerChain(QSGNode *chainParent, const cc::SharedQuadState
     return layerChain;
 }
 
-
 RenderPassTexture::RenderPassTexture(const cc::RenderPass::Id &id, QSGRenderContext *context)
     : QSGTexture()
     , m_id(id)
@@ -235,55 +265,79 @@ void RenderPassTexture::grab()
     m_context->renderNextFrame(m_renderer.data(), m_fbo->handle());
 }
 
-RawTextureNode::RawTextureNode(GLuint textureId, const QSize &textureSize, bool hasAlpha, QQuickWindow *window)
-    : m_texture(window->createTextureFromId(textureId, textureSize, QQuickWindow::CreateTextureOption(hasAlpha ? QQuickWindow::TextureHasAlphaChannel : 0)))
+MailboxTexture::MailboxTexture(const cc::TransferableResource *resource, bool hasAlpha)
+    : m_resource(resource)
+    , m_textureId(0)
+    , m_textureSize(toQt(resource->size))
+    , m_hasAlpha(hasAlpha)
 {
-    setTexture(m_texture.data());
+}
+
+void MailboxTexture::bind()
+{
+    glBindTexture(GL_TEXTURE_2D, m_textureId);
+}
+
+void MailboxTexture::fetchTexture(gpu::gles2::MailboxManager *mailboxManager)
+{
+    Q_ASSERT(m_resource);
+    gpu::gles2::Texture *tex = ConsumeTexture(mailboxManager, GL_TEXTURE_2D, *reinterpret_cast<const gpu::gles2::MailboxName*>(m_resource->mailbox.name));
+
+    // The texture might already have been deleted.
+    // FIXME: We might be able to avoid this check with better synchronization.
+    if (tex)
+        m_textureId = service_id(tex);
+
+    // We do not need to fetch this texture again.
+    m_resource = 0;
 }
 
 DelegatedFrameNode::DelegatedFrameNode(QQuickWindow *window)
     : m_window(window)
-    , m_testTexturesSize(sizeof(m_testTextures) / sizeof(GLuint))
+    , m_numPendingSyncPoints(0)
 {
     setFlag(UsePreprocess);
-
-    // Generate plain color textures to be used until we can use the real textures from the ResourceProvider.
-    glGenTextures(m_testTexturesSize, m_testTextures);
-    for (unsigned i = 0; i < m_testTexturesSize; ++i) {
-        QImage image(1, 1, QImage::Format_ARGB32_Premultiplied);
-        image.fill(static_cast<Qt::GlobalColor>(i + Qt::red));
-
-        // Swizzle
-        const int width = image.width();
-        const int height = image.height();
-        for (int j = 0; j < height; ++j) {
-            uint *p = (uint *) image.scanLine(j);
-            for (int x = 0; x < width; ++x)
-                p[x] = ((p[x] << 16) & 0xff0000) | ((p[x] >> 16) & 0xff) | (p[x] & 0xff00ff00);
-        }
-
-        glBindTexture(GL_TEXTURE_2D, m_testTextures[i]);
-        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width(), image.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, image.constBits() );
-    }
 }
 
 DelegatedFrameNode::~DelegatedFrameNode()
 {
-    glDeleteTextures(m_testTexturesSize, m_testTextures);
 }
 
 void DelegatedFrameNode::preprocess()
 {
-    // Render any intermediate RenderPass in order.
-    Q_FOREACH (const QSharedPointer<RenderPassTexture> &texture, m_renderPassTextures)
-        texture->grab();
+    // With the threaded render loop the GUI thread has been unlocked at this point.
+    // We can now wait for the Chromium GPU thread to produce textures that will be
+    // rendered on our quads and fetch the IDs from the mailboxes we were given.
+    QList<MailboxTexture *> mailboxesToFetch;
+    Q_FOREACH (const QSharedPointer<MailboxTexture> &mailboxTexture, m_mailboxTextures.values())
+        if (mailboxTexture->needsToFetch())
+            mailboxesToFetch.append(mailboxTexture.data());
+
+    if (!mailboxesToFetch.isEmpty()) {
+        QMutexLocker lock(&m_mutex);
+        base::MessageLoop *gpuMessageLoop = gpu_message_loop();
+        content::SyncPointManager *syncPointManager = sync_point_manager();
+
+        Q_FOREACH (MailboxTexture *mailboxTexture, mailboxesToFetch) {
+            m_numPendingSyncPoints++;
+            AddSyncPointCallbackOnGpuThread(gpuMessageLoop, syncPointManager, mailboxTexture->resource()->sync_point, base::Bind(&DelegatedFrameNode::syncPointRetired, this, &mailboxesToFetch));
+        }
+
+        m_mailboxesFetchedWaitCond.wait(&m_mutex);
+    }
+
+    // Then render any intermediate RenderPass in order.
+    Q_FOREACH (const QSharedPointer<RenderPassTexture> &renderPass, m_renderPassTextures)
+        renderPass->grab();
 }
 
 void DelegatedFrameNode::commit(cc::DelegatedFrameData *frameData)
 {
-    // Keep the old list around to find the ones we can re-use.
+    // Keep the old texture lists around to find the ones we can re-use.
     QList<QSharedPointer<RenderPassTexture> > oldRenderPassTextures;
     m_renderPassTextures.swap(oldRenderPassTextures);
+    QMap<int, QSharedPointer<MailboxTexture> > oldMailboxTextures;
+    m_mailboxTextures.swap(oldMailboxTextures);
 
     // The RenderPasses list is actually a tree where a parent RenderPass is connected
     // to its dependencies through a RenderPass::Id reference in one or more RenderPassQuads.
@@ -330,37 +384,97 @@ void DelegatedFrameNode::commit(cc::DelegatedFrameData *frameData)
                 currentLayerChain = buildLayerChain(renderPassChain, currentLayerState);
             }
 
-            QSGSimpleTextureNode *textureNode = 0;
             switch (quad->material) {
             case cc::DrawQuad::RENDER_PASS: {
                 const cc::RenderPassDrawQuad *renderPassQuad = cc::RenderPassDrawQuad::MaterialCast(quad);
                 QSGTexture *texture = findRenderPassTexture(renderPassQuad->render_pass_id, m_renderPassTextures).data();
                 if (texture) {
-                    textureNode = new QSGSimpleTextureNode;
+                    QSGSimpleTextureNode *textureNode = new QSGSimpleTextureNode;
+                    textureNode->setRect(toQt(quad->rect));
                     textureNode->setTexture(texture);
+                    currentLayerChain->appendChildNode(textureNode);
                 } else {
                     qWarning("Unknown RenderPass layer: Id %d", renderPassQuad->render_pass_id.layer_id);
-                    textureNode = new RawTextureNode(0, QSize(1, 1), false, m_window);
+                    continue;
                 }
                 break;
             } case cc::DrawQuad::TEXTURE_CONTENT: {
-                uint32 resourceId = cc::TextureDrawQuad::MaterialCast(quad)->resource_id;
-                textureNode = new RawTextureNode(m_testTextures[resourceId % m_testTexturesSize], QSize(1, 1), false, m_window);
+                const cc::TextureDrawQuad *tquad = cc::TextureDrawQuad::MaterialCast(quad);
+                const cc::TransferableResource *res = findResource(frameData->resource_list, tquad->resource_id);
+
+                // See if we already have a texture for this resource ID. The ID changes when the contents is updated,
+                // even if the GL texture ID is the same as a previous resource.
+                // Reusing a texture only saves us the sync point waiting and mailbox fetching.
+                QSharedPointer<MailboxTexture> &texture = m_mailboxTextures[res->id] = oldMailboxTextures.value(res->id);
+                if (!texture) {
+                    texture = QSharedPointer<MailboxTexture>(new MailboxTexture(res, quad->ShouldDrawWithBlending()));
+                    // TransferableResource::size isn't always set properly for TextureDrawQuads, use the size of its DrawQuad::rect instead.
+                    texture->setTextureSize(toQt(quad->rect.size()));
+                }
+
+                QSGSimpleTextureNode *textureNode = new QSGSimpleTextureNode;
+                textureNode->setTextureCoordinatesTransform(tquad->flipped ? QSGSimpleTextureNode::MirrorVertically : QSGSimpleTextureNode::NoTransform);
+                textureNode->setRect(toQt(quad->rect));
+                textureNode->setFiltering(res->filter == GL_LINEAR ? QSGTexture::Linear : QSGTexture::Nearest);
+                textureNode->setTexture(texture.data());
+                currentLayerChain->appendChildNode(textureNode);
                 break;
             } case cc::DrawQuad::TILED_CONTENT: {
-                uint32 resourceId = cc::TileDrawQuad::MaterialCast(quad)->resource_id;
-                textureNode = new RawTextureNode(m_testTextures[resourceId % m_testTexturesSize], QSize(1, 1), false, m_window);
+                const cc::TileDrawQuad *tquad = cc::TileDrawQuad::MaterialCast(quad);
+                const cc::TransferableResource *res = findResource(frameData->resource_list, tquad->resource_id);
+
+                QSharedPointer<MailboxTexture> &texture = m_mailboxTextures[res->id] = oldMailboxTextures.value(res->id);
+                if (!texture)
+                    texture = QSharedPointer<MailboxTexture>(new MailboxTexture(res, quad->ShouldDrawWithBlending()));
+
+                QSGSimpleTextureNode *textureNode = new QSGSimpleTextureNode;
+                textureNode->setRect(toQt(quad->rect));
+                textureNode->setFiltering(res->filter == GL_LINEAR ? QSGTexture::Linear : QSGTexture::Nearest);
+                textureNode->setTexture(texture.data());
+
+                // FIXME: Find out if we can implement a QSGSimpleTextureNode::setSourceRect instead of this hack.
+                // This has to be done at the end since many QSGSimpleTextureNode methods would overwrite this.
+                QSGGeometry::updateTexturedRectGeometry(textureNode->geometry(), textureNode->rect(), textureNode->texture()->convertToNormalizedSourceRect(toQt(tquad->tex_coord_rect)));
+                currentLayerChain->appendChildNode(textureNode);
+
                 break;
             } default:
                 qWarning("Unimplemented quad material: %d", quad->material);
-                textureNode = new RawTextureNode(0, QSize(1, 1), false, m_window);
+                continue;
             }
-
-            textureNode->setRect(toQt(quad->rect));
-            textureNode->setFiltering(QSGTexture::Linear);
-            currentLayerChain->appendChildNode(textureNode);
         }
     }
 }
 
+void DelegatedFrameNode::fetchTexturesAndUnlockQt(DelegatedFrameNode *frameNode, QList<MailboxTexture *> *mailboxesToFetch)
+{
+    // Fetch texture IDs from the mailboxes while we're on the GPU thread, where the MailboxManager lives.
+    gpu::gles2::MailboxManager *mailboxManager = mailbox_manager();
+    Q_FOREACH (MailboxTexture *mailboxTexture, *mailboxesToFetch)
+        mailboxTexture->fetchTexture(mailboxManager);
+
+    // glFlush before yielding to the SG thread, whose context might already start using
+    // some shared resources provided by the unflushed context here, on the Chromium GPU thread.
+    glFlush();
+
+    // Chromium provided everything we were waiting for, let Qt start rendering.
+    QMutexLocker lock(&frameNode->m_mutex);
+    frameNode->m_mailboxesFetchedWaitCond.wakeOne();
+}
+
+void DelegatedFrameNode::syncPointRetired(DelegatedFrameNode *frameNode, QList<MailboxTexture *> *mailboxesToFetch)
+{
+    // The way that sync points are normally used by the GpuCommandBufferStub is that it asks
+    // the GpuScheduler to resume the work of the associated GL command stream / context once
+    // the sync point has been retired by the dependency's context. In other words, a produced
+    // texture means that the mailbox can be consumed, but the texture itself isn't expected
+    // to be ready until to control is given back to the GpuScheduler through the event loop.
+    // Do the same for our implementation by posting a message to the event loop once the last
+    // of our syncpoints has been retired (the syncpoint callback is called synchronously) and
+    // only at this point we wake the Qt rendering thread.
+    QMutexLocker lock(&frameNode->m_mutex);
+    if (!--frameNode->m_numPendingSyncPoints)
+        base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(&DelegatedFrameNode::fetchTexturesAndUnlockQt, frameNode, mailboxesToFetch));
+}
+
 #endif // QT_VERSION
diff --git a/lib/delegated_frame_node.h b/lib/delegated_frame_node.h
index 9eb9b5c48a0e571b68c5be402cabbc3c631e0170..0b6657e9828f630c9bb74ef5d122c77325d743bb 100644
--- a/lib/delegated_frame_node.h
+++ b/lib/delegated_frame_node.h
@@ -42,8 +42,10 @@
 #ifndef DELEGATED_FRAME_NODE_H
 #define DELEGATED_FRAME_NODE_H
 
+#include <QMutex>
 #include <QSGNode>
 #include <QSharedPointer>
+#include <QWaitCondition>
 
 #if (QT_VERSION >= QT_VERSION_CHECK(5, 2, 0))
 
@@ -55,6 +57,7 @@ namespace cc {
 class DelegatedFrameData;
 }
 
+class MailboxTexture;
 class RenderPassTexture;
 
 class DelegatedFrameNode : public QSGNode {
@@ -67,8 +70,15 @@ public:
 private:
     QQuickWindow *m_window;
     QList<QSharedPointer<RenderPassTexture> > m_renderPassTextures;
-    const size_t m_testTexturesSize;
-    GLuint m_testTextures[Qt::transparent - Qt::red];
+    QMap<int, QSharedPointer<MailboxTexture> > m_mailboxTextures;
+    int m_numPendingSyncPoints;
+    QWaitCondition m_mailboxesFetchedWaitCond;
+    QMutex m_mutex;
+
+    // Making those callbacks static bypasses base::Bind's ref-counting requirement
+    // of the this pointer when the callback is a method.
+    static void fetchTexturesAndUnlockQt(DelegatedFrameNode *frameNode, QList<MailboxTexture *> *mailboxesToFetch);
+    static void syncPointRetired(DelegatedFrameNode *frameNode, QList<MailboxTexture *> *mailboxesToFetch);
 };
 
 #endif // QT_VERSION
diff --git a/lib/lib.pro b/lib/lib.pro
index c25920b1609f7086277f1645d2366a5c238cd954..32af217b6057bbe761c8fbd8f11602d46f7fb288 100644
--- a/lib/lib.pro
+++ b/lib/lib.pro
@@ -40,6 +40,7 @@ SOURCES = \
         delegated_frame_node.cpp \
         dev_tools_http_handler_delegate_qt.cpp \
         download_manager_delegate_qt.cpp \
+        chromium_gpu_helper.cpp \
         javascript_dialog_manager_qt.cpp \
         render_widget_host_view_qt.cpp \
         resource_context_qt.cpp \
@@ -58,6 +59,7 @@ HEADERS = \
         delegated_frame_node.h \
         dev_tools_http_handler_delegate_qt.h \
         download_manager_delegate_qt.h \
+        chromium_gpu_helper.h \
         javascript_dialog_manager_qt.h \
         render_widget_host_view_qt.h \
         render_widget_host_view_qt_delegate.h \
diff --git a/lib/quick/render_widget_host_view_qt_delegate_quick.cpp b/lib/quick/render_widget_host_view_qt_delegate_quick.cpp
index 8989759f635b26f09e57079d1359b416aeaa1447..2d90e772bdd340d1968a5543c1e1e37f5daee1cd 100644
--- a/lib/quick/render_widget_host_view_qt_delegate_quick.cpp
+++ b/lib/quick/render_widget_host_view_qt_delegate_quick.cpp
@@ -58,10 +58,29 @@ void RenderWidgetHostViewQtDelegateQuick::update(const QRect&)
     QQuickItem::update();
 }
 
+void RenderWidgetHostViewQtDelegateQuick::itemChange(ItemChange change, const ItemChangeData &value)
+{
+    QQuickItem::itemChange(change, value);
+    if (change == QQuickItem::ItemSceneChange && value.window)
+        connect(value.window, SIGNAL(frameSwapped()), SLOT(onFrameSwapped()));
+}
+
 QSGNode *RenderWidgetHostViewQtDelegateQuick::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
 {
     return m_client->updatePaintNode(oldNode, QQuickItem::window());
 }
+
+void RenderWidgetHostViewQtDelegateQuick::releaseResources()
+{
+    // This is the only callback we get before being removed from a window while we still know it.
+    QQuickItem::window()->disconnect(this);
+}
+
+void RenderWidgetHostViewQtDelegateQuick::onFrameSwapped()
+{
+    m_client->sendDelegatedFrameAck();
+}
+
 #endif // QT_VERSION
 
 
diff --git a/lib/quick/render_widget_host_view_qt_delegate_quick.h b/lib/quick/render_widget_host_view_qt_delegate_quick.h
index 80f5baca88991b8b029af892fe93578b9d740a5d..612b89ed1c29ea470482107f5cd121e2ef83dea0 100644
--- a/lib/quick/render_widget_host_view_qt_delegate_quick.h
+++ b/lib/quick/render_widget_host_view_qt_delegate_quick.h
@@ -216,7 +216,12 @@ public:
     virtual WId nativeWindowIdForCompositor() const;
     virtual void update(const QRect& rect = QRect());
 
+    virtual void itemChange(ItemChange, const ItemChangeData &);
     virtual QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
+    virtual void releaseResources();
+
+public Q_SLOTS:
+    void onFrameSwapped();
 };
 #endif // QT_VERSION
 
diff --git a/lib/render_widget_host_view_qt.cpp b/lib/render_widget_host_view_qt.cpp
index b6a1d290567603586a043962b0600bd7e94d89a1..16adb5ec2e167a35b215f68d6d2c02b1e101d51a 100644
--- a/lib/render_widget_host_view_qt.cpp
+++ b/lib/render_widget_host_view_qt.cpp
@@ -168,16 +168,18 @@ void RenderWidgetHostViewQt::setAdapterClient(WebContentsAdapterClient *adapterC
         InitAsChild(0);
 }
 
-void RenderWidgetHostViewQt::releaseAndAckDelegatedFrame()
+void RenderWidgetHostViewQt::sendDelegatedFrameAck()
 {
+    if (!m_pendingAckFrameData)
+        return;
+
     cc::CompositorFrameAck ack;
-    // FIXME: This releases all resources of the frame for now.
-    ack.resources = m_pendingFrameData->resource_list;
+    ack.resources = m_pendingAckFrameData->resource_list;
     content::RenderWidgetHostImpl::SendSwapCompositorFrameAck(
         m_host->GetRoutingID(), m_pendingOutputSurfaceId,
         m_host->GetProcess()->GetID(), ack);
 
-    m_pendingFrameData.reset();
+    m_pendingAckFrameData.reset();
 }
 
 BackingStoreQt* RenderWidgetHostViewQt::GetBackingStore()
@@ -592,10 +594,9 @@ bool RenderWidgetHostViewQt::HasAcceleratedSurface(const gfx::Size&)
 void RenderWidgetHostViewQt::OnSwapCompositorFrame(uint32 output_surface_id, scoped_ptr<cc::CompositorFrame> frame)
 {
     Q_ASSERT(frame->delegated_frame_data);
-    SwapDelegatedFrame(output_surface_id,
-                       frame->delegated_frame_data.Pass(),
-                       frame->metadata.device_scale_factor,
-                       frame->metadata.latency_info);
+    m_pendingOutputSurfaceId = output_surface_id;
+    m_pendingUpdateFrameData = frame->delegated_frame_data.Pass();
+    m_delegate->update();
 }
 
 void RenderWidgetHostViewQt::GetScreenInfo(WebKit::WebScreenInfo* results)
@@ -650,19 +651,19 @@ void RenderWidgetHostViewQt::paint(QPainter *painter, const QRectF& boundingRect
 QSGNode *RenderWidgetHostViewQt::updatePaintNode(QSGNode *oldNode, QQuickWindow *window)
 {
 #if (QT_VERSION >= QT_VERSION_CHECK(5, 2, 0))
-    if (!m_pendingFrameData) {
-        delete oldNode;
-        return 0;
-    }
+    if (!m_pendingUpdateFrameData)
+        return oldNode;
+
     DelegatedFrameNode *frameNode = static_cast<DelegatedFrameNode *>(oldNode);
     if (!frameNode)
         frameNode = new DelegatedFrameNode(window);
 
-    frameNode->commit(m_pendingFrameData.get());
-
-    content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
-        base::Bind(&RenderWidgetHostViewQt::releaseAndAckDelegatedFrame, this->AsWeakPtr()));
+    // Switch the frame from one pointer to the other to keep track of its state
+    // to be able to update and then ack each frame only once.
+    Q_ASSERT(!m_pendingAckFrameData);
+    m_pendingAckFrameData.reset(m_pendingUpdateFrameData.release());
 
+    frameNode->commit(m_pendingAckFrameData.get());
     return frameNode;
 #else
     return 0;
@@ -763,16 +764,6 @@ void RenderWidgetHostViewQt::Paint(const gfx::Rect& damage_rect)
     m_delegate->update(r);
 }
 
-void RenderWidgetHostViewQt::SwapDelegatedFrame(uint32 output_surface_id, scoped_ptr<cc::DelegatedFrameData> frame_data, float frame_device_scale_factor, const ui::LatencyInfo& latency_info) {
-    gfx::Size frame_size_in_dip;
-    if (!frame_data->render_pass_list.empty())
-        frame_size_in_dip = gfx::ToFlooredSize(gfx::ScaleSize(frame_data->render_pass_list.back()->output_rect.size(), 1.f/frame_device_scale_factor));
-
-    m_pendingOutputSurfaceId = output_surface_id;
-    m_pendingFrameData = frame_data.Pass();
-    m_delegate->update();
-}
-
 void RenderWidgetHostViewQt::ProcessGestures(ui::GestureRecognizer::Gestures *gestures)
 {
     if (!gestures || gestures->empty())
diff --git a/lib/render_widget_host_view_qt.h b/lib/render_widget_host_view_qt.h
index 24c84555683b17d0201a19f6904526bcd0ea73a0..be32cfcf587a0891611981beb40a956958830b5a 100644
--- a/lib/render_widget_host_view_qt.h
+++ b/lib/render_widget_host_view_qt.h
@@ -99,7 +99,6 @@ public:
 
     void setDelegate(RenderWidgetHostViewQtDelegate *delegate);
     void setAdapterClient(WebContentsAdapterClient *adapterClient);
-    void releaseAndAckDelegatedFrame();
     BackingStoreQt* GetBackingStore();
 
     virtual content::BackingStore *AllocBackingStore(const gfx::Size &size);
@@ -168,6 +167,7 @@ public:
     // Overridden from RenderWidgetHostViewQtDelegateClient.
     virtual void paint(QPainter *, const QRectF& boundingRect) Q_DECL_OVERRIDE;
     virtual QSGNode *updatePaintNode(QSGNode *, QQuickWindow *) Q_DECL_OVERRIDE;
+    virtual void sendDelegatedFrameAck() Q_DECL_OVERRIDE;
     virtual void fetchBackingStore() Q_DECL_OVERRIDE;
     virtual void notifyResize() Q_DECL_OVERRIDE;
     virtual bool forwardEvent(QEvent *) Q_DECL_OVERRIDE;
@@ -196,7 +196,6 @@ public:
 
 private:
     void Paint(const gfx::Rect& damage_rect);
-    void SwapDelegatedFrame(uint32 output_surface_id, scoped_ptr<cc::DelegatedFrameData> frame_data, float frame_device_scale_factor, const ui::LatencyInfo& latency_info);
     void ProcessGestures(ui::GestureRecognizer::Gestures *gestures);
     int GetMappedTouch(int qtTouchId);
     void RemoveExpiredMappings(QTouchEvent *ev);
@@ -211,7 +210,8 @@ private:
 
     BackingStoreQt *m_backingStore;
     uint32 m_pendingOutputSurfaceId;
-    scoped_ptr<cc::DelegatedFrameData> m_pendingFrameData;
+    scoped_ptr<cc::DelegatedFrameData> m_pendingUpdateFrameData;
+    scoped_ptr<cc::DelegatedFrameData> m_pendingAckFrameData;
 
     WebContentsAdapterClient *m_adapterClient;
     MultipleMouseClickHelper m_clickHelper;
diff --git a/lib/render_widget_host_view_qt_delegate.h b/lib/render_widget_host_view_qt_delegate.h
index 2f1401b6daab73cbb9baca2cb4bc77ae4ac803e5..c541e36e78602ba3d95b0601c19936bdffdfd99c 100644
--- a/lib/render_widget_host_view_qt_delegate.h
+++ b/lib/render_widget_host_view_qt_delegate.h
@@ -64,6 +64,7 @@ public:
     virtual ~RenderWidgetHostViewQtDelegateClient() { }
     virtual void paint(QPainter *, const QRectF& boundingRect) = 0;
     virtual QSGNode *updatePaintNode(QSGNode *, QQuickWindow *) = 0;
+    virtual void sendDelegatedFrameAck() = 0;
     virtual void fetchBackingStore() = 0;
     virtual void notifyResize() = 0;
     virtual bool forwardEvent(QEvent *) = 0;
diff --git a/lib/type_conversion.h b/lib/type_conversion.h
index 6a9a124282f96c124e71531ee55308a7a8d3d40e..b2e29685df9f9e26b14da0d98a96ad6900e11155 100644
--- a/lib/type_conversion.h
+++ b/lib/type_conversion.h
@@ -81,6 +81,11 @@ inline QRect toQt(const gfx::Rect &rect)
     return QRect(rect.x(), rect.y(), rect.width(), rect.height());
 }
 
+inline QRectF toQt(const gfx::RectF &rect)
+{
+    return QRectF(rect.x(), rect.y(), rect.width(), rect.height());
+}
+
 inline QSize toQt(const gfx::Size &size)
 {
     return QSize(size.width(), size.height());
diff --git a/lib/web_engine_context.cpp b/lib/web_engine_context.cpp
index 62adf43efebf5c164111f39d208192193d837f78..4a6a6c5cb21cab7845cdb06e2a214cd08645851f 100644
--- a/lib/web_engine_context.cpp
+++ b/lib/web_engine_context.cpp
@@ -55,13 +55,15 @@
 #include "content/public/common/content_paths.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/main_function_params.h"
+#include "ui/gl/gl_switches.h"
 #include "webkit/common/user_agent/user_agent_util.h"
 
 #include "content_browser_client_qt.h"
 #include "content_client_qt.h"
 #include "type_conversion.h"
-#include <QCoreApplication>
+#include <QGuiApplication>
 #include <QStringList>
+#include <qpa/qplatformnativeinterface.h>
 
 namespace {
 
@@ -134,6 +136,10 @@ WebEngineContext::WebEngineContext()
     parsedCommandLine->AppendSwitch(switches::kNoSandbox);
     parsedCommandLine->AppendSwitch(switches::kDisablePlugins);
 
+    // Tell Chromium to use EGL instead of GLX if the Qt xcb plugin also does.
+    if (qApp->platformName() == QStringLiteral("xcb") && qApp->platformNativeInterface()->nativeResourceForWindow(QByteArrayLiteral("egldisplay"), 0))
+        parsedCommandLine->AppendSwitchASCII(switches::kUseGL, gfx::kGLImplementationEGLName);
+
     m_contentRunner->Initialize(0, 0, m_mainDelegate.get());
     m_browserRunner->Initialize(content::MainFunctionParams(*CommandLine::ForCurrentProcess()));
 
diff --git a/patches/0001-Add-accessors-for-the-Qt-delegated-renderer-integrat.patch b/patches/0001-Add-accessors-for-the-Qt-delegated-renderer-integrat.patch
new file mode 100644
index 0000000000000000000000000000000000000000..fe63dfc0f0dbe1b7797e3243c167c351dd46f835
--- /dev/null
+++ b/patches/0001-Add-accessors-for-the-Qt-delegated-renderer-integrat.patch
@@ -0,0 +1,84 @@
+From e40d3482d46ff88755aa2bd76048de698ae03915 Mon Sep 17 00:00:00 2001
+From: Jocelyn Turcotte <jocelyn.turcotte@digia.com>
+Date: Fri, 20 Sep 2013 15:00:47 +0200
+Subject: [PATCH] Add accessors for the Qt delegated renderer integration.
+
+This is needed to fetch the MessageLoop, the MailboxManager and the
+SyncPointManager of the GPU in-process host.
+---
+ content/common/gpu/gpu_channel_manager.h | 2 ++
+ content/gpu/gpu_child_thread.cc          | 6 ++++++
+ content/gpu/gpu_child_thread.h           | 6 ++++++
+ 3 files changed, 14 insertions(+)
+
+diff --git a/content/common/gpu/gpu_channel_manager.h b/content/common/gpu/gpu_channel_manager.h
+index f01a1c5..e41a548 100644
+--- a/content/common/gpu/gpu_channel_manager.h
++++ b/content/common/gpu/gpu_channel_manager.h
+@@ -89,6 +89,8 @@ class GpuChannelManager : public IPC::Listener,
+ 
+   gpu::gles2::ProgramCache* program_cache();
+ 
++  gpu::gles2::MailboxManager* mailbox_manager() { return mailbox_manager_.get(); }
++
+   GpuMemoryManager* gpu_memory_manager() { return &gpu_memory_manager_; }
+ 
+   GpuChannel* LookupChannel(int32 client_id);
+diff --git a/content/gpu/gpu_child_thread.cc b/content/gpu/gpu_child_thread.cc
+index 170b364..a84a9e0 100644
+--- a/content/gpu/gpu_child_thread.cc
++++ b/content/gpu/gpu_child_thread.cc
+@@ -40,6 +40,8 @@ bool GpuProcessLogMessageHandler(int severity,
+ 
+ }  // namespace
+ 
++GpuChildThread* GpuChildThread::instance_ = 0;
++
+ GpuChildThread::GpuChildThread(GpuWatchdogThread* watchdog_thread,
+                                bool dead_on_arrival,
+                                const gpu::GPUInfo& gpu_info,
+@@ -53,6 +55,8 @@ GpuChildThread::GpuChildThread(GpuWatchdogThread* watchdog_thread,
+   target_services_ = NULL;
+ #endif
+   g_thread_safe_sender.Get() = thread_safe_sender();
++
++  instance_ = this;
+ }
+ 
+ GpuChildThread::GpuChildThread(const std::string& channel_id)
+@@ -71,6 +75,8 @@ GpuChildThread::GpuChildThread(const std::string& channel_id)
+     VLOG(1) << "gfx::GLSurface::InitializeOneOff()";
+   }
+   g_thread_safe_sender.Get() = thread_safe_sender();
++
++  instance_ = this;
+ }
+ 
+ GpuChildThread::~GpuChildThread() {
+diff --git a/content/gpu/gpu_child_thread.h b/content/gpu/gpu_child_thread.h
+index ff0c925..82bb32a 100644
+--- a/content/gpu/gpu_child_thread.h
++++ b/content/gpu/gpu_child_thread.h
+@@ -56,6 +56,10 @@ class GpuChildThread : public ChildThread {
+   virtual bool Send(IPC::Message* msg) OVERRIDE;
+   virtual bool OnControlMessageReceived(const IPC::Message& msg) OVERRIDE;
+ 
++  GpuChannelManager* ChannelManager() const { return gpu_channel_manager_.get(); }
++
++  static GpuChildThread* instance() { return instance_; }
++
+  private:
+   // Message handlers.
+   void OnInitialize();
+@@ -94,6 +98,8 @@ class GpuChildThread : public ChildThread {
+   // Whether the GPU thread is running in the browser process.
+   bool in_browser_process_;
+ 
++  static GpuChildThread* instance_;
++
+   DISALLOW_COPY_AND_ASSIGN(GpuChildThread);
+ };
+ 
+-- 
+1.8.4.2
+
diff --git a/patches/0001-Add-seams-to-setup-GL-contexts-sharing-with-QtQuick.patch b/patches/0001-Add-seams-to-setup-GL-contexts-sharing-with-QtQuick.patch
new file mode 100644
index 0000000000000000000000000000000000000000..55cf5a5d522a9916fab38c039f2a1bcacb65d897
--- /dev/null
+++ b/patches/0001-Add-seams-to-setup-GL-contexts-sharing-with-QtQuick.patch
@@ -0,0 +1,109 @@
+From 559c011aabd6fc9f064d2913e4fae06db2c8495b Mon Sep 17 00:00:00 2001
+From: Jocelyn Turcotte <jocelyn.turcotte@digia.com>
+Date: Thu, 24 Oct 2013 18:26:59 +0200
+Subject: [PATCH] Add seams to setup GL contexts sharing with QtQuick.
+
+This will allow us to know right before the first GL context is
+instantiated by Chromium so that we can install those contexts to
+be shared with QtQuick GL contexts as well.
+---
+ content/common/gpu/gpu_channel_manager.cc       | 8 +++++++-
+ content/public/browser/content_browser_client.h | 5 +++++
+ ui/gl/gl_share_group.cc                         | 3 +++
+ ui/gl/gl_share_group.h                          | 7 +++++--
+ 4 files changed, 20 insertions(+), 3 deletions(-)
+
+diff --git a/content/common/gpu/gpu_channel_manager.cc b/content/common/gpu/gpu_channel_manager.cc
+index 8b466bd..fe3f7b3 100644
+--- a/content/common/gpu/gpu_channel_manager.cc
++++ b/content/common/gpu/gpu_channel_manager.cc
+@@ -11,6 +11,7 @@
+ #include "content/common/gpu/gpu_memory_manager.h"
+ #include "content/common/gpu/gpu_messages.h"
+ #include "content/common/gpu/sync_point_manager.h"
++#include "content/public/browser/content_browser_client.h"
+ #include "gpu/command_buffer/service/feature_info.h"
+ #include "gpu/command_buffer/service/gpu_switches.h"
+ #include "gpu/command_buffer/service/mailbox_manager.h"
+@@ -124,7 +125,12 @@ void GpuChannelManager::OnEstablishChannel(int client_id, bool share_context) {
+       DCHECK(!mailbox_manager_.get());
+       mailbox_manager_ = new gpu::gles2::MailboxManager;
+     }
+-    share_group = share_group_.get();
++    // Qt: Ask the browser client at the top to manage the context sharing.
++    // This can only work with --in-process-gpu or --single-process.
++    if (GetContentClient()->browser() && GetContentClient()->browser()->GetInProcessGpuShareGroup())
++      share_group = GetContentClient()->browser()->GetInProcessGpuShareGroup();
++    else
++      share_group = share_group_.get();
+     mailbox_manager = mailbox_manager_.get();
+   }
+ 
+diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h
+index 1f5e836..2168769 100644
+--- a/content/public/browser/content_browser_client.h
++++ b/content/public/browser/content_browser_client.h
+@@ -48,6 +48,7 @@ class CryptoModuleBlockingPasswordDelegate;
+ }
+ 
+ namespace gfx {
++class GLShareGroup;
+ class ImageSkia;
+ }
+ 
+@@ -563,6 +564,10 @@ class CONTENT_EXPORT ContentBrowserClient {
+   // Return NULL to use the default one for the platform to be created.
+   virtual LocationProvider* OverrideSystemLocationProvider();
+ 
++  // Allow an embedder to provide a share group reimplementation to connect renderer
++  // GL contexts with the root compositor.
++  virtual gfx::GLShareGroup* GetInProcessGpuShareGroup() { return 0; }
++
+ #if defined(OS_POSIX) && !defined(OS_MACOSX)
+   // Populates |mappings| with all files that need to be mapped before launching
+   // a child process.
+diff --git a/ui/gl/gl_share_group.cc b/ui/gl/gl_share_group.cc
+index 8e8958b..347873d 100644
+--- a/ui/gl/gl_share_group.cc
++++ b/ui/gl/gl_share_group.cc
+@@ -18,6 +18,9 @@ GLShareGroup::GLShareGroup()
+ }
+ 
+ void GLShareGroup::AddContext(GLContext* context) {
++  if (contexts_.empty())
++    AboutToAddFirstContext();
++
+   contexts_.insert(context);
+ }
+ 
+diff --git a/ui/gl/gl_share_group.h b/ui/gl/gl_share_group.h
+index 1deed63..f1b0369 100644
+--- a/ui/gl/gl_share_group.h
++++ b/ui/gl/gl_share_group.h
+@@ -31,7 +31,7 @@ class GL_EXPORT GLShareGroup : public base::RefCounted<GLShareGroup> {
+ 
+   // Returns a pointer to any initialized context in the share group
+   // or NULL if there are no initialized contexts in the share group.
+-  GLContext* GetContext();
++  virtual GLContext* GetContext();
+ 
+   // Sets and returns the unique shared GL context. Used for context
+   // virtualization.
+@@ -45,10 +45,13 @@ class GL_EXPORT GLShareGroup : public base::RefCounted<GLShareGroup> {
+   int GetRendererID();
+ #endif
+ 
++ protected:
++  virtual ~GLShareGroup();
++  virtual void AboutToAddFirstContext() { }
++
+  private:
+   friend class base::RefCounted<GLShareGroup>;
+ 
+-  ~GLShareGroup();
+ 
+   // References to GLContext are by raw pointer to avoid a reference count
+   // cycle.
+-- 
+1.8.4.2
+
diff --git a/patches/patch-chromium.sh b/patches/patch-chromium.sh
index 2c3834b081cd5ac480f887fc011798374123920c..38cc4c126186a1e9727e73149f7624d4b03230d8 100755
--- a/patches/patch-chromium.sh
+++ b/patches/patch-chromium.sh
@@ -69,6 +69,8 @@ git am $PATCH_DIR/0001-Solve-conflicts-when-including-both-QtOpenGL-headers.patc
 git am $PATCH_DIR/0001-Do-not-forward-declare-UIResourceRequest-Identity-an.patch
 git am $PATCH_DIR/0001-Fix-the-build-with-a-GL-ES2-configured-Qt.patch
 git am $PATCH_DIR/0001-Hide-the-definition-of-MessagePumpGtk-GetDefaultXDis.patch
+git am $PATCH_DIR/0001-Add-accessors-for-the-Qt-delegated-renderer-integrat.patch
+git am $PATCH_DIR/0001-Add-seams-to-setup-GL-contexts-sharing-with-QtQuick.patch
 
 cd $CHROMIUM_SRC_DIR/third_party/WebKit
 echo "Entering $PWD"