Android圖形系統(tǒng)概述

圖形系統(tǒng)是Android中非常重要的子系統(tǒng)暑竟,與其他子系統(tǒng)相互協(xié)作敬扛,完成圖形界面的渲染和顯示辙培。

概述

官方提供了一個(gè)圖形系統(tǒng)的關(guān)鍵組件協(xié)作圖,如下所示:

Android官方圖形架構(gòu)

這幅圖大致描述了圖形數(shù)據(jù)的流轉(zhuǎn):OpenGL ES崭庸、MediaPlayer等生產(chǎn)者生產(chǎn)圖形數(shù)據(jù)到Surface怀浆,Surface通過IGraphicBufferProducerGraphicBuffer跨進(jìn)程傳輸給消費(fèi)者SurfaceFlingerSurfaceFlinger根據(jù)WMS提供的窗口信息合成所有的Layer(對應(yīng)于Surface)怕享,具體的合成策略由hwcomposerHAL模塊決定并實(shí)施执赡,最后也是由該模塊送顯到Display,而Gralloc模塊則負(fù)責(zé)分配圖形緩沖區(qū)熬粗。不過該圖缺乏層次感搀玖,通過下圖我們詳細(xì)分析整個(gè)流程。
圖形系統(tǒng)架構(gòu)

大體上驻呐,應(yīng)用開發(fā)者可以通過兩種方式將圖像繪制到屏幕上:

  • Canvas
  • OpenGL ES

Canvas是一個(gè)2D圖形API灌诅,是Android View樹實(shí)際的渲染者。Canvas又可分為Skia軟件繪制和hwui硬件加速繪制含末。
Android4.0之前默認(rèn)是Skia繪制猜拾,該方式完全通過CPU完成繪圖指令,并且全部在主線程操作佣盒,在復(fù)雜場景下單幀容易超過16ms導(dǎo)致卡頓挎袜。
從Android4.0開始,默認(rèn)開啟硬件加速渲染,而且5.0開始把渲染操作拆分到了兩個(gè)線程:主線程和渲染線程盯仪,主線程負(fù)責(zé)記錄渲染指令紊搪,渲染線程負(fù)責(zé)通過OpenGL ES完成渲染,兩個(gè)線程可以并發(fā)執(zhí)行全景。

除了Canvas耀石,開發(fā)者還可以在異步線程直接通過OpenGL ES進(jìn)行渲染,一般適用于游戲爸黄、視頻播放等獨(dú)立場景滞伟。

從應(yīng)用側(cè)來看,不管是Canvas炕贵,還是OpenGL ES梆奈,最終渲染到的目標(biāo)都是Surface,現(xiàn)在比較流行的跨平臺UI框架Flutter在Android平臺上也是直接渲染到Surface称开。Surface是一個(gè)窗口亩钟,例如:一個(gè)Activity是一個(gè)Surface、一個(gè)Dialog也是一個(gè)Surface钥弯,承載了上層的圖形數(shù)據(jù)径荔,與SurfaceFlinger側(cè)的Layer相對應(yīng)。
Native層Surface實(shí)現(xiàn)了ANativeWindow結(jié)構(gòu)體脆霎,在構(gòu)造函數(shù)中持有一個(gè)IGraphicBufferProducer总处,用于和BufferQueue進(jìn)行交互。BufferQueue是連接Surface和Layer的紐帶睛蛛,當(dāng)上層圖形數(shù)據(jù)渲染到Surface時(shí)鹦马,實(shí)際是渲染到了BufferQueue中的一個(gè)GraphicBuffer,然后通過IGraphicBufferProducerGraphicBuffer提交到BufferQueue忆肾,讓SurfaceFlinger進(jìn)行后續(xù)的合成顯示工作荸频。

