1. DRM/KMS 架构概述
DRM (Direct Rendering Manager) 是 Linux 内核中负责图形显示和渲染的子系统。KMS (Kernel Mode Setting) 是 DRM 的核心部分,负责显示模式设置、图层合成和输出管理。理解 DRM/KMS 架构是开发多图层显示驱动的基础。
1.1 DRM 框架分层
DRM 框架从上到下分为三层:
- 用户空间层:应用程序通过 libdrm、Wayland、X11 等库调用 DRM ioctl 接口。
- 内核 DRM 核心层:提供通用框架、GEM 内存管理、KMS 对象管理、fence 同步机制。
- 硬件驱动层:具体 GPU/显示控制器驱动,实现回调函数操作硬件寄存器。
关键点:DRM 核心层屏蔽了硬件差异,驱动开发者只需实现
struct drm_driver 中的回调函数,即可让用户空间通过标准接口访问显示硬件。
1.2 KMS 核心组件
KMS 定义了四个核心对象,它们共同协作完成显示输出:
| 组件 | 英文全称 | 核心职责 | 关键数据结构 |
|---|---|---|---|
| CRTC | Cathode Ray Tube Controller | 扫描输出控制、时序生成、帧同步 | struct drm_crtc |
| PLANE | Hardware Plane | 图层合成、缩放、色彩转换 | struct drm_plane |
| ENCODER | Encoder | 像素数据编码(如 TMDS、LVDS、eDP) | struct drm_encoder |
| CONNECTOR | Connector | 物理连接器检测、EDID 读取、热插拔 | struct drm_connector |
历史背景:CRTC 名称源自早期 CRT 显示器时代,现代 LCD 屏幕仍沿用此概念,表示显示控制器的扫描输出通道。
1.3 组件关系与数据流
KMS 组件之间的连接关系形成一条完整的显示链路:
- PLANE 从 framebuffer 读取像素数据,进行缩放和色彩调整。
- CRTC 从 PLANE 接收合成后的像素流,生成符合显示时序的信号。
- ENCODER 将 CRTC 输出的并行像素数据编码为串行传输格式。
- CONNECTOR 将编码后的信号通过物理接口发送到显示器。
1.4 组件注册与初始化流程
在 DRM 驱动中,KMS 组件的注册顺序决定了显示链路的建立方式。典型的初始化流程如下:
// 1. 注册 DRM 设备
drm_dev_alloc(&driver, dev);
drm_dev_register(dev, 0);
// 2. 创建 CRTC
struct drm_crtc *crtc;
drm_crtc_init(dev, crtc, &crtc_funcs);
// 3. 创建 PLANE(主平面 + 叠加平面)
struct drm_plane *primary, *overlay;
drm_universal_plane_init(dev, primary, 0, &plane_funcs,
formats, num_formats, NULL,
DRM_PLANE_TYPE_PRIMARY, NULL);
drm_universal_plane_init(dev, overlay, 0, &plane_funcs,
formats, num_formats, NULL,
DRM_PLANE_TYPE_OVERLAY, NULL);
// 4. 创建 ENCODER
struct drm_encoder *encoder;
drm_encoder_init(dev, encoder, &encoder_funcs,
DRM_MODE_ENCODER_TMDS, NULL);
// 5. 创建 CONNECTOR
struct drm_connector *connector;
drm_connector_init(dev, connector, &connector_funcs,
DRM_MODE_CONNECTOR_HDMIA);
// 6. 建立连接关系
drm_mode_connector_attach_encoder(connector, encoder);
encoder->possible_crtcs = drm_crtc_mask(crtc);
注意事项:
encoder->possible_crtcs 位掩码决定了该编码器可以连接到哪些 CRTC。在多 CRTC 系统中,必须正确设置此掩码,否则原子检查会失败。
1.5 组件关系总结
下表总结了 KMS 组件之间的关键关系:
| 关系 | 描述 | 内核实现方式 |
|---|---|---|
| PLANE → CRTC | 平面绑定到 CRTC,提供像素源 | plane->crtc 指针 |
| CRTC → ENCODER | CRTC 输出连接到编码器 | encoder->crtc 指针 |
| ENCODER → CONNECTOR | 编码器连接到物理连接器 | connector->encoder_ids[] 数组 |
| CONNECTOR → CRTC | 连接器通过编码器间接关联 CRTC | 原子状态中的 crtc 指针 |
核心概念:KMS 组件通过 原子状态对象(
struct drm_atomic_state)实现联动。一次原子提交可以同时更新多个 PLANE 和 CRTC 的状态,保证画面更新不撕裂。