一、动画刷新基础:人眼视觉暂留原理、帧率与刷新率概念、Android显示系统架构概览
各位同学,咱们开始第一课。
做动画刷新驱动适配,说白了就是跟屏幕上的每一帧画面打交道。你想想看,手机屏幕上的画面为什么能动起来?为什么60Hz的屏幕看起来流畅,30Hz就卡得不行?这些问题的根,都在我们今天要聊的基础里。
我个人习惯,不管做什么驱动,先把物理原理和系统架构摸透。底层的寄存器配置、中断处理、buffer管理,全都建立在这些基础之上。好,咱们直接开整。
1.1 人眼视觉暂留——动画的生理基础
动画能骗过眼睛,靠的是人眼的一个生理特性:视觉暂留(Persistence of Vision)。
说白了,就是当一幅画面从眼前消失后,大脑还会把它“留”大约1/24秒。如果下一幅画面在这个时间内出现,大脑就会觉得两幅画面是连续的,从而产生“动”的错觉。
关键数字:人眼视觉暂留时间约为 40ms ~ 50ms。也就是说,只要画面更新的间隔小于这个时间,人眼就分辨不出闪烁。
我在项目中遇到过一件事:早期调一款低端平板,屏幕刷新率只有50Hz,但动画帧率跑到了60fps。结果画面撕裂严重,用户反馈说“屏幕在抖”。后来一查,是刷新率跟不上帧率,视觉暂留效应被打破了。嗯,这里要注意,视觉暂留是动画流畅的生理下限,但不是唯一条件。
1.2 帧率(FPS)与刷新率(Hz)——两个容易搞混的概念
这两个词,我见过太多人混着用了。咱们一次说清楚。
| 概念 | 英文 | 定义 | 谁决定的 |
|---|---|---|---|
| 帧率 | FPS (Frames Per Second) | GPU/CPU每秒能生成多少帧画面 | 应用层、渲染管线、GPU性能 |
| 刷新率 | Hz (Hertz) | 屏幕硬件每秒能显示多少帧画面 | 屏幕面板、驱动IC、DDIC配置 |
举个例子:
- 你玩《原神》,GPU拼了命跑出90fps,这叫帧率。
- 你的手机屏幕是60Hz的,每秒只能刷新60次画面,这叫刷新率。
- 结果呢?GPU多生成的30帧,屏幕根本来不及显示,要么丢掉,要么撕裂。
避坑指南:我曾经在适配一款90Hz屏幕时,只改了驱动里的刷新率参数,没管帧率同步。结果屏幕确实以90Hz在刷,但GPU只输出45fps,每一帧被重复显示了一次,看起来跟45Hz没区别。用户反馈“开了高刷跟没开一样”。后来加了帧率统计才发现问题。
所以,帧率和刷新率必须匹配。理想情况是:帧率 = 刷新率,或者帧率是刷新率的整数倍(比如60fps配120Hz,每帧刷两次)。否则就会出现卡顿、撕裂、掉帧。
1.3 Android显示系统架构概览——从App到屏幕的完整链路
好,现在咱们把视野拉高,看看Android系统里,一帧画面从诞生到显示,到底走了多远的路。
我画了一张架构图,你跟着箭头走一遍,基本就全明白了。
咱们从上往下捋一遍:
- 应用层:你的App通过Canvas、OpenGL ES或者Vulkan绘制画面。绘制结果是一块一块的图形缓冲区(GraphicBuffer)。
- 框架层:SurfaceFlinger是核心。它把多个App的缓冲区合成一张完整的屏幕画面。Choreographer负责协调帧率,VSync信号就是它管的。
- HAL层:硬件适配层。HWC(Hardware Composer)决定哪些图层由GPU合成,哪些由显示硬件直接合成。Gralloc管理图形内存。
- 内核层:驱动真正干活的地方。DRM/KMS管理显示模式和帧缓冲,GPU驱动处理渲染命令,显示控制器驱动控制屏幕时序。
个人经验:我刚开始做驱动时,总觉得HAL层是多余的,直接操作寄存器不香吗?后来发现,没有HAL层,上层App换一个屏幕就得改一遍驱动代码。HAL层就是那个“适配器”,让上层代码跟硬件解耦。你想想看,没有它,Android怎么支持几百种不同的屏幕面板?
1.4 关键角色:VSync——整个刷新流程的节拍器
说到刷新,绕不开VSync(垂直同步)。
VSync是屏幕硬件发出的一个脉冲信号,告诉系统:“我这一帧已经显示完了,可以准备下一帧了。” 整个Android的动画刷新,都是跟着VSync的节奏走的。
| VSync类型 | 来源 | 作用 |
|---|---|---|
| 硬件VSync | 显示控制器/DDIC | 由屏幕硬件产生,精确到微秒级 |
| 软件VSync | SurfaceFlinger | 基于硬件VSync模拟,用于Choreographer调度 |
我记得有一次调一个第三方屏幕,硬件VSync信号不稳定,有时候丢脉冲。结果SurfaceFlinger收不到VSync,以为屏幕没准备好,就一直不发新帧。画面直接卡死。后来我在驱动里加了VSync监测,发现丢脉冲就自动补偿,才算解决。
注意:VSync信号的质量,直接影响动画流畅度。如果VSync抖动超过1ms,用户就能感觉到卡顿。所以驱动里对VSync的处理,必须用中断,不能用轮询。轮询的延迟和不确定性,在刷新适配里是致命的。
1.5 本章小结
咱们今天聊了三件事:
- 视觉暂留是动画能成立的生理基础,40ms是底线。
- 帧率 vs 刷新率,一个软件生成,一个硬件显示,必须匹配。
- Android显示架构从App到屏幕,经过Framework、HAL、Kernel四层,VSync是贯穿始终的节拍器。
这些概念,后面每一章都会用到。尤其是VSync和帧率刷新率的关系,是驱动适配的核心矛盾。你把这些基础打牢了,后面调驱动、改参数、修bug,心里才有底。