架構(gòu)2--SurfaceFlinger 和 Hardware Composer

轉(zhuǎn)自:https://source.android.com/devices/graphics/?hl=zh-cn

SurfaceFlinger 和 Hardware Composer

擁有圖形數(shù)據(jù)緩沖區(qū)的確不錯(cuò)刑桑,如果還能在設(shè)備屏幕上查看它們就更是錦上添花了。這正是 SurfaceFlinger 和 Hardware Composer HAL 的用武之地善茎。

SurfaceFlinger

SurfaceFlinger 的作用是接受來自多個(gè)來源的數(shù)據(jù)緩沖區(qū)硬梁,對(duì)它們進(jìn)行合成佩憾,然后發(fā)送到顯示設(shè)備度陆。以前亮蒋,該過程通過軟件到硬件幀緩沖區(qū)(例如/dev/graphics/fb0)的位塊傳輸來實(shí)現(xiàn),但是這樣的日子已經(jīng)遠(yuǎn)去负甸。

當(dāng)應(yīng)用進(jìn)入前臺(tái)時(shí)流强,WindowManager 服務(wù)會(huì)向 SurfaceFlinger 請(qǐng)求一個(gè)繪圖 Surface。SurfaceFlinger 會(huì)創(chuàng)建一個(gè)其主要組件為 BufferQueue 的層呻待,而 SurfaceFlinger 是其消耗方打月。生產(chǎn)方端的 Binder 對(duì)象通過 WindowManager 傳遞到應(yīng)用,然后應(yīng)用可以開始直接將幀發(fā)送到 SurfaceFlinger蚕捉。

注意:盡管本部分使用 SurfaceFlinger 術(shù)語奏篙,但 WindowManager 會(huì)使用術(shù)語“窗口”(而不是“層”)…而將“層”用來表示其他內(nèi)容。(有人認(rèn)為 SurfaceFlinger 實(shí)際上應(yīng)稱為 LayerFlinger迫淹。)

大多數(shù)應(yīng)用通常在屏幕上有三個(gè)層:屏幕頂部的狀態(tài)欄秘通、底部或側(cè)面的導(dǎo)航欄以及應(yīng)用的界面。有些應(yīng)用會(huì)擁有更多或更少的層(例如敛熬,默認(rèn)主屏幕應(yīng)用有一個(gè)單獨(dú)的壁紙層肺稀,而全屏游戲可能會(huì)隱藏狀態(tài)欄)。每個(gè)層都可以單獨(dú)更新应民。狀態(tài)欄和導(dǎo)航欄由系統(tǒng)進(jìn)程渲染盹靴,而應(yīng)用層由應(yīng)用渲染,兩者之間不進(jìn)行協(xié)調(diào)瑞妇。

設(shè)備顯示會(huì)按一定速率刷新稿静,在手機(jī)和平板電腦上通常為每秒 60 幀。如果顯示內(nèi)容在刷新期間更新辕狰,則會(huì)出現(xiàn)撕裂現(xiàn)象改备;因此,請(qǐng)務(wù)必只在周期之間更新內(nèi)容蔓倍。在可以安全更新內(nèi)容時(shí)悬钳,系統(tǒng)便會(huì)收到來自顯示設(shè)備的信號(hào)盐捷。由于歷史原因,我們將該信號(hào)稱為 VSYNC 信號(hào)默勾。

刷新率可能會(huì)隨時(shí)間而變化碉渡,例如,一些移動(dòng)設(shè)備的刷新率范圍在 58 fps 到 62 fps 之間母剥,具體要視當(dāng)前條件而定滞诺。對(duì)于連接了 HDMI 的電視,刷新率在理論上可以下降到 24 Hz 或 48 Hz环疼,以便與視頻相匹配习霹。由于每個(gè)刷新周期只能更新屏幕一次,因此以 200 fps 的刷新率為顯示設(shè)備提交緩沖區(qū)只是在做無用功炫隶,因?yàn)榇蠖鄶?shù)幀永遠(yuǎn)不會(huì)被看到淋叶。SurfaceFlinger 不會(huì)在應(yīng)用提交緩沖區(qū)時(shí)執(zhí)行操作,而是在顯示設(shè)備準(zhǔn)備好接收新的緩沖區(qū)時(shí)才會(huì)喚醒伪阶。

