aboutsummaryrefslogtreecommitdiffstats
path: root/share/qtcreator/qml/qmlpuppet
diff options
context:
space:
mode:
authorThomas Hartmann <thomas.hartmann@qt.io>2020-10-05 21:50:35 +0200
committerThomas Hartmann <thomas.hartmann@qt.io>2020-10-09 15:13:39 +0000
commit29c833d54f93bc3443e055d2f958589f03463057 (patch)
treef8fae14c6aa49686f321b4204db7069f0649373f /share/qtcreator/qml/qmlpuppet
parent2fe99cef9fc6b43203c65d4b753366accd7b7b51 (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')
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.cpp34
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.h2
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/instances/objectnodeinstance.cpp5
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/instances/objectnodeinstance.h2
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceclientproxy.cpp15
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.cpp3
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5rendernodeinstanceserver.cpp23
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quickitemnodeinstance.cpp79
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quickitemnodeinstance.h8
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/instances/servernodeinstance.cpp5
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/instances/servernodeinstance.h3
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;