File indexing completed on 2024-06-09 05:25:54

0001 /*
0002     SPDX-FileCopyrightText: 2010 Fredrik Höglund <fredrik@kde.org>
0003     SPDX-FileCopyrightText: 2018 Alex Nemeth <alex.nemeth329@gmail.com>
0004 
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 #pragma once
0009 
0010 #include "effect/effect.h"
0011 #include "opengl/glutils.h"
0012 
0013 #include <QList>
0014 
0015 #include <unordered_map>
0016 
0017 namespace KWin
0018 {
0019 
0020 class BlurManagerInterface;
0021 
0022 struct BlurRenderData
0023 {
0024     /// Temporary render targets needed for the Dual Kawase algorithm, the first texture
0025     /// contains not blurred background behind the window, it's cached.
0026     std::vector<std::unique_ptr<GLTexture>> textures;
0027     std::vector<std::unique_ptr<GLFramebuffer>> framebuffers;
0028 };
0029 
0030 struct BlurEffectData
0031 {
0032     /// The region that should be blurred behind the window
0033     std::optional<QRegion> content;
0034 
0035     /// The region that should be blurred behind the frame
0036     std::optional<QRegion> frame;
0037 
0038     /// The render data per screen. Screens can have different color spaces.
0039     std::unordered_map<Output *, BlurRenderData> render;
0040 };
0041 
0042 class BlurEffect : public KWin::Effect
0043 {
0044     Q_OBJECT
0045 
0046 public:
0047     BlurEffect();
0048     ~BlurEffect() override;
0049 
0050     static bool supported();
0051     static bool enabledByDefault();
0052 
0053     void reconfigure(ReconfigureFlags flags) override;
0054     void prePaintScreen(ScreenPrePaintData &data, std::chrono::milliseconds presentTime) override;
0055     void prePaintWindow(EffectWindow *w, WindowPrePaintData &data, std::chrono::milliseconds presentTime) override;
0056     void drawWindow(const RenderTarget &renderTarget, const RenderViewport &viewport, EffectWindow *w, int mask, const QRegion &region, WindowPaintData &data) override;
0057 
0058     bool provides(Feature feature) override;
0059     bool isActive() const override;
0060 
0061     int requestedEffectChainPosition() const override
0062     {
0063         return 20;
0064     }
0065 
0066     bool eventFilter(QObject *watched, QEvent *event) override;
0067 
0068     bool blocksDirectScanout() const override;
0069 
0070 public Q_SLOTS:
0071     void slotWindowAdded(KWin::EffectWindow *w);
0072     void slotWindowDeleted(KWin::EffectWindow *w);
0073     void slotScreenRemoved(KWin::Output *screen);
0074     void slotPropertyNotify(KWin::EffectWindow *w, long atom);
0075     void setupDecorationConnections(EffectWindow *w);
0076 
0077 private:
0078     void initBlurStrengthValues();
0079     QRegion blurRegion(EffectWindow *w) const;
0080     QRegion decorationBlurRegion(const EffectWindow *w) const;
0081     bool decorationSupportsBlurBehind(const EffectWindow *w) const;
0082     bool shouldBlur(const EffectWindow *w, int mask, const WindowPaintData &data) const;
0083     void updateBlurRegion(EffectWindow *w);
0084     void blur(const RenderTarget &renderTarget, const RenderViewport &viewport, EffectWindow *w, int mask, const QRegion &region, WindowPaintData &data);
0085     GLTexture *ensureNoiseTexture();
0086 
0087 private:
0088     struct
0089     {
0090         std::unique_ptr<GLShader> shader;
0091         int mvpMatrixLocation;
0092         int offsetLocation;
0093         int halfpixelLocation;
0094     } m_downsamplePass;
0095 
0096     struct
0097     {
0098         std::unique_ptr<GLShader> shader;
0099         int mvpMatrixLocation;
0100         int offsetLocation;
0101         int halfpixelLocation;
0102     } m_upsamplePass;
0103 
0104     struct
0105     {
0106         std::unique_ptr<GLShader> shader;
0107         int mvpMatrixLocation;
0108         int noiseTextureSizeLocation;
0109         int texStartPosLocation;
0110 
0111         std::unique_ptr<GLTexture> noiseTexture;
0112         qreal noiseTextureScale = 1.0;
0113         int noiseTextureStength = 0;
0114     } m_noisePass;
0115 
0116     bool m_valid = false;
0117     long net_wm_blur_region = 0;
0118     QRegion m_paintedArea; // keeps track of all painted areas (from bottom to top)
0119     QRegion m_currentBlur; // keeps track of the currently blured area of the windows(from bottom to top)
0120     Output *m_currentScreen = nullptr;
0121 
0122     size_t m_iterationCount; // number of times the texture will be downsized to half size
0123     int m_offset;
0124     int m_expandSize;
0125     int m_noiseStrength;
0126 
0127     struct OffsetStruct
0128     {
0129         float minOffset;
0130         float maxOffset;
0131         int expandSize;
0132     };
0133 
0134     QList<OffsetStruct> blurOffsets;
0135 
0136     struct BlurValuesStruct
0137     {
0138         int iteration;
0139         float offset;
0140     };
0141 
0142     QList<BlurValuesStruct> blurStrengthValues;
0143 
0144     QMap<EffectWindow *, QMetaObject::Connection> windowBlurChangedConnections;
0145     std::unordered_map<EffectWindow *, BlurEffectData> m_windows;
0146 
0147     static BlurManagerInterface *s_blurManager;
0148     static QTimer *s_blurManagerRemoveTimer;
0149 };
0150 
0151 inline bool BlurEffect::provides(Effect::Feature feature)
0152 {
0153     if (feature == Blur) {
0154         return true;
0155     }
0156     return KWin::Effect::provides(feature);
0157 }
0158 
0159 } // namespace KWin