2. DRM 核心概念:CRTC、Encoder、Connector、Plane、Framebuffer、Mode Object 与 Property

DRM (Direct Rendering Manager) 是 Linux 内核中负责图形显示和渲染管理的核心框架。在瑞芯微平台(如 RK3568、RK3588)的显示驱动开发中,理解 DRM 的六大核心对象及其关系是进行驱动移植、显示优化和多屏调试的基础。本章将逐一剖析这些对象,并揭示它们如何协同工作,最终将帧缓冲区中的像素数据呈现到物理显示器上。

学习提示: DRM 的架构设计遵循“管道”思想。你可以将整个显示链路想象成一条流水线:Framebuffer 是原料仓库,Plane 是加工工位,CRTC 是传送带控制器,Encoder 是信号编码器,Connector 是出货接口。理解这个比喻,本章内容将迎刃而解。

2.1 核心对象全景图

在深入每个对象之前,我们先通过一张架构图建立整体认知。下图展示了 DRM 显示管道中各个核心对象的连接关系与数据流向。

DRM 核心对象架构图 DRM 显示管道核心对象关系图 Framebuffer (帧缓冲区) Plane (硬件图层) CRTC (显示控制器) Encoder (信号编码器) Connector (物理连接器) Display (物理显示器) 说明:数据从 Framebuffer 出发,经过 Plane 合成,由 CRTC 控制时序,经 Encoder 编码,通过 Connector 输出到物理显示器。 每个对象都通过 Property 暴露可配置属性,用户态通过 Mode Object 进行统一管理。

2.2 Framebuffer(帧缓冲区)

Framebuffer 是 DRM 中最基础的内存对象,它代表一块用于存储像素数据的物理连续或非连续内存区域。用户态应用程序(如 Wayland Compositor、Xorg)将渲染完成的图像数据写入 Framebuffer,然后由显示硬件读取并输出。

2.2.1 关键属性

属性描述瑞芯微平台注意事项
width / height帧缓冲区的像素宽度和高度需对齐到 16 或 32 像素边界
pitch每行像素的字节数(stride)RK3588 要求 pitch 为 64 字节对齐
depth / bpp颜色深度(如 32bpp)支持 ARGB8888、XRGB8888 等格式
handles / offsetsGEM 句柄数组及每平面的偏移多平面格式(如 NV12)需注意 offset 计算

2.2.2 创建流程

// 用户态通过 DRM_IOCTL_MODE_ADDFB2 创建 Framebuffer
struct drm_mode_fb_cmd2 fb_cmd = {
    .width = 1920,
    .height = 1080,
    .pixel_format = DRM_FORMAT_XRGB8888,
    .handles[0] = gem_handle,  // 从 GEM 分配的内存句柄
    .pitches[0] = 1920 * 4,    // 每行字节数
};
int ret = drmIoctl(fd, DRM_IOCTL_MODE_ADDFB2, &fb_cmd);
// fb_cmd.fb_id 即为新创建的 Framebuffer ID
性能陷阱: 在瑞芯微平台上,频繁创建和销毁 Framebuffer 会导致显存碎片化。建议使用 Framebuffer 池 或 DMA-BUF 导入机制来复用内存,避免在每帧都重新分配。

2.3 Plane(硬件图层)

Plane 代表显示控制器中的一个硬件图层。现代 SoC(如 RK3588)通常支持多个硬件图层(如主图层、光标图层、视频图层),每个 Plane 可以独立配置位置、大小、透明度、Z-order 和色彩格式。Plane 是 DRM 实现合成(Composition)的关键。

2.3.1 Plane 类型

类型枚举值用途瑞芯微典型数量
Primary PlaneDRM_PLANE_TYPE_PRIMARY主显示图层,通常用于桌面背景或主应用1 个
Cursor PlaneDRM_PLANE_TYPE_CURSOR硬件光标层,支持小尺寸、高刷新率更新1 个
Overlay PlaneDRM_PLANE_TYPE_OVERLAY叠加层,用于视频播放、UI 弹窗等2~4 个

