Move all dirty region scene repaint scheduling to Scene

The Compositor contains nothing that can potentially get dirty and need
repainting.

As is, the advantages of this move aren't really noticeable, but it
makes sense with multiple scenes.

Backend parts are far from ideal, they can be improved later on as we
progress with the scene redesign.
This commit is contained in:
Vlad Zahorodnii 2021-11-09 12:36:24 +02:00
parent 158fb016a4
commit 6d0cca5c7f
21 changed files with 83 additions and 79 deletions

View file

@ -56,7 +56,7 @@ void BufferSizeChangeTest::testShmBufferSizeChange()
// add a first repaint
QSignalSpy frameRenderedSpy(Compositor::self()->scene(), &Scene::frameRendered);
QVERIFY(frameRenderedSpy.isValid());
Compositor::self()->addRepaintFull();
Compositor::self()->scene()->addRepaintFull();
QVERIFY(frameRenderedSpy.wait());
// now change buffer size
@ -65,7 +65,7 @@ void BufferSizeChangeTest::testShmBufferSizeChange()
QSignalSpy damagedSpy(client, &AbstractClient::damaged);
QVERIFY(damagedSpy.isValid());
QVERIFY(damagedSpy.wait());
KWin::Compositor::self()->addRepaintFull();
KWin::Compositor::self()->scene()->addRepaintFull();
QVERIFY(frameRenderedSpy.wait());
}
@ -93,7 +93,7 @@ void BufferSizeChangeTest::testShmBufferSizeChangeOnSubSurface()
// add a first repaint
QSignalSpy frameRenderedSpy(Compositor::self()->scene(), &Scene::frameRendered);
QVERIFY(frameRenderedSpy.isValid());
Compositor::self()->addRepaintFull();
Compositor::self()->scene()->addRepaintFull();
QVERIFY(frameRenderedSpy.wait());
// change buffer size of sub surface
@ -105,7 +105,7 @@ void BufferSizeChangeTest::testShmBufferSizeChangeOnSubSurface()
QVERIFY(damagedParentSpy.wait());
// add a second repaint
KWin::Compositor::self()->addRepaintFull();
KWin::Compositor::self()->scene()->addRepaintFull();
QVERIFY(frameRenderedSpy.wait());
}

View file

@ -13,6 +13,7 @@
#include "cursor.h"
#include "platform.h"
#include "renderbackend.h"
#include "scene.h"
#include "wayland_server.h"
#include <KConfigGroup>
@ -80,7 +81,7 @@ void GenericSceneOpenGLTest::testRestart()
QCOMPARE(kwinApp()->platform()->selectedCompositor(), KWin::OpenGLCompositing);
// trigger a repaint
KWin::Compositor::self()->addRepaintFull();
KWin::Compositor::self()->scene()->addRepaintFull();
// and wait 100 msec to ensure it's rendered
// TODO: introduce frameRendered signal in SceneOpenGL
QTest::qWait(100);

View file

@ -87,7 +87,7 @@ void SceneQPainterTest::initTestCase()
void SceneQPainterTest::testStartFrame()
{
// this test verifies that the initial rendering is correct
Compositor::self()->addRepaintFull();
Compositor::self()->scene()->addRepaintFull();
auto scene = Compositor::self()->scene();
QVERIFY(scene);
QCOMPARE(kwinApp()->platform()->selectedCompositor(), QPainterCompositing);
@ -261,7 +261,7 @@ void SceneQPainterTest::testCompositorRestart()
QVERIFY(scene);
// this should directly trigger a frame
KWin::Compositor::self()->addRepaintFull();
KWin::Compositor::self()->scene()->addRepaintFull();
QSignalSpy frameRenderedSpy(scene, &Scene::frameRendered);
QVERIFY(frameRenderedSpy.isValid());
QVERIFY(frameRenderedSpy.wait());
@ -360,7 +360,7 @@ void SceneQPainterTest::testX11Window()
QVERIFY(scene);
// this should directly trigger a frame
KWin::Compositor::self()->addRepaintFull();
KWin::Compositor::self()->scene()->addRepaintFull();
QSignalSpy frameRenderedSpy(scene, &Scene::frameRendered);
QVERIFY(frameRenderedSpy.isValid());
QVERIFY(frameRenderedSpy.wait());

View file

@ -130,7 +130,7 @@ void XwaylandServerCrashTest::testCrash()
QCOMPARE(kwinApp()->x11ScreenNumber(), -1);
// Render a frame to ensure that the compositor doesn't crash.
Compositor::self()->addRepaintFull();
Compositor::self()->scene()->addRepaintFull();
QSignalSpy frameRenderedSpy(Compositor::self()->scene(), &Scene::frameRendered);
QVERIFY(frameRenderedSpy.wait());
}

