Commit a3ec0c9a authored by Vlad Zahorodnii's avatar Vlad Zahorodnii

Delegate repaint scheduling to the Scene

In order to unlock per screen rendering, we need to track repaints for
every screen individually. While we could do this in the Compositor class,
tracking repaints in the Scene seems a better alternative in long run
because we will have to instantiate a Scene for each composited screen
one day.
parent 992e88de
......@@ -448,7 +448,6 @@ void Compositor::stop()
delete m_scene;
m_scene = nullptr;
compositeTimer.stop();
repaints_region = QRegion();
m_state = State::Off;
emit compositingToggled(false);
......@@ -529,41 +528,26 @@ void Compositor::reinitialize()
}
}
void Compositor::addRepaint(int x, int y, int w, int h)
void Compositor::addRepaint(int x, int y, int width, int height)
{
if (m_state != State::On) {
return;
}
repaints_region += QRegion(x, y, w, h);
scheduleRepaint();
addRepaint(QRegion(x, y, width, height));
}
void Compositor::addRepaint(const QRect& r)
void Compositor::addRepaint(const QRect &rect)
{
if (m_state != State::On) {
return;
}
repaints_region += r;
scheduleRepaint();
addRepaint(QRegion(rect));
}
void Compositor::addRepaint(const QRegion& r)
void Compositor::addRepaint(const QRegion &region)
{
if (m_state != State::On) {
return;
if (m_scene) {
m_scene->addRepaint(region);
}
repaints_region += r;
scheduleRepaint();
}
void Compositor::addRepaintFull()
{
if (m_state != State::On) {
return;
}
const QSize &s = screens()->size();
repaints_region = QRegion(0, 0, s.width(), s.height());
scheduleRepaint();
addRepaint(screens()->geometry());
}
void Compositor::timerEvent(QTimerEvent *te)
......@@ -666,10 +650,6 @@ void Compositor::performCompositing()
}
}
QRegion repaints = repaints_region;
// clear all repaints, so that post-pass can add repaints for the next repaint
repaints_region = QRegion();
const std::chrono::nanoseconds now = std::chrono::steady_clock::now().time_since_epoch();
const std::chrono::milliseconds presentTime =
std::chrono::duration_cast<std::chrono::milliseconds>(now);
......@@ -680,9 +660,15 @@ void Compositor::performCompositing()
m_renderTimer.start();
if (kwinApp()->platform()->isPerScreenRenderingEnabled()) {
for (int screenId = 0; screenId < screens()->count(); ++screenId) {
const QRegion repaints = m_scene->repaints(screenId);
m_scene->resetRepaints(screenId);
m_scene->paint(screenId, repaints, windows, presentTime);
}
} else {
const QRegion repaints = m_scene->repaints(-1);
m_scene->resetRepaints(-1);
m_scene->paint(-1, repaints, windows, presentTime);
}
m_timeSinceLastVBlank = m_renderTimer.elapsed();
......
......@@ -146,7 +146,6 @@ private:
QList<xcb_atom_t> m_unusedSupportProperties;
QTimer m_unusedSupportPropertyTimer;
qint64 vBlankInterval, fpsInterval;
QRegion repaints_region;
qint64 m_timeSinceLastVBlank;
......
......@@ -56,6 +56,7 @@
*/
#include "scene.h"
#include "abstract_output.h"
#include "platform.h"
#include <QQuickWindow>
......@@ -86,6 +87,10 @@ namespace KWin
Scene::Scene(QObject *parent)
: QObject(parent)
{
if (kwinApp()->platform()->isPerScreenRenderingEnabled()) {
connect(screens(), &Screens::countChanged, this, &Scene::reallocRepaints);
}
reallocRepaints();
}
Scene::~Scene()
......@@ -93,6 +98,49 @@ Scene::~Scene()
Q_ASSERT(m_windows.isEmpty());
}
void Scene::addRepaint(const QRegion &region)
{
if (kwinApp()->platform()->isPerScreenRenderingEnabled()) {
if (m_repaints.count() != screens()->count()) {
return; // Repaints haven't been reallocated yet, do nothing.
}
for (int screenId = 0; screenId < m_repaints.count(); ++screenId) {
AbstractOutput *output = kwinApp()->platform()->findOutput(screenId);
const QRegion dirtyRegion = region & output->geometry();
if (!dirtyRegion.isEmpty()) {
m_repaints[screenId] += dirtyRegion;
}
}
} else {
m_repaints[0] += region;
}
Compositor::self()->scheduleRepaint();
}
QRegion Scene::repaints(int screenId) const
{
const int index = screenId == -1 ? 0 : screenId;
return m_repaints[index];
}
void Scene::resetRepaints(int screenId)
{
const int index = screenId == -1 ? 0 : screenId;
m_repaints[index] = QRegion();
}
void Scene::reallocRepaints()
{
if (kwinApp()->platform()->isPerScreenRenderingEnabled()) {
m_repaints.resize(screens()->count());
} else {
m_repaints.resize(1);
}
m_repaints.fill(infiniteRegion());
}
// returns mask and possibly modified region
void Scene::paintScreen(int* mask, const QRegion &damage, const QRegion &repaint,
QRegion *updateRegion, QRegion *validRegion,
......
......@@ -55,6 +55,17 @@ public:
class EffectFrame;
class Window;
/**
* Schedules a repaint for the specified @a region.
*/
void addRepaint(const QRegion &region);
/**
* Returns the repaints region for output with the specified @a screenId.
*/
QRegion repaints(int screenId) const;
void resetRepaints(int screenId);
// Returns true if the ctor failed to properly initialize.
virtual bool initFailed() const = 0;
virtual CompositingType compositingType() const = 0;
......@@ -265,9 +276,11 @@ private:
void paintWindowThumbnails(Scene::Window *w, const QRegion &region, qreal opacity, qreal brightness, qreal saturation);
void paintDesktopThumbnails(Scene::Window *w);
std::chrono::milliseconds m_expectedPresentTimestamp = std::chrono::milliseconds::zero();
void reallocRepaints();
QHash< Toplevel*, Window* > m_windows;
// windows in their stacking order
QVector< Window* > stacking_order;
QVector<QRegion> m_repaints;
// how many times finalPaintScreen() has been called
int m_paintScreenCount = 0;
};
......
Markdown is supported
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