1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtQuick module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qsgrendernode.h"
41#include "qsgrendernode_p.h"
42
43QT_BEGIN_NAMESPACE
44
45/*!
46 \class QSGRenderNode
47 \brief The QSGRenderNode class represents a set of custom rendering commands
48 targeting the graphics API that is in use by the scenegraph.
49 \inmodule QtQuick
50 \since 5.8
51 */
52
53QSGRenderNode::QSGRenderNode()
54 : QSGNode(RenderNodeType),
55 d(new QSGRenderNodePrivate)
56{
57}
58
59/*!
60 Destructs the render node. Derived classes are expected to perform cleanup
61 similar to releaseResources() in here.
62
63 When a low-level graphics API is in use, the scenegraph will make sure
64 there is a CPU-side wait for the GPU to complete all work submitted to the
65 scenegraph's graphics command queue before the scenegraph's nodes are
66 deleted. Therefore there is no need to issue additional waits here, unless
67 the render() implementation is using additional command queues.
68
69 \sa releaseResources()
70 */
71QSGRenderNode::~QSGRenderNode()
72{
73 delete d;
74}
75
76QSGRenderNodePrivate::QSGRenderNodePrivate()
77 : m_matrix(nullptr)
78 , m_clip_list(nullptr)
79 , m_opacity(1)
80 , m_needsExternalRendering(true)
81 , m_prepareCallback(nullptr)
82{
83}
84
85/*!
86 When the underlying rendering API is OpenGL, this function should return a
87 mask where each bit represents graphics states changed by the \l render()
88 function:
89
90 \list
91 \li DepthState - depth write mask, depth test enabled, depth comparison function
92 \li StencilState - stencil write masks, stencil test enabled, stencil operations,
93 stencil comparison functions
94 \li ScissorState - scissor enabled, scissor test enabled
95 \li ColorState - clear color, color write mask
96 \li BlendState - blend enabled, blend function
97 \li CullState - front face, cull face enabled
98 \li ViewportState - viewport
99 \li RenderTargetState - render target
100 \endlist
101
102 With APIs other than OpenGL, the only relevant values are the ones that
103 correspond to dynamic state changes recorded on the command list/buffer.
104 For example, RSSetViewports, RSSetScissorRects, OMSetBlendFactor,
105 OMSetStencilRef in case of D3D12, or vkCmdSetViewport, vkCmdSetScissor,
106 vkCmdSetBlendConstants, vkCmdSetStencilRef in case of Vulkan, and only when
107 such commands were added to the scenegraph's command list queried via the
108 QSGRendererInterface::CommandList resource enum. States set in pipeline
109 state objects do not need to be reported here. Similarly, draw call related
110 settings (pipeline states, descriptor sets, vertex or index buffer
111 bindings, root signature, descriptor heaps, etc.) are always set again by
112 the scenegraph so render() can freely change them.
113
114 \note RenderTargetState is no longer supported with APIs like Vulkan. This
115 is by nature. render() is invoked while the Qt Quick scenegraph's main
116 command buffer is recording a renderpass, so there is no possibility of
117 changing the target and starting another renderpass (on that command buffer
118 at least). Therefore returning a value with RenderTargetState set is not
119 sensible.
120
121 The software backend exposes its QPainter and saves and restores before and
122 after invoking render(). Therefore reporting any changed states from here
123 is not necessary.
124
125 The function is called by the renderer so it can reset the states after
126 rendering this node. This makes the implementation of render() simpler
127 since it does not have to query and restore these states.
128
129 The default implementation returns 0, meaning no relevant state was changed
130 in render().
131
132 \note This function may be called before render().
133 */
134QSGRenderNode::StateFlags QSGRenderNode::changedStates() const
135{
136 return {};
137}
138
139/*!
140 \fn void QSGRenderNode::render(const RenderState *state)
141
142 This function is called by the renderer and should paint this node with
143 directly invoking commands in the graphics API (OpenGL, Direct3D, etc.)
144 currently in use.
145
146 The effective opacity can be retrieved with \l inheritedOpacity().
147
148 The projection matrix is available through \a state, while the model-view
149 matrix can be fetched with \l matrix(). The combined matrix is then the
150 projection matrix times the model-view matrix. The correct stacking of the
151 items in the scene is ensured by the projection matrix.
152
153 When using the provided matrices, the coordinate system for vertex data
154 follows the usual QQuickItem conventions: top-left is (0, 0), bottom-right
155 is the corresponding QQuickItem's width() and height() minus one. For
156 example, assuming a two float (x-y) per vertex coordinate layout, a
157 triangle covering half of the item can be specified as (width - 1, height - 1),
158 (0, 0), (0, height - 1) using counter-clockwise direction.
159
160 \note QSGRenderNode is provided as a means to implement custom 2D or 2.5D
161 Qt Quick items. It is not intended for integrating true 3D content into the
162 Qt Quick scene. That use case is better supported by
163 QQuickFramebufferObject, QQuickWindow::beforeRendering(), or the
164 equivalents of those for APIs other than OpenGL.
165
166 \note QSGRenderNode can perform significantly better than texture-based
167 approaches (such as, QQuickFramebufferObject), especially on systems where
168 the fragment processing power is limited. This is because it avoids
169 rendering to a texture and then drawing a textured quad. Rather,
170 QSGRenderNode allows recording draw calls in line with the scenegraph's
171 other commands, avoiding an additional render target and the potentially
172 expensive texturing and blending.
173
174 Clip information is calculated before the function is called.
175 Implementations wishing to take clipping into account can set up scissoring
176 or stencil based on the information in \a state. The stencil buffer is
177 filled with the necessary clip shapes, but it is up to the implementation
178 to enable stencil testing.
179
180 Some scenegraph backends, software in particular, use no scissor or
181 stencil. There the clip region is provided as an ordinary QRegion.
182
183 With the legacy, direct OpenGL based renderer, the following states are set
184 on the render thread's context before this function is called:
185
186 \list
187 \li glColorMask(true, true, true, true)
188 \li glDepthMask(false)
189 \li glDisable(GL_DEPTH_TEST)
190 \li glStencilFunc(GL_EQUAL, state.stencilValue, 0xff); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP) depending on clip
191 \li glScissor(state.scissorRect.x(), state.scissorRect.y(),
192 state.scissorRect.width(), state.scissorRect.height()) depending on clip
193 \li glEnable(GL_BLEND)
194 \li glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA)
195 \li glDisable(GL_CULL_FACE)
196 \endlist
197
198 States that are not listed above, but are covered by \l StateFlags, can
199 have arbitrary values.
200
201 \note There is no state set with other graphics APIs, considering that many
202 of them do not have a concept of the traditional OpenGL state machine.
203 Rather, it is up to the implementation to create pipeline state objects
204 with the desired blending, scissor, and stencil tests enabled. Note that
205 this also includes OpenGL via the RHI. New QSGRenderNode implementations
206 are recommended to set all scissor, stencil and blend state explicitly (as
207 shown in the above list), even if they are targeting OpenGL.
208
209 \l changedStates() should return which states this function changes. If a
210 state is not covered by \l StateFlags, the state should be set to the
211 default value according to the OpenGL specification. For other APIs, see
212 the documentation for changedStates() for more information.
213
214 \note Depth writes are disabled when this function is called
215 (glDepthMask(false) with OpenGL). Enabling depth writes can lead to
216 unexpected results, depending on the scenegraph backend in use and the
217 content in the scene, so exercise caution with this.
218
219 For APIs other than OpenGL, it will likely be necessary to query certain
220 API-specific resources (for example, the graphics device or the command
221 list/buffer to add the commands to). This is done via QSGRendererInterface.
222
223 Assume nothing about the pipelines and dynamic states bound on the command
224 list/buffer when this function is called.
225
226 With some graphics APIs it can be necessary to also connect to the
227 QQuickWindow::beforeRendering() signal, because that is emitted before
228 recording the beginning of a renderpass on the command buffer
229 (vkCmdBeginRenderPass with Vulkan, or starting to encode via
230 MTLRenderCommandEncoder in case of Metal). Recording copy operations cannot
231 be done inside render() with such APIs. Rather, do it in the slot connected
232 (with DirectConnection) to the beforeRendering signal.
233
234 \sa QSGRendererInterface, QQuickWindow::rendererInterface()
235 */
236
237/*!
238 This function is called when all custom graphics resources allocated by
239 this node have to be freed immediately. In case the node does not directly
240 allocate graphics resources (buffers, textures, render targets, fences,
241 etc.) through the graphics API that is in use, there is nothing to do here.
242
243 Failing to release all custom resources can lead to incorrect behavior in
244 graphics device loss scenarios on some systems since subsequent
245 reinitialization of the graphics system may fail.
246
247 \note Some scenegraph backends may choose not to call this function.
248 Therefore it is expected that QSGRenderNode implementations perform cleanup
249 both in their destructor and in releaseResources().
250
251 Unlike with the destructor, it is expected that render() can reinitialize
252 all resources it needs when called after a call to releaseResources().
253
254 With OpenGL, the scenegraph's OpenGL context will be current both when
255 calling the destructor and this function.
256 */
257void QSGRenderNode::releaseResources()
258{
259}
260
261/*!
262 \enum QSGRenderNode::StateFlag
263
264 This enum is a bit mask identifying several states.
265
266 \value DepthState Depth
267 \value StencilState Stencil
268 \value ScissorState Scissor
269 \value ColorState Color
270 \value BlendState Blend
271 \value CullState Cull
272 \value ViewportState View poirt
273 \value RenderTargetState Render target
274
275 */
276
277/*!
278 \enum QSGRenderNode::RenderingFlag
279
280 Possible values for the bitmask returned from flags().
281
282 \value BoundedRectRendering Indicates that the implementation of render()
283 does not render outside the area reported from rect() in item
284 coordinates. Such node implementations can lead to more efficient rendering,
285 depending on the scenegraph backend. For example, the software backend can
286 continue to use the more optimal partial update path when all render nodes
287 in the scene have this flag set.
288
289 \value DepthAwareRendering Indicates that the implementations of render()
290 conforms to scenegraph expectations by only generating a Z value of 0 in
291 scene coordinates which is then transformed by the matrices retrieved from
292 RenderState::projectionMatrix() and matrix(), as described in the notes for
293 render(). Such node implementations can lead to more efficient rendering,
294 depending on the scenegraph backend. For example, the batching OpenGL
295 renderer can continue to use a more optimal path when all render nodes in
296 the scene have this flag set.
297
298 \value OpaqueRendering Indicates that the implementation of render() writes
299 out opaque pixels for the entire area reported from rect(). By default the
300 renderers must assume that render() can also output semi or fully
301 transparent pixels. Setting this flag can improve performance in some
302 cases.
303
304 \sa render(), rect()
305 */
306
307/*!
308 \return flags describing the behavior of this render node.
309
310 The default implementation returns 0.
311
312 \sa RenderingFlag, rect()
313 */
314QSGRenderNode::RenderingFlags QSGRenderNode::flags() const
315{
316 return {};
317}
318
319/*!
320 \return the bounding rectangle in item coordinates for the area render()
321 touches. The value is only in use when flags() includes
322 BoundedRectRendering, ignored otherwise.
323
324 Reporting the rectangle in combination with BoundedRectRendering is
325 particularly important with the \c software backend because otherwise
326 having a rendernode in the scene would trigger fullscreen updates, skipping
327 all partial update optimizations.
328
329 For rendernodes covering the entire area of a corresponding QQuickItem the
330 return value will be (0, 0, item->width(), item->height()).
331
332 \note Nodes are also free to render outside the boundaries specified by the
333 item's width and height, since the scenegraph nodes are not bounded by the
334 QQuickItem geometry, as long as this is reported correctly from this function.
335
336 \sa flags()
337*/
338QRectF QSGRenderNode::rect() const
339{
340 return QRectF();
341}
342
343/*!
344 \return pointer to the current model-view matrix.
345 */
346const QMatrix4x4 *QSGRenderNode::matrix() const
347{
348 return d->m_matrix;
349}
350
351/*!
352 \return the current clip list.
353 */
354const QSGClipNode *QSGRenderNode::clipList() const
355{
356 return d->m_clip_list;
357}
358
359/*!
360 \return the current effective opacity.
361 */
362qreal QSGRenderNode::inheritedOpacity() const
363{
364 return d->m_opacity;
365}
366
367QSGRenderNode::RenderState::~RenderState()
368{
369}
370
371/*!
372 \fn const QMatrix4x4 *QSGRenderNode::RenderState::projectionMatrix() const
373
374 \return pointer to the current projection matrix.
375
376 The model-view matrix can be retrieved with QSGRenderNode::matrix().
377 Typically \c{projection * modelview} is the matrix that is then used in the
378 vertex shader to transform the vertices.
379 */
380
381/*!
382 \fn const QMatrix4x4 *QSGRenderNode::RenderState::scissorRect() const
383
384 \return the current scissor rectangle when clipping is active. x and y are
385 the bottom left coordinates.
386
387 \note Be aware of the differences between graphics APIs: for some the
388 scissor rect is only active when scissoring is enabled (for example,
389 OpenGL), while for others the scissor rect is equal to the viewport rect
390 when there is no need to scissor away anything (for example, Direct3D 12).
391 */
392
393/*!
394 \fn const QMatrix4x4 *QSGRenderNode::RenderState::scissorEnabled() const
395
396 \return the current state of scissoring.
397
398 \note Only relevant for graphics APIs that have a dedicated on/off state of
399 scissoring.
400 */
401
402/*!
403 \fn const QMatrix4x4 *QSGRenderNode::RenderState::stencilValue() const
404
405 \return the current stencil reference value when clipping is active.
406 */
407
408/*!
409 \fn const QMatrix4x4 *QSGRenderNode::RenderState::stencilEnabled() const
410
411 \return the current state of stencil testing.
412
413 \note With graphics APIs where stencil testing is enabled in pipeline state
414 objects, instead of individual state-setting commands, it is up to the
415 implementation of render() to enable stencil testing with operations
416 \c KEEP, comparison function \c EQUAL, and a read and write mask of \c 0xFF.
417 */
418
419/*!
420 \fn const QRegion *QSGRenderNode::RenderState::clipRegion() const
421
422 \return the current clip region or null for backends where clipping is
423 implemented via stencil or scissoring.
424
425 The software backend uses no projection, scissor or stencil, meaning most
426 of the render state is not in use. However, the clip region that can be set
427 on the QPainter still has to be communicated since reconstructing this
428 manually in render() is not reasonable. It can therefore be queried via
429 this function. The region is in world coordinates and can be passed
430 to QPainter::setClipRegion() with Qt::ReplaceClip. This must be done before
431 calling QPainter::setTransform() since the clip region is already mapped to
432 the transform provided in QSGRenderNode::matrix().
433 */
434
435/*!
436 \return pointer to a \a state value.
437
438 Reserved for future use.
439 */
440void *QSGRenderNode::RenderState::get(const char *state) const
441{
442 Q_UNUSED(state);
443 return nullptr;
444}
445
446QT_END_NAMESPACE
447

source code of qtdeclarative/src/quick/scenegraph/coreapi/qsgrendernode.cpp