DRM显示驱动开发 硬件光标与VBlank同步 - 第3节

3.1 VBlank 定义与垂直消隐期

VBlank(Vertical Blanking Interval,垂直消隐期)是显示系统中一个基础且关键的时间窗口。在光栅扫描显示设备(如 LCD、OLED 屏幕)中,图像是从左到右、从上到下逐行扫描显示的。当扫描完一帧的最后一行后,电子枪(或等效的像素更新逻辑)需要从屏幕右下角回到左上角,开始下一帧的扫描。这个回扫过程所对应的时间段,就是 VBlank。

核心定义: VBlank 是两帧图像显示之间的“空白”时间间隔,在此期间没有新的像素数据被写入显示面板,显示器处于消隐状态。

3.1.1 垂直消隐期的物理意义

在 CRT 显示器时代,VBlank 是电子枪回扫的物理必需。在 LCD 等现代显示设备中,虽然不再有电子枪,但 VBlank 的概念被保留并扩展为一种重要的同步机制:

  • 帧缓冲切换安全窗口: 在 VBlank 期间切换显示缓冲区(Page Flip),可以避免用户看到撕裂(Tearing)的画面。
  • 显示控制器状态重置: 为下一帧的扫描线输出准备行指针、时钟等硬件状态。
  • 低功耗模式入口: 部分显示控制器在 VBlank 期间可进入低功耗状态。
关键认知: 即使现代显示器不再需要物理回扫,VBlank 作为“帧间安全切换窗口”的抽象概念,在所有图形驱动开发中依然不可替代。

3.1.2 VBlank 与 VSync 的关系

VBlank 是时间段,VSync(垂直同步)是信号。VSync 信号通常在每个 VBlank 开始时由显示控制器硬件产生,用于通知 GPU 或驱动:现在可以安全更新帧缓冲区了。

概念 类型 作用
VBlank 时间段 两帧之间的消隐窗口,持续若干微秒到毫秒
VSync 硬件信号/中断 VBlank 开始时刻的触发信号,驱动据此调度操作
VBlank 周期 时间间隔 从一次 VBlank 开始到下一次 VBlank 开始的时间
VBlank 与 VSync 时序关系 帧 N 显示 帧 N+1 显示 帧 N+2 显示 VBlank VBlank VSync 脉冲 VSync 脉冲 t VBlank 周期 = 1 / 刷新率

3.2 刷新率与 VBlank 周期

刷新率(Refresh Rate)是显示器每秒更新完整画面的次数,单位是 Hz。常见的刷新率有 60Hz、120Hz、144Hz 等。VBlank 周期与刷新率直接相关:

公式: VBlank 周期 = 1 / 刷新率

例如,60Hz 显示器的 VBlank 周期约为 16.67ms,120Hz 约为 8.33ms。但 VBlank 本身只是这个周期中的一小部分。

3.2.1 帧周期构成

一个完整的帧周期由两部分组成:

  • 有效显示时间(Active Area): 实际扫描并显示像素数据的时间。
  • 垂直消隐时间(VBlank): 回扫或等待时间。
刷新率 帧周期 典型 VBlank 时长 VBlank 占比
60 Hz 16.67 ms ~1.5 ms ~9%
120 Hz 8.33 ms ~0.8 ms ~9.6%
144 Hz 6.94 ms ~0.7 ms ~10%
240 Hz 4.17 ms ~0.4 ms ~9.6%
注意: 高刷新率下 VBlank 窗口极短(亚毫秒级),驱动必须在 VBlank 中断服务程序中高效完成帧缓冲切换或光标更新,否则可能错过窗口导致画面撕裂。
帧周期构成:有效显示区 vs VBlank 60 Hz 有效显示 ~15.2ms VBlank 16.67ms 120 Hz 有效显示 ~7.5ms VBlank 8.33ms VBlank 窗口随刷新率变化 • 刷新率越高,帧周期越短 • VBlank 绝对时长随刷新率升高而缩短 • VBlank 占比相对稳定(约 8%~10%) • 驱动需在 VBlank 内完成关键操作

3.3 VBlank 在显示流水线中的作用

