diff --git a/src/effects.cpp b/src/effects.cpp index ad6d21691b..106fb0712c 100644 --- a/src/effects.cpp +++ b/src/effects.cpp @@ -1859,7 +1859,12 @@ void EffectsHandlerImpl::renderScreen(EffectScreen *screen) renderTarget.setDevicePixelRatio(screen->devicePixelRatio()); auto output = static_cast(screen)->platformOutput(); - m_scene->prePaint(output); + + RenderLayer layer(output->renderLoop()); + SceneDelegate delegate(m_scene, output); + delegate.setLayer(&layer); + + m_scene->prePaint(&delegate); m_scene->paint(&renderTarget, output->geometry()); m_scene->postPaint(); } diff --git a/src/scene/decorationitem.h b/src/scene/decorationitem.h index 0fb4fdde6a..ca8eb7ee82 100644 --- a/src/scene/decorationitem.h +++ b/src/scene/decorationitem.h @@ -18,6 +18,7 @@ namespace KWin class Window; class Deleted; +class Output; namespace Decoration { diff --git a/src/scene/item.cpp b/src/scene/item.cpp index 5bcf06a5ea..73d1bcbeb1 100644 --- a/src/scene/item.cpp +++ b/src/scene/item.cpp @@ -6,20 +6,19 @@ #include "scene/item.h" #include "composite.h" -#include "core/output.h" +#include "core/renderlayer.h" #include "core/renderloop.h" -#include "main.h" #include "scene/scene.h" #include "utils/common.h" -#include "workspace.h" namespace KWin { Item::Item(Item *parent) + : m_scene(Compositor::self()->scene()) { setParentItem(parent); - connect(workspace(), &Workspace::outputRemoved, this, &Item::removeRepaints); + connect(m_scene, &Scene::delegateRemoved, this, &Item::removeRepaints); } Item::~Item() @@ -27,7 +26,7 @@ Item::~Item() setParentItem(nullptr); for (const auto &dirty : std::as_const(m_repaints)) { if (!dirty.isEmpty()) { - Compositor::self()->scene()->addRepaint(dirty); + m_scene->addRepaint(dirty); } } } @@ -293,19 +292,14 @@ void Item::scheduleRepaint(const QRegion ®ion) void Item::scheduleRepaintInternal(const QRegion ®ion) { - const QList outputs = workspace()->outputs(); const QRegion globalRegion = mapToGlobal(region); - if (kwinApp()->operationMode() != Application::OperationModeX11) { - for (const auto &output : outputs) { - const QRegion dirtyRegion = globalRegion & output->geometry(); - if (!dirtyRegion.isEmpty()) { - m_repaints[output] += dirtyRegion; - output->renderLoop()->scheduleRepaint(this); - } + const QList delegates = m_scene->delegates(); + for (SceneDelegate *delegate : delegates) { + const QRegion dirtyRegion = globalRegion & delegate->viewport(); + if (!dirtyRegion.isEmpty()) { + m_repaints[delegate] += dirtyRegion; + delegate->layer()->loop()->scheduleRepaint(this); } - } else { - m_repaints[outputs.constFirst()] += globalRegion; - outputs.constFirst()->renderLoop()->scheduleRepaint(this); } } @@ -314,16 +308,12 @@ void Item::scheduleFrame() if (!isVisible()) { return; } - const QList outputs = workspace()->outputs(); - if (kwinApp()->operationMode() != Application::OperationModeX11) { - const QRect geometry = mapToGlobal(rect()).toAlignedRect(); - for (const Output *output : outputs) { - if (output->geometry().intersects(geometry)) { - output->renderLoop()->scheduleRepaint(this); - } + const QRect geometry = mapToGlobal(rect()).toRect(); + const QList delegates = m_scene->delegates(); + for (SceneDelegate *delegate : delegates) { + if (delegate->viewport().intersects(geometry)) { + delegate->layer()->loop()->scheduleRepaint(this); } - } else { - outputs.constFirst()->renderLoop()->scheduleRepaint(this); } } @@ -349,19 +339,19 @@ WindowQuadList Item::quads() const return m_quads.value(); } -QRegion Item::repaints(Output *output) const +QRegion Item::repaints(SceneDelegate *delegate) const { - return m_repaints.value(output); + return m_repaints.value(delegate); } -void Item::resetRepaints(Output *output) +void Item::resetRepaints(SceneDelegate *delegate) { - m_repaints.insert(output, QRegion()); + m_repaints.insert(delegate, QRegion()); } -void Item::removeRepaints(Output *output) +void Item::removeRepaints(SceneDelegate *delegate) { - m_repaints.remove(output); + m_repaints.remove(delegate); } bool Item::explicitVisible() const @@ -401,7 +391,7 @@ void Item::updateEffectiveVisibility() m_effectiveVisible = effectiveVisible; if (!m_effectiveVisible) { - Compositor::self()->scene()->addRepaint(mapToGlobal(boundingRect()).toAlignedRect()); + m_scene->addRepaint(mapToGlobal(boundingRect()).toAlignedRect()); } else { scheduleRepaintInternal(boundingRect().toAlignedRect()); } diff --git a/src/scene/item.h b/src/scene/item.h index 220f9fc517..709edcda35 100644 --- a/src/scene/item.h +++ b/src/scene/item.h @@ -18,7 +18,8 @@ namespace KWin { -class Output; +class SceneDelegate; +class Scene; /** * The Item class is the base class for items in the scene. @@ -101,8 +102,8 @@ public: void scheduleRepaint(const QRectF ®ion); void scheduleRepaint(const QRegion ®ion); void scheduleFrame(); - QRegion repaints(Output *output) const; - void resetRepaints(Output *output); + QRegion repaints(SceneDelegate *delegate) const; + void resetRepaints(SceneDelegate *delegate); WindowQuadList quads() const; virtual void preprocess(); @@ -137,8 +138,9 @@ private: bool computeEffectiveVisibility() const; void updateEffectiveVisibility(); - void removeRepaints(Output *output); + void removeRepaints(SceneDelegate *delegate); + Scene *m_scene; QPointer m_parentItem; QList m_childItems; QMatrix4x4 m_transform; @@ -149,7 +151,7 @@ private: int m_z = 0; bool m_explicitVisible = true; bool m_effectiveVisible = true; - QMap m_repaints; + QMap m_repaints; mutable std::optional m_quads; mutable std::optional> m_sortedChildItems; }; diff --git a/src/scene/scene.cpp b/src/scene/scene.cpp index 93a67bb117..2b8b33f441 100644 --- a/src/scene/scene.cpp +++ b/src/scene/scene.cpp @@ -111,7 +111,7 @@ SurfaceItem *SceneDelegate::scanoutCandidate() const void SceneDelegate::prePaint() { - m_scene->prePaint(m_output); + m_scene->prePaint(this); } void SceneDelegate::postPaint() @@ -124,6 +124,11 @@ void SceneDelegate::paint(RenderTarget *renderTarget, const QRegion ®ion) m_scene->paint(renderTarget, region.translated(viewport().topLeft())); } +Output *SceneDelegate::output() const +{ + return m_output; +} + QRect SceneDelegate::viewport() const { return m_output ? m_output->geometry() : m_scene->geometry(); @@ -235,6 +240,7 @@ void Scene::addDelegate(SceneDelegate *delegate) void Scene::removeDelegate(SceneDelegate *delegate) { m_delegates.removeOne(delegate); + Q_EMIT delegateRemoved(delegate); } static SurfaceItem *findTopMostSurface(SurfaceItem *item) @@ -286,16 +292,17 @@ SurfaceItem *Scene::scanoutCandidate() const return candidate; } -void Scene::prePaint(Output *output) +void Scene::prePaint(SceneDelegate *delegate) { createStackingOrder(); + painted_delegate = delegate; if (kwinApp()->operationMode() == Application::OperationModeX11) { painted_screen = workspace()->outputs().constFirst(); m_renderer->setRenderTargetRect(geometry()); m_renderer->setRenderTargetScale(1); } else { - painted_screen = output; + painted_screen = painted_delegate->output(); m_renderer->setRenderTargetRect(painted_screen->fractionalGeometry()); m_renderer->setRenderTargetScale(painted_screen->scale()); } @@ -336,31 +343,31 @@ void Scene::prePaint(Output *output) } } -static void resetRepaintsHelper(Item *item, Output *output) +static void resetRepaintsHelper(Item *item, SceneDelegate *delegate) { - item->resetRepaints(output); + item->resetRepaints(delegate); const auto childItems = item->childItems(); for (Item *childItem : childItems) { - resetRepaintsHelper(childItem, output); + resetRepaintsHelper(childItem, delegate); } } -static void accumulateRepaints(Item *item, Output *output, QRegion *repaints) +static void accumulateRepaints(Item *item, SceneDelegate *delegate, QRegion *repaints) { - *repaints += item->repaints(output); - item->resetRepaints(output); + *repaints += item->repaints(delegate); + item->resetRepaints(delegate); const auto childItems = item->childItems(); for (Item *childItem : childItems) { - accumulateRepaints(childItem, output, repaints); + accumulateRepaints(childItem, delegate, repaints); } } void Scene::preparePaintGenericScreen() { for (WindowItem *windowItem : std::as_const(stacking_order)) { - resetRepaintsHelper(windowItem, painted_screen); + resetRepaintsHelper(windowItem, painted_delegate); WindowPrePaintData data; data.mask = m_paintContext.mask; @@ -384,7 +391,7 @@ void Scene::preparePaintSimpleScreen() Window *window = windowItem->window(); WindowPrePaintData data; data.mask = m_paintContext.mask; - accumulateRepaints(windowItem, painted_screen, &data.paint); + accumulateRepaints(windowItem, painted_delegate, &data.paint); // Clip out the decoration for opaque windows; the decoration is drawn in the second pass. if (window->opacity() == 1.0) { @@ -419,7 +426,7 @@ void Scene::preparePaintSimpleScreen() } if (m_dndIcon) { - accumulateRepaints(m_dndIcon.get(), painted_screen, &m_paintContext.damage); + accumulateRepaints(m_dndIcon.get(), painted_delegate, &m_paintContext.damage); } } diff --git a/src/scene/scene.h b/src/scene/scene.h index bc03a93367..6deefd6c27 100644 --- a/src/scene/scene.h +++ b/src/scene/scene.h @@ -51,6 +51,7 @@ public: explicit SceneDelegate(Scene *scene, Output *output, QObject *parent = nullptr); ~SceneDelegate() override; + Output *output() const; QRect viewport() const; QRegion repaints() const override; @@ -90,7 +91,7 @@ public: void removeDelegate(SceneDelegate *delegate); SurfaceItem *scanoutCandidate() const; - void prePaint(Output *output); + void prePaint(SceneDelegate *delegate); void postPaint(); void paint(RenderTarget *renderTarget, const QRegion ®ion); @@ -146,6 +147,7 @@ public: Q_SIGNALS: void preFrameRender(); void frameRendered(); + void delegateRemoved(SceneDelegate *delegate); protected: void createStackingOrder(); @@ -185,6 +187,7 @@ protected: // The screen that is being currently painted Output *painted_screen = nullptr; + SceneDelegate *painted_delegate = nullptr; // windows in their stacking order QVector stacking_order;