1. DRM 框架概述

DRM(Direct Rendering Manager)是 Linux 内核中负责图形显示与 GPU 渲染管理的核心子系统。它向上为用户态提供标准接口(/dev/dri/card0),向下抽象 GPU 与显示控制器硬件。理解 DRM 的架构组成与核心对象,是排查 GPU 渲染异常与 HDR 显示故障的基础。

1.1 DRM 架构分层

DRM 子系统采用分层设计,从硬件到用户空间共分为四层:

层次 组件 职责
硬件层 GPU / Display Controller / Encoder / PHY 像素渲染、扫描输出、信号编码与物理传输
内核驱动层 DRM Core + KMS + GEM + GPU 驱动 设备抽象、内存管理、模式设置、命令提交
用户态库层 libdrm / Mesa / Vulkan ICD 封装 ioctl、提供 3D 加速与显示控制 API
应用层 Wayland Compositor / Xorg / 游戏引擎 合成、窗口管理、渲染请求发起
排查要点: 故障定位时,首先确认问题发生在哪一层。例如,dmesg 中的 DRM 错误通常指向内核驱动层;而应用程序崩溃或画面撕裂则更多与用户态库或合成器相关。

1.2 核心对象模型

DRM 使用面向对象的方式抽象显示管线,核心对象包括 CRTC、Encoder、Connector 和 Plane。它们之间的关系构成了完整的显示数据流。

DRM 核心对象关系图 Plane 像素数据源 CRTC 扫描输出控制器 Encoder 信号编码器 Connector 物理接口 显示器 数据流向: Plane → CRTC → Encoder → Connector → 显示器 每个环节都可能出现故障

1.2.1 CRTC

CRTC(Cathode Ray Tube Controller)是显示管线的核心调度器。它负责从 Plane 读取像素数据,生成视频时序信号(行同步、场同步、像素时钟),并将数据流发送给 Encoder。每个 CRTC 对应一个独立的显示输出通道。

1.2.2 Encoder

Encoder 将 CRTC 输出的并行像素数据转换为特定接口标准所需的串行信号。常见的编码类型包括:

  • TMDS — 用于 HDMI/DVI
  • DisplayPort — 用于 DP/eDP
  • LVDS — 用于嵌入式 LCD
  • DSI — 用于 MIPI 接口

1.2.3 Connector

Connector 代表物理显示接口,如 HDMI 端口、DP 端口、VGA 接口等。它负责检测显示器是否连接、读取 EDID 数据(包含显示器支持的分辨率、刷新率、HDR 能力等),并将信号最终传输到显示器。

1.2.4 Plane

Plane 是像素数据的来源,每个 Plane 对应一个帧缓冲区(FB)。DRM 支持叠加多个 Plane 实现硬件合成,例如:

  • Primary Plane — 主显示层,通常包含桌面背景
  • Overlay Plane — 叠加层,用于视频播放或硬件光标
  • Cursor Plane — 光标专用层,低延迟更新
HDR 排查提示: 检查 Connector 的 EDID 是否包含 HDR 静态元数据块(CTA-861 扩展块)。使用 cat /sys/class/drm/card0-HDMI-A-1/edid | edid-decode 可查看 HDR 支持能力。

1.3 渲染流程简介

一个完整的 DRM 渲染帧从应用程序发起到屏幕显示,经历以下关键步骤:

  1. 缓冲区分配 — 通过 GEM(Graphics Execution Manager)分配显存,创建帧缓冲区对象(FB)。
  2. 渲染提交 — GPU 执行渲染命令,将结果写入 FB。用户态通过 drmModeAddFB2() 注册 FB。
  3. Page Flip — 应用程序调用 drmModePageFlip() 或 atomic commit,将新 FB 切换到 CRTC 的扫描源。
  4. 扫描输出 — CRTC 按视频时序逐行读取 FB 像素,发送给 Encoder。
  5. 信号编码与传输 — Encoder 将像素数据编码为 TMDS/DP 信号,通过 Connector 输出到显示器。
DRM 渲染帧流程 ① 分配 FB GEM 分配显存 ② GPU 渲染 写入帧缓冲区 ③ Page Flip 切换扫描源 ④ 扫描输出 CRTC 逐行读取 ⑤ 显示 屏幕刷新 常见故障点: • 步骤①:显存不足 → 分配失败,dmesg 出现 "GEM: out of memory" • 步骤③:Flip 超时 → 画面卡顿,atomic check 返回 -EBUSY • 步骤④:时序异常 → 屏幕闪烁或黑屏,检查 CRTC 时钟配置 • 步骤⑤:HDR 元数据丢失 → 颜色失真,检查 Connector 的 HDR 属性

1.4 关键数据结构

在 DRM 内核代码中,核心对象对应以下数据结构:

// CRTC 结构体(简化)
struct drm_crtc {
    struct drm_device *dev;
    struct drm_plane *primary;   // 主 Plane
    struct drm_plane *cursor;    // 光标 Plane
    uint32_t mode_valid;         // 当前模式是否有效
    // ...
};

// Plane 结构体(简化)
struct drm_plane {
    struct drm_device *dev;
    uint32_t possible_crtcs;     // 可绑定的 CRTC 位掩码
    struct drm_plane_state *state;
    // ...
};

// Connector 结构体(简化)
struct drm_connector {
    struct drm_device *dev;
    struct drm_encoder *encoder; // 当前绑定的 Encoder
    struct edid *edid;           // 显示器 EDID 数据
    enum drm_connector_status status; // 连接状态
    // ...
};
调试命令速查:
# modetest -M <driver> -c — 查看所有 Connector 状态与 EDID
# cat /sys/kernel/debug/dri/0/state — 查看当前 atomic state
# drm_info — 显示所有 DRM 对象拓扑关系

1.5 本章小结