本页目录

DRM 与图形

Linux 有两套图形栈:fbdev(1990s)只是向显存写像素,DRM(2010s+)提供完整的现代 GPU 接口——KMS 管显示模式设置(atomic modesetting 让多显示器配置变成原子操作),GEM 管显存分配和跨进程共享(DMA-BUF 在 GPU 和 Wayland compositor 之间零拷贝传递 buffer)。amdgpu 和 i915 是这两个子系统的最大消费者。 内核版本: 2.6 ~ 6.x

概述

Linux 上有两套图形栈:fbdev(framebuffer,1990s)和 DRM(Direct Rendering Manager,2010s+)。fbdev 只是向显存写像素——没有 GPU 加速、没有多平面合成、没有 vsync 同步。DRM 提供完整的现代 GPU 接口:模式设置 (KMS)、显存管理 (GEM)、GPU 命令提交 (render) 和跨设备 buffer 共享 (DMA-BUF)。

用户态看到的是 /dev/dri/card0(主 GPU)和 /dev/dri/renderD128(render-only,不需要 mode setting 权限)。Mesa 和 Vulkan 驱动通过这些设备文件与内核通信。

DRM 三个核心子系统

KMS (Kernel Mode Setting): 显示管线

KMS 管理"如何把像素送到显示器"。涉及的硬件抽象:

  • CRTC (阴极射线管控制器——历史名称保留): 扫描控制器,从 framebuffer 读像素,按 timing 产生 video signal。每个 CRTC 驱动一个显示器
  • Encoder: 把 CRTC 的像素流编码为物理接口格式(TMDS for HDMI, LVDS for laptop panel, DisplayPort)
  • Connector: 物理端口(HDMI-A-1, DP-2, eDP-1)。检测显示器热插拔(HPD),读 EDID(显示器能力描述:支持的分辨率、刷新率)
  • Plane: 叠加层。Primary plane = 主 framebuffer。Overlay plane = 硬件加速的叠加(视频播放、鼠标光标)。现代 GPU 有 multiple planes 可以硬件合成

这些对象构成一条 pipeline: CRTC → Encoder → Connector。用户态通过 DRM_IOCTL_MODE_* ioctl 配置这条管线。

Atomic Modesetting

旧 API 是逐步设置参数——先改 CRTC mode,再改 connector,等——每一步中间态可能在屏幕上闪烁。Atomic modesetting 把整个显示状态封装为一个 drm_atomic_state 结构:

// 构造一次 atomic commit:
struct drm_atomic_state *state = drm_atomic_state_alloc(dev);
// 添加 CRTC/plane/connector property 修改
drm_atomic_commit(state);
// → 验证 (check) → 如果通过, 在 vblank 期间原子应用 → 无闪烁过渡

关键性质:全或无——验证失败(如分辨率不被支持),整个 commit 被拒绝,显示保持不变。这消除了"设备已改了一半"的中间态。

GEM (Graphics Execution Manager): 显存管理

GPU 内存不是简单的 malloc——它涉及 VRAM(显存)、GTT(Graphics Translation Table,部分可见的系统内存)、不同引擎的可见性约束。GEM 提供 driver-agnostic 的 buffer 管理:

// 分配 GPU buffer (由驱动实现):
struct drm_gem_object *obj = drm_gem_object_create(dev, size);
// → 返回 handle → 用户态 mmap → 访问 buffer 内容

关键特性:DMA-BUF。GPU buffer 可以导出为一个 file descriptor (drm_prime_handle_to_fd),另一个 GPU 或 V4L2 设备通过该 fd import——实现零拷贝跨设备共享⁠。Wayland compositor 就是这样把 client 渲染的 buffer 直接送到显示引擎,不需要 CPU 复制。

GPU 驱动架构: KMD + UMD 分离

现代 GPU 驱动分为两部分:

KMD (Kernel Mode Driver): amdgpu.ko, i915.ko, nouveau.ko。负责模式设置(显示)、显存管理(GEM/TTM)、命令提交(ring buffer)、fence 同步、固件管理。

UMD (User Mode Driver): Mesa (OpenGL/Vulkan) 或 NVIDIA 的闭源驱动。负责把 OpenGL/Vulkan API 翻译为 GPU 命令,着色器编译。通过 /dev/dri/renderD* 通信——不需要 mode setting 权限,也不需要 root。

KMD 提供的是基础设施⁠(分配 buffer、提交命令),UMD 提供的是应用 API。这种分离意味着 Mesa 可以独立于内核更新,新 OpenGL 版本不需要重编内核。

fbdev → DRM 迁移

fbdev 是 1990s 的帧缓冲接口:mmap(fbdev_fd) 得到显存映射,直接写像素。没有 vsync、没有多 plane、没有 GPU 加速。现代系统通过 drm_fb_helper 在 DRM 之上模拟 fbdev 接口——为了兼容老程序(如 fbi, directfb)。但底层仍然是 DRM。

参考

  • 源码⁠: drivers/gpu/drm/ (core), drivers/gpu/drm/amd/ (amdgpu), drivers/gpu/drm/i915/, include/drm/, include/uapi/drm/
  • 内核文档⁠: Documentation/gpu/
  • Mesa: docs.mesa3d.org

Keywords: DRM, KMS, GEM, atomic modesetting, CRTC, plane, DMA-BUF, amdgpu, i915, fbdev, Wayland