3. DRM与KMS基础概念
在嵌入式显示系统中,DRM (Direct Rendering Manager) 是 Linux 内核中负责图形显示和渲染的核心框架,而 KMS (Kernel Mode Setting) 则是 DRM 框架中专门管理显示模式、分辨率、刷新率和显示管线的子系统。理解 DRM 与 KMS 的架构关系,是配置 Weston 合成器与底层显示硬件的先决条件。
3.1 DRM 框架简介
DRM 最初是为管理 GPU 的 3D 渲染和 2D 加速而设计,后来演变为一个统一的显示子系统框架。它通过 /dev/dri/card0 等设备节点向用户空间提供 ioctl 调用,支持缓冲区管理、同步对象(Fence)、内存共享(DMA-BUF)以及 KMS 功能。
drivers/gpu/drm/ 目录下,上层对接用户空间的 libdrm 库,下层对接具体的 GPU 或显示控制器驱动(如 i915、msm、vc4、rockchip)。
DRM 的核心组件包括:
- DRM Core:提供通用框架、ioctl 分发、对象管理、内存管理(GEM/TTM)。
- KMS 子系统:管理显示模式设置、输出管线配置、页面翻转(Page Flip)。
- Framebuffer 管理:管理显存中的帧缓冲区对象,支持多平面格式。
- 同步机制:Fence 和 Sync File 用于 GPU 与显示控制器之间的同步。
3.2 KMS 的核心职责
KMS (Kernel Mode Setting) 是 DRM 框架中负责显示模式配置的核心子系统。在早期的 Linux 显示架构中,模式设置由用户空间的 X Server 完成(UMS, User Mode Setting),这导致模式切换时出现闪烁、多显示器支持困难等问题。KMS 将模式设置移入内核,确保显示状态的一致性和原子性。
KMS 的核心职责包括:
| 职责 | 说明 | 关键操作 |
|---|---|---|
| 显示模式管理 | 管理显示分辨率、刷新率、像素时钟、时序参数(H/V Blanking) | DRM_IOCTL_MODE_GETCONNECTOR / SETCRTC |
| 显示管线配置 | 将 CRTC、Encoder、Connector、Plane 组合成完整的显示输出链路 | DRM_IOCTL_MODE_ATOMIC 原子提交 |
| 页面翻转 (Page Flip) | 在 VBlank 期间切换帧缓冲区,实现无撕裂的显示更新 | DRM_IOCTL_MODE_PAGE_FLIP |
| 光标管理 | 独立于主显示平面的硬件光标层移动和更新 | DRM_IOCTL_MODE_CURSOR |
| 原子模式设置 | 支持一次性提交多个显示对象的配置变更,保证状态一致性 | DRM_IOCTL_MODE_ATOMIC + 属性 |
3.3 CRTC / Encoder / Connector / Plane 四大对象
KMS 将显示管线抽象为四个核心对象,它们共同描述从帧缓冲区到物理显示接口的完整数据流路径。理解这四个对象的关系是配置显示输出的基础。
3.3.1 CRTC (Cathode Ray Tube Controller)
CRTC 是显示管线的核心时序生成器,负责从帧缓冲区读取像素数据,按照设定的分辨率、刷新率和时序参数生成视频信号。每个 CRTC 对应一个独立的显示输出通道,通常与一个物理显示接口(如 HDMI、DP)关联。
- 关键属性:模式(Mode)、位置(x/y)、旋转、缩放、伽马校正。
- 硬件映射:在嵌入式 SoC 中,CRTC 通常对应显示控制器(Display Controller)的一个通道。
- 限制:一个 CRTC 同一时间只能驱动一个 Connector,但可以通过克隆模式输出到多个 Connector。
3.3.2 Encoder (编码器)
Encoder 负责将 CRTC 输出的并行数字视频信号转换为特定显示接口所需的串行信号或协议格式。常见的 Encoder 类型包括:
| Encoder 类型 | 输出接口 | 典型应用 |
|---|---|---|
| TMDS | HDMI / DVI | 消费电子显示器 |
| LVDS | LVDS 接口 | 嵌入式 LCD 屏 |
| eDP | 嵌入式 DisplayPort | 笔记本 / 平板内置屏 |
| DSI | MIPI DSI | 手机 / 嵌入式小屏 |
| DAC | VGA | 老旧显示器 |
3.3.3 Connector (连接器)
Connector 代表物理显示接口和与之连接的显示器设备。它负责检测显示器的连接状态、读取 EDID 数据(获取显示器支持的分辨率列表)以及管理热插拔事件。
- 状态检测:通过
drmModeGetConnector获取连接状态(connected / disconnected)。 - EDID 解析:从显示器读取 EDID 数据块,解析出支持的模式列表、物理尺寸、色彩特性。
- 热插拔:通过 udev 事件或 DRM 事件通知用户空间连接状态变化。
modetest -M <driver> 命令可以列出当前系统中所有 CRTC、Encoder、Connector 和 Plane 的详细信息,是排查显示输出问题的首选工具。
3.3.4 Plane (平面)
Plane 是 KMS 中用于描述显示层的对象。每个 Plane 对应一个独立的帧缓冲区,可以叠加在 CRTC 的输出上。硬件支持多个 Plane 时,可以实现硬件合成(Hardware Composition),减少 GPU 的合成负担。
- 主平面 (Primary Plane):每个 CRTC 必须有一个主平面,用于显示主要的帧缓冲区内容。
- 光标平面 (Cursor Plane):专门用于显示硬件光标,支持独立的位置和大小控制。
- 叠加平面 (Overlay Plane):额外的显示层,可用于视频播放、UI 叠加等场景。
Plane 的关键属性包括:
| 属性 | 说明 | 示例值 |
|---|---|---|
| fb_id | 绑定的帧缓冲区 ID | 32 |
| crtc_id | 绑定的 CRTC ID | 1 |
| src_x / src_y | 源帧缓冲区裁剪起始坐标(16.16 定点数) | 0 |
| src_w / src_h | 源帧缓冲区裁剪宽高(16.16 定点数) | 1920 << 16 |
| crtc_x / crtc_y | 显示输出位置(像素坐标) | 0 |
| crtc_w / crtc_h | 显示输出尺寸(像素) | 1920 |
| zpos | 叠加顺序(数值越大越靠上) | 0 / 1 / 2 |
3.4 四大对象的绑定关系与配置流程
在 Weston 合成器启动时,它会通过 libdrm 遍历系统中的所有 CRTC、Encoder、Connector 和 Plane,然后按照以下流程建立绑定关系:
- 枚举 Connector:遍历所有 Connector,检查连接状态和 EDID 信息。
- 选择模式:从 Connector 的模式列表中选择最佳显示模式(通常为最高分辨率)。
- 查找 Encoder:根据 Connector 的 encoder_id 找到对应的 Encoder。
- 分配 CRTC:找到一个空闲的 CRTC,设置显示模式。
- 绑定 Plane:将主平面绑定到 CRTC,并设置帧缓冲区。
- 原子提交:使用
DRM_IOCTL_MODE_ATOMIC一次性提交所有配置。
drm_backend 模块调用 drmModeGetResources 获取所有 KMS 对象,然后使用 drmModeAtomicCommit 进行原子配置。如果硬件支持多个 Plane,Weston 会优先使用叠加平面实现硬件合成,减少 GPU 负载。