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 QSGRhiSupport::depthStencilBufferFlags()));
1256 depthStencil->setName(QByteArrayLiteral("Depth-stencil buffer for QQuickRenderTarget"));
1257 if (!depthStencil->create()) {
1258 qWarning("Failed to build depth-stencil buffer for QQuickRenderTarget");
1259 return false;
1260 }
1261 }
1262
1263 QRhiColorAttachment colorAttachment(renderBuffer);
1264 QRhiTextureRenderTargetDescription rtDesc(colorAttachment);
1265 rtDesc.setDepthStencilBuffer(depthStencil.get());
1266 std::unique_ptr<QRhiTextureRenderTarget> rt(rhi->newTextureRenderTarget(rtDesc));
1267 rt->setName(QByteArrayLiteral("RT for QQuickRenderTarget with renderbuffer"));
1268 std::unique_ptr<QRhiRenderPassDescriptor> rp(rt->newCompatibleRenderPassDescriptor());
1269 rt->setRenderPassDescriptor(rp.get());
1270
1271 if (!rt->create()) {
1272 qWarning("Failed to build renderbuffer-based render target for QQuickRenderTarget");
1273 return false;
1274 }
1275
1276 dst->rt.renderTarget = rt.release();
1277 dst->rt.owns = true;
1278 dst->res.rpDesc = rp.release();
1279 dst->implicitBuffers.depthStencil = depthStencil.release();
1280
1281 return true;
1282}
1283
1284static bool createRhiRenderTarget(QRhiTexture *texture,
1285 const QSize &pixelSize,
1286 int sampleCount,
1287 bool multisampleResolve,
1288 QRhi *rhi,
1290{
1291 // Simple path: no user-supplied depth texture. So create our own
1292 // depth-stencil buffer, using renderbuffers (so this is still GLES 2.0
1293 // compatible), with MSAA support being GLES 3.0 compatible.
1294
1295 sampleCount = QSGRhiSupport::chooseSampleCount(sampleCount, rhi);
1296 if (sampleCount <= 1)
1297 multisampleResolve = false;
1298
1299 std::unique_ptr<QRhiRenderBuffer> depthStencil;
1300 if (dst->implicitBuffers.depthStencil) {
1301 if (dst->implicitBuffers.depthStencil->pixelSize() == pixelSize
1302 && dst->implicitBuffers.depthStencil->sampleCount() == sampleCount)
1303 {
1304 depthStencil.reset(dst->implicitBuffers.depthStencil);
1305 dst->implicitBuffers.depthStencil = nullptr;
1306 }
1307 }
1308
1309 std::unique_ptr<QRhiTexture> colorBuffer;
1310 QRhiTexture::Flags multisampleTextureFlags;
1311 QRhiTexture::Format multisampleTextureFormat = texture->format();
1312 if (multisampleResolve) {
1313 multisampleTextureFlags = QRhiTexture::RenderTarget;
1314 if (texture->flags().testFlag(QRhiTexture::sRGB))
1315 multisampleTextureFlags |= QRhiTexture::sRGB;
1316
1317 if (dst->implicitBuffers.multisampleTexture) {
1318 if (dst->implicitBuffers.multisampleTexture->pixelSize() == pixelSize
1319 && dst->implicitBuffers.multisampleTexture->format() == multisampleTextureFormat
1320 && dst->implicitBuffers.multisampleTexture->sampleCount() == sampleCount
1321 && dst->implicitBuffers.multisampleTexture->flags().testFlags(multisampleTextureFlags))
1322 {
1323 colorBuffer.reset(dst->implicitBuffers.multisampleTexture);
1324 dst->implicitBuffers.multisampleTexture = nullptr;
1325 }
1326 }
1327 }
1328
1329 dst->implicitBuffers.reset(rhi);
1330
1331 if (!depthStencil) {
1332 depthStencil.reset(rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil, pixelSize, sampleCount,
1333 QSGRhiSupport::depthStencilBufferFlags()));
1334 depthStencil->setName(QByteArrayLiteral("Depth-stencil buffer for QQuickRenderTarget"));
1335 if (!depthStencil->create()) {
1336 qWarning("Failed to build depth-stencil buffer for QQuickRenderTarget");
1337 return false;
1338 }
1339 }
1340
1341 if (multisampleResolve && !colorBuffer) {
1342 colorBuffer.reset(rhi->newTexture(multisampleTextureFormat, pixelSize, sampleCount, multisampleTextureFlags));
1343 colorBuffer->setName(QByteArrayLiteral("Multisample color buffer for QQuickRenderTarget"));
1344 colorBuffer->setWriteViewFormat(texture->writeViewFormat());
1345 if (!colorBuffer->create()) {
1346 qWarning("Failed to build multisample color buffer for QQuickRenderTarget");
1347 return false;
1348 }
1349 }
1350
1351 QRhiColorAttachment colorAttachment;
1352 if (multisampleResolve) {
1353 colorAttachment.setTexture(colorBuffer.get());
1354 colorAttachment.setResolveTexture(texture);
1355 } else {
1356 colorAttachment.setTexture(texture);
1357 }
1358 QRhiTextureRenderTargetDescription rtDesc(colorAttachment);
1359 rtDesc.setDepthStencilBuffer(depthStencil.get());
1360 std::unique_ptr<QRhiTextureRenderTarget> rt(rhi->newTextureRenderTarget(rtDesc));
1361 rt->setName(QByteArrayLiteral("RT for QQuickRenderTarget"));
1362 std::unique_ptr<QRhiRenderPassDescriptor> rp(rt->newCompatibleRenderPassDescriptor());
1363 rt->setRenderPassDescriptor(rp.get());
1364
1365 if (!rt->create()) {
1366 qWarning("Failed to build texture render target for QQuickRenderTarget");
1367 return false;
1368 }
1369
1370 dst->rt.renderTarget = rt.release();
1371 dst->rt.owns = true;
1372 dst->res.rpDesc = rp.release();
1373 dst->implicitBuffers.depthStencil = depthStencil.release();
1374 if (multisampleResolve)
1375 dst->implicitBuffers.multisampleTexture = colorBuffer.release();
1376
1377 return true;
1378}
1379
1380static bool createRhiRenderTargetWithDepthTexture(QRhiTexture *texture,
1381 QRhiTexture *depthTexture,
1382 const QSize &pixelSize,
1383 int sampleCount,
1384 bool multisampleResolve,
1385 QRhi *rhi,
1387{
1388 // This version takes a user-supplied depthTexture. That texture is always
1389 // non-multisample. If sample count is > 1, we still need our own
1390 // multisample depth-stencil buffer, and the depth(stencil) data is expected
1391 // to be resolved (and written out) to depthTexture, _if_ the underlying API
1392 // supports it (see QRhi's ResolveDepthStencil feature). The intermediate,
1393 // multisample depth-stencil buffer must be a texture here (not
1394 // renderbuffer), specifically for OpenGL ES and its related multisample
1395 // extensions.
1396
1397 sampleCount = QSGRhiSupport::chooseSampleCount(sampleCount, rhi);
1398 if (sampleCount <= 1)
1399 multisampleResolve = false;
1400
1401 std::unique_ptr<QRhiTexture> depthStencil;
1402 if (dst->implicitBuffers.depthStencilTexture) {
1403 if (dst->implicitBuffers.depthStencilTexture->pixelSize() == pixelSize
1404 && dst->implicitBuffers.depthStencilTexture->sampleCount() == sampleCount)
1405 {
1406 depthStencil.reset(dst->implicitBuffers.depthStencilTexture);
1407 dst->implicitBuffers.depthStencilTexture = nullptr;
1408 }
1409 }
1410
1411 std::unique_ptr<QRhiTexture> colorBuffer;
1412 QRhiTexture::Flags multisampleTextureFlags;
1413 QRhiTexture::Format multisampleTextureFormat = texture->format();
1414 if (multisampleResolve) {
1415 multisampleTextureFlags = QRhiTexture::RenderTarget;
1416 if (texture->flags().testFlag(QRhiTexture::sRGB))
1417 multisampleTextureFlags |= QRhiTexture::sRGB;
1418
1419 if (dst->implicitBuffers.multisampleTexture) {
1420 if (dst->implicitBuffers.multisampleTexture->pixelSize() == pixelSize
1421 && dst->implicitBuffers.multisampleTexture->format() == multisampleTextureFormat
1422 && dst->implicitBuffers.multisampleTexture->sampleCount() == sampleCount
1423 && dst->implicitBuffers.multisampleTexture->flags().testFlags(multisampleTextureFlags))
1424 {
1425 colorBuffer.reset(dst->implicitBuffers.multisampleTexture);
1426 dst->implicitBuffers.multisampleTexture = nullptr;
1427 }
1428 }
1429 }
1430
1431 dst->implicitBuffers.reset(rhi);
1432
1433 bool needsDepthStencilBuffer = true;
1434 if (sampleCount <= 1) {
1435 depthStencil.reset();
1436 needsDepthStencilBuffer = false;
1437 }
1438 if (depthTexture->pixelSize() != pixelSize) {
1439 qWarning("Custom depth texture size (%dx%d) does not match the QQuickRenderTarget (%dx%d)",
1440 depthTexture->pixelSize().width(),
1441 depthTexture->pixelSize().height(),
1442 pixelSize.width(),
1443 pixelSize.height());
1444 return false;
1445 }
1446 if (depthTexture->sampleCount() > 1) {
1447 qWarning("Custom depth texture cannot be multisample");
1448 return false;
1449 }
1450 if (needsDepthStencilBuffer && !depthStencil) {
1451 QRhiTexture::Format multisampleDepthTextureFormat = depthTexture->format();
1452 depthStencil.reset(rhi->newTexture(multisampleDepthTextureFormat, pixelSize, sampleCount, QRhiTexture::RenderTarget));
1453 depthStencil->setName(QByteArrayLiteral("Depth-stencil texture for QQuickRenderTarget"));
1454 if (!depthStencil->create()) {
1455 qWarning("Failed to build depth-stencil buffer for QQuickRenderTarget");
1456 return false;
1457 }
1458 }
1459
1460 if (multisampleResolve && !colorBuffer) {
1461 colorBuffer.reset(rhi->newTexture(multisampleTextureFormat, pixelSize, sampleCount, multisampleTextureFlags));
1462 colorBuffer->setName(QByteArrayLiteral("Multisample color buffer for QQuickRenderTarget"));
1463 colorBuffer->setWriteViewFormat(texture->writeViewFormat());
1464 if (!colorBuffer->create()) {
1465 qWarning("Failed to build multisample color buffer for QQuickRenderTarget");
1466 return false;
1467 }
1468 }
1469
1470 QRhiColorAttachment colorAttachment;
1471 if (multisampleResolve) {
1472 colorAttachment.setTexture(colorBuffer.get());
1473 colorAttachment.setResolveTexture(texture);
1474 } else {
1475 colorAttachment.setTexture(texture);
1476 }
1477
1478 QRhiTextureRenderTargetDescription rtDesc(colorAttachment);
1479 if (sampleCount > 1) {
1480 rtDesc.setDepthTexture(depthStencil.get());
1481 if (rhi->isFeatureSupported(QRhi::ResolveDepthStencil))
1482 rtDesc.setDepthResolveTexture(depthTexture);
1483 else
1484 qWarning("Depth-stencil resolve is not supported by the underlying 3D API, depth contents will not be resolved");
1485 } else {
1486 rtDesc.setDepthTexture(depthTexture);
1487 }
1488
1489 std::unique_ptr<QRhiTextureRenderTarget> rt(rhi->newTextureRenderTarget(rtDesc));
1490 rt->setName(QByteArrayLiteral("RT for QQuickRenderTarget"));
1491 std::unique_ptr<QRhiRenderPassDescriptor> rp(rt->newCompatibleRenderPassDescriptor());
1492 rt->setRenderPassDescriptor(rp.get());
1493
1494 if (!rt->create()) {
1495 qWarning("Failed to build texture render target for QQuickRenderTarget");
1496 return false;
1497 }
1498
1499 dst->rt.renderTarget = rt.release();
1500 dst->rt.owns = true;
1501 dst->res.rpDesc = rp.release();
1502 if (depthStencil)
1503 dst->implicitBuffers.depthStencilTexture = depthStencil.release();
1504 if (multisampleResolve)
1505 dst->implicitBuffers.multisampleTexture = colorBuffer.release();
1506
1507 return true;
1508}
1509
1510static bool createRhiRenderTargetMultiView(QRhiTexture *texture,
1511 QRhiTexture *maybeCustomDepthTexture,
1512 const QSize &pixelSize,
1513 int arraySize,
1514 int sampleCount,
1515 bool multisampleResolve,
1516 QRhi *rhi,
1518{
1519 // Multiview path, working with texture arrays. Optionally with a
1520 // user-supplied, non-multisample depth texture (array). (same semantics
1521 // then as with createRhiRenderTargetWithDepthTexture, but everything is a
1522 // 2D texture array here)
1523
1524 sampleCount = QSGRhiSupport::chooseSampleCount(sampleCount, rhi);
1525 if (sampleCount <= 1)
1526 multisampleResolve = false;
1527
1528 std::unique_ptr<QRhiTexture> depthStencil;
1529 if (dst->implicitBuffers.depthStencilTexture) {
1530 if (dst->implicitBuffers.depthStencilTexture->pixelSize() == pixelSize
1531 && dst->implicitBuffers.depthStencilTexture->sampleCount() == sampleCount
1532 && dst->implicitBuffers.depthStencilTexture->arraySize() == arraySize)
1533 {
1534 depthStencil.reset(dst->implicitBuffers.depthStencilTexture);
1535 dst->implicitBuffers.depthStencilTexture = nullptr;
1536 }
1537 }
1538
1539 std::unique_ptr<QRhiTexture> colorBuffer;
1540 QRhiTexture::Flags multisampleTextureFlags;
1541 QRhiTexture::Format multisampleTextureFormat = texture->format();
1542 if (multisampleResolve) {
1543 multisampleTextureFlags = QRhiTexture::RenderTarget;
1544 if (texture->flags().testFlag(QRhiTexture::sRGB))
1545 multisampleTextureFlags |= QRhiTexture::sRGB;
1546
1547 if (dst->implicitBuffers.multisampleTexture) {
1548 if (dst->implicitBuffers.multisampleTexture->pixelSize() == pixelSize
1549 && dst->implicitBuffers.multisampleTexture->format() == multisampleTextureFormat
1550 && dst->implicitBuffers.multisampleTexture->sampleCount() == sampleCount
1551 && dst->implicitBuffers.multisampleTexture->arraySize() == arraySize
1552 && dst->implicitBuffers.multisampleTexture->flags().testFlags(multisampleTextureFlags))
1553 {
1554 colorBuffer.reset(dst->implicitBuffers.multisampleTexture);
1555 dst->implicitBuffers.multisampleTexture = nullptr;
1556 }
1557 }
1558 }
1559
1560 dst->implicitBuffers.reset(rhi);
1561
1562 bool needsDepthStencilBuffer = true;
1563 if (maybeCustomDepthTexture) {
1564 if (sampleCount <= 1) {
1565 depthStencil.reset();
1566 needsDepthStencilBuffer = false;
1567 }
1568 if (maybeCustomDepthTexture->arraySize() != arraySize) {
1569 qWarning("Custom depth texture array size (%d) does not match QQuickRenderTarget (%d)",
1570 maybeCustomDepthTexture->arraySize(), arraySize);
1571 return false;
1572 }
1573 if (maybeCustomDepthTexture->pixelSize() != pixelSize) {
1574 qWarning("Custom depth texture size (%dx%d) does not match the QQuickRenderTarget (%dx%d)",
1575 maybeCustomDepthTexture->pixelSize().width(),
1576 maybeCustomDepthTexture->pixelSize().height(),
1577 pixelSize.width(),
1578 pixelSize.height());
1579 return false;
1580 }
1581 if (maybeCustomDepthTexture->sampleCount() > 1) {
1582 qWarning("Custom depth texture cannot be multisample");
1583 return false;
1584 }
1585 }
1586 if (needsDepthStencilBuffer && !depthStencil) {
1587 QRhiTexture::Format format;
1588 if (maybeCustomDepthTexture)
1589 format = maybeCustomDepthTexture->format();
1590 else
1591 format = rhi->isTextureFormatSupported(QRhiTexture::D24S8) ? QRhiTexture::D24S8 : QRhiTexture::D32FS8;
1592 depthStencil.reset(rhi->newTextureArray(format, arraySize, pixelSize, sampleCount, QRhiTexture::RenderTarget));
1593 depthStencil->setName(QByteArrayLiteral("Depth-stencil buffer (multiview) for QQuickRenderTarget"));
1594 if (!depthStencil->create()) {
1595 qWarning("Failed to build depth-stencil texture array for QQuickRenderTarget");
1596 return false;
1597 }
1598 }
1599
1600 if (multisampleResolve && !colorBuffer) {
1601 colorBuffer.reset(rhi->newTextureArray(multisampleTextureFormat, arraySize, pixelSize, sampleCount, multisampleTextureFlags));
1602 colorBuffer->setName(QByteArrayLiteral("Multisample color buffer (multiview) for QQuickRenderTarget"));
1603 colorBuffer->setWriteViewFormat(texture->writeViewFormat());
1604 if (!colorBuffer->create()) {
1605 qWarning("Failed to build multisample texture array for QQuickRenderTarget");
1606 return false;
1607 }
1608 }
1609
1610 QRhiColorAttachment colorAttachment;
1611 colorAttachment.setMultiViewCount(arraySize);
1612 if (multisampleResolve) {
1613 colorAttachment.setTexture(colorBuffer.get());
1614 colorAttachment.setResolveTexture(texture);
1615 } else {
1616 colorAttachment.setTexture(texture);
1617 }
1618
1619 QRhiTextureRenderTargetDescription rtDesc(colorAttachment);
1620 if (sampleCount > 1) {
1621 rtDesc.setDepthTexture(depthStencil.get());
1622 if (maybeCustomDepthTexture) {
1623 if (rhi->isFeatureSupported(QRhi::ResolveDepthStencil))
1624 rtDesc.setDepthResolveTexture(maybeCustomDepthTexture);
1625 else
1626 qWarning("Depth-stencil resolve is not supported by the underlying 3D API, depth contents will not be resolved");
1627 }
1628 } else {
1629 if (depthStencil)
1630 rtDesc.setDepthTexture(depthStencil.get());
1631 else if (maybeCustomDepthTexture)
1632 rtDesc.setDepthTexture(maybeCustomDepthTexture);
1633 }
1634
1635 QRhiTextureRenderTarget::Flags rtFlags;
1636 if (!maybeCustomDepthTexture)
1637 rtFlags |= QRhiTextureRenderTarget::DoNotStoreDepthStencilContents;
1638
1639 std::unique_ptr<QRhiTextureRenderTarget> rt(rhi->newTextureRenderTarget(rtDesc, rtFlags));
1640 rt->setName(QByteArrayLiteral("RT for multiview QQuickRenderTarget"));
1641 std::unique_ptr<QRhiRenderPassDescriptor> rp(rt->newCompatibleRenderPassDescriptor());
1642 rt->setRenderPassDescriptor(rp.get());
1643
1644 if (!rt->create()) {
1645 qWarning("Failed to build multiview texture render target for QQuickRenderTarget");
1646 return false;
1647 }
1648
1649 dst->rt.renderTarget = rt.release();
1650 dst->rt.owns = true;
1651 dst->res.rpDesc = rp.release();
1652 if (depthStencil)
1653 dst->implicitBuffers.depthStencilTexture = depthStencil.release();
1654 if (multisampleResolve)
1655 dst->implicitBuffers.multisampleTexture = colorBuffer.release();
1656
1657 dst->rt.multiViewCount = arraySize;
1658
1659 return true;
1660}
1661
1662bool QQuickRenderTargetPrivate::resolve(QRhi *rhi, QQuickWindowRenderTarget *dst)
1663{
1664 // dst->implicitBuffers may contain valid objects. If so, and their
1665 // properties are suitable, they are expected to be reused. Once taken what
1666 // we can reuse, it needs to be reset().
1667
1668 switch (type) {
1669 case Type::Null:
1670 dst->implicitBuffers.reset(rhi);
1671 return true;
1672
1673 case Type::NativeTexture:
1674 {
1675 QRhiTexture::Format format = u.nativeTexture.rhiFormat == QRhiTexture::UnknownFormat ? QRhiTexture::RGBA8
1676 : QRhiTexture::Format(u.nativeTexture.rhiFormat);
1677 QRhiTexture::Format viewFormat = u.nativeTexture.rhiViewFormat == QRhiTexture::UnknownFormat ? QRhiTexture::RGBA8
1678 : QRhiTexture::Format(u.nativeTexture.rhiViewFormat);
1679 const auto flags = QRhiTexture::RenderTarget | QRhiTexture::Flags(u.nativeTexture.rhiFormatFlags);
1680 std::unique_ptr<QRhiTexture> texture(rhi->newTexture(format, pixelSize, multisampleResolve ? 1 : sampleCount, flags));
1681 const bool textureIsSrgb = flags.testFlag(QRhiTexture::sRGB);
1682 const bool viewIsSrgb = QRhiTexture::Flags(u.nativeTexture.rhiViewFormatFlags).testFlag(QRhiTexture::sRGB);
1683 if (viewFormat != format || viewIsSrgb != textureIsSrgb)
1684 texture->setWriteViewFormat({ viewFormat, viewIsSrgb });
1685 if (!texture->createFrom({ u.nativeTexture.object, u.nativeTexture.layoutOrState })) {
1686 qWarning("Failed to build wrapper texture for QQuickRenderTarget");
1687 return false;
1688 }
1689 if (customDepthTexture) {
1690 if (!createRhiRenderTargetWithDepthTexture(texture.get(), customDepthTexture, pixelSize, sampleCount, multisampleResolve, rhi, dst))
1691 return false;
1692 } else {
1693 if (!createRhiRenderTarget(texture.get(), pixelSize, sampleCount, multisampleResolve, rhi, dst))
1694 return false;
1695 }
1696 dst->res.texture = texture.release();
1697 }
1698 return true;
1699
1700 case Type::NativeTextureArray:
1701 {
1702 QRhiTexture::Format format = u.nativeTextureArray.rhiFormat == QRhiTexture::UnknownFormat ? QRhiTexture::RGBA8
1703 : QRhiTexture::Format(u.nativeTextureArray.rhiFormat);
1704 QRhiTexture::Format viewFormat = u.nativeTextureArray.rhiViewFormat == QRhiTexture::UnknownFormat ? QRhiTexture::RGBA8
1705 : QRhiTexture::Format(u.nativeTextureArray.rhiViewFormat);
1706 const auto flags = QRhiTexture::RenderTarget | QRhiTexture::Flags(u.nativeTextureArray.rhiFormatFlags);
1707 const int arraySize = u.nativeTextureArray.arraySize;
1708 std::unique_ptr<QRhiTexture> texture(rhi->newTextureArray(format, arraySize, pixelSize, multisampleResolve ? 1 : sampleCount, flags));
1709 const bool textureIsSrgb = flags.testFlag(QRhiTexture::sRGB);
1710 const bool viewIsSrgb = QRhiTexture::Flags(u.nativeTextureArray.rhiViewFormatFlags).testFlag(QRhiTexture::sRGB);
1711 if (viewFormat != format || viewIsSrgb != textureIsSrgb)
1712 texture->setWriteViewFormat({ viewFormat, viewIsSrgb });
1713 if (!texture->createFrom({ u.nativeTextureArray.object, u.nativeTextureArray.layoutOrState })) {
1714 qWarning("Failed to build wrapper texture array for QQuickRenderTarget");
1715 return false;
1716 }
1717 if (!createRhiRenderTargetMultiView(texture.get(), customDepthTexture, pixelSize, arraySize, sampleCount, multisampleResolve, rhi, dst))
1718 return false;
1719 dst->res.texture = texture.release();
1720 }
1721 return true;
1722
1723 case Type::NativeRenderbuffer:
1724 {
1725 std::unique_ptr<QRhiRenderBuffer> renderbuffer(rhi->newRenderBuffer(QRhiRenderBuffer::Color, pixelSize, sampleCount));
1726 if (!renderbuffer->createFrom({ u.nativeRenderbufferObject })) {
1727 qWarning("Failed to build wrapper renderbuffer for QQuickRenderTarget");
1728 return false;
1729 }
1730 if (customDepthTexture)
1731 qWarning("Custom depth texture is not supported with renderbuffers in QQuickRenderTarget");
1732 if (!createRhiRenderTargetWithRenderBuffer(renderbuffer.get(), pixelSize, sampleCount, rhi, dst))
1733 return false;
1734 dst->res.renderBuffer = renderbuffer.release();
1735 }
1736 return true;
1737
1738 case Type::RhiRenderTarget:
1739 dst->implicitBuffers.reset(rhi);
1740 dst->rt.renderTarget = u.rhiRt;
1741 dst->rt.owns = false;
1742 if (dst->rt.renderTarget->resourceType() == QRhiResource::TextureRenderTarget) {
1743 auto texRt = static_cast<QRhiTextureRenderTarget *>(dst->rt.renderTarget);
1744 const QRhiTextureRenderTargetDescription desc = texRt->description();
1745 bool first = true;
1746 for (auto it = desc.cbeginColorAttachments(), end = desc.cendColorAttachments(); it != end; ++it) {
1747 if (it->multiViewCount() <= 1)
1748 continue;
1749 if (first || dst->rt.multiViewCount == it->multiViewCount()) {
1750 first = false;
1751 if (it->texture() && it->texture()->flags().testFlag(QRhiTexture::TextureArray)) {
1752 if (it->texture()->arraySize() >= it->layer() + it->multiViewCount()) {
1753 dst->rt.multiViewCount = it->multiViewCount();
1754 } else {
1755 qWarning("Invalid QQuickRenderTarget; needs at least %d elements in texture array, got %d",
1756 it->layer() + it->multiViewCount(),
1757 it->texture()->arraySize());
1758 return false;
1759 }
1760 } else {
1761 qWarning("Invalid QQuickRenderTarget; multiview requires a texture array");
1762 return false;
1763 }
1764 } else {
1765 qWarning("Inconsistent multiViewCount in QQuickRenderTarget (was %d, now found an attachment with %d)",
1766 dst->rt.multiViewCount, it->multiViewCount());
1767 return false;
1768 }
1769 }
1770 }
1771 if (customDepthTexture)
1772 qWarning("Custom depth texture is not supported with QRhiRenderTarget in QQuickRenderTarget");
1773 return true;
1774
1775 case Type::PaintDevice:
1776 dst->implicitBuffers.reset(rhi);
1777 dst->sw.paintDevice = u.paintDevice;
1778 dst->sw.owns = false;
1779 return true;
1780 }
1781
1782 Q_UNREACHABLE_RETURN(false);
1783}
1784
1785QT_END_NAMESPACE
\inmodule QtGuiPrivate \inheaderfile rhi/qrhi.h
Definition qrhi.h:580
\inmodule QtGuiPrivate \inheaderfile rhi/qrhi.h
Definition qrhi.h:624
Combined button and popup list for selecting options.
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)