当更好的显示适得其反:在 Hyprland 中修复‘blurry’ VLC
Source: Dev.to
背景
要理解为什么一个普通的视频播放器会显得模糊,我们需要一些技术背景。
1. HiDPI(高像素密度)显示器
- 物理现实: 传统屏幕的像素密度大约是 96 PPI。一个 50 像素的按钮大约只有半英寸宽。现代屏幕在相同的物理空间内大约塞进了两倍的像素。
- 逻辑像素 vs. 物理像素: 当 Qt 在 HiDPI 屏幕上绘制同样的 50 像素按钮时,它在物理上会非常小(≈ ¼ 英寸)。为了显示正常,Qt 必须渲染一个 100 像素的按钮。
- 缩放因子: 系统会应用一个缩放因子(例如 200 %),使每个逻辑像素映射到两个物理像素。这样无论像素密度如何,界面都保持可读且清晰。
2. Qt
Qt 是 VLC 用来构建界面的框架。它的主要工作是 光栅化。
什么是光栅化?
把蓝图和照片作对比。
- 蓝图(矢量): UI 以数学方式描述,例如 “绘制一个半径为 50 单位的完美圆”。这种描述拥有无限分辨率。
- 照片(光栅): 为了在屏幕上显示 UI,Qt 将数学描述转换为一张由彩色点(像素)组成的网格。这一过程就是光栅化。
光栅化完成后,Qt 会把结果存入 图形缓冲区——本质上是 RAM 中的一张位图——并将其交给显示服务器,以便在屏幕上呈现。

3. 显示服务器
显示服务器位于应用程序(客户端)和硬件(内核/GPU)之间。它的职责是接收所有打开的应用程序提供的缓冲区(图像),并决定它们在物理屏幕上的具体位置。
4. 协议:X11 与 Wayland
这些是定义应用程序如何与显示硬件通信的标准。
X11
- 诞生于 1980 年代的网络透明协议。
- 需要三个独立的组件:
- 客户端(应用): 请求绘制窗口。
- X 服务器(显示服务器): 一个“愚蠢”的中间人,控制硬件但不负责窗口布局逻辑。
- 窗口管理器: 决定窗口放置位置。
- 由于 X11 协议禁止显示服务器做出策略决定(如窗口放置),每一次操作都涉及三方对话(App ↔ Server ↔ WM)。
- X11 依赖 全局坐标空间——所有屏幕共享同一个统一画布。所有应用必须对该网格的比例保持一致。当同时使用 HiDPI 与普通 DPI 显示器时,X11 难以只对画布的部分进行伸缩。
- DPI 感知是系统范围的(例如
Xft.dpi),而许多旧应用会忽略它,使得每屏幕独立缩放变得困难。
Wayland
- 旨在消除 X11 的低效之处。
- “显示服务器” 与 “窗口管理器” 合并为一个叫 合成器(本例中为 Hyprland)的软件组件。
- 直接控制: 客户端自行分配缓冲区并直接交给合成器。
- 隔离: 每个应用拥有自己的独立 surface(一张私有的纸)。合成器可以把一个 surface 按 2× 缩放,而保持另一个 surface 为 1×,从而提供每窗口的灵活性——这正是现代 HiDPI 屏幕所需的。
- Wayland 对 HiDPI 的处理是无缝的——合成器可以显式告知每个 surface 如何缩放,根本不需要全局 DPI 设置。
5. 桥梁:XWayland
X11 作为标准已经存在了超过 30 年。成千上万的应用(如旧游戏、Steam 以及 VLC 3.0)只会使用 X11 协议。由于标准的 X11 应用无法通过 Wayland 协议通信,XWayland 充当了翻译层。它是一个完整功能的 X 服务器,运行在你的 Wayland 会话内部。
- 对应用(VLC)而言: XWayland 看起来就是普通的 X 服务器。
- 对合成器(Hyprland)而言: XWa
yland 看起来像是单个应用窗口。
但这会导致一个问题。XWayland 应用继承了 X11 的缩放限制——它们无法从 Wayland 合成器接收每窗口的缩放指令。这迫使 Hyprland 做出妥协:
- 让它们以原生 1× 分辨率渲染(清晰但非常小)。
- 使用
xwayland:force_zero_scaling将它们放大(尺寸可读但模糊)。
Hyprland 的 xwayland:force_zero_scaling 设置(默认启用)选择了第二种方案:它告诉 XWayland 应用它们正运行在低 DPI 显示器上,然后对其输出进行放大。结果是文字可读,但会出现模糊——因为应用以 1× 渲染,认为自己在标准显示器上,而 Hyprland 将这些像素拉伸以适配你的 HiDPI 屏幕。
问题与解决方案
VLC 3.0 缺乏原生 Wayland 支持,因此会回退到 XWayland。这会导致缩放问题:VLC 3.0 忽略 X11 的 DPI 提示,按原生 1× 分辨率渲染。当 Hyprland 的 xwayland:force_zero_scaling 被禁用(默认设置)时,它会放大 VLC 的 1× 输出,导致画面模糊。
步骤 1 – 在 Hyprland 中禁用强制缩放
在你的 Hyprland 配置文件中添加以下内容:
xwayland {
force_zero_scaling = true
}
结果: VLC 渲染清晰——但非常小。
步骤 2 – 告诉 Qt 按 2× 缩放
完全绕过 X11 的 DPI 系统,使用 Qt 的缩放因子启动 VLC:
QT_SCALE_FACTOR=2 vlc
结果: VLC 会遵循 Qt 的环境变量,在内部以 2× 渲染 UI,并且因为已禁用强制缩放,Hyprland 不会再次对其进行缩放——从而得到清晰、尺寸合适的文字。
结束语
这段旅程让我有机会更好地了解 Linux GUI 生态系统。我仍在学习 Linux 图形栈的细节(这是一条深不见底的兔子洞!)。如果我对任何架构细节过于简化,或者您知道在 Hyprland 中处理此事的更简洁方式,我很乐意听取您的反馈。欢迎随时联系或纠正我!