4. 核心概念
Wayland 协议本身只定义“客户端与合成器如何对话”,真正决定画面长什么样、输入落到哪里、窗口如何被管理的,是一组核心对象。理解这些对象之间的职责边界,是排查多屏座舱显示问题的前提。本节把它们放在同一条渲染与输入链路上讲解,而不是孤立地背名词。
一、渲染链路:buffer → surface → region → output
wl_buffer 是最底层的像素容器,它描述一块共享内存或 GPU 纹理的格式、宽高与步幅。客户端把绘制结果写入 buffer,然后通过 wl_surface.attach 把 buffer 挂到 surface 上,再用 commit 提交。合成器收到 commit 后,才真正把这块 buffer 合成到屏幕上。
wl_surface 是客户端可见的“画布”,它本身不持有像素,只持有当前挂载的 buffer、变换、缩放和损坏区域。多屏场景下,同一个 surface 可能被合成器映射到不同 output,因此 surface 的坐标是逻辑坐标,最终由合成器结合 output 的缩放与变换换算成物理像素。
wl_region 表示 surface 上的一个矩形集合,常用于 set_opaque_region 和 set_input_region。前者告诉合成器“这块区域不透明,可以跳过下层绘制”,后者决定“哪些区域能接收输入”。在座舱中,仪表盘中央的圆形表盘常配合 region 做输入裁剪,避免透明角落误触。
wl_output 代表一个物理或虚拟显示输出,携带分辨率、刷新率、缩放、物理尺寸与变换信息。多屏座舱里,中控屏、仪表屏、副驾屏各自对应一个 output,合成器负责把 surface 分配到合适的 output 上。
二、输入链路:seat 与 surface 的绑定
wl_seat 是输入能力的集合,一个 seat 可以包含键盘、指针、触摸等 capability。客户端通过 wl_seat.get_pointer、get_keyboard、get_touch 获取具体设备对象。合成器根据指针位置、焦点策略和 surface 的 input region,决定把事件发给哪个 surface。
多屏座舱中常见“一个 seat 覆盖多屏”或“每屏独立 seat”两种设计。前者适合统一交互,后者适合仪表屏只接受方向盘按键、中控屏只接受触摸的隔离场景。选择哪种,取决于功能安全与交互隔离要求。
三、窗口语义:shell 与 layer-shell 的分工
shell 不是单一协议,而是一类“窗口角色”协议的统称。传统桌面用 xdg-shell 定义顶层窗口、弹出菜单、最大化等语义;座舱中则大量使用 layer-shell,它允许客户端声明自己属于 background、bottom、top、overlay 等层级,并支持锚定到屏幕边缘、设置独占区域。
subsurface 解决的是“同一窗口内部的局部更新”。子 surface 依附于父 surface,可以独立提交 buffer,并支持同步模式,保证父子内容在同一帧生效。视频播放、仪表指针动画常用 subsurface,避免整窗重绘。
| 对象 | 核心职责 | 座舱典型用法 |
|---|---|---|
| wl_buffer | 承载像素与格式 | 仪表帧、视频帧、UI 纹理 |
| wl_surface | 提交与合成单元 | 每个可视窗口或图层 |
| wl_region | 局部不透明/输入区域 | 圆形表盘输入裁剪 |
| wl_output | 显示目标与参数 | 中控屏、仪表屏、副驾屏 |
| wl_seat | 输入能力集合 | 触摸、按键、方向盘输入 |
| shell | 窗口角色与生命周期 | 普通应用窗口 |
| subsurface | 父子局部合成 | 视频层、动画指针 |
| layer-shell | 层级、锚定、独占 | 状态栏、HUD、背景层 |
四、案例与排障:多屏座舱中的典型问题
场景一:仪表屏上的指针动画卡顿。若整窗每帧重绘,带宽与合成开销都高。改用 subsurface 只提交指针区域,并配合 region 标记不透明区,可显著降低负载。
场景二:中控屏弹出菜单被状态栏遮挡。这通常是层级问题:状态栏使用 layer-shell 的 top 层,而菜单属于 xdg-shell 顶层窗口。需要调整 layer-shell 层级或让菜单使用 overlay 层。
场景三:触摸点落在透明区域却触发按钮。检查 set_input_region 是否设置正确,透明区域应排除在输入区域之外。
wayland-info 查看 output 与 seat 能力,用合成器日志确认 surface 被分配到哪个 output,再核对 region 与 layer 层级。先定位对象,再定位协议调用,最后才怀疑渲染性能。
# 查看 Wayland 输出与输入能力
wayland-info | grep -A5 "wl_output"
wayland-info | grep -A5 "wl_seat"
# 合成器日志中观察 surface 与 layer 分配
journalctl -u compositor --since "5 min ago" | grep -i "surface\|layer"
把这八个对象串起来看:buffer 提供像素,surface 负责提交,region 做局部裁剪,output 决定显示目标,seat 提供输入,shell 与 layer-shell 决定窗口语义与层级,subsurface 处理窗口内部的局部合成。多屏座舱的绝大多数显示与交互问题,都可以沿这条链路逐段定位。