Commit a3b52661 authored by Vlad Zahorodnii's avatar Vlad Zahorodnii
Browse files

Drop Platform::renderLoop()

Having a render loop in the Platform has always been awkward. Another
way to interpret the platform not supporting per screen rendering would
be that all outputs share the same render loop.

On X11, Scene::painted_screen is going to correspond to the primary
screen, we should not rely on this assumption though!
parent ba000d5a
Pipeline #137956 passed with stage
in 13 minutes and 30 seconds
......@@ -141,11 +141,6 @@ QString AbstractOutput::serialNumber() const
return QString();
}
RenderLoop *AbstractOutput::renderLoop() const
{
return nullptr;
}
void AbstractOutput::inhibitDirectScanout()
{
m_directScanoutCount++;
......
......@@ -180,10 +180,10 @@ public:
virtual QString serialNumber() const;
/**
* Returns the RenderLoop for this output. This function returns @c null if the
* underlying platform doesn't support per-screen rendering mode.
* Returns the RenderLoop for this output. If the platform does not support per screen
* rendering, all outputs will share the same render loop.
*/
virtual RenderLoop *renderLoop() const;
virtual RenderLoop *renderLoop() const = 0;
void inhibitDirectScanout();
void uninhibitDirectScanout();
......
......@@ -46,7 +46,7 @@ EglBackend::~EglBackend()
// No completion events will be received for in-flight frames, this may lock the
// render loop. We need to ensure that the render loop is back to its initial state
// if the render backend is about to be destroyed.
RenderLoopPrivate::get(kwinApp()->platform()->renderLoop())->invalidate();
RenderLoopPrivate::get(m_backend->renderLoop())->invalidate();
}
SurfaceTexture *EglBackend::createSurfaceTextureX11(SurfacePixmapX11 *texture)
......
......@@ -90,8 +90,8 @@ bool SwapEventFilter::event(xcb_generic_event_t *event)
// it's CLOCK_MONOTONIC, so no special conversions are needed.
const std::chrono::microseconds timestamp((uint64_t(swapEvent->ust_hi) << 32) | swapEvent->ust_lo);
RenderLoopPrivate *renderLoopPrivate = RenderLoopPrivate::get(kwinApp()->platform()->renderLoop());
renderLoopPrivate->notifyFrameCompleted(timestamp);
const auto platform = static_cast<X11StandalonePlatform *>(kwinApp()->platform());
RenderLoopPrivate::get(platform->renderLoop())->notifyFrameCompleted(timestamp);
return true;
}
......@@ -122,7 +122,7 @@ GlxBackend::~GlxBackend()
// No completion events will be received for in-flight frames, this may lock the
// render loop. We need to ensure that the render loop is back to its initial state
// if the render backend is about to be destroyed.
RenderLoopPrivate::get(kwinApp()->platform()->renderLoop())->invalidate();
RenderLoopPrivate::get(m_backend->renderLoop())->invalidate();
if (isFailed()) {
m_overlayWindow->destroy();
......
......@@ -23,6 +23,16 @@ QString X11Output::name() const
return m_name;
}
RenderLoop *X11Output::renderLoop() const
{
return m_loop;
}
void X11Output::setRenderLoop(RenderLoop *loop)
{
m_loop = loop;
}
int X11Output::xineramaNumber() const
{
return m_xineramaNumber;
......
......@@ -32,6 +32,9 @@ public:
QString name() const override;
RenderLoop *renderLoop() const override;
void setRenderLoop(RenderLoop *loop);
int xineramaNumber() const;
void setXineramaNumber(int number);
......@@ -54,6 +57,7 @@ private:
void setCrtc(xcb_randr_crtc_t crtc);
void setGammaRampSize(int size);
RenderLoop *m_loop = nullptr;
xcb_randr_crtc_t m_crtc = XCB_NONE;
QString m_name;
QRect m_geometry;
......
......@@ -531,6 +531,7 @@ void X11StandalonePlatform::doUpdateOutputs()
// drm platform do this.
Xcb::RandR::CrtcGamma gamma(crtcs[i]);
output->setRenderLoop(m_renderLoop);
output->setCrtc(crtcs[i]);
output->setGammaRampSize(gamma.isNull() ? 0 : gamma->size);
output->setGeometry(geometry);
......@@ -560,7 +561,7 @@ void X11StandalonePlatform::doUpdateOutputs()
// The workspace handles having no outputs poorly. If the last output is about to be
// removed, create a dummy output to avoid crashing.
if (changed.isEmpty() && added.isEmpty()) {
auto dummyOutput = new X11PlaceholderOutput();
auto dummyOutput = new X11PlaceholderOutput(m_renderLoop);
m_outputs << dummyOutput;
Q_EMIT outputAdded(dummyOutput);
Q_EMIT outputEnabled(dummyOutput);
......
......@@ -21,6 +21,7 @@
namespace KWin
{
class RenderLoop;
class XInputIntegration;
class WindowSelector;
class X11EventFilter;
......@@ -64,7 +65,7 @@ public:
void scheduleUpdateOutputs();
void updateOutputs();
RenderLoop *renderLoop() const override;
RenderLoop *renderLoop() const;
Outputs outputs() const override;
Outputs enabledOutputs() const override;
......
......@@ -10,11 +10,17 @@
namespace KWin
{
X11PlaceholderOutput::X11PlaceholderOutput(QObject *parent)
X11PlaceholderOutput::X11PlaceholderOutput(RenderLoop *loop, QObject *parent)
: AbstractOutput(parent)
, m_loop(loop)
{
}
RenderLoop *X11PlaceholderOutput::renderLoop() const
{
return m_loop;
}
QString X11PlaceholderOutput::name() const
{
return QStringLiteral("Placeholder-0");
......
......@@ -16,12 +16,16 @@ class X11PlaceholderOutput : public AbstractOutput
Q_OBJECT
public:
explicit X11PlaceholderOutput(QObject *parent = nullptr);
explicit X11PlaceholderOutput(RenderLoop *loop, QObject *parent = nullptr);
RenderLoop *renderLoop() const override;
QString name() const override;
QRect geometry() const override;
int refreshRate() const override;
QSize pixelSize() const override;
private:
RenderLoop *m_loop;
};
} // namespace KWin
......@@ -351,18 +351,17 @@ void Compositor::startupWithWorkspace()
Q_ASSERT(m_scene);
m_scene->initialize();
const Platform *platform = kwinApp()->platform();
if (platform->isPerScreenRenderingEnabled()) {
const QVector<AbstractOutput *> outputs = platform->enabledOutputs();
const QVector<AbstractOutput *> outputs = kwinApp()->platform()->enabledOutputs();
if (kwinApp()->platform()->isPerScreenRenderingEnabled()) {
for (AbstractOutput *output : outputs) {
registerRenderLoop(output->renderLoop(), output);
}
connect(platform, &Platform::outputEnabled,
connect(kwinApp()->platform(), &Platform::outputEnabled,
this, &Compositor::handleOutputEnabled);
connect(platform, &Platform::outputDisabled,
connect(kwinApp()->platform(), &Platform::outputDisabled,
this, &Compositor::handleOutputDisabled);
} else {
registerRenderLoop(platform->renderLoop(), nullptr);
registerRenderLoop(outputs.constFirst()->renderLoop(), nullptr);
}
m_state = State::On;
......@@ -397,6 +396,17 @@ void Compositor::startupWithWorkspace()
m_scene->addRepaintFull();
}
AbstractOutput *Compositor::findOutput(RenderLoop *loop) const
{
const auto outputs = kwinApp()->platform()->enabledOutputs();
for (AbstractOutput *output : outputs) {
if (output->renderLoop() == loop) {
return output;
}
}
return nullptr;
}
void Compositor::registerRenderLoop(RenderLoop *renderLoop, AbstractOutput *output)
{
Q_ASSERT(!m_renderLoops.contains(renderLoop));
......@@ -622,8 +632,8 @@ void Compositor::composite(RenderLoop *renderLoop)
return;
}
const auto &output = m_renderLoops[renderLoop];
fTraceDuration("Paint (", output ? output->name() : QStringLiteral("screens"), ")");
AbstractOutput *output = findOutput(renderLoop);
fTraceDuration("Paint (", output->name(), ")");
const auto windows = windowsToRender();
......
......@@ -135,6 +135,8 @@ private:
bool attemptOpenGLCompositing();
bool attemptQPainterCompositing();
AbstractOutput *findOutput(RenderLoop *loop) const;
State m_state = State::Off;
CompositorSelectionOwner *m_selectionOwner = nullptr;
QTimer m_releaseSelectionTimer;
......
......@@ -60,7 +60,7 @@ void ColorPickerEffect::postPaintScreen()
{
effects->postPaintScreen();
if (m_scheduledPosition != QPoint(-1, -1) && (!m_paintedScreen || m_paintedScreen->geometry().contains(m_scheduledPosition))) {
if (m_scheduledPosition != QPoint(-1, -1) && effects->renderTargetRect().contains(m_scheduledPosition)) {
uint8_t data[3];
const QRect geo = effects->renderTargetRect();
const QPoint screenPosition(m_scheduledPosition.x() - geo.x(), m_scheduledPosition.y() - geo.y());
......
......@@ -268,7 +268,7 @@ void ScreenShotEffect::takeScreenShot(ScreenShotWindowData *screenshot)
bool ScreenShotEffect::takeScreenShot(ScreenShotAreaData *screenshot)
{
if (!m_paintedScreen) {
if (!effects->waylandDisplay()) {
// On X11, all screens are painted simultaneously and there is no native HiDPI support.
QImage snapshot = blitScreenshot(screenshot->area);
if (screenshot->flags & ScreenShotIncludeCursor) {
......
......@@ -255,9 +255,9 @@ void Item::scheduleRepaint(const QRegion &region)
void Item::scheduleRepaintInternal(const QRegion &region)
{
const QVector<AbstractOutput *> outputs = kwinApp()->platform()->enabledOutputs();
const QRegion globalRegion = mapToGlobal(region);
if (kwinApp()->platform()->isPerScreenRenderingEnabled()) {
const QVector<AbstractOutput *> outputs = kwinApp()->platform()->enabledOutputs();
for (const auto &output : outputs) {
const QRegion dirtyRegion = globalRegion & output->geometry();
if (!dirtyRegion.isEmpty()) {
......@@ -266,8 +266,8 @@ void Item::scheduleRepaintInternal(const QRegion &region)
}
}
} else {
m_repaints[nullptr] += globalRegion;
kwinApp()->platform()->renderLoop()->scheduleRepaint(this);
m_repaints[outputs.constFirst()] += globalRegion;
outputs.constFirst()->renderLoop()->scheduleRepaint(this);
}
}
......@@ -276,16 +276,16 @@ void Item::scheduleFrame()
if (!isVisible()) {
return;
}
const QVector<AbstractOutput *> outputs = kwinApp()->platform()->enabledOutputs();
if (kwinApp()->platform()->isPerScreenRenderingEnabled()) {
const QRect geometry = mapToGlobal(rect());
const QVector<AbstractOutput *> outputs = kwinApp()->platform()->enabledOutputs();
for (const AbstractOutput *output : outputs) {
if (output->geometry().intersects(geometry)) {
output->renderLoop()->scheduleRepaint(this);
}
}
} else {
kwinApp()->platform()->renderLoop()->scheduleRepaint(this);
outputs.constFirst()->renderLoop()->scheduleRepaint(this);
}
}
......
......@@ -3186,7 +3186,7 @@ public:
QMatrix4x4 projectionMatrix() const;
/**
* Returns the currently rendered screen. Only set for per-screen rendering, e.g. Wayland.
* Returns the currently rendered screen. It's always the primary screen on X11.
*/
EffectScreen *screen() const;
......
......@@ -432,11 +432,6 @@ void Platform::setPerScreenRenderingEnabled(bool enabled)
m_isPerScreenRenderingEnabled = enabled;
}
RenderLoop *Platform::renderLoop() const
{
return nullptr;
}
AbstractOutput *Platform::createVirtualOutput(const QString &name, const QSize &size, double scale)
{
Q_UNUSED(name);
......
......@@ -37,7 +37,6 @@ class OpenGLBackend;
class Outline;
class OutlineVisual;
class QPainterBackend;
class RenderLoop;
class Scene;
class ScreenEdges;
class Session;
......@@ -344,12 +343,6 @@ public:
*/
bool isPerScreenRenderingEnabled() const;
/**
* If the Platform doesn't support per screen rendering, this function returns the
* RenderLoop that drives compositing.
*/
virtual RenderLoop *renderLoop() const;
virtual AbstractOutput *createVirtualOutput(const QString &name, const QSize &size, qreal scaling);
virtual void removeVirtualOutput(AbstractOutput *output);
......
......@@ -143,8 +143,8 @@ void Scene::addRepaint(const QRect &rect)
void Scene::addRepaint(const QRegion &region)
{
const QVector<AbstractOutput *> outputs = kwinApp()->platform()->enabledOutputs();
if (kwinApp()->platform()->isPerScreenRenderingEnabled()) {
const QVector<AbstractOutput *> outputs = kwinApp()->platform()->enabledOutputs();
for (const auto &output : outputs) {
const QRegion dirtyRegion = region & output->geometry();
if (!dirtyRegion.isEmpty()) {
......@@ -153,8 +153,8 @@ void Scene::addRepaint(const QRegion &region)
}
}
} else {
m_repaints[0] += region;
kwinApp()->platform()->renderLoop()->scheduleRepaint();
m_repaints[outputs.constFirst()] += region;
outputs.constFirst()->renderLoop()->scheduleRepaint();
}
}
......@@ -261,16 +261,17 @@ void Scene::paintScreen(AbstractOutput *output, const QList<Toplevel *> &topleve
setRenderTargetScale(output->scale());
QRegion update, valid;
paintScreen(renderTargetRect(), QRect(), &update, &valid, output->renderLoop());
paintScreen(renderTargetRect(), QRect(), &update, &valid);
clearStackingOrder();
}
// returns mask and possibly modified region
void Scene::paintScreen(const QRegion &damage, const QRegion &repaint,
QRegion *updateRegion, QRegion *validRegion, RenderLoop *renderLoop)
QRegion *updateRegion, QRegion *validRegion)
{
const QRegion displayRegion(geometry());
const RenderLoop *renderLoop = painted_screen->renderLoop();
const std::chrono::milliseconds presentTime =
std::chrono::duration_cast<std::chrono::milliseconds>(renderLoop->nextPresentationTimestamp());
......@@ -289,7 +290,7 @@ void Scene::paintScreen(const QRegion &damage, const QRegion &repaint,
QRegion region = damage;
auto screen = painted_screen ? EffectScreenImpl::get(painted_screen) : nullptr;
auto screen = EffectScreenImpl::get(painted_screen);
ScreenPrePaintData pdata;
pdata.mask = (damage == displayRegion) ? 0 : PAINT_SCREEN_REGION;
pdata.paint = region;
......
......@@ -209,7 +209,7 @@ protected:
void clearStackingOrder();
// shared implementation, starts painting the screen
void paintScreen(const QRegion &damage, const QRegion &repaint,
QRegion *updateRegion, QRegion *validRegion, RenderLoop *renderLoop);
QRegion *updateRegion, QRegion *validRegion);
// Render cursor texture in case hardware cursor is disabled/non-applicable
virtual void paintCursor(AbstractOutput *output, const QRegion &region) = 0;
friend class EffectsHandlerImpl;
......
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