1. DRM 基础概念:架构概览与四大组件详解
DRM(Direct Rendering Manager)是 Linux 内核中负责显示输出的核心框架。理解 DRM 的架构分层与四大组件——CRTC、Encoder、Connector、Plane——是进行显示驱动性能分析与 Atomic API 优化的前提。本章从整体架构入手,逐一拆解每个组件的职责、数据流与关键数据结构。
1.1 DRM 架构概览
DRM 位于内核空间,向上通过 drm_open / drm_ioctl 接口暴露给用户态(如 Xorg、Wayland、libdrm),向下通过 KMS(Kernel Mode Setting)控制硬件显示控制器。整个架构分为三层:
- 用户态:应用程序通过 libdrm 调用 DRM ioctl,提交 framebuffer、配置显示模式。
- 内核 DRM 核心层:提供通用框架、对象管理、Atomic 校验与提交。
- 驱动层:实现具体的硬件操作函数,如
mode_set、atomic_flush。
1.2 四大组件详解
DRM KMS 将显示输出抽象为四个核心对象,它们共同构成一条完整的显示流水线:
| 组件 | 内核结构体 | 核心职责 | 性能关注点 |
|---|---|---|---|
| CRTC | drm_crtc |
控制显示时序、扫描输出、帧同步 | 模式切换延迟、vblank 中断处理 |
| Encoder | drm_encoder |
将 CRTC 输出的像素数据编码为物理接口信号 | 编码器时钟频率、链路训练 |
| Connector | drm_connector |
检测物理显示器连接、获取 EDID、报告状态 | 热插拔检测延迟、EDID 读取 |
| Plane | drm_plane |
管理图层叠加、缩放、旋转、颜色转换 | 图层合成带宽、Alpha 混合开销 |
1.3 CRTC:显示时序的指挥官
CRTC(Cathode Ray Tube Controller,沿用历史名称)负责生成显示时序信号,包括行同步(HSync)、场同步(VSync)、像素时钟。每个 CRTC 对应一个独立的显示输出通道,驱动中通过 drm_crtc_helper_funcs 实现模式设置:
struct drm_crtc_helper_funcs {
void (*mode_set)(struct drm_crtc *crtc,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode);
void (*atomic_flush)(struct drm_crtc *crtc, struct drm_crtc_state *old_state);
bool (*get_scanout_position)(struct drm_crtc *crtc,
bool in_vblank_irq,
int *vpos, int *hpos,
ktime_t *stime, ktime_t *etime);
};
性能关键点:atomic_flush 必须在 vblank 期间完成,否则会导致画面撕裂(tearing)。优化方向是缩短 flush 内的寄存器写入时间。
1.4 Encoder 与 Connector:物理链路的两端
Encoder 将 CRTC 输出的并行像素数据转换为特定物理接口的串行信号,如 HDMI、DP、LVDS、eDP。每个 Encoder 通过 drm_encoder_possible_crtcs 位掩码声明可连接的 CRTC。
Connector 代表物理显示接口,负责检测显示器是否连接、读取 EDID(扩展显示标识数据)、报告当前连接状态。Connector 的状态变化会触发 drm_connector_helper_funcs.detect 回调。
| 接口类型 | Encoder 编码方式 | Connector 检测方式 | 常见性能问题 |
|---|---|---|---|
| HDMI | TMDS 编码 | HPD 引脚 + EDID | EDID 读取阻塞、HDCP 握手延迟 |
| DisplayPort | ANX 编码 / 8b10b | HPD + DPCD 读取 | 链路训练失败重试、MST 拓扑管理 |
| eDP | 嵌入式 DP | 固定连接,无需 HPD | PSR 进入/退出延迟 |
| LVDS | 并行转差分 | 无热插拔 | 固定时序,无动态调整 |
detect 回调不应在原子上下文中执行耗时操作(如 I2C 读取 EDID)。建议使用工作队列异步检测,避免阻塞显示配置流程。
1.5 Plane:图层合成的核心
Plane 是 DRM 中负责图层管理的组件,每个 Plane 可以绑定一个 framebuffer,并支持位置、大小、缩放、旋转、Alpha 混合等属性。现代硬件通常提供多个硬件 Plane(Overlay),用于在显示控制器内部直接合成多层画面,避免 GPU 合成。
Plane 分为三种类型:
- Primary Plane:每个 CRTC 至少有一个,用于显示主图层(通常为桌面背景或应用窗口)。
- Overlay Plane:额外的硬件叠加层,用于视频播放、UI 弹窗等,减少合成带宽。
- Cursor Plane:专用硬件光标层,支持快速移动而不触发全屏刷新。
struct drm_plane_state {
struct drm_framebuffer *fb; // 绑定的帧缓冲
uint32_t crtc_x, crtc_y; // 在 CRTC 上的位置
uint32_t crtc_w, crtc_h; // 显示尺寸
uint32_t src_x, src_y; // 源裁剪坐标 (16.16 定点)
uint32_t src_w, src_h; // 源裁剪尺寸
uint16_t alpha; // 全局 Alpha 值 (0-65535)
bool pixel_blend_mode; // 混合模式
};
1.6 四大组件的数据流关系
一个完整的显示输出路径为:Framebuffer → Plane → CRTC → Encoder → Connector → 显示器。在 Atomic API 中,所有组件的状态通过 drm_atomic_state 统一管理,一次提交可以同时更新多个组件的配置。