3. Linux图形基础

在车载Linux图形系统中,GPU驱动并不是孤立存在的。应用层通过图形API提交渲染命令,内核层则要完成显存管理、显示控制器配置、缓冲区共享与合成送显。要理解GPU与DRM的集成工程,必须先厘清一组基础术语:帧缓冲(Framebuffer)、DRM、KMS、GEM、TTM、DMA-BUF。它们不是并列的“功能模块”,而是从“像素内存”到“显示输出”再到“跨设备共享”的分层协作体系。

一、核心原理:从像素到屏幕的分层协作

最底层是帧缓冲(Framebuffer)。它本质上是一块内存区域,保存着屏幕每个像素的颜色值。早期Linux使用/dev/fb0这样的fbdev接口,应用直接映射显存并写入像素。fbdev简单,但无法处理多图层、硬件光标、页面翻转和GPU渲染同步,因此现代车载系统已逐步转向DRM。

DRM(Direct Rendering Manager)是Linux内核的图形子系统,负责统一管理GPU和显示控制器。它向上提供/dev/dri/card0、/dev/dri/renderD128等设备节点,向下协调GPU驱动、显示驱动和内存管理。DRM不是单一驱动,而是一套框架,包含KMS、GEM、TTM等子模块。

KMS(Kernel Mode Setting)负责显示模式设置,包括分辨率、刷新率、色彩格式、图层合成和输出路由。KMS把显示管线抽象为CRTC、Encoder、Connector、Plane等对象。CRTC代表扫描输出引擎,Encoder负责信号编码,Connector代表物理接口(如HDMI、LVDS、MIPI-DSI),Plane代表图层。车载多屏场景中,KMS决定哪个图层送到哪块屏幕,是显示控制的核心。

GEM(Graphics Execution Manager)是DRM中的图形缓冲区管理框架,主要负责GPU可访问的显存对象分配、句柄管理和同步。GEM提供DRM_IOCTL_GEM_CREATE、GEM_MMAP等接口,让用户空间创建和映射缓冲区。它更贴近GPU渲染,强调“可执行、可映射、可共享”。

TTM(Translation Table Manager)是更底层的内存管理器,负责把GPU缓冲区在不同内存域之间迁移,例如系统内存、显存、GTT(图形地址转换表)。TTM解决的是“缓冲区放在哪里、如何被GPU访问”的问题。GEM通常与TTM配合使用:GEM负责对象生命周期和用户接口,TTM负责实际内存放置与迁移。

DMA-BUF是跨设备缓冲区共享机制。它允许一个设备(如GPU)分配的缓冲区被另一个设备(如显示控制器、视频解码器、摄像头)直接访问,而无需拷贝。DMA-BUF通过文件描述符传递,配合dma_buf_export、dma_buf_attach、dma_buf_map_attachment等内核API完成共享。在车载系统中,DMA-BUF是实现“GPU渲染、显示送显、视频叠加”零拷贝的关键。

Linux图形基础术语分层关系 用户空间:图形应用 / Wayland合成器 / OpenGL ES / Vulkan 通过 libdrm、EGL、GBM 调用 DRM 接口 DRM 子系统(/dev/dri/card0、renderD128) 统一管理 GPU 渲染、显示输出、内存对象与跨设备共享 KMS 负责显示控制 | GEM 负责缓冲区对象 | TTM 负责内存迁移 | DMA-BUF 负责跨设备共享 KMS CRTC / Encoder Connector / Plane 分辨率、刷新率、图层合成 GEM 缓冲区对象 句柄 / 映射 / 同步 GPU 可访问显存管理 TTM 内存域迁移 系统内存 / 显存 / GTT 缓冲区放置与地址转换 DMA-BUF 跨设备共享 fd 传递 / 零拷贝 GPU、显示、视频共用 帧缓冲 Framebuffer:最终被扫描输出的像素内存 KMS 将 Plane 绑定到 Framebuffer,显示控制器读取像素送屏 关系:GEM/TTM 管理缓冲区 → DMA-BUF 共享 → KMS 配置显示 → Framebuffer 送显

二、方法流程:一次渲染送显的完整路径

以车载仪表盘渲染一帧为例,典型流程如下:

  1. 应用通过EGL/OpenGL ES创建渲染表面,底层由GBM或DRM分配GEM缓冲区。
  2. GEM对象若需要迁移到显存,由TTM决定放置位置并建立GPU地址映射。
  3. GPU执行渲染命令,将结果写入该缓冲区。
  4. 若该缓冲区需要送给显示控制器,通过DMA-BUF导出为文件描述符,并附加到KMS的Plane上。
  5. KMS配置CRTC、Encoder、Connector,将Plane与Framebuffer绑定,触发页面翻转。
  6. 显示控制器按刷新率扫描Framebuffer,像素最终输出到车载屏幕。
# 查看 DRM 设备与 KMS 状态
ls /dev/dri/
modetest -M rockchip -c   # 查看 Connector
modetest -M rockchip -p   # 查看 CRTC / Plane

# 查看 GEM 对象与 DMA-BUF 共享情况
cat /sys/kernel/debug/dri/0/gem
cat /sys/kernel/debug/dma_buf/bufinfo

三、案例场景:车载多屏与摄像头叠加

在智能座舱中,常见场景是:GPU渲染仪表盘和IVI界面,摄像头采集倒车影像,视频解码器播放多媒体,三路内容最终合成到中控屏和仪表屏。若没有DMA-BUF,每一路都要拷贝到CPU内存再送显,带宽和延迟都无法接受。实际工程中,摄像头输出DMA-BUF,视频解码器输出DMA-BUF,GPU渲染输出GEM缓冲区并导出DMA-BUF,KMS直接把这些缓冲区绑定到不同Plane,由显示控制器硬件合成。这样既降低CPU占用,也保证倒车影像的低延迟。

工程提示:车载项目调试显示异常时,优先确认三件事:KMS的Connector是否连接、Plane是否绑定正确的Framebuffer、DMA-BUF的格式与stride是否匹配。很多“黑屏”或“花屏”并非GPU渲染错误,而是KMS送显配置或DMA-BUF格式协商不一致。

四、误区与复盘:常见理解偏差

术语 常见误区 正确理解
Framebuffer 认为它等于DRM 它只是像素内存抽象,DRM是更上层的完整图形框架
GEM 认为GEM就是显存分配器 GEM负责对象和句柄,实际内存放置常由TTM完成
TTM 认为所有GPU都必须用TTM 部分驱动使用VRAM helper或自研内存管理,TTM是通用方案之一
DMA-BUF 认为它只是拷贝缓冲区 它强调共享与零拷贝,通过fd传递实现跨设备直接访问
KMS 认为KMS只负责设置分辨率 KMS还管理图层、Plane、页面翻转和输出路由
一句话总结:Framebuffer是“最终显示的像素”,DRM是“图形总管”,KMS管“怎么显示”,GEM管“缓冲区对象”,TTM管“缓冲区放哪”,DMA-BUF管“怎么跨设备共享”。理解这六者的分层与协作,是后续GPU驱动移植、显示调试和性能优化的基础。