图形系统是Android中很是重要的子系统,与其余子系统相互协做,完成图形界面的渲染和显示。shell
官方提供了一个图形系统的关键组件协做图,以下所示:
这幅图大体描述了图形数据的流转:OpenGL ES、MediaPlayer等生产者生产图形数据到Surface,Surface经过IGraphicBufferProducer
把GraphicBuffer
跨进程传输给消费者SurfaceFlinger
,SurfaceFlinger
根据WMS
提供的窗口信息合成全部的Layer
(对应于Surface),具体的合成策略由hwcomposer
HAL模块决定并实施,最后也是由该模块送显到Display,而Gralloc
模块则负责分配图形缓冲区。不过该图缺少层次感,经过下图咱们详细分析整个流程。segmentfault
大致上,应用开发者能够经过两种方式将图像绘制到屏幕上:缓存
Canvas
是一个2D图形API,是Android View树实际的渲染者。Canvas
又可分为Skia
软件绘制和hwui
硬件加速绘制。
Android4.0以前默认是Skia
绘制,该方式彻底经过CPU完成绘图指令,而且所有在主线程操做,在复杂场景下单帧容易超过16ms致使卡顿。
从Android4.0开始,默认开启硬件加速渲染,并且5.0开始把渲染操做拆分到了两个线程:主线程和渲染线程,主线程负责记录渲染指令,渲染线程负责经过OpenGL ES
完成渲染,两个线程能够并发执行。微信
除了Canvas
,开发者还能够在异步线程直接经过OpenGL ES
进行渲染,通常适用于游戏、视频播放等独立场景。架构
从应用侧来看,无论是Canvas
,仍是OpenGL ES
,最终渲染到的目标都是Surface,如今比较流行的跨平台UI框架Flutter
在Android平台上也是直接渲染到Surface。Surface是一个窗口,例如:一个Activity是一个Surface、一个Dialog也是一个Surface,承载了上层的图形数据,与SurfaceFlinger侧的Layer相对应。
Native层Surface实现了ANativeWindow
结构体,在构造函数中持有一个IGraphicBufferProducer
,用于和BufferQueue
进行交互。BufferQueue
是链接Surface和Layer的纽带,当上层图形数据渲染到Surface时,实际是渲染到了BufferQueue
中的一个GraphicBuffer
,而后经过IGraphicBufferProducer
把GraphicBuffer
提交到BufferQueue
,让SurfaceFlinger进行后续的合成显示工做。并发
SurfaceFlinger负责合成全部的Layer并送显到Display,这些Layer主要有两种合成方式:composer
OpenGL ES
:把这些图层合成到FrameBuffer,而后把FrameBuffer提交给hwcomposer
完成剩余合成和显示工做。hwcomposer
:经过HWC
模块合成部分图层和FrameBuffer,并显示到Display。Android图形系统包含了两对生产者和消费者模型,它们都经过BufferQueue进行链接:框架
Canvas
和OpenGL ES
生产图形数据,SurfaceFlinger
消费图形数据。SurfaceFlinger
合成全部图层的图形数据,Display显示合成结果。Surface属于APP进程,Layer属于系统进程,若是它们之间只用一个Buffer,那么必然存在显示和性能问题,因此图形系统引入了BufferQueue
,一个Buffer用于绘制,一个Buffer用于显示,双方处理完以后,交换一下Buffer,这样效率就高不少了。BufferQueue
的通讯流程以下所示:异步
acquireBuffer
获取一个有效缓存;releaseBuffer
把Buffer交还给BufferQueue。GraphicBuffer
表明的图形缓冲区是由Gralloc
模块分配的,而且能够跨进程传输(实际传输的只是一个指针)。IGraphicBufferProducer
接口(在Surface类里面),用于生产;SurfaceFlinger端使用的是BufferQueue的IGraphicBufferConsumer
接口(在GLConsumer类里面),用于消费。Surface
表示APP进程的一个窗口,承载了窗口的图形数据,SurfaceFlinger
是系统进程合成全部窗口(Layer)的系统服务,负责合成全部Surface提供的图形数据,而后送显到屏幕。SurfaceFlinger
既是上层应用的消费者,又是Display的生产者,起到了承上启下的做用。官方提供了一个架构图,以下所示:函数
该图可能较抽象,咱们经过一个实例理解下这层关系,下图是微信添加朋友的弹窗界面:
<img src="https://ltlovezh.oss-cn-beiji...; width="300" />
咱们能够经过adb shell dumpsys SurfaceFlinger
查看该界面包含几个窗口(Surface):
从SurfaceFlinger
的dump信息能够看到:
com.tencent.mm/com.tencent.mm.ui.LauncherUI#0
是微信的主窗口,而且铺满了整个屏幕(0,0,1080,2340)
。PopupWindow:7020633#0
是弹起的PopupWindow
,它是一个独立的窗口(Surface),屏幕坐标范围是(599,210,1058,983)
。StatusBar#0
表示系统状态栏,由系统进程负责绘制,屏幕坐标范围是(0,0,1080,80)
,即此状态栏高80像素。NavigationBar#0
表示系统导航栏,由系统进程负责绘制,屏幕坐标范围是(0,2214,1080,2340)
,即此导航栏高126像素。Device
,即HWC
硬件模块负责合成这些Layer。SurfaceFlinger
会合成上述全部图层(Layer),并送显到内嵌的Display 0
。本篇文章从上到下简述了Android图形系统的流转流程,以及承载图形数据流转的重要结构:BufferQueue
,最后经过dump信息论证了多Surface实例。