diff options
author | Thomas Hartmann <thomas.hartmann@qt.io> | 2020-10-05 21:50:35 +0200 |
---|---|---|
committer | Thomas Hartmann <thomas.hartmann@qt.io> | 2020-10-09 15:13:39 +0000 |
commit | 29c833d54f93bc3443e055d2f958589f03463057 (patch) | |
tree | f8fae14c6aa49686f321b4204db7069f0649373f /share/qtcreator/qml/qmlpuppet | |
parent | 2fe99cef9fc6b43203c65d4b753366accd7b7b51 (diff) |
QmlDesigner: Implement different render path for Qt 6
When building with Qt 6 or if qmlpuppet_unifiedRenderPath is set
in the environment we switch to a different render path.
In this case we use QQuickWindow::grabWindow() and render the root item.
No composition is done in the Qt Creator process anymore.
This is a similar approach we already take for the 3D view.
Performance is acceptable and we fix rendering issues related to
effects and layers.
Change-Id: Ic963eca047e0bf16ca3a099ec94658ae2af0fb63
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
Diffstat (limited to 'share/qtcreator/qml/qmlpuppet')
11 files changed, 155 insertions, 24 deletions
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.cpp index 45d5fce845..183f036bf7 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.cpp @@ -72,22 +72,23 @@ #include <requestmodelnodepreviewimagecommand.h> #include <changelanguagecommand.h> +#include <designersupportdelegate.h> +#include <QAbstractAnimation> #include <QDebug> -#include <QQmlEngine> -#include <QQmlApplicationEngine> -#include <QFileSystemWatcher> -#include <QUrl> -#include <QSet> #include <QDir> -#include <QVariant> +#include <QFileSystemWatcher> #include <QMetaType> +#include <QMutableVectorIterator> +#include <QQmlApplicationEngine> #include <QQmlComponent> #include <QQmlContext> -#include <qqmllist.h> -#include <QAbstractAnimation> +#include <QQmlEngine> +#include <QQuickItemGrabResult> #include <QQuickView> #include <QSet> -#include <designersupportdelegate.h> +#include <QUrl> +#include <QVariant> +#include <qqmllist.h> #include <algorithm> @@ -1461,4 +1462,19 @@ void NodeInstanceServer::disableTimer() m_timerMode = TimerMode::DisableTimer; } +void NodeInstanceServer::sheduleRootItemRender() +{ + QSharedPointer<QQuickItemGrabResult> result = m_rootNodeInstance.createGrabResult(); + qint32 instanceId = m_rootNodeInstance.instanceId(); + + if (result) { + connect(result.data(), &QQuickItemGrabResult::ready, [this, result, instanceId] { + QVector<ImageContainer> imageVector; + ImageContainer container(instanceId, result->image(), instanceId); + imageVector.append(container); + nodeInstanceClient()->pixmapChanged(PixmapChangedCommand(imageVector)); + }); + } +} + } // namespace QmlDesigner diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.h index bd6349d29a..d5726a31f6 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.h +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.h @@ -241,6 +241,8 @@ protected: ComponentCompletedCommand createComponentCompletedCommand(const QList<ServerNodeInstance> &instanceList); ChangeSelectionCommand createChangeSelectionCommand(const QList<ServerNodeInstance> &instanceList); + void sheduleRootItemRender(); + void addChangedProperty(const InstancePropertyPair &property); virtual void startRenderTimer(); diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/objectnodeinstance.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/objectnodeinstance.cpp index 5991e2b28e..d69846d400 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/objectnodeinstance.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/objectnodeinstance.cpp @@ -908,6 +908,11 @@ QImage ObjectNodeInstance::renderPreviewImage(const QSize & /*previewImageSize*/ return QImage(); } +QSharedPointer<QQuickItemGrabResult> ObjectNodeInstance::createGrabResult() const +{ + return {}; +} + QObject *ObjectNodeInstance::parent() const { if (!object()) diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/objectnodeinstance.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/objectnodeinstance.h index 3026ffefce..29e7dc640b 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/objectnodeinstance.h +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/objectnodeinstance.h @@ -84,6 +84,8 @@ public: virtual QImage renderImage() const; virtual QImage renderPreviewImage(const QSize &previewImageSize) const; + virtual QSharedPointer<QQuickItemGrabResult> createGrabResult() const; + virtual QObject *parent() const; Pointer parentInstance() const; diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceclientproxy.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceclientproxy.cpp index defbf5614a..64b6eb409c 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceclientproxy.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceclientproxy.cpp @@ -33,6 +33,7 @@ #include "qt5previewnodeinstanceserver.h" #include "qt5rendernodeinstanceserver.h" #include "qt5testnodeinstanceserver.h" +#include "quickitemnodeinstance.h" #include <designersupportdelegate.h> @@ -56,7 +57,19 @@ Qt5NodeInstanceClientProxy::Qt5NodeInstanceClientProxy(QObject *parent) : NodeInstanceClientProxy(parent) { prioritizeDown(); - DesignerSupport::activateDesignerWindowManager(); +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) + const bool qt6 = false; +#else + const bool qt6 = true; +#endif + + const bool unifiedRenderPath = qt6 || qEnvironmentVariableIsSet("QMLPUPPET_UNIFIED_RENDER_PATH"); + + if (unifiedRenderPath) + Internal::QuickItemNodeInstance::enableUnifiedRenderPath(true); + else + DesignerSupport::activateDesignerWindowManager(); + if (QCoreApplication::arguments().at(1) == QLatin1String("--readcapturedstream")) { qputenv("DESIGNER_DONT_USE_SHARED_MEMORY", "1"); setNodeInstanceServer(std::make_unique<Qt5TestNodeInstanceServer>(this)); diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.cpp index 8a4b086aa5..c2015299c5 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.cpp @@ -64,6 +64,8 @@ void Qt5NodeInstanceServer::initializeView() m_quickView = new QQuickView; +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) + /* enables grab window without show */ QSurfaceFormat surfaceFormat = m_quickView->requestedFormat(); surfaceFormat.setVersion(4, 1); surfaceFormat.setProfile(QSurfaceFormat::CoreProfile); @@ -72,6 +74,7 @@ void Qt5NodeInstanceServer::initializeView() m_quickView->setFormat(surfaceFormat); DesignerSupport::createOpenGLContext(m_quickView.data()); +#endif if (qEnvironmentVariableIsSet("QML_FILE_SELECTORS")) { QQmlFileSelector *fileSelector = new QQmlFileSelector(engine(), engine()); diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5rendernodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5rendernodeinstanceserver.cpp index 08b20ccd22..fd3446f396 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5rendernodeinstanceserver.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5rendernodeinstanceserver.cpp @@ -87,17 +87,27 @@ void Qt5RenderNodeInstanceServer::collectItemChangesAndSendChangeCommands() if (ancestorInstance.isValid()) m_dirtyInstanceSet.insert(ancestorInstance); } - DesignerSupport::updateDirtyNode(item); + Internal::QuickItemNodeInstance::updateDirtyNode(item); } } clearChangedPropertyList(); - if (!m_dirtyInstanceSet.isEmpty()) { - nodeInstanceClient()->pixmapChanged(createPixmapChangedCommand(QtHelpers::toList(m_dirtyInstanceSet))); - m_dirtyInstanceSet.clear(); + if (Internal::QuickItemNodeInstance::unifiedRenderPath()) { + /* QQuickItem::grabToImage render path */ + /* TODO implement QQuickItem::grabToImage based rendering */ + /* sheduleRootItemRender(); */ + nodeInstanceClient()->pixmapChanged(createPixmapChangedCommand({rootNodeInstance()})); + } else { + if (!m_dirtyInstanceSet.isEmpty()) { + nodeInstanceClient()->pixmapChanged( + createPixmapChangedCommand(QtHelpers::toList(m_dirtyInstanceSet))); + m_dirtyInstanceSet.clear(); + } } + m_dirtyInstanceSet.clear(); + resetAllItems(); slowDownRenderTimer(); @@ -137,6 +147,11 @@ void Qt5RenderNodeInstanceServer::createScene(const CreateSceneCommand &command) } nodeInstanceClient()->pixmapChanged(createPixmapChangedCommand(instanceList)); + +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) +#else + quickView()->show(); +#endif } void Qt5RenderNodeInstanceServer::clearScene(const ClearSceneCommand &command) diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quickitemnodeinstance.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quickitemnodeinstance.cpp index 6e67d58b92..bfaff0eea8 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quickitemnodeinstance.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quickitemnodeinstance.cpp @@ -41,6 +41,7 @@ namespace QmlDesigner { namespace Internal { bool QuickItemNodeInstance::s_createEffectItem = false; +bool QuickItemNodeInstance::s_unifiedRenderPath = false; QuickItemNodeInstance::QuickItemNodeInstance(QQuickItem *item) : ObjectNodeInstance(item), @@ -58,7 +59,7 @@ QuickItemNodeInstance::QuickItemNodeInstance(QQuickItem *item) QuickItemNodeInstance::~QuickItemNodeInstance() { - if (quickItem()) + if (quickItem() && checkIfRefFromEffect(instanceId())) designerSupport()->derefFromEffectItem(quickItem()); } @@ -156,6 +157,19 @@ void QuickItemNodeInstance::createEffectItem(bool createEffectItem) s_createEffectItem = createEffectItem; } +void QuickItemNodeInstance::enableUnifiedRenderPath(bool unifiedRenderPath) +{ + s_unifiedRenderPath = unifiedRenderPath; +} + +bool QuickItemNodeInstance::checkIfRefFromEffect(qint32 id) +{ + if (s_unifiedRenderPath) + return false; + + return (s_createEffectItem || id == 0); +} + void QuickItemNodeInstance::initialize(const ObjectNodeInstance::Pointer &objectNodeInstance, InstanceContainer::NodeFlags flags) { @@ -166,10 +180,10 @@ void QuickItemNodeInstance::initialize(const ObjectNodeInstance::Pointer &object quickItem()->setParentItem(qobject_cast<QQuickItem*>(nodeInstanceServer()->quickView()->rootObject())); } - if (quickItem()->window()) { - if (s_createEffectItem || instanceId() == 0) - designerSupport()->refFromEffectItem(quickItem(), - !flags.testFlag(InstanceContainer::ParentTakesOverRendering)); + if (quickItem()->window() && checkIfRefFromEffect(instanceId())) { + designerSupport()->refFromEffectItem(quickItem(), + !flags.testFlag( + InstanceContainer::ParentTakesOverRendering)); } ObjectNodeInstance::initialize(objectNodeInstance, flags); @@ -246,6 +260,20 @@ QStringList QuickItemNodeInstance::allStates() const return list; } +void QuickItemNodeInstance::updateDirtyNode(QQuickItem *item) +{ + if (s_unifiedRenderPath) { + item->update(); + return; + } + DesignerSupport::updateDirtyNode(item); +} + +bool QuickItemNodeInstance::unifiedRenderPath() +{ + return s_unifiedRenderPath; +} + QRectF QuickItemNodeInstance::contentItemBoundingBox() const { if (contentItem()) { @@ -378,6 +406,9 @@ double QuickItemNodeInstance::y() const QImage QuickItemNodeInstance::renderImage() const { + if (s_unifiedRenderPath && !isRootNodeInstance()) + return {}; + updateDirtyNodesRecursive(quickItem()); QRectF renderBoundingRect = boundingRect(); @@ -390,7 +421,16 @@ QImage QuickItemNodeInstance::renderImage() const nodeInstanceServer()->quickView()->beforeSynchronizing(); nodeInstanceServer()->quickView()->beforeRendering(); - QImage renderImage = designerSupport()->renderImageForItem(quickItem(), renderBoundingRect, size); + QImage renderImage; + +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) + if (s_unifiedRenderPath) + renderImage = nodeInstanceServer()->quickView()->grabWindow(); + else + renderImage = designerSupport()->renderImageForItem(quickItem(), renderBoundingRect, size); +#else + renderImage = nodeInstanceServer()->quickView()->grabWindow(); +#endif nodeInstanceServer()->quickView()->afterRendering(); @@ -411,7 +451,20 @@ QImage QuickItemNodeInstance::renderPreviewImage(const QSize &previewImageSize) nodeInstanceServer()->quickView()->beforeSynchronizing(); nodeInstanceServer()->quickView()->beforeRendering(); - QImage image = designerSupport()->renderImageForItem(quickItem(), previewItemBoundingRect, size); + QImage image; +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) + if (s_unifiedRenderPath) + image = nodeInstanceServer()->quickView()->grabWindow(); + else + image = designerSupport()->renderImageForItem(quickItem(), + previewItemBoundingRect, + size); + +#else + image = nodeInstanceServer()->quickView()->grabWindow(); +#endif + + image = image.scaledToWidth(size.width()); nodeInstanceServer()->quickView()->afterRendering(); @@ -426,6 +479,11 @@ QImage QuickItemNodeInstance::renderPreviewImage(const QSize &previewImageSize) return QImage(); } +QSharedPointer<QQuickItemGrabResult> QuickItemNodeInstance::createGrabResult() const +{ + return quickItem()->grabToImage(size().toSize()); +} + void QuickItemNodeInstance::updateAllDirtyNodesRecursive() { updateAllDirtyNodesRecursive(quickItem()); @@ -490,10 +548,11 @@ void QuickItemNodeInstance::updateDirtyNodesRecursive(QQuickItem *parentItem) co void QuickItemNodeInstance::updateAllDirtyNodesRecursive(QQuickItem *parentItem) const { - foreach (QQuickItem *childItem, parentItem->childItems()) - updateAllDirtyNodesRecursive(childItem); + const QList<QQuickItem *> children = parentItem->childItems(); + for (QQuickItem *childItem : children) + updateAllDirtyNodesRecursive(childItem); - DesignerSupport::updateDirtyNode(parentItem); + updateDirtyNode(parentItem); } static inline bool isRectangleSane(const QRectF &rect) diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quickitemnodeinstance.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quickitemnodeinstance.h index f42e45a8ff..2c68fe7974 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quickitemnodeinstance.h +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quickitemnodeinstance.h @@ -45,6 +45,7 @@ public: static Pointer create(QObject *objectToBeWrapped); static void createEffectItem(bool createEffectItem); + static void enableUnifiedRenderPath(bool createEffectItem); void initialize(const ObjectNodeInstance::Pointer &objectNodeInstance, InstanceContainer::NodeFlags flags) override; @@ -70,6 +71,8 @@ public: QImage renderImage() const override; QImage renderPreviewImage(const QSize &previewImageSize) const override; + QSharedPointer<QQuickItemGrabResult> createGrabResult() const override; + void updateAllDirtyNodesRecursive() override; @@ -98,6 +101,9 @@ public: QList<QQuickItem*> allItemsRecursive() const override; QStringList allStates() const override; + static void updateDirtyNode(QQuickItem *item); + static bool unifiedRenderPath(); + protected: explicit QuickItemNodeInstance(QQuickItem*); QQuickItem *quickItem() const; @@ -118,6 +124,7 @@ protected: double x() const; double y() const; + bool checkIfRefFromEffect(qint32 id); private: //variables QPointer<QQuickItem> m_contentItem; @@ -131,6 +138,7 @@ private: //variables double m_width; double m_height; static bool s_createEffectItem; + static bool s_unifiedRenderPath; }; } // namespace Internal diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/servernodeinstance.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/servernodeinstance.cpp index 69c854f3e9..511a89b62b 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/servernodeinstance.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/servernodeinstance.cpp @@ -120,6 +120,11 @@ QImage ServerNodeInstance::renderPreviewImage(const QSize &previewImageSize) con return m_nodeInstance->renderPreviewImage(previewImageSize); } +QSharedPointer<QQuickItemGrabResult> ServerNodeInstance::createGrabResult() const +{ + return m_nodeInstance->createGrabResult(); +} + bool ServerNodeInstance::isRootNodeInstance() const { return isValid() && m_nodeInstance->isRootNodeInstance(); diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/servernodeinstance.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/servernodeinstance.h index 975d0e8c37..9150b2bd4e 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/servernodeinstance.h +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/servernodeinstance.h @@ -40,6 +40,7 @@ class QGraphicsItem; class QGraphicsTransform; #if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)) class QQuickItem; +class QQuickItemGrabResult; #endif QT_END_NAMESPACE @@ -102,6 +103,8 @@ public: QImage renderImage() const; QImage renderPreviewImage(const QSize &previewImageSize) const; + QSharedPointer<QQuickItemGrabResult> createGrabResult() const; + ServerNodeInstance parent() const; bool hasParent() const; |