View file

@ -106,7 +106,7 @@ void XwaylandServerRestartTest::testRestart()
QVERIFY(client->isDecorated());
// Render a frame to ensure that the compositor doesn't crash.
Compositor::self()->addRepaintFull();
Compositor::self()->scene()->addRepaintFull();
QSignalSpy frameRenderedSpy(Compositor::self()->scene(), &Scene::frameRendered);
QVERIFY(frameRenderedSpy.wait());

View file

@ -18,6 +18,7 @@
#include "logging.h"
#include "main.h"
#include "renderloop.h"
#include "scene.h"
#include "scene_qpainter_drm_backend.h"
#include "session.h"
#include "udev.h"
@ -147,8 +148,8 @@ void DrmBackend::reactivate()
output->renderLoop()->uninhibit();
}
if (Compositor *compositor = Compositor::self()) {
compositor->addRepaintFull();
if (Compositor::compositing()) {
Compositor::self()->scene()->addRepaintFull();
}
// While the session had been inactive, an output could have been added or
@ -712,8 +713,8 @@ bool DrmBackend::applyOutputChanges(const WaylandOutputConfig &config)
}
};
updateCursor();
if (auto compositor = Compositor::self()) {
compositor->addRepaintFull();
if (Compositor::compositing()) {
Compositor::self()->scene()->addRepaintFull();
}
return true;
}

View file

