4. Weston合成器入门
Weston 是 Wayland 协议的开源参考合成器(Reference Compositor),由 Wayland 项目维护,承担着窗口管理、输入事件分发、图形缓冲区合成与呈现的核心职责。在车载 Linux 系统中,Weston 不仅是图形显示的“总装车间”,更是连接 GPU/Display Controller、输入设备、应用客户端与系统策略的枢纽。理解 Weston 的架构与启动机制,是后续进行 Wayland 功能定制、性能调优和故障排查的基础。本章将深入拆解 Weston 的模块化架构、插件化后端设计、三种典型后端(headless、DRM、X11)的适用场景,以及从配置文件到进程启动的完整流程。
上图展示了 Weston 的整体架构关系。客户端通过 Wayland 协议与 Weston 核心通信,核心通过后端抽象层适配不同的显示硬件与运行环境。在车载场景中,DRM 后端是量产首选,headless 后端常用于自动化测试,X11 后端则多用于开发阶段的快速验证。
4.1 Weston 核心架构与插件系统
4.1.1 核心原理:libweston 与插件化设计
Weston 自 1.12 版本起将核心逻辑抽取为 libweston 库,这是一个可复用的合成器库,而 Weston 可执行程序只是 libweston 的一个前端实例。这种设计使得 OEM 和 Tier1 供应商可以直接基于 libweston 构建自己的合成器,而不必从零实现 Wayland 协议。libweston 内部包含以下关键模块:
- Compositor 核心:负责场景图(Scene Graph)管理、缓冲区分配与合成调度、输出帧呈现。
- Shell 接口:定义窗口管理策略,包括窗口布局、焦点管理、全屏/分屏逻辑。Weston 默认提供 desktop-shell,车载场景常替换为 custom-shell 或 IVI-Shell。
- Renderer 抽象:支持 pixman(软件渲染)和 GLES2(GPU 硬件渲染)。车载 SoC 通常使用 GLES2 以获得最佳性能。
- Backend 插件:通过动态加载 .so 文件的方式接入不同的显示后端,这是 Weston 最具扩展性的设计之一。
插件系统采用 weston_plugin_api 机制。每个后端插件必须实现 weston_backend 接口,包括初始化、输出创建、输入设备注册等回调函数。Weston 在启动时通过 weston_compositor_load_backend() 动态加载指定插件,并调用其 backend_init() 函数完成初始化。
4.1.2 判断方法:如何选择正确的后端
在车载项目中,选择后端需要根据目标硬件和运行阶段进行判断。下表总结了三种后端的核心差异:
| 后端类型 | 显示输出 | 硬件依赖 | 典型场景 | 性能特征 |
|---|---|---|---|---|
| headless | 无物理输出 | 仅需 CPU 内存 | CI 自动化测试、离屏渲染、远程帧缓冲 | 无 vsync 同步,帧率不受硬件限制 |
| DRM | 直接输出到显示器 | 需要 /dev/dri/card0、GPU 驱动 | 量产车机、仪表盘、中控娱乐 | 支持硬件合成、零拷贝、Page Flip |
| X11 | 通过 X Server 间接输出 | 需要 X11 运行环境 | 开发调试、在 PC 上模拟车载环境 | 多一层拷贝,性能低于 DRM |
判断流程通常如下:
- 确认目标硬件是否有 DRM 节点(
ls /dev/dri/)。若存在 card0 且 GPU 驱动正常,优先选择 DRM 后端。 - 若仅用于单元测试或无需真实显示,选择 headless 后端,配合
weston --backend=headless-backend.so启动。 - 若在开发主机(如 Ubuntu PC)上调试 Wayland 客户端,使用 X11 后端可避免直接操作显卡。
4.1.3 案例拆解:车载仪表盘双屏异显的后端配置
某车载项目使用 NXP i.MX8QM 处理器,需要同时驱动 12.3 英寸仪表屏(1920x720)和 15.6 英寸中控屏(1920x1080)。初始现象是两块屏幕只能克隆显示,无法独立输出不同内容。分析发现 Weston 默认只创建一个输出(Output),需要配置 DRM 后端的多输出支持。
关键操作步骤:
# 1. 检查 DRM 设备节点
ls /dev/dri/
# 输出: card0 card1 (card0 为内嵌DP, card1 为LVDS)
# 2. 在 weston.ini 中配置两个输出
[output]
name=LVDS-1
mode=1920x720@60
transform=normal
[output]
name=DP-1
mode=1920x1080@60
transform=normal
# 3. 启动 Weston 时指定 DRM 后端
weston --backend=drm-backend.so --tty=1 --config=/etc/weston.ini
结果对比:配置前 weston --info 仅显示一个输出;配置后显示两个输出,且可通过 wayland-info 工具看到两个 wl_output 全局对象。风险点在于:若两个屏幕的时序参数(mode)不匹配,可能导致其中一个输出黑屏。复盘经验:在车载多屏场景中,务必为每个输出显式指定 mode,避免 Weston 自动协商失败。
4.1.4 常见误区与总结
weston --renderer=pixman 可以用于 CPU 渲染性能基准测试,但无法反映 GPU 合成能力。误区2:忽略插件 ABI 兼容性。Weston 版本升级后,旧的后端插件 .so 文件可能因 ABI 变化而无法加载,报错
undefined symbol。车载项目应锁定 Weston 版本并同步编译所有插件。
总结:Weston 的插件化架构是其适应多样化车载硬件的关键。理解 libweston 与后端插件的边界,能够帮助工程师快速定位问题——是合成逻辑问题还是后端适配问题。
4.2 后端详解:headless、DRM 与 X11
4.2.1 核心原理:三种后端的实现差异
headless 后端(headless-backend.so)不创建任何物理输出,它使用共享内存(shm)作为缓冲区,通过 weston_output 的虚拟输出接口将渲染结果提交到内存中。该后端常用于:
- Weston 自带的
weston-simple-egl测试程序离屏渲染。 - 配合 weston-test 插件进行自动化集成测试。
- 远程桌面场景(如通过 GStreamer 将帧编码推流)。
DRM 后端(drm-backend.so)直接与 Linux 内核的 DRM/KMS 子系统交互。它通过 drmModeGetResources 枚举连接器(Connector)和编码器(Encoder),使用 drmModeSetCrtc 设置显示模式,并通过 drmModePageFlip 实现无撕裂的帧提交。DRM 后端还支持硬件平面(Plane)合成,可将多个窗口直接映射到不同的硬件平面,减少 GPU 合成负载。
X11 后端(x11-backend.so)将 Weston 作为一个 X11 客户端运行。它创建一个 X11 窗口作为 Weston 的“画布”,所有 Wayland 客户端的表面(Surface)最终都合成到这个 X11 窗口中。该后端主要用于开发调试,因为它允许在普通桌面环境中运行 Weston,而无需切换 TTY 或独占显卡。
4.2.2 操作流程:DRM 后端的启动与验证
在车载 Linux 系统中,DRM 后端是量产标准。以下是标准启动流程:
# 1. 确保 DRM 驱动已加载
dmesg | grep -i drm
# 应看到 [drm] Initialized i915 或 [drm] Initialized vivante
# 2. 停止可能占用 DRM 的进程(如 X Server)
systemctl stop gdm # 或 lightdm
# 3. 切换到空闲 TTY
chvt 1
# 4. 启动 Weston(使用 DRM 后端)
weston --backend=drm-backend.so --tty=1 --config=/etc/weston.ini --log=/var/log/weston.log &
# 5. 验证运行状态
weston --info # 查看输出信息
cat /var/log/weston.log | grep -i "output"
验证关键点:
- 日志中出现
Output LVDS-1 (crtc 32) video modes:表示输出创建成功。 - 使用
modetest -M imx-drm查看当前 CRTC 状态,确认 Weston 已接管显示。 - 运行
weston-simple-egl测试客户端,观察屏幕是否有旋转的三角形。
4.2.3 案例拆解:headless 后端在 CI 测试中的应用
某 Tier1 供应商需要在无显示硬件的 Jenkins 服务器上运行 Wayland 客户端回归测试。初始方案是使用 Xvfb(虚拟 X Server),但无法验证 Wayland 特有的缓冲区共享和帧回调机制。改用 Weston headless 后端后:
# Jenkins 构建脚本中启动 headless Weston
weston --backend=headless-backend.so --width=1920 --height=1080 --config=/dev/null &
sleep 2
export WAYLAND_DISPLAY=wayland-1
# 运行测试客户端
./test_client --test-case=surface_attach
./test_client --test-case=pointer_motion
关键参数:--width 和 --height 指定虚拟输出分辨率。测试结果通过 weston-test 插件提供的 weston_test_runner 接口获取帧呈现时间戳,从而验证帧率是否达标。该方案将测试时间从 15 分钟缩短至 3 分钟,且无需物理显示设备。
4.2.4 常见误区与总结
weston --debug 查看平面分配日志。
总结:三种后端各有适用边界。车载量产必须使用 DRM 后端,但 headless 后端在测试和远程诊断中价值巨大。X11 后端则作为开发阶段的“安”,避免频繁切换 TTY 带来的不便。
4.3 配置与启动流程
4.3.1 核心原理:weston.ini 配置体系
Weston 的配置文件采用 INI 格式,默认路径为 /etc/xdg/weston/weston.ini 或 ~/.config/weston.ini。配置分为多个 section:
| Section | 关键键值 | 作用 |
|---|---|---|
| [core] | shell、backend、renderer | 指定核心模块、后端类型、渲染器 |
| [shell] | panel-location、background-color | 配置桌面壳的面板位置和背景 |
| [output] | name、mode、transform、scale | 定义每个显示输出的参数 |
| [input-method] | path、options | 加载输入法模块 |
| [launcher] | icon、path | 定义桌面启动器图标 |
启动流程分为四个阶段:
- 解析配置:Weston 读取 weston.ini,确定后端类型、渲染器、输出列表。
- 加载插件:通过
dlopen()加载后端 .so 文件,并调用backend_init()。 - 初始化输出:后端创建
weston_output,设置模式、缩放、变换。 - 启动 Shell:加载 shell 模块(如 desktop-shell.so),创建面板、背景、启动应用。
4.3.2 操作流程:车载场景的典型配置
以下是一个适用于车载中控的 weston.ini 配置示例:
[core]
shell=desktop-shell.so
backend=drm-backend.so
renderer=gles2
idle-time=0
[shell]
panel-location=top
panel-size=48
background-color=0xff002233
# 禁止屏幕保护
locking=false
[output]
name=LVDS-1
mode=1920x720@60
transform=normal
scale=1
[output]
name=HDMI-A-1
mode=1920x1080@60
transform=normal
scale=1
[launcher]
icon=/usr/share/icons/ic_launcher_home.png
path=/usr/bin/vehicle_hmi
[input-method]
path=/usr/lib/libinput-method-ivi.so
options=--enable-auto-switch
启动命令:
weston --config=/etc/weston.ini --log=/var/log/weston.log --tty=1
关键参数说明:
idle-time=0:禁用空闲休眠,避免车载屏幕意外熄灭。locking=false:禁用屏幕锁定,防止 HMI 无法唤醒。background-color:使用 ARGB 格式,设置深色背景以减少 OLED 烧屏风险。
4.3.3 案例拆解:启动失败排查流程
某项目在实车启动时,Weston 进程反复崩溃,日志显示 fatal: failed to create output。初步排查步骤:
# 1. 查看完整日志
tail -50 /var/log/weston.log
# 关键行: [drm] failed to set mode 1920x720@60 for output LVDS-1
# 2. 检查 DRM 是否支持该模式
modetest -M imx-drm -c
# 发现 LVDS-1 支持的最大分辨率为 1366x768,不支持 1920x720
# 3. 修改配置,使用 EDID 推荐模式
[output]
name=LVDS-1
mode=preferred
结果对比:修改后 Weston 正常启动,屏幕显示 1366x768。复盘经验:车载屏幕的 EDID 信息可能不完整,导致 Weston 无法读取正确的 mode 列表。建议在开发阶段使用 weston --info 确认实际支持的 mode,再写入配置。
4.3.4 常见误区与总结
--idle-time=0 以外的值,否则长时间停车后屏幕可能休眠,且无法通过触摸唤醒(需配置 input-method 的 wakeup 功能)。注意:Weston 启动时若检测到已有进程占用 DRM master(如 X Server),会报
drmSetMaster failed。务必先停止 X Server 或使用 loginctl 切换 session。
总结:配置与启动流程是 Weston 落地的“最后一公里”。车载项目应提前固化 weston.ini 模板,并在 CI 中验证配置变更,避免因配置错误导致量产启动失败。