Commit 6fd60861 authored by David Edmundson's avatar David Edmundson
Browse files

Update QtQuick views at the start of the frame

Right now we update QtQuick views after a composition has rendered so
that we'll have them ready for our next frame.

One of my machines (With X11 + nvidia) was quite stuttery, profiling
shows we spend a huge amount of time with the CPU blocked waiting for
the vblank from the previous main compositing to finish swapping before
we could start processing the QtQuick rendering. Time when the CPU is
blocked is wasted time.

This patch does mean kwin's compositing cycle lasts longer but a recent
patch changes the rendering policy when we start a fullscreen effect anyway so
hopefully that should still give us enough time to render that first frame in time.


(cherry picked from commit 63bf8112)
parent feb77d90
Pipeline #211446 passed with stage
in 20 minutes and 26 seconds
......@@ -32,7 +32,6 @@ public:
QPointer<QuickSceneView> mouseImplicitGrab;
bool running = false;
QScopedPointer<QWindow> dummyWindow;
EffectScreen *paintedScreen = nullptr;
};
bool QuickSceneEffectPrivate::isItemOnScreen(QQuickItem *item, EffectScreen *screen)
......@@ -234,44 +233,42 @@ void QuickSceneEffect::activateView(QuickSceneView *view)
}
}
void QuickSceneEffect::paintScreen(int mask, const QRegion &region, ScreenPaintData &data)
// Screen views are repainted just before kwin performs its compositing cycle to avoid stalling for vblank
void QuickSceneEffect::prePaintScreen(ScreenPrePaintData &data, std::chrono::milliseconds presentTime)
{
Q_UNUSED(mask)
Q_UNUSED(region)
d->paintedScreen = data.screen();
Q_UNUSED(presentTime)
if (effects->waylandDisplay()) {
QuickSceneView *screenView = d->views.value(data.screen());
if (screenView) {
effects->renderOffscreenQuickView(screenView);
QuickSceneView *screenView = d->views.value(data.screen);
if (screenView && screenView->isDirty()) {
screenView->update();
screenView->resetDirty();
}
} else {
for (QuickSceneView *screenView : qAsConst(d->views)) {
effects->renderOffscreenQuickView(screenView);
if (screenView->isDirty()) {
screenView->update();
screenView->resetDirty();
}
}
}
}
void QuickSceneEffect::postPaintScreen()
void QuickSceneEffect::paintScreen(int mask, const QRegion &region, ScreenPaintData &data)
{
// Screen views are repainted after kwin performs its compositing cycle. Another alternative
// is to update the views after receiving a vblank.
Q_UNUSED(mask)
Q_UNUSED(region)
if (effects->waylandDisplay()) {
QuickSceneView *screenView = d->views.value(d->paintedScreen);
if (screenView && screenView->isDirty()) {
QMetaObject::invokeMethod(screenView, &QuickSceneView::update, Qt::QueuedConnection);
screenView->resetDirty();
QuickSceneView *screenView = d->views.value(data.screen());
if (screenView) {
effects->renderOffscreenQuickView(screenView);
}
} else {
for (QuickSceneView *screenView : qAsConst(d->views)) {
if (screenView->isDirty()) {
QMetaObject::invokeMethod(screenView, &QuickSceneView::update, Qt::QueuedConnection);
screenView->resetDirty();
}
effects->renderOffscreenQuickView(screenView);
}
}
effects->postPaintScreen();
}
bool QuickSceneEffect::isActive() const
......
......@@ -115,8 +115,8 @@ public:
bool eventFilter(QObject *watched, QEvent *event) override;
void prePaintScreen(ScreenPrePaintData &data, std::chrono::milliseconds presentTime) override;
void paintScreen(int mask, const QRegion &region, ScreenPaintData &data) override;
void postPaintScreen() override;
bool isActive() const override;
void windowInputMouseEvent(QEvent *event) override;
......
......@@ -293,6 +293,9 @@ void Scene::prePaint(Output *output)
prePaintData.mask = 0;
prePaintData.screen = EffectScreenImpl::get(painted_screen);
effects->makeOpenGLContextCurrent();
Q_EMIT preFrameRender();
effects->prePaintScreen(prePaintData, m_expectedPresentTimestamp);
m_paintContext.damage = prePaintData.paint;
m_paintContext.mask = prePaintData.mask;
......
......@@ -180,6 +180,7 @@ public:
virtual void render(Item *item, int mask, const QRegion &region, const WindowPaintData &data) = 0;
Q_SIGNALS:
void preFrameRender();
void frameRendered();
protected:
......
......@@ -166,7 +166,7 @@ void WindowThumbnailItem::updateFrameRenderingConnection()
}
if (Compositor::self()->backend()->compositingType() == OpenGLCompositing) {
m_frameRenderingConnection = connect(Compositor::self()->scene(), &Scene::frameRendered, this, &WindowThumbnailItem::updateOffscreenTexture);
m_frameRenderingConnection = connect(Compositor::self()->scene(), &Scene::preFrameRender, this, &WindowThumbnailItem::updateOffscreenTexture);
}
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment