从零自绘 Wayland 合成器要面对哪些取舍

自绘 Wayland 合成器的核心取舍在于,你要自己承担客户端内容合成、输出管理与协议实现这三件事的复杂度,换来对渲染路径和交互细节的完全控制。走现成库的路线,Smithay 和 wlroots 代表两种抽象程度,前者给你渲染与后端构件,把会话与外壳逻辑留给你,后者提供更成型的骨架。是否值得自绘,取决于产品是否需要独一份的视觉与交互效果。

合成器到底要负责哪些事

合成器的中心职责是把各客户端送来的图形缓冲区合成为一帧,再提交给显示硬件。围绕这一步还有大量配套工作。它要通过 udev 发现显卡与输入设备,通过 libinput 接收事件,通过会话管理在 TTY 切换时释放设备。它要实现 xdg-shell 这类核心协议让应用能创建窗口,也要处理 wl_drm 与 linux_dmabuf 让客户端走硬件加速路径,还要管理输出、缩放与刷新率、输入焦点。Smithay 的文档把后端分成会话管理、输入处理、图形三块,并说明合成客户端内容最复杂。这些工作与视觉设计无关,却占了自研工程量的大头。

Smithay 和 wlroots 抽象层次差在哪

两者的选择直接影响你后面要写多少代码。

  • Smithay 提供 allocator 与 renderer 两组核心抽象,前者分配和转换图形缓冲区,后者负责渲染,具体实现目前以 GBM 与 OpenGL ES 2 为主。它把外壳逻辑留给使用方,适合要做独特交互的项目。
  • Smithay 还提供 DRM、EGL、libinput、udev、session 等模块,各自用 cargo feature 开关,可以只取需要的部分。
  • 它还带 X11 与 winit 两个后端,方便把合成器当普通客户端运行来调试,文档建议优先用 X11,因为 winit 与事件循环集成得不够好。
  • wlroots 提供更接近成品的骨架,协议实现更齐全,代价是渲染与布局的可定制空间更小。
  • 已有基于 Smithay 的自绘项目走通了这条路,它们的 backend 目录同时保留 KMS、winit、X11 三种后端与独立的 render 模块,这种结构值得参考。

渲染路径上的实际选择

渲染器决定你能否用上硬件加速,也决定合成一帧的开销。走 OpenGL ES 2 最成熟,生态支持最广,缺点是某些平台性能上限不高。走 Vulkan 能拿到更细的控制,Smithay 也有模块,但驱动与设备兼容性要多花时间验证。纯 CPU 的 pixman 路径实现简单,适合调试和不追求性能的场景。另一条路线是让客户端共享缓冲区,通过 dma-buf 把渲染结果零拷贝交给合成器,避免一次显存到内存的往返。Smithay 文档指出,即便客户端使用 dma-buf,通常也要先初始化 wl_drm 设施。

多输出与缩放怎么处理

多显示器的复杂度来自几处。每个输出有独立刷新率与时序,合成循环要按最慢的那个同步,否则会撕裂或抖动。缩放比例不同意味着同一份缓冲区要在不同输出上以不同分辨率呈现,分数缩放尤其麻烦,常见做法是先按整数倍渲染再缩放。输出热插拔要求合成器在运行中重建渲染目标并重绑主循环资源。Smithay 提供多 GPU 模块,跨显卡输出要显式处理缓冲区复制。

自己写还是用现成方案

按顺序过一遍下面几个问题,答案决定路线。

  1. 产品是否需要现成合成器无法表达的交互与视觉,比如非常规的窗口组织方式。
  2. 团队是否具备处理 DRM、EGL、DMA 缓冲区这些底层问题的经验,出问题能否定位到内核与驱动的边界。
  3. 能否接受协议实现长期滞后于标准演进,并有人力持续跟进。

三个问题里只有一个肯定,用现成合成器做外壳扩展通常更划算。

常见问题

问,自绘合成器能不能只在 Wayland 上跑。多数项目保留 X11 后端用于开发和调试,可以在已有桌面的机器上直接运行。

问,输入法支持是不是要自己写。文本输入协议由合成器侧实现,输入法框架接入要额外投入。

问,用 Rust 写会不会有生态缺口。底层系统库绑定要自己维护,这是 Rust 桌面项目的普遍投入。