@ -19,6 +19,7 @@
#include "main.h"
#include "renderloop.h"
#include "renderloop_p.h"
#include "scene.h"
#include "screens.h"
#include "session.h"
#include "waylandoutputconfig.h"
@ -267,8 +268,8 @@ bool DrmOutput::setDrmDpmsMode(DpmsMode mode)
if (active) {
m_renderLoop->uninhibit();
m_gpu->platform()->checkOutputsAreOn();
if (Compositor *compositor = Compositor::self()) {
compositor->addRepaintFull();
if (Compositor::compositing()) {
Compositor::self()->scene()->addRepaintFull();
}
} else {
m_renderLoop->inhibit();

View file

@ -13,6 +13,7 @@
#include "main.h"
#include "platform.h"
#include "renderloop.h"
#include "scene.h"
#include "screens.h"
#include "session.h"
#include "vsyncmonitor.h"
@ -50,7 +51,7 @@ void FramebufferQPainterBackend::reactivate()
for (AbstractOutput *output : outputs) {
output->renderLoop()->uninhibit();
}
Compositor::self()->addRepaintFull();
Compositor::self()->scene()->addRepaintFull();
}
void FramebufferQPainterBackend::deactivate()

View file

@ -27,6 +27,7 @@
#include "cursor.h"
#include "input.h"
#include "main.h"
#include "scene.h"
#include "screens.h"
#include "pointer_input.h"
#include "wayland_server.h"
@ -200,7 +201,7 @@ void WaylandSubSurfaceCursor::move(const QPointF &globalPosition)
// place the sub-surface relative to the output it is on and factor in the hotspot
const auto relativePosition = globalPosition.toPoint() - Cursors::self()->currentCursor()->hotspot() - m_output->geometry().topLeft();
m_subSurface->setPosition(relativePosition);
Compositor::self()->addRepaintFull();
Compositor::self()->scene()->addRepaintFull();
}
WaylandInputDevice::WaylandInputDevice(KWayland::Client::Keyboard *keyboard, WaylandSeat *seat)
@ -859,7 +860,7 @@ WaylandOutput *WaylandBackend::createOutput(const QPoint &position, const QSize
connect(waylandOutput, &WaylandOutput::sizeChanged, this, [this, waylandOutput](const QSize &size) {
Q_UNUSED(size)
updateScreenSize(waylandOutput);
Compositor::self()->addRepaintFull();
Compositor::self()->scene()->addRepaintFull();
});
connect(waylandOutput, &WaylandOutput::frameRendered, this, [waylandOutput]() {
waylandOutput->resetRendered();

View file

@ -11,6 +11,7 @@
#include "kwinglobals.h"
#include "composite.h"
#include "scene.h"
#include "screens.h"
#include "utils.h"
#include "xcbutils.h"
@ -167,7 +168,7 @@ bool OverlayWindowX11::event(xcb_generic_event_t *event)
const auto *expose = reinterpret_cast<xcb_expose_event_t*>(event);
if (expose->window == rootWindow() // root window needs repainting
|| (m_window != XCB_WINDOW_NONE && expose->window == m_window)) { // overlay needs repainting
Compositor::self()->addRepaint(expose->x, expose->y, expose->width, expose->height);
Compositor::self()->scene()->addRepaint(expose->x, expose->y, expose->width, expose->height);
}
} else if (eventType == XCB_VISIBILITY_NOTIFY) {
const auto *visibility = reinterpret_cast<xcb_visibility_notify_event_t*>(event);
@ -177,8 +178,12 @@ bool OverlayWindowX11::event(xcb_generic_event_t *event)
auto compositor = Compositor::self();
if (!was_visible && m_visible) {
// hack for #154825
compositor->addRepaintFull();
QTimer::singleShot(2000, compositor, &Compositor::addRepaintFull);
compositor->scene()->addRepaintFull();
QTimer::singleShot(2000, compositor, [compositor]() {
if (compositor->compositing()) {
compositor->scene()->addRepaintFull();
}
});
}
compositor->scheduleRepaint();
}

View file

@ -353,6 +353,7 @@ void Compositor::startupWithWorkspace()
Workspace::self()->markXStackingOrderAsDirty();
Q_ASSERT(m_scene);
m_scene->initialize();
const Platform *platform = kwinApp()->platform();
if (platform->isPerScreenRenderingEnabled()) {
@ -373,7 +374,6 @@ void Compositor::startupWithWorkspace()
// Sets also the 'effects' pointer.
kwinApp()->platform()->createEffectsHandler(this, m_scene);
connect(Workspace::self(), &Workspace::deletedRemoved, m_scene, &Scene::removeToplevel);
connect(effects, &EffectsHandler::virtualScreenGeometryChanged, this, &Compositor::addRepaintFull);
for (X11Client *c : Workspace::self()->clientList()) {
c->setupCompositing();
@ -399,7 +399,7 @@ void Compositor::startupWithWorkspace()
}
// Render at least once.
addRepaintFull();
m_scene->addRepaintFull();
}
void Compositor::registerRenderLoop(RenderLoop *renderLoop, AbstractOutput *output)
@ -565,7 +565,6 @@ void Compositor::deleteUnusedSupportProperties()
void Compositor::configChanged()
{
reinitialize();
addRepaintFull();
}
void Compositor::reinitialize()
@ -582,28 +581,6 @@ void Compositor::reinitialize()
}
}
void Compositor::addRepaint(int x, int y, int width, int height)
{
addRepaint(QRegion(x, y, width, height));
}
void Compositor::addRepaint(const QRect &rect)
{
addRepaint(QRegion(rect));
}
void Compositor::addRepaint(const QRegion &region)
{
if (m_scene) {
m_scene->addRepaint(region);
}
}
void Compositor::addRepaintFull()
{
addRepaint(screens()->geometry());
}
void Compositor::handleFrameRequested(RenderLoop *renderLoop)
{
composite(renderLoop);

View file

@ -41,13 +41,6 @@ public:
~Compositor() override;
static Compositor *self();
// when adding repaints caused by a window, you probably want to use
// either Toplevel::addRepaint() or Toplevel::addWorkspaceRepaint()
void addRepaint(const QRect& r);
void addRepaint(const QRegion& r);
void addRepaint(int x, int y, int w, int h);
void addRepaintFull();
/**
* Schedules a new repaint if no repaint is currently scheduled.
*/

View file

@ -1172,22 +1172,22 @@ EffectWindow* EffectsHandlerImpl::currentTabBoxWindow() const
void EffectsHandlerImpl::addRepaintFull()
{
m_compositor->addRepaintFull();
m_compositor->scene()->addRepaintFull();
}
void EffectsHandlerImpl::addRepaint(const QRect& r)
{
m_compositor->addRepaint(r);
m_compositor->scene()->addRepaint(r);
}
void EffectsHandlerImpl::addRepaint(const QRegion& r)
{
m_compositor->addRepaint(r);
m_compositor->scene()->addRepaint(r);
}
void EffectsHandlerImpl::addRepaint(int x, int y, int w, int h)
{
m_compositor->addRepaint(x, y, w, h);
m_compositor->scene()->addRepaint(x, y, w, h);
}
EffectScreen *EffectsHandlerImpl::activeScreen() const
@ -1349,7 +1349,7 @@ QStringList EffectsHandlerImpl::listOfEffects() const
bool EffectsHandlerImpl::loadEffect(const QString& name)
{
makeOpenGLContextCurrent();
m_compositor->addRepaintFull();
m_compositor->scene()->addRepaintFull();
return m_effectLoader->loadEffect(name);
}
@ -1371,7 +1371,7 @@ void EffectsHandlerImpl::unloadEffect(const QString& name)
effect_order.erase(it);
effectsChanged();
m_compositor->addRepaintFull();
m_compositor->scene()->addRepaintFull();
}
void EffectsHandlerImpl::destroyEffect(Effect *effect)

