Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qquick3ditem2d.cpp
Go to the documentation of this file.
1// Copyright (C) 2020 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include <QtQuick3D/qquick3dobject.h>
5#include <QtQuick3D/private/qquick3ditem2d_p.h>
6
7#include <QtQuick/private/qquickitem_p.h>
8#include <QtQuick/private/qsgrenderer_p.h>
9#include <QtQuick/private/qquickwindow_p.h>
10
11#include <QtQuick3DRuntimeRender/private/qssgrenderitem2d_p.h>
12#include "qquick3dnode_p_p.h"
13
14#include <QtGui/rhi/qrhi.h>
15
17
18/*
19internal
20*/
21
24{
25 m_contentItem = new QQuickItem();
26 m_contentItem->setObjectName(QLatin1String("parent of ") + item->objectName()); // for debugging
27 // No size is set for m_contentItem. This is intentional, otherwise item2d anchoring breaks.
28 QQuickItemPrivate::get(m_contentItem)->ensureSubsceneDeliveryAgent();
30
33}
34
36{
37 delete m_contentItem;
38
39 // This is sketchy. Similarly to the problems QQuick3DTexture has with its
40 // QSGTexture, the same problems arise here with the QSGRenderer. The
41 // associated scenegraph resource must be destroyed on the render thread,
42 // if there is one. If the scenegraph gets invalidated, that's easy due to
43 // signals/slots, but there's no such signal if an object with Item2Ds in
44 // it gets dynamically destroyed.
45 // Here on the gui thread in this dtor there's no way to properly manage
46 // the QSG resource's releasing anymore. Rather, as QSGRenderer is a
47 // QObject, do a deleteLater(), which typically works, but is not a 100%
48 // guarantee that the object will get destroyed on the render thread
49 // eventually, since in theory it could happen that the render thread is
50 // not even running at this point anymore (if the window is closing / the
51 // app is shutting down) - although in practice that won't be an issue
52 // since that case is taken care of the sceneGraphInvalidated signal.
53 // So while unlikely, a leak may still occur under certain circumstances.
54 if (m_renderer)
55 m_renderer->deleteLater();
56}
57
59{
60 item->setParent(m_contentItem);
61 item->setParentItem(m_contentItem);
63 connect(item, &QQuickItem::enabledChanged, this, &QQuick3DItem2D::updatePicking);
64 connect(item, &QQuickItem::visibleChanged, this, &QQuick3DItem2D::updatePicking);
65 m_sourceItems.append(item);
66 update();
67}
69{
70 m_sourceItems.removeOne(item);
71 if (item)
73 if (m_sourceItems.isEmpty())
75 else
76 update();
77}
78
80{
81 return m_contentItem;
82}
83
88
89void QQuick3DItem2D::invalidated()
90{
91 // clean up the renderer
92 if (m_renderer) {
93 delete m_renderer;
94 m_renderer = nullptr;
95 }
96}
97
98void QQuick3DItem2D::updatePicking()
99{
100 m_pickingDirty = true;
101 update();
102}
103
105{
106 auto *sourceItemPrivate = QQuickItemPrivate::get(m_contentItem);
107 QQuickWindow *window = m_contentItem->window();
108
109 if (!window) {
110 const auto &manager = QQuick3DObjectPrivate::get(this)->sceneManager;
111 window = manager->window();
112 }
113
114 if (!node) {
115 markAllDirty();
116 node = new QSSGRenderItem2D();
117 }
118
120
121 auto itemNode = static_cast<QSSGRenderItem2D *>(node);
123
124 m_rootNode = sourceItemPrivate->rootNode();
125 if (!m_rootNode) {
126 return nullptr;
127 }
128
129 if (!m_renderer) {
131 connect(window, &QQuickWindow::sceneGraphInvalidated, this, &QQuick3DItem2D::invalidated, Qt::DirectConnection);
133
134 // item2D rendernode has its own render pass descriptor and it should
135 // be removed before deleting rhi context.
136 // Otherwise, rhi will complain about the unreleased resource.
137 connect(
138 m_renderer,
140 this,
141 [this]() {
142 auto itemNode = static_cast<QSSGRenderItem2D *>(QQuick3DObjectPrivate::get(this)->spatialNode);
143 if (itemNode) {
144 if (itemNode->m_rp) {
145 itemNode->m_rp->deleteLater();
146 itemNode->m_rp = nullptr;
147 }
148 }
149 },
151 }
152
153 {
154 // Block the sceneGraphChanged() signal. Calling nodeChanged() will emit the sceneGraphChanged()
155 // signal, which is connected to the update() slot to mark the object dirty, which could cause
156 // and constant update even if the 2D content doesn't change.
157 QSignalBlocker blocker(m_renderer);
158 m_renderer->setRootNode(m_rootNode);
159 m_rootNode->markDirty(QSGNode::DirtyForceUpdate); // Force matrix, clip and opacity update.
160 m_renderer->nodeChanged(m_rootNode, QSGNode::DirtyForceUpdate); // Force render list update.
161 }
162
163 if (m_pickingDirty) {
164 m_pickingDirty = false;
165 bool isPickable = false;
166 for (auto item : m_sourceItems) {
167 // Enable picking for Item2D if any of its child is visible and enabled.
168 if (item->isVisible() && item->isEnabled()) {
169 isPickable = true;
170 break;
171 }
172 }
173 itemNode->setState(QSSGRenderNode::LocalState::Pickable, isPickable);
174 }
175
176 itemNode->m_renderer = m_renderer;
177
178 return node;
179}
180
185
187{
188 const auto &manager = QQuick3DObjectPrivate::get(this)->sceneManager;
189 auto *sourcePrivate = QQuickItemPrivate::get(m_contentItem);
190 auto *window = manager->window();
191 if (m_window != window) {
192 update(); // Just schedule an upate immediately.
193 if (m_window) {
194 disconnect(m_window, SIGNAL(destroyed(QObject*)), this, SLOT(derefWindow(QObject*)));
195 sourcePrivate->derefWindow();
196 }
197 m_window = window;
198 sourcePrivate->refWindow(window);
199 connect(window, SIGNAL(destroyed(QObject*)), this, SLOT(derefWindow(QObject*)));
200 sourcePrivate->refFromEffectItem(true);
201 }
202}
203
205{
206 auto *itemPriv = QQuickItemPrivate::get(item);
207
208 if (win == itemPriv->window) {
209 itemPriv->window = nullptr;
210 itemPriv->windowRefCount = 0;
211
212 itemPriv->prevDirtyItem = nullptr;
213 itemPriv->nextDirtyItem = nullptr;
214 }
215
216 for (auto *child: itemPriv->childItems)
218}
219
220void QQuick3DItem2D::derefWindow(QObject *win)
221{
222 detachWindow(m_contentItem, win);
223}
224
bool isEnabled() const
Returns true if the item is enabled; otherwise, false is returned.
void setParentItem(QGraphicsItem *parent)
Sets this item's parent item to newParent.
bool isVisible() const
Returns true if the item is visible; otherwise, false is returned.
static void setObjectOwnership(QObject *, ObjectOwnership)
Sets the ownership of object.
static QObjectPrivate * get(QObject *o)
Definition qobject_p.h:150
\inmodule QtCore
Definition qobject.h:103
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2960
Q_WEAK_OVERLOAD void setObjectName(const QString &name)
Sets the object's name to name.
Definition qobject.h:127
void destroyed(QObject *=nullptr)
This signal is emitted immediately before the object obj is destroyed, after any instances of QPointe...
void deleteLater()
\threadsafe
Definition qobject.cpp:2435
QQuickItem * contentItem() const
void itemDestroyed(QQuickItem *item) override
void markAllDirty() override
void removeChildItem(QQuickItem *item)
void allChildrenRemoved()
void addChildItem(QQuickItem *item)
~QQuick3DItem2D() override
QQuick3DItem2D(QQuickItem *item, QQuick3DNode *parent=nullptr)
void preSync() override
QSSGRenderGraphObject * updateSpatialNode(QSSGRenderGraphObject *node) override
void markAllDirty() override
QSSGRenderGraphObject * updateSpatialNode(QSSGRenderGraphObject *node) override
static QQuick3DObjectPrivate * get(QQuick3DObject *item)
static QQuickItemPrivate * get(QQuickItem *item)
The QQuickItem class provides the most basic of all visual items in \l {Qt Quick}.
Definition qquickitem.h:63
void visibleChanged()
QQuickWindow * window() const
Returns the window in which this item is rendered.
void childrenChanged()
void enabledChanged()
\qmltype Window \instantiates QQuickWindow \inqmlmodule QtQuick
void sceneGraphInvalidated()
\qmlsignal QtQuick::Window::sceneGraphInitialized()
void deleteLater()
When called without a frame being recorded, this function is equivalent to deleting the object.
Definition qrhi.cpp:3545
void sceneGraphChanged()
This signal is emitted on the first modification of a node in the tree after the last scene render.
void setRootNode(QSGRootNode *node)
Sets the node as the root of the QSGNode scene that you want to render.
@ DirtyForceUpdate
Definition qsgnode.h:78
void markDirty(DirtyState bits)
Notifies all connected renderers that the node has dirty bits.
Definition qsgnode.cpp:624
virtual QSGRenderer * createRenderer(QSGRendererInterface::RenderMode renderMode=QSGRendererInterface::RenderMode2D)=0
void nodeChanged(QSGNode *node, QSGNode::DirtyState state) override
Updates internal data structures and emits the sceneGraphChanged() signal.
Exception-safe wrapper around QObject::blockSignals().
Definition qobject.h:483
QWidget * window() const
Returns the window for this widget, i.e.
Definition qwidget.cpp:4313
Combined button and popup list for selecting options.
@ DirectConnection
static void * context
#define SLOT(a)
Definition qobjectdefs.h:52
#define SIGNAL(a)
Definition qobjectdefs.h:53
static void detachWindow(QQuickItem *item, QObject *win)
QLatin1StringView QLatin1String
Definition qstringfwd.h:31
#define emit
QWidget * win
Definition settings.cpp:6
myObject disconnect()
[26]
QGraphicsItem * item
QLayoutItem * child
[0]
aWidget window() -> setWindowTitle("New Window Title")
[2]
QNetworkAccessManager manager
QRhiRenderPassDescriptor * m_rp
Definition moc.h:23