aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@qt.io>2020-04-29 17:11:31 +0200
committerLaszlo Agocs <laszlo.agocs@qt.io>2020-04-30 18:56:19 +0200
commitdb7bfdc06bf68d5e4a78f293033024a60fb92464 (patch)
treeb55374fea993ca0c1b8a0e3fefe1e63c41a230b4
parent93e0e671e9eeef679024fe3e2e4534f2f10533cb (diff)
Add beforeFrameBegin() and afterFrameEnd() to QQuickWindow
New additions to the QQuickWindow signal family. Out of the three stages of the (modern) frame generation process, only two are covered by the existing beforeRendering, beforeRenderPassRecording - afterRenderPassRecording, afterRendering pairs. With the new ones, the rendering of a simple Qt Quick scene looks like the following: emit beforeFrameBegin QRhi::beginFrame() emit beforeRendering ... (additional render passes targeting textures when layers or View3D are involved) QRhi::beginPass() emit beforeRenderPassRecording ... emit afterRenderPassRecording QRhi::endPass() emit afterRendering QRhi::endFrame() emit afterFrameEnd This fits very well the revised QQuickRenderControl API, which has explicit beginFrame-endFrame points as well. So now we can make both QQuickRenderControl and the render loops to emit these signals at the appropriate points. Task-number: QTBUG-83883 Change-Id: Ib385b29393f3b39b0700432d14ea3976cf337fa0 Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io> Reviewed-by: Andy Nichols <andy.nichols@qt.io>
-rw-r--r--src/quick/items/qquickrendercontrol.cpp4
-rw-r--r--src/quick/items/qquickwindow.cpp52
-rw-r--r--src/quick/items/qquickwindow.h3
-rw-r--r--src/quick/scenegraph/qsgrenderloop.cpp4
-rw-r--r--src/quick/scenegraph/qsgthreadedrenderloop.cpp4
5 files changed, 67 insertions, 0 deletions
diff --git a/src/quick/items/qquickrendercontrol.cpp b/src/quick/items/qquickrendercontrol.cpp
index b14a3f35f7..eba3ef99a7 100644
--- a/src/quick/items/qquickrendercontrol.cpp
+++ b/src/quick/items/qquickrendercontrol.cpp
@@ -660,6 +660,8 @@ void QQuickRenderControl::beginFrame()
if (!d->rhi || d->rhi->isRecordingFrame())
return;
+ emit d->window->beforeFrameBegin();
+
d->rhi->beginOffscreenFrame(&d->cb, QRhi::ExternalContentsInPass); // must specify ExternalContents since we do not know in advance
}
@@ -683,6 +685,8 @@ void QQuickRenderControl::endFrame()
d->rhi->endOffscreenFrame();
d->cb = nullptr;
+
+ emit d->window->afterFrameEnd();
}
bool QQuickRenderControlPrivate::initRhi()
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index 445eea7fa6..755e0ddf69 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -4620,6 +4620,58 @@ QQmlIncubationController *QQuickWindow::incubationController() const
*/
/*!
+ \fn void QQuickWindow::beforeFrameBegin()
+
+ This signal is emitted before the scene graph starts preparing the frame.
+ This precedes signals like beforeSynchronizing() or beforeRendering(). It is
+ the earliest signal that is emitted by the scene graph rendering thread
+ when starting to prepare a new frame.
+
+ This signal is relevant for lower level graphics frameworks that need to
+ execute certain operations, such as resource cleanup, at a stage where Qt
+ Quick has not initiated the recording of a new frame via the underlying
+ rendering hardware interface APIs.
+
+ \warning This signal is emitted from the scene graph rendering thread. If your
+ slot function needs to finish before execution continues, you must make sure that
+ the connection is direct (see Qt::ConnectionType).
+
+ \since 6.0
+
+ \sa afterFrameEnd()
+*/
+
+/*!
+ \qmlsignal QtQuick.Window::Window::beforeFrameBegin()
+ \internal
+*/
+
+/*!
+ \fn void QQuickWindow::afterFrameEnd()
+
+ This signal is emitted when the scene graph has submitted a frame. This is
+ emitted after all other related signals, such as afterRendering(). It is
+ the last signal that is emitted by the scene graph rendering thread when
+ rendering a frame.
+
+ \note Unlike frameSwapped(), this signal is guaranteed to be emitted also
+ when the Qt Quick output is redirected via QQuickRenderControl.
+
+ \warning This signal is emitted from the scene graph rendering thread. If your
+ slot function needs to finish before execution continues, you must make sure that
+ the connection is direct (see Qt::ConnectionType).
+
+ \since 6.0
+
+ \sa beforeFrameBegin()
+*/
+
+/*!
+ \qmlsignal QtQuick.Window::Window::afterFrameEnd()
+ \internal
+*/
+
+/*!
\qmlsignal QtQuick.Window::Window::afterRenderPassRecording()
\internal
\since 5.14
diff --git a/src/quick/items/qquickwindow.h b/src/quick/items/qquickwindow.h
index a2278a8df0..deb57376ab 100644
--- a/src/quick/items/qquickwindow.h
+++ b/src/quick/items/qquickwindow.h
@@ -236,6 +236,9 @@ Q_SIGNALS:
Q_REVISION(6, 0) void paletteChanged();
Q_REVISION(6, 0) void paletteCreated();
+ Q_REVISION(6, 0) void beforeFrameBegin();
+ Q_REVISION(6, 0) void afterFrameEnd();
+
public Q_SLOTS:
void update();
void releaseResources();
diff --git a/src/quick/scenegraph/qsgrenderloop.cpp b/src/quick/scenegraph/qsgrenderloop.cpp
index a49f4a2263..cb9f7f331f 100644
--- a/src/quick/scenegraph/qsgrenderloop.cpp
+++ b/src/quick/scenegraph/qsgrenderloop.cpp
@@ -704,6 +704,8 @@ void QSGGuiThreadRenderLoop::renderWindow(QQuickWindow *window)
emit window->afterAnimating();
+ emit window->beforeFrameBegin();
+
// Begin the frame before syncing -> sync is where we may invoke
// updatePaintNode() on the items and they may want to do resource updates.
// Also relevant for applications that connect to the before/afterSynchronizing
@@ -799,6 +801,8 @@ void QSGGuiThreadRenderLoop::renderWindow(QQuickWindow *window)
if (needsPresent)
cd->fireFrameSwapped();
+ emit window->afterFrameEnd();
+
qint64 swapTime = 0;
if (profileFrames)
swapTime = renderTimer.nsecsElapsed();
diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp
index 5f6a7597ab..2fc2ef43a2 100644
--- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp
+++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp
@@ -713,6 +713,8 @@ void QSGRenderThread::syncAndRender(QImage *grabImage)
if (!grabRequested)
pendingUpdate = 0;
+ emit window->beforeFrameBegin();
+
QQuickWindowPrivate *cd = QQuickWindowPrivate::get(window);
// Begin the frame before syncing -> sync is where we may invoke
// updatePaintNode() on the items and they may want to do resource updates.
@@ -883,6 +885,8 @@ void QSGRenderThread::syncAndRender(QImage *grabImage)
qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "- rendering done");
+ emit window->afterFrameEnd();
+
// Though it would be more correct to put this block directly after
// fireFrameSwapped in the if (current) branch above, we don't do
// that to avoid blocking the GUI thread in the case where it