2. KMS核心概念:CRTC、Encoder、Connector、Plane、Framebuffer的对象模型与生命周期
KMS(Kernel Mode Setting)是DRM子系统中负责显示输出配置的核心框架。要理解GPU如何将渲染好的画面最终呈现在显示器上,必须掌握KMS的五大核心对象:CRTC、Encoder、Connector、Plane和Framebuffer。它们共同构成了从内存中的像素数据到物理显示设备的完整数据管道。
2.1 五大核心对象概述
下表总结了每个KMS对象的角色、核心数据结构以及在显示管线中的位置:
| 对象 | 核心数据结构 | 角色描述 | 管线位置 |
|---|---|---|---|
| Framebuffer | struct drm_framebuffer |
内存中的像素数据缓冲区,包含颜色格式、宽高、步幅等信息 | 数据源(最上游) |
| Plane | struct drm_plane |
硬件图层,负责将Framebuffer的内容进行缩放、裁剪、旋转后合成到CRTC | 图层合成层 |
| CRTC | struct drm_crtc |
显示控制器,生成像素时钟、行/场同步信号,驱动显示时序 | 时序生成与扫描输出 |
| Encoder | struct drm_encoder |
信号编码器,将CRTC输出的并行像素数据转换为特定接口协议(如HDMI、DP、LVDS) | 信号编码转换 |
| Connector | struct drm_connector |
物理连接器,代表显示设备接口(如HDMI端口、DP端口),负责EDID读取和热插拔检测 | 物理连接(最下游) |
Framebuffer(由用户态创建)→ Plane → CRTC → Encoder → Connector。但它们的数据流方向是相反的:Framebuffer → Plane → CRTC → Encoder → Connector。
2.2 KMS显示管线数据流
下面的SVG图展示了从Framebuffer到Connector的完整数据流,以及每个对象在管线中的职责边界:
2.3 各对象的生命周期详解
2.3.1 Framebuffer:短暂的数据载体
Framebuffer是KMS对象中生命周期最短的。它由用户态应用程序通过drmModeAddFB()或drmModeAddFB2()创建,关联到一块已经分配好的GPU内存(GEM对象)。当用户态程序销毁Framebuffer或关闭DRM文件描述符时,内核会释放其引用。只有当所有引用它的Plane都停止使用后,Framebuffer才会被真正销毁。
// 用户态创建Framebuffer示例
struct drm_mode_fb_cmd2 fb_cmd = {
.width = 1920,
.height = 1080,
.pixel_format = DRM_FORMAT_XRGB8888,
.handles = { gem_handle },
.pitches = { 1920 * 4 },
};
int fb_id;
int ret = drmIoctl(fd, DRM_IOCTL_MODE_ADDFB2, &fb_cmd);
if (ret == 0) {
fb_id = fb_cmd.fb_id;
}
2.3.2 Plane:硬件图层单元
Plane代表GPU中的硬件图层(Overlay或Primary)。每个Plane可以绑定一个Framebuffer,并配置其在屏幕上的显示位置、缩放比例、透明度等属性。Plane的生命周期与驱动绑定:在bind()回调中创建,在unbind()中销毁。Plane分为三种类型:
- DRM_PLANE_TYPE_PRIMARY:主平面,每个CRTC必须关联一个,用于显示桌面背景或主应用窗口。
- DRM_PLANE_TYPE_OVERLAY:叠加平面,用于视频播放、UI叠加层等,支持硬件缩放和颜色空间转换。
- DRM_PLANE_TYPE_CURSOR:光标平面,专用于鼠标指针,通常尺寸固定(如64x64)。
2.3.3 CRTC:显示时序引擎
CRTC是KMS中最核心的对象,它负责生成显示时序(像素时钟、行同步、场同步、消隐区间等)。每个CRTC必须绑定至少一个Encoder才能输出信号。CRTC的状态包括:
- 激活状态:是否正在扫描输出。
- 显示模式:分辨率、刷新率、时序参数(
drm_display_mode)。 - 关联的Plane列表:当前参与合成的所有Plane。
2.3.4 Encoder:信号编码桥接
Encoder负责将CRTC输出的并行RGB/YCbCr像素数据转换为特定显示接口的串行信号。常见的Encoder类型包括:
| Encoder类型 | 对应接口 | 编码方式 |
|---|---|---|
DRM_MODE_ENCODER_TMDS |
HDMI / DVI | TMDS(最小化传输差分信号) |
DRM_MODE_ENCODER_DP |
DisplayPort | 微包化差分信号 |
DRM_MODE_ENCODER_LVDS |
LVDS(笔记本内屏) | 低压差分信号 |
DRM_MODE_ENCODER_DSI |
MIPI DSI(手机/平板) | 串行显示接口 |
2.3.5 Connector:物理接口与探测
Connector是KMS对象中最靠近硬件的部分,它代表一个物理显示接口。Connector的生命周期相对动态:
- 初始化时:驱动枚举所有物理接口,创建对应的Connector对象。
- 热插拔时:通过
drm_connector_register()和drm_connector_unregister()动态管理。 - 探测(Probe):每次状态变化时,驱动会读取显示器的EDID(扩展显示标识数据),获取支持的分辨率列表。
2.4 对象间的绑定关系
KMS对象之间通过引用指针和状态链表建立连接。下面的SVG图展示了典型的绑定拓扑:
2.5 对象生命周期管理最佳实践
- 初始化阶段:在
bind()中按顺序创建CRTC → Encoder → Connector → Plane。使用drmm_crtc_alloc_with_planes()等辅助函数简化内存管理。 - 状态管理:使用
drm_atomic_state进行事务性提交,避免部分更新导致的状态不一致。 - 热插拔处理:在
connector->funcs->detect()中实现EDID读取和状态更新,通过drm_kms_helper_hotplug_event()通知用户态。 - 销毁顺序:在
unbind()中先销毁Plane,再销毁CRTC/Encoder/Connector。Framebuffer由用户态负责释放。 - 引用计数:所有KMS对象都使用
kref引用计数,确保在最后一个引用释放前不会被销毁。
2.6 多平面合成(Multi-plane Composition)
现代GPU支持多个硬件平面同时合成,这是实现高性能显示的关键。多平面合成的核心优势在于:
- 减少GPU渲染负载:视频播放层、UI层、光标层各自独立更新,无需在GPU中合成完整帧。
- 降低内存带宽:每个平面只更新变化的部分,无需重新传输整个帧缓冲区。
- 支持硬件缩放:Overlay Plane通常支持独立的缩放系数,适合视频播放时的全屏切换。
// 多平面合成的Atomic Commit示例(用户态)
struct drm_mode_atomic atomic = {0};
uint32_t plane_ids[3] = { primary_id, overlay_id, cursor_id };
uint32_t fb_ids[3] = { primary_fb, overlay_fb, cursor_fb };
// 配置每个Plane的显示位置
struct drm_plane_state plane_states[3] = {
{ .crtc_id = crtc_id, .fb_id = primary_fb, .src_x = 0, .src_y = 0,
.src_w = 1920 << 16, .src_h = 1080 << 16,
.crtc_x = 0, .crtc_y = 0, .crtc_w = 1920, .crtc_h = 1080 },
{ .crtc_id = crtc_id, .fb_id = overlay_fb, .src_x = 0, .src_y = 0,
.src_w = 1280 << 16, .src_h = 720 << 16,
.crtc_x = 100, .crtc_y = 50, .crtc_w = 1280, .crtc_h = 720 },
{ .crtc_id = crtc_id, .fb_id = cursor_fb, .src_x = 0, .src_y = 0,
.src_w = 64 << 16, .src_h = 64 << 16,
.crtc_x = 800, .crtc_y = 600, .crtc_w = 64, .crtc_h = 64 }
};
// 提交原子更新
atomic.flags = DRM_MODE_ATOMIC_ALLOW_MODESET;
atomic.count_plane_deps = 0;
atomic.objects = (uint64_t)plane_ids;
atomic.plane_mask = (1 << 3) - 1;
// ... 填充其他字段后调用 drmIoctl(fd, DRM_IOCTL_MODE_ATOMIC, &atomic)
2.7 本章小结
KMS的五大核心对象构成了一个清晰的分层显示管线:
- Framebuffer:数据源,生命周期由用户态控制。
- Plane:图层合成单元,支持多平面并行处理。
- CRTC:时序引擎,驱动整个显示流程。
- Encoder:信号编码桥接,适配不同物理接口。
- Connector:物理接口,负责与显示设备通信。