前面介绍了比较直观的framebuffer模块(负责把有一个内存地址ADDR的内容显示到屏上),hwc模块(叠加器,负责把surfaceFlinger送来的各种输入layer叠加到显存上),接下来开始介绍surfaceFLinger这个android显示相关最核心的系统服务。
文章目录
一、SurfaceFlinger定义与概念
Surface定义—供生产方与消耗方交换图形buf缓冲区
要理解SurfaceFlinger,当然先要理解surface这一基础概念。应用的每个 Window 会关联一个 Surface,Surface会关联真正的Graphic Buffer缓冲队列。android绘图的API很多,比如2D的绘图skia;3D的绘图OpenGL,Vulkan等,绘制到surface上。
SurfaceFlinger定义—统一管理surface的显示系统服务
SurfaceFlinger是一个系统服务,要实现了Surface的建立、控制、管理,创建display显示通道,控制GraphicBuffer申请轮转,基于Vsync事件同步 管理需要参与显示的surface给HWComposer硬件叠加器叠加显示到屏幕上。
SurfaceFlinger的基础框架client&&service(待更新)
二、SurfaceFlinger关键设计分析
BufferQueue—基础buffer轮转组件
BufferQueues 是 Android 图形组件之间的粘合剂。它们是一对队列,可以管理buffer从生产方到消耗方的固定周期。BufferQueue 是将缓冲区池与队列相结合的数据结构,用 Binder IPC 在进程之间传递buffer(生产者消费者可在不同进程)。图像生产方的一些示例包括由相机 HAL 或 OpenGL ES 游戏生成的相机预览。图像消耗方的一些示例包括 SurfaceFlinger 或显示 OpenGL ES 流的另一个应用,如显示相机取景器的相机应用。
Vsync—基于显示刷新事件的过程同步控制
基于Vsync信号(垂直时序刷新信号,可以简单理解为屏幕每刷新一帧上报一个事件,比如60HZ刷新的屏幕,vsync上报就是每秒均衡的60次) 同步显示buffer处理流水线(包括 渲染绘制、合成、显示),让绘制叠加显示更有序匹配。
SurfaceFlinger 通过调用 setVsyncEnabled 来控制 HWC 是否生成 VSYNC 事件。在 VSYNC 事件中,屏幕开始显示帧 N,而 SurfaceFlinger 开始为帧 N+1 合成,应用处理等待的输入并绘制生成帧 N+2。
CPU开始处理第1帧的纹理,处理完成之后GPU进行合成,在第1帧到来时候,显示屏显示第1帧,接着同步的CPU可以开始处理第2帧的纹理,GPU在CPU处理完成之后栅格化合成,在第2个垂直同步信号到来的时候,显示屏可以展示第2帧。如下图为 不基于vsync和基于vsync的两种方式;
Triple Buffer—三重缓存机制 提高对性能波动的容忍度
除了Vsync的机制,Android还使用了多级缓冲的手段以优化UI流程度。下图分别为 双buffer和三buffer缓存面临 性能波动的情况下 平滑处理情况。
可见 由于资源抢占等性能问题导致某一帧GPU掉链子,vsync信号到来时buffer B的数据还没准备好,而此时Display又在显示buffer A的数据,双buffer条件下 导致 后面CPU/GPU没有新的buffer着手准备数据,空白时间无事可做,后面Jank频出,如果三buffer情况,CPU/GPU可以用C buffer开始准备数据。
fence机制—提前送帧设计降低buffer轮转延时
fence:android4.4开始引入的一种资源同步机制,主要用于处理跨硬件场景,如CPU、GPU、HWC之间的buffer资源同步。简单来说,就是 生产者 把buffer 在生产完成之前 带上一个fence节点 提前送出去(常叫aquire fence),消费者需要使用的时候 通过fence去查看是否生产完 来决定使用。或者 消费者 收到buffer后准备使用前就 把buffer 带上一个fence(常叫release fence)还给生产者,生产者需要再绘制时 通过fence去查看 是否消费完成。核心就是省去buffer中间调度传递的时间; android中基本fence是使用图如下:
参考博文:https://blog.csdn.net/runafterhit/article/details/89293013
hwcomposer—多图层硬件叠加器封装
为了解放GPU的绘制能力,很多芯片厂家会提供硬件叠加合成,如果硬件叠加器支持的场景都可以走硬件叠加,解放GPU的绘制能力专心绘制,提升的渲染性能同时还能大幅度的降低功耗(GPU强绘制,叠加搬移并不擅长,高功耗)。
参考博文:https://blog.csdn.net/runafterhit/article/details/118884165
overlay—独立与主图层的单独显示层(依赖硬件,常作视频显示)
Overlay(覆盖)是一种数字视频的显示技术,它允许数字信号不经过显示芯片(GPU)处理,而直接通过显存输出到显示器屏幕上。Overlay显示模式最大的用途在于优化视频播放。很多芯片厂商在适配底层显示系统的时候,都会针对 播放视频内容做效果优化的视频独立通路得到更好的效果。
这个很好理解,视频的采集-编码-压缩传输-解码-调优显示 和 图形 和 绘制渲染 本身可以说是两个领域,各自有各自的技术衍生发展方向。一般基于android的TV和机顶盒都会支持overlay显示这种方式。
三、SurfaceFlinger关键流程分析(待更新)
1、从surface的resize用例关键流程分析
前期准备,启动binder线程池(支持client和service通信)
在关联SurfaceFlinger之前,先要准备好通信环境(client和service是基于binder通信的)。首先获取ProcessState对象。调用startThreadPool方法启动进程内的binder线程池。
// set up the thread-pool
sp<ProcessState> proc(ProcessState::self());
ProcessState::self()->startThreadPool();
应用创建client,通过client创建surface(service端创建layer)
SurfaceFlinger是一个系统服务,应用通过client客户端连接service服务,应用 用client创建surface(对应一个surfaceContrl来管理),服务端创建layer来表示应用的surface,layer中通过BufferQueue管理 生产消费模型,BufferQueue中包含BufferSlot数组 关联 真正的 绘制内存;
sp<SurfaceComposerClient> client = new SurfaceComposerClient(); // 创建与service关联的client
sp<SurfaceControl> surfaceControl = // 创建一个surface-通过surfaceContrl管理
client->createSurface(String8("resize"), 160, 240, PIXEL_FORMAT_RGB_565, 0);
sp<Surface> surface = surfaceControl->getSurface(); // 通过surfaceContrl获取surface
应用程序对窗口的控制和绘制surface提交
拿到surface之后就可以往上面开始绘制了,为了让画面能够显示出来,还需要设置zorder,也就是Z序,表示在图形叠加过程中的层位置,z越大越在顶层(可通过dumpsys看每个layer的z=xxx来看其大小)
// 设置surface的zorder 让他能够显示
SurfaceComposerClient::openGlobalTransaction();
surfaceControl->setLayer(100000);
SurfaceComposerClient::closeGlobalTransaction();
设置了Z序列后,图层可以显示出来了,通过surface->lock锁定取出outBuffer(锁定的含义就是此时这个buffer正在被使用,不能参与轮转合成),进行绘制(这里直接通过cpu进行memset,由于前面格式是RGB565,系统大端,16bit高位是表示blue,是一个蓝色的区域),绘制完成后unlockAndPost()解锁送显示(此动作会把buffer送到缓存区,并最后触发一个signalLayerUpdate通知SurfaceFlinger合并输出)。
ANativeWindow_Buffer outBuffer;
surface->lock(&outBuffer, NULL);
ssize_t bpr = outBuffer.stride * bytesPerPixel(outBuffer.format);
android_memset16((uint16_t*)outBuffer.bits, 0xF800, bpr*outBuffer.height);
surface->unlockAndPost();
绘制完成buffer提交显示后,还可以改变surface属性调整显示,比如setSize改变其大小;(这里是通过消息事件通知surfaceFlinger调整大小,没有改变buffer内容,因此不用lock重新绘制)
SurfaceComposerClient::openGlobalTransaction();
surfaceControl->setSize(320, 240);
SurfaceComposerClient::closeGlobalTransaction();
2、从SurfaceFlinger关键处理流程分析
收到surface的signal信号等待Vsync叠加
当APP绘制完成buffer后,unlockAndPost()最终会发送signal到SurfaceFlinger的消息队列MessageQueue,SurfaceFlinger会等待Vsync信号(垂直时序信号,每一帧显示画面一次事件)到来后进行 事件处理开始同步合成显示。
onMessageReceived主要收两类消息:1、INVALIDATE 无效重新绘制事件(触发检测是否需要重新绘制,需要就触发refresh事件); 2、REFRESH 刷新显示事件;
refresh核心流程如下:遍历参与显示的layer标记-收集需要真正显示的layer-设置HWC叠加器-执行硬件/软件叠加 显示工作
void SurfaceFlinger::handleMessageRefresh() {
// ...略...
// 1、按Zorder遍历每一个参与显示的layer,判断是否需要刷新并标记(发送signalLayerUpdate事件);
preComposition(refreshStartTime);
// 2、把全部layer按Z序取出过滤,保留在屏幕上非透明区域图层layersSortedByZ收集
rebuildLayerStacks();
// 3、设置HWComposer,将Layer中的信息传递给HWC叠加器 进行prepare
setUpHWComposer();
// 4、遍历全部显示通道,执行叠加显示主体presentAndGetReleaseFences叠加显示获取取releaseFence,
doComposition();
// 5、善后工作
postComposition(refreshStartTime);
// ...略...
}
四、SurfaceFlinger的典型android通路(待更新)
五、dumpsys SurfaceFlinger调试命令
通过dumpsys SurfaceFlinger可以查看surfaceFlinger相关系统信息,比如 系统中的layer信息,hwc合成信息,buffer信息 等等;
参考博文:https://blog.csdn.net/feifei_csdn/article/details/81703778
参考
官方文档:https://source.android.google.cn/devices/graphics
老罗:https://blog.csdn.net/luoshengyang/article/details/7846923
https://gitee.com/ldkxingzhe/ldk/blob/master/Android_Service_SurfaceFlinger.org
https://blog.csdn.net/freekiteyu/article/details/79483406
http://www.wowotech.net/graphic_subsystem/graphic_subsystem_overview.html
https://blog.csdn.net/haigand/article/details/90489336
https://zhuanlan.zhihu.com/p/62813895
https://blog.csdn.net/rabbyheathy/article/details/103748551
http://www.kokojia.com/article/18618.html
https://blog.csdn.net/feifei_csdn/article/details/81703778
https://www.imooc.com/article/279279