圖形系統是 Android 中很是重要的子系統,與其餘子系統相互協做,完成圖形界面的渲染和顯示。shell
概述
官方提供了一個圖形系統的關鍵組件協做圖,以下所示:緩存
這幅圖大體描述了圖形數據的流轉:OpenGL ES、MediaPlayer 等生產者生產圖形數據到 Surface,Surface 經過 IGraphicBufferProducer把 GraphicBuffer 跨進程傳輸給消費者SurfaceFlinger。微信
SurfaceFlinger 根據 WMS 提供的窗口信息合成全部的 Layer(對應於 Surface ),具體的合成策略由 hwcomposerHAL 模塊決定並實施,最後也是由該模塊送顯到 Display,而 Gralloc 模塊則負責分配圖形緩衝區。架構
不過該圖缺少層次感,經過下圖咱們詳細分析整個流程。併發
大致上,應用開發者能夠經過兩種方式將圖像繪製到屏幕上:app
Canvascomposer
OpenGL ES框架
Canvas 是一個2D圖形 API ,是 Android View 樹實際的渲染者。Canvas 又可分爲Skia 軟件繪製和 hwui 硬件加速繪製。異步
Android 4.0 以前默認是 Skia 繪製,該方式徹底經過 CPU 完成繪圖指令,而且所有在主線程操做,在複雜場景下單幀容易超過16ms致使卡頓。編輯器
從 Android 4.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主要有兩種合成方式:
OpenGL ES:把這些圖層合成到 FrameBuffer,而後把FrameBuffer提交給hwcomposer 完成剩餘合成和顯示工做。
hwcomposer:經過HWC模塊合成部分圖層和FrameBuffer,並顯示到Display。
BufferQueue
Android 圖形系統包含了兩對生產者和消費者模型,它們都經過 BufferQueue 進行鏈接:
Canvas 和 OpenGL ES 生產圖形數據,SurfaceFlinger消 費圖形數據。
SurfaceFlinger合成全部圖層的圖形數據,Display顯示合成結果。
Surface屬於APP進程,Layer屬於系統進程,若是它們之間只用一個Buffer,那麼必然存在顯示和性能問題,因此圖形系統引入了BufferQueue,一個Buffer用於繪製,一個Buffer用於顯示,雙方處理完以後,交換一下Buffer,這樣效率就高不少了。
BufferQueue的通訊流程以下所示:
生產者從BufferQueue出隊一個空閒GraphicBuffer,交給上層填充圖形數據;
數據填充後,生產者把裝載圖形數據的GraphicBuffer入隊到BufferQueue,也能夠丟棄這塊Buffer,直接cancelBuffer送回到BufferQueue;
消費者經過acquireBuffer獲取一個有效緩存;
完成內容消費後(好比上屏),消費者調用releaseBuffer把Buffer交還給BufferQueue。
GraphicBuffer表明的圖形緩衝區是由Gralloc模塊分配的,而且能夠跨進程傳輸(實際傳輸的只是一個指針)。
一般而言,APP端使用的是BufferQueue的IGraphicBufferProducer接口(在Surface類裏面),用於生產;SurfaceFlinger端使用的是BufferQueue的IGraphicBufferConsumer接口(在GLConsumer類裏面),用於消費。
Surface 與 SurfaceFlinger
Surface 表示 APP 進程的一個窗口,承載了窗口的圖形數據,SurfaceFlinger 是系統進程合成全部窗口(Layer)的系統服務,負責合成全部 Surface 提供的圖形數據,而後送顯到屏幕。
SurfaceFlinger 既是上層應用的消費者,又是 Display 的生產者,起到了承上啓下的做用。官方提供了一個架構圖,以下所示:
該圖可能較抽象,咱們經過一個實例理解下這層關係,下圖是微信添加朋友的彈窗界面:
咱們能夠經過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 實例。
做者:ltlovezh
連接:https://juejin.im/post/6844903955709820936
-- END --
進技術交流羣,掃碼添加個人微信:Byte-Flow
獲取視頻教程和源碼
推薦:
FFmpeg + OpenGL ES 實現 3D 全景播放器
FFmpeg + OpenGLES 實現視頻解碼播放和視頻濾鏡
以爲不錯,點個在看唄~
本文分享自微信公衆號 - 字節流動(google_developer)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。