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
qsgabstractsoftwarerenderer.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
5
10
11#include <QtCore/QLoggingCategory>
12#include <QtGui/QWindow>
13#include <QtQuick/QSGSimpleRectNode>
14
15Q_LOGGING_CATEGORY(lc2DRender, "qt.scenegraph.softwarecontext.abstractrenderer")
16
18
21 , m_background(new QSGSimpleRectNode)
22 , m_nodeUpdater(new QSGSoftwareRenderableNodeUpdater(this))
23{
24 // Setup special background node
25 auto backgroundRenderable = new QSGSoftwareRenderableNode(QSGSoftwareRenderableNode::SimpleRect, m_background);
26 addNodeMapping(m_background, backgroundRenderable);
27}
28
30{
31 // Cleanup RenderableNodes
32 delete m_background;
33
34 qDeleteAll(m_nodes);
35
36 delete m_nodeUpdater;
37}
38
40{
41 return m_nodes.value(node, nullptr);
42}
43
44// Used by GammaRay
45const QVector<QSGSoftwareRenderableNode*> &QSGAbstractSoftwareRenderer::renderableNodes() const
46{
47 return m_renderableNodes;
48}
49
54
56{
57 m_renderableNodes.append(node);
58}
59
61{
63 nodeGeometryUpdated(node);
64 }
66 nodeMaterialUpdated(node);
67 }
69 nodeMatrixUpdated(node);
70 }
72 nodeAdded(node);
73 }
75 nodeRemoved(node);
76 }
78 nodeOpacityUpdated(node);
79 }
81 m_nodeUpdater->updateNodes(node);
82 }
84 m_nodeUpdater->updateNodes(node);
85 }
87}
88
90{
91 QRegion dirtyRegion;
92 // If there are no nodes, do nothing
93 if (m_renderableNodes.isEmpty())
94 return dirtyRegion;
95
96 auto iterator = m_renderableNodes.begin();
97 // First node is the background and needs to painted without blending
98 auto backgroundNode = *iterator;
99 dirtyRegion += backgroundNode->renderNode(painter, /*force opaque painting*/ true);
100 iterator++;
101
102 for (; iterator != m_renderableNodes.end(); ++iterator) {
103 auto node = *iterator;
104 dirtyRegion += node->renderNode(painter);
105 }
106
107 return dirtyRegion;
108}
109
111{
112 // Clear the previous renderlist
113 m_renderableNodes.clear();
114 // Add the background renderable (always first)
115 m_renderableNodes.append(renderableNode(m_background));
116 // Build the renderlist
118}
119
121{
122 // Iterate through the renderlist from front to back
123 // Objective is to update the dirty status and rects.
124 for (auto i = m_renderableNodes.rbegin(); i != m_renderableNodes.rend(); ++i) {
125 auto node = *i;
126 if (!m_dirtyRegion.isEmpty()) {
127 // See if the current dirty regions apply to the current node
128 node->addDirtyRegion(m_dirtyRegion, true);
129 }
130
131 if (!m_obscuredRegion.isEmpty()) {
132 // Don't try to paint things that are covered by opaque objects
133 node->subtractDirtyRegion(m_obscuredRegion);
134 }
135
136 // Keep up with obscured regions
137 if (node->isOpaque()) {
138 m_obscuredRegion += node->boundingRectMin();
139 }
140
141 if (node->isDirty()) {
142 // Don't paint things outside of the rendering area
143 if (!m_background->rect().toRect().contains(node->boundingRectMax(), /*proper*/ true)) {
144 // Some part(s) of node is(are) outside of the rendering area
145 QRegion renderArea(m_background->rect().toRect());
146 QRegion outsideRegions = node->dirtyRegion().subtracted(renderArea);
147 if (!outsideRegions.isEmpty())
148 node->subtractDirtyRegion(outsideRegions);
149 }
150
151 // Get the dirty region's to pass to the next nodes
152 if (node->isOpaque()) {
153 // if isOpaque, subtract node's dirty rect from m_dirtyRegion
154 m_dirtyRegion -= node->boundingRectMin();
155 } else {
156 // if isAlpha, add node's dirty rect to m_dirtyRegion
157 m_dirtyRegion += node->dirtyRegion();
158 }
159 // if previousDirtyRegion has content outside of boundingRect add to m_dirtyRegion
160 QRegion prevDirty = node->previousDirtyRegion();
161 if (!prevDirty.isNull())
162 m_dirtyRegion += prevDirty;
163 }
164 }
165
166 if (m_obscuredRegion.contains(m_background->rect().toAlignedRect())) {
167 m_isOpaque = true;
168 } else {
169 m_isOpaque = false;
170 }
171
172 // Empty dirtyRegion (for second pass)
173 m_dirtyRegion = QRegion();
174 m_obscuredRegion = QRegion();
175
176 // Iterate through the renderlist from back to front
177 // Objective is to make sure all non-opaque items are painted when an item under them is dirty
178 for (auto j = m_renderableNodes.begin(); j != m_renderableNodes.end(); ++j) {
179 auto node = *j;
180
181 if ((!node->isOpaque() || node->boundingRectMax() != node->boundingRectMin()) && !m_dirtyRegion.isEmpty()) {
182 // Blended nodes need to be updated
183 // QTBUG-113745: Also nodes with floating point boundary rectangles need to
184 // be updated. The reason is that m_obscuredRegion contains only the rounded
185 // down bounding rectangle (node->boundingRectMin()) and thus not the whole
186 // node. As a result up to 1 pixel would be overpainted when it should not.
187 node->addDirtyRegion(m_dirtyRegion, true);
188 }
189
190 m_dirtyRegion += node->dirtyRegion();
191 }
192
193 QRegion updateRegion = m_dirtyRegion;
194
195 // Empty dirtyRegion
196 m_dirtyRegion = QRegion();
197 m_obscuredRegion = QRegion();
198
199 return updateRegion;
200}
201
203{
204 if (m_background->color() == color)
205 return;
206 m_background->setColor(color);
207 renderableNode(m_background)->markMaterialDirty();
208}
209
211{
212 if (m_background->rect().toRect() == rect && m_devicePixelRatio == devicePixelRatio)
213 return;
214 m_background->setRect(rect);
215 m_devicePixelRatio = devicePixelRatio;
216 renderableNode(m_background)->markGeometryDirty();
217 // Invalidate the whole scene when the background is resized
218 markDirty();
219}
220
222{
223 return m_background->color();
224}
225
227{
228 return m_background->rect().toRect();
229}
230
231void QSGAbstractSoftwareRenderer::nodeAdded(QSGNode *node)
232{
233 qCDebug(lc2DRender, "nodeAdded %p", (void*)node);
234
235 m_nodeUpdater->updateNodes(node);
236}
237
238void QSGAbstractSoftwareRenderer::nodeRemoved(QSGNode *node)
239{
240 qCDebug(lc2DRender, "nodeRemoved %p", (void*)node);
241
242 auto renderable = renderableNode(node);
243 // remove mapping
244 if (renderable != nullptr) {
245 // Need to mark this region dirty in the other nodes
246 QRegion dirtyRegion = renderable->previousDirtyRegion(true);
247 if (dirtyRegion.isEmpty())
248 dirtyRegion = renderable->boundingRectMax();
249 m_dirtyRegion += dirtyRegion;
250 m_nodes.remove(node);
251 delete renderable;
252 }
253
254 // Remove all children nodes as well
255 for (QSGNode *child = node->firstChild(); child; child = child->nextSibling()) {
256 nodeRemoved(child);
257 }
258
259 m_nodeUpdater->updateNodes(node, true);
260}
261
262void QSGAbstractSoftwareRenderer::nodeGeometryUpdated(QSGNode *node)
263{
264 qCDebug(lc2DRender, "nodeGeometryUpdated");
265
266 // Mark node as dirty
267 auto renderable = renderableNode(node);
268 if (renderable != nullptr) {
269 renderable->markGeometryDirty();
270 } else {
271 m_nodeUpdater->updateNodes(node);
272 }
273}
274
275void QSGAbstractSoftwareRenderer::nodeMaterialUpdated(QSGNode *node)
276{
277 qCDebug(lc2DRender, "nodeMaterialUpdated");
278
279 // Mark node as dirty
280 auto renderable = renderableNode(node);
281 if (renderable != nullptr) {
282 renderable->markMaterialDirty();
283 } else {
284 m_nodeUpdater->updateNodes(node);
285 }
286}
287
288void QSGAbstractSoftwareRenderer::nodeMatrixUpdated(QSGNode *node)
289{
290 qCDebug(lc2DRender, "nodeMaterialUpdated");
291
292 // Update children nodes
293 m_nodeUpdater->updateNodes(node);
294}
295
296void QSGAbstractSoftwareRenderer::nodeOpacityUpdated(QSGNode *node)
297{
298 qCDebug(lc2DRender, "nodeOpacityUpdated");
299
300 // Update children nodes
301 m_nodeUpdater->updateNodes(node);
302}
303
305{
306 m_dirtyRegion = QRegion(m_background->rect().toRect());
307}
308
The QColor class provides colors based on RGB, HSV or CMYK values.
Definition qcolor.h:31
bool remove(const Key &key)
Removes the item that has the key from the hash.
Definition qhash.h:958
T value(const Key &key) const noexcept
Definition qhash.h:1054
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
Definition qhash.h:1303
The QPainter class performs low-level painting on widgets and other paint devices.
Definition qpainter.h:46
QRect toAlignedRect() const noexcept
Definition qrect.cpp:2338
constexpr QRect toRect() const noexcept
Returns a QRect based on the values of this rectangle.
Definition qrect.h:859
\inmodule QtCore\reentrant
Definition qrect.h:30
The QRegion class specifies a clip region for a painter.
Definition qregion.h:27
bool contains(const QPoint &p) const
Returns true if the region contains the point p; otherwise returns false.
bool isEmpty() const
Returns true if the region is empty; otherwise returns false.
QRegion subtracted(const QRegion &r) const
QSGRootNode * rootNode() const
Returns the root of the QSGNode scene.
const QVector< QSGSoftwareRenderableNode * > & renderableNodes() const
void addNodeMapping(QSGNode *node, QSGSoftwareRenderableNode *renderableNode)
void appendRenderableNode(QSGSoftwareRenderableNode *node)
void setBackgroundColor(const QColor &color)
QSGSoftwareRenderableNode * renderableNode(QSGNode *node) const
void nodeChanged(QSGNode *node, QSGNode::DirtyState state) override
void setBackgroundRect(const QRect &rect, qreal devicePixelRatio)
void visitChildren(QSGNode *node)
\group qtquick-scenegraph-nodes \title Qt Quick Scene Graph Node classes
Definition qsgnode.h:37
@ DirtyMaterial
Definition qsgnode.h:75
@ DirtyNodeAdded
Definition qsgnode.h:72
@ DirtyForceUpdate
Definition qsgnode.h:78
@ DirtySubtreeBlocked
Definition qsgnode.h:70
@ DirtyNodeRemoved
Definition qsgnode.h:73
@ DirtyOpacity
Definition qsgnode.h:76
@ DirtyGeometry
Definition qsgnode.h:74
@ DirtyMatrix
Definition qsgnode.h:71
QSGNode * firstChild() const
Returns the first child of this node.
Definition qsgnode.h:105
The renderer class is the abstract baseclass used for rendering the QML scene graph.
void nodeChanged(QSGNode *node, QSGNode::DirtyState state) override
Updates internal data structures and emits the sceneGraphChanged() signal.
qreal devicePixelRatio() const
The QSGSimpleRectNode class is a convenience class for drawing solid filled rectangles using scenegra...
QRectF rect() const
Returns the rectangle that this rect node covers.
void setColor(const QColor &color)
Sets the color of this rectangle to color.
void setRect(const QRectF &rect)
Sets the rectangle of this rect node to rect.
QColor color() const
Returns the color of this rectangle.
void updateNodes(QSGNode *node, bool isNodeRemoved=false)
#define this
Definition dialogs.cpp:9
qDeleteAll(list.begin(), list.end())
rect
[4]
else opt state
[0]
Combined button and popup list for selecting options.
static void * context
#define Q_LOGGING_CATEGORY(name,...)
#define qCDebug(category,...)
GLuint color
[2]
double qreal
Definition qtypes.h:187
QLayoutItem * child
[0]
QPainter painter(this)
[7]