1. Linux 显示子系统概述:DRM/KMS 框架简介、显示管线概念、GPU 在显示子系统中的角色
1.1 显示子系统的核心使命
Linux 显示子系统负责管理从应用程序生成图形数据到最终在物理显示设备上输出像素的完整链路。其核心使命包括:
- 帧缓冲管理:分配、映射和管理显存中的帧缓冲区。
- 显示模式设置:配置显示控制器的时序、分辨率、刷新率等参数。
- 合成与渲染:将多个图形层(Layer/Plane)合成为最终画面。
- GPU 加速:利用 GPU 进行 2D/3D 渲染和视频编解码。
- 输出管理:管理物理连接器(HDMI、DP、VGA 等)和显示设备(显示器、投影仪)。
关键认知: 显示子系统是 Linux 图形栈的基石,所有图形界面(X11、Wayland)和 GPU 计算(OpenCL、Vulkan)都依赖其提供的底层抽象。
1.2 DRM/KMS 框架简介
DRM(Direct Rendering Manager)是 Linux 内核中负责图形显示和 GPU 管理的核心框架。KMS(Kernel Mode Setting)是 DRM 框架中专门负责显示模式设置和输出管理的子系统。
1.2.1 DRM 框架架构
DRM 框架采用分层设计,将用户空间、内核核心和硬件驱动解耦:
1.2.2 KMS 核心对象模型
KMS 将显示管线抽象为四个核心对象,它们共同描述了从帧缓冲区到物理显示器的完整路径:
| KMS 对象 | 角色描述 | 关键属性 |
|---|---|---|
| CRTC | 显示控制器核心,负责从帧缓冲区读取像素数据并生成视频时序信号 | 分辨率、刷新率、扫描模式、Gamma 校正 |
| Encoder | 将 CRTC 输出的并行像素数据编码为特定接口协议(TMDS、LVDS、eDP 等) | 编码类型、支持的连接器类型、电源状态 |
| Connector | 物理接口,连接显示设备(显示器、HDMI 线缆等),检测热插拔和 EDID 信息 | 连接类型(HDMI/DP/VGA)、物理状态、EDID 数据块 |
| Plane | 硬件图层,支持独立缩放、色彩空间转换和 Alpha 混合 | Z-order、透明度、裁剪区域、像素格式 |
| Framebuffer | 内存中的像素数据缓冲区,由 GEM 对象管理 | 宽度、高度、像素格式、内存句柄 |
KMS 对象关系: Framebuffer → CRTC → Encoder → Connector → 显示器。Plane 作为 CRTC 的输入源,可以叠加多个图层。
1.3 显示管线概念
显示管线(Display Pipeline)描述了像素数据从内存到屏幕的完整处理流程。理解管线是 GPU 驱动开发的核心基础。
1.3.1 显示管线阶段
- 帧缓冲读取:CRTC 通过 DMA 引擎从显存或系统内存中读取帧缓冲数据。
- 图层合成:多个 Plane 按照 Z-order 顺序进行 Alpha 混合,生成最终像素。
- 色彩处理:Gamma 校正、色彩空间转换(RGB ↔ YUV)、色域映射。
- 时序生成:CRTC 生成垂直/水平同步信号、消隐区间等视频时序。
- 编码传输:Encoder 将并行像素数据编码为串行差分信号(如 TMDS、DisplayPort 的 Main Link)。
- 物理输出:Connector 通过线缆将信号传输到显示器,显示器进行最终像素渲染。
1.4 GPU 在显示子系统中的角色
GPU(Graphics Processing Unit)在显示子系统中承担多重角色,不仅仅是渲染加速器:
| 角色 | 功能描述 | 涉及 DRM 组件 |
|---|---|---|
| 渲染加速器 | 执行 3D 渲染、着色器计算、几何处理,生成帧缓冲内容 | DRM 渲染节点 (/dev/dri/renderD*)、GEM、调度器 |
| 显示控制器 | 集成或独立的显示引擎,负责扫描输出、图层合成、时序生成 | KMS CRTC、Plane、VBlank 事件 |
| 内存管理器 | 管理显存(VRAM)和系统内存的分配、映射、共享(DMA-BUF) | GEM、TTM、DMA-BUF、IOMMU |
| 编解码引擎 | 硬件加速视频编解码(H.264/H.265/VP9),减少 CPU 负载 | DRM 编解码接口、VA-API/VDPAU 后端 |
| 电源管理 | 动态调节 GPU 频率、电压、电源状态,平衡性能与功耗 | DRM 电源管理回调、Runtime PM、freq/volt 控制 |
1.4.1 GPU 与 CPU 的协作模式
现代显示子系统采用异步并行模型,CPU 和 GPU 各自独立工作,通过同步机制协调:
- CPU 侧:应用程序提交渲染命令、更新窗口内容、处理输入事件。
- GPU 侧:执行渲染管线、扫描输出帧缓冲、处理显示中断。
- 同步点:Fence(dma_fence)、Sync File、VBlank 事件、Buffer Age。
常见误区: GPU 驱动开发 ≠ 仅开发渲染驱动。显示控制器驱动(KMS 驱动)是 GPU 驱动中独立且关键的部分,负责管理显示管线,与 3D 渲染驱动共享 GEM 内存管理基础设施。
1.5 DRM 驱动开发的核心数据结构
每个 DRM 驱动都需要实现 struct drm_driver 结构体,这是内核与驱动交互的主接口:
// include/drm/drm_drv.h
struct drm_driver {
/* 驱动基本信息 */
const char *name; // 驱动名称,如 "i915"
const char *desc; // 驱动描述
const char *date; // 驱动日期
/* 加载与卸载 */
int (*load)(struct drm_device *, unsigned long flags);
void (*unload)(struct drm_device *);
/* 文件操作 */
const struct file_operations *fops;
/* GEM 内存管理 */
int (*gem_create_object)(struct drm_device *dev,
size_t size,
struct drm_gem_object **obj);
void (*gem_free_object)(struct drm_gem_object *obj);
/* KMS 回调 */
const struct drm_mode_config_funcs *mode_config_funcs;
/* IRQ 处理 */
irqreturn_t (*irq_handler)(int irq, void *arg);
void (*irq_preinstall)(struct drm_device *dev);
int (*irq_postinstall)(struct drm_device *dev);
void (*irq_uninstall)(struct drm_device *dev);
/* 调试与信息 */
void (*debugfs_init)(struct drm_minor *minor);
};
1.5.1 KMS 驱动核心回调
KMS 驱动通过 struct drm_mode_config_funcs 实现模式设置的核心逻辑:
// include/drm/drm_mode_config.h
struct drm_mode_config_funcs {
/* 帧缓冲创建/销毁 */
struct drm_framebuffer *(*fb_create)(struct drm_device *dev,
struct drm_file *file_priv,
const struct drm_mode_fb_cmd2 *mode_cmd);
void (*fb_destroy)(struct drm_framebuffer *fb);
/* 输出轮询(热插拔检测) */
int (*output_poll_changed)(struct drm_device *dev);
/* 原子提交(Atomic Commit) */
int (*atomic_commit)(struct drm_device *dev,
struct drm_atomic_state *state,
bool nonblock);
/* 模式验证 */
int (*mode_valid)(struct drm_device *dev,
struct drm_display_mode *mode);
};
开发提示: 现代 DRM 驱动推荐使用 Atomic Modeset 接口,它提供事务性的模式设置更新,避免撕裂(Tearing)和中间状态。所有 KMS 对象的状态变更通过
drm_atomic_state 统一管理。
1.6 本章小结
- Linux 显示子系统以 DRM/KMS 框架 为核心,提供从用户空间到硬件的完整抽象。
- KMS 对象模型(CRTC、Encoder、Connector、Plane、Framebuffer)是理解显示管线的关键。
- 显示管线 描述了像素数据从内存到屏幕的完整处理流程,涉及 DMA、合成、色彩处理、时序生成和编码传输。
- GPU 在显示子系统中 承担渲染加速、显示控制、内存管理、编解码和电源管理等多重角色。
- DRM 驱动通过
struct drm_driver和struct drm_mode_config_funcs与内核框架对接。