Commit 63bf8112 authored by David Edmundson's avatar David Edmundson Committed by ivan tkachenko
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.
parent 4384f9c5
Pipeline #210336 failed with stage
in 28 minutes and 40 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;
......
......@@ -286,6 +286,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;
......
......@@ -178,6 +178,7 @@ public:
virtual void render(Item *item, int mask, const QRegion &region, const WindowPaintData &data) = 0;
Q_SIGNALS:
void preFrameRender();
void frameRendered();
protected:
......
......@@ -165,7 +165,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