圖形系統是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實例。