SurfaceFlinger負(fù)責(zé)合成所有的Layer并送顯到Display,這些Layer主要有兩種合成方式:

  • OpenGL ES:把這些圖層合成到FrameBuffer客冈,然后把FrameBuffer提交給hwcomposer完成剩余合成和顯示工作旭从。
  • hwcomposer:通過HWC模塊合成部分圖層和FrameBuffer,并顯示到Display场仲。

BufferQueue

Android圖形系統(tǒng)包含了兩對生產(chǎn)者和消費(fèi)者模型和悦,它們都通過BufferQueue進(jìn)行連接:

  1. CanvasOpenGL ES生產(chǎn)圖形數(shù)據(jù),SurfaceFlinger消費(fèi)圖形數(shù)據(jù)渠缕。
  2. SurfaceFlinger合成所有圖層的圖形數(shù)據(jù)鸽素,Display顯示合成結(jié)果。

Surface屬于APP進(jìn)程亦鳞,Layer屬于系統(tǒng)進(jìn)程馍忽,如果它們之間只用一個(gè)Buffer棒坏,那么必然存在顯示和性能問題,所以圖形系統(tǒng)引入了BufferQueue遭笋,一個(gè)Buffer用于繪制坝冕,一個(gè)Buffer用于顯示,雙方處理完之后坐梯,交換一下Buffer徽诲,這樣效率就高很多了。BufferQueue的通信流程如下所示:

  • 生產(chǎn)者從BufferQueue出隊(duì)一個(gè)空閑GraphicBuffer吵血,交給上層填充圖形數(shù)據(jù);
  • 數(shù)據(jù)填充后偷溺,生產(chǎn)者把裝載圖形數(shù)據(jù)的GraphicBuffer入隊(duì)到BufferQueue蹋辅,也可以丟棄這塊Buffer,直接cancelBuffer送回到BufferQueue挫掏;
  • 消費(fèi)者通過acquireBuffer獲取一個(gè)有效緩存侦另;
  • 完成內(nèi)容消費(fèi)后(比如上屏),消費(fèi)者調(diào)用releaseBuffer把Buffer交還給BufferQueue尉共。
  • GraphicBuffer代表的圖形緩沖區(qū)是由Gralloc模塊分配的褒傅,并且可以跨進(jìn)程傳輸(實(shí)際傳輸?shù)闹皇且粋€(gè)指針)。
  • 通常而言袄友,APP端使用的是BufferQueue的IGraphicBufferProducer接口(在Surface類里面)殿托,用于生產(chǎn);SurfaceFlinger端使用的是BufferQueue的IGraphicBufferConsumer接口(在GLConsumer類里面)剧蚣,用于消費(fèi)支竹。

Surface與SurfaceFlinger

Surface表示APP進(jìn)程的一個(gè)窗口,承載了窗口的圖形數(shù)據(jù)鸠按,SurfaceFlinger是系統(tǒng)進(jìn)程合成所有窗口(Layer)的系統(tǒng)服務(wù)礼搁,負(fù)責(zé)合成所有Surface提供的圖形數(shù)據(jù),然后送顯到屏幕目尖。SurfaceFlinger既是上層應(yīng)用的消費(fèi)者馒吴,又是Display的生產(chǎn)者,起到了承上啟下的作用瑟曲。官方提供了一個(gè)架構(gòu)圖饮戳,如下所示:

Android圖形管道

該圖可能較抽象,我們通過一個(gè)實(shí)例理解下這層關(guān)系测蹲,下圖是微信添加朋友的彈窗界面:
<img src="https://ltlovezh.oss-cn-beijing.aliyuncs.com/graphics/%E5%BE%AE%E4%BF%A1.png" width="300" />
我們可以通過adb shell dumpsys SurfaceFlinger查看該界面包含幾個(gè)窗口(Surface):

微信多Surface

