/* SPDX-FileCopyrightText: 2010 Fredrik Höglund SPDX-FileCopyrightText: 2018 Alex Nemeth SPDX-License-Identifier: GPL-2.0-or-later */ #pragma once #include "effect/effect.h" #include "opengl/glutils.h" #include "scene/item.h" #include #include namespace KWin { class BlurManagerInterface; struct BlurRenderData { /// Temporary render targets needed for the Dual Kawase algorithm, the first texture /// contains not blurred background behind the window, it's cached. std::vector> textures; std::vector> framebuffers; }; struct BlurEffectData { /// The region that should be blurred behind the window std::optional content; /// The region that should be blurred behind the frame std::optional frame; /// The render data per screen. Screens can have different color spaces. std::unordered_map render; ItemEffect windowEffect; }; class BlurEffect : public KWin::Effect { Q_OBJECT public: BlurEffect(); ~BlurEffect() override; static bool supported(); static bool enabledByDefault(); void reconfigure(ReconfigureFlags flags) override; void prePaintScreen(ScreenPrePaintData &data, std::chrono::milliseconds presentTime) override; void prePaintWindow(EffectWindow *w, WindowPrePaintData &data, std::chrono::milliseconds presentTime) override; void drawWindow(const RenderTarget &renderTarget, const RenderViewport &viewport, EffectWindow *w, int mask, const QRegion ®ion, WindowPaintData &data) override; bool provides(Feature feature) override; bool isActive() const override; int requestedEffectChainPosition() const override { return 20; } bool eventFilter(QObject *watched, QEvent *event) override; bool blocksDirectScanout() const override; public Q_SLOTS: void slotWindowAdded(KWin::EffectWindow *w); void slotWindowDeleted(KWin::EffectWindow *w); void slotScreenRemoved(KWin::Output *screen); #if KWIN_BUILD_X11 void slotPropertyNotify(KWin::EffectWindow *w, long atom); #endif void setupDecorationConnections(EffectWindow *w); private: void initBlurStrengthValues(); QRegion blurRegion(EffectWindow *w) const; QRegion decorationBlurRegion(const EffectWindow *w) const; bool decorationSupportsBlurBehind(const EffectWindow *w) const; bool shouldBlur(const EffectWindow *w, int mask, const WindowPaintData &data) const; void updateBlurRegion(EffectWindow *w); void blur(const RenderTarget &renderTarget, const RenderViewport &viewport, EffectWindow *w, int mask, const QRegion ®ion, WindowPaintData &data); GLTexture *ensureNoiseTexture(); private: struct { std::unique_ptr shader; int mvpMatrixLocation; int offsetLocation; int halfpixelLocation; } m_downsamplePass; struct { std::unique_ptr shader; int mvpMatrixLocation; int offsetLocation; int halfpixelLocation; } m_upsamplePass; struct { std::unique_ptr shader; int mvpMatrixLocation; int noiseTextureSizeLocation; int texStartPosLocation; std::unique_ptr noiseTexture; qreal noiseTextureScale = 1.0; int noiseTextureStength = 0; } m_noisePass; bool m_valid = false; #if KWIN_BUILD_X11 long net_wm_blur_region = 0; #endif QRegion m_paintedArea; // keeps track of all painted areas (from bottom to top) QRegion m_currentBlur; // keeps track of the currently blured area of the windows(from bottom to top) Output *m_currentScreen = nullptr; size_t m_iterationCount; // number of times the texture will be downsized to half size int m_offset; int m_expandSize; int m_noiseStrength; struct OffsetStruct { float minOffset; float maxOffset; int expandSize; }; QList blurOffsets; struct BlurValuesStruct { int iteration; float offset; }; QList blurStrengthValues; QMap windowBlurChangedConnections; std::unordered_map m_windows; static BlurManagerInterface *s_blurManager; static QTimer *s_blurManagerRemoveTimer; }; inline bool BlurEffect::provides(Effect::Feature feature) { if (feature == Blur) { return true; } return KWin::Effect::provides(feature); } } // namespace KWin