1. 显示子系统概述:Linux 显示架构演进历史
Linux 显示子系统在过去二十多年中经历了从简单到复杂、从封闭到开放的深刻变革。早期内核仅提供最基本的帧缓冲抽象(fbdev),随着 GPU 硬件复杂化、显示管线多样化以及用户空间对合成器(如 Wayland)的需求,内核社区逐步演进到以 DRM(Direct Rendering Manager)和 KMS(Kernel Mode Setting)为核心的现代显示架构。本章从历史演进、核心概念对比两个维度,帮助读者建立完整的显示子系统知识图谱。
1.1 Linux 显示架构演进时间线
下表梳理了从 Linux 2.2 时代到当前 6.x 内核的关键里程碑:
| 时间 / 内核版本 | 里程碑事件 | 架构特征 |
|---|---|---|
| 1999 / 2.2.x | fbdev 框架引入 | 简单帧缓冲,仅支持单层、固定时序,无硬件加速 |
| 2004 / 2.6.x | DRM 初版合并(i915 驱动) | 提供 GEM/TTM 内存管理,用户空间可直接提交命令缓冲区 |
| 2008 / 2.6.29 | KMS 框架首次合入 | 内核接管显示模式设置,取代用户空间 Xorg 控制 |
| 2012 / 3.4 | Atomic KMS 概念提出 | 支持无撕裂、逐帧原子提交,为合成器提供事务性 API |
| 2016 / 4.8 | Atomic KMS 正式稳定 | 所有主要 GPU 驱动完成原子化迁移 |
| 2020 / 5.10 | fbdev 模拟层(drm_fb_helper)成熟 | DRM 驱动可兼容旧 fbdev 用户空间,迁移路径清晰 |
| 2024 / 6.8 | 部分架构开始移除原生 fbdev 驱动 | 社区推动彻底弃用 fbdev,全面转向 DRM/KMS |
关键认知: 演进的核心驱动力来自两方面——GPU 硬件从固定管线变为可编程管线,以及用户空间合成器(Wayland/Weston)需要内核提供无撕裂、零拷贝的显示控制能力。fbdev 无法满足这些需求,DRM/KMS 成为必然选择。
1.2 fbdev 与 DRM/KMS 基本概念对比
fbdev(Frame Buffer Device)和 DRM/KMS(Direct Rendering Manager / Kernel Mode Setting)代表了两种截然不同的显示控制哲学。下面从架构层次、API 设计、硬件抽象、内存管理、模式设置、多图层支持六个维度进行对比:
| 对比维度 | fbdev | DRM/KMS |
|---|---|---|
| 架构层次 | 单一 /dev/fbX 设备节点,内核直接暴露帧缓冲 | 多设备节点(/dev/dri/card0, /dev/dri/renderD128),分层设计 |
| API 设计 | 基于 ioctl + mmap,操作简单但功能有限 | 基于 ioctl + 属性对象(property),支持原子提交 |
| 硬件抽象 | 几乎无抽象,驱动直接操作寄存器 | KMS 抽象出 CRTC、Encoder、Connector、Plane 四大对象 |
| 内存管理 | 固定 DMA 缓冲区,不支持 GPU 显存 | GEM(Graphics Execution Manager)或 TTM,支持显存分配与共享 |
| 模式设置 | 通过 fb_var_screeninfo / fb_fix_screeninfo 结构体 | 通过 drm_mode_create_dumb / drm_mode_setcrtc 等 KMS 接口 |
| 多图层支持 | 仅单层,无硬件合成 | 支持多个 Plane(主层、光标层、覆盖层),硬件合成 |
一句话总结: fbdev 是“软件帧缓冲”,适合简单嵌入式设备;DRM/KMS 是“硬件显示管线抽象”,适合现代 GPU 和复杂显示场景。
1.3 架构演进核心驱动力
为什么 Linux 社区要投入巨大精力从 fbdev 迁移到 DRM/KMS?以下三个驱动力最为关键:
- 硬件复杂度爆炸: 现代 SoC 显示子系统包含多个显示控制器、DSI/HDMI/DP 接口、写回通道(writeback)、硬件光标、旋转/缩放引擎。fbdev 的单一帧缓冲模型无法表达这些硬件能力。
- 无撕裂与低延迟需求: 用户空间合成器(如 Weston、Mutter)需要内核提供 VBlank 同步、Page Flip、Atomic Commit 等机制,确保每一帧切换不产生撕裂(tearing)。fbdev 的 PAN_DISPLAY 接口无法保证原子性。
- 内存共享与零拷贝: DRM 的 GEM 机制允许 GPU、显示控制器、视频编解码器共享同一块物理内存,避免数据拷贝。fbdev 的固定 DMA 缓冲区无法实现这种共享。
迁移陷阱: 许多嵌入式工程师试图在旧内核上通过 fbdev 模拟层(fbcon + drm_fb_helper)临时过渡,但需要注意:fbdev 模拟层无法提供硬件合成、多 Plane、写回通道等高级特性。长期方案必须直接使用 DRM/KMS 原生接口。
1.4 显示子系统软件架构总览
下面这张 SVG 架构图展示了从用户空间到硬件的完整显示软件栈,重点标出 fbdev 与 DRM/KMS 两条路径的差异:
1.5 关键概念速查表
为帮助读者快速建立概念映射,下面列出 DRM/KMS 四大核心对象及其与 fbdev 的对应关系:
| DRM/KMS 对象 | 功能描述 | fbdev 对应物 | 迁移关注点 |
|---|---|---|---|
| CRTC | 显示控制器,负责扫描输出、生成时序 | 无直接对应,fbdev 隐含在驱动内部 | 需要显式配置 CRTC 与 Connector 绑定 |
| Encoder | 编码器,将 CRTC 信号转换为接口协议 | 无对应 | 通常由驱动自动匹配,但需理解编码器类型 |
| Connector | 物理连接器,代表 HDMI/DP/DSI 等接口 | 无对应 | 需要检测连接器状态(connected/disconnected) |
| Plane | 硬件图层,支持叠加、缩放、旋转 | 单层帧缓冲 | 多 Plane 是 DRM 最大优势,但驱动需正确暴露 |
1.6 迁移路径概览
从 fbdev 迁移到 DRM/KMS 通常遵循以下步骤,后续章节将逐一深入:
- 理解硬件显示管线: 梳理 SoC 的 CRTC 数量、Encoder 类型、Connector 接口、Plane 能力。
- 注册 DRM 驱动: 实现 drm_driver 结构体,调用 drm_dev_alloc / drm_dev_register。
- 实现 KMS 对象: 创建 CRTC、Encoder、Connector、Plane,并实现对应的回调函数。
- 实现 GEM 内存管理: 选择 GEM(简单场景)或 TTM(复杂 GPU),实现 dumb buffer 分配。
- 实现 Atomic Commit: 支持 drm_atomic_state 提交,确保无撕裂切换。
- 添加 fbdev 模拟层(可选): 使用 drm_fb_helper 兼容旧应用,但仅作为过渡。
- 用户空间适配: 修改应用或合成器,直接使用 DRM/KMS API。
学习建议: 本章是后续所有章节的基础。建议读者在阅读过程中,对照自己熟悉的硬件平台(如 i.MX8、RK3588、Raspberry Pi)的显示控制器手册,将 CRTC/Encoder/Connector/Plane 映射到具体硬件模块上,理解会更深刻。