當(dāng) VSYNC 信號(hào)到達(dá)時(shí)煞檩,SurfaceFlinger 會(huì)遍歷它的層列表,以尋找新的緩沖區(qū)栅贴。如果找到新的緩沖區(qū)斟湃,它會(huì)獲取該緩沖區(qū);否則筹误,它會(huì)繼續(xù)使用以前獲取的緩沖區(qū)。SurfaceFlinger 總是需要可顯示的內(nèi)容癣缅,因此它會(huì)保留一個(gè)緩沖區(qū)厨剪。如果在某個(gè)層上沒有提交緩沖區(qū),則該層會(huì)被忽略友存。

SurfaceFlinger 在收集可見層的所有緩沖區(qū)之后祷膳,便會(huì)詢問 Hardware Composer 應(yīng)如何進(jìn)行合成。

Hardware Composer

Hardware Composer HAL (HWC) 是在 Android 3.0 中推出的屡立,并且多年來一直都在不斷演進(jìn)直晨。它主要是用來確定通過可用硬件來合成緩沖區(qū)的最有效方法。作為 HAL膨俐,其實(shí)現(xiàn)是特定于設(shè)備的勇皇,而且通常由顯示設(shè)備硬件原始設(shè)備制造商 (OEM) 完成。

當(dāng)考慮疊加平面時(shí)焚刺,很容易發(fā)現(xiàn)這種方法的好處敛摘。它的目的是在顯示硬件(而不是 GPU)中將多個(gè)緩沖區(qū)合成在一起。例如乳愉,假設(shè)有一部處于縱向模式的普通 Android 手機(jī)兄淫,其狀態(tài)欄在頂部屯远,導(dǎo)航欄在底部,其他地方為應(yīng)用內(nèi)容捕虽。每個(gè)層的內(nèi)容都在單獨(dú)的緩沖區(qū)中慨丐。您可以使用以下任一方法處理合成:

將應(yīng)用內(nèi)容渲染到暫存緩沖區(qū)中,然后在其上渲染狀態(tài)欄泄私,再在其上渲染導(dǎo)航欄房揭,最后將暫存緩沖區(qū)傳送到顯示硬件。

將三個(gè)緩沖區(qū)全部傳送到顯示硬件挖滤,并告知它從不同的緩沖區(qū)讀取屏幕不同部分的數(shù)據(jù)崩溪。

后一種方法可以顯著提高效率。

顯示處理器功能差異很大斩松。疊加層的數(shù)量(無論層是否可以旋轉(zhuǎn)或混合)以及對(duì)定位和疊加的限制很難通過 API 表達(dá)伶唯。HWC 會(huì)嘗試通過一系列決策來適應(yīng)這種多樣性:

SurfaceFlinger 向 HWC 提供一個(gè)完整的層列表,并詢問“您希望如何處理這些層惧盹?”

HWC 的響應(yīng)方式是將每個(gè)層標(biāo)記為疊加層或 GLES 合成乳幸。

SurfaceFlinger 會(huì)處理所有 GLES 合成,將輸出緩沖區(qū)傳送到 HWC钧椰,并讓 HWC 處理其余部分粹断。

由于硬件供應(yīng)商可以定制決策代碼,因此可以在每臺(tái)設(shè)備上實(shí)現(xiàn)最佳性能嫡霞。

當(dāng)屏幕上的內(nèi)容沒有變化時(shí)瓶埋,疊加平面的效率可能會(huì)低于 GL 合成。當(dāng)疊加層內(nèi)容具有透明像素且疊加層混合在一起時(shí)诊沪,尤其如此养筒。在此類情況下,HWC 可以選擇為部分或全部層請(qǐng)求 GLES 合成端姚,并保留合成的緩沖區(qū)晕粪。如果 SurfaceFlinger 返回要求合成同一組緩沖區(qū),HWC 可以繼續(xù)顯示先前合成的暫存緩沖區(qū)渐裸。這可以延長閑置設(shè)備的電池續(xù)航時(shí)間巫湘。

