Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qquickrhiitem.cpp
Go to the documentation of this file.
1// Copyright (C) 2023 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qquickrhiitem_p.h"
5
7
164
166{
167 return m_sgTexture.get();
168}
169
171{
172 // owns either m_colorTexture or m_resolveTexture
173 m_sgTexture.reset();
174
175 m_colorTexture = nullptr;
176 m_resolveTexture = nullptr;
177
178 m_msaaColorBuffer.reset();
179}
180
187
189{
190 if (!m_rhi) {
191 m_rhi = m_window->rhi();
192 if (!m_rhi) {
193 qWarning("No QRhi found for window %p, QQuickRhiItem will not be functional", m_window);
194 return;
195 }
196 }
197
198 m_dpr = m_window->effectiveDevicePixelRatio();
199 const int minTexSize = m_rhi->resourceLimit(QRhi::TextureSizeMin);
200 const int maxTexSize = m_rhi->resourceLimit(QRhi::TextureSizeMax);
201
202 QQuickRhiItemPrivate *itemD = m_item->d_func();
203 QSize newSize = QSize(itemD->fixedTextureWidth, itemD->fixedTextureHeight);
204 if (newSize.isEmpty())
205 newSize = QSize(int(m_item->width()), int(m_item->height())) * m_dpr;
206
207 newSize.setWidth(qMin(maxTexSize, qMax(minTexSize, newSize.width())));
208 newSize.setHeight(qMin(maxTexSize, qMax(minTexSize, newSize.height())));
209
210 if (m_colorTexture) {
211 if (m_colorTexture->format() != itemD->rhiTextureFormat
212 || m_colorTexture->sampleCount() != itemD->samples)
213 {
216 }
217 }
218
219 if (m_msaaColorBuffer) {
220 if (m_msaaColorBuffer->backingFormat() != itemD->rhiTextureFormat
221 || m_msaaColorBuffer->sampleCount() != itemD->samples)
222 {
225 }
226 }
227
228 if (m_sgTexture && m_sgTexture->hasAlphaChannel() != itemD->blend) {
231 }
232
233 if (!m_colorTexture && itemD->samples <= 1) {
234 if (!m_rhi->isTextureFormatSupported(itemD->rhiTextureFormat)) {
235 qWarning("QQuickRhiItem: The requested texture format (%d) is not supported by the "
236 "underlying 3D graphics API implementation", int(itemD->rhiTextureFormat));
237 }
238 m_colorTexture = m_rhi->newTexture(itemD->rhiTextureFormat, newSize, itemD->samples,
240 if (!m_colorTexture->create()) {
241 qWarning("Failed to create backing texture for QQuickRhiItem");
242 delete m_colorTexture;
243 m_colorTexture = nullptr;
244 return;
245 }
246 }
247
248 if (itemD->samples > 1) {
249 if (!m_msaaColorBuffer) {
251 qWarning("QQuickRhiItem: Multisample renderbuffers are reported as unsupported; "
252 "sample count %d will not work as expected", itemD->samples);
253 }
254 if (!m_rhi->isTextureFormatSupported(itemD->rhiTextureFormat)) {
255 qWarning("QQuickRhiItem: The requested texture format (%d) is not supported by the "
256 "underlying 3D graphics API implementation", int(itemD->rhiTextureFormat));
257 }
258 m_msaaColorBuffer.reset(m_rhi->newRenderBuffer(QRhiRenderBuffer::Color, newSize, itemD->samples,
259 {}, itemD->rhiTextureFormat));
260 if (!m_msaaColorBuffer->create()) {
261 qWarning("Failed to create multisample color buffer for QQuickRhiItem");
262 m_msaaColorBuffer.reset();
263 return;
264 }
265 }
266 if (!m_resolveTexture) {
267 m_resolveTexture = m_rhi->newTexture(itemD->rhiTextureFormat, newSize, 1,
269 if (!m_resolveTexture->create()) {
270 qWarning("Failed to create resolve texture for QQuickRhiItem");
271 delete m_resolveTexture;
272 m_resolveTexture = nullptr;
273 return;
274 }
275 }
276 } else if (m_resolveTexture) {
278 m_resolveTexture = nullptr;
279 }
280
281 if (m_colorTexture && m_colorTexture->pixelSize() != newSize) {
283 if (!m_colorTexture->create())
284 qWarning("Failed to rebuild texture for QQuickRhiItem after resizing");
285 }
286
287 if (m_msaaColorBuffer && m_msaaColorBuffer->pixelSize() != newSize) {
288 m_msaaColorBuffer->setPixelSize(newSize);
289 if (!m_msaaColorBuffer->create())
290 qWarning("Failed to rebuild multisample color buffer for QQuickRhiitem after resizing");
291 }
292
293 if (m_resolveTexture && m_resolveTexture->pixelSize() != newSize) {
295 if (!m_resolveTexture->create())
296 qWarning("Failed to rebuild resolve texture for QQuickRhiItem after resizing");
297 }
298
299 if (!m_sgTexture) {
300 QQuickWindow::CreateTextureOptions options;
301 if (itemD->blend)
302 options |= QQuickWindow::TextureHasAlphaChannel;
303 // the QSGTexture takes ownership of the QRhiTexture
304 m_sgTexture.reset(m_window->createTextureFromRhiTexture(m_colorTexture ? m_colorTexture : m_resolveTexture,
305 options));
306 setTexture(m_sgTexture.get());
307 }
308
309 if (itemD->autoRenderTarget) {
310 const QSize pixelSize = m_colorTexture ? m_colorTexture->pixelSize()
311 : m_msaaColorBuffer->pixelSize();
314 if (!m_depthStencilBuffer->create()) {
315 qWarning("Failed to create depth-stencil buffer for QQuickRhiItem");
317 return;
318 }
319 } else if (m_depthStencilBuffer->pixelSize() != pixelSize) {
320 m_depthStencilBuffer->setPixelSize(pixelSize);
321 if (!m_depthStencilBuffer->create()) {
322 qWarning("Failed to rebuild depth-stencil buffer for QQuickRhiItem with new size");
323 return;
324 }
325 }
326 if (!m_renderTarget) {
327 QRhiColorAttachment color0;
328 if (m_colorTexture)
329 color0.setTexture(m_colorTexture);
330 else
331 color0.setRenderBuffer(m_msaaColorBuffer.get());
332 if (itemD->samples > 1)
333 color0.setResolveTexture(m_resolveTexture);
336 m_renderPassDescriptor.reset(m_renderTarget->newCompatibleRenderPassDescriptor());
337 m_renderTarget->setRenderPassDescriptor(m_renderPassDescriptor.get());
338 if (!m_renderTarget->create()) {
339 qWarning("Failed to create render target for QQuickRhiitem");
341 return;
342 }
343 }
344 } else {
346 }
347
348 if (newSize != itemD->effectiveTextureSize) {
349 itemD->effectiveTextureSize = newSize;
351 }
352
354 if (cb)
355 m_renderer->initialize(cb);
356
357 m_renderer->synchronize(m_item);
358}
359
361{
362 QRhiSwapChain *swapchain = m_window->swapChain();
363 QSGRendererInterface *rif = m_window->rendererInterface();
364
365 // Handle both cases: on-screen QQuickWindow vs. off-screen QQuickWindow
366 // e.g. by using QQuickRenderControl to redirect into a texture.
367 QRhiCommandBuffer *cb = swapchain ? swapchain->currentFrameCommandBuffer()
368 : static_cast<QRhiCommandBuffer *>(
370
371 if (!cb) {
372 qWarning("QQuickRhiItem: Neither swapchain nor redirected command buffer are available.");
373 return nullptr;
374 }
375
376 return cb;
377}
378
380{
381 // called before Qt Quick starts recording its main render pass
382
383 if (!isValid() || !m_renderPending)
384 return;
385
387 if (!cb)
388 return;
389
390 m_renderPending = false;
391 m_renderer->render(cb);
392
395}
396
405
412
417{
418 // Changing to an empty size should not involve destroying and then later
419 // recreating the node, because we do not know how expensive the user's
420 // renderer setup is. Rather, keep the node if it already exist, and clamp
421 // all accesses to width and height. Hence the unusual !oldNode condition here.
422 if (!oldNode && (width() <= 0 || height() <= 0))
423 return nullptr;
424
425 Q_D(QQuickRhiItem);
426 QQuickRhiItemNode *n = static_cast<QQuickRhiItemNode *>(oldNode);
427 if (!n) {
428 if (!d->node)
429 d->node = new QQuickRhiItemNode(this);
430 if (!d->node->hasRenderer()) {
432 if (r) {
433 r->node = d->node;
434 d->node->setRenderer(r);
435 } else {
436 qWarning("No QQuickRhiItemRenderer was created; the item will not render");
437 delete d->node;
438 d->node = nullptr;
439 return nullptr;
440 }
441 }
442 n = d->node;
443 }
444
445 n->sync();
446
447 if (!n->isValid()) {
448 delete n;
449 d->node = nullptr;
450 return nullptr;
451 }
452
453 if (window()->rhi()->isYUpInFramebuffer()) {
454 n->setTextureCoordinatesTransform(d->mirrorVertically
457 } else {
458 n->setTextureCoordinatesTransform(d->mirrorVertically
461 }
462 n->setFiltering(d->smooth ? QSGTexture::Linear : QSGTexture::Nearest);
463 n->setRect(0, 0, qMax<int>(0, width()), qMax<int>(0, height()));
464
465 n->scheduleUpdate();
466
467 return n;
468}
469
474{
475 return QQuickItem::event(e);
476}
477
481void QQuickRhiItem::geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry)
482{
483 QQuickItem::geometryChange(newGeometry, oldGeometry);
484 if (newGeometry.size() != oldGeometry.size())
485 update();
486}
487
492{
493 // called on the gui thread if the item is removed from scene
494
495 Q_D(QQuickRhiItem);
496 d->node = nullptr;
497}
498
499void QQuickRhiItem::invalidateSceneGraph()
500{
501 // called on the render thread when the scenegraph is invalidated
502
503 Q_D(QQuickRhiItem);
504 d->node = nullptr;
505}
506
511{
512 return true;
513}
514
519{
520 if (QQuickItem::isTextureProvider()) // e.g. if Item::layer::enabled == true
522
523 Q_D(const QQuickRhiItem);
524 if (!d->node) // create a node to have a provider, the texture will be null but that's ok
525 d->node = new QQuickRhiItemNode(const_cast<QQuickRhiItem *>(this));
526
527 return d->node;
528}
529
566{
567 Q_D(const QQuickRhiItem);
568 return d->samples;
569}
570
572{
573 Q_D(QQuickRhiItem);
574 if (d->samples == samples)
575 return;
576
577 d->samples = samples;
579 update();
580}
581
603{
604 Q_D(const QQuickRhiItem);
605 return d->itemTextureFormat;
606}
607
609{
610 Q_D(QQuickRhiItem);
611 if (d->itemTextureFormat == format)
612 return;
613
614 d->itemTextureFormat = format;
615 switch (format) {
617 d->rhiTextureFormat = QRhiTexture::RGBA8;
618 break;
620 d->rhiTextureFormat = QRhiTexture::RGBA16F;
621 break;
623 d->rhiTextureFormat = QRhiTexture::RGBA32F;
624 break;
626 d->rhiTextureFormat = QRhiTexture::RGB10A2;
627 break;
628 }
630 update();
631}
632
641{
642 Q_D(const QQuickRhiItem);
643 return d->autoRenderTarget;
644}
645
659{
660 Q_D(QQuickRhiItem);
661 if (d->autoRenderTarget == enabled)
662 return;
663
664 d->autoRenderTarget = enabled;
666 update();
667}
668
680{
681 Q_D(const QQuickRhiItem);
682 return d->mirrorVertically;
683}
684
686{
687 Q_D(QQuickRhiItem);
688 if (d->mirrorVertically == enable)
689 return;
690
691 d->mirrorVertically = enable;
693 update();
694}
695
716{
717 Q_D(const QQuickRhiItem);
718 return d->fixedTextureWidth;
719}
720
722{
723 Q_D(QQuickRhiItem);
724 if (d->fixedTextureWidth == width)
725 return;
726
727 d->fixedTextureWidth = width;
729 update();
730}
731
752{
753 Q_D(const QQuickRhiItem);
754 return d->fixedTextureHeight;
755}
756
758{
759 Q_D(QQuickRhiItem);
760 if (d->fixedTextureHeight == height)
761 return;
762
763 d->fixedTextureHeight = height;
765 update();
766}
767
790{
791 Q_D(const QQuickRhiItem);
792 return d->effectiveTextureSize;
793}
794
823{
824 Q_D(const QQuickRhiItem);
825 return d->blend;
826}
827
829{
830 Q_D(QQuickRhiItem);
831 if (d->blend == enable)
832 return;
833
834 d->blend = enable;
836 update();
837}
838
850
873
886{
887 if (node)
888 node->scheduleUpdate();
889}
890
897{
898 return node ? node->m_rhi : nullptr;
899}
900
922{
923 return node ? node->m_colorTexture : nullptr;
924}
925
964{
965 return node ? node->m_msaaColorBuffer.get() : nullptr;
966}
967
987{
988 return node ? node->m_resolveTexture : nullptr;
989}
990
1004{
1005 return node ? node->m_depthStencilBuffer.get() : nullptr;
1006}
1007
1037{
1038 return node ? node->m_renderTarget.get() : nullptr;
1039}
1040
\inmodule QtCore
Definition qcoreevent.h:45
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2960
The QQuickItem class provides the most basic of all visual items in \l {Qt Quick}.
Definition qquickitem.h:63
bool event(QEvent *) override
\reimp
void setFlag(Flag flag, bool enabled=true)
Enables the specified flag for this item if enabled is true; if enabled is false, the flag is disable...
virtual void geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry)
virtual QSGTextureProvider * textureProvider() const
Returns the texture provider for an item.
QQuickWindow * window() const
Returns the window in which this item is rendered.
qreal width
This property holds the width of this item.
Definition qquickitem.h:75
qreal height
This property holds the height of this item.
Definition qquickitem.h:76
bool enabled
\qmlproperty bool QtQuick::Item::enabled
Definition qquickitem.h:79
void update()
Schedules a call to updatePaintNode() for this item.
virtual bool isTextureProvider() const
Returns true if this item is a texture provider.
QRhiTexture * m_colorTexture
QQuickRhiItem * m_item
QQuickRhiItemNode(QQuickRhiItem *item)
QRhiCommandBuffer * queryCommandBuffer()
std::unique_ptr< QRhiTextureRenderTarget > m_renderTarget
std::unique_ptr< QRhiRenderPassDescriptor > m_renderPassDescriptor
std::unique_ptr< QQuickRhiItemRenderer > m_renderer
QQuickWindow * m_window
std::unique_ptr< QRhiRenderBuffer > m_depthStencilBuffer
std::unique_ptr< QSGTexture > m_sgTexture
bool isValid() const
QSGTexture * texture() const override
Returns a pointer to the texture object.
std::unique_ptr< QRhiRenderBuffer > m_msaaColorBuffer
QRhiTexture * m_resolveTexture
\inmodule QtQuick
QRhiTexture * colorTexture() const
void update()
Call this function when the content of the offscreen color buffer should be updated.
QRhiRenderTarget * renderTarget() const
QRhiRenderBuffer * msaaColorBuffer() const
virtual ~QQuickRhiItemRenderer()
The Renderer is automatically deleted when the scene graph resources for the QQuickRhiItem item are c...
QRhiTexture * resolveTexture() const
QRhiRenderBuffer * depthStencilBuffer() const
QQuickRhiItemRenderer()
Constructs a new renderer.
\inmodule QtQuick
void setSampleCount(int samples)
int fixedColorBufferHeight
The fixed height, in pixels, of the item's associated texture.
QSGNode * updatePaintNode(QSGNode *, UpdatePaintNodeData *) override
void autoRenderTargetChanged()
void colorBufferFormatChanged()
QQuickRhiItem(QQuickItem *parent=nullptr)
Constructs a new QQuickRhiItem with the given parent.
bool alphaBlending
Controls if blending is always enabled when drawing the quad textured with the content generated by t...
void geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) override
\reimp
void alphaBlendingChanged()
void setAlphaBlending(bool enable)
void effectiveColorBufferSizeChanged()
bool isMirrorVerticallyEnabled() const
void setMirrorVertically(bool enable)
int fixedColorBufferWidth
The fixed width, in pixels, of the item's associated texture or renderbuffer.
bool event(QEvent *) override
\reimp
void fixedColorBufferHeightChanged()
QSize effectiveColorBufferSize
This property exposes the size, in pixels, of the underlying color buffer (the QRhiTexture or QRhiRen...
void releaseResources() override
\reimp
friend class QQuickRhiItemNode
void setFixedColorBufferHeight(int height)
QSGTextureProvider * textureProvider() const override
\reimp
void mirrorVerticallyChanged()
void setFixedColorBufferWidth(int width)
TextureFormat colorBufferFormat
This property controls the texture format for the texture used as the color buffer.
void setColorBufferFormat(TextureFormat format)
~QQuickRhiItem() override
Destructor.
void sampleCountChanged()
bool isTextureProvider() const override
\reimp
void setAutoRenderTarget(bool enabled)
Controls if a depth-stencil QRhiRenderBuffer and a QRhiTextureRenderTarget is created and maintained ...
bool isAutoRenderTargetEnabled() const
void fixedColorBufferWidthChanged()
virtual QQuickRhiItemRenderer * createRenderer()=0
Reimplement this function to create and return a new instance of a QQuickRhiItemRenderer subclass.
int sampleCount
This property controls for sample count for multisample antialiasing.
void beforeRendering()
\qmlsignal QtQuick::Window::afterSynchronizing()
\inmodule QtCore\reentrant
Definition qrect.h:484
constexpr QSizeF size() const noexcept
Returns the size of the rectangle.
Definition qrect.h:735
\inmodule QtGui
Definition qrhi.h:576
\inmodule QtGui
Definition qrhi.h:1651
\inmodule QtGui
Definition qrhi.h:1094
\inmodule QtGui
Definition qrhi.h:1158
void deleteLater()
When called without a frame being recorded, this function is equivalent to deleting the object.
Definition qrhi.cpp:3545
\inmodule QtGui
Definition qrhi.h:1549
virtual QRhiCommandBuffer * currentFrameCommandBuffer()=0
\inmodule QtGui
Definition qrhi.h:895
Format format() const
Definition qrhi.h:972
@ UsedAsTransferSource
Definition qrhi.h:902
@ RenderTarget
Definition qrhi.h:898
int sampleCount() const
Definition qrhi.h:995
virtual bool create()=0
Creates the corresponding native graphics resources.
@ RGBA32F
Definition qrhi.h:926
@ RGBA16F
Definition qrhi.h:925
@ RGB10A2
Definition qrhi.h:930
QSize pixelSize() const
Definition qrhi.h:975
void setPixelSize(const QSize &sz)
Sets the texture size, specified in pixels, to sz.
Definition qrhi.h:976
\inmodule QtGuiPrivate \inheaderfile rhi/qrhi.h
Definition qrhi.h:1804
bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags={}) const
Definition qrhi.cpp:10102
int resourceLimit(ResourceLimit limit) const
Definition qrhi.cpp:10121
bool isFeatureSupported(QRhi::Feature feature) const
Definition qrhi.cpp:10110
QRhiRenderBuffer * newRenderBuffer(QRhiRenderBuffer::Type type, const QSize &pixelSize, int sampleCount=1, QRhiRenderBuffer::Flags flags={}, QRhiTexture::Format backingFormatHint=QRhiTexture::UnknownFormat)
Definition qrhi.cpp:10535
QRhiTextureRenderTarget * newTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc, QRhiTextureRenderTarget::Flags flags={})
Definition qrhi.cpp:10682
@ TextureSizeMin
Definition qrhi.h:1887
@ TextureSizeMax
Definition qrhi.h:1888
QRhiTexture * newTexture(QRhiTexture::Format format, const QSize &pixelSize, int sampleCount=1, QRhiTexture::Flags flags={})
Definition qrhi.cpp:10562
@ MultisampleRenderBuffer
Definition qrhi.h:1833
\group qtquick-scenegraph-nodes \title Qt Quick Scene Graph Node classes
Definition qsgnode.h:37
@ DirtyMaterial
Definition qsgnode.h:75
void markDirty(DirtyState bits)
Notifies all connected renderers that the node has dirty bits.
Definition qsgnode.cpp:624
An interface providing access to some of the graphics API specific internals of the scenegraph.
void setTexture(QSGTexture *texture)
Sets the texture of this texture node to texture.
The QSGTextureProvider class encapsulates texture based entities in QML.
void textureChanged()
This signal is emitted when the texture changes.
\inmodule QtQuick
Definition qsgtexture.h:20
\inmodule QtCore
Definition qsize.h:25
constexpr int height() const noexcept
Returns the height.
Definition qsize.h:133
constexpr int width() const noexcept
Returns the width.
Definition qsize.h:130
constexpr void setWidth(int w) noexcept
Sets the width to the given width.
Definition qsize.h:136
constexpr bool isEmpty() const noexcept
Returns true if either of the width and height is less than or equal to 0; otherwise returns false.
Definition qsize.h:124
constexpr void setHeight(int h) noexcept
Sets the height to the given height.
Definition qsize.h:139
void screenChanged(QScreen *screen)
This signal is emitted when a window's screen changes, either by being set explicitly with setScreen(...
Combined button and popup list for selecting options.
@ DirectConnection
#define qWarning
Definition qlogging.h:166
constexpr const T & qMin(const T &a, const T &b)
Definition qminmax.h:40
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
GLsizei samples
GLint GLsizei GLsizei height
GLboolean r
[2]
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLint GLsizei width
GLboolean enable
GLfloat n
GLint GLsizei GLsizei GLenum format
SSL_CTX int(* cb)(SSL *ssl, unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg)
#define emit
QGraphicsItem * item