在看高清电影的时候,需要帧率达到60fps(一秒显示60幅图画,即16毫秒显示一张图片),我们看起来才会比较舒服,流畅。在android4.1之前,都是通过2个buf进行显示的,或者更加多个。前面已经提到过一个buf进行显示存在的问题。
但是又两个或者多个buf也会存在缺陷:
上图是没有Vsync机制的显示图示。其上黄色区域,每个间隔代表16ms,蓝色后绿色代表buf.当cup显示第一个buf的时候,同时也应该填充第二个buf,但是又时候。cpu会偷懒,没有及时的去填充第二个buf,导致显示的还是之前的buf。这种情况如果比较频繁,会导致我们的视频看起来比较卡。其cpu没有被强制在Vsync处开始工作,下面是多次改进的流程图:
改进的思路很简单,当Vsync到来的时候,cpu,gpu必须工作(被强制),这样就变成了第二幅图示。但是这是理想的状态,如果cpu,或者gpu中有一个掉链子了怎么?
如上图中的第三个图示,假设某个时刻,GPU生病了,要做的工作太多克,没有忙过来,没有能及时完成。可以看到图示。绿色的框超过了时间点,但是没有办法,这样就产生了一个jankel(没有buf存放新数据),导致下个周期没有事情可做。并且会产生蝴蝶效应,不停的产生jankel。
该进的思路就是增加一个buf,变成了最后一个图示。相当于溜了一个备用的buf。
最后还有一个Vsync虚拟化的改进,分为Vsync-APP,Vsync-SF(surfaceFlinger)。前面提高,改进之后,gpu,cpu被强制在每个Vsync到来是工作,我们知道应用程序构造好数据只够要发送给surfaceFlinger:
surfaceFlinger会使用cpu,gpu进行渲染,即生成画面,最后发送给Disply,假如三个都是在Vsync到来时同时开始工作:
Vsync到来APP需要更新画面(填充buf),这个更新的画面需要发送给surfaceFlinger,但是surfaceFlinger在下个Vsync才能进行处理(合并新画面,把APP1的画面与其他的画面合成),合并好的画面在下一个Vsync到来是才能显示。这样的话,图片更新到图片显示,已经过去了两个Vsync,即36毫秒。这样的话,会使我们的应用程序感觉非常的卡。
那么怎么解决这个问题呢?他们的问题在于,所有单位在Vsync到来时,才开工。比如。即使APP已经准备好更新的画面了,surfaceFlinger也没有立即开工,他在等到Vsync到来时才开工。那如果能让surfaceFlinger及时开工,不就解决这个问题了吗?