SurfaceFlinger及Android应用RenderThread角度观察Jank丢帧卡顿
SurfaceFlinger及Android应用RenderThread角度观察Jank丢帧卡顿
CPU、GPU、Display 三个部分:CPU 负责计算帧数据,把计算好的数据交给 GPU,GPU 会对图形数据进行渲染,渲染好后放到 buffer (图像缓冲区)存起来,然后 Display (屏幕或显示器)把 Buffer呈现到屏幕。
Google 在 Android 4.1 系统中对 Android Display 系统进行了重构,引入了 Project Butter(黄油计划):在系统收到 Vsync 信号后,上层 CPU 和 GPU 马上进行下一帧画面数据的处理,完成后及时将数据写入到 Buffer 中,Google 称之为 Drawing with Vsync。
在ViewRootImpl中完成对界面的measure、layout和draw等绘制流程后,用户依然还是看不到内容,因为Android系统的显示流程除了UI 线程的绘制外,还需要经过RenderThread线程的渲染处理,渲染完成后,还需要通过Binder调用“上帧”交给surfaceflinger进程进行合成后才能最终显示到屏幕上。
Android应用渲染流程中,应用扮演的是生产者角色,SurfaceFlinger扮演的是消费者,工作的流程如下:
应用在开始绘制渲染之前,需要通过调用dequeueBuffer从SurfaceFlinger管理的BufferQueue 申请一处于free状态的可用Buffer,如果此时没有可用Buffer则阻塞等待;
应用拿到可用的Buffer后,使用GPU绘制渲染,渲染完成后再通过Binder调用queueBuffer将数据返回给应用进程对应的BufferQueue,如果是 GPU 渲染的话,这里还有个 GPU处理的过程,所以这个 Buffer 不会马上可用,需要等 GPU 渲染完成的Fence信号,并申请sf的Vsync-sf唤醒消费者SurfaceFlinger进行消费;
SurfaceFlinger 收到 Vsync-sf 信号之后,开始准备合成,使用 acquireBuffer获取应用对应的 BufferQueue 中的 Buffer 并进行合成操作;
合成结束后,SurfaceFlinger 调用 releaseBuffer将 Buffer 置为可用的free状态,返回到应用对应的 BufferQueue中。
从 SurfaceFlinger 角度来说,在 App 连续的动画或者手指滑动列表时(关键是连续),如果有一个 Vsync 到来时候 ,App 没有可以用来合成的 Buffer,那么这个 Vsync 周期 SurfaceFlinger 就不会走合成逻辑(或者是去合成其他的 Layer),那么这一帧就会显示 App 的上一帧的画面,这里发生了卡顿;
从App的角度来看,如果渲染线程在一个 Vsync 周期内没有 queueBuffer 到 SurfaceFlinger 中 App 对应的 BufferQueue 中,那么我们认为这里发生了卡顿。
如果线程Running时长过长导致运行变慢,最终出现上帧超时而掉帧,就需要结合具体tag信息查看到底在执行什么逻辑,然后结合自身的代码实现看是否可以优化。或者看看当前JIT线程任务是否繁忙,判断是否是因为应用没有被及时编译成机器码而导致运行时长过长。
出于功耗节能的原因,VSYNC-sf与VSYNC-app并不一定会固定不停触发。如果app或sf并没有刷新画面的需求,那么触发信号进行绘制和合成是不必要的(功耗)。触发VSYNC-sf和VSYNC-app的两个EventThread会在requestNextVsync调用后才会将下一个VSYNC-sf或VSYNC-app发出。因此,当(各自EventThread)requestNextVsync没有调用时,VSYNC-app和VSYNC-sf也就出现异常。BufferQueueLayer::onFrameAvailable会在应用提交后调用,该方法通过调用SF的signalLayerUpdate触发产生下一个VSYNC-sf。
Android trace presentFence屏幕显示的帧-CSDN博客文章浏览阅读807次,点赞20次,收藏21次。在Android系统中,presentFence是屏幕显示帧的关键信号,当帧成功显示时,presentFence会发出信号。FrameMissed、GpuFrameMissed和HwcFrameMissed表示上一次合成的结果,SurfaceFlinger在每次被Vsync-sf唤醒时会检查上一次合成的presentFence是否已发出信号,若未发出则认为是帧丢失。BufferTx在queueBuffer后增加,在SurfaceFlinger合成时减少,其内有可用Buffer时,SurfaceFlingerhttps://blog.csdn.net/zhangphil/article/details/148099387