kwin模糊度代码解读

本篇文档主要讲述kwin绘制模糊特效的流程,和相关函数的理解注释。

相关文件和函数

src/plugins/windowsystem/windoweffects.cpp

        主要进行窗口的查询和窗口属性的设置。

// 启用或禁用窗口模糊效果,根据给定的窗口ID、启用标志和区域,启用或禁用窗口的模糊效果。
// window 窗口ID
// enable 是否启用模糊效果
// region 模糊效果的区域
void WindowEffects::enableBlurBehind(WId window, bool enable, const QRegion &region)

/**
 * @brief 查找窗口 根据给定的窗口标识符,在应用程序中查找对应的窗口对象。
 *  win 窗口标识符
 * @return 找到的窗口对象指针,若未找到则返回 nullptr
 */
QWindow *findWindow(WId win)

qApp->allWindows() 这个调用是访问 QApplication 类的 allWindows() 成员函数。这个函数的目的是返回当前应用程序中所有顶级窗口的列表。
allWindows() 函数返回一个 QList 类型的列表,其中包含了指向所有顶级窗口的指针。但是KWin 的 qApp 上下文特殊性:KWin 的 
qApp->allWindows() 可能返回的不是普通应用程序的窗口,而是 KWin 所有的“管理”对象。
这些对象代表了整个系统中的窗口,而不仅仅是 KWin 自己创建的窗口。
这是因为 KWin 作为窗口管理器,掌握了所有应用程序窗口的句柄和信息,
而这些窗口都可以在 KWin 的 Qt 上下文中表现为顶级窗口。

src/effects/blur/blur.cpp

        监听窗口属性变化,然后进行着色器、纹理的绘制模糊背景。

/**
 * @brief 事件过滤器
 * 当指定对象触发事件时,通过此函数进行事件过滤。
 * @param watched 被观察的对象指针 如果watched确实是一个QWindow对象
 * @param event 事件指针 并且发生的事件是QEvent::DynamicPropertyChange
 * @return 如果事件被处理则返回 true,否则返回 false

将事件对象event强制转换为QDynamicPropertyChangeEvent类型,以便访问事件的属性名。
然后,检查发生变化的属性名是否为"kwin_blur"。如果是,代码尝试在effects中找到与
internal(即当前QWindow)对应的窗口对象。如果找到了,就调用updateBlurRegion函数来更新该窗口的模糊区域。
 */
bool BlurEffect::eventFilter(QObject *watched, QEvent *event)

/**
 * @brief 更新模糊区域  更新需要模糊的区域,绘制不再这里
 * 根据给定的 EffectWindow 对象,更新其对应的模糊区域。
 * @param w EffectWindow 对象的指针
 
如果窗口w有内部窗口(w->internalWindow()),并且这个内部窗口有kwin_blur属性,则尝试从这个属性中获取QRegion类型的值,并更新region和valid。
如果valid为true,则将窗口w与当前的region关联起来,存储在blurRegions映射中。这个映射可能用于跟踪每个窗口的模糊区域,以便后续应用模糊效果。
如果valid为false,则从blurRegions映射中移除与窗口w相关的条目,表示该窗口当前没有有效的模糊区域。
 */
void BlurEffect::updateBlurRegion(EffectWindow *w)

/**
 * @brief 构造函数
 * 初始化 BlurEffect 对象,执行相关配置和初始化操作。
 
  创建BlurConfig 的实例;
  创建着色器实例,实例创建成功后,调用initBlurStrengthValues()和reconfigure(ReconfigureAll)函数;
  如果着色器和纹理都是有效的,则获取当前是xcb 还是wayland 针对不同环境进行相对应初始化操作;
  监听窗口增加、删除、内饰改变、属性通知、虚拟桌面改变和xcb连接变化,作相应的功能处理;
  net_wm_blur_region xcb初始化,如果xcb连接变化,也会更新net_wm_blur_region;
  遍历所有窗口作处理。
 */
BlurEffect::BlurEffect()

