Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Toggle main menu visibility
Loading...
Searching...
No Matches
qsgrenderer.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
// Qt-Security score:significant reason:default
4
5
#
include
"qsgrenderer_p.h"
6
#
include
"qsgnodeupdater_p.h"
7
#
include
<
private
/
qquickprofiler_p
.
h
>
8
#
include
<
qtquick_tracepoints_p
.
h
>
9
10
#
include
<
QtCore
/
QElapsedTimer
>
11
12
QT_BEGIN_NAMESPACE
13
14
static
QElapsedTimer
frameTimer
;
15
static
qint64
preprocessTime
;
16
static
qint64
updatePassTime
;
17
18
Q_TRACE_POINT(qtquick, QSG_preprocess_entry)
19
Q_TRACE_POINT(qtquick, QSG_preprocess_exit)
20
Q_TRACE_POINT(qtquick, QSG_update_entry)
21
Q_TRACE_POINT(qtquick, QSG_update_exit)
22
Q_TRACE_POINT(qtquick, QSG_renderScene_entry)
23
Q_TRACE_POINT(qtquick, QSG_renderScene_exit)
24
25
int
qt_sg_envInt(
const
char
*name,
int
defaultValue)
26
{
27
if
(Q_LIKELY(!qEnvironmentVariableIsSet(name)))
28
return
defaultValue;
29
bool
ok =
false
;
30
int
value = qEnvironmentVariableIntValue(name, &ok);
31
return
ok ? value : defaultValue;
32
}
33
34
/*!
35
\class QSGRenderer
36
\brief The renderer class is the abstract baseclass used for rendering the
37
QML scene graph.
38
39
The renderer is not tied to any particular surface. It expects a context to
40
be current and will render into that surface according to how the device rect,
41
viewport rect and projection transformation are set up.
42
43
Rendering is a sequence of steps initiated by calling renderScene(). This will
44
effectively draw the scene graph starting at the root node. The QSGNode::preprocess()
45
function will be called for all the nodes in the graph, followed by an update
46
pass which updates all matrices, opacity, clip states and similar in the graph.
47
Because the update pass is called after preprocess, it is safe to modify the graph
48
during preprocess. To run a custom update pass over the graph, install a custom
49
QSGNodeUpdater using setNodeUpdater(). Once all the graphs dirty states are updated,
50
the virtual render() function is called.
51
52
The render() function is implemented by QSGRenderer subclasses to render the graph
53
in the most optimal way for a given hardware.
54
55
The renderer can make use of stencil, depth and color buffers in addition to the
56
scissor rect.
57
58
\internal
59
*/
60
61
62
QSGRenderer::QSGRenderer(QSGRenderContext *context)
63
: m_current_opacity(1)
64
, m_current_determinant(1)
65
, m_device_pixel_ratio(1)
66
, m_context(context)
67
, m_current_uniform_data(
nullptr
)
68
, m_current_resource_update_batch(
nullptr
)
69
, m_rhi(
nullptr
)
70
, m_node_updater(
nullptr
)
71
, m_changed_emitted(
false
)
72
, m_is_rendering(
false
)
73
, m_is_preprocessing(
false
)
74
{
75
m_current_projection_matrix.resize(1);
76
m_current_projection_matrix_native_ndc.resize(1);
77
}
78
79
80
QSGRenderer::~QSGRenderer()
81
{
82
setRootNode(
nullptr
);
83
delete
m_node_updater;
84
}
85
86
/*!
87
Returns the node updater that this renderer uses to update states in the
88
scene graph.
89
90
If no updater is specified a default one is constructed.
91
*/
92
93
QSGNodeUpdater *QSGRenderer::nodeUpdater()
const
94
{
95
if
(!m_node_updater)
96
const_cast
<QSGRenderer *>(
this
)->m_node_updater =
new
QSGNodeUpdater();
97
return
m_node_updater;
98
}
99
100
101
/*!
102
Sets the node updater that this renderer uses to update states in the
103
scene graph.
104
105
This will delete and override any existing node updater
106
*/
107
void
QSGRenderer::setNodeUpdater(QSGNodeUpdater *updater)
108
{
109
if
(m_node_updater)
110
delete
m_node_updater;
111
m_node_updater = updater;
112
}
113
114
bool
QSGRenderer::isMirrored()
const
115
{
116
QMatrix4x4 matrix = projectionMatrix(0);
117
// Mirrored relative to the usual Qt coordinate system with origin in the top left corner.
118
return
matrix(0, 0) * matrix(1, 1) - matrix(0, 1) * matrix(1, 0) > 0;
119
}
120
121
void
QSGRenderer::renderScene()
122
{
123
if
(!rootNode())
124
return
;
125
126
Q_TRACE_SCOPE(QSG_renderScene);
127
m_is_rendering =
true
;
128
129
bool
profileFrames = QSG_LOG_TIME_RENDERER().isDebugEnabled();
130
if
(profileFrames)
131
frameTimer.start();
132
Q_QUICK_SG_PROFILE_START(QQuickProfiler::SceneGraphRendererFrame);
133
134
// The QML Profiler architecture is extremely fragile: we have to record a
135
// hardcoded number of data points for each event, otherwise the view will
136
// show weird things in Creator. So record a dummy Binding data point, even
137
// though it is meaningless for our purposes.
138
Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRendererFrame,
139
QQuickProfiler::SceneGraphRendererBinding);
140
141
qint64 renderTime = 0;
142
143
preprocess();
144
145
Q_TRACE(QSG_render_entry);
146
render();
147
if
(profileFrames)
148
renderTime = frameTimer.nsecsElapsed();
149
Q_TRACE(QSG_render_exit);
150
Q_QUICK_SG_PROFILE_END(QQuickProfiler::SceneGraphRendererFrame,
151
QQuickProfiler::SceneGraphRendererRender);
152
153
m_is_rendering =
false
;
154
m_changed_emitted =
false
;
155
156
qCDebug(QSG_LOG_TIME_RENDERER,
157
"time in renderer: total=%dms, preprocess=%d, updates=%d, rendering=%d"
,
158
int
(renderTime / 1000000),
159
int
(preprocessTime / 1000000),
160
int
((updatePassTime - preprocessTime) / 1000000),
161
int
((renderTime - updatePassTime) / 1000000));
162
}
163
164
void
QSGRenderer::prepareSceneInline()
165
{
166
if
(!rootNode())
167
return
;
168
169
Q_ASSERT(!m_is_rendering);
170
m_is_rendering =
true
;
171
172
preprocess();
173
174
prepareInline();
175
}
176
177
void
QSGRenderer::renderSceneInline()
178
{
179
Q_ASSERT(m_is_rendering);
180
181
renderInline();
182
183
m_is_rendering =
false
;
184
m_changed_emitted =
false
;
185
}
186
187
/*!
188
Updates internal data structures and emits the sceneGraphChanged() signal.
189
190
If \a flags contains the QSGNode::DirtyNodeRemoved flag, the node might be
191
in the process of being destroyed. It is then not safe to downcast the node
192
pointer.
193
*/
194
195
void
QSGRenderer::nodeChanged(QSGNode *node, QSGNode::DirtyState state)
196
{
197
if
(state & QSGNode::DirtyNodeAdded)
198
addNodesToPreprocess(node);
199
if
(state & QSGNode::DirtyNodeRemoved)
200
removeNodesToPreprocess(node);
201
if
(state & QSGNode::DirtyUsePreprocess) {
202
if
(node->flags() & QSGNode::UsePreprocess)
203
m_nodes_to_preprocess.insert(node);
204
else
205
m_nodes_to_preprocess.remove(node);
206
}
207
208
if
(!m_changed_emitted && !m_is_rendering) {
209
// Premature overoptimization to avoid excessive signal emissions
210
m_changed_emitted =
true
;
211
emit sceneGraphChanged();
212
}
213
}
214
215
void
QSGRenderer::preprocess()
216
{
217
Q_TRACE(QSG_preprocess_entry);
218
219
m_is_preprocessing =
true
;
220
221
QSGRootNode *root = rootNode();
222
Q_ASSERT(root);
223
224
// We need to take a copy here, in case any of the preprocess calls deletes a node that
225
// is in the preprocess list and thus, changes the m_nodes_to_preprocess behind our backs
226
// For the default case, when this does not happen, the cost is negligible.
227
QSet<QSGNode *> items = m_nodes_to_preprocess;
228
229
m_context->preprocess();
230
231
for
(QSet<QSGNode *>::const_iterator it = items.constBegin();
232
it != items.constEnd(); ++it) {
233
QSGNode *n = *it;
234
235
// If we are currently preprocessing, check this node hasn't been
236
// deleted or something. we don't want a use-after-free!
237
if
(m_nodes_dont_preprocess.contains(n))
// skip
238
continue
;
239
if
(!nodeUpdater()->isNodeBlocked(n, root)) {
240
n->preprocess();
241
}
242
}
243
244
bool
profileFrames = QSG_LOG_TIME_RENDERER().isDebugEnabled();
245
if
(profileFrames)
246
preprocessTime = frameTimer.nsecsElapsed();
247
Q_TRACE(QSG_preprocess_exit);
248
Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRendererFrame,
249
QQuickProfiler::SceneGraphRendererPreprocess);
250
Q_TRACE(QSG_update_entry);
251
252
nodeUpdater()->updateStates(root);
253
254
if
(profileFrames)
255
updatePassTime = frameTimer.nsecsElapsed();
256
Q_TRACE(QSG_update_exit);
257
Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRendererFrame,
258
QQuickProfiler::SceneGraphRendererUpdate);
259
260
m_is_preprocessing =
false
;
261
m_nodes_dont_preprocess.clear();
262
}
263
264
265
266
void
QSGRenderer::addNodesToPreprocess(QSGNode *node)
267
{
268
for
(QSGNode *c = node->firstChild(); c; c = c->nextSibling())
269
addNodesToPreprocess(c);
270
if
(node->flags() & QSGNode::UsePreprocess)
271
m_nodes_to_preprocess.insert(node);
272
}
273
274
void
QSGRenderer::removeNodesToPreprocess(QSGNode *node)
275
{
276
for
(QSGNode *c = node->firstChild(); c; c = c->nextSibling())
277
removeNodesToPreprocess(c);
278
if
(node->flags() & QSGNode::UsePreprocess) {
279
m_nodes_to_preprocess.remove(node);
280
281
// If preprocessing *now*, mark the node as gone.
282
if
(m_is_preprocessing)
283
m_nodes_dont_preprocess.insert(node);
284
}
285
}
286
287
void
QSGRenderer::prepareInline()
288
{
289
}
290
291
void
QSGRenderer::renderInline()
292
{
293
}
294
295
296
/*!
297
\class QSGNodeDumper
298
\brief The QSGNodeDumper class provides a way of dumping a scene grahp to the console.
299
300
This class is solely for debugging purposes.
301
302
\internal
303
*/
304
305
void
QSGNodeDumper::dump(QSGNode *n)
306
{
307
QSGNodeDumper dump;
308
dump.visitNode(n);
309
}
310
311
void
QSGNodeDumper::visitNode(QSGNode *n)
312
{
313
qDebug() << QByteArray(m_indent * 2,
' '
).constData() << n;
314
QSGNodeVisitor::visitNode(n);
315
}
316
317
void
QSGNodeDumper::visitChildren(QSGNode *n)
318
{
319
++m_indent;
320
QSGNodeVisitor::visitChildren(n);
321
--m_indent;
322
}
323
324
325
QT_END_NAMESPACE
QT_BEGIN_NAMESPACE
Combined button and popup list for selecting options.
Definition
qsequentialanimationgroup.cpp:47
frameTimer
static QT_BEGIN_NAMESPACE QElapsedTimer frameTimer
Definition
qsgrenderer.cpp:14
preprocessTime
static qint64 preprocessTime
Definition
qsgrenderer.cpp:15
updatePassTime
static qint64 updatePassTime
Definition
qsgrenderer.cpp:16
qtdeclarative
src
quick
scenegraph
coreapi
qsgrenderer.cpp
Generated on
for Qt by
1.18.0