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