運(yùn)行 Android 4.4 或更高版本的設(shè)備通常支持 4 個(gè)疊加平面。嘗試合成多于疊加層的層會(huì)導(dǎo)致系統(tǒng)對(duì)其中一些層使用 GLES 合成昏鹃,這意味著應(yīng)用使用的層數(shù)會(huì)對(duì)功耗和性能產(chǎn)生重大影響尚氛。

虛擬顯示設(shè)備

SurfaceFlinger 支持一個(gè)主要顯示設(shè)備(即內(nèi)置在手機(jī)或平板電腦中的顯示屏)、一個(gè)外部顯示設(shè)備(如通過 HDMI 連接的電視)以及一個(gè)或多個(gè)令合成的輸出在系統(tǒng)中可用的虛擬顯示設(shè)備洞渤。虛擬顯示設(shè)備可用于記錄屏幕或通過網(wǎng)絡(luò)發(fā)送屏幕怠褐。

虛擬顯示設(shè)備可以與主顯示設(shè)備共享相同的一組層(層堆疊),也可擁有自己的一組層您宪。虛擬顯示設(shè)備沒有 VSYNC奈懒,因此主顯示設(shè)備的 VSYNC 用于為所有顯示設(shè)備觸發(fā)合成奠涌。

在舊版本的 Android 中,虛擬顯示設(shè)備總是通過 GLES 合成磷杏,而 Hardware Composer 管理的合成僅用于主要顯示設(shè)備溜畅。在 Android 4.4 中,Hardware Composer 能夠參與虛擬顯示設(shè)備合成极祸。

正如您所預(yù)期的慈格,為虛擬顯示設(shè)備生成的幀會(huì)寫入 BufferQueue。

案例研究:screenrecord

screenrecord 命令可讓您將屏幕上顯示的所有內(nèi)容作為一個(gè) .mp4 文件記錄在磁盤上遥金。為此浴捆,我們必須從 SurfaceFlinger 接收合成的幀,將它們寫入視頻編碼器稿械,然后將已編碼的視頻數(shù)據(jù)寫入一個(gè)文件选泻。視頻編解碼器由單獨(dú)的進(jìn)程 (mediaserver) 進(jìn)行管理,因此我們必須在系統(tǒng)中移動(dòng)大量圖形緩沖區(qū)美莫。為了使其更具挑戰(zhàn)性页眯,我們嘗試以全分辨率錄制 60 fps 的視頻。高效完成這項(xiàng)工作的關(guān)鍵是 BufferQueue厢呵。

MediaCodec 類允許應(yīng)用以緩沖區(qū)中的原始字節(jié)或通過Surface來提供數(shù)據(jù)窝撵。當(dāng) screenrecord 請(qǐng)求訪問視頻編碼器時(shí),mediaserver 會(huì)創(chuàng)建一個(gè) BufferQueue襟铭,將其自身連接到消耗方端碌奉,然后將生產(chǎn)方端作為 Surface 傳回到 screenrecord。

然后寒砖,screenrecord 命令要求 SurfaceFlinger 創(chuàng)建一個(gè)鏡像主顯示設(shè)備的虛擬顯示設(shè)備(即赐劣,它具有完全相同的層),并指示它將輸出發(fā)送到來自 mediaserver 的 Surface入撒。在這種情況下隆豹,SurfaceFlinger 是緩沖區(qū)的生產(chǎn)方椭岩,而不是消耗方茅逮。

配置完成后,screenrecord 會(huì)等待顯示編碼數(shù)據(jù)判哥。在應(yīng)用繪制時(shí)献雅,其緩沖區(qū)會(huì)前往 SurfaceFlinger,SurfaceFlinger 將它們合成為單個(gè)緩沖區(qū)塌计,然后直接發(fā)送到 mediaserver 中的視頻編碼器挺身。screenrecord 進(jìn)程甚至從未看到過完整的幀。在內(nèi)部锌仅,mediaserver 具有自己的移動(dòng)緩沖區(qū)的方式章钾,這種方式還通過句柄傳遞數(shù)據(jù)墙贱,從而最大限度地降低開銷。

案例研究:模擬輔助顯示設(shè)備