/**
 * @brief 初始化模糊强度值
 * 创建一个均匀分布的模糊强度值数组。
 */
void BlurEffect::initBlurStrengthValues()

/**
 * @brief 重新配置模糊效果
 * 根据给定的重新配置标志,重新配置模糊效果。
 * @param flags 重新配置标志
 
 读取创建的模糊强度值数组的内容,然后更新纹理,通过调用effects的addRepaintFull方法,请求对所有窗口进行完整重绘,以确保新的模糊效果能够立即生效。
 */
void BlurEffect::reconfigure(ReconfigureFlags flags)

/**
 * @brief 更新纹理
 * 该函数用于更新模糊效果的纹理。
 * 在函数执行过程中,首先删除之前创建的帧缓冲对象。然后为原始尺寸的纹理、下采样纹理以及辅助纹理预留内存空间。
 * 接着,根据默认帧缓冲的颜色编码设置纹理格式。如果默认帧缓冲的颜色编码为SRGB,则使用SRGB8_ALPHA8作为纹理格式。
 * 接下来,根据屏幕大小和下采样迭代次数创建一系列纹理和帧缓冲对象,并将它们添加到对应的容器中。
 * 最后一个纹理作为临时辅助纹理。
 * 然后,标记渲染目标的有效性,并清空渲染目标栈,为渲染准备栈空间。
 * 之后,根据下采样迭代次数,将部分渲染目标推入栈中,用于后续的渲染过程。
 * 最后,将第一个渲染目标推入栈中,并重置噪声纹理。
 */
void BlurEffect::updateTexture()

/**
 * @brief 窗口添加时的槽函数
 * 当添加新的 EffectWindow 时,会调用此槽函数。
 * @param w EffectWindow 指针,表示添加的窗口
 
 安装事件过滤器 更新装饰 和窗口的模糊背景
 */
void BlurEffect::slotWindowAdded(EffectWindow *w)

/**
 * @brief 设置装饰连接
 * 为指定的 EffectWindow 对象设置装饰连接,当装饰的模糊区域发生变化时,会触发更新模糊区域的操作。
 * @param w EffectWindow 对象指针
 */
void BlurEffect::setupDecorationConnections(EffectWindow *w)

/**
 * @brief 窗口被删除时的槽函数
 * 当指定的窗口对象被删除时,从模糊区域列表中移除该窗口,并断开与窗口模糊变化信号的连接。
 * @param w 窗口对象指针
 */
void BlurEffect::slotWindowDeleted(EffectWindow *w)

/**
 * @brief 槽函数:属性通知
 * 当窗口的属性发生变化时,该函数会被调用。
 * @param w 窗口指针
 * @param atom 属性原子
 
 会根据窗口不为空,且atom等于net_wm_blur_region,且net_wm_blur_region不为空,才会更新模糊区域
 */
void BlurEffect::slotPropertyNotify(EffectWindow *w, long atom)

/**
 * @brief 槽函数:屏幕几何形状改变时触发
 * 当屏幕几何形状改变时,此槽函数将被调用。
 * 该函数首先确保当前使用的是OpenGL上下文,然后更新纹理。
 * 接着,获取所有窗口的模糊区域,并更新每个窗口的模糊区域。
 * 最后,完成OpenGL上下文的当前操作。
 */
void BlurEffect::slotScreenGeometryChanged()

/**
 * @brief 执行模糊效果
 * 根据给定的形状、屏幕区域、透明度、屏幕投影矩阵以及是否是停靠窗口,执行模糊效果。
 * @param shape 模糊效果的形状区域
 * @param screen 屏幕区域
 * @param opacity 透明度
 * @param screenProjection 屏幕投影矩阵
 * @param isDock 是否是停靠窗口
 * @param windowRect 窗口矩形
 */
void BlurEffect::doBlur(const QRegion &shape, const QRect &screen, const float opacity, const QMatrix4x4 &screenProjection, bool isDock, QRect windowRect)

