Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qquickrendertarget.cpp
Go to the documentation of this file.
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// Qt-Security score:significant reason:default
4
6#include <rhi/qrhi.h>
7#include <QtQuick/private/qquickitem_p.h>
8#include <QtQuick/private/qquickwindow_p.h>
9#include <QtQuick/private/qsgrhisupport_p.h>
10
12
13/*!
14 \class QQuickRenderTarget
15 \since 6.0
16 \inmodule QtQuick
17
18 \brief The QQuickRenderTarget class provides an opaque container for native
19 graphics resources specifying a render target, and associated metadata.
20
21 \sa QQuickWindow::setRenderTarget(), QQuickGraphicsDevice
22*/
23
24QQuickRenderTargetPrivate::QQuickRenderTargetPrivate()
25 : ref(1)
26{
27}
28
29QQuickRenderTargetPrivate::QQuickRenderTargetPrivate(const QQuickRenderTargetPrivate &other)
30 : ref(1),
31 type(other.type),
32 pixelSize(other.pixelSize),
33 devicePixelRatio(other.devicePixelRatio),
34 sampleCount(other.sampleCount),
35 u(other.u),
36 customDepthTexture(other.customDepthTexture),
37 mirrorVertically(other.mirrorVertically),
38 multisampleResolve(other.multisampleResolve)
39{
40}
41
42/*!
43 Constructs a default QQuickRenderTarget that does not reference any native
44 objects.
45 */
46QQuickRenderTarget::QQuickRenderTarget()
47 : d(new QQuickRenderTargetPrivate)
48{
49}
50
51/*!
52 \internal
53 */
54void QQuickRenderTarget::detach()
55{
56 qAtomicDetach(d);
57}
58
59/*!
60 \internal
61 */
62QQuickRenderTarget::QQuickRenderTarget(const QQuickRenderTarget &other)
63 : d(other.d)
64{
65 d->ref.ref();
66}
67
68/*!
69 \internal
70 */
71QQuickRenderTarget &QQuickRenderTarget::operator=(const QQuickRenderTarget &other)
72{
73 qAtomicAssign(d, other.d);
74 return *this;
75}
76
77/*!
78 Destructor.
79 */
80QQuickRenderTarget::~QQuickRenderTarget()
81{
82 if (!d->ref.deref())
83 delete d;
84}
85
86/*!
87 \return true if this QQuickRenderTarget is default constructed, referencing
88 no native objects.
89 */
90bool QQuickRenderTarget::isNull() const
91{
92 return d->type == QQuickRenderTargetPrivate::Type::Null;
93}
94
95/*!
96 \return the device pixel ratio for the render target. This is the ratio
97 between \e{device pixels} and \e{device independent pixels}.
98
99 The default device pixel ratio is 1.0.
100
101 \since 6.3
102
103 \sa setDevicePixelRatio()
104*/
105qreal QQuickRenderTarget::devicePixelRatio() const
106{
107 return d->devicePixelRatio;
108}
109
110/*!
111 Sets the device pixel ratio for this render target to \a ratio. This is
112 the ratio between \e{device pixels} and \e{device independent pixels}.
113
114 Note that the specified device pixel ratio value will be ignored if
115 QQuickRenderControl::renderWindow() is re-implemented to return a valid
116 QWindow.
117
118 \since 6.3
119
120 \sa devicePixelRatio()
121*/
122void QQuickRenderTarget::setDevicePixelRatio(qreal ratio)
123{
124 if (d->devicePixelRatio == ratio)
125 return;
126
127 detach();
128 d->devicePixelRatio = ratio;
129}
130
131/*!
132 \return Returns whether the render target is mirrored vertically.
133
134 The default value is \c {false}.
135
136 \since 6.4
137
138 \sa setMirrorVertically()
139*/
140bool QQuickRenderTarget::mirrorVertically() const
141{
142 return d->mirrorVertically;
143}
144
145
146/*!
147 Sets the size of the render target contents should be mirrored vertically to
148 \a enable when drawing. This allows easy integration of third-party rendering
149 code that does not follow the standard expectations.
150
151 \note This function should not be used when using the \c software backend.
152
153 \since 6.4
154
155 \sa mirrorVertically()
156 */
157void QQuickRenderTarget::setMirrorVertically(bool enable)
158{
159 if (d->mirrorVertically == enable)
160 return;
161
162 detach();
163 d->mirrorVertically = enable;
164}
165
166/*!
167 \return the currently set depth texture or, in most cases, \nullptr.
168
169 The value is only non-null when setDepthTexture() was called.
170
171 \since 6.8
172 */
173QRhiTexture *QQuickRenderTarget::depthTexture() const
174{
175 return d->customDepthTexture;
176}
177
178/*!
179 Requests using the given \a texture as the depth or depth-stencil buffer.
180 Ownership of \a texture is not taken.
181
182 The request is only taken into account when relevant. For example, calling
183 this function has no effect with fromRhiRenderTarget(), fromPaintDevice(),
184 or fromOpenGLRenderBuffer().
185
186 Normally a depth-stencil buffer is created automatically, transparently to
187 the user of QQuickRenderTarget. Therefore, there is no need to call this
188 function in most cases when working with QQuickRenderTarget. In special
189 circumstances, it can however become essential to be able to provide a
190 texture to render depth (or depth and stencil) data into, instead of letting
191 Qt Quick create its own intermediate textures or buffers. An example of this
192 is \l{https://www.khronos.org/openxr/}{OpenXR} and its extensions such as
193 \l{https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#XR_KHR_composition_layer_depth}{XR_KHR_composition_layer_depth}.
194 In order to "submit the depth buffer" to the XR compositor, one has to, in
195 practice, retrieve an already created depth (depth-stencil) texture from
196 OpenXR (from the XrSwapchain) and use that texture as the render target for
197 depth data. That would not be possible without this function.
198
199 \note The \a texture is always expected to be a non-multisample 2D texture
200 or texture array (for multiview). If MSAA is involved, the samples are
201 resolved into \a texture at the end of the render pass, regardless of having
202 the MultisampleResolve flag set or not. MSAA is only supported for depth
203 (depth-stencil) textures when the underlying 3D API supports this, and this
204 support is not universally available. See \l{QRhi::ResolveDepthStencil}{the
205 relevant QRhi feature flag} for details. When this is not supported and
206 multisampling is requested in combination with a custom depth texture, \a
207 texture is not going to be touched during rendering and a warning is
208 printed.
209
210 \since 6.8
211
212 \note When it comes to OpenGL and OpenGL ES, using depth textures is not
213 functional on OpenGL ES 2.0 and requires at least OpenGL ES 3.0. Multisample
214 (MSAA) support is not available without at least OpenGL ES 3.1, or OpenGL
215 3.0 on desktop.
216 */
217void QQuickRenderTarget::setDepthTexture(QRhiTexture *texture)
218{
219 if (d->customDepthTexture == texture)
220 return;
221
222 detach();
223 d->customDepthTexture = texture;
224}
225
226/*!
227 \enum QQuickRenderTarget::Flag
228 Flags for the static QQuickRenderTarget constructor functions.
229
230 \value MultisampleResolve Indicates that the \c sampleCount argument is not
231 the number of samples for the provided texture (and that the texture is
232 still a non-multisample texture), but rather the desired samples for
233 multisample antialiasing. Triggers automatically creating and managing an
234 intermediate multisample texture (or texture array) as the color buffer,
235 transparently to the application. The samples are resolved into the provided
236 texture at the end of the render pass automatically. When this flag is not
237 set, and the \c sampleCount argument is greater than 1, it implies the
238 provided texture is multisample. The flag has no effect is the
239 \c sampleCount is 1 (indicating that multisampling is not involved).
240
241 \since 6.8
242*/
243
244/*!
245 \return a new QQuickRenderTarget referencing an OpenGL texture object
246 specified by \a textureId.
247
248 \a format specifies the native internal format of the
249 texture. Only texture formats that are supported by Qt's rendering
250 infrastructure should be used.
251
252 \a pixelSize specifies the size of the image, in pixels. Currently only 2D
253 textures are supported.
254
255 \a sampleCount specifies the number of samples. 0 or 1 means no
256 multisampling, while a value like 4 or 8 states that the native object is a
257 multisample texture.
258
259 The texture is used as the first color attachment of the render target used
260 by the Qt Quick scenegraph. A depth-stencil buffer, if applicable, is
261 created and used automatically.
262
263 The OpenGL object name \a textureId must be a valid name in the rendering
264 context used by the Qt Quick scenegraph.
265
266 \note the resulting QQuickRenderTarget does not own any native resources,
267 it merely contains references and the associated metadata of the size and
268 sample count. It is the caller's responsibility to ensure that the native
269 resource exists as long as necessary.
270
271 \since 6.4
272
273 \sa QQuickWindow::setRenderTarget(), QQuickRenderControl
274 */
275#if QT_CONFIG(opengl) || defined(Q_QDOC)
276QQuickRenderTarget QQuickRenderTarget::fromOpenGLTexture(uint textureId, uint format,
277 const QSize &pixelSize, int sampleCount)
278{
279 QQuickRenderTarget rt;
280 QQuickRenderTargetPrivate *d = QQuickRenderTargetPrivate::get(&rt);
281
282 if (!textureId) {
283 qWarning("QQuickRenderTarget: textureId is invalid");
284 return rt;
285 }
286
287 if (pixelSize.isEmpty()) {
288 qWarning("QQuickRenderTarget: Cannot create with empty size");
289 return rt;
290 }
291
292 d->type = QQuickRenderTargetPrivate::Type::NativeTexture;
293 d->pixelSize = pixelSize;
294 d->sampleCount = qMax(1, sampleCount);
295
296 QRhiTexture::Flags formatFlags;
297 QRhiTexture::Format rhiFormat = QSGRhiSupport::toRhiTextureFormatFromGL(format, &formatFlags);
298 d->u.nativeTexture = { textureId, 0, uint(rhiFormat), uint(formatFlags), uint(rhiFormat), uint(formatFlags) };
299
300 return rt;
301}
302
303/*!
304 \overload
305
306 \return a new QQuickRenderTarget referencing an OpenGL texture
307 object specified by \a textureId. The texture is assumed to have a
308 format of GL_RGBA (GL_RGBA8).
309
310 \a pixelSize specifies the size of the image, in pixels. Currently
311 only 2D textures are supported.
312
313 \a sampleCount specifies the number of samples. 0 or 1 means no
314 multisampling, while a value like 4 or 8 states that the native
315 object is a multisample texture.
316
317 The texture is used as the first color attachment of the render target used
318 by the Qt Quick scenegraph. A depth-stencil buffer, if applicable, is
319 created and used automatically.
320
321 The OpenGL object name \a textureId must be a valid name in the rendering
322 context used by the Qt Quick scenegraph.
323
324 \note the resulting QQuickRenderTarget does not own any native resources,
325 it merely contains references and the associated metadata of the size and
326 sample count. It is the caller's responsibility to ensure that the native
327 resource exists as long as necessary.
328
329 \sa QQuickWindow::setRenderTarget(), QQuickRenderControl
330*/
331QQuickRenderTarget QQuickRenderTarget::fromOpenGLTexture(uint textureId, const QSize &pixelSize, int sampleCount)
332{
333 return fromOpenGLTexture(textureId, 0, pixelSize, sampleCount);
334}
335
336/*!
337 \overload
338
339 \return a new QQuickRenderTarget referencing an OpenGL 2D texture or texture
340 array object specified by \a textureId.
341
342 \a format specifies the native internal format of the texture. Only texture
343 formats that are supported by Qt's rendering infrastructure should be used.
344
345 \a pixelSize specifies the size of the image, in pixels. Currently only 2D
346 textures and 2D texture arrays are supported.
347
348 \a sampleCount specifies the number of samples. 0 or 1 means no
349 multisampling, while a value like 4 or 8 states that the native object is a
350 multisample texture, except when \a flags contains \l MultisampleResolve. In
351 that case, \a textureId is assumed to be a non-multisample 2D texture or 2D
352 texture array, and \a sampleCount defines the number of samples desired. The
353 resulting QQuickRenderTarget will use an intermediate, automatically created
354 multisample texture (or texture array) as its color attachment, and will
355 resolve the samples into \a textureId. This is the recommended approach to
356 perform MSAA when the native OpenGL texture is not already multisample.
357
358 When \a arraySize is greater than 1, it implies multiview rendering
359 (\l{https://registry.khronos.org/OpenGL/extensions/OVR/OVR_multiview.txt}{GL_OVR_multiview},
360 \l QRhiColorAttachment::setMultiViewCount()), which can be relevant with
361 VR/AR especially. In this case \a arraySize is the number of views,
362 typically \c 2. See \l QSGMaterial::viewCount() for details on enabling
363 multiview rendering within the Qt Quick scenegraph.
364
365 A depth-stencil buffer, if applicable, is created and used automatically.
366 When the color buffer is multisample, the depth-stencil buffer will
367 automatically be multisample too. For multiview rendering, the depth-stencil
368 texture will automatically be made an array with a matching \a arraySize.
369
370 The OpenGL object name \a textureId must be a valid 2D texture name in the
371 rendering context used by the Qt Quick scenegraph. When \a arraySize is
372 greater than 1, \a textureId must be a valid 2D texture array name.
373
374 \note the resulting QQuickRenderTarget does not own any native resources, it
375 merely contains references and the associated metadata of the size and
376 sample count. It is the caller's responsibility to ensure that the native
377 resource exists as long as necessary.
378
379 \since 6.8
380
381 \note The implementation of this overload is not compatible with OpenGL ES
382 2.0 or 3.0, and requires OpenGL ES 3.1 at minimum. (or OpenGL 3.0 on
383 desktop)
384
385 \sa QQuickWindow::setRenderTarget(), QQuickRenderControl, fromOpenGLTexture()
386 */
387QQuickRenderTarget QQuickRenderTarget::fromOpenGLTexture(uint textureId, uint format, QSize pixelSize, int sampleCount, int arraySize, Flags flags)
388{
389 QQuickRenderTarget rt;
390 QQuickRenderTargetPrivate *d = QQuickRenderTargetPrivate::get(&rt);
391
392 if (!textureId) {
393 qWarning("QQuickRenderTarget: textureId is invalid");
394 return rt;
395 }
396
397 if (pixelSize.isEmpty()) {
398 qWarning("QQuickRenderTarget: Cannot create with empty size");
399 return rt;
400 }
401
402 QRhiTexture::Flags formatFlags;
403 QRhiTexture::Format rhiFormat = QSGRhiSupport::toRhiTextureFormatFromGL(format, &formatFlags);
404
405 d->pixelSize = pixelSize;
406 d->sampleCount = qMax(1, sampleCount);
407 d->multisampleResolve = flags.testFlag(Flag::MultisampleResolve);
408
409 if (arraySize <= 1) {
410 d->type = QQuickRenderTargetPrivate::Type::NativeTexture;
411 d->u.nativeTexture = { textureId, 0, uint(rhiFormat), uint(formatFlags), uint(rhiFormat), uint(formatFlags) };
412 } else {
413 d->type = QQuickRenderTargetPrivate::Type::NativeTextureArray;
414 d->u.nativeTextureArray = { textureId, 0, arraySize, uint(rhiFormat), uint(formatFlags), uint(rhiFormat), uint(formatFlags) };
415 }
416
417 return rt;
418}
419
420/*!
421 \return a new QQuickRenderTarget referencing an OpenGL renderbuffer object
422 specified by \a renderbufferId.
423
424 The renderbuffer will be used as the color attachment for the internal
425 framebuffer object. This function is provided to allow targeting
426 renderbuffers that are created by the application with some external buffer
427 underneath, such as an EGLImageKHR. Once the application has called
428 \l{https://www.khronos.org/registry/OpenGL/extensions/OES/OES_EGL_image.txt}{glEGLImageTargetRenderbufferStorageOES},
429 the renderbuffer can be passed to this function.
430
431 \a pixelSize specifies the size of the image, in pixels.
432
433 \a sampleCount specifies the number of samples. 0 or 1 means no
434 multisampling, while a value like 4 or 8 states that the native object is a
435 multisample renderbuffer.
436
437 \note the resulting QQuickRenderTarget does not own any native resources,
438 it merely contains references and the associated metadata of the size and
439 sample count. It is the caller's responsibility to ensure that the native
440 resource exists as long as necessary.
441
442 \since 6.2
443
444 \sa QQuickWindow::setRenderTarget(), QQuickRenderControl
445 */
446QQuickRenderTarget QQuickRenderTarget::fromOpenGLRenderBuffer(uint renderbufferId, const QSize &pixelSize, int sampleCount)
447{
448 QQuickRenderTarget rt;
449 QQuickRenderTargetPrivate *d = QQuickRenderTargetPrivate::get(&rt);
450
451 if (!renderbufferId) {
452 qWarning("QQuickRenderTarget: renderbufferId is invalid");
453 return rt;
454 }
455
456 if (pixelSize.isEmpty()) {
457 qWarning("QQuickRenderTarget: Cannot create with empty size");
458 return rt;
459 }
460
461 d->type = QQuickRenderTargetPrivate::Type::NativeRenderbuffer;
462 d->pixelSize = pixelSize;
463 d->sampleCount = qMax(1, sampleCount);
464 d->u.nativeRenderbufferObject = renderbufferId;
465
466 return rt;
467}
468#endif
469
470/*!
471 \return a new QQuickRenderTarget referencing a D3D11 texture object
472 specified by \a texture.
473
474 \a format specifies the DXGI_FORMAT of the texture. Only texture formats
475 that are supported by Qt's rendering infrastructure should be used.
476
477 \a pixelSize specifies the size of the image, in pixels. Currently only 2D
478 textures are supported.
479
480 \a sampleCount specifies the number of samples. 0 or 1 means no
481 multisampling, while a value like 4 or 8 states that the native object is a
482 multisample texture.
483
484 The texture is used as the first color attachment of the render target used
485 by the Qt Quick scenegraph. A depth-stencil buffer, if applicable, is
486 created and used automatically.
487
488 \note the resulting QQuickRenderTarget does not own any native resources,
489 it merely contains references and the associated metadata of the size and
490 sample count. It is the caller's responsibility to ensure that the native
491 resource exists as long as necessary.
492
493 \since 6.4
494
495 \sa QQuickWindow::setRenderTarget(), QQuickRenderControl
496 */
497#if defined(Q_OS_WIN) || defined(Q_QDOC)
498QQuickRenderTarget QQuickRenderTarget::fromD3D11Texture(void *texture, uint format,
499 const QSize &pixelSize, int sampleCount)
500{
501 QQuickRenderTarget rt;
502 QQuickRenderTargetPrivate *d = QQuickRenderTargetPrivate::get(&rt);
503
504 if (!texture) {
505 qWarning("QQuickRenderTarget: texture is null");
506 return rt;
507 }
508
509 if (pixelSize.isEmpty()) {
510 qWarning("QQuickRenderTarget: Cannot create with empty size");
511 return rt;
512 }
513
514 d->type = QQuickRenderTargetPrivate::Type::NativeTexture;
515 d->pixelSize = pixelSize;
516 d->sampleCount = qMax(1, sampleCount);
517
518 QRhiTexture::Flags formatFlags;
519 QRhiTexture::Format rhiFormat = QSGRhiSupport::toRhiTextureFormatFromDXGI(format, &formatFlags);
520 d->u.nativeTexture = { quint64(texture), 0, uint(rhiFormat), uint(formatFlags), uint(rhiFormat), uint(formatFlags) };
521
522 return rt;
523}
524
525/*!
526 \overload
527
528 \return a new QQuickRenderTarget referencing a D3D11 texture
529 object specified by \a texture. The texture is assumed to have a
530 format of DXGI_FORMAT_R8G8B8A8_UNORM.
531
532 \a pixelSize specifies the size of the image, in pixels. Currently only 2D
533 textures are supported.
534
535 \a sampleCount specifies the number of samples. 0 or 1 means no
536 multisampling, while a value like 4 or 8 states that the native object is a
537 multisample texture.
538
539 The texture is used as the first color attachment of the render target used
540 by the Qt Quick scenegraph. A depth-stencil buffer, if applicable, is
541 created and used automatically.
542
543 \note the resulting QQuickRenderTarget does not own any native resources,
544 it merely contains references and the associated metadata of the size and
545 sample count. It is the caller's responsibility to ensure that the native
546 resource exists as long as necessary.
547
548 \sa QQuickWindow::setRenderTarget(), QQuickRenderControl
549*/
550QQuickRenderTarget QQuickRenderTarget::fromD3D11Texture(void *texture, const QSize &pixelSize, int sampleCount)
551{
552 return fromD3D11Texture(texture, 0 /* DXGI_FORMAT_UNKNOWN */, pixelSize, sampleCount);
553}
554
555/*!
556 \overload
557
558 \return a new QQuickRenderTarget referencing a D3D11 texture object
559 specified by \a texture.
560
561 \a format specifies the DXGI_FORMAT of the texture. Only texture formats
562 that are supported by Qt's rendering infrastructure should be used.
563
564 \a pixelSize specifies the size of the image, in pixels. Currently only 2D
565 textures are supported.
566
567 \a sampleCount specifies the number of samples. 0 or 1 means no
568 multisampling, while a value like 4 or 8 states that the native object is a
569 multisample texture, except when \a flags contains \l MultisampleResolve. In
570 that case, \a texture is assumed to be a non-multisample 2D texture and \a
571 sampleCount defines the number of samples desired. The resulting
572 QQuickRenderTarget will use an intermediate, automatically created
573 multisample texture as its color attachment, and will resolve the samples
574 into \a texture. This is the recommended approach to perform MSAA when the
575 native texture is not already multisample.
576
577 The texture is used as the first color attachment of the render target used
578 by the Qt Quick scenegraph. A depth-stencil buffer, if applicable, is
579 created and used automatically. When the color buffer is multisample, the
580 depth-stencil buffer will automatically be multisample too.
581
582 \note the resulting QQuickRenderTarget does not own any native resources, it
583 merely contains references and the associated metadata of the size and
584 sample count. It is the caller's responsibility to ensure that the native
585 resource exists as long as necessary.
586
587 \since 6.8
588
589 \sa QQuickWindow::setRenderTarget(), QQuickRenderControl, fromD3D11Texture()
590 */
591QQuickRenderTarget QQuickRenderTarget::fromD3D11Texture(void *texture, uint format, QSize pixelSize, int sampleCount, Flags flags)
592{
593 QQuickRenderTarget rt = fromD3D11Texture(texture, format, pixelSize, sampleCount);
594 QQuickRenderTargetPrivate::get(&rt)->multisampleResolve = flags.testFlag(Flag::MultisampleResolve);
595 return rt;
596}
597
598/*!
599 \return a new QQuickRenderTarget referencing a D3D12 texture object
600 specified by \a texture.
601
602 \a resourceState must a valid bitmask with bits from D3D12_RESOURCE_STATES,
603 specifying the resource's current state.
604
605 \a format specifies the DXGI_FORMAT of the texture. Only texture formats
606 that are supported by Qt's rendering infrastructure should be used.
607
608 \a pixelSize specifies the size of the image, in pixels. Currently only 2D
609 textures are supported.
610
611 \a sampleCount specifies the number of samples. 0 or 1 means no
612 multisampling, while a value like 4 or 8 states that the native object is a
613 multisample texture.
614
615 The texture is used as the first color attachment of the render target used
616 by the Qt Quick scenegraph. A depth-stencil buffer, if applicable, is
617 created and used automatically.
618
619 \note the resulting QQuickRenderTarget does not own any native resources,
620 it merely contains references and the associated metadata of the size and
621 sample count. It is the caller's responsibility to ensure that the native
622 resource exists as long as necessary.
623
624 \since 6.6
625
626 \sa QQuickWindow::setRenderTarget(), QQuickRenderControl
627 */
628QQuickRenderTarget QQuickRenderTarget::fromD3D12Texture(void *texture,
629 int resourceState,
630 uint format,
631 const QSize &pixelSize,
632 int sampleCount)
633{
634 QQuickRenderTarget rt;
635 QQuickRenderTargetPrivate *d = QQuickRenderTargetPrivate::get(&rt);
636
637 if (!texture) {
638 qWarning("QQuickRenderTarget: texture is null");
639 return rt;
640 }
641
642 if (pixelSize.isEmpty()) {
643 qWarning("QQuickRenderTarget: Cannot create with empty size");
644 return rt;
645 }
646
647 d->type = QQuickRenderTargetPrivate::Type::NativeTexture;
648 d->pixelSize = pixelSize;
649 d->sampleCount = qMax(1, sampleCount);
650
651 QRhiTexture::Flags formatFlags;
652 QRhiTexture::Format rhiFormat = QSGRhiSupport::toRhiTextureFormatFromDXGI(format, &formatFlags);
653 d->u.nativeTexture = { quint64(texture), resourceState, uint(rhiFormat), uint(formatFlags), uint(rhiFormat), uint(formatFlags) };
654
655 return rt;
656}
657
658/*!
659 \overload
660
661 \return a new QQuickRenderTarget referencing a D3D12 2D texture or 2D
662 texture array object specified by \a texture.
663
664 \a resourceState must a valid bitmask with bits from D3D12_RESOURCE_STATES,
665 specifying the resource's current state.
666
667 \a format specifies the DXGI_FORMAT of the texture. Only texture formats
668 that are supported by Qt's rendering infrastructure should be used.
669
670 \a viewFormat is the DXGI_FORMAT used for the render target view (RTV).
671 Often the same as \a format. Functional only when
672 \l{https://microsoft.github.io/DirectX-Specs/d3d/RelaxedCasting.html}{relaxed
673 format casting} is supported by the driver, the argument is ignored otherwise.
674 In practice support is expected to be always available on Windows 10 1703
675 and newer.
676
677 \a pixelSize specifies the size of the image, in pixels. Currently only 2D
678 textures and 2D texture arrays are supported.
679
680 \a sampleCount specifies the number of samples. 0 or 1 means no
681 multisampling, while a value like 4 or 8 states that the native object is a
682 multisample texture, except when \a flags contains \l MultisampleResolve. In
683 that case, \a texture is assumed to be a non-multisample 2D texture or 2D
684 texture array, and \a sampleCount defines the number of samples desired. The
685 resulting QQuickRenderTarget will use an intermediate, automatically created
686 multisample texture (or texture array) as its color attachment, and will
687 resolve the samples into \a texture. This is the recommended approach to
688 perform MSAA when the native D3D12 texture is not already multisample.
689
690 The number of array elements (layers) is given in \a arraySize. When greater
691 than 1, it implies multiview rendering
692 (\l{https://microsoft.github.io/DirectX-Specs/d3d/ViewInstancing.html}{view
693 instancing}), which can be relevant with VR/AR especially. \a arraySize is
694 the number of views, typically \c 2. See \l QSGMaterial::viewCount() for
695 details on enabling multiview rendering within the Qt Quick scenegraph.
696
697 The texture is used as the first color attachment of the render target used
698 by the Qt Quick scenegraph. A depth-stencil buffer, if applicable, is
699 created and used automatically. When the color buffer is multisample, the
700 depth-stencil buffer will automatically be multisample too. For multiview
701 rendering, the depth-stencil texture will automatically be made an array
702 with a matching \a arraySize.
703
704 \note the resulting QQuickRenderTarget does not own any native resources, it
705 merely contains references and the associated metadata of the size and
706 sample count. It is the caller's responsibility to ensure that the native
707 resource exists as long as necessary.
708
709 \since 6.8
710
711 \sa QQuickWindow::setRenderTarget(), QQuickRenderControl
712 */
713QQuickRenderTarget QQuickRenderTarget::fromD3D12Texture(void *texture,
714 int resourceState,
715 uint format,
716 uint viewFormat,
717 QSize pixelSize,
718 int sampleCount,
719 int arraySize,
720 Flags flags)
721{
722 QQuickRenderTarget rt;
723 QQuickRenderTargetPrivate *d = QQuickRenderTargetPrivate::get(&rt);
724
725 if (!texture) {
726 qWarning("QQuickRenderTarget: texture is null");
727 return rt;
728 }
729
730 if (pixelSize.isEmpty()) {
731 qWarning("QQuickRenderTarget: Cannot create with empty size");
732 return rt;
733 }
734
735 QRhiTexture::Flags formatFlags;
736 QRhiTexture::Format rhiFormat = QSGRhiSupport::toRhiTextureFormatFromDXGI(format, &formatFlags);
737 QRhiTexture::Flags viewFormatFlags;
738 QRhiTexture::Format rhiViewFormat = QSGRhiSupport::toRhiTextureFormatFromDXGI(viewFormat, &viewFormatFlags);
739
740 d->pixelSize = pixelSize;
741 d->sampleCount = qMax(1, sampleCount);
742 d->multisampleResolve = flags.testFlag(Flag::MultisampleResolve);
743
744 if (arraySize <= 1) {
745 d->type = QQuickRenderTargetPrivate::Type::NativeTexture;
746 d->u.nativeTexture = { quint64(texture), resourceState, uint(rhiFormat), uint(formatFlags), uint(rhiViewFormat), uint(viewFormatFlags) };
747 } else {
748 d->type = QQuickRenderTargetPrivate::Type::NativeTextureArray;
749 d->u.nativeTextureArray = { quint64(texture), resourceState, arraySize, uint(rhiFormat), uint(formatFlags), uint(rhiViewFormat), uint(viewFormatFlags) };
750 }
751
752 return rt;
753}
754
755#endif // Q_OS_WIN
756
757/*!
758 \return a new QQuickRenderTarget referencing a Metal texture object
759 specified by \a texture.
760
761 \a format specifies the MTLPixelFormat of the texture. Only texture formats
762 that are supported by Qt's rendering infrastructure should be used.
763
764 \a pixelSize specifies the size of the image, in pixels. Currently only 2D
765 textures are supported.
766
767 \a sampleCount specifies the number of samples. 0 or 1 means no
768 multisampling, while a value like 4 or 8 states that the native object is a
769 multisample texture.
770
771 The texture is used as the first color attachment of the render target used
772 by the Qt Quick scenegraph. A depth-stencil buffer, if applicable, is
773 created and used automatically.
774
775 \note the resulting QQuickRenderTarget does not own any native resources,
776 it merely contains references and the associated metadata of the size and
777 sample count. It is the caller's responsibility to ensure that the native
778 resource exists as long as necessary.
779
780 \since 6.4
781
782 \sa QQuickWindow::setRenderTarget(), QQuickRenderControl
783 */
784#if QT_CONFIG(metal) || defined(Q_QDOC)
785QQuickRenderTarget QQuickRenderTarget::fromMetalTexture(MTLTexture *texture, uint format,
786 const QSize &pixelSize, int sampleCount)
787{
788 QQuickRenderTarget rt;
789 QQuickRenderTargetPrivate *d = QQuickRenderTargetPrivate::get(&rt);
790
791 if (!texture) {
792 qWarning("QQuickRenderTarget: texture is null");
793 return rt;
794 }
795
796 if (pixelSize.isEmpty()) {
797 qWarning("QQuickRenderTarget: Cannot create with empty size");
798 return rt;
799 }
800
801 d->type = QQuickRenderTargetPrivate::Type::NativeTexture;
802 d->pixelSize = pixelSize;
803 d->sampleCount = qMax(1, sampleCount);
804
805 QRhiTexture::Flags formatFlags;
806 QRhiTexture::Format rhiFormat = QSGRhiSupport::toRhiTextureFormatFromMetal(format, &formatFlags);
807 d->u.nativeTexture = { quint64(texture), 0, uint(rhiFormat), uint(formatFlags), uint(rhiFormat), uint(formatFlags) };
808
809 return rt;
810}
811
812/*!
813 \overload
814
815 \return a new QQuickRenderTarget referencing a Metal texture object
816 specified by \a texture. The texture is assumed to have a format of
817 MTLPixelFormatRGBA8Unorm.
818
819 \a pixelSize specifies the size of the image, in pixels. Currently only 2D
820 textures are supported.
821
822 \a sampleCount specifies the number of samples. 0 or 1 means no
823 multisampling, while a value like 4 or 8 states that the native object is a
824 multisample texture.
825
826 The texture is used as the first color attachment of the render target used
827 by the Qt Quick scenegraph. A depth-stencil buffer, if applicable, is
828 created and used automatically.
829
830 \note the resulting QQuickRenderTarget does not own any native resources,
831 it merely contains references and the associated metadata of the size and
832 sample count. It is the caller's responsibility to ensure that the native
833 resource exists as long as necessary.
834
835 \sa QQuickWindow::setRenderTarget(), QQuickRenderControl
836*/
837QQuickRenderTarget QQuickRenderTarget::fromMetalTexture(MTLTexture *texture, const QSize &pixelSize, int sampleCount)
838{
839 return fromMetalTexture(texture, 0 /* MTLPixelFormatInvalid */, pixelSize, sampleCount);
840}
841
842/*!
843 \overload
844
845 \return a new QQuickRenderTarget referencing a Metal 2D texture or 2D
846 texture array given in \a texture.
847
848 \a format specifies the MTLPixelFormat of the texture. Only texture formats
849 that are supported by Qt's rendering infrastructure should be used.
850
851 \a viewFormat is usually set to the same value as \a format. In some cases,
852 such as when rendering into a texture with a \c{_SRGB} format and the
853 implicit linear->sRGB conversion on shader writes is not wanted, the value
854 can be different. Note however that the value may be ignored by Qt, when at
855 run time QRhi reports that the \l{QRhi::TextureViewFormat} feature is
856 unsupported.
857
858 \a pixelSize specifies the size of the image, in pixels. Currently only 2D
859 textures and 2D texture arrays are supported.
860
861 \a sampleCount specifies the number of samples. 0 or 1 means no
862 multisampling, while a value like 4 or 8 states that the native object is a
863 multisample texture, except when \a flags contains \l MultisampleResolve. In
864 that case, \a texture is assumed to be a non-multisample 2D texture or 2D
865 texture array, and \a sampleCount defines the number of samples desired. The
866 resulting QQuickRenderTarget will use an intermediate, automatically created
867 multisample texture (or texture array) as its color attachment, and will
868 resolve the samples into \a texture. This is the recommended approach to
869 perform MSAA when the native Metal texture is not already multisample.
870
871 The number of array elements (layers) is given in \a arraySize. When greater
872 than 1, it implies multiview rendering, which can be relevant with VR/AR
873 especially. \a arraySize is the number of views, typically \c 2. See
874 \l QSGMaterial::viewCount() for details on enabling multiview rendering within
875 the Qt Quick scenegraph.
876
877 The texture is used as the first color attachment of the render target used
878 by the Qt Quick scenegraph. A depth-stencil buffer, if applicable, is
879 created and used automatically. When the color buffer is multisample, the
880 depth-stencil buffer will automatically be multisample too. For multiview
881 rendering, the depth-stencil texture will automatically be made an array
882 with a matching \a arraySize.
883
884 \note the resulting QQuickRenderTarget does not own any native resources, it
885 merely contains references and the associated metadata of the size and
886 sample count. It is the caller's responsibility to ensure that the native
887 resource exists as long as necessary.
888
889 \since 6.8
890
891 \sa QQuickWindow::setRenderTarget(), QQuickRenderControl
892 */
893QQuickRenderTarget QQuickRenderTarget::fromMetalTexture(MTLTexture *texture, uint format, uint viewFormat,
894 QSize pixelSize, int sampleCount, int arraySize, Flags flags)
895{
896 QQuickRenderTarget rt;
897 QQuickRenderTargetPrivate *d = QQuickRenderTargetPrivate::get(&rt);
898
899 if (!texture) {
900 qWarning("QQuickRenderTarget: texture is null");
901 return rt;
902 }
903
904 if (pixelSize.isEmpty()) {
905 qWarning("QQuickRenderTarget: Cannot create with empty size");
906 return rt;
907 }
908
909 QRhiTexture::Flags formatFlags;
910 QRhiTexture::Format rhiFormat = QSGRhiSupport::toRhiTextureFormatFromMetal(format, &formatFlags);
911 QRhiTexture::Flags viewFormatFlags;
912 QRhiTexture::Format rhiViewFormat = QSGRhiSupport::toRhiTextureFormatFromMetal(viewFormat, &viewFormatFlags);
913
914 d->pixelSize = pixelSize;
915 d->sampleCount = qMax(1, sampleCount);
916 d->multisampleResolve = flags.testFlag(Flag::MultisampleResolve);
917
918 if (arraySize <= 1) {
919 d->type = QQuickRenderTargetPrivate::Type::NativeTexture;
920 d->u.nativeTexture = { quint64(texture), 0, uint(rhiFormat), uint(formatFlags), uint(rhiViewFormat), uint(viewFormatFlags) };
921 } else {
922 d->type = QQuickRenderTargetPrivate::Type::NativeTextureArray;
923 d->u.nativeTextureArray = { quint64(texture), 0, arraySize, uint(rhiFormat), uint(formatFlags), uint(rhiViewFormat), uint(viewFormatFlags) };
924 }
925
926 return rt;
927}
928
929#endif
930
931/*!
932 \return a new QQuickRenderTarget referencing a Vulkan image object
933 specified by \a image. The current \a layout of the image must be provided
934 as well.
935
936 \a format specifies the VkFormat of the image. Only image formats that are
937 supported by Qt's rendering infrastructure should be used.
938
939 \a pixelSize specifies the size of the image, in pixels. Currently only 2D
940 textures are supported.
941
942 \a sampleCount specifies the number of samples. 0 or 1 means no
943 multisampling, while a value like 4 or 8 states that the native object is a
944 multisample texture.
945
946 The image is used as the first color attachment of the render target used
947 by the Qt Quick scenegraph. A depth-stencil buffer, if applicable, is
948 created and used automatically.
949
950 \note the resulting QQuickRenderTarget does not own any native resources,
951 it merely contains references and the associated metadata of the size and
952 sample count. It is the caller's responsibility to ensure that the native
953 resource exists as long as necessary.
954
955 \since 6.4
956
957 \sa QQuickWindow::setRenderTarget(), QQuickRenderControl
958 */
959#if QT_CONFIG(vulkan) || defined(Q_QDOC)
960QQuickRenderTarget QQuickRenderTarget::fromVulkanImage(VkImage image, VkImageLayout layout, VkFormat format, const QSize &pixelSize, int sampleCount)
961{
962 QQuickRenderTarget rt;
963 QQuickRenderTargetPrivate *d = QQuickRenderTargetPrivate::get(&rt);
964
965 if (image == VK_NULL_HANDLE) {
966 qWarning("QQuickRenderTarget: image is invalid");
967 return rt;
968 }
969
970 if (pixelSize.isEmpty()) {
971 qWarning("QQuickRenderTarget: Cannot create with empty size");
972 return rt;
973 }
974
975 d->type = QQuickRenderTargetPrivate::Type::NativeTexture;
976 d->pixelSize = pixelSize;
977 d->sampleCount = qMax(1, sampleCount);
978
979 QRhiTexture::Flags formatFlags;
980 QRhiTexture::Format rhiFormat = QSGRhiSupport::toRhiTextureFormatFromVulkan(format, &formatFlags);
981 d->u.nativeTexture = { quint64(image), layout, uint(rhiFormat), uint(formatFlags), uint(rhiFormat), uint(formatFlags) };
982
983 return rt;
984}
985
986/*!
987 \overload
988
989 \return a new QQuickRenderTarget referencing a Vulkan image object specified
990 by \a image. The image is assumed to have a format of
991 VK_FORMAT_R8G8B8A8_UNORM.
992
993 \a pixelSize specifies the size of the image, in pixels. Currently only 2D
994 textures are supported.
995
996 \a sampleCount specifies the number of samples. 0 or 1 means no
997 multisampling, while a value like 4 or 8 states that the native object is a
998 multisample texture.
999
1000 The texture is used as the first color attachment of the render target used
1001 by the Qt Quick scenegraph. A depth-stencil buffer, if applicable, is
1002 created and used automatically.
1003
1004 \note the resulting QQuickRenderTarget does not own any native resources,
1005 it merely contains references and the associated metadata of the size and
1006 sample count. It is the caller's responsibility to ensure that the native
1007 resource exists as long as necessary.
1008
1009 \sa QQuickWindow::setRenderTarget(), QQuickRenderControl
1010*/
1011QQuickRenderTarget QQuickRenderTarget::fromVulkanImage(VkImage image, VkImageLayout layout, const QSize &pixelSize, int sampleCount)
1012{
1013 return fromVulkanImage(image, layout, VK_FORMAT_UNDEFINED, pixelSize, sampleCount);
1014}
1015
1016/*!
1017 \overload
1018
1019 \return a new QQuickRenderTarget referencing a Vulkan image object
1020 specified by \a image. The current \a layout of the image must be provided
1021 as well. The image must be either a 2D texture or 2D texture array.
1022
1023 \a format specifies the VkFormat of the image. Only image formats that are
1024 supported by Qt's rendering infrastructure should be used.
1025
1026 \a viewFormat is usually set to the same value as \a format. In some cases,
1027 such as when rendering into a texture with a \c{_SRGB} format and the
1028 implicit linear->sRGB conversion on shader writes is not wanted, the value
1029 can be different. (for example, a \a format of \c VK_FORMAT_R8G8B8A8_SRGB
1030 and \a viewFormat of \c VK_FORMAT_R8G8B8A8_UNORM).
1031
1032 \a pixelSize specifies the size of the image, in pixels. Currently only 2D
1033 textures are supported.
1034
1035 \a sampleCount specifies the number of samples. 0 or 1 means no
1036 multisampling, while a value like 4 or 8 states that the native object is a
1037 multisample texture, except when \a flags contains \l MultisampleResolve. In
1038 that case, \a image is assumed to be a non-multisample 2D texture or 2D
1039 texture array, and \a sampleCount defines the number of samples desired. The
1040 resulting QQuickRenderTarget will use an intermediate, automatically created
1041 multisample texture (or texture array) as its color attachment, and will
1042 resolve the samples into \a image. This is the recommended approach to
1043 perform MSAA when the native Vulkan image is not already multisample.
1044
1045 The number of array elements (layers) is given in \a arraySize. When greater
1046 than 1, it implies multiview rendering
1047 (\l{https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_KHR_multiview.html}{VK_KHR_multiview}),
1048 which can be relevant with VR/AR especially. \a arraySize is the number of
1049 views, typically \c 2. See \l QSGMaterial::viewCount() for details on
1050 enabling multiview rendering within the Qt Quick scenegraph.
1051
1052 The texture is used as the first color attachment of the render target used
1053 by the Qt Quick scenegraph. A depth-stencil buffer, if applicable, is
1054 created and used automatically. When the color buffer is multisample, the
1055 depth-stencil buffer will automatically be multisample too. For multiview
1056 rendering, the depth-stencil texture will automatically be made an array
1057 with a matching \a arraySize.
1058
1059 \note the resulting QQuickRenderTarget does not own any native resources, it
1060 merely contains references and the associated metadata of the size and
1061 sample count. It is the caller's responsibility to ensure that the native
1062 resource exists as long as necessary.
1063
1064 \since 6.8
1065
1066 \sa QQuickWindow::setRenderTarget(), QQuickRenderControl
1067 */
1068QQuickRenderTarget QQuickRenderTarget::fromVulkanImage(VkImage image, VkImageLayout layout, VkFormat format, VkFormat viewFormat,
1069 QSize pixelSize, int sampleCount, int arraySize, Flags flags)
1070{
1071 QQuickRenderTarget rt;
1072 QQuickRenderTargetPrivate *d = QQuickRenderTargetPrivate::get(&rt);
1073
1074 if (image == VK_NULL_HANDLE) {
1075 qWarning("QQuickRenderTarget: image is invalid");
1076 return rt;
1077 }
1078
1079 if (pixelSize.isEmpty()) {
1080 qWarning("QQuickRenderTarget: Cannot create with empty size");
1081 return rt;
1082 }
1083
1084 QRhiTexture::Flags formatFlags;
1085 QRhiTexture::Format rhiFormat = QSGRhiSupport::toRhiTextureFormatFromVulkan(format, &formatFlags);
1086 QRhiTexture::Flags viewFormatFlags;
1087 QRhiTexture::Format rhiViewFormat = QSGRhiSupport::toRhiTextureFormatFromVulkan(viewFormat, &viewFormatFlags);
1088
1089 d->pixelSize = pixelSize;
1090 d->sampleCount = qMax(1, sampleCount);
1091 d->multisampleResolve = flags.testFlag(Flag::MultisampleResolve);
1092
1093 if (arraySize <= 1) {
1094 d->type = QQuickRenderTargetPrivate::Type::NativeTexture;
1095 d->u.nativeTexture = { quint64(image), layout, uint(rhiFormat), uint(formatFlags), uint(rhiViewFormat), uint(viewFormatFlags) };
1096 } else {
1097 d->type = QQuickRenderTargetPrivate::Type::NativeTextureArray;
1098 d->u.nativeTextureArray = { quint64(image), layout, arraySize, uint(rhiFormat), uint(formatFlags), uint(rhiViewFormat), uint(viewFormatFlags) };
1099 }
1100
1101 return rt;
1102}
1103
1104#endif // Vulkan
1105
1106/*!
1107 \return a new QQuickRenderTarget referencing an existing \a renderTarget.
1108
1109 \a renderTarget will in most cases be a QRhiTextureRenderTarget, which
1110 allows directing the Qt Quick scene's rendering into a QRhiTexture.
1111
1112 \note the resulting QQuickRenderTarget does not own \a renderTarget and any
1113 underlying native resources, it merely contains references and the
1114 associated metadata of the size and sample count. It is the caller's
1115 responsibility to ensure that the referenced resources exists as long as
1116 necessary.
1117
1118 \since 6.6
1119
1120 \sa QQuickWindow::setRenderTarget(), QQuickRenderControl
1121*/
1122QQuickRenderTarget QQuickRenderTarget::fromRhiRenderTarget(QRhiRenderTarget *renderTarget)
1123{
1124 QQuickRenderTarget rt;
1125 QQuickRenderTargetPrivate *d = QQuickRenderTargetPrivate::get(&rt);
1126
1127 if (!renderTarget) {
1128 qWarning("QQuickRenderTarget: Needs a valid QRhiRenderTarget");
1129 return rt;
1130 }
1131
1132 d->type = QQuickRenderTargetPrivate::Type::RhiRenderTarget;
1133 d->pixelSize = renderTarget->pixelSize();
1134 d->sampleCount = renderTarget->sampleCount();
1135 d->u.rhiRt = renderTarget;
1136
1137 return rt;
1138}
1139
1140/*!
1141 \return a new QQuickRenderTarget referencing a paint device object
1142 specified by \a device.
1143
1144 This option of redirecting rendering to a QPaintDevice is available only
1145 when running with the \c software backend of Qt Quick.
1146
1147 \note The QQuickRenderTarget does not take ownship of \a device, it is the
1148 caller's responsibility to ensure the object exists as long as necessary.
1149
1150 \since 6.4
1151
1152 \sa QQuickWindow::setRenderTarget(), QQuickRenderControl
1153 */
1154QQuickRenderTarget QQuickRenderTarget::fromPaintDevice(QPaintDevice *device)
1155{
1156 QQuickRenderTarget rt;
1157 QQuickRenderTargetPrivate *d = QQuickRenderTargetPrivate::get(&rt);
1158
1159 d->type = QQuickRenderTargetPrivate::Type::PaintDevice;
1160 d->pixelSize = QSize(device->width(), device->height());
1161 d->u.paintDevice = device;
1162
1163 return rt;
1164}
1165
1166/*!
1167 \fn bool QQuickRenderTarget::operator==(const QQuickRenderTarget &a, const QQuickRenderTarget &b) noexcept
1168 \return true if \a a and \a b refer to the same set of native objects and
1169 have matching associated data (size, sample count).
1170*/
1171/*!
1172 \fn bool QQuickRenderTarget::operator!=(const QQuickRenderTarget &a, const QQuickRenderTarget &b) noexcept
1173
1174 \return true if \a a and \a b refer to a different set of native objects,
1175 or the associated data (size, sample count) does not match.
1176*/
1177
1178/*!
1179 \internal
1180*/
1181bool QQuickRenderTarget::isEqual(const QQuickRenderTarget &other) const noexcept
1182{
1183 if (d->type != other.d->type
1184 || d->pixelSize != other.d->pixelSize
1185 || d->devicePixelRatio != other.d->devicePixelRatio
1186 || d->sampleCount != other.d->sampleCount
1187 || d->mirrorVertically != other.d->mirrorVertically
1188 || d->multisampleResolve != other.d->multisampleResolve)
1189 {
1190 return false;
1191 }
1192
1193 switch (d->type) {
1194 case QQuickRenderTargetPrivate::Type::Null:
1195 break;
1196 case QQuickRenderTargetPrivate::Type::NativeTexture:
1197 if (d->u.nativeTexture.object != other.d->u.nativeTexture.object
1198 || d->u.nativeTexture.layoutOrState != other.d->u.nativeTexture.layoutOrState
1199 || d->u.nativeTexture.rhiFormat != other.d->u.nativeTexture.rhiFormat
1200 || d->u.nativeTexture.rhiFormatFlags != other.d->u.nativeTexture.rhiFormatFlags
1201 || d->u.nativeTexture.rhiViewFormat != other.d->u.nativeTexture.rhiViewFormat
1202 || d->u.nativeTexture.rhiViewFormatFlags != other.d->u.nativeTexture.rhiViewFormatFlags)
1203 return false;
1204 break;
1205 case QQuickRenderTargetPrivate::Type::NativeTextureArray:
1206 if (d->u.nativeTextureArray.object != other.d->u.nativeTextureArray.object
1207 || d->u.nativeTextureArray.layoutOrState != other.d->u.nativeTextureArray.layoutOrState
1208 || d->u.nativeTextureArray.arraySize != other.d->u.nativeTextureArray.arraySize
1209 || d->u.nativeTextureArray.rhiFormat != other.d->u.nativeTextureArray.rhiFormat
1210 || d->u.nativeTextureArray.rhiFormatFlags != other.d->u.nativeTextureArray.rhiFormatFlags
1211 || d->u.nativeTextureArray.rhiViewFormat != other.d->u.nativeTextureArray.rhiViewFormat
1212 || d->u.nativeTextureArray.rhiViewFormatFlags != other.d->u.nativeTextureArray.rhiViewFormatFlags)
1213 return false;
1214 break;
1215 case QQuickRenderTargetPrivate::Type::NativeRenderbuffer:
1216 if (d->u.nativeRenderbufferObject != other.d->u.nativeRenderbufferObject)
1217 return false;
1218 break;
1219 case QQuickRenderTargetPrivate::Type::RhiRenderTarget:
1220 if (d->u.rhiRt != other.d->u.rhiRt)
1221 return false;
1222 break;
1223 case QQuickRenderTargetPrivate::Type::PaintDevice:
1224 if (d->u.paintDevice != other.d->u.paintDevice)
1225 return false;
1226 break;
1227 default:
1228 break;
1229 }
1230
1231 return true;
1232}
1233
1234static bool createRhiRenderTargetWithRenderBuffer(QRhiRenderBuffer *renderBuffer,
1235 const QSize &pixelSize,
1236 int sampleCount,
1237 QRhi *rhi,
1239{
1240 sampleCount = QSGRhiSupport::chooseSampleCount(sampleCount, rhi);
1241
1242 std::unique_ptr<QRhiRenderBuffer> depthStencil;
1243 if (dst->implicitBuffers.depthStencil) {
1244 if (dst->implicitBuffers.depthStencil->pixelSize() == pixelSize
1245 && dst->implicitBuffers.depthStencil->sampleCount() == sampleCount)
1246 {
1247 depthStencil.reset(dst->implicitBuffers.depthStencil);
1248 dst->implicitBuffers.depthStencil = nullptr;
1249 }
1250 }
1251 dst->implicitBuffers.reset(rhi);
1252
1253 if (!depthStencil) {
1254 depthStencil.reset(rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil, pixelSize, sampleCount));
1255 depthStencil->setName(QByteArrayLiteral("Depth-stencil buffer for QQuickRenderTarget"));
1256 if (!depthStencil->create()) {
1257 qWarning("Failed to build depth-stencil buffer for QQuickRenderTarget");
1258 return false;
1259 }
1260 }
1261
1262 QRhiColorAttachment colorAttachment(renderBuffer);
1263 QRhiTextureRenderTargetDescription rtDesc(colorAttachment);
1264 rtDesc.setDepthStencilBuffer(depthStencil.get());
1265 std::unique_ptr<QRhiTextureRenderTarget> rt(rhi->newTextureRenderTarget(rtDesc));
1266 rt->setName(QByteArrayLiteral("RT for QQuickRenderTarget with renderbuffer"));
1267 std::unique_ptr<QRhiRenderPassDescriptor> rp(rt->newCompatibleRenderPassDescriptor());
1268 rt->setRenderPassDescriptor(rp.get());
1269
1270 if (!rt->create()) {
1271 qWarning("Failed to build renderbuffer-based render target for QQuickRenderTarget");
1272 return false;
1273 }
1274
1275 dst->rt.renderTarget = rt.release();
1276 dst->rt.owns = true;
1277 dst->res.rpDesc = rp.release();
1278 dst->implicitBuffers.depthStencil = depthStencil.release();
1279
1280 return true;
1281}
1282
1283static bool createRhiRenderTarget(QRhiTexture *texture,
1284 const QSize &pixelSize,
1285 int sampleCount,
1286 bool multisampleResolve,
1287 QRhi *rhi,
1289{
1290 // Simple path: no user-supplied depth texture. So create our own
1291 // depth-stencil buffer, using renderbuffers (so this is still GLES 2.0
1292 // compatible), with MSAA support being GLES 3.0 compatible.
1293
1294 sampleCount = QSGRhiSupport::chooseSampleCount(sampleCount, rhi);
1295 if (sampleCount <= 1)
1296 multisampleResolve = false;
1297
1298 std::unique_ptr<QRhiRenderBuffer> depthStencil;
1299 if (dst->implicitBuffers.depthStencil) {
1300 if (dst->implicitBuffers.depthStencil->pixelSize() == pixelSize
1301 && dst->implicitBuffers.depthStencil->sampleCount() == sampleCount)
1302 {
1303 depthStencil.reset(dst->implicitBuffers.depthStencil);
1304 dst->implicitBuffers.depthStencil = nullptr;
1305 }
1306 }
1307
1308 std::unique_ptr<QRhiTexture> colorBuffer;
1309 QRhiTexture::Flags multisampleTextureFlags;
1310 QRhiTexture::Format multisampleTextureFormat = texture->format();
1311 if (multisampleResolve) {
1312 multisampleTextureFlags = QRhiTexture::RenderTarget;
1313 if (texture->flags().testFlag(QRhiTexture::sRGB))
1314 multisampleTextureFlags |= QRhiTexture::sRGB;
1315
1316 if (dst->implicitBuffers.multisampleTexture) {
1317 if (dst->implicitBuffers.multisampleTexture->pixelSize() == pixelSize
1318 && dst->implicitBuffers.multisampleTexture->format() == multisampleTextureFormat
1319 && dst->implicitBuffers.multisampleTexture->sampleCount() == sampleCount
1320 && dst->implicitBuffers.multisampleTexture->flags().testFlags(multisampleTextureFlags))
1321 {
1322 colorBuffer.reset(dst->implicitBuffers.multisampleTexture);
1323 dst->implicitBuffers.multisampleTexture = nullptr;
1324 }
1325 }
1326 }
1327
1328 dst->implicitBuffers.reset(rhi);
1329
1330 if (!depthStencil) {
1331 depthStencil.reset(rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil, pixelSize, sampleCount));
1332 depthStencil->setName(QByteArrayLiteral("Depth-stencil buffer for QQuickRenderTarget"));
1333 if (!depthStencil->create()) {
1334 qWarning("Failed to build depth-stencil buffer for QQuickRenderTarget");
1335 return false;
1336 }
1337 }
1338
1339 if (multisampleResolve && !colorBuffer) {
1340 colorBuffer.reset(rhi->newTexture(multisampleTextureFormat, pixelSize, sampleCount, multisampleTextureFlags));
1341 colorBuffer->setName(QByteArrayLiteral("Multisample color buffer for QQuickRenderTarget"));
1342 colorBuffer->setWriteViewFormat(texture->writeViewFormat());
1343 if (!colorBuffer->create()) {
1344 qWarning("Failed to build multisample color buffer for QQuickRenderTarget");
1345 return false;
1346 }
1347 }
1348
1349 QRhiColorAttachment colorAttachment;
1350 if (multisampleResolve) {
1351 colorAttachment.setTexture(colorBuffer.get());
1352 colorAttachment.setResolveTexture(texture);
1353 } else {
1354 colorAttachment.setTexture(texture);
1355 }
1356 QRhiTextureRenderTargetDescription rtDesc(colorAttachment);
1357 rtDesc.setDepthStencilBuffer(depthStencil.get());
1358 std::unique_ptr<QRhiTextureRenderTarget> rt(rhi->newTextureRenderTarget(rtDesc));
1359 rt->setName(QByteArrayLiteral("RT for QQuickRenderTarget"));
1360 std::unique_ptr<QRhiRenderPassDescriptor> rp(rt->newCompatibleRenderPassDescriptor());
1361 rt->setRenderPassDescriptor(rp.get());
1362
1363 if (!rt->create()) {
1364 qWarning("Failed to build texture render target for QQuickRenderTarget");
1365 return false;
1366 }
1367
1368 dst->rt.renderTarget = rt.release();
1369 dst->rt.owns = true;
1370 dst->res.rpDesc = rp.release();
1371 dst->implicitBuffers.depthStencil = depthStencil.release();
1372 if (multisampleResolve)
1373 dst->implicitBuffers.multisampleTexture = colorBuffer.release();
1374
1375 return true;
1376}
1377
1378static bool createRhiRenderTargetWithDepthTexture(QRhiTexture *texture,
1379 QRhiTexture *depthTexture,
1380 const QSize &pixelSize,
1381 int sampleCount,
1382 bool multisampleResolve,
1383 QRhi *rhi,
1385{
1386 // This version takes a user-supplied depthTexture. That texture is always
1387 // non-multisample. If sample count is > 1, we still need our own
1388 // multisample depth-stencil buffer, and the depth(stencil) data is expected
1389 // to be resolved (and written out) to depthTexture, _if_ the underlying API
1390 // supports it (see QRhi's ResolveDepthStencil feature). The intermediate,
1391 // multisample depth-stencil buffer must be a texture here (not
1392 // renderbuffer), specifically for OpenGL ES and its related multisample
1393 // extensions.
1394
1395 sampleCount = QSGRhiSupport::chooseSampleCount(sampleCount, rhi);
1396 if (sampleCount <= 1)
1397 multisampleResolve = false;
1398
1399 std::unique_ptr<QRhiTexture> depthStencil;
1400 if (dst->implicitBuffers.depthStencilTexture) {
1401 if (dst->implicitBuffers.depthStencilTexture->pixelSize() == pixelSize
1402 && dst->implicitBuffers.depthStencilTexture->sampleCount() == sampleCount)
1403 {
1404 depthStencil.reset(dst->implicitBuffers.depthStencilTexture);
1405 dst->implicitBuffers.depthStencilTexture = nullptr;
1406 }
1407 }
1408
1409 std::unique_ptr<QRhiTexture> colorBuffer;
1410 QRhiTexture::Flags multisampleTextureFlags;
1411 QRhiTexture::Format multisampleTextureFormat = texture->format();
1412 if (multisampleResolve) {
1413 multisampleTextureFlags = QRhiTexture::RenderTarget;
1414 if (texture->flags().testFlag(QRhiTexture::sRGB))
1415 multisampleTextureFlags |= QRhiTexture::sRGB;
1416
1417 if (dst->implicitBuffers.multisampleTexture) {
1418 if (dst->implicitBuffers.multisampleTexture->pixelSize() == pixelSize
1419 && dst->implicitBuffers.multisampleTexture->format() == multisampleTextureFormat
1420 && dst->implicitBuffers.multisampleTexture->sampleCount() == sampleCount
1421 && dst->implicitBuffers.multisampleTexture->flags().testFlags(multisampleTextureFlags))
1422 {
1423 colorBuffer.reset(dst->implicitBuffers.multisampleTexture);
1424 dst->implicitBuffers.multisampleTexture = nullptr;
1425 }
1426 }
1427 }
1428
1429 dst->implicitBuffers.reset(rhi);
1430
1431 bool needsDepthStencilBuffer = true;
1432 if (sampleCount <= 1) {
1433 depthStencil.reset();
1434 needsDepthStencilBuffer = false;
1435 }
1436 if (depthTexture->pixelSize() != pixelSize) {
1437 qWarning("Custom depth texture size (%dx%d) does not match the QQuickRenderTarget (%dx%d)",
1438 depthTexture->pixelSize().width(),
1439 depthTexture->pixelSize().height(),
1440 pixelSize.width(),
1441 pixelSize.height());
1442 return false;
1443 }
1444 if (depthTexture->sampleCount() > 1) {
1445 qWarning("Custom depth texture cannot be multisample");
1446 return false;
1447 }
1448 if (needsDepthStencilBuffer && !depthStencil) {
1449 QRhiTexture::Format multisampleDepthTextureFormat = depthTexture->format();
1450 depthStencil.reset(rhi->newTexture(multisampleDepthTextureFormat, pixelSize, sampleCount, QRhiTexture::RenderTarget));
1451 depthStencil->setName(QByteArrayLiteral("Depth-stencil texture for QQuickRenderTarget"));
1452 if (!depthStencil->create()) {
1453 qWarning("Failed to build depth-stencil buffer for QQuickRenderTarget");
1454 return false;
1455 }
1456 }
1457
1458 if (multisampleResolve && !colorBuffer) {
1459 colorBuffer.reset(rhi->newTexture(multisampleTextureFormat, pixelSize, sampleCount, multisampleTextureFlags));
1460 colorBuffer->setName(QByteArrayLiteral("Multisample color buffer for QQuickRenderTarget"));
1461 colorBuffer->setWriteViewFormat(texture->writeViewFormat());
1462 if (!colorBuffer->create()) {
1463 qWarning("Failed to build multisample color buffer for QQuickRenderTarget");
1464 return false;
1465 }
1466 }
1467
1468 QRhiColorAttachment colorAttachment;
1469 if (multisampleResolve) {
1470 colorAttachment.setTexture(colorBuffer.get());
1471 colorAttachment.setResolveTexture(texture);
1472 } else {
1473 colorAttachment.setTexture(texture);
1474 }
1475
1476 QRhiTextureRenderTargetDescription rtDesc(colorAttachment);
1477 if (sampleCount > 1) {
1478 rtDesc.setDepthTexture(depthStencil.get());
1479 if (rhi->isFeatureSupported(QRhi::ResolveDepthStencil))
1480 rtDesc.setDepthResolveTexture(depthTexture);
1481 else
1482 qWarning("Depth-stencil resolve is not supported by the underlying 3D API, depth contents will not be resolved");
1483 } else {
1484 rtDesc.setDepthTexture(depthTexture);
1485 }
1486
1487 std::unique_ptr<QRhiTextureRenderTarget> rt(rhi->newTextureRenderTarget(rtDesc));
1488 rt->setName(QByteArrayLiteral("RT for QQuickRenderTarget"));
1489 std::unique_ptr<QRhiRenderPassDescriptor> rp(rt->newCompatibleRenderPassDescriptor());
1490 rt->setRenderPassDescriptor(rp.get());
1491
1492 if (!rt->create()) {
1493 qWarning("Failed to build texture render target for QQuickRenderTarget");
1494 return false;
1495 }
1496
1497 dst->rt.renderTarget = rt.release();
1498 dst->rt.owns = true;
1499 dst->res.rpDesc = rp.release();
1500 if (depthStencil)
1501 dst->implicitBuffers.depthStencilTexture = depthStencil.release();
1502 if (multisampleResolve)
1503 dst->implicitBuffers.multisampleTexture = colorBuffer.release();
1504
1505 return true;
1506}
1507
1508static bool createRhiRenderTargetMultiView(QRhiTexture *texture,
1509 QRhiTexture *maybeCustomDepthTexture,
1510 const QSize &pixelSize,
1511 int arraySize,
1512 int sampleCount,
1513 bool multisampleResolve,
1514 QRhi *rhi,
1516{
1517 // Multiview path, working with texture arrays. Optionally with a
1518 // user-supplied, non-multisample depth texture (array). (same semantics
1519 // then as with createRhiRenderTargetWithDepthTexture, but everything is a
1520 // 2D texture array here)
1521
1522 sampleCount = QSGRhiSupport::chooseSampleCount(sampleCount, rhi);
1523 if (sampleCount <= 1)
1524 multisampleResolve = false;
1525
1526 std::unique_ptr<QRhiTexture> depthStencil;
1527 if (dst->implicitBuffers.depthStencilTexture) {
1528 if (dst->implicitBuffers.depthStencilTexture->pixelSize() == pixelSize
1529 && dst->implicitBuffers.depthStencilTexture->sampleCount() == sampleCount
1530 && dst->implicitBuffers.depthStencilTexture->arraySize() == arraySize)
1531 {
1532 depthStencil.reset(dst->implicitBuffers.depthStencilTexture);
1533 dst->implicitBuffers.depthStencilTexture = nullptr;
1534 }
1535 }
1536
1537 std::unique_ptr<QRhiTexture> colorBuffer;
1538 QRhiTexture::Flags multisampleTextureFlags;
1539 QRhiTexture::Format multisampleTextureFormat = texture->format();
1540 if (multisampleResolve) {
1541 multisampleTextureFlags = QRhiTexture::RenderTarget;
1542 if (texture->flags().testFlag(QRhiTexture::sRGB))
1543 multisampleTextureFlags |= QRhiTexture::sRGB;
1544
1545 if (dst->implicitBuffers.multisampleTexture) {
1546 if (dst->implicitBuffers.multisampleTexture->pixelSize() == pixelSize
1547 && dst->implicitBuffers.multisampleTexture->format() == multisampleTextureFormat
1548 && dst->implicitBuffers.multisampleTexture->sampleCount() == sampleCount
1549 && dst->implicitBuffers.multisampleTexture->arraySize() == arraySize
1550 && dst->implicitBuffers.multisampleTexture->flags().testFlags(multisampleTextureFlags))
1551 {
1552 colorBuffer.reset(dst->implicitBuffers.multisampleTexture);
1553 dst->implicitBuffers.multisampleTexture = nullptr;
1554 }
1555 }
1556 }
1557
1558 dst->implicitBuffers.reset(rhi);
1559
1560 bool needsDepthStencilBuffer = true;
1561 if (maybeCustomDepthTexture) {
1562 if (sampleCount <= 1) {
1563 depthStencil.reset();
1564 needsDepthStencilBuffer = false;
1565 }
1566 if (maybeCustomDepthTexture->arraySize() != arraySize) {
1567 qWarning("Custom depth texture array size (%d) does not match QQuickRenderTarget (%d)",
1568 maybeCustomDepthTexture->arraySize(), arraySize);
1569 return false;
1570 }
1571 if (maybeCustomDepthTexture->pixelSize() != pixelSize) {
1572 qWarning("Custom depth texture size (%dx%d) does not match the QQuickRenderTarget (%dx%d)",
1573 maybeCustomDepthTexture->pixelSize().width(),
1574 maybeCustomDepthTexture->pixelSize().height(),
1575 pixelSize.width(),
1576 pixelSize.height());
1577 return false;
1578 }
1579 if (maybeCustomDepthTexture->sampleCount() > 1) {
1580 qWarning("Custom depth texture cannot be multisample");
1581 return false;
1582 }
1583 }
1584 if (needsDepthStencilBuffer && !depthStencil) {
1585 QRhiTexture::Format format;
1586 if (maybeCustomDepthTexture)
1587 format = maybeCustomDepthTexture->format();
1588 else
1589 format = rhi->isTextureFormatSupported(QRhiTexture::D24S8) ? QRhiTexture::D24S8 : QRhiTexture::D32FS8;
1590 depthStencil.reset(rhi->newTextureArray(format, arraySize, pixelSize, sampleCount, QRhiTexture::RenderTarget));
1591 depthStencil->setName(QByteArrayLiteral("Depth-stencil buffer (multiview) for QQuickRenderTarget"));
1592 if (!depthStencil->create()) {
1593 qWarning("Failed to build depth-stencil texture array for QQuickRenderTarget");
1594 return false;
1595 }
1596 }
1597
1598 if (multisampleResolve && !colorBuffer) {
1599 colorBuffer.reset(rhi->newTextureArray(multisampleTextureFormat, arraySize, pixelSize, sampleCount, multisampleTextureFlags));
1600 colorBuffer->setName(QByteArrayLiteral("Multisample color buffer (multiview) for QQuickRenderTarget"));
1601 colorBuffer->setWriteViewFormat(texture->writeViewFormat());
1602 if (!colorBuffer->create()) {
1603 qWarning("Failed to build multisample texture array for QQuickRenderTarget");
1604 return false;
1605 }
1606 }
1607
1608 QRhiColorAttachment colorAttachment;
1609 colorAttachment.setMultiViewCount(arraySize);
1610 if (multisampleResolve) {
1611 colorAttachment.setTexture(colorBuffer.get());
1612 colorAttachment.setResolveTexture(texture);
1613 } else {
1614 colorAttachment.setTexture(texture);
1615 }
1616
1617 QRhiTextureRenderTargetDescription rtDesc(colorAttachment);
1618 if (sampleCount > 1) {
1619 rtDesc.setDepthTexture(depthStencil.get());
1620 if (maybeCustomDepthTexture) {
1621 if (rhi->isFeatureSupported(QRhi::ResolveDepthStencil))
1622 rtDesc.setDepthResolveTexture(maybeCustomDepthTexture);
1623 else
1624 qWarning("Depth-stencil resolve is not supported by the underlying 3D API, depth contents will not be resolved");
1625 }
1626 } else {
1627 if (depthStencil)
1628 rtDesc.setDepthTexture(depthStencil.get());
1629 else if (maybeCustomDepthTexture)
1630 rtDesc.setDepthTexture(maybeCustomDepthTexture);
1631 }
1632
1633 QRhiTextureRenderTarget::Flags rtFlags;
1634 if (!maybeCustomDepthTexture)
1635 rtFlags |= QRhiTextureRenderTarget::DoNotStoreDepthStencilContents;
1636
1637 std::unique_ptr<QRhiTextureRenderTarget> rt(rhi->newTextureRenderTarget(rtDesc, rtFlags));
1638 rt->setName(QByteArrayLiteral("RT for multiview QQuickRenderTarget"));
1639 std::unique_ptr<QRhiRenderPassDescriptor> rp(rt->newCompatibleRenderPassDescriptor());
1640 rt->setRenderPassDescriptor(rp.get());
1641
1642 if (!rt->create()) {
1643 qWarning("Failed to build multiview texture render target for QQuickRenderTarget");
1644 return false;
1645 }
1646
1647 dst->rt.renderTarget = rt.release();
1648 dst->rt.owns = true;
1649 dst->res.rpDesc = rp.release();
1650 if (depthStencil)
1651 dst->implicitBuffers.depthStencilTexture = depthStencil.release();
1652 if (multisampleResolve)
1653 dst->implicitBuffers.multisampleTexture = colorBuffer.release();
1654
1655 dst->rt.multiViewCount = arraySize;
1656
1657 return true;
1658}
1659
1660bool QQuickRenderTargetPrivate::resolve(QRhi *rhi, QQuickWindowRenderTarget *dst)
1661{
1662 // dst->implicitBuffers may contain valid objects. If so, and their
1663 // properties are suitable, they are expected to be reused. Once taken what
1664 // we can reuse, it needs to be reset().
1665
1666 switch (type) {
1667 case Type::Null:
1668 dst->implicitBuffers.reset(rhi);
1669 return true;
1670
1671 case Type::NativeTexture:
1672 {
1673 QRhiTexture::Format format = u.nativeTexture.rhiFormat == QRhiTexture::UnknownFormat ? QRhiTexture::RGBA8
1674 : QRhiTexture::Format(u.nativeTexture.rhiFormat);
1675 QRhiTexture::Format viewFormat = u.nativeTexture.rhiViewFormat == QRhiTexture::UnknownFormat ? QRhiTexture::RGBA8
1676 : QRhiTexture::Format(u.nativeTexture.rhiViewFormat);
1677 const auto flags = QRhiTexture::RenderTarget | QRhiTexture::Flags(u.nativeTexture.rhiFormatFlags);
1678 std::unique_ptr<QRhiTexture> texture(rhi->newTexture(format, pixelSize, multisampleResolve ? 1 : sampleCount, flags));
1679 const bool textureIsSrgb = flags.testFlag(QRhiTexture::sRGB);
1680 const bool viewIsSrgb = QRhiTexture::Flags(u.nativeTexture.rhiViewFormatFlags).testFlag(QRhiTexture::sRGB);
1681 if (viewFormat != format || viewIsSrgb != textureIsSrgb)
1682 texture->setWriteViewFormat({ viewFormat, viewIsSrgb });
1683 if (!texture->createFrom({ u.nativeTexture.object, u.nativeTexture.layoutOrState })) {
1684 qWarning("Failed to build wrapper texture for QQuickRenderTarget");
1685 return false;
1686 }
1687 if (customDepthTexture) {
1688 if (!createRhiRenderTargetWithDepthTexture(texture.get(), customDepthTexture, pixelSize, sampleCount, multisampleResolve, rhi, dst))
1689 return false;
1690 } else {
1691 if (!createRhiRenderTarget(texture.get(), pixelSize, sampleCount, multisampleResolve, rhi, dst))
1692 return false;
1693 }
1694 dst->res.texture = texture.release();
1695 }
1696 return true;
1697
1698 case Type::NativeTextureArray:
1699 {
1700 QRhiTexture::Format format = u.nativeTextureArray.rhiFormat == QRhiTexture::UnknownFormat ? QRhiTexture::RGBA8
1701 : QRhiTexture::Format(u.nativeTextureArray.rhiFormat);
1702 QRhiTexture::Format viewFormat = u.nativeTextureArray.rhiViewFormat == QRhiTexture::UnknownFormat ? QRhiTexture::RGBA8
1703 : QRhiTexture::Format(u.nativeTextureArray.rhiViewFormat);
1704 const auto flags = QRhiTexture::RenderTarget | QRhiTexture::Flags(u.nativeTextureArray.rhiFormatFlags);
1705 const int arraySize = u.nativeTextureArray.arraySize;
1706 std::unique_ptr<QRhiTexture> texture(rhi->newTextureArray(format, arraySize, pixelSize, multisampleResolve ? 1 : sampleCount, flags));
1707 const bool textureIsSrgb = flags.testFlag(QRhiTexture::sRGB);
1708 const bool viewIsSrgb = QRhiTexture::Flags(u.nativeTextureArray.rhiViewFormatFlags).testFlag(QRhiTexture::sRGB);
1709 if (viewFormat != format || viewIsSrgb != textureIsSrgb)
1710 texture->setWriteViewFormat({ viewFormat, viewIsSrgb });
1711 if (!texture->createFrom({ u.nativeTextureArray.object, u.nativeTextureArray.layoutOrState })) {
1712 qWarning("Failed to build wrapper texture array for QQuickRenderTarget");
1713 return false;
1714 }
1715 if (!createRhiRenderTargetMultiView(texture.get(), customDepthTexture, pixelSize, arraySize, sampleCount, multisampleResolve, rhi, dst))
1716 return false;
1717 dst->res.texture = texture.release();
1718 }
1719 return true;
1720
1721 case Type::NativeRenderbuffer:
1722 {
1723 std::unique_ptr<QRhiRenderBuffer> renderbuffer(rhi->newRenderBuffer(QRhiRenderBuffer::Color, pixelSize, sampleCount));
1724 if (!renderbuffer->createFrom({ u.nativeRenderbufferObject })) {
1725 qWarning("Failed to build wrapper renderbuffer for QQuickRenderTarget");
1726 return false;
1727 }
1728 if (customDepthTexture)
1729 qWarning("Custom depth texture is not supported with renderbuffers in QQuickRenderTarget");
1730 if (!createRhiRenderTargetWithRenderBuffer(renderbuffer.get(), pixelSize, sampleCount, rhi, dst))
1731 return false;
1732 dst->res.renderBuffer = renderbuffer.release();
1733 }
1734 return true;
1735
1736 case Type::RhiRenderTarget:
1737 dst->implicitBuffers.reset(rhi);
1738 dst->rt.renderTarget = u.rhiRt;
1739 dst->rt.owns = false;
1740 if (dst->rt.renderTarget->resourceType() == QRhiResource::TextureRenderTarget) {
1741 auto texRt = static_cast<QRhiTextureRenderTarget *>(dst->rt.renderTarget);
1742 const QRhiTextureRenderTargetDescription desc = texRt->description();
1743 bool first = true;
1744 for (auto it = desc.cbeginColorAttachments(), end = desc.cendColorAttachments(); it != end; ++it) {
1745 if (it->multiViewCount() <= 1)
1746 continue;
1747 if (first || dst->rt.multiViewCount == it->multiViewCount()) {
1748 first = false;
1749 if (it->texture() && it->texture()->flags().testFlag(QRhiTexture::TextureArray)) {
1750 if (it->texture()->arraySize() >= it->layer() + it->multiViewCount()) {
1751 dst->rt.multiViewCount = it->multiViewCount();
1752 } else {
1753 qWarning("Invalid QQuickRenderTarget; needs at least %d elements in texture array, got %d",
1754 it->layer() + it->multiViewCount(),
1755 it->texture()->arraySize());
1756 return false;
1757 }
1758 } else {
1759 qWarning("Invalid QQuickRenderTarget; multiview requires a texture array");
1760 return false;
1761 }
1762 } else {
1763 qWarning("Inconsistent multiViewCount in QQuickRenderTarget (was %d, now found an attachment with %d)",
1764 dst->rt.multiViewCount, it->multiViewCount());
1765 return false;
1766 }
1767 }
1768 }
1769 if (customDepthTexture)
1770 qWarning("Custom depth texture is not supported with QRhiRenderTarget in QQuickRenderTarget");
1771 return true;
1772
1773 case Type::PaintDevice:
1774 dst->implicitBuffers.reset(rhi);
1775 dst->sw.paintDevice = u.paintDevice;
1776 dst->sw.owns = false;
1777 return true;
1778 }
1779
1780 Q_UNREACHABLE_RETURN(false);
1781}
1782
1783QT_END_NAMESPACE
\inmodule QtGuiPrivate \inheaderfile rhi/qrhi.h
Definition qrhi.h:577
\inmodule QtGuiPrivate \inheaderfile rhi/qrhi.h
Definition qrhi.h:621
static bool createRhiRenderTargetWithRenderBuffer(QRhiRenderBuffer *renderBuffer, const QSize &pixelSize, int sampleCount, QRhi *rhi, QQuickWindowRenderTarget *dst)
static bool createRhiRenderTargetWithDepthTexture(QRhiTexture *texture, QRhiTexture *depthTexture, const QSize &pixelSize, int sampleCount, bool multisampleResolve, QRhi *rhi, QQuickWindowRenderTarget *dst)
static bool createRhiRenderTargetMultiView(QRhiTexture *texture, QRhiTexture *maybeCustomDepthTexture, const QSize &pixelSize, int arraySize, int sampleCount, bool multisampleResolve, QRhi *rhi, QQuickWindowRenderTarget *dst)
static bool createRhiRenderTarget(QRhiTexture *texture, const QSize &pixelSize, int sampleCount, bool multisampleResolve, QRhi *rhi, QQuickWindowRenderTarget *dst)