在 DRM 显示驱动中,VBlank 是连接显示控制器、GPU 渲染和用户空间应用程序的同步枢纽。它在显示流水线中扮演以下关键角色:

3.3.1 帧缓冲切换(Page Flip)

当应用程序更新画面时,驱动需要在 VBlank 期间切换显示控制器读取的帧缓冲地址。如果切换发生在有效显示区,用户将看到屏幕上半部分显示旧帧、下半部分显示新帧的撕裂现象。

VBlank 同步的 Page Flip 流程:
  1. 应用程序提交新的帧缓冲(FB)到 DRM。
  2. 驱动等待下一个 VBlank 中断。
  3. 在 VBlank 中断服务程序中,更新显示控制器的帧缓冲基址寄存器。
  4. 显示控制器从下一帧开始读取新的 FB,用户看到完整的新画面。

3.3.2 硬件光标更新

硬件光标(Hardware Cursor)是显示控制器内置的叠加层,独立于主帧缓冲。更新光标位置或图像时,同样需要在 VBlank 期间进行,以避免光标闪烁或撕裂。

  • 光标位置更新: 修改光标位置寄存器,需在 VBlank 窗口内完成。
  • 光标图像切换: 更新光标缓冲区指针,需与帧同步对齐。
  • 光标使能/禁用: 状态切换也应在 VBlank 期间执行。

3.3.3 VBlank 中断与驱动调度

显示控制器在每次 VBlank 开始时触发硬件中断。DRM 驱动注册中断处理函数,在中断上下文中执行时间敏感操作:

// 简化的 VBlank 中断处理流程(伪代码)
static irqreturn_t display_vblank_handler(int irq, void *dev_id)
{
    struct drm_device *dev = dev_id;
    struct drm_crtc *crtc = ...;

    // 1. 更新 VBlank 计数器
    drm_crtc_handle_vblank(crtc);

    // 2. 检查是否有等待的 Page Flip
    if (crtc->state->pending_page_flip)
        commit_pending_flip(crtc);

    // 3. 更新硬件光标位置(如果需要)
    if (crtc->cursor_needs_update)
        update_hw_cursor(crtc);

    // 4. 唤醒等待 VBlank 的用户空间进程
    wake_up(&crtc->vblank_wait_queue);

    return IRQ_HANDLED;
}
VBlank 在显示流水线中的核心作用 用户空间应用 DRM 核心层 显示驱动 显示控制器硬件 VBlank 中断处理 硬件中断 唤醒等待队列 更新硬件寄存器 VBlank 同步操作 1. 帧缓冲切换 2. 硬件光标更新 3. VBlank 计数器递增 4. 等待队列唤醒 5. 性能统计采样 6. 垂直同步信号生成 7. 低功耗模式切换 8. 显示时序校准

3.3.4 用户空间 VBlank 等待

DRM 提供了 DRM_IOCTL_WAIT_VBLANK 等 ioctl,允许用户空间应用程序主动等待 VBlank 事件。这在以下场景中非常有用:

  • 游戏渲染循环: 等待 VBlank 后再提交新帧,实现垂直同步。
  • 视频播放: 与显示器刷新率对齐,避免丢帧或重复帧。
  • 合成器(Compositor): 在 VBlank 期间执行合成操作,减少延迟。
最佳实践: 在 DRM 驱动开发中,VBlank 中断处理函数应保持轻量,只执行必要的寄存器更新和状态标记。耗时的操作(如内存拷贝)应推迟到工作队列或线程上下文中执行,避免阻塞中断响应。

3.4 本章小结

VBlank 是显示驱动开发中不可回避的核心概念。理解 VBlank 的定义、周期构成以及在显示流水线中的多重作用,是后续学习硬件光标同步、Page Flip 优化和 VBlank 控制的基础。关键要点:

  • VBlank 是两帧之间的安全切换窗口,由显示控制器硬件保证。
  • VBlank 周期 = 1 / 刷新率,高刷新率下 VBlank 窗口极短。
  • VBlank 中断是驱动调度帧缓冲切换、光标更新等操作的同步锚点。
  • 用户空间通过 DRM ioctl 等待 VBlank,实现应用层垂直同步。