WindowManager 可以要求 SurfaceFlinger 創(chuàng)建一個(gè)可見層贱傀,將 SurfaceFlinger 作為其 BufferQueue 消耗方惨撇。也可以要求 SurfaceFlinger 創(chuàng)建一個(gè)虛擬顯示設(shè)備,同樣以 SurfaceFlinger 作為其 BufferQueue 生產(chǎn)方府寒。如果連接它們并配置渲染到可見層的虛擬顯示設(shè)備魁衙,會(huì)出現(xiàn)什么情況?

創(chuàng)建一個(gè)閉合循環(huán)株搔,其中合成的屏幕顯示在窗口中剖淀。該窗口現(xiàn)在是合成輸出的一部分,因此在下一次刷新時(shí)纤房,該窗口中的合成圖像也會(huì)顯示窗口內(nèi)容(然后一直循環(huán)下去)纵隔。要實(shí)際查看該過程,請(qǐng)?jiān)谠O(shè)置中啟用開發(fā)者選項(xiàng)帆卓,選擇模擬輔助顯示設(shè)備巨朦,然后啟用一個(gè)窗口。另外有個(gè)好處是剑令,可使用 screenrecord 捕獲啟用顯示設(shè)備的操作糊啡,然后逐幀播放。

Except as otherwise noted, the content of this page is licensed under theCreative Commons Attribution 3.0 License, and code samples are licensed under theApache 2.0 License. For details, see ourSite Policies. Java is a registered trademark of Oracle and/or its affiliates.

Last updated 九月 13, 2017.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末吁津,一起剝皮案震驚了整個(gè)濱河市棚蓄,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌碍脏,老刑警劉巖梭依,帶你破解...
    沈念sama閱讀 223,126評(píng)論 6 520
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異典尾,居然都是意外死亡役拴,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,421評(píng)論 3 400
  • 文/潘曉璐 我一進(jìn)店門钾埂,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人褥紫,你說我怎么就攤上這事∷杩迹” “怎么了?”我有些...
    開封第一講書人閱讀 169,941評(píng)論 0 366
  • 文/不壞的土叔 我叫張陵,是天一觀的道長儡炼。 經(jīng)常有香客問我妓湘,道長乌询,這世上最難降的妖魔是什么多柑? 我笑而不...
    開封第一講書人閱讀 60,294評(píng)論 1 300
  • 正文 為了忘掉前任楣责,我火速辦了婚禮竣灌,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘秆麸。我一直安慰自己初嘹,他們只是感情好沮趣,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,295評(píng)論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著房铭,像睡著了一般。 火紅的嫁衣襯著肌膚如雪翁狐。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,874評(píng)論 1 314
  • 那天露懒,我揣著相機(jī)與錄音砂心,去河邊找鬼懈词。 笑死辩诞,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的译暂。 我是一名探鬼主播,決...
    沈念sama閱讀 41,285評(píng)論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼褐桌,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼象迎!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起砾淌,我...
    開封第一講書人閱讀 40,249評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎赃春,沒想到半個(gè)月后劫乱,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體织中,經(jīng)...
    沈念sama閱讀 46,760評(píng)論 1 321
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡衷戈,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,840評(píng)論 3 343
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了刁笙。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片谦趣。...
    茶點(diǎn)故事閱讀 40,973評(píng)論 1 354
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖前鹅,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情舰绘,我是刑警寧澤,帶...
    沈念sama閱讀 36,631評(píng)論 5 351
  • 正文 年R本政府宣布叉橱,位于F島的核電站者蠕,受9級(jí)特大地震影響窃祝,放射性物質(zhì)發(fā)生泄漏踱侣。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,315評(píng)論 3 336
  • 文/蒙蒙 一抡句、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧逞壁,春花似錦流济、人聲如沸腌闯。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,797評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至蘸泻,卻和暖如春嘲玫,著一層夾襖步出監(jiān)牢的瞬間蟋恬,已是汗流浹背趁冈。 一陣腳步聲響...
    開封第一講書人閱讀 33,926評(píng)論 1 275
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留沐绒,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,431評(píng)論 3 379
  • 正文 我出身青樓乔遮,卻偏偏與公主長得像取刃,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子璧疗,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,982評(píng)論 2 361

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