SurfaceFlinger的dump信息可以看到:

  • com.tencent.mm/com.tencent.mm.ui.LauncherUI#0是微信的主窗口莹捡,并且鋪滿了整個(gè)屏幕(0,0,1080,2340)
  • PopupWindow:7020633#0是彈起的PopupWindow扣甲,它是一個(gè)獨(dú)立的窗口(Surface)篮赢,屏幕坐標(biāo)范圍是(599,210,1058,983)齿椅。
  • StatusBar#0表示系統(tǒng)狀態(tài)欄,由系統(tǒng)進(jìn)程負(fù)責(zé)繪制启泣,屏幕坐標(biāo)范圍是(0,0,1080,80)涣脚,即此狀態(tài)欄高80像素。
  • NavigationBar#0表示系統(tǒng)導(dǎo)航欄寥茫,由系統(tǒng)進(jìn)程負(fù)責(zé)繪制遣蚀,屏幕坐標(biāo)范圍是(0,2214,1080,2340),即此導(dǎo)航欄高126像素纱耻。
  • 最后兩個(gè)窗口也是系統(tǒng)窗口芭梯,具體作用不知。
  • 上述所有圖層的合成類型都是Device弄喘,即HWC硬件模塊負(fù)責(zé)合成這些Layer玖喘。
  • SurfaceFlinger會合成上述所有圖層(Layer),并送顯到內(nèi)嵌的Display 0蘑志。

總結(jié)

本篇文章從上到下簡述了Android圖形系統(tǒng)的流轉(zhuǎn)流程累奈,以及承載圖形數(shù)據(jù)流轉(zhuǎn)的重要結(jié)構(gòu):BufferQueue,最后通過dump信息論證了多Surface實(shí)例急但。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末澎媒,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子波桩,更是在濱河造成了極大的恐慌戒努,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,185評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件突委,死亡現(xiàn)場離奇詭異柏卤,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)匀油,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評論 3 393
  • 文/潘曉璐 我一進(jìn)店門缘缚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人敌蚜,你說我怎么就攤上這事桥滨。” “怎么了弛车?”我有些...
    開封第一講書人閱讀 163,524評論 0 353
  • 文/不壞的土叔 我叫張陵齐媒,是天一觀的道長。 經(jīng)常有香客問我纷跛,道長喻括,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,339評論 1 293
  • 正文 為了忘掉前任贫奠,我火速辦了婚禮唬血,結(jié)果婚禮上望蜡,老公的妹妹穿的比我還像新娘。我一直安慰自己拷恨,他們只是感情好脖律,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,387評論 6 391
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著腕侄,像睡著了一般小泉。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上冕杠,一...
    開封第一講書人閱讀 51,287評論 1 301
  • 那天微姊,我揣著相機(jī)與錄音,去河邊找鬼分预。 笑死柒桑,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的噪舀。 我是一名探鬼主播,決...
    沈念sama閱讀 40,130評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼飘诗,長吁一口氣:“原來是場噩夢啊……” “哼与倡!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起昆稿,我...
    開封第一講書人閱讀 38,985評論 0 275
  • 序言:老撾萬榮一對情侶失蹤纺座,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后溉潭,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體净响,經(jīng)...
    沈念sama閱讀 45,420評論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,617評論 3 334
  • 正文 我和宋清朗相戀三年喳瓣,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了馋贤。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,779評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡畏陕,死狀恐怖配乓,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情惠毁,我是刑警寧澤犹芹,帶...
    沈念sama閱讀 35,477評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站鞠绰,受9級特大地震影響腰埂,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜蜈膨,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,088評論 3 328
  • 文/蒙蒙 一屿笼、第九天 我趴在偏房一處隱蔽的房頂上張望牺荠。 院中可真熱鬧,春花似錦刁卜、人聲如沸志电。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽挑辆。三九已至,卻和暖如春孝情,著一層夾襖步出監(jiān)牢的瞬間鱼蝉,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評論 1 269
  • 我被黑心中介騙來泰國打工箫荡, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留魁亦,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,876評論 2 370
  • 正文 我出身青樓羔挡,卻偏偏與公主長得像洁奈,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子绞灼,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,700評論 2 354

推薦閱讀更多精彩內(nèi)容