summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
m---------3rdparty0
-rw-r--r--examples/quick/quicknanobrowser/main.cpp8
-rw-r--r--examples/quick/quicknanobrowser/quicknanobrowser.pro2
-rw-r--r--lib/chromium_gpu_helper.cpp86
-rw-r--r--lib/chromium_gpu_helper.h76
-rw-r--r--lib/content_browser_client_qt.cpp64
-rw-r--r--lib/content_browser_client_qt.h9
-rw-r--r--lib/delegated_frame_node.cpp202
-rw-r--r--lib/delegated_frame_node.h14
-rw-r--r--lib/lib.pro2
-rw-r--r--lib/quick/render_widget_host_view_qt_delegate_quick.cpp19
-rw-r--r--lib/quick/render_widget_host_view_qt_delegate_quick.h5
-rw-r--r--lib/render_widget_host_view_qt.cpp43
-rw-r--r--lib/render_widget_host_view_qt.h6
-rw-r--r--lib/render_widget_host_view_qt_delegate.h1
-rw-r--r--lib/type_conversion.h5
-rw-r--r--lib/web_engine_context.cpp8
-rw-r--r--patches/0001-Add-accessors-for-the-Qt-delegated-renderer-integrat.patch84
-rw-r--r--patches/0001-Add-seams-to-setup-GL-contexts-sharing-with-QtQuick.patch109
-rwxr-xr-xpatches/patch-chromium.sh2
20 files changed, 667 insertions, 78 deletions
diff --git a/3rdparty b/3rdparty
-Subproject 63f1510d708ce6e90354c63655fa21bd4906e52
+Subproject 9427c1a0222ebd67efef1a2c7990a0fa5c9aac8
diff --git a/examples/quick/quicknanobrowser/main.cpp b/examples/quick/quicknanobrowser/main.cpp
index 982c1eb7a..6c2f91de6 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 c32540a71..2132b031a 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 000000000..3d393c25d
--- /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 000000000..e0ac8e2a3
--- /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 4ff15d3b1..97d5c8e4e 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 f8c42e569..b97eaa5e1 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 dea9605be..0e3f34fff 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 9eb9b5c48..0b6657e98 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 c25920b16..32af217b6 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 8989759f6..2d90e772b 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 80f5baca8..612b89ed1 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 b6a1d2905..16adb5ec2 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 24c845556..be32cfcf5 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 2f1401b6d..c541e36e7 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 6a9a12428..b2e29685d 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 62adf43ef..4a6a6c5cb 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 000000000..fe63dfc0f
--- /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 000000000..55cf5a5d5
--- /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 2c3834b08..38cc4c126 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"