2.3.2 Plane 属性与合成

// 通过 drmModeObjectGetProperties 获取 Plane 的 Property
drmModeObjectProperties *props = drmModeObjectGetProperties(fd, plane_id, DRM_MODE_OBJECT_PLANE);
for (int i = 0; i < props->count_props; i++) {
    drmModePropertyRes *prop = drmModeGetProperty(fd, props->props[i]);
    printf("Property: %s, Value: %llu\n", prop->name, props->prop_values[i]);
    drmModeFreeProperty(prop);
}
drmModeFreeObjectProperties(props);
Plane 合成示意图 Plane 硬件图层合成示意图 Primary Plane Z-order: 0 Overlay Plane Z-order: 1, Alpha: 0.8 Cursor Plane Z-order: 2, 32x32 CRTC 硬件合成器 按 Z-order 混合 输出

2.4 CRTC(显示控制器)

CRTC (Cathode Ray Tube Controller,历史名称沿用至今) 是 DRM 显示管道的核心调度器。它负责从 Framebuffer 读取像素数据,生成显示时序信号(行同步、场同步、像素时钟),并将数据流发送给 Encoder。在瑞芯微平台上,CRTC 通常对应 VOP (Video Output Processor) 模块。

2.4.1 CRTC 核心职责

  • 时序生成: 根据 Mode (显示模式) 生成精确的 Hsync、Vsync、DE 信号。
  • 扫描控制: 控制从 Framebuffer 读取像素的起始地址和扫描顺序。
  • 色彩管理: 应用 Gamma/LUT 校正、色彩矩阵转换。
  • VBlank 管理: 提供垂直消隐区中断,用于帧同步和 Page Flip。

2.4.2 瑞芯微 VOP 与 CRTC 映射

芯片型号VOP 模块CRTC 数量最大分辨率
RK3568VOP22 (CRTC-0, CRTC-1)4K@60
RK3588VOP33 (CRTC-0 ~ CRTC-2)8K@60
RK3399VOPB / VOPL24K@30

2.5 Encoder(编码器)

Encoder 负责将 CRTC 输出的并行像素数据转换为特定显示接口所需的串行信号格式。常见的 Encoder 类型包括 HDMI Encoder、DP Encoder、MIPI DSI Encoder、LVDS Encoder 等。在瑞芯微平台中,Encoder 通常由 SoC 内部的显示接口控制器(如 HDMI TX Controller)实现。

2.5.1 Encoder 与 CRTC 的绑定

// 内核驱动中,Encoder 通过 drm_encoder_init 注册,并关联可能的 CRTC 掩码
struct drm_encoder *encoder;
drm_encoder_init(drm_dev, encoder, &rk_encoder_funcs, DRM_MODE_ENCODER_TMDS, NULL);
encoder->possible_crtcs = drm_crtc_mask(crtc);  // 绑定到特定 CRTC

2.6 Connector(连接器)

Connector 代表物理显示接口,如 HDMI 端口、DP 端口、eDP 接口、MIPI DSI 接口等。Connector 负责检测显示器是否连接(Hot Plug Detect)、读取显示器的 EDID 数据(获取支持的分辨率列表)、以及管理物理连接状态。

2.6.1 Connector 状态与 EDID

  • connected: 检测到显示器,可通过 EDID 获取显示模式列表。
  • disconnected: 无显示器连接,驱动应关闭输出以节省功耗。
  • unknown: 状态未知,驱动需轮询检测。
// 用户态获取 Connector 信息
drmModeConnector *conn = drmModeGetConnector(fd, connector_id);
if (conn->connection == DRM_MODE_CONNECTED) {
    printf("Connector %d connected, %d modes available\n", connector_id, conn->count_modes);
    for (int i = 0; i < conn->count_modes; i++) {
        drmModeModeInfo *mode = &conn->modes[i];
        printf("  Mode: %s, %dx%d@%dHz\n", mode->name, mode->hdisplay, mode->vdisplay, mode->vrefresh);
    }
}
drmModeFreeConnector(conn);

