原创文章,转载注明出处。
一、Android流畅度概念
显示器刷新率(HZ):显示器物理刷新速率。
显卡合成帧速率 (FPS ):显卡一秒内能合成的帧数。
显示器依赖显卡提供的输入(显卡合成帧,显示器消费帧),典型的生产者消费者问题。那么自然会考虑到同步问题:
- 如果显卡输入小于显示器的刷新率,将会有画面被复用,出现卡顿感。
- 如果显卡输入大于显示器的刷新率,卡顿感是没有了,但是会有多出来的输入帧被浪费掉。
那么就引出了两个问题:
- 每秒刷新多少帧画面,用户会感觉到流畅?
- 如何保证显卡输出和屏幕刷新同步呢?
- 每秒刷新多少帧画面,用户会感觉到流畅?
由于人类眼睛的特殊生理结构,如果所看画面的帧率是高于24的话,则会认为是连贯的,这个现象称之为视觉暂留。一般来说,30fps是可以接受的。但是如果提升到60fps的话,可以明显提升交互感和逼真感,超过75fps则不容易察觉到有明显的流畅度提升了。另外,在分辨率固定的情况下,刷新率越高,对显卡的数据处理能力要求也越高,例如:当画面的分辨率是1024×768时,画面的刷新率要达到80帧/秒,那么显卡在一秒钟内需要处理的像素量就达到了“1024×768×80”。为了将资源利用达到最大化,Android系统将输出的帧率固定在了60fps。那么要求最少16.67ms要绘制出一帧并显示出来,这样用户将会感觉非常流畅。
- 如何保证显卡输出和屏幕刷新同步呢?
Android系统引入了垂直同步信号(VSync)来解决此问题。每16.6ms发送一次垂直同步信号,通知CPU与GPU在这个时间段内处理UI任务,只能保证整个流程步调一致而已。
讲到垂直同步,那么需要先简单交代下图形系统整个生产消费模型,简单示意如下:
在图形系统中,主要有两对生产者消费者模型:
应用层作为生产者,通过软件绘制(CPU绘制)/硬件绘制(GPU绘制)途径,分别由Skia/OpenGl绘图引擎绘制出UI图形数据,由GraphicBuffer作为数据载体,交由消费者SurfaceFlinger去把多层视图计算、裁剪、组合为最终视图,然后SurfaceFlinger作为生产者把最终的UI视图交由HWComposer或OpenGL合成最终的像素点数据,由FrameBuffer作为数据载体,供消费者显示器使用。
那么具体Vsync怎么同步呢?
硬件Vsync信号发出,由SurfaceFlinger接收,执行消费UI合成送显素材的操作,同时SurfaceFlinger把信号分发给Choreographer,它负责同步应用层UI的绘制,包括动画、输入和绘制的时机都由它来统一调度触发时机。
在第一次同步信号发出过程中,SurfaceFlinger轮空,因为还没有可消费的帧素材,第一轮主要由Choreographer通知注册监听的动画、输入和绘制执行响应操作,准备好第一帧,这一帧会在一下轮Vsync信号发出时被SurfaceFlinger消费,因此应用层的UI绘制是领先于SurfaceFlinger一轮的。
3 流畅度问题探讨
Vsync解决了同步问题,那么要保证流畅度,必须在16.6ms内完成UI任务。那么在哪些情况下无法保证绘制在16.6ms内完成呢?
1)绘制本身任务太重,导致耗时。
2)Handler更新UI,但是之前的消息任务耗时,导致当前UI绘制被delay。
3)当前时间内没有得到CPU调度。
网友评论