Vsync-app 实例
本图是一个非常典型的Androiddisplay 系统如何利用Vsync-appevent 来更新App的view.
- App 通过Connection向EventThread 请求SW-VSYNCevent(最终并且通过callEventThread::requestNextVsync()).一般来说App 是通过Choreographer.doScheduleVsync()来请求Vsyncevent.
- DispSync 产生SW-VSYNC event并call DispSyncSource的onDispSyncEvent().
- DispSyncSource产生VSYNC-app信号跳变.
- 同时DispSyncSource使EventThread(app)的waitForEvent()结束sleep,并把VSYNC-app通知到App进程(gallery3d).
- Gallery3d 进程收到VSYNC-app信号,在其main线程(UI Thread)中开始draw 一个frame(发送draw command 给GL thread).
- GL Thread 开始draw view.
- 当GL thread 线程Draw 完一frame后,把draw buffer 放到buffer queue中.
- SufaceView中画好的buffer 数据增加为1.这个buffer 将被surfaceflinger 在适当的时候合成.
Vsync-sf实例
上图是一个典型的Vsync-sf的实例.
- App draw 完一个frame (SurfaceView) 并且把此frame通过调用BufferQueueProducer::queueBuffer() 放到bufferqueue中,并且通过call EventThread::requestNextVsync(),请求SW-VSYNCevent.此时由于DispSync没有fireSW-Sync event所以EventThread在EventThread::waitForEvent()中sleep.
- DispSync触发SW-SYNC event信号并且call DispSyncSource::onDispSyncEvent().
- 在DispSyncSource::onDispSyncEvent()中首先引起Vsync-sf跳变,然后在call EventThread::onVSyncEvent(nsecs_ttimestamp).
- 在EventThread::onVSyncEvent(nsecs_ttimestamp)中,会唤醒EventThread::waitForEvent()中的sleep,从而发送消息到Surfaceflinger.
- SurfaceFlinger收到EventThread发过来的Vsync-sf跳变信息, 开始合成dirty layer, 本例是SurfaceView.合成完以后发送更新的消息到DisplayHW.
- Display HW 收到更新的消息时,HW vsync event还没有来,因此DisplayHW sleep了一段事件.当HWvsync event到来时,DisplayHW 便更新其LCD的内容.把最新的内容显示在LCD上.
自此我们完成了Vsync子系统的分析.回到系统性能上,我们可以看出系统的性能(FPS) 可能于如下因素有关.
- DispSync的调度. DispSync是Vsync系统的心脏, 如果DispSync来不及调度, 则有可能由于去SW-SYNC event的产生不及时而影响系统的性能.
- View Draw 花费了过多的时间也会引性能问题, 如果其不能在一个SW-SYNC时间内完成, 那么此应用就会有一个Janks.由于现在的Androd系统都采用了HWUI,viewdraw 往往是GPU直接draw,所以很多时候是GPUperformance 问题.
- HW display 的性能问题.LCD 上所绘画的内容, 最终需要HW display在HW vsync触发是把其内容显示在LCD上.
- Binder 的调度问题, 我们可以看到无论是requestNextVsync () 还是queueBuffer() 都是App通过binder与surfaceflinger进程通信的.而这些binder在大多数时间是sleep的.如果binder由于CPU 调度而错过了一个Vsync跳变点, 那么就有一个frame发生Janks.