summaryrefslogtreecommitdiffstats
path: root/src/webenginewidgets
diff options
context:
space:
mode:
authorJüri Valdmann <juri.valdmann@qt.io>2020-06-17 10:05:32 +0200
committerJüri Valdmann <juri.valdmann@qt.io>2020-07-06 16:30:11 +0200
commit08203aef3ab102bfb91928f37846b2b19a4540ee (patch)
treeb5b6be71629475e96c509e11e2b67644698588a3 /src/webenginewidgets
parent45e3909e0fb628b6283fef8ea94861b7ca87093b (diff)
Move scenegraph handling out of core
Replace Display{Producer,Consumer,FrameSink} with the new classes Compositor and Compositor::Observer. The Compositor subclasses are implemented by the OutputSurfaces, replacing DisplayProducer in this role. Unlike DisplayProducer, the new classes do not use QtQuick scenegraph types, but rather give access to the software QImage or OpenGL texture directly. The connection to the "other half" is simplified by replacing DisplayConsumer with Compositor::Observer, which is no longer implemented by RenderWidgetHostViewQt, but directly by its delegates in the quick and widgets libraries. RenderWidgetHostViewQt now only provides the delegate with a Compositor::Id which is used to connect the corresponding Compositor and Observer. The delegates are responsible for generating QtQuick scenegraph nodes from the information provided by the Compositor subclasses. Behavior with software and old OpenGL scenegraph backends is unchanged: both continue to work. As for the RHI scenegraph backend, the code here is correct but nonetheless not working: changes are needed in qtbase to make RHI use the global share context for its OpenGL context. Fixes: QTBUG-78682 Change-Id: I837da8860a18ec366ed33f6ecc44c147245e1101 Reviewed-by: Michal Klocek <michal.klocek@qt.io>
Diffstat (limited to 'src/webenginewidgets')
-rw-r--r--src/webenginewidgets/api/qwebenginepage_p.h2
-rw-r--r--src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp100
-rw-r--r--src/webenginewidgets/render_widget_host_view_qt_delegate_widget.h5
3 files changed, 72 insertions, 35 deletions
diff --git a/src/webenginewidgets/api/qwebenginepage_p.h b/src/webenginewidgets/api/qwebenginepage_p.h
index 3ddf4b3d6..847684198 100644
--- a/src/webenginewidgets/api/qwebenginepage_p.h
+++ b/src/webenginewidgets/api/qwebenginepage_p.h
@@ -106,7 +106,7 @@ public:
QColor backgroundColor() const override;
void loadStarted(const QUrl &provisionalUrl, bool isErrorPage = false) override;
void loadCommitted() override { }
- void loadVisuallyCommitted() override { }
+ void didFirstVisuallyNonEmptyPaint() override { }
void loadFinished(bool success, const QUrl &url, bool isErrorPage = false, int errorCode = 0, const QString &errorDescription = QString()) override;
void focusContainer() override;
void unhandledKeyEvent(QKeyEvent *event) override;
diff --git a/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp b/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp
index a52fdef00..853553c47 100644
--- a/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp
+++ b/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp
@@ -56,14 +56,19 @@
namespace QtWebEngineCore {
-class RenderWidgetHostViewQuickItem : public QQuickItem {
+class RenderWidgetHostViewQuickItem : public QQuickItem, public Compositor::Observer
+{
public:
RenderWidgetHostViewQuickItem(RenderWidgetHostViewQtDelegateClient *client) : m_client(client)
{
setFlag(ItemHasContents, true);
// Mark that this item should receive focus when the parent QQuickWidget receives focus.
setFocus(true);
+
+ bind(client->compositorId());
}
+ ~RenderWidgetHostViewQuickItem() { unbind(); }
+
protected:
bool event(QEvent *event) override
{
@@ -84,17 +89,80 @@ protected:
{
m_client->forwardEvent(event);
}
- QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) override
+ void itemChange(ItemChange change, const ItemChangeData &value) override
{
- return m_client->updatePaintNode(oldNode);
+ QQuickItem::itemChange(change, value);
+ if (change == QQuickItem::ItemSceneChange) {
+ for (const QMetaObject::Connection &c : qAsConst(m_windowConnections))
+ disconnect(c);
+ m_windowConnections.clear();
+ if (value.window) {
+ m_windowConnections.append(connect(
+ value.window, &QQuickWindow::beforeRendering, this,
+ &RenderWidgetHostViewQuickItem::onBeforeRendering, Qt::DirectConnection));
+ }
+ }
}
+ QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) override
+ {
+ auto comp = compositor();
+ if (!comp)
+ return nullptr;
+
+ QQuickWindow *win = QQuickItem::window();
+
+ // Delete old node before swapFrame to decrement refcount of
+ // QImage in software mode.
+ delete oldNode;
+ QSGImageNode *node = win->createImageNode();
+ node->setOwnsTexture(true);
+
+ comp->swapFrame();
+
+ if (comp->type() == Compositor::Type::Software) {
+ QImage image = comp->image();
+ float pixPerDip = comp->devicePixelRatio();
+ QSizeF sizeInDips = QSizeF(image.size()) / pixPerDip;
+ node->setRect(QRectF(QPointF(0, 0), sizeInDips));
+ node->setTexture(win->createTextureFromImage(image));
+ } else if (comp->type() == Compositor::Type::OpenGL) {
+ QSize texSize = comp->textureSize();
+ float pixPerDip = comp->devicePixelRatio();
+ QSizeF sizeInDips = QSizeF(texSize) / pixPerDip;
+ node->setRect(QRectF(QPointF(0, 0), sizeInDips));
+ QQuickWindow::CreateTextureOptions texOpts;
+ if (comp->hasAlphaChannel())
+ texOpts.setFlag(QQuickWindow::TextureHasAlphaChannel);
+ int texId = comp->textureId();
+ node->setTexture(win->createTextureFromNativeObject(QQuickWindow::NativeObjectTexture,
+ texId, 0, texSize, texOpts));
+ node->setTextureCoordinatesTransform(QSGImageNode::MirrorVertically);
+ } else {
+ Q_UNREACHABLE();
+ }
+ return node;
+ }
+ void onBeforeRendering()
+ {
+ auto comp = compositor();
+ if (!comp || comp->type() != Compositor::Type::OpenGL)
+ return;
+ comp->waitForTexture();
+ }
QVariant inputMethodQuery(Qt::InputMethodQuery query) const override
{
return m_client->inputMethodQuery(query);
}
+ void readyToSwap() override
+ {
+ // Call update() on UI thread.
+ QMetaObject::invokeMethod(this, &QQuickItem::update, Qt::QueuedConnection);
+ }
+
private:
RenderWidgetHostViewQtDelegateClient *m_client;
+ QList<QMetaObject::Connection> m_windowConnections;
};
RenderWidgetHostViewQtDelegateWidget::RenderWidgetHostViewQtDelegateWidget(RenderWidgetHostViewQtDelegateClient *client, QWidget *parent)
@@ -293,32 +361,6 @@ QWindow* RenderWidgetHostViewQtDelegateWidget::window() const
return root ? root->windowHandle() : 0;
}
-QSGTexture *RenderWidgetHostViewQtDelegateWidget::createTextureFromImage(const QImage &image)
-{
- return quickWindow()->createTextureFromImage(image, QQuickWindow::TextureCanUseAtlas);
-}
-
-QSGLayer *RenderWidgetHostViewQtDelegateWidget::createLayer()
-{
- QSGRenderContext *renderContext = QQuickWindowPrivate::get(quickWindow())->context;
- return renderContext->sceneGraphContext()->createLayer(renderContext);
-}
-
-QSGImageNode *RenderWidgetHostViewQtDelegateWidget::createImageNode()
-{
- return quickWindow()->createImageNode();
-}
-
-QSGRectangleNode *RenderWidgetHostViewQtDelegateWidget::createRectangleNode()
-{
- return quickWindow()->createRectangleNode();
-}
-
-void RenderWidgetHostViewQtDelegateWidget::update()
-{
- m_rootItem->update();
-}
-
void RenderWidgetHostViewQtDelegateWidget::updateCursor(const QCursor &cursor)
{
QQuickWidget::setCursor(cursor);
diff --git a/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.h b/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.h
index 034fdd65c..57b272183 100644
--- a/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.h
+++ b/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.h
@@ -79,11 +79,6 @@ public:
void hide() override;
bool isVisible() const override;
QWindow* window() const override;
- QSGTexture *createTextureFromImage(const QImage &) override;
- QSGLayer *createLayer() override;
- QSGImageNode *createImageNode() override;
- QSGRectangleNode *createRectangleNode() override;
- void update() override;
void updateCursor(const QCursor &) override;
void resize(int width, int height) override;
void move(const QPoint &screenPos) override;