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 框架采用分层设计,将用户空间、内核核心和硬件驱动解耦:

DRM 框架分层架构 用户空间层 (Userspace) libdrm | Mesa 3D | X11/Wayland 合成器 | Vulkan/OpenGL 应用 ioctl / mmap 内核核心层 (Kernel Core) DRM Core (drm.ko) — 通用框架、对象管理、事件分发 KMS 子系统 — 模式设置、CRTC/Encoder/Connector/Plane 管理 GEM — 图形内存管理、DMA-BUF 共享 drm_driver 回调接口 硬件驱动层 (Driver) i915 (Intel) | amdgpu (AMD) | nouveau (NVIDIA) | msm (Qualcomm) | vc4 (Raspberry Pi) 物理硬件 (GPU + Display Controller + Connector)

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 显示管线阶段

  1. 帧缓冲读取:CRTC 通过 DMA 引擎从显存或系统内存中读取帧缓冲数据。
  2. 图层合成:多个 Plane 按照 Z-order 顺序进行 Alpha 混合,生成最终像素。
  3. 色彩处理:Gamma 校正、色彩空间转换(RGB ↔ YUV)、色域映射。
  4. 时序生成:CRTC 生成垂直/水平同步信号、消隐区间等视频时序。
  5. 编码传输:Encoder 将并行像素数据编码为串行差分信号(如 TMDS、DisplayPort 的 Main Link)。
  6. 物理输出:Connector 通过线缆将信号传输到显示器,显示器进行最终像素渲染。
显示管线数据流 帧缓冲 Framebuffer GEM 对象 图层合成 Plane 混合 Alpha 合成 色彩处理 Gamma 校正 色彩空间转换 时序生成 CRTC 时序 VBlank/HBlank 编码 Encoder TMDS/DP 显示管线关键指标 • 像素时钟 = 水平分辨率 × 垂直分辨率 × 刷新率 × (1 + 消隐开销) • 带宽需求 = 像素时钟 × 每像素比特数 (bpp) • 管线延迟 = 帧缓冲读取延迟 + 合成延迟 + 编码传输延迟 + 显示器响应延迟

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 与内核框架对接。