Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qsgrendernode.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
"qsgrendernode.h"
6
#
include
"qsgrendernode_p.h"
7
8
QT_BEGIN_NAMESPACE
9
10
/*!
11
\class QSGRenderNode
12
\brief The QSGRenderNode class represents a set of custom rendering commands
13
targeting the graphics API that is in use by the scenegraph.
14
\inmodule QtQuick
15
\since 5.8
16
17
QSGRenderNode allows creating scene graph nodes that perform their own
18
custom rendering via QRhi (the common approach from Qt 6.6 on), directly
19
via a 3D graphics API such as OpenGL, Vulkan, or Metal, or, when the \c
20
software backend is in use, via QPainter.
21
22
QSGRenderNode is the enabler for one of the three ways to integrate custom
23
2D/3D rendering into a Qt Quick scene. The other two options are to perform
24
the rendering \c before or \c after the Qt Quick scene's own rendering,
25
or to generate a whole separate render pass targeting a dedicated render
26
target (a texture) and then have an item in the scene display the texture.
27
The QSGRenderNode-based approach is similar to the former, in the sense
28
that no additional render passes or render targets are involved, and allows
29
injecting custom rendering commands "inline" with the Qt Quick scene's
30
own rendering. See \l{Qt Quick Scene Graph} for a further discussion of
31
the three approaches.
32
33
\sa {Scene Graph - Custom QSGRenderNode}
34
*/
35
36
QSGRenderNode::QSGRenderNode()
37
: QSGNode(RenderNodeType),
38
d(
new
QSGRenderNodePrivate)
39
{
40
}
41
42
/*!
43
Destructs the render node. Derived classes are expected to perform cleanup
44
similar to releaseResources() in here.
45
46
With QRhi and resources such as QRhiBuffer, QRhiTexture,
47
QRhiGraphicsPipeline, etc., it is often good practice to use smart pointers,
48
such as std::unique_ptr, which can often avoid the need to implement a
49
destructor, and lead to more compact source code. Keep in mind, however,
50
that implementing releaseResources(), likely containing a number of reset()
51
calls on the unique_ptrs, is still important.
52
53
\sa releaseResources()
54
*/
55
QSGRenderNode::~QSGRenderNode()
56
{
57
delete
d;
58
}
59
60
QSGRenderNodePrivate::QSGRenderNodePrivate()
61
: m_matrix(
nullptr
)
62
, m_clip_list(
nullptr
)
63
, m_opacity(1)
64
{
65
m_projectionMatrix.resize(1);
66
}
67
68
/*!
69
This function should return a mask where each bit represents graphics states
70
changed by the \l render() function.
71
72
\note With Qt 6 and QRhi-based rendering the only relevant values are
73
ViewportState and ScissorState. Other values can be returned but are
74
ignored in practice.
75
76
\value ViewportState Viewport
77
\value ScissorState Scissor test enabled state, scissor rectangle
78
\value DepthState This value has no effect in Qt 6.
79
\value StencilState This value has no effect in Qt 6.
80
\value ColorState This value has no effect in Qt 6.
81
\value BlendState This value has no effect in Qt 6.
82
\value CullState This value has no effect in Qt 6.
83
\value RenderTargetState This value has no effect in Qt 6.
84
85
\note The \c software backend exposes its QPainter and saves and restores
86
before and after invoking render(). Therefore reporting any changed states
87
from here is not necessary.
88
89
The default implementation returns 0, meaning no relevant state was changed
90
in render().
91
92
\note This function may be called before render().
93
*/
94
QSGRenderNode::StateFlags QSGRenderNode::changedStates()
const
95
{
96
return
{};
97
}
98
99
/*!
100
Called from the frame preparation phase. There is a call to this function
101
before each invocation of render().
102
103
Unlike render(), this function is called before the scenegraph starts
104
recording the render pass for the current frame on the underlying command
105
buffer. This is useful when doing rendering with graphics APIs, such as
106
Vulkan, where copy type of operations will need to be recorded before the
107
render pass.
108
109
The default implementation is empty.
110
111
When implementing a QSGRenderNode that uses QRhi to render, query the QRhi
112
object from the QQuickWindow via \l{QQuickWindow::rhi()}. To get a
113
QRhiCommandBuffer for submitting work to, call commandBuffer(). To query
114
information about the active render target, call renderTarget(). See the
115
\l{{Scene Graph - Custom QSGRenderNode}} example for details.
116
117
\since 6.0
118
*/
119
void
QSGRenderNode::prepare()
120
{
121
}
122
123
/*!
124
\fn void QSGRenderNode::render(const RenderState *state)
125
126
This function is called by the renderer and should paint this node with
127
directly invoking commands via QRhi or directly via the underlying graphics
128
API (OpenGL, Direct3D, etc.).
129
130
The effective opacity can be retrieved with \l inheritedOpacity().
131
132
The projection matrix is available through \a state, while the model-view
133
matrix can be fetched with \l matrix(). The combined matrix is then the
134
projection matrix times the model-view matrix. The correct stacking of the
135
items in the scene is ensured by the projection matrix.
136
137
When using the provided matrices, the coordinate system for vertex data
138
follows the usual QQuickItem conventions: top-left is (0, 0), bottom-right
139
is the corresponding QQuickItem's width() and height() minus one. For
140
example, assuming a two float (x-y) per vertex coordinate layout, a
141
triangle covering half of the item can be specified as (width - 1, height - 1),
142
(0, 0), (0, height - 1) using counter-clockwise direction.
143
144
\note QSGRenderNode is provided as a means to implement custom 2D or 2.5D Qt
145
Quick items. It is not intended for integrating true 3D content into the Qt
146
Quick scene. That use case is better supported by the other methods for
147
integrating custom rendering.
148
149
\note QSGRenderNode can perform significantly better than texture-based
150
approaches (such as, QQuickRhiItem), especially on systems where
151
the fragment processing power is limited. This is because it avoids
152
rendering to a texture and then drawing a textured quad. Rather,
153
QSGRenderNode allows recording draw calls in line with the scenegraph's
154
other commands, avoiding an additional render target and the potentially
155
expensive texturing and blending.
156
157
Clip information is calculated before the function is called.
158
Implementations wishing to take clipping into account can set up scissoring
159
or stencil based on the information in \a state. The stencil buffer is
160
filled with the necessary clip shapes, but it is up to the implementation
161
to enable stencil testing.
162
163
Some scenegraph backends, software in particular, use no scissor or
164
stencil. There the clip region is provided as an ordinary QRegion.
165
166
When implementing a QSGRenderNode that uses QRhi to render, query the QRhi
167
object from the QQuickWindow via \l{QQuickWindow::rhi()}. To get a
168
QRhiCommandBuffer for submitting work to, call commandBuffer(). To query
169
information about the active render target, call renderTarget(). See the
170
\l{{Scene Graph - Custom QSGRenderNode}} example for details.
171
172
With Qt 6 and its QRhi-based scene graph renderer, no assumptions should be
173
made about the active (OpenGL) state when this function is called, even
174
when OpenGL is in use. Assume nothing about the pipelines and dynamic
175
states bound on the command list/buffer when this function is called.
176
177
\note Depth writes are expected to be disabled. Enabling depth writes can
178
lead to unexpected results, depending on the scenegraph backend in use and
179
the content in the scene, so exercise caution with this.
180
181
\note In Qt 6, \l changedStates() has limited use. See the documentation
182
for changedStates() for more information.
183
184
With some graphics APIs, including when using QRhi directly, it can be
185
necessary to reimplement prepare() in addition, or alternatively connect to
186
the QQuickWindow::beforeRendering() signal. These are called/emitted before
187
recording the beginning of a renderpass on the command buffer
188
(vkCmdBeginRenderPass with Vulkan, or starting to encode via
189
MTLRenderCommandEncoder in case of Metal. Recording copy operations cannot
190
be done inside render() with such APIs. Rather, do such operations either
191
in prepare() or the slot connected to beforeRendering (with
192
DirectConnection).
193
194
\sa QSGRendererInterface, QQuickWindow::rendererInterface()
195
*/
196
197
/*!
198
This function is called when all custom graphics resources allocated by
199
this node have to be freed immediately. In case the node does not directly
200
allocate graphics resources (buffers, textures, render targets, fences,
201
etc.) through the graphics API that is in use, there is nothing to do here.
202
203
Failing to release all custom resources can lead to incorrect behavior in
204
graphics device loss scenarios on some systems since subsequent
205
reinitialization of the graphics system may fail.
206
207
\note Some scenegraph backends may choose not to call this function.
208
Therefore it is expected that QSGRenderNode implementations perform cleanup
209
both in their destructor and in releaseResources().
210
211
Unlike with the destructor, it is expected that render() can reinitialize
212
all resources it needs when called after a call to releaseResources().
213
214
With OpenGL, the scenegraph's OpenGL context will be current both when
215
calling the destructor and this function.
216
*/
217
void
QSGRenderNode::releaseResources()
218
{
219
}
220
221
/*!
222
\enum QSGRenderNode::StateFlag
223
224
This enum contains the possible values for use in the bitmask returned from changedStates().
225
226
\value ViewportState Viewport
227
\value ScissorState Scissor test enabled state, scissor rectangle
228
\value DepthState This value has no effect in Qt 6.
229
\value StencilState This value has no effect in Qt 6.
230
\value ColorState This value has no effect in Qt 6.
231
\value BlendState This value has no effect in Qt 6.
232
\value CullState This value has no effect in Qt 6.
233
\value RenderTargetState This value has no effect in Qt 6.
234
*/
235
236
/*!
237
\enum QSGRenderNode::RenderingFlag
238
239
Possible values for the bitmask returned from flags().
240
241
\value BoundedRectRendering Indicates that the implementation of render()
242
does not render outside the area reported from rect() in item
243
coordinates. Such node implementations can lead to more efficient rendering,
244
depending on the scenegraph backend. For example, the \c software backend can
245
continue to use the more optimal partial update path when all render nodes
246
in the scene have this flag set.
247
248
\value DepthAwareRendering Indicates that the implementations of render()
249
conforms to scenegraph expectations by only generating a Z value of 0 in
250
scene coordinates which is then transformed by the matrices retrieved from
251
RenderState::projectionMatrix() and matrix(), as described in the notes for
252
render(). Such node implementations can lead to more efficient rendering,
253
depending on the scenegraph backend. For example, the batching OpenGL
254
renderer can continue to use a more optimal path when all render nodes in
255
the scene have this flag set.
256
257
\value OpaqueRendering Indicates that the implementation of render() writes
258
out opaque pixels for the entire area reported from rect(). By default the
259
renderers must assume that render() can also output semi or fully
260
transparent pixels. Setting this flag can improve performance in some
261
cases.
262
263
\value NoExternalRendering Indicates that the implementations of prepare()
264
and render() exclusively use the QRhi family of APIs, instead of
265
directly calling a 3D API such as OpenGL, Vulkan, or Metal.
266
267
\sa render(), prepare(), rect(), QRhi
268
*/
269
270
/*!
271
\return flags describing the behavior of this render node.
272
273
The default implementation returns 0.
274
275
\sa RenderingFlag, rect()
276
*/
277
QSGRenderNode::RenderingFlags QSGRenderNode::flags()
const
278
{
279
return
{};
280
}
281
282
/*!
283
\return the bounding rectangle in item coordinates for the area render()
284
touches. The value is only in use when flags() includes
285
BoundedRectRendering, ignored otherwise.
286
287
Reporting the rectangle in combination with BoundedRectRendering is
288
particularly important with the \c software backend because otherwise
289
having a rendernode in the scene would trigger fullscreen updates, skipping
290
all partial update optimizations.
291
292
For rendernodes covering the entire area of a corresponding QQuickItem the
293
return value will be (0, 0, item->width(), item->height()).
294
295
\note Nodes are also free to render outside the boundaries specified by the
296
item's width and height, since the scenegraph nodes are not bounded by the
297
QQuickItem geometry, as long as this is reported correctly from this function.
298
299
\sa flags()
300
*/
301
QRectF QSGRenderNode::rect()
const
302
{
303
return
QRectF();
304
}
305
306
/*!
307
\return pointer to the current projection matrix.
308
309
In render() this is the same matrix that is returned from
310
RenderState::projectionMatrix(). This getter exists so that prepare() also
311
has a way to query the projection matrix.
312
313
When working with a modern graphics API, or Qt's own graphics abstraction
314
layer, it is more than likely that one will want to load
315
\c{*projectionMatrix() * *matrix()} into a uniform buffer. That is however
316
something that needs to be done in prepare(), so outside the recording of a
317
render pass. That is why both matrices are queriable directly from the
318
QSGRenderNode, both in prepare() and render().
319
320
\since 6.5
321
*/
322
const
QMatrix4x4 *QSGRenderNode::projectionMatrix()
const
323
{
324
return
&d->m_projectionMatrix[0];
325
}
326
327
/*!
328
\internal
329
*/
330
const
QMatrix4x4 *QSGRenderNode::projectionMatrix(qsizetype index)
const
331
{
332
return
&d->m_projectionMatrix[index];
333
}
334
335
/*!
336
\return pointer to the current model-view matrix.
337
*/
338
const
QMatrix4x4 *QSGRenderNode::matrix()
const
339
{
340
return
d->m_matrix;
341
}
342
343
/*!
344
\return the current clip list.
345
*/
346
const
QSGClipNode *QSGRenderNode::clipList()
const
347
{
348
return
d->m_clip_list;
349
}
350
351
/*!
352
\return the current effective opacity.
353
*/
354
qreal QSGRenderNode::inheritedOpacity()
const
355
{
356
return
d->m_opacity;
357
}
358
359
/*!
360
\return the current render target.
361
362
This is provided mainly to enable prepare() and render() implementations
363
that use QRhi accessing the QRhiRenderTarget's
364
\l{QRhiRenderPassDescriptor}{renderPassDescriptor} or
365
\l{QRhiRenderTarget::pixelSize()}{pixel size}.
366
367
To build a QRhiGraphicsPipeline, which implies having to provide a
368
QRhiRenderPassDescriptor, query the renderPassDescriptor from the render
369
target. Be aware however that the render target may change over the
370
lifetime of the custom QQuickItem and the QSGRenderNode. For example,
371
consider what happens when dynamically setting \c{layer.enabled: true} on
372
the item or an ancestor of it: this triggers rendering into a texture, not
373
directly to the window, which means the QSGRenderNode is going to work with
374
a different render target from then on. The new render target may then have
375
a different pixel format, which can make already built graphics pipelines
376
incompatible. This can be handled with logic such as the following:
377
378
\code
379
if (m_pipeline && renderTarget()->renderPassDescriptor()->serializedFormat() != m_renderPassFormat) {
380
delete m_pipeline;
381
m_pipeline = nullptr;
382
}
383
if (!m_pipeline) {
384
// Build a new QRhiGraphicsPipeline.
385
// ...
386
// Store the serialized format for fast and simple comparisons later on.
387
m_renderPassFormat = renderTarget()->renderPassDescriptor()->serializedFormat();
388
}
389
\endcode
390
391
\since 6.6
392
393
\sa commandBuffer()
394
*/
395
QRhiRenderTarget *QSGRenderNode::renderTarget()
const
396
{
397
return
d->m_rt.rt;
398
}
399
400
/*!
401
\return the current command buffer.
402
403
\since 6.6
404
405
\sa renderTarget()
406
*/
407
QRhiCommandBuffer *QSGRenderNode::commandBuffer()
const
408
{
409
return
d->m_rt.cb;
410
}
411
412
QSGRenderNode::RenderState::~RenderState()
413
{
414
}
415
416
/*!
417
\class QSGRenderNode::RenderState
418
\brief Provides information about the projection matrix and clipping.
419
\inmodule QtQuick
420
421
The render state contains information for the renderer when invoking
422
commands to the scenegraph backends.
423
424
\sa QSGRenderNode::render()
425
*/
426
427
/*!
428
\fn const QMatrix4x4 *QSGRenderNode::RenderState::projectionMatrix() const
429
430
\return pointer to the current projection matrix.
431
432
The model-view matrix can be retrieved with QSGRenderNode::matrix().
433
Typically \c{projection * modelview} is the matrix that is then used in the
434
vertex shader to transform the vertices.
435
*/
436
437
/*!
438
\fn const QMatrix4x4 *QSGRenderNode::RenderState::scissorRect() const
439
440
\return the current scissor rectangle when clipping is active. x and y are
441
the bottom left coordinates.
442
*/
443
444
/*!
445
\fn const QMatrix4x4 *QSGRenderNode::RenderState::scissorEnabled() const
446
447
\return the current state of scissoring.
448
449
\note Only relevant for graphics APIs that have a dedicated on/off state of
450
scissoring.
451
*/
452
453
/*!
454
\fn const QMatrix4x4 *QSGRenderNode::RenderState::stencilValue() const
455
456
\return the current stencil reference value when clipping is active.
457
*/
458
459
/*!
460
\fn const QMatrix4x4 *QSGRenderNode::RenderState::stencilEnabled() const
461
462
\return the current state of stencil testing.
463
464
\note With graphics APIs where stencil testing is enabled in pipeline state
465
objects, instead of individual state-setting commands, it is up to the
466
implementation of render() to enable stencil testing with operations
467
\c KEEP, comparison function \c EQUAL, and a read and write mask of \c 0xFF.
468
*/
469
470
/*!
471
\fn const QRegion *QSGRenderNode::RenderState::clipRegion() const
472
473
\return the current clip region or null for backends where clipping is
474
implemented via stencil or scissoring.
475
476
The \c software backend uses no projection, scissor or stencil, meaning most
477
of the render state is not in use. However, the clip region that can be set
478
on the QPainter still has to be communicated since reconstructing this
479
manually in render() is not reasonable. It can therefore be queried via
480
this function. The region is in world coordinates and can be passed
481
to QPainter::setClipRegion() with Qt::ReplaceClip. This must be done before
482
calling QPainter::setTransform() since the clip region is already mapped to
483
the transform provided in QSGRenderNode::matrix().
484
*/
485
486
/*!
487
\return pointer to a \a state value.
488
489
Reserved for future use.
490
*/
491
void
*QSGRenderNode::RenderState::get(
const
char
*state)
const
492
{
493
Q_UNUSED(state);
494
return
nullptr
;
495
}
496
497
QT_END_NAMESPACE
QT_BEGIN_NAMESPACE
Combined button and popup list for selecting options.
Definition
qrandomaccessasyncfile_darwin.mm:17
qtdeclarative
src
quick
scenegraph
coreapi
qsgrendernode.cpp
Generated on
for Qt by
1.16.1