View file

@ -10,6 +10,7 @@
#include "main.h"
#include "platform.h"
#include "renderloop.h"
#include "scene.h"
#include "screens.h"
#include "utils.h"
@ -27,7 +28,7 @@ Item::~Item()
setParentItem(nullptr);
for (const auto &dirty : qAsConst(m_repaints)) {
if (!dirty.isEmpty()) {
Compositor::self()->addRepaint(dirty);
Compositor::self()->scene()->addRepaint(dirty);
}
}
}

View file

@ -114,9 +114,6 @@ void Workspace::updateStackingOrder(bool propagate_new_clients)
}
Q_EMIT stackingOrderChanged();
if (m_compositor) {
m_compositor->addRepaintFull();
}
if (active_client)
active_client->updateMouseGrab();

View file

@ -269,11 +269,10 @@ void Platform::setSoftwareCursorForced(bool forced)
void Platform::triggerCursorRepaint()
{
if (!Compositor::self()) {
return;
if (Compositor::compositing()) {
Compositor::self()->scene()->addRepaint(m_cursor.lastRenderedGeometry);
Compositor::self()->scene()->addRepaint(Cursors::self()->currentCursor()->geometry());
}
Compositor::self()->addRepaint(m_cursor.lastRenderedGeometry);
Compositor::self()->addRepaint(Cursors::self()->currentCursor()->geometry());
}
void Platform::cursorRendered(const QRect &geometry)
@ -469,10 +468,9 @@ void Platform::processPinchGestureCancelled(quint32 time)
void Platform::repaint(const QRect &rect)
{
if (!Compositor::self()) {
return;
if (Compositor::compositing()) {
Compositor::self()->scene()->addRepaint(rect);
}
Compositor::self()->addRepaint(rect);
}
void Platform::setReady(bool ready)

View file

@ -151,7 +151,7 @@ void ScreencastManager::streamOutput(KWaylandServer::ScreencastStreamV1Interface
stream->recordFrame(texture.data(), region);
};
connect(stream, &PipeWireStream::startStreaming, waylandStream, [streamOutput, stream, bufferToStream] {
Compositor::self()->addRepaint(streamOutput->geometry());
Compositor::self()->scene()->addRepaint(streamOutput->geometry());
streamOutput->recordingStarted();
connect(streamOutput, &AbstractWaylandOutput::outputChange, stream, bufferToStream);
});

View file

@ -61,6 +61,7 @@
#include "unmanaged.h"
#include "waylandclient.h"
#include "windowitem.h"
#include "workspace.h"
#include "x11client.h"
#include <QQuickWindow>
@ -86,7 +87,6 @@ namespace KWin
Scene::Scene(QObject *parent)
: QObject(parent)
{
connect(kwinApp()->platform(), &Platform::outputDisabled, this, &Scene::removeRepaints);
}
Scene::~Scene()
@ -94,6 +94,30 @@ Scene::~Scene()
Q_ASSERT(m_windows.isEmpty());
}
void Scene::initialize()
{
connect(kwinApp()->platform(), &Platform::outputDisabled, this, &Scene::removeRepaints);
connect(workspace(), &Workspace::geometryChanged, this, &Scene::addRepaintFull);
connect(workspace(), &Workspace::currentDesktopChanged, this, &Scene::addRepaintFull);
connect(workspace(), &Workspace::stackingOrderChanged, this, &Scene::addRepaintFull);
}
void Scene::addRepaintFull()
{
addRepaint(workspace()->geometry());
}
void Scene::addRepaint(int x, int y, int width, int height)
{
addRepaint(QRegion(x, y, width, height));
}
void Scene::addRepaint(const QRect &rect)
{
addRepaint(QRegion(rect));
}
void Scene::addRepaint(const QRegion &region)
{
if (kwinApp()->platform()->isPerScreenRenderingEnabled()) {

View file

@ -53,10 +53,15 @@ public:
class EffectFrame;
class Window;
void initialize();
/**
* Schedules a repaint for the specified @a region.
*/
void addRepaint(const QRegion &region);
void addRepaint(const QRect &rect);
void addRepaint(int x, int y, int width, int height);
void addRepaintFull();
/**
* Returns the repaints region for output with the specified @a output.

View file

@ -344,15 +344,15 @@ void Toplevel::addWorkspaceRepaint(int x, int y, int w, int h)
void Toplevel::addWorkspaceRepaint(const QRect& r2)
{
if (!Compositor::compositing())
return;
Compositor::self()->addRepaint(r2);
if (Compositor::compositing()) {
Compositor::self()->scene()->addRepaint(r2);
}
}
void Toplevel::addWorkspaceRepaint(const QRegion &region)
{
if (Compositor::compositing()) {
Compositor::self()->addRepaint(region);
Compositor::self()->scene()->addRepaint(region);
}
}

View file

@ -180,7 +180,6 @@ Workspace::Workspace()
Q_ASSERT(kwinApp()->operationMode() == Application::OperationMode::OperationModeX11);
m_compositor = X11Compositor::create(this);
}
connect(this, &Workspace::currentDesktopChanged, m_compositor, &Compositor::addRepaintFull);
connect(m_compositor, &QObject::destroyed, this, [this] { m_compositor = nullptr; });
auto decorationBridge = Decoration::DecorationBridge::create(this);
@ -1192,7 +1191,7 @@ void Workspace::updateCurrentActivity(const QString &new_activity)
//if ( effects != NULL && old_desktop != 0 && old_desktop != new_desktop )
// static_cast<EffectsHandlerImpl*>( effects )->desktopChanged( old_desktop );
if (Compositor::compositing() && m_compositor)
m_compositor->addRepaintFull();
m_compositor->scene()->addRepaintFull();
#else
Q_UNUSED(new_activity)
#endif