1/****************************************************************************
2**
3** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the Qt3D 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 "qblitframebuffer.h"
41#include "qblitframebuffer_p.h"
42
43#include <Qt3DRender/qframegraphnodecreatedchange.h>
44
45QT_BEGIN_NAMESPACE
46
47namespace Qt3DRender {
48
49/*!
50 \class Qt3DRender::QBlitFramebuffer
51 \inmodule Qt3DRender
52 \since 5.10
53 \ingroup framegraph
54 \brief FrameGraph node to transfer a rectangle of pixel values from one
55 region of a render target to another.
56
57 This node inserts a \c glBlitFrameBuffer or an equivalent into the command
58 stream. This provides a more efficient method for copying rectangles
59 between textures or surface backbuffers wrapped by QRenderTarget than
60 drawing textured quads. It also supports scaling with the specified
61 interpolation method.
62
63 \note In practice the QBlitFramebuffer node will often be used in
64 combination with QNoDraw since a blit should not involve issuing draw calls
65 for any entities.
66
67*/
68/*!
69 \enum Qt3DRender::QBlitFramebuffer::InterpolationMethod
70
71 Specifies the interpolation applied if the image is stretched.
72
73 \value Nearest
74 Nearest-neighbor interpolation.
75 \value Linear
76 Linear interpolation.
77*/
78/*!
79 \property Qt3DRender::QBlitFramebuffer::destination
80
81 Specifies the destination render target. When not set, the destination
82 is assumed to be the default framebuffer (i.e. the backbuffer of
83 the current surface), if there is one.
84
85 \note the source and destination must not refer to the same render
86 target.
87*/
88/*!
89
90 \property Qt3DRender::QBlitFramebuffer::destinationAttachmentPoint
91
92 Specifies the target attachment point.
93*/
94
95/*!
96 \property Qt3DRender::QBlitFramebuffer::destinationRect
97
98 Specifies the destination rectangle. The coordinates are assumed to follow
99 the normal Qt coordinate system, meaning Y runs from top to bottom.
100*/
101
102/*!
103 \property Qt3DRender::QBlitFramebuffer::source
104
105 Specifies the source render target. When not set, the source is assumed to
106 be the default framebuffer (i.e. the backbuffer of the current surface), if
107 there is one.
108
109 \note the source and destination must not refer to the same render target.
110
111*/
112/*!
113 \property Qt3DRender::QBlitFramebuffer::sourceAttachmentPoint
114
115 Specifies the source attachment point.
116
117*/
118/*!
119 \property Qt3DRender::QBlitFramebuffer::sourceRect
120
121 Specifies the source rectangle. The coordinates are assumed to follow the
122 normal Qt coordinate system, meaning Y runs from top to bottom.
123 */
124
125
126/*!
127 \qmltype BlitFramebuffer
128 \inqmlmodule Qt3D.Render
129 \instantiates Qt3DRender::QBlitFramebuffer
130 \inherits FrameGraphNode
131 \since 5.10
132 \brief FrameGraph node to transfer a rectangle of pixel values from one
133 region of a render target to another.
134
135 This node inserts a \c glBlitFrameBuffer or an equivalent into the command
136 stream. This provides a more efficient method for copying rectangles
137 between textures or surface backbuffers wrapped by QRenderTarget than
138 drawing textured quads. It also supports scaling with the specified
139 interpolation method.
140
141 \note In practice the BlitFramebuffer node will often be used in
142 combination with NoDraw since a blit should not involve issuing draw calls
143 for any entities.
144*/
145
146/*!
147 \qmlproperty RenderTarget BlitFramebuffer::source
148
149 Specifies the source render target. When not set, the source is assumed to
150 be the default framebuffer (i.e. the backbuffer of the current surface), if
151 there is one.
152
153 \note the source and destination must not refer to the same render target.
154 */
155
156/*!
157 \qmlproperty RenderTarget BlitFramebuffer::destination
158
159 Specifies the destination render target. When not set, the destination is
160 assumed to be the default framebuffer (i.e. the backbuffer of the current
161 surface), if there is one.
162
163 \note the source and destination must not refer to the same render target.
164 */
165
166/*!
167 \qmlproperty Rect BlitFramebuffer::sourceRect
168
169 Specifies the source rectangle. The coordinates are assumed to follow the
170 normal Qt coordinate system, meaning Y runs from top to bottom.
171 */
172
173/*!
174 \qmlproperty Rect BlitFramebuffer::destinationRect
175
176 Specifies the destination rectangle. The coordinates are assumed to follow
177 the normal Qt coordinate system, meaning Y runs from top to bottom.
178 */
179
180/*!
181 \qmlproperty RenderTargetOutput.AttachmentPoint BlitFramebuffer::sourceAttachmentPoint
182
183 Specifies the source attachment point. Defaults to
184 RenderTargetOutput.AttachmentPoint.Color0.
185 */
186
187/*!
188 \qmlproperty RenderTargetOutput.AttachmentPoint BlitFramebuffer::destinationAttachmentPoint
189
190 Specifies the source attachment point. Defaults to
191 RenderTargetOutput.AttachmentPoint.Color0.
192 */
193
194/*!
195 \qmlproperty InterpolationMethod BlitFramebuffer::interpolationMethod
196
197 Specifies the interpolation applied if the image is stretched. Defaults to Linear.
198 */
199
200QBlitFramebufferPrivate::QBlitFramebufferPrivate()
201 : QFrameGraphNodePrivate()
202 , m_source(nullptr)
203 , m_destination(nullptr)
204 , m_sourceRect(QRect())
205 , m_destinationRect(QRect())
206 , m_sourceAttachmentPoint(Qt3DRender::QRenderTargetOutput::AttachmentPoint::Color0)
207 , m_destinationAttachmentPoint(Qt3DRender::QRenderTargetOutput::AttachmentPoint::Color0)
208 , m_interpolationMethod(QBlitFramebuffer::Linear)
209{
210}
211
212/*!
213 Constructs a new QBlitFramebuffer with the given \a parent.
214 */
215QBlitFramebuffer::QBlitFramebuffer(QNode *parent)
216 : QFrameGraphNode(*new QBlitFramebufferPrivate, parent)
217{
218
219}
220
221/*!
222 \internal
223 */
224QBlitFramebuffer::QBlitFramebuffer(QBlitFramebufferPrivate &dd, QNode *parent)
225 : QFrameGraphNode(dd, parent)
226{
227}
228
229/*!
230 Destructor.
231 */
232QBlitFramebuffer::~QBlitFramebuffer()
233{
234
235}
236
237/*!
238 \return the source render target.
239 */
240QRenderTarget *QBlitFramebuffer::source() const
241{
242 Q_D(const QBlitFramebuffer);
243 return d->m_source;
244}
245
246/*!
247 \return the destination render target.
248 */
249QRenderTarget *QBlitFramebuffer::destination() const
250{
251 Q_D(const QBlitFramebuffer);
252 return d->m_destination;
253}
254
255/*!
256 \return the source rectangle.
257 */
258QRectF QBlitFramebuffer::sourceRect() const
259{
260 Q_D(const QBlitFramebuffer);
261 return d->m_sourceRect;
262}
263
264/*!
265 \return the destination rectangle.
266 */
267QRectF QBlitFramebuffer::destinationRect() const
268{
269 Q_D(const QBlitFramebuffer);
270 return d->m_destinationRect;
271}
272
273/*!
274 \return the source attachment point.
275 */
276Qt3DRender::QRenderTargetOutput::AttachmentPoint QBlitFramebuffer::sourceAttachmentPoint() const
277{
278 Q_D(const QBlitFramebuffer);
279 return d->m_sourceAttachmentPoint;
280}
281
282/*!
283 \return the destination attachment point.
284 */
285QRenderTargetOutput::AttachmentPoint QBlitFramebuffer::destinationAttachmentPoint() const
286{
287 Q_D(const QBlitFramebuffer);
288 return d->m_destinationAttachmentPoint;
289}
290
291/*!
292 \return the interpolation method.
293 */
294QBlitFramebuffer::InterpolationMethod QBlitFramebuffer::interpolationMethod() const
295{
296 Q_D(const QBlitFramebuffer);
297 return d->m_interpolationMethod;
298}
299
300/*!
301 Sets the source render target. The default value is nullptr, in which
302 case the source is assumed to be be the default framebuffer (i.e. the
303 backbuffer of the current surface), if there is one.
304
305 \note the source and destination must not refer to the same render target.
306
307 \note As with other nodes, \a source gets automatically parented to the
308 QBlitFramebuffer instance when no parent has been set. The lifetime is also
309 tracked, meaning the source reverts to nullptr in case the currently set
310 \a source is destroyed.
311 */
312void QBlitFramebuffer::setSource(QRenderTarget *source)
313{
314 Q_D(QBlitFramebuffer);
315 if (d->m_source != source) {
316 if (d->m_source) {
317 // Remove bookkeeping connection
318 d->unregisterDestructionHelper(node: d->m_source);
319 }
320
321 d->m_source = source;
322
323 if (d->m_source) {
324 // Ensures proper bookkeeping. Calls us back with nullptr in case the rt gets destroyed.
325 d->registerDestructionHelper(node: d->m_source, func: &QBlitFramebuffer::setSource, d->m_source);
326
327 if (!d->m_source->parent())
328 d->m_source->setParent(this);
329 }
330
331 emit sourceChanged();
332 }
333}
334
335/*!
336 Sets the destination render target. The default value is nullptr, in which
337 case the destination is assumed to be be the default framebuffer (i.e. the
338 backbuffer of the current surface), if there is one.
339
340 \note the source and destination must not refer to the same render target.
341
342 \note As with other nodes, \a destination gets automatically parented to the
343 QBlitFramebuffer instance when no parent has been set. The lifetime is also
344 tracked, meaning the destination reverts to nullptr in case the currently set
345 \a destination is destroyed.
346 */
347void QBlitFramebuffer::setDestination(QRenderTarget *destination)
348{
349 Q_D(QBlitFramebuffer);
350 if (d->m_destination != destination) {
351 if (d->m_destination) {
352 // Remove bookkeeping connection
353 d->unregisterDestructionHelper(node: d->m_destination);
354 }
355
356 d->m_destination = destination;
357
358 if (d->m_destination) {
359 // Ensures proper bookkeeping. Calls us back with nullptr in case the rt gets destroyed.
360 d->registerDestructionHelper(node: d->m_destination, func: &QBlitFramebuffer::setDestination, d->m_destination);
361
362 if (!d->m_destination->parent())
363 d->m_destination->setParent(this);
364 }
365
366 emit destinationChanged();
367 }
368}
369
370// TO DO Qt6: convert QRectF to QRect
371/*!
372 Sets the source rectangle to \a inputRect. The coordinates are assumed to
373 follow the normal Qt coordinate system, meaning Y runs from top to bottom.
374 */
375void QBlitFramebuffer::setSourceRect(const QRectF &inputRect)
376{
377 Q_D(QBlitFramebuffer);
378 if (d->m_sourceRect != inputRect) {
379 d->m_sourceRect = inputRect.toRect();
380 emit sourceRectChanged();
381 }
382}
383
384/*!
385 Sets the destination rectangle to \a outputRect. The coordinates are assumed
386 to follow the normal Qt coordinate system, meaning Y runs from top to
387 bottom.
388 */
389void QBlitFramebuffer::setDestinationRect(const QRectF &outputRect)
390{
391 Q_D(QBlitFramebuffer);
392 if (d->m_destinationRect != outputRect) {
393 d->m_destinationRect = outputRect.toRect();
394 emit destinationRectChanged();
395 }
396}
397
398/*!
399 Sets the \a sourceAttachmentPoint. Defaults to
400 Qt3DRender::QRenderTargetOutput::AttachmentPoint::Color0.
401 */
402void QBlitFramebuffer::setSourceAttachmentPoint(Qt3DRender::QRenderTargetOutput::AttachmentPoint sourceAttachmentPoint)
403{
404 Q_D(QBlitFramebuffer);
405 if (d->m_sourceAttachmentPoint != sourceAttachmentPoint) {
406 d->m_sourceAttachmentPoint = sourceAttachmentPoint;
407 emit sourceAttachmentPointChanged();
408 }
409}
410
411/*!
412 Sets the \a destinationAttachmentPoint. Defaults to
413 Qt3DRender::QRenderTargetOutput::AttachmentPoint::Color0.
414 */
415void QBlitFramebuffer::setDestinationAttachmentPoint(QRenderTargetOutput::AttachmentPoint destinationAttachmentPoint)
416{
417 Q_D(QBlitFramebuffer);
418 if (d->m_destinationAttachmentPoint != destinationAttachmentPoint) {
419 d->m_destinationAttachmentPoint = destinationAttachmentPoint;
420 emit destinationAttachmentPointChanged();
421 }
422}
423
424/*!
425 Sets the \a interpolationMethod that is applied if the image is stretched.
426 Defaults to Linear.
427 */
428void QBlitFramebuffer::setInterpolationMethod(QBlitFramebuffer::InterpolationMethod interpolationMethod)
429{
430 Q_D(QBlitFramebuffer);
431 if (d->m_interpolationMethod != interpolationMethod) {
432 d->m_interpolationMethod = interpolationMethod;
433 emit interpolationMethodChanged();
434 }
435}
436
437/*!
438 \internal
439 */
440Qt3DCore::QNodeCreatedChangeBasePtr QBlitFramebuffer::createNodeCreationChange() const
441{
442 auto creationChange = QFrameGraphNodeCreatedChangePtr<QBlitFramebufferData>::create(arguments: this);
443 auto &data = creationChange->data;
444 Q_D(const QBlitFramebuffer);
445 data.m_sourceRect = d->m_sourceRect;
446 data.m_destinationRect = d->m_destinationRect;
447 data.m_sourceRenderTargetId = Qt3DCore::qIdForNode(node: d->m_source);
448 data.m_destinationRenderTargetId = Qt3DCore::qIdForNode(node: d->m_destination);
449 data.m_sourceAttachmentPoint = d->m_sourceAttachmentPoint;
450 data.m_destinationAttachmentPoint = d->m_destinationAttachmentPoint;
451 data.m_interpolationMethod = d->m_interpolationMethod;
452
453 return creationChange;
454}
455
456} // namespace Qt3DRender
457
458QT_END_NAMESPACE
459

source code of qt3d/src/render/framegraph/qblitframebuffer.cpp