aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/items/qquickrendercontrol.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/quick/items/qquickrendercontrol.cpp')
-rw-r--r--src/quick/items/qquickrendercontrol.cpp118
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();