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。
关键点:DRM 核心层不直接操作硬件,所有显示配置最终由驱动层的回调函数完成。性能瓶颈常出现在驱动层对 Atomic 提交的处理延迟上。
DRM 架构分层图 用户态 (User Space) Xorg / Wayland / libdrm / DRM ioctl 内核 DRM 核心层 (Core) 对象管理 / Atomic 校验 / 通用 ioctl 处理 驱动层 (Driver) 硬件寄存器操作 / 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 混合开销
性能提示:在 Atomic API 优化中,Plane 的提交频率和 CRTC 的 vblank 同步是两大核心瓶颈。减少不必要的 Plane 更新、利用硬件叠加层而非 GPU 合成,可显著降低延迟。

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 内的寄存器写入时间。

CRTC 时序控制与 vblank 同步 像素时钟 CRTC 扫描输出 vblank 中断 性能要点 • atomic_flush 必须在 vblank 期间完成 • 减少寄存器写入次数 • 避免在中断中做耗时操作

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 并行转差分 无热插拔 固定时序,无动态调整
避坑指南:Connector 的 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;            // 混合模式
};
Plane 图层合成流水线 Primary Plane 桌面背景 / 主窗口 Overlay Plane 视频 / 弹窗 / 游戏 UI Cursor Plane 硬件合成器 Alpha 混合 / 缩放 CRTC 最终输出 优化要点 • 优先使用 Overlay Plane • 减少 Plane 更新次数 • 避免频繁 切换 fb • 利用硬件 光标层

1.6 四大组件的数据流关系

一个完整的显示输出路径为:Framebuffer → Plane → CRTC → Encoder → Connector → 显示器。在 Atomic API 中,所有组件的状态通过 drm_atomic_state 统一管理,一次提交可以同时更新多个组件的配置。

性能分析切入点:在追踪性能瓶颈时,应依次检查:Plane 的 framebuffer 切换频率 → CRTC 的 vblank 中断处理时间 → Encoder 的链路训练状态 → Connector 的 EDID 读取延迟。任何一环出现阻塞,都会导致显示卡顿或帧率下降。