/**
 * @brief 绘制窗口的模糊效果
 * 在指定的窗口上绘制模糊效果。
 * @param w 窗口指针
 * @param mask 掩码值
 * @param region 区域对象
 * @param data 窗口绘制数据
 */
void BlurEffect::drawWindow(EffectWindow *w, int mask, const QRegion &region, WindowPaintData &data)

/**
 * @brief 判断是否应该应用模糊效果
 * 根据给定的窗口、遮罩和窗口绘制数据,判断是否应该应用模糊效果。
 * @param w 指向 EffectWindow 对象的指针,表示窗口
 * @param mask 遮罩值
 * @param data 窗口绘制数据
 * @return 如果应该应用模糊效果则返回 true,否则返回 false
 
 这个函数通过检查渲染目标、着色器、全屏效果、窗口类型以及窗口的缩放和平移等条件,来决定是否应该对给定的窗口应用模糊效果。
 如果窗口没有进行有效的渲染设置、正在被全屏效果覆盖、是桌面窗口、或者进行了缩放或平移且没有强制要求模糊,则不会应用模糊效果。
 */
bool BlurEffect::shouldBlur(const EffectWindow *w, int mask, const WindowPaintData &data) const

/**
 * @brief 上传几何数据
 * 将给定的模糊区域和窗口区域上传到给定的顶点缓冲区中。
 * @param vbo 顶点缓冲区指针
 * @param blurRegion 模糊区域
 * @param windowRegion 窗口区域
 *
 * @return 上传是否成功,成功返回 true,失败返回 false
 */
bool BlurEffect::uploadGeometry(GLVertexBuffer *vbo, const QRegion &blurRegion, const QRegion &windowRegion)

/**
 * @brief 上传区域
 * 将指定的区域进行下采样处理,并将处理后的顶点坐标上传至给定的地图指针中。
 * @param map 地图指针的引用
 * @param region 指定的区域
 * @param downSampleIterations 下采样迭代次数
 */
void BlurEffect::uploadRegion(QVector2D *&map, const QRegion &region, const int downSampleIterations)

/**
 * @brief 获取模糊区域
 * 根据给定的 EffectWindow 对象,获取其对应的模糊区域。
 * @param w EffectWindow 对象指针
 * @return 模糊区域
 */
QRegion BlurEffect::blurRegion(const EffectWindow *w) const

/**
 * @brief 判断窗口装饰是否支持背景模糊效果
 * 判断给定的 EffectWindow 对象是否支持背景模糊效果。
 * @param w EffectWindow 对象指针
 * @return 如果窗口装饰支持背景模糊效果,则返回 true;否则返回 false
 */
bool BlurEffect::decorationSupportsBlurBehind(const EffectWindow *w) const

/**
 * @brief 预处理窗口绘制前的模糊效果
 * 在窗口绘制前,预处理模糊效果。该效果依赖于 `prePaintWindow` 方法按从下到上的顺序调用。
 * @param w 窗口指针
 * @param data 窗口预绘制数据引用
 * @param presentTime 当前呈现时间
 
 目的是在窗口的预绘制阶段管理和优化模糊效果的绘制,确保模糊效果能够正确地应用于需要模糊的区域,并且不会不必要地重绘其他区域。
 */
void BlurEffect::prePaintWindow(EffectWindow *w, WindowPrePaintData &data, std::chrono::milliseconds presentTime)

/**
 * @brief 对纹理进行下采样
 * 使用给定的顶点缓冲区对象对纹理进行下采样处理。
 * @param vbo 顶点缓冲区对象指针
 * @param blurRectCount 模糊矩形数量
 */
void BlurEffect::downSampleTexture(GLVertexBuffer *vbo, int blurRectCount)

/**
 * @brief 复制屏幕采样纹理
 * 将屏幕采样纹理复制到指定的顶点缓冲区对象中,并根据模糊矩形数量和形状进行模糊处理。
 * @param vbo 顶点缓冲区对象指针
 * @param blurRectCount 模糊矩形数量
 * @param blurShape 模糊形状区域
 * @param screenProjection 屏幕投影矩阵
 */
