diff options
m--------- | 3rdparty | 0 | ||||
-rw-r--r-- | lib/lib.pro | 4 | ||||
-rw-r--r-- | lib/quick/qquickwebengineview.cpp | 12 | ||||
-rw-r--r-- | lib/quick/render_widget_host_view_qt_delegate_quick.cpp | 28 | ||||
-rw-r--r-- | lib/quick/render_widget_host_view_qt_delegate_quick.h | 23 | ||||
-rw-r--r-- | lib/render_widget_host_view_qt.cpp | 31 | ||||
-rw-r--r-- | lib/render_widget_host_view_qt.h | 10 | ||||
-rw-r--r-- | lib/render_widget_host_view_qt_delegate.cpp | 336 | ||||
-rw-r--r-- | lib/render_widget_host_view_qt_delegate.h | 14 | ||||
-rw-r--r-- | lib/type_conversion.h | 23 | ||||
-rw-r--r-- | lib/web_contents_adapter_client.h | 1 | ||||
-rw-r--r-- | lib/web_contents_view_qt.cpp | 4 | ||||
-rw-r--r-- | patches/0001-Solve-conflicts-when-including-both-QtOpenGL-headers.patch | 77 | ||||
-rwxr-xr-x | patches/patch-chromium.sh | 1 |
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" |