QmdDesigner: Enable rendering single items again for render puppet

Change the form editor rendering to be done by item basis instead of
just rendering the entire scene (unified rendering).

Fixes: QDS-2933
Change-Id: I999cbc834791bc6e96334eab8273d97e4f58975f
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
This commit is contained in:
Miikka Heikkinen
2021-08-25 14:50:18 +03:00
parent ea2b4872a9
commit 8aad2c803a
8 changed files with 114 additions and 15 deletions

View File

@@ -218,6 +218,7 @@ public:
virtual void handleInstanceHidden(const ServerNodeInstance &instance, bool enable, bool checkAncestors); virtual void handleInstanceHidden(const ServerNodeInstance &instance, bool enable, bool checkAncestors);
virtual QImage grabWindow() = 0; virtual QImage grabWindow() = 0;
virtual QImage grabItem(QQuickItem *item) = 0;
public slots: public slots:
void refreshLocalFileProperty(const QString &path); void refreshLocalFileProperty(const QString &path);

View File

@@ -761,7 +761,8 @@ void Qt5InformationNodeInstanceServer::updateNodesRecursive(QQuickItem *item)
const auto childItems = item->childItems(); const auto childItems = item->childItems();
for (QQuickItem *childItem : childItems) for (QQuickItem *childItem : childItems)
updateNodesRecursive(childItem); updateNodesRecursive(childItem);
if (Internal::QuickItemNodeInstance::unifiedRenderPath()) {
if (Internal::QuickItemNodeInstance::unifiedRenderPathOrQt6()) {
if (item->flags() & QQuickItem::ItemHasContents) if (item->flags() & QQuickItem::ItemHasContents)
item->update(); item->update();
} else { } else {
@@ -773,7 +774,7 @@ QQuickItem *Qt5InformationNodeInstanceServer::getContentItemForRendering(QQuickI
{ {
QQuickItem *contentItem = QQmlProperty::read(rootItem, "contentItem").value<QQuickItem *>(); QQuickItem *contentItem = QQmlProperty::read(rootItem, "contentItem").value<QQuickItem *>();
if (contentItem) { if (contentItem) {
if (!Internal::QuickItemNodeInstance::unifiedRenderPath()) if (!Internal::QuickItemNodeInstance::unifiedRenderPathOrQt6())
designerSupport()->refFromEffectItem(contentItem, false); designerSupport()->refFromEffectItem(contentItem, false);
QmlDesigner::Internal::QmlPrivateGate::disableNativeTextRendering(contentItem); QmlDesigner::Internal::QmlPrivateGate::disableNativeTextRendering(contentItem);
} }
@@ -899,7 +900,7 @@ void Qt5InformationNodeInstanceServer::doRenderModelNode3DImageView()
instanceObj = instance.internalObject(); instanceObj = instance.internalObject();
} }
QSize renderSize = m_modelNodePreviewImageCommand.size(); QSize renderSize = m_modelNodePreviewImageCommand.size();
if (Internal::QuickItemNodeInstance::unifiedRenderPath()) { if (Internal::QuickItemNodeInstance::unifiedRenderPathOrQt6()) {
// Requested size is already adjusted for target pixel ratio, so we have to adjust // Requested size is already adjusted for target pixel ratio, so we have to adjust
// back if ratio is not default for our window. // back if ratio is not default for our window.
double ratio = m_modelNode3DImageViewData.window->devicePixelRatio(); double ratio = m_modelNode3DImageViewData.window->devicePixelRatio();
@@ -1106,7 +1107,7 @@ Qt5InformationNodeInstanceServer::~Qt5InformationNodeInstanceServer()
if (m_editView3DData.rootItem) if (m_editView3DData.rootItem)
QMetaObject::invokeMethod(m_editView3DData.rootItem, "aboutToShutDown", Qt::DirectConnection); QMetaObject::invokeMethod(m_editView3DData.rootItem, "aboutToShutDown", Qt::DirectConnection);
if (!Internal::QuickItemNodeInstance::unifiedRenderPath()) { if (!Internal::QuickItemNodeInstance::unifiedRenderPathOrQt6()) {
if (m_editView3DData.contentItem) if (m_editView3DData.contentItem)
designerSupport()->derefFromEffectItem(m_editView3DData.contentItem); designerSupport()->derefFromEffectItem(m_editView3DData.contentItem);
if (m_modelNode3DImageViewData.contentItem) if (m_modelNode3DImageViewData.contentItem)

View File

@@ -64,11 +64,11 @@ Qt5NodeInstanceClientProxy::Qt5NodeInstanceClientProxy(QObject *parent) :
const bool qt6 = true; const bool qt6 = true;
#endif #endif
const bool unifiedRenderPath = qt6 || qEnvironmentVariableIsSet("QMLPUPPET_UNIFIED_RENDER_PATH"); const bool unifiedRenderPath = qEnvironmentVariableIsSet("QMLPUPPET_UNIFIED_RENDER_PATH");
if (unifiedRenderPath) if (unifiedRenderPath)
Internal::QuickItemNodeInstance::enableUnifiedRenderPath(true); Internal::QuickItemNodeInstance::enableUnifiedRenderPath(true);
else else if (!qt6)
DesignerSupport::activateDesignerWindowManager(); DesignerSupport::activateDesignerWindowManager();
if (QCoreApplication::arguments().at(1) == QLatin1String("--readcapturedstream")) { if (QCoreApplication::arguments().at(1) == QLatin1String("--readcapturedstream")) {

View File

@@ -44,10 +44,13 @@
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
#include <QtGui/private/qrhi_p.h> #include <QtGui/private/qrhi_p.h>
#include <QtQuick/private/qquickwindow_p.h> #include <QtQuick/private/qquickitem_p.h>
#include <QtQuick/private/qsgrenderer_p.h>
#include <QtQuick/private/qquickrendercontrol_p.h> #include <QtQuick/private/qquickrendercontrol_p.h>
#include <QtQuick/private/qquickrendertarget_p.h> #include <QtQuick/private/qquickrendertarget_p.h>
#include <QtQuick/private/qquickwindow_p.h>
#include <QtQuick/private/qsgcontext_p.h>
#include <QtQuick/private/qsgrenderer_p.h>
#include <QtQuick/private/qsgrhilayer_p.h>
#endif #endif
namespace QmlDesigner { namespace QmlDesigner {
@@ -332,6 +335,80 @@ QImage Qt5NodeInstanceServer::grabWindow()
return {}; return {};
} }
QImage Qt5NodeInstanceServer::grabItem(QQuickItem *item)
{
QImage renderImage;
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
if (!m_viewData.rootItem || (m_viewData.bufferDirty && !initRhi(m_viewData)))
return {};
QQuickItemPrivate *pItem = QQuickItemPrivate::get(item);
pItem->refFromEffectItem(false);
ServerNodeInstance instance = instanceForObject(item);
const auto childInstances = instance.childItems();
// Hide immediate children that have instances and are QQuickItems so we get only
// the parent item's content, as compositing is handled on creator side.
for (const auto &childInstance : childInstances) {
QQuickItem *childItem = qobject_cast<QQuickItem *>(childInstance.internalObject());
if (childItem) {
QQuickItemPrivate *pChild = QQuickItemPrivate::get(childItem);
pChild->refFromEffectItem(true);
}
}
m_viewData.renderControl->polishItems();
m_viewData.renderControl->beginFrame();
m_viewData.renderControl->sync();
// Connection to afterRendering is necessary, as this needs to be done before
// call to endNextRhiFrame which happens inside QQuickRenderControl::render()
QMetaObject::Connection connection = QObject::connect(m_viewData.window.data(),
&QQuickWindow::afterRendering,
this, [&]() {
// To get only the single item, we need to make a layer out of it, which enables
// us to render it to a texture that we can grab to an image.
QSGRenderContext *rc = QQuickWindowPrivate::get(m_viewData.window.data())->context;
QSGLayer *layer = rc->sceneGraphContext()->createLayer(rc);
layer->setItem(pItem->itemNode());
QSizeF itemSize = QSizeF(item->width(), item->height());
layer->setRect(QRectF(0, itemSize.height(), itemSize.width(), -itemSize.height()));
const QSize minSize = rc->sceneGraphContext()->minimumFBOSize();
layer->setSize(QSize(qMax(minSize.width(), int(itemSize.width())),
qMax(minSize.height(), int(itemSize.height()))));
layer->scheduleUpdate();
if (layer->updateTexture())
renderImage = layer->toImage();
else
qWarning() << __FUNCTION__ << "Failed to update layer texture";
delete layer;
layer = nullptr;
});
m_viewData.renderControl->render();
QObject::disconnect(connection);
m_viewData.renderControl->endFrame();
// Restore visibility of immediate children that have instances and are QQuickItems
for (const auto &childInstance : childInstances) {
QQuickItem *childItem = qobject_cast<QQuickItem *>(childInstance.internalObject());
if (childItem) {
QQuickItemPrivate *pChild = QQuickItemPrivate::get(childItem);
pChild->derefFromEffectItem(true);
}
}
pItem->derefFromEffectItem(false);
#else
Q_UNUSED(item)
#endif
return renderImage;
}
void Qt5NodeInstanceServer::refreshBindings() void Qt5NodeInstanceServer::refreshBindings()
{ {
DesignerSupport::refreshExpressions(context()); DesignerSupport::refreshExpressions(context());

View File

@@ -69,6 +69,7 @@ public:
void reparentInstances(const ReparentInstancesCommand &command) override; void reparentInstances(const ReparentInstancesCommand &command) override;
QImage grabWindow() override; QImage grabWindow() override;
QImage grabItem(QQuickItem *item) override;
protected: protected:
void initializeView() override; void initializeView() override;

View File

@@ -102,9 +102,6 @@ void Qt5RenderNodeInstanceServer::collectItemChangesAndSendChangeCommands()
clearChangedPropertyList(); clearChangedPropertyList();
if (Internal::QuickItemNodeInstance::unifiedRenderPath()) { if (Internal::QuickItemNodeInstance::unifiedRenderPath()) {
/* QQuickItem::grabToImage render path */
/* TODO implement QQuickItem::grabToImage based rendering */
/* sheduleRootItemRender(); */
if (windowDirty) if (windowDirty)
nodeInstanceClient()->pixmapChanged(createPixmapChangedCommand({rootNodeInstance()})); nodeInstanceClient()->pixmapChanged(createPixmapChangedCommand({rootNodeInstance()}));
} else { } else {

View File

@@ -171,10 +171,15 @@ void QuickItemNodeInstance::enableUnifiedRenderPath(bool unifiedRenderPath)
bool QuickItemNodeInstance::checkIfRefFromEffect(qint32 id) bool QuickItemNodeInstance::checkIfRefFromEffect(qint32 id)
{ {
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
if (s_unifiedRenderPath) if (s_unifiedRenderPath)
return false; return false;
return (s_createEffectItem || id == 0); return (s_createEffectItem || id == 0);
#else
Q_UNUSED(id)
return false;
#endif
} }
void QuickItemNodeInstance::initialize(const ObjectNodeInstance::Pointer &objectNodeInstance, void QuickItemNodeInstance::initialize(const ObjectNodeInstance::Pointer &objectNodeInstance,
@@ -267,9 +272,13 @@ QStringList QuickItemNodeInstance::allStates() const
void QuickItemNodeInstance::updateDirtyNode(QQuickItem *item) void QuickItemNodeInstance::updateDirtyNode(QQuickItem *item)
{ {
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
if (s_unifiedRenderPath) if (s_unifiedRenderPath)
return; return;
DesignerSupport::updateDirtyNode(item); DesignerSupport::updateDirtyNode(item);
#else
Q_UNUSED(item)
#endif
} }
bool QuickItemNodeInstance::unifiedRenderPath() bool QuickItemNodeInstance::unifiedRenderPath()
@@ -277,6 +286,15 @@ bool QuickItemNodeInstance::unifiedRenderPath()
return s_unifiedRenderPath; return s_unifiedRenderPath;
} }
bool QuickItemNodeInstance::unifiedRenderPathOrQt6()
{
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
return true;
#else
return s_unifiedRenderPath;
#endif
}
QRectF QuickItemNodeInstance::contentItemBoundingBox() const QRectF QuickItemNodeInstance::contentItemBoundingBox() const
{ {
if (contentItem()) { if (contentItem()) {
@@ -415,16 +433,15 @@ QImage QuickItemNodeInstance::renderImage() const
updateDirtyNodesRecursive(quickItem()); updateDirtyNodesRecursive(quickItem());
QRectF renderBoundingRect = boundingRect(); QRectF renderBoundingRect = boundingRect();
QImage renderImage;
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QSize size = renderBoundingRect.size().toSize(); QSize size = renderBoundingRect.size().toSize();
static double devicePixelRatio = qgetenv("FORMEDITOR_DEVICE_PIXEL_RATIO").toDouble(); static double devicePixelRatio = qgetenv("FORMEDITOR_DEVICE_PIXEL_RATIO").toDouble();
if (size.width() * size.height() > 4000 * 4000) if (size.width() * size.height() > 4000 * 4000)
size = QSize(0,0); size = QSize(0,0);
size *= devicePixelRatio; size *= devicePixelRatio;
QImage renderImage;
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
if (s_unifiedRenderPath) { if (s_unifiedRenderPath) {
renderImage = nodeInstanceServer()->quickWindow()->grabWindow(); renderImage = nodeInstanceServer()->quickWindow()->grabWindow();
} else { } else {
@@ -438,8 +455,12 @@ QImage QuickItemNodeInstance::renderImage() const
} }
renderImage.setDevicePixelRatio(devicePixelRatio); renderImage.setDevicePixelRatio(devicePixelRatio);
#else #else
if (s_unifiedRenderPath)
renderImage = nodeInstanceServer()->grabWindow(); renderImage = nodeInstanceServer()->grabWindow();
else
renderImage = nodeInstanceServer()->grabItem(quickItem());
renderImage = renderImage.copy(renderBoundingRect.toRect()); renderImage = renderImage.copy(renderBoundingRect.toRect());
/* When grabbing an offscren window the device pixel ratio is 1 */ /* When grabbing an offscren window the device pixel ratio is 1 */
renderImage.setDevicePixelRatio(1); renderImage.setDevicePixelRatio(1);
#endif #endif

View File

@@ -104,6 +104,7 @@ public:
static void updateDirtyNode(QQuickItem *item); static void updateDirtyNode(QQuickItem *item);
static bool unifiedRenderPath(); static bool unifiedRenderPath();
static bool unifiedRenderPathOrQt6();
protected: protected:
explicit QuickItemNodeInstance(QQuickItem*); explicit QuickItemNodeInstance(QQuickItem*);