void BlurEffect::copyScreenSampleTexture(GLVertexBuffer *vbo, int blurRectCount, QRegion blurShape, const QMatrix4x4 &screenProjection)

/**
 * @brief 对纹理进行上采样
 * 对给定的纹理进行上采样处理。
 * @param vbo 顶点缓冲区对象指针
 * @param blurRectCount 模糊矩形数量
 */
void BlurEffect::upSampleTexture(GLVertexBuffer *vbo, int blurRectCount)

/**
 * @brief 将模糊效果渲染到屏幕上
 * 将指定的模糊效果渲染到屏幕上,使用给定的顶点缓冲区对象(VBO)进行绘制。
 * @param vbo 顶点缓冲区对象指针
 * @param vboStart 起始的顶点索引
 * @param blurRectCount 模糊矩形的数量
 * @param screenProjection 屏幕投影矩阵
 * @param windowPosition 窗口位置
 */
void BlurEffect::upscaleRenderToScreen(GLVertexBuffer *vbo, int vboStart, int blurRectCount, const QMatrix4x4 &screenProjection, QPoint windowPosition)

/**
 * @brief 应用噪声效果
 * 在给定的顶点缓冲区对象上应用噪声效果。
 * @param vbo 顶点缓冲区对象指针
 * @param vboStart 顶点缓冲区对象起始索引
 * @param blurRectCount 模糊矩形数量
 * @param screenProjection 屏幕投影矩阵
 * @param windowPosition 窗口位置
 */
void BlurEffect::applyNoise(GLVertexBuffer *vbo, int vboStart, int blurRectCount, const QMatrix4x4 &screenProjection, QPoint windowPosition)

 

src/effects/blur/blurshader.cpp

        模糊背景着色器的创建,偏移位置,都是着色器相关的处理。

/**
 * @brief 构造函数
 * 初始化 BlurShader 对象,并加载所需的着色器。
 * @param parent 父对象指针
 
 确保在静态链接的情况下将资源链接到最终的应用程序二进制文件中;
 调用ShaderManager::instance()->generateShaderFromFile 创建着色器,创建出下采样、上采样、复制和噪声四种
 然后设置着色到渲染上下文中
 */
BlurShader::BlurShader(QObject *parent)

 

src/libkwineffects/kwinglutils.cpp

        着色器设置和配置的功能,以及生成着色器

/**
 * @brief 从文件中生成着色器
 * 根据给定的着色器特性、顶点着色器文件和片段着色器文件,从文件中生成着色器。
 * @param traits 着色器特性
 * @param vertexFile 顶点着色器文件路径
 * @param fragmentFile 片段着色器文件路径
 * @return 生成的着色器对象的智能指针
 */
 std::unique_ptr<GLShader> ShaderManager::generateShaderFromFile(ShaderTraits traits, const QString &vertexFile, const QString &fragmentFile)
 
 /**
 * @brief 获取着色器统一变量的位置
 * 通过给定的统一变量名称,在着色器程序中获取其位置。
 * @param name 统一变量名称
 * @return 返回统一变量的位置,如果未找到则返回-1
 */
 int GLShader::uniformLocation(const char *name)
 
 /**
 * @brief 向 ShaderManager 中添加着色器
 * 将指定的着色器添加到 ShaderManager 中,并返回该着色器的指针。
 * @param traits 着色器特性
 * @return 指向添加的着色器的指针
 */
 GLShader *ShaderManager::pushShader(ShaderTraits traits)
 
 /**
 * @brief 设置矩阵类型的统一变量
 * 将指定的矩阵类型的统一变量设置为给定的矩阵值。
 * @return 设置是否成功,成功返回true,失败返回false
 */
 bool GLShader::setUniform...存在多个重载函数

 

src/effects/blur/blur_config.cpp

        代码简单,主要对配置文件的处理。

 

src/effects.cpp

        找到对应的窗口并返回。

