刷新策略概述:全屏刷新、局部刷新、脏矩形(Dirty Rect)机制

帧缓冲的刷新策略直接决定了显示系统的功耗、流畅度与带宽占用。在嵌入式系统中,GPU 与显示控制器之间的数据传输是性能瓶颈之一,选择合适的刷新策略可以显著降低无效传输、减少功耗并提升帧率。本章从三种核心刷新策略入手,深入分析其原理、适用场景与性能权衡。

1. 全屏刷新 (Full Refresh)

全屏刷新是最基础的刷新方式:每次垂直同步(VBlank)周期到来时,显示控制器将整个帧缓冲区的数据从系统内存或显存传输到显示面板。无论屏幕内容是否发生变化,整个帧都会被重新发送。

核心特征: 实现简单、无状态跟踪开销、适用于动态变化剧烈的场景(如视频播放、3D 游戏)。但带宽浪费严重,尤其在静态 UI 或低刷新率需求场景下功耗较高。
全屏刷新流程 帧缓冲 完整帧数据 (1920x1080) 显示控制器 逐行扫描 全部像素 面板 特点 每帧传输完整数据 → 高带宽占用 | 无状态跟踪 → 实现简单 静态场景下功耗浪费严重 | 适用于视频/游戏等动态内容
全屏刷新性能指标(以 1920×1080@60fps 为例)
参数 数值 说明
每帧数据量 1920 × 1080 × 4 = 8.29 MB RGBA8888 格式
带宽需求 8.29 MB × 60 = 497.4 MB/s 仅帧缓冲传输
静态场景浪费 ≈ 100% 内容无变化时仍全量传输

2. 局部刷新 (Partial Refresh)

局部刷新仅更新屏幕中发生变化的部分区域。显示控制器通过配置寄存器指定起始坐标和宽高,DMA 控制器只传输该区域内的像素数据。这种方式在 UI 交互、文本输入、静态背景叠加动态元素等场景中效果显著。

适用场景: 智能手表表盘更新、车载仪表盘指针变化、电子墨水屏局部刷新、嵌入式 GUI 中的按钮点击反馈。局部刷新可将带宽降低 60%~90%,同时减少 GPU 渲染负载。
局部刷新流程 帧缓冲 脏区域 (x=50,y=45) DMA 控制器 仅传输脏区域 80×50 像素 + 位置信息 显示 控制器 覆盖更新 到面板 局部刷新关键参数 起始坐标 (x, y) | 区域宽高 (w, h) | 像素格式 | 行跨度 (stride) 带宽节省 = 1 - (脏区域面积 / 全屏面积) | 典型节省 70%~95%

3. 脏矩形机制 (Dirty Rect)

脏矩形机制是局部刷新的进阶实现。系统维护一个或多个“脏矩形”列表,记录自上次刷新以来所有发生变化的屏幕区域。在每次刷新周期中,将这些脏矩形合并、裁剪后,仅传输这些区域的数据。脏矩形机制是现代 GUI 框架(如 Qt、Flutter、Android SurfaceFlinger)的核心优化手段。

3.1 脏矩形合并策略

当多个脏矩形存在重叠或相邻时,需要进行合并以减少传输次数。常见的合并策略包括:

  • 直接合并: 将多个脏矩形合并为一个包含所有区域的最小外接矩形。实现简单,但可能引入额外像素传输。
  • 贪心合并: 按面积或位置排序后,依次合并相邻或重叠的矩形,减少冗余传输。
  • 栅格化合并: 将屏幕划分为固定大小的栅格(如 32×32),标记脏栅格后批量传输。适用于硬件加速。
脏矩形合并策略对比
策略 算法复杂度 传输效率 实现难度 典型场景
直接合并 O(n) 中(可能传输多余像素) 低 简单 UI、少量更新
贪心合并 O(n log n) 高(接近最优) 中 复杂 UI、多窗口
栅格化合并 O(1) 查表 高(硬件友好) 低(硬件支持) GPU 合成、游戏引擎

3.2 脏矩形生命周期

一个脏矩形从产生到清除经历以下阶段:

  1. 标记: 应用层或 GPU 渲染完成后,将发生变化的区域标记为脏。
  2. 收集: 合成器(Compositor)收集当前帧的所有脏矩形。
  3. 合并: 执行合并策略,生成最终的传输区域列表。
  4. 裁剪: 对合并后的区域进行边界裁剪,确保不超出屏幕范围。
  5. 传输: DMA 控制器按区域列表依次传输像素数据。
  6. 清除: 传输完成后清除脏标记,等待下一帧。
脏矩形生命周期与合并流程 ① 标记脏区域 应用层/GPU ② 收集脏矩形 合成器 ③ 合并策略 直接/贪心/栅格 ④ 裁剪 边界 ⑤ DMA 传输 按区域列表 ⑥ 清除脏标记 等待下一帧 脏矩形合并示例 R1 R2 R3 合并后: 180×50

4. 三种策略对比与选型

维度 全屏刷新 局部刷新 脏矩形机制
带宽效率 低(100% 传输) 中高(按区域) 高(合并后传输)
实现复杂度 低 中 高
硬件要求 无特殊要求 DMA 支持区域传输 DMA + 合成器支持
适用场景 视频、3D 游戏 UI 交互、仪表盘 复杂 GUI、多窗口
功耗影响 高 中 低
帧率稳定性 稳定(固定带宽) 波动(取决于脏区域大小) 较稳定(合并后区域可控)
工程注意事项:
  • 脏矩形机制在脏区域过多(如全屏滚动)时,合并后的区域可能接近全屏,此时应回退到全屏刷新以避免合并开销。
  • 局部刷新需要显示控制器支持非矩形区域更新,部分低端 LCD 控制器仅支持矩形区域。
  • DMA 传输的起始地址对齐(通常 4 字节或 8 字节)会影响局部刷新的性能,未对齐地址可能导致额外的内存读取。
  • 在多缓冲区场景下,脏矩形标记需要与缓冲区切换同步,避免撕裂(tearing)现象。

5. 实际案例:嵌入式 GUI 中的脏矩形优化

以基于 STM32F769 的嵌入式 GUI 系统为例,运行 emWin 图形库,屏幕分辨率 800×480,RGB565 格式:

  • 全屏刷新: 每帧传输 800 × 480 × 2 = 768 KB,60fps 下带宽需求 46 MB/s。
  • 脏矩形优化后: 典型 UI 交互(按钮点击、滑块拖动)脏区域约 100×50 像素,每帧传输 100 × 50 × 2 = 10 KB,带宽需求降至 0.6 MB/s,降低约 98.7%。
  • 实际效果: CPU 占用从 45% 降至 8%,系统功耗降低 62%,帧率从 30fps 提升至 60fps。
关键结论: 脏矩形机制是嵌入式帧缓冲性能优化的核心手段。在大多数 UI 场景中,脏区域面积通常小于全屏的 10%,合理利用脏矩形合并与 DMA 局部传输,可将帧缓冲带宽降低一个数量级,同时显著提升系统响应速度与能效比。