Android - SurfaceFlinger 之 VSync 概括

标题先写。

之前看了一次SF, 感觉到一知半解, 画了些图, 总感觉没找到重点, 而且有些问题太深入(Fence), 反而影响整体的理解, 网上的文章要么太深入, 要么太浅显, 要么就是太依赖代码, 很少有一个把大致的流程介绍的浅显易懂的。
我觉得代码都是开源的, 哪里都有, 把重点问题列出来, 流程说清楚, 特别是白前因后果。
有了前因后果再去看问题, 就可以事半功倍。

----------------------吐槽分割线--------------------------

VSync 百度百科

V-Sync(垂直同步)这个功能事实上由来已久,早于Voodoo2的时代V-Sync就已引入到DirectX和Windows操作系统当中,其作用主要是让显卡的运算和显示器刷新率一致以稳定输出的画面质量。

VSync 解决的问题

tear.png

VSync 主要解决的就是上面这个问题。

产生的原因:

假设屏幕刷新率为60HZ, 显卡的刷新率是100HZ。
当显示第一帧的时候, 大家都没问题, 当显示第二帧的时候, 屏幕可能刷新到一半的时候, 显示的内容被显卡给更新了, 导致下半部分的内容跟上半部分不一致。 (这里涉及到了屏幕更新, 可以想象成从上到下,从左到右, 屏幕上的内容是一个一个像素的更新的, 只是更新速率够快, 人感觉不到)

解决的方式:

屏幕每次刷新之前就会发送一个信号告诉系统, 我现在准备刷新了, 然后系统再去调用CPU和GPU进行UI更新。

不使用VSync更新UI

no_vsync.png

显示器Display的更新速率是稳定的。
CPUGPU的绘制的时间是不固定的。
这就导致了Jank的出现。
1: 第一个VSync到来的时候,Display显示帧1, CPU休眠了一段时间再运行。
2: 第二个VSync到来的时候, 由于上一帧的帧2没有生成, 所以Display仍然显示帧1。(这就导致了画面延迟的问题)
3: 第三个VSync到来的时候, 帧2的内容终于显示完毕, Display显示帧2
总结: 由于CPUGPU更新的时间点不固定, 导致UI不能及时被显示到屏幕上。
(PS: Display把UI从内存显示到屏幕上, 这个时间很短暂, 可以忽略不计, 如果没有这个概念, 有些问题会想不明白)

使用VSync更新UI

usb_vsync.png

1: 第一个VSync到来的时候,Display显示帧1, CPU立刻运行,然后GPU也接着运行,并且生成帧2.
2: 第二个VSync到来的时候, 由于帧2已经生成, 所以Display显示帧2, CPU立刻运行,然后GPU也接着运行,并且生成内容3.
3: 第三个VSync到来的时候, 由于帧3已经生成, 所以Display显示帧3, CPU立刻运行,然后GPU也接着运行,并且生成内容4.
总结: 由于CPUGPU在每次VSync到来之后立刻执行, 如果能保证CPUGPU运行的时间在一个VSync的周期内, 那么是不会出现Jank的。

备注:
图片拷贝了网上的图片。

推荐阅读更多精彩内容