/**
 * @brief 查找窗口
 * 在 EffectsHandlerImpl 中查找给定的 QWindow 对应的 EffectWindow。
 * @param w 要查找的 QWindow 指针
 * @return 如果找到对应的 EffectWindow,则返回其指针;否则返回 nullptr
 */
EffectWindow *EffectsHandlerImpl::findWindow(QWindow *w) const

/**
 * @brief 添加全屏重绘
 * 在 EffectsHandlerImpl 类中,调用此方法将在场景中添加全屏重绘操作。
 */
void EffectsHandlerImpl::addRepaintFull()

/**
 * @brief 获取 xcb 连接
 * 返回一个指向 xcb 连接对象的指针。
 * @return xcb 连接对象的指针
 */
inline xcb_connection_t *EffectsHandlerImpl::xcbConnection() const

/**
 * @brief 宣布支持属性
 * 在 EffectsHandlerImpl 类中,宣布对给定属性名称的支持,并返回该属性的 xcb_atom_t 标识符。
 * @param propertyName 属性名称
 * @param effect 效果指针
 * @return 属性的 xcb_atom_t 标识符
 */
xcb_atom_t EffectsHandlerImpl::announceSupportProperty(const QByteArray &propertyName, Effect *effect)

/**
 * @brief 读取窗口属性
 * 从给定的窗口中读取指定的属性,并将其作为字节数组返回。
 * @param atom 属性原子
 * @param type 属性类型
 * @param format 格式
 * @return 字节数组,包含读取到的窗口属性;如果读取失败,则返回空字节数组
 */
QByteArray EffectWindowImpl::readProperty(long atom, long type, int format) const

 

src/workspace.cpp

        关于模糊部分,主要是在查找需要模糊的窗口,下面函数是调用的顺序

/**
 * @brief 在 Workspace 中查找内部窗口
 * 在 Workspace 中查找给定的 QWindow 对应的内部窗口。
 * @param w 要查找的 QWindow 指针
 * @return 如果找到对应的内部窗口,则返回该窗口的指针;否则返回 nullptr
 */
Window *Workspace::findInternal(QWindow *w) const

/**
 * @brief 查找未管理的窗口
 * 在工作空间中查找与给定窗口ID匹配的未管理窗口。
 * @param w 窗口ID
 * @return 返回与给定窗口ID匹配的未管理窗口的指针,若未找到则返回nullptr
 */
Unmanaged *Workspace::findUnmanaged(xcb_window_t w) const

/**
 * @brief 在未管理列表中查找符合条件的未管理对象
 * 根据给定的函数条件,在未管理列表中查找符合条件的未管理对象,并返回该对象的指针。
 * @param func 查找条件函数
 * 查找条件函数,接受一个指向未管理对象的常量指针作为参数,返回一个布尔值表示是否满足条件。
 * @return 符合条件的未管理对象指针
 * 如果找到符合条件的未管理对象,则返回该对象的指针;否则返回 nullptr。
 */
Unmanaged *Workspace::findUnmanaged(std::function<bool(const Unmanaged *)> func) const

 

src/window.h

        查找模糊窗口的最后步骤。

/**
 * @brief 在列表中查找元素
 * 在给定的列表中查找满足指定条件的元素,并返回该元素的指针。
 * @param list 列表
 * @param func 判断函数,用于判断元素是否满足条件
 * @return 若找到满足条件的元素,则返回该元素的指针;否则返回 nullptr。
 * @throw 不抛出异常
 * @note U 必须是从 T 派生的类。
 */
template<class T, class U>
inline T *Window::findInList(const QList<T *> &list, std::function<bool(const U *)> func)

给一个窗口绘制模糊度的流程?

  • 外部调用接口后,发生的设置窗口属性逻辑

 

  • 设置窗口属性后,事件过滤器过滤属性改变事件,并找到对应的窗口,然后更新模糊区域的过程

 

  • 最后绘制的函数,省略了中间部分

 

绘制的详细过程

  • 将区域上传到opengl,根据之前计算出来的区域和模糊数组等,

本文档均为个人理解,如有偏差,感谢纠正。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值