1// Copyright (C) 2020 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 "qquickrendertarget_p.h"
5#include <rhi/qrhi.h>
6#include <QtQuick/private/qquickitem_p.h>
7#include <QtQuick/private/qquickwindow_p.h>
8#include <QtQuick/private/qsgrhisupport_p.h>
9
10QT_BEGIN_NAMESPACE
11
12/*!
13 \class QQuickRenderTarget
14 \since 6.0
15 \inmodule QtQuick
16
17 \brief The QQuickRenderTarget class provides an opaque container for native
18 graphics resources specifying a render target, and associated metadata.
19
20 \sa QQuickWindow::setRenderTarget(), QQuickGraphicsDevice
21*/
22
23QQuickRenderTargetPrivate::QQuickRenderTargetPrivate()
24 : ref(1)
25{
26}
27
28QQuickRenderTargetPrivate::QQuickRenderTargetPrivate(const QQuickRenderTargetPrivate *other)
29 : ref(1),
30 type(other->type),
31 pixelSize(other->pixelSize),
32 devicePixelRatio(other->devicePixelRatio),
33 sampleCount(other->sampleCount),
34 u(other->u),
35 mirrorVertically(other->mirrorVertically)
36{
37}
38
39/*!
40 Constructs a default QQuickRenderTarget that does not reference any native
41 objects.
42 */
43QQuickRenderTarget::QQuickRenderTarget()
44 : d(new QQuickRenderTargetPrivate)
45{
46}
47
48/*!
49 \internal
50 */
51void QQuickRenderTarget::detach()
52{
53 qAtomicDetach(d);
54}
55
56/*!
57 \internal
58 */
59QQuickRenderTarget::QQuickRenderTarget(const QQuickRenderTarget &other)
60 : d(other.d)
61{
62 d->ref.ref();
63}
64
65/*!
66 \internal
67 */
68QQuickRenderTarget &QQuickRenderTarget::operator=(const QQuickRenderTarget &other)
69{
70 qAtomicAssign(d, x: other.d);
71 return *this;
72}
73
74/*!
75 Destructor.
76 */
77QQuickRenderTarget::~QQuickRenderTarget()
78{
79 if (!d->ref.deref())
80 delete d;
81}
82
83/*!
84 \return true if this QQuickRenderTarget is default constructed, referencing
85 no native objects.
86 */
87bool QQuickRenderTarget::isNull() const
88{
89 return d->type == QQuickRenderTargetPrivate::Type::Null;
90}
91
92/*!
93 \return the device pixel ratio for the render target. This is the ratio
94 between \e{device pixels} and \e{device independent pixels}.
95
96 The default device pixel ratio is 1.0.
97
98 \since 6.3
99
100 \sa setDevicePixelRatio()
101*/
102qreal QQuickRenderTarget::devicePixelRatio() const
103{
104 return d->devicePixelRatio;
105}
106
107/*!
108 Sets the device pixel ratio for this render target to \a ratio. This is
109 the ratio between \e{device pixels} and \e{device independent pixels}.
110
111 Note that the specified device pixel ratio value will be ignored if
112 QQuickRenderControl::renderWindow() is re-implemented to return a valid
113 QWindow.
114
115 \since 6.3
116
117 \sa devicePixelRatio()
118*/
119void QQuickRenderTarget::setDevicePixelRatio(qreal ratio)
120{
121 if (d->devicePixelRatio == ratio)
122 return;
123
124 detach();
125 d->devicePixelRatio = ratio;
126}
127
128/*!
129 \return Returns whether the render target is mirrored vertically.
130
131 The default value is \c {false}.
132
133 \since 6.4
134
135 \sa setMirrorVertically()
136*/
137bool QQuickRenderTarget::mirrorVertically() const
138{
139 return d->mirrorVertically;
140}
141
142
143/*!
144 Sets the size of the render target contents should be mirrored vertically to
145 \a enable when drawing. This allows easy integration of third-party rendering
146 code that does not follow the standard expectations.
147
148 \note This function should not be used when using the \c software backend.
149
150 \since 6.4
151
152 \sa mirrorVertically()
153 */
154void QQuickRenderTarget::setMirrorVertically(bool enable)
155{
156 if (d->mirrorVertically == enable)
157 return;
158
159 detach();
160 d->mirrorVertically = enable;
161}
162
163/*!
164 \return a new QQuickRenderTarget referencing an OpenGL texture object
165 specified by \a textureId.
166
167 \a format specifies the native internal format of the
168 texture. Only texture formats that are supported by Qt's rendering
169 infrastructure should be used.
170
171 \a pixelSize specifies the size of the image, in pixels. Currently only 2D
172 textures are supported.
173
174 \a sampleCount specific the number of samples. 0 or 1 means no
175 multisampling, while a value like 4 or 8 states that the native object is a
176 multisample texture.
177
178 The texture is used as the first color attachment of the render target used
179 by the Qt Quick scenegraph. A depth-stencil buffer, if applicable, is
180 created and used automatically.
181
182 The OpenGL object name \a textureId must be a valid name in the rendering
183 context used by the Qt Quick scenegraph.
184
185 \note the resulting QQuickRenderTarget does not own any native resources,
186 it merely contains references and the associated metadata of the size and
187 sample count. It is the caller's responsibility to ensure that the native
188 resource exists as long as necessary.
189
190 \since 6.4
191
192 \sa QQuickWindow::setRenderTarget(), QQuickRenderControl
193 */
194#if QT_CONFIG(opengl) || defined(Q_QDOC)
195QQuickRenderTarget QQuickRenderTarget::fromOpenGLTexture(uint textureId, uint format,
196 const QSize &pixelSize, int sampleCount)
197{
198 QQuickRenderTarget rt;
199 QQuickRenderTargetPrivate *d = QQuickRenderTargetPrivate::get(rt: &rt);
200
201 if (!textureId) {
202 qWarning(msg: "QQuickRenderTarget: textureId is invalid");
203 return rt;
204 }
205
206 if (pixelSize.isEmpty()) {
207 qWarning(msg: "QQuickRenderTarget: Cannot create with empty size");
208 return rt;
209 }
210
211 d->type = QQuickRenderTargetPrivate::Type::NativeTexture;
212 d->pixelSize = pixelSize;
213 d->sampleCount = qMax(a: 1, b: sampleCount);
214
215 auto rhiFormat = QSGRhiSupport::toRhiTextureFormatFromGL(format);
216 d->u.nativeTexture = { .object: textureId, .layoutOrState: 0, .rhiFormat: uint(rhiFormat), .rhiFlags: 0 };
217
218 return rt;
219}
220
221/*!
222 \overload
223
224 \return a new QQuickRenderTarget referencing an OpenGL texture
225 object specified by \a textureId. The texture is assumed to have a
226 format of GL_RGBA (GL_RGBA8).
227
228 \a pixelSize specifies the size of the image, in pixels. Currently
229 only 2D textures are supported.
230
231 \a sampleCount specific the number of samples. 0 or 1 means no
232 multisampling, while a value like 4 or 8 states that the native
233 object is a multisample texture.
234
235 The texture is used as the first color attachment of the render target used
236 by the Qt Quick scenegraph. A depth-stencil buffer, if applicable, is
237 created and used automatically.
238
239 The OpenGL object name \a textureId must be a valid name in the rendering
240 context used by the Qt Quick scenegraph.
241
242 \note the resulting QQuickRenderTarget does not own any native resources,
243 it merely contains references and the associated metadata of the size and
244 sample count. It is the caller's responsibility to ensure that the native
245 resource exists as long as necessary.
246
247 \sa QQuickWindow::setRenderTarget(), QQuickRenderControl
248*/
249QQuickRenderTarget QQuickRenderTarget::fromOpenGLTexture(uint textureId, const QSize &pixelSize, int sampleCount)
250{
251 return fromOpenGLTexture(textureId, format: 0, pixelSize, sampleCount);
252}
253
254/*!
255 \return a new QQuickRenderTarget referencing an OpenGL renderbuffer object
256 specified by \a renderbufferId.
257
258 The renderbuffer will be used as the color attachment for the internal
259 framebuffer object. This function is provided to allow targeting
260 renderbuffers that are created by the application with some external buffer
261 underneath, such as an EGLImageKHR. Once the application has called
262 \l{https://www.khronos.org/registry/OpenGL/extensions/OES/OES_EGL_image.txt}{glEGLImageTargetRenderbufferStorageOES},
263 the renderbuffer can be passed to this function.
264
265 \a pixelSize specifies the size of the image, in pixels.
266
267 \a sampleCount specific the number of samples. 0 or 1 means no
268 multisampling, while a value like 4 or 8 states that the native object is a
269 multisample renderbuffer.
270
271 \note the resulting QQuickRenderTarget does not own any native resources,
272 it merely contains references and the associated metadata of the size and
273 sample count. It is the caller's responsibility to ensure that the native
274 resource exists as long as necessary.
275
276 \since 6.2
277
278 \sa QQuickWindow::setRenderTarget(), QQuickRenderControl
279 */
280QQuickRenderTarget QQuickRenderTarget::fromOpenGLRenderBuffer(uint renderbufferId, const QSize &pixelSize, int sampleCount)
281{
282 QQuickRenderTarget rt;
283 QQuickRenderTargetPrivate *d = QQuickRenderTargetPrivate::get(rt: &rt);
284
285 if (!renderbufferId) {
286 qWarning(msg: "QQuickRenderTarget: renderbufferId is invalid");
287 return rt;
288 }
289
290 if (pixelSize.isEmpty()) {
291 qWarning(msg: "QQuickRenderTarget: Cannot create with empty size");
292 return rt;
293 }
294
295 d->type = QQuickRenderTargetPrivate::Type::NativeRenderbuffer;
296 d->pixelSize = pixelSize;
297 d->sampleCount = qMax(a: 1, b: sampleCount);
298 d->u.nativeRenderbufferObject = renderbufferId;
299
300 return rt;
301}
302#endif
303
304/*!
305 \return a new QQuickRenderTarget referencing a D3D11 texture object
306 specified by \a texture.
307
308 \a format specifies the DXGI_FORMAT of the texture. Only texture formats
309 that are supported by Qt's rendering infrastructure should be used.
310
311 \a pixelSize specifies the size of the image, in pixels. Currently only 2D
312 textures are supported.
313
314 \a sampleCount specific the number of samples. 0 or 1 means no
315 multisampling, while a value like 4 or 8 states that the native object is a
316 multisample texture.
317
318 The texture is used as the first color attachment of the render target used
319 by the Qt Quick scenegraph. A depth-stencil buffer, if applicable, is
320 created and used automatically.
321
322 \note the resulting QQuickRenderTarget does not own any native resources,
323 it merely contains references and the associated metadata of the size and
324 sample count. It is the caller's responsibility to ensure that the native
325 resource exists as long as necessary.
326
327 \since 6.4
328
329 \sa QQuickWindow::setRenderTarget(), QQuickRenderControl
330 */
331#if defined(Q_OS_WIN) || defined(Q_QDOC)
332QQuickRenderTarget QQuickRenderTarget::fromD3D11Texture(void *texture, uint format,
333 const QSize &pixelSize, int sampleCount)
334{
335 QQuickRenderTarget rt;
336 QQuickRenderTargetPrivate *d = QQuickRenderTargetPrivate::get(&rt);
337
338 if (!texture) {
339 qWarning("QQuickRenderTarget: texture is null");
340 return rt;
341 }
342
343 if (pixelSize.isEmpty()) {
344 qWarning("QQuickRenderTarget: Cannot create with empty size");
345 return rt;
346 }
347
348 d->type = QQuickRenderTargetPrivate::Type::NativeTexture;
349 d->pixelSize = pixelSize;
350 d->sampleCount = qMax(1, sampleCount);
351
352 QRhiTexture::Flags flags;
353 auto rhiFormat = QSGRhiSupport::toRhiTextureFormatFromDXGI(format, &flags);
354 d->u.nativeTexture = { quint64(texture), 0, uint(rhiFormat), uint(flags) };
355
356 return rt;
357}
358
359/*!
360 \overload
361
362 \return a new QQuickRenderTarget referencing a D3D11 texture
363 object specified by \a texture. The texture is assumed to have a
364 format of DXGI_FORMAT_R8G8B8A8_UNORM.
365
366 \a pixelSize specifies the size of the image, in pixels. Currently only 2D
367 textures are supported.
368
369 \a sampleCount specific the number of samples. 0 or 1 means no
370 multisampling, while a value like 4 or 8 states that the native object is a
371 multisample texture.
372
373 The texture is used as the first color attachment of the render target used
374 by the Qt Quick scenegraph. A depth-stencil buffer, if applicable, is
375 created and used automatically.
376
377 \note the resulting QQuickRenderTarget does not own any native resources,
378 it merely contains references and the associated metadata of the size and
379 sample count. It is the caller's responsibility to ensure that the native
380 resource exists as long as necessary.
381
382 \sa QQuickWindow::setRenderTarget(), QQuickRenderControl
383*/
384QQuickRenderTarget QQuickRenderTarget::fromD3D11Texture(void *texture, const QSize &pixelSize, int sampleCount)
385{
386 return fromD3D11Texture(texture, 0 /* DXGI_FORMAT_UNKNOWN */, pixelSize, sampleCount);
387}
388
389/*!
390 \return a new QQuickRenderTarget referencing a D3D12 texture object
391 specified by \a texture.
392
393 \a resourceState must a valid bitmask with bits from D3D12_RESOURCE_STATES,
394 specifying the resource's current state.
395
396 \a format specifies the DXGI_FORMAT of the texture. Only texture formats
397 that are supported by Qt's rendering infrastructure should be used.
398
399 \a pixelSize specifies the size of the image, in pixels. Currently only 2D
400 textures are supported.
401
402 \a sampleCount specific the number of samples. 0 or 1 means no
403 multisampling, while a value like 4 or 8 states that the native object is a
404 multisample texture.
405
406 The texture is used as the first color attachment of the render target used
407 by the Qt Quick scenegraph. A depth-stencil buffer, if applicable, is
408 created and used automatically.
409
410 \note the resulting QQuickRenderTarget does not own any native resources,
411 it merely contains references and the associated metadata of the size and
412 sample count. It is the caller's responsibility to ensure that the native
413 resource exists as long as necessary.
414
415 \since 6.6
416
417 \sa QQuickWindow::setRenderTarget(), QQuickRenderControl
418 */
419QQuickRenderTarget QQuickRenderTarget::fromD3D12Texture(void *texture,
420 int resourceState,
421 uint format,
422 const QSize &pixelSize,
423 int sampleCount)
424{
425 QQuickRenderTarget rt;
426 QQuickRenderTargetPrivate *d = QQuickRenderTargetPrivate::get(&rt);
427
428 if (!texture) {
429 qWarning("QQuickRenderTarget: texture is null");
430 return rt;
431 }
432
433 if (pixelSize.isEmpty()) {
434 qWarning("QQuickRenderTarget: Cannot create with empty size");
435 return rt;
436 }
437
438 d->type = QQuickRenderTargetPrivate::Type::NativeTexture;
439 d->pixelSize = pixelSize;
440 d->sampleCount = qMax(1, sampleCount);
441
442 QRhiTexture::Flags flags;
443 auto rhiFormat = QSGRhiSupport::toRhiTextureFormatFromDXGI(format, &flags);
444 d->u.nativeTexture = { quint64(texture), resourceState, uint(rhiFormat), uint(flags) };
445
446 return rt;
447}
448#endif
449
450/*!
451 \return a new QQuickRenderTarget referencing a Metal texture object
452 specified by \a texture.
453
454 \a format specifies the MTLPixelFormat of the texture. Only texture formats
455 that are supported by Qt's rendering infrastructure should be used.
456
457 \a pixelSize specifies the size of the image, in pixels. Currently only 2D
458 textures are supported.
459
460 \a sampleCount specific the number of samples. 0 or 1 means no
461 multisampling, while a value like 4 or 8 states that the native object is a
462 multisample texture.
463
464 The texture is used as the first color attachment of the render target used
465 by the Qt Quick scenegraph. A depth-stencil buffer, if applicable, is
466 created and used automatically.
467
468 \note the resulting QQuickRenderTarget does not own any native resources,
469 it merely contains references and the associated metadata of the size and
470 sample count. It is the caller's responsibility to ensure that the native
471 resource exists as long as necessary.
472
473 \since 6.4
474
475 \sa QQuickWindow::setRenderTarget(), QQuickRenderControl
476 */
477#if defined(Q_OS_MACOS) || defined(Q_OS_IOS) || defined(Q_QDOC)
478QQuickRenderTarget QQuickRenderTarget::fromMetalTexture(MTLTexture *texture, uint format,
479 const QSize &pixelSize, int sampleCount)
480{
481 QQuickRenderTarget rt;
482 QQuickRenderTargetPrivate *d = QQuickRenderTargetPrivate::get(&rt);
483
484 if (!texture) {
485 qWarning("QQuickRenderTarget: texture is null");
486 return rt;
487 }
488
489 if (pixelSize.isEmpty()) {
490 qWarning("QQuickRenderTarget: Cannot create with empty size");
491 return rt;
492 }
493
494 d->type = QQuickRenderTargetPrivate::Type::NativeTexture;
495 d->pixelSize = pixelSize;
496 d->sampleCount = qMax(1, sampleCount);
497
498 QRhiTexture::Flags flags;
499 auto rhiFormat = QSGRhiSupport::toRhiTextureFormatFromMetal(format, &flags);
500 d->u.nativeTexture = { quint64(texture), 0, uint(rhiFormat), uint(flags) };
501
502 return rt;
503}
504
505/*!
506 \overload
507
508 \return a new QQuickRenderTarget referencing a Metal texture object
509 specified by \a texture. The texture is assumed to have a format of
510 MTLPixelFormatRGBA8Unorm.
511
512 \a pixelSize specifies the size of the image, in pixels. Currently only 2D
513 textures are supported.
514
515 \a sampleCount specific the number of samples. 0 or 1 means no
516 multisampling, while a value like 4 or 8 states that the native object is a
517 multisample texture.
518
519 The texture is used as the first color attachment of the render target used
520 by the Qt Quick scenegraph. A depth-stencil buffer, if applicable, is
521 created and used automatically.
522
523 \note the resulting QQuickRenderTarget does not own any native resources,
524 it merely contains references and the associated metadata of the size and
525 sample count. It is the caller's responsibility to ensure that the native
526 resource exists as long as necessary.
527
528 \sa QQuickWindow::setRenderTarget(), QQuickRenderControl
529*/
530QQuickRenderTarget QQuickRenderTarget::fromMetalTexture(MTLTexture *texture, const QSize &pixelSize, int sampleCount)
531{
532 return fromMetalTexture(texture, 0 /* MTLPixelFormatInvalid */, pixelSize, sampleCount);
533}
534#endif
535
536/*!
537 \return a new QQuickRenderTarget referencing a Vulkan image object
538 specified by \a image. The current \a layout of the image must be provided
539 as well.
540
541 \a format specifies the VkFormat of the image. Only image formats that are
542 supported by Qt's rendering infrastructure should be used.
543
544 \a pixelSize specifies the size of the image, in pixels. Currently only 2D
545 textures are supported.
546
547 \a sampleCount specific the number of samples. 0 or 1 means no
548 multisampling, while a value like 4 or 8 states that the native object is a
549 multisample texture.
550
551 The image is used as the first color attachment of the render target used
552 by the Qt Quick scenegraph. A depth-stencil buffer, if applicable, is
553 created and used automatically.
554
555 \note the resulting QQuickRenderTarget does not own any native resources,
556 it merely contains references and the associated metadata of the size and
557 sample count. It is the caller's responsibility to ensure that the native
558 resource exists as long as necessary.
559
560 \since 6.4
561
562 \sa QQuickWindow::setRenderTarget(), QQuickRenderControl
563 */
564#if QT_CONFIG(vulkan) || defined(Q_QDOC)
565QQuickRenderTarget QQuickRenderTarget::fromVulkanImage(VkImage image, VkImageLayout layout, VkFormat format,
566 const QSize &pixelSize, int sampleCount)
567{
568 QQuickRenderTarget rt;
569 QQuickRenderTargetPrivate *d = QQuickRenderTargetPrivate::get(rt: &rt);
570
571 if (image == VK_NULL_HANDLE) {
572 qWarning(msg: "QQuickRenderTarget: image is invalid");
573 return rt;
574 }
575
576 if (pixelSize.isEmpty()) {
577 qWarning(msg: "QQuickRenderTarget: Cannot create with empty size");
578 return rt;
579 }
580
581 d->type = QQuickRenderTargetPrivate::Type::NativeTexture;
582 d->pixelSize = pixelSize;
583 d->sampleCount = qMax(a: 1, b: sampleCount);
584
585 QRhiTexture::Flags flags;
586 auto rhiFormat = QSGRhiSupport::toRhiTextureFormatFromVulkan(format, flags: &flags);
587 d->u.nativeTexture = { .object: quint64(image), .layoutOrState: layout, .rhiFormat: uint(rhiFormat), .rhiFlags: uint(flags) };
588
589 return rt;
590}
591
592/*!
593 \overload
594
595 \return a new QQuickRenderTarget referencing a Vulkan image object specified
596 by \a image. The image is assumed to have a format of
597 VK_FORMAT_R8G8B8A8_UNORM.
598
599 \a pixelSize specifies the size of the image, in pixels. Currently only 2D
600 textures are supported.
601
602 \a sampleCount specific the number of samples. 0 or 1 means no
603 multisampling, while a value like 4 or 8 states that the native object is a
604 multisample texture.
605
606 The texture is used as the first color attachment of the render target used
607 by the Qt Quick scenegraph. A depth-stencil buffer, if applicable, is
608 created and used automatically.
609
610 \note the resulting QQuickRenderTarget does not own any native resources,
611 it merely contains references and the associated metadata of the size and
612 sample count. It is the caller's responsibility to ensure that the native
613 resource exists as long as necessary.
614
615 \sa QQuickWindow::setRenderTarget(), QQuickRenderControl
616*/
617QQuickRenderTarget QQuickRenderTarget::fromVulkanImage(VkImage image, VkImageLayout layout, const QSize &pixelSize, int sampleCount)
618{
619 return fromVulkanImage(image, layout, format: VK_FORMAT_UNDEFINED, pixelSize, sampleCount);
620}
621#endif
622
623/*!
624 \return a new QQuickRenderTarget referencing an existing \a renderTarget.
625
626 \a renderTarget will in most cases be a QRhiTextureRenderTarget, which
627 allows directing the Qt Quick scene's rendering into a QRhiTexture.
628
629 \note the resulting QQuickRenderTarget does not own \a renderTarget and any
630 underlying native resources, it merely contains references and the
631 associated metadata of the size and sample count. It is the caller's
632 responsibility to ensure that the referenced resources exists as long as
633 necessary.
634
635 \since 6.6
636
637 \sa QQuickWindow::setRenderTarget(), QQuickRenderControl
638*/
639QQuickRenderTarget QQuickRenderTarget::fromRhiRenderTarget(QRhiRenderTarget *renderTarget)
640{
641 QQuickRenderTarget rt;
642 QQuickRenderTargetPrivate *d = QQuickRenderTargetPrivate::get(rt: &rt);
643
644 if (!renderTarget) {
645 qWarning(msg: "QQuickRenderTarget: Needs a valid QRhiRenderTarget");
646 return rt;
647 }
648
649 d->type = QQuickRenderTargetPrivate::Type::RhiRenderTarget;
650 d->pixelSize = renderTarget->pixelSize();
651 d->sampleCount = renderTarget->sampleCount();
652 d->u.rhiRt = renderTarget;
653
654 return rt;
655}
656
657/*!
658 \return a new QQuickRenderTarget referencing a paint device object
659 specified by \a device.
660
661 This option of redirecting rendering to a QPaintDevice is available only
662 when running with the \c software backend of Qt Quick.
663
664 \note The QQuickRenderTarget does not take ownship of \a device, it is the
665 caller's responsibility to ensure the object exists as long as necessary.
666
667 \since 6.4
668
669 \sa QQuickWindow::setRenderTarget(), QQuickRenderControl
670 */
671QQuickRenderTarget QQuickRenderTarget::fromPaintDevice(QPaintDevice *device)
672{
673 QQuickRenderTarget rt;
674 QQuickRenderTargetPrivate *d = QQuickRenderTargetPrivate::get(rt: &rt);
675
676 d->type = QQuickRenderTargetPrivate::Type::PaintDevice;
677 d->pixelSize = QSize(device->width(), device->height());
678 d->u.paintDevice = device;
679
680 return rt;
681}
682
683/*!
684 \fn bool QQuickRenderTarget::operator==(const QQuickRenderTarget &a, const QQuickRenderTarget &b) noexcept
685 \return true if \a a and \a b refer to the same set of native objects and
686 have matching associated data (size, sample count).
687*/
688/*!
689 \fn bool QQuickRenderTarget::operator!=(const QQuickRenderTarget &a, const QQuickRenderTarget &b) noexcept
690
691 \return true if \a a and \a b refer to a different set of native objects,
692 or the associated data (size, sample count) does not match.
693*/
694
695/*!
696 \internal
697*/
698bool QQuickRenderTarget::isEqual(const QQuickRenderTarget &other) const noexcept
699{
700 if (d->type != other.d->type
701 || d->pixelSize != other.d->pixelSize
702 || d->devicePixelRatio != other.d->devicePixelRatio
703 || d->sampleCount != other.d->sampleCount
704 || d->mirrorVertically != other.d->mirrorVertically)
705 {
706 return false;
707 }
708
709 switch (d->type) {
710 case QQuickRenderTargetPrivate::Type::Null:
711 break;
712 case QQuickRenderTargetPrivate::Type::NativeTexture:
713 if (d->u.nativeTexture.object != other.d->u.nativeTexture.object
714 || d->u.nativeTexture.layoutOrState != other.d->u.nativeTexture.layoutOrState
715 || d->u.nativeTexture.rhiFormat != other.d->u.nativeTexture.rhiFormat
716 || d->u.nativeTexture.rhiFlags != other.d->u.nativeTexture.rhiFlags)
717 return false;
718 break;
719 case QQuickRenderTargetPrivate::Type::NativeRenderbuffer:
720 if (d->u.nativeRenderbufferObject != other.d->u.nativeRenderbufferObject)
721 return false;
722 break;
723 case QQuickRenderTargetPrivate::Type::RhiRenderTarget:
724 if (d->u.rhiRt != other.d->u.rhiRt)
725 return false;
726 break;
727 case QQuickRenderTargetPrivate::Type::PaintDevice:
728 if (d->u.paintDevice != other.d->u.paintDevice)
729 return false;
730 break;
731 default:
732 break;
733 }
734
735 return true;
736}
737
738static bool createRhiRenderTarget(const QRhiColorAttachment &colorAttachment,
739 const QSize &pixelSize,
740 int sampleCount,
741 QRhi *rhi,
742 QQuickWindowRenderTarget *dst)
743{
744 std::unique_ptr<QRhiRenderBuffer> depthStencil(rhi->newRenderBuffer(type: QRhiRenderBuffer::DepthStencil, pixelSize, sampleCount));
745 if (!depthStencil->create()) {
746 qWarning(msg: "Failed to build depth-stencil buffer for QQuickRenderTarget");
747 return false;
748 }
749
750 QRhiTextureRenderTargetDescription rtDesc(colorAttachment);
751 rtDesc.setDepthStencilBuffer(depthStencil.get());
752 std::unique_ptr<QRhiTextureRenderTarget> rt(rhi->newTextureRenderTarget(desc: rtDesc));
753 std::unique_ptr<QRhiRenderPassDescriptor> rp(rt->newCompatibleRenderPassDescriptor());
754 rt->setRenderPassDescriptor(rp.get());
755
756 if (!rt->create()) {
757 qWarning(msg: "Failed to build texture render target for QQuickRenderTarget");
758 return false;
759 }
760
761 dst->renderTarget = rt.release();
762 dst->rpDesc = rp.release();
763 dst->depthStencil = depthStencil.release();
764 dst->owns = true; // ownership of the native resource itself is not transferred but the QRhi objects are on us now
765
766 return true;
767}
768
769bool QQuickRenderTargetPrivate::resolve(QRhi *rhi, QQuickWindowRenderTarget *dst)
770{
771 switch (type) {
772 case Type::Null:
773 dst->renderTarget = nullptr;
774 dst->paintDevice = nullptr;
775 dst->owns = false;
776 return true;
777
778 case Type::NativeTexture:
779 {
780 const auto format = u.nativeTexture.rhiFormat == QRhiTexture::UnknownFormat ? QRhiTexture::RGBA8
781 : QRhiTexture::Format(u.nativeTexture.rhiFormat);
782 const auto flags = QRhiTexture::RenderTarget | QRhiTexture::Flags(u.nativeTexture.rhiFlags);
783 std::unique_ptr<QRhiTexture> texture(rhi->newTexture(format, pixelSize, sampleCount, flags));
784 if (!texture->createFrom(src: { .object: u.nativeTexture.object, .layout: u.nativeTexture.layoutOrState })) {
785 qWarning(msg: "Failed to build wrapper texture for QQuickRenderTarget");
786 return false;
787 }
788 QRhiColorAttachment att(texture.get());
789 if (!createRhiRenderTarget(colorAttachment: att, pixelSize, sampleCount, rhi, dst))
790 return false;
791 dst->texture = texture.release();
792 }
793 return true;
794
795 case Type::NativeRenderbuffer:
796 {
797 std::unique_ptr<QRhiRenderBuffer> renderbuffer(rhi->newRenderBuffer(type: QRhiRenderBuffer::Color, pixelSize, sampleCount));
798 if (!renderbuffer->createFrom(src: { .object: u.nativeRenderbufferObject })) {
799 qWarning(msg: "Failed to build wrapper renderbuffer for QQuickRenderTarget");
800 return false;
801 }
802 QRhiColorAttachment att(renderbuffer.get());
803 if (!createRhiRenderTarget(colorAttachment: att, pixelSize, sampleCount, rhi, dst))
804 return false;
805 dst->renderBuffer = renderbuffer.release();
806 }
807 return true;
808
809 case Type::RhiRenderTarget:
810 dst->renderTarget = u.rhiRt;
811 dst->rpDesc = u.rhiRt->renderPassDescriptor(); // just for QQuickWindowRenderTarget::reset()
812 dst->owns = false;
813 return true;
814 case Type::PaintDevice:
815 dst->paintDevice = u.paintDevice;
816 dst->owns = false;
817 return true;
818
819 default:
820 break;
821 }
822 return false;
823}
824
825QT_END_NAMESPACE
826

source code of qtdeclarative/src/quick/items/qquickrendertarget.cpp