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