summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJocelyn Turcotte <jocelyn.turcotte@digia.com>2013-09-13 15:29:53 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-10-14 15:50:35 +0200
commit0b9ea2d05d1081ce4a667f0c7036a205bcd751a3 (patch)
tree3d194274878b1501bbe15428554d74aedafd0d56
parent338e24b48601a3cfdcde0977b6c9390d33d51c9f (diff)
Render delegated renderer frames using the Qt scene graph.
This provides a stub implementation that renders quads and RenderPasses using QSGNodes in QQuickWebEngineView. The BackingStore code path is still supported when the delegated renderer switch is not enabled. To use the new rendering, pass the following switches: --enable-delegated-renderer --enable-threaded-compositing This uses debug, plain color textures until we can fetch tiles and textures from the ResourceProvider across OpenGL context boundaries. Change-Id: I33ea0738dc5a326ef79c1435f75c044c42e8551f Reviewed-by: Zeno Albisser <zeno.albisser@digia.com>
m---------3rdparty0
-rw-r--r--lib/lib.pro4
-rw-r--r--lib/quick/qquickwebengineview.cpp12
-rw-r--r--lib/quick/render_widget_host_view_qt_delegate_quick.cpp28
-rw-r--r--lib/quick/render_widget_host_view_qt_delegate_quick.h23
-rw-r--r--lib/render_widget_host_view_qt.cpp31
-rw-r--r--lib/render_widget_host_view_qt.h10
-rw-r--r--lib/render_widget_host_view_qt_delegate.cpp336
-rw-r--r--lib/render_widget_host_view_qt_delegate.h14
-rw-r--r--lib/type_conversion.h23
-rw-r--r--lib/web_contents_adapter_client.h1
-rw-r--r--lib/web_contents_view_qt.cpp4
-rw-r--r--patches/0001-Solve-conflicts-when-including-both-QtOpenGL-headers.patch77
-rwxr-xr-xpatches/patch-chromium.sh1
14 files changed, 548 insertions, 16 deletions
diff --git a/3rdparty b/3rdparty
-Subproject 679147eead574d186ebf3069647b4c23e8ccace
+Subproject c9d97c73d7b1295b8c714ccaf1e5b717841bccc
diff --git a/lib/lib.pro b/lib/lib.pro
index dbfde8c59..eda03287d 100644
--- a/lib/lib.pro
+++ b/lib/lib.pro
@@ -9,6 +9,10 @@ TEMPLATE = lib
TARGET = Qt5WebEngineCore
+QT += qml quick
+QT_PRIVATE += qml-private quick-private gui-private core-private
+qtHaveModule(v8): QT_PRIVATE += v8-private
+
# Defining keywords such as 'signal' clashes with the chromium code base.
DEFINES += QT_NO_KEYWORDS \
Q_FORWARD_DECLARE_OBJC_CLASS=QT_FORWARD_DECLARE_CLASS
diff --git a/lib/quick/qquickwebengineview.cpp b/lib/quick/qquickwebengineview.cpp
index 55d871093..dfab8ea0e 100644
--- a/lib/quick/qquickwebengineview.cpp
+++ b/lib/quick/qquickwebengineview.cpp
@@ -56,8 +56,12 @@ QQuickWebEngineViewPrivate::QQuickWebEngineViewPrivate()
adapter->initialize(this);
}
-RenderWidgetHostViewQtDelegate *QQuickWebEngineViewPrivate::CreateRenderWidgetHostViewQtDelegate(CompositingMode)
+RenderWidgetHostViewQtDelegate *QQuickWebEngineViewPrivate::CreateRenderWidgetHostViewQtDelegate(CompositingMode mode)
{
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 2, 0))
+ if (mode == DelegatedCompositing)
+ return new RenderWidgetHostViewQtDelegateQuick;
+#endif
return new RenderWidgetHostViewQtDelegateQuickPainted;
}
@@ -207,7 +211,11 @@ void QQuickWebEngineView::geometryChanged(const QRectF &newGeometry, const QRect
QQuickItem::geometryChanged(newGeometry, oldGeometry);
Q_FOREACH(QQuickItem *child, childItems()) {
- Q_ASSERT(qobject_cast<RenderWidgetHostViewQtDelegateQuickPainted *>(child));
+ Q_ASSERT(
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 2, 0))
+ qobject_cast<RenderWidgetHostViewQtDelegateQuick *>(child) ||
+#endif
+ qobject_cast<RenderWidgetHostViewQtDelegateQuickPainted *>(child));
child->setSize(newGeometry.size());
}
}
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 6f8243690..b77503f2c 100644
--- a/lib/quick/render_widget_host_view_qt_delegate_quick.cpp
+++ b/lib/quick/render_widget_host_view_qt_delegate_quick.cpp
@@ -41,6 +41,30 @@
#include "render_widget_host_view_qt_delegate_quick.h"
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 2, 0))
+RenderWidgetHostViewQtDelegateQuick::RenderWidgetHostViewQtDelegateQuick(QQuickItem *parent)
+ : RenderWidgetHostViewQtDelegateQuickBase<QQuickItem>(parent)
+{
+ setFlag(ItemHasContents);
+}
+
+WId RenderWidgetHostViewQtDelegateQuick::nativeWindowIdForCompositor() const
+{
+ return QQuickItem::window()->winId();
+}
+
+void RenderWidgetHostViewQtDelegateQuick::update(const QRect&)
+{
+ QQuickItem::update();
+}
+
+QSGNode *RenderWidgetHostViewQtDelegateQuick::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
+{
+ return RenderWidgetHostViewQtDelegate::updatePaintNode(oldNode, QQuickItem::window());
+}
+#endif // QT_VERSION
+
+
RenderWidgetHostViewQtDelegateQuickPainted::RenderWidgetHostViewQtDelegateQuickPainted(QQuickItem *parent)
: RenderWidgetHostViewQtDelegateQuickBase<QQuickPaintedItem>(parent)
{
@@ -48,9 +72,7 @@ RenderWidgetHostViewQtDelegateQuickPainted::RenderWidgetHostViewQtDelegateQuickP
WId RenderWidgetHostViewQtDelegateQuickPainted::nativeWindowIdForCompositor() const
{
- // Only used to enable accelerated compositing by the compositor
- // directly on our native window, which we want to eventually do
- // through the delegated renderer instead.
+ // This causes a failure of the compositor initialization which ends up disabling it completely.
return 0;
}
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 67c38a75d..ce4d87c3d 100644
--- a/lib/quick/render_widget_host_view_qt_delegate_quick.h
+++ b/lib/quick/render_widget_host_view_qt_delegate_quick.h
@@ -42,15 +42,6 @@
#ifndef RENDER_WIDGET_HOST_VIEW_QT_DELEGATE_QUICK_H
#define RENDER_WIDGET_HOST_VIEW_QT_DELEGATE_QUICK_H
-// On Mac we need to reset this define in order to prevent definition
-// of "check" macros etc. The "check" macro collides with a member function name in QtQuick.
-// See AssertMacros.h in the Mac SDK.
-#include <QtGlobal> // We need this for the Q_OS_MAC define.
-#if defined(Q_OS_MAC)
-#undef __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES
-#define __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES 0
-#endif
-
#include "render_widget_host_view_qt_delegate.h"
#include "qquickwebengineview_p.h"
@@ -186,6 +177,20 @@ protected:
}
};
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 2, 0))
+class RenderWidgetHostViewQtDelegateQuick : public RenderWidgetHostViewQtDelegateQuickBase<QQuickItem>
+{
+ Q_OBJECT
+public:
+ RenderWidgetHostViewQtDelegateQuick(QQuickItem *parent = 0);
+
+ virtual WId nativeWindowIdForCompositor() const;
+ virtual void update(const QRect& rect = QRect());
+
+ virtual QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
+};
+#endif // QT_VERSION
+
class RenderWidgetHostViewQtDelegateQuickPainted : public RenderWidgetHostViewQtDelegateQuickBase<QQuickPaintedItem>
{
Q_OBJECT
diff --git a/lib/render_widget_host_view_qt.cpp b/lib/render_widget_host_view_qt.cpp
index 99bf94653..d9f1a48df 100644
--- a/lib/render_widget_host_view_qt.cpp
+++ b/lib/render_widget_host_view_qt.cpp
@@ -47,6 +47,7 @@
#include "shared/shared_globals.h"
+#include "cc/output/compositor_frame_ack.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/renderer_host/ui_events_helper.h"
#include "content/common/gpu/gpu_messages.h"
@@ -161,6 +162,18 @@ bool RenderWidgetHostViewQt::handleEvent(QEvent* event) {
return true;
}
+void RenderWidgetHostViewQt::releaseAndAckDelegatedFrame()
+{
+ cc::CompositorFrameAck ack;
+ // FIXME: This releases all resources of the frame for now.
+ ack.resources = m_pendingFrameData->resource_list;
+ content::RenderWidgetHostImpl::SendSwapCompositorFrameAck(
+ m_host->GetRoutingID(), m_pendingOutputSurfaceId,
+ m_host->GetProcess()->GetID(), ack);
+
+ m_pendingFrameData.reset();
+}
+
BackingStoreQt* RenderWidgetHostViewQt::GetBackingStore()
{
bool force_create = !m_host->empty();
@@ -554,6 +567,15 @@ bool RenderWidgetHostViewQt::HasAcceleratedSurface(const gfx::Size&)
return false;
}
+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);
+}
+
void RenderWidgetHostViewQt::GetScreenInfo(WebKit::WebScreenInfo* results)
{
QWindow* window = m_delegate->window();
@@ -617,6 +639,15 @@ 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)
{
diff --git a/lib/render_widget_host_view_qt.h b/lib/render_widget_host_view_qt.h
index 97261ca92..337351b69 100644
--- a/lib/render_widget_host_view_qt.h
+++ b/lib/render_widget_host_view_qt.h
@@ -45,6 +45,7 @@
#include "shared/shared_globals.h"
#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "ui/base/gestures/gesture_recognizer.h"
#include "ui/base/gestures/gesture_types.h"
@@ -87,6 +88,7 @@ class RenderWidgetHostViewQt
: public content::RenderWidgetHostViewBase
, public ui::GestureConsumer
, public ui::GestureEventHelper
+ , public base::SupportsWeakPtr<RenderWidgetHostViewQt>
{
public:
RenderWidgetHostViewQt(content::RenderWidgetHost* widget);
@@ -95,6 +97,8 @@ public:
void setDelegate(RenderWidgetHostViewQtDelegate *delegate);
void setAdapterClient(WebContentsAdapterClient *adapterClient);
bool handleEvent(QEvent* event);
+ cc::DelegatedFrameData *pendingDelegatedFrame() const { return m_pendingFrameData.get(); }
+ void releaseAndAckDelegatedFrame();
BackingStoreQt* GetBackingStore();
virtual content::BackingStore *AllocBackingStore(const gfx::Size &size);
@@ -147,6 +151,7 @@ public:
virtual void AcceleratedSurfaceSuspend();
virtual void AcceleratedSurfaceRelease();
virtual bool HasAcceleratedSurface(const gfx::Size&);
+ virtual void OnSwapCompositorFrame(uint32 output_surface_id, scoped_ptr<cc::CompositorFrame> frame) Q_DECL_OVERRIDE;
virtual void GetScreenInfo(WebKit::WebScreenInfo* results);
virtual gfx::Rect GetBoundsInRootWindow();
virtual gfx::GLSurfaceHandle GetCompositingSurface();
@@ -182,6 +187,7 @@ 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);
@@ -193,6 +199,10 @@ private:
QMap<int, int> m_touchIdMapping;
WebKit::WebTouchEvent m_accumTouchEvent;
scoped_ptr<RenderWidgetHostViewQtDelegate> m_delegate;
+
+ uint32 m_pendingOutputSurfaceId;
+ scoped_ptr<cc::DelegatedFrameData> m_pendingFrameData;
+
WebContentsAdapterClient *m_adapterClient;
MultipleMouseClickHelper m_clickHelper;
diff --git a/lib/render_widget_host_view_qt_delegate.cpp b/lib/render_widget_host_view_qt_delegate.cpp
index 0a3a5106f..3ec9d450a 100644
--- a/lib/render_widget_host_view_qt_delegate.cpp
+++ b/lib/render_widget_host_view_qt_delegate.cpp
@@ -43,9 +43,243 @@
#include "backing_store_qt.h"
#include "render_widget_host_view_qt.h"
+#include "type_conversion.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
-#include <QPainter>
+
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 2, 0))
+#include "cc/quads/draw_quad.h"
+#include "cc/quads/render_pass_draw_quad.h"
+#include "cc/quads/texture_draw_quad.h"
+#include "cc/quads/tile_draw_quad.h"
+#include <QSGNode>
+#include <QSGSimpleTextureNode>
+#include <QSGTexture>
+#include <QtQuick/private/qquickclipnode_p.h>
+#include <QtQuick/private/qquickwindow_p.h>
+#include <QtQuick/private/qsgcontext_p.h>
+#include <QtQuick/private/qsgrenderer_p.h>
+
+class RenderPassTexture : public QSGTexture
+{
+public:
+ RenderPassTexture(const cc::RenderPass::Id &id, QSGContext *context);
+
+ const cc::RenderPass::Id &id() const { return m_id; }
+ void bind();
+
+ int textureId() const { return m_fbo ? m_fbo->texture() : 0; }
+ QSize textureSize() const { return m_rect.size(); }
+ bool hasAlphaChannel() const { return m_format != GL_RGB; }
+ bool hasMipmaps() const { return false; }
+
+ void setRect(const QRect &rect) { m_rect = rect; }
+ void setFormat(GLenum format) { m_format = format; }
+ void setDevicePixelRatio(qreal ratio) { m_device_pixel_ratio = ratio; }
+ QSGNode *rootNode() { return m_rootNode.data(); }
+
+ void grab();
+
+private:
+ cc::RenderPass::Id m_id;
+ QRect m_rect;
+ qreal m_device_pixel_ratio;
+ GLenum m_format;
+
+ QScopedPointer<QSGRootNode> m_rootNode;
+ QScopedPointer<QSGRenderer> m_renderer;
+ QScopedPointer<QOpenGLFramebufferObject> m_fbo;
+
+ QSGContext *m_context;
+};
+
+RenderPassTexture::RenderPassTexture(const cc::RenderPass::Id &id, QSGContext *context)
+ : QSGTexture()
+ , m_id(id)
+ , m_device_pixel_ratio(1)
+ , m_format(GL_RGBA)
+ , m_rootNode(new QSGRootNode)
+ , m_context(context)
+{
+}
+
+void RenderPassTexture::bind()
+{
+ glBindTexture(GL_TEXTURE_2D, m_fbo ? m_fbo->texture() : 0);
+ updateBindOptions();
+}
+
+void RenderPassTexture::grab()
+{
+ if (!m_rootNode->firstChild()) {
+ m_renderer.reset();
+ m_fbo.reset();
+ return;
+ }
+ if (!m_renderer) {
+ m_renderer.reset(m_context->createRenderer());
+ m_renderer->setRootNode(m_rootNode.data());
+ }
+ m_renderer->setDevicePixelRatio(m_device_pixel_ratio);
+
+ if (!m_fbo || m_fbo->size() != m_rect.size() || m_fbo->format().internalTextureFormat() != m_format)
+ {
+ QOpenGLFramebufferObjectFormat format;
+ format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
+ format.setInternalTextureFormat(m_format);
+
+ m_fbo.reset(new QOpenGLFramebufferObject(m_rect.size(), format));
+ glBindTexture(GL_TEXTURE_2D, m_fbo->texture());
+ updateBindOptions(true);
+ }
+
+ m_rootNode->markDirty(QSGNode::DirtyForceUpdate); // Force matrix, clip and opacity update.
+ m_renderer->nodeChanged(m_rootNode.data(), QSGNode::DirtyForceUpdate); // Force render list update.
+
+ m_renderer->setDeviceRect(m_rect.size());
+ m_renderer->setViewportRect(m_rect.size());
+ QRectF mirrored(m_rect.left(), m_rect.bottom(), m_rect.width(), -m_rect.height());
+ m_renderer->setProjectionMatrixToRect(mirrored);
+ m_renderer->setClearColor(Qt::transparent);
+
+ m_context->renderNextFrame(m_renderer.data(), m_fbo->handle());
+}
+
+class RawTextureNode : public QSGSimpleTextureNode {
+public:
+ RawTextureNode(GLuint textureId, const QSize &textureSize, bool hasAlpha, QQuickWindow *window);
+
+private:
+ QScopedPointer<QSGTexture> m_texture;
+};
+
+RawTextureNode::RawTextureNode(GLuint textureId, const QSize &textureSize, bool hasAlpha, QQuickWindow *window)
+ : m_texture(window->createTextureFromId(textureId, textureSize, QQuickWindow::CreateTextureOption(hasAlpha ? QQuickWindow::TextureHasAlphaChannel : 0)))
+{
+ setTexture(m_texture.data());
+}
+
+class DelegatedFrameNode : public QSGNode {
+public:
+ DelegatedFrameNode();
+ ~DelegatedFrameNode();
+ void preprocess();
+ QList<QSharedPointer<RenderPassTexture> > renderPassTextures;
+
+ const size_t testTexturesSize;
+ GLuint testTextures[Qt::transparent - Qt::red];
+};
+
+DelegatedFrameNode::DelegatedFrameNode()
+ : testTexturesSize(sizeof(testTextures) / sizeof(GLuint))
+{
+ setFlag(UsePreprocess);
+
+ // Generate plain color textures to be used until we can use the real textures from the ResourceProvider.
+ glGenTextures(testTexturesSize, testTextures);
+ for (unsigned i = 0; i < 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, testTextures[i]);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width(), image.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, image.constBits() );
+ }
+}
+
+DelegatedFrameNode::~DelegatedFrameNode()
+{
+ glDeleteTextures(testTexturesSize, testTextures);
+}
+
+void DelegatedFrameNode::preprocess()
+{
+ // Render any intermediate RenderPass in order.
+ Q_FOREACH (const QSharedPointer<RenderPassTexture> &texture, renderPassTextures)
+ texture->grab();
+}
+
+static inline QSharedPointer<RenderPassTexture> findRenderPassTexture(const cc::RenderPass::Id &id, const QList<QSharedPointer<RenderPassTexture> > &list)
+{
+ Q_FOREACH (const QSharedPointer<RenderPassTexture> &texture, list)
+ if (texture->id() == id)
+ return texture;
+ return QSharedPointer<RenderPassTexture>();
+}
+
+static QSGNode *buildRenderPassChain(QSGNode *chainParent, const cc::RenderPass *renderPass)
+{
+ // Chromium already ordered the quads from back to front for us, however the
+ // Qt scene graph layers individual geometries in their own z-range and uses
+ // the depth buffer to visually stack nodes according to their item tree order.
+ // This finds the z-span of all layers so that we can z-compress them to fit
+ // them between 0.0 and 1.0 on the z axis.
+ double minZ = 0;
+ double maxZ = 1;
+ double src2[8];
+ double dst4[16];
+ // topleft.x, topleft.y, topRight.y and bottomLeft.x
+ src2[0] = src2[1] = src2[3] = src2[4] = 0;
+
+ // Go through each layer in this pass and find out their transformed rect.
+ cc::SharedQuadStateList::const_iterator it = renderPass->shared_quad_state_list.begin();
+ cc::SharedQuadStateList::const_iterator sharedStateEnd = renderPass->shared_quad_state_list.end();
+ for (; it != sharedStateEnd; ++it) {
+ gfx::Size &layerSize = (*it)->content_bounds;
+ // topRight.x
+ src2[2] = layerSize.width();
+ // bottomLeft.y
+ src2[5] = layerSize.height();
+ // bottomRight
+ src2[6] = layerSize.width();
+ src2[7] = layerSize.height();
+ (*it)->content_to_target_transform.matrix().map2(src2, 4, dst4);
+ // Check the mapped corner's z value and track the boundaries.
+ minZ = std::min(std::min(std::min(std::min(minZ, dst4[2]), dst4[6]), dst4[10]), dst4[14]);
+ maxZ = std::max(std::max(std::max(std::max(maxZ, dst4[2]), dst4[6]), dst4[10]), dst4[14]);
+ }
+
+ QSGTransformNode *zCompressNode = new QSGTransformNode;
+ QMatrix4x4 zCompressMatrix;
+ zCompressMatrix.scale(1, 1, 1 / (maxZ - minZ));
+ zCompressMatrix.translate(0, 0, -minZ);
+ zCompressNode->setMatrix(zCompressMatrix);
+ chainParent->appendChildNode(zCompressNode);
+ return zCompressNode;
+}
+
+static QSGNode *buildLayerChain(QSGNode *chainParent, const cc::SharedQuadState *layerState)
+{
+ QSGNode *layerChain = chainParent;
+ if (layerState->is_clipped) {
+ QQuickDefaultClipNode *clipNode = new QQuickDefaultClipNode(toQt(layerState->clip_rect));
+ clipNode->update();
+ layerChain->appendChildNode(clipNode);
+ layerChain = clipNode;
+ }
+ if (!layerState->content_to_target_transform.IsIdentity()) {
+ QSGTransformNode *transformNode = new QSGTransformNode;
+ transformNode->setMatrix(toQt(layerState->content_to_target_transform.matrix()));
+ layerChain->appendChildNode(transformNode);
+ layerChain = transformNode;
+ }
+ if (layerState->opacity < 1.0) {
+ QSGOpacityNode *opacityNode = new QSGOpacityNode;
+ opacityNode->setOpacity(layerState->opacity);
+ layerChain->appendChildNode(opacityNode);
+ layerChain = opacityNode;
+ }
+ return layerChain;
+}
+#endif // QT_VERSION
RenderWidgetHostViewQtDelegate::RenderWidgetHostViewQtDelegate()
: m_view(0), m_backingStore(0)
@@ -62,6 +296,106 @@ void RenderWidgetHostViewQtDelegate::paint(QPainter *painter, const QRectF &boun
m_backingStore->paintToTarget(painter, boundingRect);
}
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 2, 0))
+QSGNode *RenderWidgetHostViewQtDelegate::updatePaintNode(QSGNode *oldNode, QQuickWindow *window)
+{
+ cc::DelegatedFrameData *frameData = m_view->pendingDelegatedFrame();
+ if (!frameData) {
+ delete oldNode;
+ return 0;
+ }
+ DelegatedFrameNode *frameNode = static_cast<DelegatedFrameNode *>(oldNode);
+ if (!frameNode)
+ frameNode = new DelegatedFrameNode;
+
+ // Keep the old list around to find the ones we can re-use.
+ QList<QSharedPointer<RenderPassTexture> > oldRenderPassTextures;
+ frameNode->renderPassTextures.swap(oldRenderPassTextures);
+
+ // 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.
+ // The list is already ordered with intermediate RenderPasses placed before their
+ // parent, with the last one in the list being the root RenderPass, the one
+ // that we displayed to the user.
+ // All RenderPasses except the last one are rendered to an FBO.
+ cc::RenderPass *rootRenderPass = frameData->render_pass_list.back();
+
+ for (unsigned i = 0; i < frameData->render_pass_list.size(); ++i) {
+ cc::RenderPass *pass = frameData->render_pass_list.at(i);
+
+ QSGNode *renderPassParent = 0;
+ if (pass != rootRenderPass) {
+ QSharedPointer<RenderPassTexture> rpTexture = findRenderPassTexture(pass->id, oldRenderPassTextures);
+ if (!rpTexture) {
+ QSGContext *sgContext = QQuickWindowPrivate::get(window)->context;
+ rpTexture = QSharedPointer<RenderPassTexture>(new RenderPassTexture(pass->id, sgContext));
+ }
+ frameNode->renderPassTextures.append(rpTexture);
+ rpTexture->setDevicePixelRatio(window->devicePixelRatio());
+ rpTexture->setRect(toQt(pass->output_rect));
+ rpTexture->setFormat(pass->has_transparent_background ? GL_RGBA : GL_RGB);
+ renderPassParent = rpTexture->rootNode();
+ } else
+ renderPassParent = frameNode;
+
+ // There is currently no way to know which and how quads changed since the last frame.
+ // We have to reconstruct the node chain with their geometries on every update.
+ while (QSGNode *oldChain = renderPassParent->firstChild())
+ delete oldChain;
+
+ QSGNode *renderPassChain = buildRenderPassChain(renderPassParent, pass);
+ const cc::SharedQuadState *currentLayerState = 0;
+ QSGNode *currentLayerChain = 0;
+
+ cc::QuadList::ConstBackToFrontIterator it = pass->quad_list.BackToFrontBegin();
+ cc::QuadList::ConstBackToFrontIterator end = pass->quad_list.BackToFrontEnd();
+ for (; it != end; ++it) {
+ cc::DrawQuad *quad = *it;
+
+ if (currentLayerState != quad->shared_quad_state) {
+ currentLayerState = quad->shared_quad_state;
+ 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, frameNode->renderPassTextures).data();
+ if (texture) {
+ textureNode = new QSGSimpleTextureNode;
+ textureNode->setTexture(texture);
+ } else {
+ qWarning("Unknown RenderPass layer: Id %d", renderPassQuad->render_pass_id.layer_id);
+ textureNode = new RawTextureNode(0, QSize(1, 1), false, window);
+ }
+ break;
+ } case cc::DrawQuad::TEXTURE_CONTENT: {
+ uint32 resourceId = cc::TextureDrawQuad::MaterialCast(quad)->resource_id;
+ textureNode = new RawTextureNode(frameNode->testTextures[resourceId % frameNode->testTexturesSize], QSize(1, 1), false, window);
+ break;
+ } case cc::DrawQuad::TILED_CONTENT: {
+ uint32 resourceId = cc::TileDrawQuad::MaterialCast(quad)->resource_id;
+ textureNode = new RawTextureNode(frameNode->testTextures[resourceId % frameNode->testTexturesSize], QSize(1, 1), false, window);
+ break;
+ } default:
+ qWarning("Unimplemented quad material: %d", quad->material);
+ textureNode = new RawTextureNode(0, QSize(1, 1), false, window);
+ }
+
+ textureNode->setRect(toQt(quad->rect));
+ textureNode->setFiltering(QSGTexture::Linear);
+ currentLayerChain->appendChildNode(textureNode);
+ }
+ }
+
+ content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
+ base::Bind(&RenderWidgetHostViewQt::releaseAndAckDelegatedFrame, m_view->AsWeakPtr()));
+
+ return frameNode;
+}
+#endif // QT_VERSION
+
void RenderWidgetHostViewQtDelegate::fetchBackingStore()
{
Q_ASSERT(m_view);
diff --git a/lib/render_widget_host_view_qt_delegate.h b/lib/render_widget_host_view_qt_delegate.h
index c73aa9aec..f84d1a085 100644
--- a/lib/render_widget_host_view_qt_delegate.h
+++ b/lib/render_widget_host_view_qt_delegate.h
@@ -42,6 +42,15 @@
#ifndef RENDER_WIDGET_HOST_VIEW_QT_DELEGATE_H
#define RENDER_WIDGET_HOST_VIEW_QT_DELEGATE_H
+// On Mac we need to reset this define in order to prevent definition
+// of "check" macros etc. The "check" macro collides with a member function name in QtQuick.
+// See AssertMacros.h in the Mac SDK.
+#include <QtGlobal> // We need this for the Q_OS_MAC define.
+#if defined(Q_OS_MAC)
+#undef __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES
+#define __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES 0
+#endif
+
#include "qtwebengineglobal.h"
#include <QRect>
@@ -54,6 +63,8 @@ QT_BEGIN_NAMESPACE
class QCursor;
class QEvent;
class QPainter;
+class QQuickWindow;
+class QSGNode;
class QWindow;
QT_END_NAMESPACE
@@ -80,6 +91,9 @@ public:
protected:
RenderWidgetHostViewQtDelegate();
void paint(QPainter*, const QRectF& boundingRect);
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 2, 0))
+ QSGNode *updatePaintNode(QSGNode *, QQuickWindow *);
+#endif
void fetchBackingStore();
void notifyResize();
bool forwardEvent(QEvent*);
diff --git a/lib/type_conversion.h b/lib/type_conversion.h
index 51a543f73..2b7dee25b 100644
--- a/lib/type_conversion.h
+++ b/lib/type_conversion.h
@@ -42,9 +42,13 @@
#ifndef TYPE_CONVERSION_H
#define TYPE_CONVERSION_H
+#include <QMatrix4x4>
+#include <QRect>
#include <QString>
#include <QUrl>
#include "base/files/file_path.h"
+#include "third_party/skia/include/utils/SkMatrix44.h"
+#include "ui/gfx/rect.h"
#include "url/gurl.h"
inline QString toQt(const string16 &string)
@@ -62,6 +66,25 @@ inline GURL toGurl(const QUrl& url)
return GURL(url.toString().toStdString());
}
+inline QRect toQt(const gfx::Rect &rect)
+{
+ return QRect(rect.x(), rect.y(), rect.width(), rect.height());
+}
+
+inline QSize toQt(const gfx::Size &size)
+{
+ return QSize(size.width(), size.height());
+}
+
+inline QMatrix4x4 toQt(const SkMatrix44 &m)
+{
+ return QMatrix4x4(
+ m.get(0, 0), m.get(0, 1), m.get(0, 2), m.get(0, 3),
+ m.get(1, 0), m.get(1, 1), m.get(1, 2), m.get(1, 3),
+ m.get(2, 0), m.get(2, 1), m.get(2, 2), m.get(2, 3),
+ m.get(3, 0), m.get(3, 1), m.get(3, 2), m.get(3, 3));
+}
+
inline base::FilePath::StringType toFilePathString(const QString &str)
{
#if defined(OS_POSIX)
diff --git a/lib/web_contents_adapter_client.h b/lib/web_contents_adapter_client.h
index 8e92ead7c..d85c55173 100644
--- a/lib/web_contents_adapter_client.h
+++ b/lib/web_contents_adapter_client.h
@@ -73,6 +73,7 @@ class QWEBENGINE_EXPORT WebContentsAdapterClient {
public:
enum CompositingMode {
NoCompositing,
+ DelegatedCompositing,
ForcedGpuProcessCompositing
};
diff --git a/lib/web_contents_view_qt.cpp b/lib/web_contents_view_qt.cpp
index 8fc7f5b12..35445ccff 100644
--- a/lib/web_contents_view_qt.cpp
+++ b/lib/web_contents_view_qt.cpp
@@ -64,7 +64,9 @@ content::RenderWidgetHostView* WebContentsViewQt::CreateViewForWidget(content::R
RenderWidgetHostViewQt *view = new RenderWidgetHostViewQt(render_widget_host);
WebContentsAdapterClient::CompositingMode compositingMode = WebContentsAdapterClient::NoCompositing;
- if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kForceCompositingMode))
+ if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableDelegatedRenderer))
+ compositingMode = WebContentsAdapterClient::DelegatedCompositing;
+ else if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kForceCompositingMode))
compositingMode = WebContentsAdapterClient::ForcedGpuProcessCompositing;
Q_ASSERT(m_factoryClient);
diff --git a/patches/0001-Solve-conflicts-when-including-both-QtOpenGL-headers.patch b/patches/0001-Solve-conflicts-when-including-both-QtOpenGL-headers.patch
new file mode 100644
index 000000000..837870c24
--- /dev/null
+++ b/patches/0001-Solve-conflicts-when-including-both-QtOpenGL-headers.patch
@@ -0,0 +1,77 @@
+From 08012c5c84dc6f63c1c91d8035ec11b497e6e11c Mon Sep 17 00:00:00 2001
+From: Jocelyn Turcotte <jocelyn.turcotte@digia.com>
+Date: Fri, 6 Sep 2013 17:08:45 +0200
+Subject: [PATCH] Solve conflicts when including both QtOpenGL headers and
+ resource_provider.h
+
+If resource_provider.h is going to be used to integrate delegated frame
+to external compositors, it should avoid conflicting with the system's gl.h.
+
+Change-Id: Ie37d6cde263157e6717cc006a9896f0b9ebdaa5d
+Reviewed-by: Zeno Albisser <zeno.albisser@digia.com>
+---
+ cc/layers/texture_layer.cc | 1 +
+ cc/output/delegating_renderer.cc | 1 +
+ cc/quads/content_draw_quad_base.h | 1 -
+ cc/resources/resource_provider.h | 5 ++++-
+ 4 files changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/cc/layers/texture_layer.cc b/cc/layers/texture_layer.cc
+index 316042b..2325a80 100644
+--- a/cc/layers/texture_layer.cc
++++ b/cc/layers/texture_layer.cc
+@@ -10,6 +10,7 @@
+ #include "cc/layers/texture_layer_client.h"
+ #include "cc/layers/texture_layer_impl.h"
+ #include "cc/trees/layer_tree_host.h"
++#include "third_party/khronos/GLES2/gl2.h"
+ #include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
+
+ namespace cc {
+diff --git a/cc/output/delegating_renderer.cc b/cc/output/delegating_renderer.cc
+index bd1c5d1..0c3051c 100644
+--- a/cc/output/delegating_renderer.cc
++++ b/cc/output/delegating_renderer.cc
+@@ -23,6 +23,7 @@
+ #include "cc/quads/yuv_video_draw_quad.h"
+ #include "cc/resources/resource_provider.h"
+ #include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
++#include "third_party/khronos/GLES2/gl2.h"
+ #include "third_party/khronos/GLES2/gl2ext.h"
+
+ using WebKit::WebGraphicsContext3D;
+diff --git a/cc/quads/content_draw_quad_base.h b/cc/quads/content_draw_quad_base.h
+index cbf18ca..6229d61 100644
+--- a/cc/quads/content_draw_quad_base.h
++++ b/cc/quads/content_draw_quad_base.h
+@@ -8,7 +8,6 @@
+ #include "base/memory/scoped_ptr.h"
+ #include "cc/base/cc_export.h"
+ #include "cc/quads/draw_quad.h"
+-#include "third_party/khronos/GLES2/gl2.h"
+ #include "ui/gfx/point.h"
+ #include "ui/gfx/size.h"
+
+diff --git a/cc/resources/resource_provider.h b/cc/resources/resource_provider.h
+index b5dccc8..1d51a27 100644
+--- a/cc/resources/resource_provider.h
++++ b/cc/resources/resource_provider.h
+@@ -20,11 +20,14 @@
+ #include "cc/output/output_surface.h"
+ #include "cc/resources/texture_mailbox.h"
+ #include "cc/resources/transferable_resource.h"
+-#include "third_party/khronos/GLES2/gl2.h"
+ #include "third_party/skia/include/core/SkBitmap.h"
+ #include "third_party/skia/include/core/SkCanvas.h"
+ #include "ui/gfx/size.h"
+
++// A correct fix would be not to use GL types in this interal API file.
++typedef unsigned int GLenum;
++typedef int GLint;
++
+ namespace WebKit { class WebGraphicsContext3D; }
+
+ namespace gfx {
+--
+1.8.4
+
diff --git a/patches/patch-chromium.sh b/patches/patch-chromium.sh
index 3a9e9278e..c917f87f5 100755
--- a/patches/patch-chromium.sh
+++ b/patches/patch-chromium.sh
@@ -65,6 +65,7 @@ git am $PATCH_DIR/0001-Mac-Do-not-modify-the-child-path.patch
git am $PATCH_DIR/0001-Do-not-warn-for-header-hygiene.patch
git am $PATCH_DIR/0001-Build-files-necessary-for-touch-and-gestures.patch
git am $PATCH_DIR/0001-remove-Wno-deprecated-register-from-common.gypi.patch
+git am $PATCH_DIR/0001-Solve-conflicts-when-including-both-QtOpenGL-headers.patch
cd $CHROMIUM_SRC_DIR/third_party/WebKit
echo "Entering $PWD"