4. 图形驱动栈与软件框架

在 R-Car 平台上做多屏图形,真正决定“能不能显示、能不能同步、能不能稳定跑”的,不是某一个 API,而是从内核到应用的一整条软件栈。理解这条栈的分层与接口,才能判断问题出在哪一层,也才能正确配置多屏。本节按“自下而上”的顺序梳理:Linux DRM/KMS → Wayland/Weston → OpenGL ES/Vulkan 驱动 → R-Car 专用图形库与 BSP 集成 → 多屏配置接口。

一、最底层:Linux DRM/KMS 是显示的唯一出口

DRM(Direct Rendering Manager)负责 GPU 与显存管理,KMS(Kernel Mode Setting)负责显示控制器、CRTC、编码器、连接器与显示模式的设置。在 R-Car 上,显示相关的内核驱动通常以 DRM 驱动形式呈现,每个显示输出对应一个 CRTC + Encoder + Connector 的组合。应用层不直接操作寄存器,而是通过 /dev/dri/card0 这类设备节点,用 ioctl 或 libdrm 完成模式设置与帧缓冲提交。

关键概念是“平面(Plane)”:一个 CRTC 可以叠加多个 Plane,主平面(Primary)承载全屏内容,叠加平面(Overlay)可放视频或 UI 层。多屏的本质,就是把多个 CRTC 分别绑定到不同 Connector,并让每个 CRTC 拥有自己的 Plane 组合。可以用 modetest 快速查看当前拓扑:

modetest -M rcar-du -c   # 查看 connector 与当前连接状态
modetest -M rcar-du -p   # 查看 plane 与 CRTC 的可用组合
modetest -M rcar-du -s 39@35:1920x1080   # 将 connector 39 绑定到 CRTC 35

如果某个屏幕不亮,第一步应确认 Connector 的 status 是 connected 还是 disconnected,再看 CRTC 是否被占用。这是排障的起点。

二、中间层:Wayland/Weston 负责合成与窗口管理

DRM/KMS 之上是显示服务器。Wayland 是协议,Weston 是参考实现。Weston 通过 DRM 后端直接接管 KMS,把多个输出(Output)映射为多个屏幕,并在每个输出上合成客户端表面(Surface)。Weston 的配置文件 weston.ini 决定了输出布局、分辨率与缩放:

[output]
name=HDMI-A-1
mode=1920x1080
scale=1

[output]
name=LVDS-1
mode=1280x800
scale=1
transform=normal

多屏配置的核心是“输出名 + 模式 + 位置”。Weston 默认把多个输出并排扩展,若需要镜像,则需在合成器中显式设置相同坐标或使用克隆模式。应用通过 wl_output 获取每个输出的几何信息,再决定把窗口放到哪个屏幕。

三、渲染层:OpenGL ES 与 Vulkan 驱动

应用绘制使用 OpenGL ES 或 Vulkan。R-Car 的 GPU 驱动通常由 BSP 提供,包含用户态库(如 libGLESv2.so、libEGL.so)和内核态驱动。EGL 负责把渲染上下文与原生窗口系统(这里是 Wayland 或 GBM)连接起来。典型初始化顺序是:先获取 EGLDisplay,再选择配置,创建 EGLSurface,最后创建 GL 上下文。

Vulkan 在 R-Car 上通常通过 libvulkan.so 与 ICD 描述文件加载。与 GLES 不同,Vulkan 需要应用自己管理交换链(Swapchain),而交换链的呈现目标正是 Wayland Surface 或 GBM Surface。多屏场景下,每个屏幕对应一个交换链,应用需要为每个输出分别创建并提交。

四、R-Car 专用图形库与 BSP 集成

Renesas 在通用栈之上提供了专用图形库与 BSP 集成包,常见包括用于视频/图形协同的库、硬件合成与显示控制接口,以及针对 R-Car 的 EGL/GLES 扩展。BSP 集成主要体现在:内核 DRM 驱动、GPU 用户态驱动、Weston 后端补丁、以及 Yocto 层的配方(recipe)。实际工程中,图形栈版本必须与 BSP 版本匹配,否则容易出现 EGL 初始化失败或页面撕裂。

判断 BSP 集成是否正确的实用方法:运行 eglinfo 或 glxinfo(若可用),确认 EGL 客户端扩展中包含 EGL_WL_bind_wayland_display 或 GBM 相关扩展;若缺失,说明 Wayland/GBM 与 GPU 驱动的对接不完整。

五、多屏显示配置接口:从内核到应用

多屏配置接口分布在三个层次:内核层用 DRM ioctl 设置 CRTC/Connector;合成器层用 Weston 配置或 Wayland 协议设置输出;应用层用 EGL/Wayland API 查询输出并创建对应 Surface。一个典型的多屏应用流程是:连接 Wayland 显示 → 枚举 wl_output → 为每个输出创建窗口与 EGLSurface → 分别渲染并提交。

下面这张图把整条栈的层次、关键对象与多屏数据流放在一起,便于对照理解:

R-Car 多屏图形软件栈与数据流 应用层 多屏应用 wl_output 枚举 / 分屏渲染 OpenGL ES / Vulkan EGLSurface / Swapchain R-Car 专用图形库 硬件合成 / 显示控制扩展 Wayland 协议 / EGL 合成器层 Weston (Wayland) 多 Output 合成 / 布局 weston.ini mode / scale / transform DRM 后端 接管 KMS 输出 libdrm / ioctl 内核层 (DRM/KMS) CRTC 0 Plane: Primary → HDMI-A-1 CRTC 1 Plane: Primary → LVDS-1 Encoder HDMI / LVDS 时序转换 Connector status: connected EDID 读取 显示时序信号 硬件输出 HDMI 屏幕 1920×1080 @60Hz LVDS 屏幕 1280×800 @60Hz 同步与撕裂 VSync / 双缓冲 自下而上:内核 → 合成器 → 应用

图中可以看到,多屏并不是“一个屏幕画两次”,而是两个 CRTC 各自绑定 Connector,Weston 为每个 Output 维护独立合成路径,应用为每个输出创建独立 EGLSurface 或 Swapchain。任何一层配置错误,都会表现为某个屏幕黑屏、分辨率不对或画面撕裂。

六、多屏配置的实用检查清单

实际调试时,建议按以下顺序逐层确认,避免在应用层反复改代码却忽略底层:

  • 内核层:用 modetest -c 确认每个 Connector 的 status 与支持模式;确认 CRTC 数量足够,且没有被其他进程占用。
  • 合成器层:检查 weston.ini 中每个 output 的 name 是否与 modetest 输出一致;确认 mode 与屏幕 EDID 匹配。
  • 渲染层:确认 EGL 初始化成功,且 eglQueryString 返回的扩展包含 Wayland 或 GBM 绑定;Vulkan 需确认 ICD 文件路径正确。
  • 应用层:枚举 wl_output,为每个输出创建 Surface,并分别提交;注意每个输出的 scale 与 transform 会影响坐标换算。
常见误区:把多屏当成“一个超大 framebuffer 切两半”。在 DRM/KMS 中,每个 CRTC 有独立的扫描输出时序,跨屏拼接需要合成器或应用显式处理,不能依赖单一 framebuffer 自动分割。