diff --git a/src/plugins/screenedge/screenedgeeffect.cpp b/src/plugins/screenedge/screenedgeeffect.cpp index 337fd5ea17..12c3cc770e 100644 --- a/src/plugins/screenedge/screenedgeeffect.cpp +++ b/src/plugins/screenedge/screenedgeeffect.cpp @@ -8,11 +8,10 @@ */ #include "screenedgeeffect.h" // KWin -#include "core/rendertarget.h" -#include "core/renderviewport.h" #include "effect/effecthandler.h" -#include "opengl/gltexture.h" -#include "opengl/glutils.h" +#include "scene/imageitem.h" +#include "scene/itemrenderer.h" +#include "scene/workspacescene.h" // KDE #include #include @@ -21,7 +20,6 @@ #include #include #include -#include namespace KWin { @@ -72,102 +70,19 @@ void ScreenEdgeEffect::ensureGlowSvg() void ScreenEdgeEffect::cleanup() { - for (auto &[border, glow] : m_borders) { - effects->addRepaint(glow->geometry); - } - m_borders.clear(); -} - -void ScreenEdgeEffect::prePaintScreen(ScreenPrePaintData &data, std::chrono::milliseconds presentTime) -{ - effects->prePaintScreen(data, presentTime); - for (auto &[border, glow] : m_borders) { - if (glow->strength == 0.0) { - continue; - } - data.paint += glow->geometry; - } -} - -void ScreenEdgeEffect::paintScreen(const RenderTarget &renderTarget, const RenderViewport &viewport, int mask, const QRegion ®ion, Output *screen) -{ - effects->paintScreen(renderTarget, viewport, mask, region, screen); - for (auto &[border, glow] : m_borders) { - const qreal opacity = glow->strength; - if (opacity == 0.0) { - continue; - } - if (effects->isOpenGLCompositing()) { - GLTexture *texture = glow->texture.get(); - if (!texture) { - return; - } - glEnable(GL_BLEND); - glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - ShaderBinder binder(ShaderTrait::MapTexture | ShaderTrait::Modulate | ShaderTrait::TransformColorspace); - binder.shader()->setColorspaceUniformsFromSRGB(renderTarget.colorDescription()); - const QVector4D constant(opacity, opacity, opacity, opacity); - binder.shader()->setUniform(GLShader::Vec4Uniform::ModulationConstant, constant); - const auto scale = viewport.scale(); - QMatrix4x4 mvp = viewport.projectionMatrix(); - mvp.translate(glow->geometry.x() * scale, glow->geometry.y() * scale); - binder.shader()->setUniform(GLShader::Mat4Uniform::ModelViewProjectionMatrix, mvp); - texture->render(glow->geometry.size() * scale); - glDisable(GL_BLEND); - } else if (effects->compositingType() == QPainterCompositing) { - QImage tmp(glow->image.size(), QImage::Format_ARGB32_Premultiplied); - tmp.fill(Qt::transparent); - QPainter p(&tmp); - p.drawImage(0, 0, glow->image); - QColor color(Qt::transparent); - color.setAlphaF(opacity); - p.setCompositionMode(QPainter::CompositionMode_DestinationIn); - p.fillRect(QRect(QPoint(0, 0), tmp.size()), color); - p.end(); - - QPainter *painter = effects->scenePainter(); - const QRect &rect = glow->geometry; - const QSize &size = glow->pictureSize; - int x = rect.x(); - int y = rect.y(); - switch (glow->border) { - case ElectricTopRight: - x = rect.x() + rect.width() - size.width(); - break; - case ElectricBottomRight: - x = rect.x() + rect.width() - size.width(); - y = rect.y() + rect.height() - size.height(); - break; - case ElectricBottomLeft: - y = rect.y() + rect.height() - size.height(); - break; - default: - // nothing - break; - } - painter->drawImage(QPoint(x, y), tmp); - } - } + m_glowItems.clear(); } void ScreenEdgeEffect::edgeApproaching(ElectricBorder border, qreal factor, const QRect &geometry) { - auto it = m_borders.find(border); - if (it != m_borders.end()) { - Glow *glow = it->second.get(); - // need to update - effects->addRepaint(glow->geometry); - glow->strength = factor; - if (glow->geometry != geometry) { - glow->geometry = geometry; - effects->addRepaint(glow->geometry); - if (border == ElectricLeft || border == ElectricRight || border == ElectricTop || border == ElectricBottom) { - if (effects->isOpenGLCompositing()) { - glow->texture = GLTexture::upload(createEdgeGlow(border, geometry.size())); - } else if (effects->compositingType() == QPainterCompositing) { - glow->image = createEdgeGlow(border, geometry.size()); - } - } + auto it = m_glowItems.find(border); + if (it != m_glowItems.end()) { + ImageItem *glowItem = it->second.get(); + glowItem->setOpacity(factor); + if (glowItem->position() != geometry.topLeft() || glowItem->size() != geometry.size()) { + glowItem->setImage(glowImage(border, geometry.size())); + glowItem->setPosition(geometry.topLeft()); + glowItem->setSize(geometry.size()); } if (factor == 0.0) { m_cleanupTimer->start(); @@ -175,51 +90,41 @@ void ScreenEdgeEffect::edgeApproaching(ElectricBorder border, qreal factor, cons m_cleanupTimer->stop(); } } else if (factor != 0.0) { - // need to generate new Glow - std::unique_ptr glow = createGlow(border, factor, geometry); + std::unique_ptr glow = createGlowItem(border, factor, geometry); if (glow) { - effects->addRepaint(glow->geometry); - m_borders[border] = std::move(glow); + m_glowItems[border] = std::move(glow); } } } -std::unique_ptr ScreenEdgeEffect::createGlow(ElectricBorder border, qreal factor, const QRect &geometry) +std::unique_ptr ScreenEdgeEffect::createGlowItem(ElectricBorder border, qreal factor, const QRect &geometry) { - auto glow = std::make_unique(); - glow->border = border; - glow->strength = factor; - glow->geometry = geometry; - - // render the glow image - if (effects->isOpenGLCompositing()) { - effects->makeOpenGLContextCurrent(); - if (border == ElectricTopLeft || border == ElectricTopRight || border == ElectricBottomRight || border == ElectricBottomLeft) { - glow->texture = GLTexture::upload(createCornerGlow(border)); - } else { - glow->texture = GLTexture::upload(createEdgeGlow(border, geometry.size())); - } - if (!glow->texture) { - return nullptr; - } - glow->texture->setWrapMode(GL_CLAMP_TO_EDGE); - } else if (effects->compositingType() == QPainterCompositing) { - if (border == ElectricTopLeft || border == ElectricTopRight || border == ElectricBottomRight || border == ElectricBottomLeft) { - glow->image = createCornerGlow(border); - glow->pictureSize = cornerGlowSize(border); - } else { - glow->image = createEdgeGlow(border, geometry.size()); - glow->pictureSize = geometry.size(); - } - if (glow->image.isNull()) { - return nullptr; - } + const QImage image = glowImage(border, geometry.size()); + if (image.isNull()) { + return nullptr; } - return glow; + WorkspaceScene *scene = effects->scene(); + + std::unique_ptr imageItem = scene->renderer()->createImageItem(scene, scene->overlayItem()); + imageItem->setImage(image); + imageItem->setPosition(geometry.topLeft()); + imageItem->setSize(geometry.size()); + imageItem->setOpacity(factor); + + return imageItem; } -QImage ScreenEdgeEffect::createCornerGlow(ElectricBorder border) +QImage ScreenEdgeEffect::glowImage(ElectricBorder border, const QSize &size) +{ + if (border == ElectricLeft || border == ElectricRight || border == ElectricTop || border == ElectricBottom) { + return edgeGlowImage(border, size); + } else { + return cornerGlowImage(border); + } +} + +QImage ScreenEdgeEffect::cornerGlowImage(ElectricBorder border) { ensureGlowSvg(); @@ -237,25 +142,7 @@ QImage ScreenEdgeEffect::createCornerGlow(ElectricBorder border) } } -QSize ScreenEdgeEffect::cornerGlowSize(ElectricBorder border) -{ - ensureGlowSvg(); - - switch (border) { - case ElectricTopLeft: - return m_glow->elementSize(QStringLiteral("bottomright")).toSize(); - case ElectricTopRight: - return m_glow->elementSize(QStringLiteral("bottomleft")).toSize(); - case ElectricBottomRight: - return m_glow->elementSize(QStringLiteral("topleft")).toSize(); - case ElectricBottomLeft: - return m_glow->elementSize(QStringLiteral("topright")).toSize(); - default: - return QSize(); - } -} - -QImage ScreenEdgeEffect::createEdgeGlow(ElectricBorder border, const QSize &size) +QImage ScreenEdgeEffect::edgeGlowImage(ElectricBorder border, const QSize &size) { ensureGlowSvg(); @@ -318,7 +205,7 @@ QImage ScreenEdgeEffect::createEdgeGlow(ElectricBorder border, const QSize &size bool ScreenEdgeEffect::isActive() const { - return !m_borders.empty() && !effects->isScreenLocked(); + return !m_glowItems.empty() && !effects->isScreenLocked(); } } // namespace diff --git a/src/plugins/screenedge/screenedgeeffect.h b/src/plugins/screenedge/screenedgeeffect.h index 54dfad8c36..09b538c4ff 100644 --- a/src/plugins/screenedge/screenedgeeffect.h +++ b/src/plugins/screenedge/screenedgeeffect.h @@ -19,8 +19,8 @@ class Svg; namespace KWin { -class Glow; -class GLTexture; + +class ImageItem; class ScreenEdgeEffect : public Effect { @@ -28,8 +28,6 @@ class ScreenEdgeEffect : public Effect public: ScreenEdgeEffect(); ~ScreenEdgeEffect() override; - void prePaintScreen(ScreenPrePaintData &data, std::chrono::milliseconds presentTime) override; - void paintScreen(const RenderTarget &renderTarget, const RenderViewport &viewport, int mask, const QRegion ®ion, Output *screen) override; bool isActive() const override; int requestedEffectChainPosition() const override @@ -43,25 +41,15 @@ private Q_SLOTS: private: void ensureGlowSvg(); - std::unique_ptr createGlow(ElectricBorder border, qreal factor, const QRect &geometry); - QImage createCornerGlow(ElectricBorder border); - QImage createEdgeGlow(ElectricBorder border, const QSize &size); - QSize cornerGlowSize(ElectricBorder border); + QImage cornerGlowImage(ElectricBorder border); + QImage edgeGlowImage(ElectricBorder border, const QSize &size); + QImage glowImage(ElectricBorder border, const QSize &size); + std::unique_ptr createGlowItem(ElectricBorder border, qreal factor, const QRect &geometry); + KConfigWatcher::Ptr m_configWatcher; KSvg::Svg *m_glow = nullptr; - std::map> m_borders; + std::unordered_map> m_glowItems; QTimer *m_cleanupTimer; }; -class Glow -{ -public: - std::unique_ptr texture; - QImage image; - QSize pictureSize; - qreal strength; - QRect geometry; - ElectricBorder border; -}; - -} +} // namespace KWin