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 中的回调函数,即可让用户空间通过标准接口访问显示硬件。
DRM 框架分层架构 用户空间层 libdrm / Wayland / X11 / 应用程序 内核 DRM 核心层 DRM ioctl / GEM 内存管理 / KMS 对象 / fence 同步 硬件驱动层 struct drm_driver 回调 / 硬件寄存器操作 GPU / 显示控制器硬件

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 组件之间的连接关系形成一条完整的显示链路:

  1. PLANE 从 framebuffer 读取像素数据,进行缩放和色彩调整。
  2. CRTC 从 PLANE 接收合成后的像素流,生成符合显示时序的信号。
  3. ENCODER 将 CRTC 输出的并行像素数据编码为串行传输格式。
  4. CONNECTOR 将编码后的信号通过物理接口发送到显示器。
KMS 组件连接关系与数据流 Framebuffer 像素数据存储 PLANE 缩放 / 合成 CRTC 时序 / 扫描 ENCODER 编码转换 CONNECTOR 物理接口 屏 数据流向说明 Framebuffer → PLANE(合成) → CRTC(时序) → ENCODER(编码) → CONNECTOR(接口) → 显示器 每个组件通过 drm_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 的状态,保证画面更新不撕裂。