2.7 Mode Object 与 Property

Mode Object 是 DRM 中所有显示对象的基类。CRTC、Encoder、Connector、Plane、Framebuffer 都是 Mode Object 的子类。每个 Mode Object 都有一个唯一的 ID 和类型标识。

Property 是 DRM 实现可配置性的核心机制。每个 Property 都有一个名称、一个类型(如 range、enum、blob、object)和一个值。用户态可以通过 Property 来配置显示管道的各种参数,而无需直接操作内核结构体。

2.7.1 常用 Property 示例

Property 名称所属对象类型说明
CRTC_IDPlane / Connectorobject绑定到指定的 CRTC
FB_IDPlaneobject指定 Plane 使用的 Framebuffer
alphaPlanerange图层透明度 (0~65535)
zposPlanerangeZ-order 排序值
mode_idConnectorblob显示模式 ID
scaling_modeConnectorenum缩放模式 (None/Full/Aspect)

2.7.2 Property 的原子操作

// 使用 Atomic API 一次性提交多个 Property 更新
struct drm_mode_atomic atomic = {0};
atomic.flags = DRM_MODE_ATOMIC_ALLOW_MODESET;
atomic.count_objs = 2;
uint32_t objs[2] = {plane_id, crtc_id};
uint32_t count_props[2] = {2, 1};
uint32_t props[3] = {prop_fb_id, prop_crtc_id, prop_active};
uint64_t values[3] = {new_fb_id, crtc_id, 1};
atomic.objs_ptr = (uint64_t)objs;
atomic.count_props_ptr = (uint64_t)count_props;
atomic.props_ptr = (uint64_t)props;
atomic.values_ptr = (uint64_t)values;
int ret = drmIoctl(fd, DRM_IOCTL_MODE_ATOMIC, &atomic);
Mode Object 与 Property 关系图 Mode Object 与 Property 关系图 Mode Object (基类) CRTC Encoder Connector Plane Property 示例:CRTC_ID, FB_ID, alpha, zpos, mode_id, scaling_mode, active, gamma_lut 每个 Property 通过 drmModeObjectGetProperty / drmModeObjectSetProperty 进行读写

2.8 对象间的关系总结

为了帮助记忆,下表总结了六大核心对象之间的关系与约束:

关系描述约束条件
Framebuffer → PlanePlane 引用 Framebuffer 作为像素数据源Framebuffer 格式必须与 Plane 支持的格式匹配
Plane → CRTCPlane 必须绑定到一个 CRTC 才能参与显示一个 CRTC 可绑定多个 Plane,但 Primary Plane 必须存在
CRTC → EncoderCRTC 将像素流发送给 Encoder一个 CRTC 只能连接一个 Encoder
Encoder → ConnectorEncoder 将编码后的信号发送给 Connector一个 Encoder 可连接多个 Connector(如 HDMI+DP 复用)
Connector → DisplayConnector 通过物理线缆连接显示器Connector 状态决定显示链路是否可用
实战要点: 在瑞芯微平台调试多屏显示时,务必检查 possible_crtcs 和 possible_clones 掩码。例如,RK3588 的 HDMI0 可能只能绑定到 CRTC-0 和 CRTC-1,而 DP0 可能只能绑定到 CRTC-2。错误的绑定会导致 modeset 失败或黑屏。

2.9 本章小结

  • Framebuffer 是像素数据的载体,由用户态分配并填充。
  • Plane 是硬件图层,支持独立的位置、大小和透明度配置。
  • CRTC 是显示时序控制器,负责从 Framebuffer 读取数据并生成同步信号。
  • Encoder 将并行数据转换为串行接口信号(HDMI/DP/MIPI)。
  • Connector 是物理接口,负责检测显示器并读取 EDID。
  • Mode Object 是 DRM 对象的统一抽象,Property 提供了灵活的配置接口。
  • 原子 API (Atomic Modeset) 通过 Property 集合实现无闪烁的显示模式切换。