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 "qsgabstractrenderer_p.h" |
41 | |
42 | QT_BEGIN_NAMESPACE |
43 | |
44 | /*! |
45 | \class QSGAbstractRenderer |
46 | \brief QSGAbstractRenderer gives access to the scene graph nodes and rendering of a QSGEngine. |
47 | \inmodule QtQuick |
48 | \since 5.4 |
49 | |
50 | A QSGAbstractRenderer created by a QSGEngine allows you to set your QSGNode |
51 | tree through setRootNode() and control the rendering viewport through |
52 | setDeviceRect(), setViewportRect() and setProjectionMatrixToRect(). |
53 | You can finally trigger the rendering to the desired framebuffer through |
54 | renderScene(). |
55 | |
56 | The QSGAbstractRenderer is only available when used with a QSGEngine |
57 | and isn't exposed when used internally by QQuickWindow. |
58 | |
59 | \sa QSGEngine, QSGNode |
60 | */ |
61 | |
62 | /*! |
63 | \enum QSGAbstractRenderer::ClearModeBit |
64 | |
65 | Used with setClearMode() to indicate which buffer should |
66 | be cleared before the scene render. |
67 | |
68 | \value ClearColorBuffer Clear the color buffer using clearColor(). |
69 | \value ClearDepthBuffer Clear the depth buffer. |
70 | \value ClearStencilBuffer Clear the stencil buffer. |
71 | |
72 | \sa setClearMode(), setClearColor() |
73 | */ |
74 | |
75 | /*! |
76 | \enum QSGAbstractRenderer::MatrixTransformFlag |
77 | |
78 | Used with setProjectionMatrixToRect() to indicate the expectations towards |
79 | the generated projection matrix. |
80 | |
81 | \value MatrixTransformFlipY The traditional assumption in Qt Quick is that |
82 | Y points up in the normalized device coordinate system. There is at least |
83 | one modern graphics API where this is not the case (Vulkan). This flag can |
84 | then be used to get a projection that is appropriate for such an API. |
85 | |
86 | \sa setProjectionMatrixToRect() |
87 | |
88 | \since 5.14 |
89 | */ |
90 | |
91 | /*! |
92 | \fn void QSGAbstractRenderer::renderScene(GLuint fboId = 0) |
93 | |
94 | Render the scene to the specified \a fboId |
95 | |
96 | If \a fboId isn't specified, the scene graph will be rendered |
97 | to the default framebuffer. You will have to call |
98 | QOpenGLContext::swapBuffers() yourself afterward. |
99 | |
100 | The framebuffer specified by \a fboId will be bound automatically. |
101 | |
102 | \sa QOpenGLContext::swapBuffers(), QOpenGLFramebufferObject::handle() |
103 | */ |
104 | |
105 | /*! |
106 | \fn void QSGAbstractRenderer::sceneGraphChanged() |
107 | |
108 | This signal is emitted on the first modification of a node in |
109 | the tree after the last scene render. |
110 | */ |
111 | |
112 | /*! |
113 | \internal |
114 | */ |
115 | QSGAbstractRendererPrivate::QSGAbstractRendererPrivate() |
116 | : m_root_node(nullptr) |
117 | , m_clear_color(Qt::transparent) |
118 | , m_clear_mode(QSGAbstractRenderer::ClearColorBuffer | QSGAbstractRenderer::ClearDepthBuffer) |
119 | { |
120 | } |
121 | |
122 | /*! |
123 | \internal |
124 | */ |
125 | QSGAbstractRenderer::QSGAbstractRenderer(QObject *parent) |
126 | : QObject(*new QSGAbstractRendererPrivate, parent) |
127 | { |
128 | } |
129 | |
130 | /*! |
131 | \internal |
132 | */ |
133 | QSGAbstractRenderer::~QSGAbstractRenderer() |
134 | { |
135 | } |
136 | |
137 | /*! |
138 | Sets the \a node as the root of the QSGNode scene |
139 | that you want to render. You need to provide a \a node |
140 | before trying to render the scene. |
141 | |
142 | \note This doesn't take ownership of \a node. |
143 | |
144 | \sa rootNode() |
145 | */ |
146 | void QSGAbstractRenderer::setRootNode(QSGRootNode *node) |
147 | { |
148 | Q_D(QSGAbstractRenderer); |
149 | if (d->m_root_node == node) |
150 | return; |
151 | if (d->m_root_node) { |
152 | d->m_root_node->m_renderers.removeOne(t: this); |
153 | nodeChanged(node: d->m_root_node, state: QSGNode::DirtyNodeRemoved); |
154 | } |
155 | d->m_root_node = node; |
156 | if (d->m_root_node) { |
157 | Q_ASSERT(!d->m_root_node->m_renderers.contains(this)); |
158 | d->m_root_node->m_renderers << this; |
159 | nodeChanged(node: d->m_root_node, state: QSGNode::DirtyNodeAdded); |
160 | } |
161 | } |
162 | |
163 | /*! |
164 | Returns the root of the QSGNode scene. |
165 | |
166 | \sa setRootNode() |
167 | */ |
168 | QSGRootNode *QSGAbstractRenderer::rootNode() const |
169 | { |
170 | Q_D(const QSGAbstractRenderer); |
171 | return d->m_root_node; |
172 | } |
173 | |
174 | |
175 | /*! |
176 | \fn void QSGAbstractRenderer::setDeviceRect(const QSize &size) |
177 | \overload |
178 | |
179 | Sets the \a size of the surface being rendered to. |
180 | |
181 | \sa deviceRect() |
182 | */ |
183 | |
184 | /*! |
185 | Sets \a rect as the geometry of the surface being rendered to. |
186 | |
187 | \sa deviceRect() |
188 | */ |
189 | void QSGAbstractRenderer::setDeviceRect(const QRect &rect) |
190 | { |
191 | Q_D(QSGAbstractRenderer); |
192 | d->m_device_rect = rect; |
193 | } |
194 | |
195 | /*! |
196 | Returns the device rect of the surface being rendered to. |
197 | |
198 | \sa setDeviceRect() |
199 | */ |
200 | QRect QSGAbstractRenderer::deviceRect() const |
201 | { |
202 | Q_D(const QSGAbstractRenderer); |
203 | return d->m_device_rect; |
204 | } |
205 | |
206 | /*! |
207 | \fn void QSGAbstractRenderer::setViewportRect(const QSize &size) |
208 | \overload |
209 | |
210 | Sets the \a size of the viewport to render |
211 | on the surface. |
212 | |
213 | \sa viewportRect() |
214 | */ |
215 | |
216 | /*! |
217 | Sets \a rect as the geometry of the viewport to render |
218 | on the surface. |
219 | |
220 | \sa viewportRect() |
221 | */ |
222 | void QSGAbstractRenderer::setViewportRect(const QRect &rect) |
223 | { |
224 | Q_D(QSGAbstractRenderer); |
225 | d->m_viewport_rect = rect; |
226 | } |
227 | |
228 | /*! |
229 | Returns the rect of the viewport to render. |
230 | |
231 | \sa setViewportRect() |
232 | */ |
233 | QRect QSGAbstractRenderer::viewportRect() const |
234 | { |
235 | Q_D(const QSGAbstractRenderer); |
236 | return d->m_viewport_rect; |
237 | } |
238 | |
239 | /*! |
240 | Convenience method that calls setProjectionMatrix() with an |
241 | orthographic matrix generated from \a rect. |
242 | |
243 | \note This function assumes that the graphics API uses Y up in its |
244 | normalized device coordinate system. |
245 | |
246 | \sa setProjectionMatrix(), projectionMatrix() |
247 | */ |
248 | void QSGAbstractRenderer::setProjectionMatrixToRect(const QRectF &rect) |
249 | { |
250 | QMatrix4x4 matrix; |
251 | matrix.ortho(left: rect.x(), |
252 | right: rect.x() + rect.width(), |
253 | bottom: rect.y() + rect.height(), |
254 | top: rect.y(), |
255 | nearPlane: 1, |
256 | farPlane: -1); |
257 | setProjectionMatrix(matrix); |
258 | setProjectionMatrixWithNativeNDC(matrix); |
259 | } |
260 | |
261 | /*! |
262 | Convenience method that calls setProjectionMatrix() with an |
263 | orthographic matrix generated from \a rect. |
264 | |
265 | Set MatrixTransformFlipY in \a flags when the graphics API uses Y down in |
266 | its normalized device coordinate system (for example, Vulkan). |
267 | |
268 | \sa setProjectionMatrix(), projectionMatrix() |
269 | |
270 | \since 5.14 |
271 | */ |
272 | void QSGAbstractRenderer::setProjectionMatrixToRect(const QRectF &rect, MatrixTransformFlags flags) |
273 | { |
274 | const bool flipY = flags.testFlag(flag: MatrixTransformFlipY); |
275 | QMatrix4x4 matrix; |
276 | matrix.ortho(left: rect.x(), |
277 | right: rect.x() + rect.width(), |
278 | bottom: flipY ? rect.y() : rect.y() + rect.height(), |
279 | top: flipY ? rect.y() + rect.height() : rect.y(), |
280 | nearPlane: 1, |
281 | farPlane: -1); |
282 | setProjectionMatrix(matrix); |
283 | |
284 | if (flipY) { |
285 | matrix.setToIdentity(); |
286 | matrix.ortho(left: rect.x(), |
287 | right: rect.x() + rect.width(), |
288 | bottom: rect.y() + rect.height(), |
289 | top: rect.y(), |
290 | nearPlane: 1, |
291 | farPlane: -1); |
292 | } |
293 | setProjectionMatrixWithNativeNDC(matrix); |
294 | } |
295 | |
296 | /*! |
297 | Use \a matrix to project the QSGNode coordinates onto surface pixels. |
298 | |
299 | \sa projectionMatrix(), setProjectionMatrixToRect() |
300 | */ |
301 | void QSGAbstractRenderer::setProjectionMatrix(const QMatrix4x4 &matrix) |
302 | { |
303 | Q_D(QSGAbstractRenderer); |
304 | d->m_projection_matrix = matrix; |
305 | } |
306 | |
307 | /*! |
308 | \internal |
309 | */ |
310 | void QSGAbstractRenderer::setProjectionMatrixWithNativeNDC(const QMatrix4x4 &matrix) |
311 | { |
312 | Q_D(QSGAbstractRenderer); |
313 | d->m_projection_matrix_native_ndc = matrix; |
314 | } |
315 | |
316 | /*! |
317 | Returns the projection matrix |
318 | |
319 | \sa setProjectionMatrix(), setProjectionMatrixToRect() |
320 | */ |
321 | QMatrix4x4 QSGAbstractRenderer::projectionMatrix() const |
322 | { |
323 | Q_D(const QSGAbstractRenderer); |
324 | return d->m_projection_matrix; |
325 | } |
326 | |
327 | /*! |
328 | \internal |
329 | */ |
330 | QMatrix4x4 QSGAbstractRenderer::projectionMatrixWithNativeNDC() const |
331 | { |
332 | Q_D(const QSGAbstractRenderer); |
333 | return d->m_projection_matrix_native_ndc; |
334 | } |
335 | |
336 | /*! |
337 | Use \a color to clear the framebuffer when clearMode() is |
338 | set to QSGAbstractRenderer::ClearColorBuffer. |
339 | |
340 | \sa clearColor(), setClearMode() |
341 | */ |
342 | void QSGAbstractRenderer::setClearColor(const QColor &color) |
343 | { |
344 | Q_D(QSGAbstractRenderer); |
345 | d->m_clear_color = color; |
346 | } |
347 | |
348 | /*! |
349 | Returns the color that clears the framebuffer at the beginning |
350 | of the rendering. |
351 | |
352 | \sa setClearColor(), clearMode() |
353 | */ |
354 | QColor QSGAbstractRenderer::clearColor() const |
355 | { |
356 | Q_D(const QSGAbstractRenderer); |
357 | return d->m_clear_color; |
358 | } |
359 | |
360 | /*! |
361 | Defines which attachment of the framebuffer should be cleared |
362 | before each scene render with the \a mode flag. |
363 | |
364 | \sa clearMode(), setClearColor() |
365 | */ |
366 | void QSGAbstractRenderer::setClearMode(ClearMode mode) |
367 | { |
368 | Q_D(QSGAbstractRenderer); |
369 | d->m_clear_mode = mode; |
370 | } |
371 | |
372 | /*! |
373 | Flags defining which attachment of the framebuffer will be cleared |
374 | before each scene render. |
375 | |
376 | \sa setClearMode(), clearColor() |
377 | */ |
378 | QSGAbstractRenderer::ClearMode QSGAbstractRenderer::clearMode() const |
379 | { |
380 | Q_D(const QSGAbstractRenderer); |
381 | return d->m_clear_mode; |
382 | } |
383 | |
384 | /*! |
385 | \fn void QSGAbstractRenderer::nodeChanged(QSGNode *node, QSGNode::DirtyState state) |
386 | \internal |
387 | */ |
388 | |
389 | QT_END_NAMESPACE |
390 | |
391 | #include "moc_qsgabstractrenderer.cpp" |
392 | |