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 两条路径的差异:

Linux 显示子系统软件架构对比图 Linux 显示子系统软件架构(fbdev vs DRM/KMS) 用户空间(User Space) Xorg / Wayland fbdev 应用(旧) libdrm / Mesa 合成器(Weston) 内核空间(Kernel Space) DRM Core GEM / TTM 内存管理 Atomic Commit / Page Flip KMS 对象模型 CRTC / Encoder / Connector Plane / Blob / Property fbdev 模拟层 drm_fb_helper fbcon 兼容 GPU / Display 驱动(i915, msm, rockchip, vc4 ...) 实现 drm_driver 回调、KMS 对象注册、硬件寄存器操作 硬件层(Hardware) GPU 3D 引擎 显示控制器(CRTC) 显示接口(HDMI/DP/DSI) 显示面板 说明: 左侧 DRM Core + KMS 对象模型是主线路径;右侧 fbdev 模拟层仅用于兼容旧应用,不提供硬件合成能力。 用户空间通过 /dev/dri/card0 直接与 DRM/KMS 交互,通过 /dev/fb0 与 fbdev 模拟层交互。

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 通常遵循以下步骤,后续章节将逐一深入:

  1. 理解硬件显示管线: 梳理 SoC 的 CRTC 数量、Encoder 类型、Connector 接口、Plane 能力。
  2. 注册 DRM 驱动: 实现 drm_driver 结构体,调用 drm_dev_alloc / drm_dev_register。
  3. 实现 KMS 对象: 创建 CRTC、Encoder、Connector、Plane,并实现对应的回调函数。
  4. 实现 GEM 内存管理: 选择 GEM(简单场景)或 TTM(复杂 GPU),实现 dumb buffer 分配。
  5. 实现 Atomic Commit: 支持 drm_atomic_state 提交,确保无撕裂切换。
  6. 添加 fbdev 模拟层(可选): 使用 drm_fb_helper 兼容旧应用,但仅作为过渡。
  7. 用户空间适配: 修改应用或合成器,直接使用 DRM/KMS API。
学习建议: 本章是后续所有章节的基础。建议读者在阅读过程中,对照自己熟悉的硬件平台(如 i.MX8、RK3588、Raspberry Pi)的显示控制器手册,将 CRTC/Encoder/Connector/Plane 映射到具体硬件模块上,理解会更深刻。