diff options
Diffstat (limited to 'src/quick/items/qquickrendercontrol.cpp')
-rw-r--r-- | src/quick/items/qquickrendercontrol.cpp | 118 |
1 files changed, 110 insertions, 8 deletions
diff --git a/src/quick/items/qquickrendercontrol.cpp b/src/quick/items/qquickrendercontrol.cpp index 0575c5e5eb..3a92507141 100644 --- a/src/quick/items/qquickrendercontrol.cpp +++ b/src/quick/items/qquickrendercontrol.cpp @@ -26,7 +26,7 @@ #include <QtCore/private/qobject_p.h> #include <QtQuick/private/qquickwindow_p.h> -#include <QtGui/private/qrhi_p.h> +#include <rhi/qrhi.h> QT_BEGIN_NAMESPACE @@ -60,7 +60,7 @@ QT_BEGIN_NAMESPACE Management of the graphics devices, contexts, image and texture objects is up to the application. The device or context that will be used by Qt Quick must - be created before calling initialize(). The creation of the the texture object + be created before calling initialize(). The creation of the texture object can be deferred, see below. Qt 5.4 introduces the ability for QOpenGLContext to adopt existing native contexts. Together with QQuickRenderControl this makes it possible to create a QOpenGLContext that shares with an external @@ -281,6 +281,17 @@ int QQuickRenderControl::samples() const \note This function does not need to be, and must not be, called when using the \c software adaptation of Qt Quick. + With the default Qt Quick adaptation this function creates a new \l QRhi + object, similarly to what would happen with an on-screen QQuickWindow when + QQuickRenderControl was not used. To make this new QRhi object adopt some + existing device or context resource (e.g. use an existing QOpenGLContext + instead of creating a new one), use QQuickWindow::setGraphicsDevice() as + mentioned above. When the application wants to make the Qt Quick rendering + use an already existing \l QRhi object, that is possible as well via + \l QQuickGraphicsDevice::fromRhi(). When such a QQuickGraphicsDevice, + referencing an already existing QRhi, is set, there will be no new, + dedicated \l QRhi object created in initialize(). + \since 6.0 \sa QQuickRenderTarget, QQuickGraphicsDevice, QQuickGraphicsConfiguration::preferredInstanceExtensions() @@ -357,7 +368,8 @@ bool QQuickRenderControl::sync() return false; } if (!d->cb) { - qWarning("QQuickRenderControl cannot be used with QRhi when no QRhiCommandBuffer is provided"); + qWarning("QQuickRenderControl cannot be used with QRhi when no QRhiCommandBuffer is provided " + "(perhaps beginFrame() was not called or it was unsuccessful?)"); return false; } cd->setCustomCommandBuffer(d->cb); @@ -549,6 +561,16 @@ bool QQuickRenderControlPrivate::isRenderWindowFor(QQuickWindow *quickWin, const return false; } +bool QQuickRenderControlPrivate::isRenderWindow(const QWindow *w) +{ + Q_Q(QQuickRenderControl); + + if (window && w) + return q->renderWindowFor(window, nullptr) == w; + + return false; +} + /*! \return the QQuickWindow this QQuickRenderControl is associated with. @@ -565,6 +587,53 @@ QQuickWindow *QQuickRenderControl::window() const } /*! + \return the QRhi this QQuickRenderControl is associated with. + + \note The QRhi exists only when initialize() has successfully completed. + Before that the return value is null. + + \note This function is not applicable and returns null when using the + \c software adaptation of Qt Quick. + + \since 6.6 + + \sa commandBuffer(), beginFrame(), endFrame() + */ +QRhi *QQuickRenderControl::rhi() const +{ + Q_D(const QQuickRenderControl); + return d->rhi; +} + +/*! + \return the current command buffer. + + Once beginFrame() is called, a QRhiCommandBuffer is set up automatically. + That is the command buffer Qt Quick scenegraph uses, but in some cases + applications may also want to query it, for example to issue resource + updates (for example, a texture readback). + + The returned command buffer reference should only be used between + beginFrame() and endFrame(). There are specific exceptions, for example + calling + \l{QRhiCommandBuffer::lastCompletedGpuTime()}{lastCompletedGpuTime()} on + the command buffer right after endFrame(), but before the next + beginFrame(), is valid. + + \note This function is not applicable and returns null when using the + \c software adaptation of Qt Quick. + + \since 6.6 + + \sa rhi(), beginFrame(), endFrame() + */ +QRhiCommandBuffer *QQuickRenderControl::commandBuffer() const +{ + Q_D(const QQuickRenderControl); + return d->cb; +} + +/*! Specifies the start of a graphics frame. Calls to sync() or render() must be enclosed by calls to beginFrame() and endFrame(). @@ -574,11 +643,11 @@ QQuickWindow *QQuickRenderControl::window() const to the user of QQuickRenderControl to specify these points. A typical update step, including initialization of rendering into an - existing texture, could like like the following. The example snippet + existing texture, could look like the following. The example snippet assumes Direct3D 11 but the same concepts apply other graphics APIs as well. - \badcode + \code if (!m_quickInitialized) { m_quickWindow->setGraphicsDevice(QQuickGraphicsDevice::fromDeviceAndContext(m_engine->device(), m_engine->context())); @@ -600,6 +669,15 @@ QQuickWindow *QQuickRenderControl::window() const m_renderControl->endFrame(); // Qt Quick's rendering commands are submitted to the device context here \endcode + \note This function does not need to be, and must not be, called when using + the \c software adaptation of Qt Quick. + + \note Internally beginFrame() and endFrame() invoke + \l{QRhi::}{beginOffscreenFrame()} and \l{QRhi::}{endOffscreenFrame()}, + respectively. This implies that there must not be a frame (neither + offscreen, nor swapchain-based) being recorded on the QRhi when + this function is called. + \since 6.0 \sa endFrame(), initialize(), sync(), render(), QQuickGraphicsDevice, QQuickRenderTarget @@ -607,8 +685,18 @@ QQuickWindow *QQuickRenderControl::window() const void QQuickRenderControl::beginFrame() { Q_D(QQuickRenderControl); - if (!d->rhi || d->rhi->isRecordingFrame()) + if (!d->rhi) { + qWarning("QQuickRenderControl: No QRhi in beginFrame()"); + return; + } + if (d->frameStatus == QQuickRenderControlPrivate::RecordingFrame) { + qWarning("QQuickRenderControl: beginFrame() must be followed by a call to endFrame() before calling beginFrame() again"); return; + } + if (d->rhi->isRecordingFrame()) { + qWarning("QQuickRenderControl: Attempted to beginFrame() while the QRhi is already recording a frame"); + return; + } emit d->window->beforeFrameBegin(); @@ -639,6 +727,9 @@ void QQuickRenderControl::beginFrame() scenegraph are submitted to the context or command queue, whichever is applicable. + \note This function does not need to be, and must not be, called when using + the \c software adaptation of Qt Quick. + \since 6.0 \sa beginFrame(), initialize(), sync(), render(), QQuickGraphicsDevice, QQuickRenderTarget @@ -646,11 +737,22 @@ void QQuickRenderControl::beginFrame() void QQuickRenderControl::endFrame() { Q_D(QQuickRenderControl); - if (!d->rhi || !d->rhi->isRecordingFrame()) + if (!d->rhi) { + qWarning("QQuickRenderControl: No QRhi in endFrame()"); return; + } + if (d->frameStatus != QQuickRenderControlPrivate::RecordingFrame) { + qWarning("QQuickRenderControl: endFrame() must only be called after a successful beginFrame()"); + return; + } + if (!d->rhi->isRecordingFrame()) { + qWarning("QQuickRenderControl: Attempted to endFrame() while the QRhi is not recording a frame"); + return; + } d->rhi->endOffscreenFrame(); - d->cb = nullptr; + // do not null out d->cb; this allows calling lastCompletedGpuTime() for example + d->frameStatus = QQuickRenderControlPrivate::NotRecordingFrame; emit d->window->afterFrameEnd(); |