關(guān)于 Android 渲染你應(yīng)該了解的知識(shí)點(diǎn)

前言

談到AndroidUI繪制固额,大家可能會(huì)想到onMeasureonLayout煞聪、onDraw三大流程斗躏。但我們的View到底是如何一步一步顯示到屏幕上的?onDraw之后到View顯示到屏幕上昔脯,具體又做了哪些工作?
帶著這些問(wèn)題啄糙,我們今天就深入學(xué)習(xí)一下Android渲染的流程吧,本文主包括以下內(nèi)容:

  1. Android渲染的整體架構(gòu)是怎樣的?
  2. Android渲染的生產(chǎn)者包括哪些云稚?SkiaOpenGl的區(qū)別是什么隧饼?
  3. 什么是硬件加速?硬件繪制與軟件繪制的區(qū)別
  4. Android渲染緩沖區(qū)是什么静陈?什么是黃油計(jì)劃?
  5. Android渲染的消費(fèi)者是什么? 什么是SurfaceFlinger?

Android渲染整體架構(gòu)


我們先來(lái)看一下Android渲染的整體架構(gòu)燕雁,具體可分為以下幾個(gè)部分

  • image stream produceers: 渲染數(shù)據(jù)的生產(chǎn)者,如Appdraw方法會(huì)把繪制指令通過(guò)canvas傳遞給framework層的RenderThread線程鲸拥。
  • native Framework: RenderThread線程通過(guò)surface.dequeue得到緩沖區(qū)graphic bufer拐格,然后在上面通過(guò)OpenGL來(lái)完成真正的渲染命令。在把緩沖區(qū)交還給BufferQueue隊(duì)列中刑赶。
  • image stream consumers: surfaceFlinger從隊(duì)列中獲取數(shù)據(jù)捏浊,同時(shí)和HAL完成layer的合成工作,最終交給HAL展示撞叨。
  • HAL: 硬件抽象層金踪。把圖形數(shù)據(jù)展示到設(shè)備屏幕

可以看出浊洞,這其實(shí)是個(gè)很典型的生產(chǎn)者消費(fèi)者模式


  • 圖像生產(chǎn)者: 也就是我們的APP,再深入點(diǎn)就是canvas->surface胡岔。
  • 圖像消費(fèi)者:SurfaceFlinger
  • 圖像緩沖區(qū):BufferQueue法希,一般是3緩沖區(qū)

下面我們就從生產(chǎn)者,消費(fèi)者靶瘸,緩沖區(qū)三個(gè)部分來(lái)詳細(xì)了解下Android渲染的過(guò)程

圖像生產(chǎn)者

從上面的架構(gòu)圖可知铁材,圖像的生產(chǎn)者主要有MediaPlayerCameraPreview奕锌,NDK(Skia)著觉,OpenGl ES
其中MediaPlayerCamera Preview是通過(guò)直接讀取圖像源來(lái)生成圖像數(shù)據(jù)惊暴,NDK(Skia)饼丘,OpenGL ES是通過(guò)自身的繪制能力生產(chǎn)的圖像數(shù)據(jù)

OpenGLVulkan辽话、Skia的區(qū)別

  • OpenGL: 是一種跨平臺(tái)的3D圖形繪制規(guī)范接口肄鸽。OpenGL EL則是專(zhuān)門(mén)針對(duì)嵌入式設(shè)備,如手機(jī)做了優(yōu)化油啤。
  • Skiaskia是圖像渲染庫(kù)典徘,2D圖形繪制自己就能完成。3D效果(依賴(lài)硬件)由OpenGL益咬、Vulkan逮诲、Metal支持。它不僅支持2D幽告、3D梅鹦,同時(shí)支持CPU軟件繪制和GPU硬件加速。Android冗锁、flutter都是使用它來(lái)完成繪制齐唆。
  • Vulkan: Android引入了Vulkan支持。VulKan是用來(lái)替換OpenGL的冻河。它不僅支持3D箍邮,也支持2D,同時(shí)更加輕量級(jí)

硬件加速

關(guān)于硬件加速叨叙,相信大家也經(jīng)常聽(tīng)到锭弊,尤其是有些API不支持硬件加速,因此需要我們手動(dòng)關(guān)閉摔敛,那么硬件加速到底是什么呢?

CPUGPU的區(qū)別

除了屏幕廷蓉,UI 渲染還要依賴(lài)另外兩個(gè)核心的硬件:CPUGPU

  • CPUCentral Processing Unit马昙,中央處理器)桃犬,是計(jì)算機(jī)系統(tǒng)的運(yùn)算和控制核心,是信息處理行楞、程序運(yùn)行的最終執(zhí)行單元攒暇;
  • GPUGraphics Processin Unit,圖形處理器)子房,是一種專(zhuān)門(mén)用于圖像運(yùn)算的處理器形用,在計(jì)算機(jī)系統(tǒng)中通常被稱(chēng)為 "顯卡"的核心部件就是 GPU

UI 組件在繪制到屏幕之前证杭,都需要經(jīng)過(guò) Rasterization(柵格化)操作田度,而柵格化又是一個(gè)非常耗時(shí)的操作。


Rasterization 柵格化是繪制那些 Button解愤、Shape镇饺、PathString送讲、Bitmap 等顯示組件最基礎(chǔ)的操作奸笤。柵格化將這些 UI 組件拆分到顯示器的不同像素上進(jìn)行顯示。這是一個(gè)非常耗時(shí)的操作哼鬓,GPU 的引入就是為了加快柵格化监右。

硬件繪制與軟件繪制

  • 從圖中可以看到,軟件繪制使用 Skia 庫(kù)异希,它是一款能在低端設(shè)備健盒,如手機(jī)呈現(xiàn)高質(zhì)量的 2D 跨平臺(tái)圖形框架,類(lèi)似 Chrome称簿、Flutter 內(nèi)部使用的都是 Skia 庫(kù)味榛。
  • 硬件繪制的思想就是通過(guò)底層軟件代碼,將 CPU 不擅長(zhǎng)的圖形計(jì)算轉(zhuǎn)換成 GPU 專(zhuān)用指令予跌,由 GPU 完成繪制任務(wù)搏色。

所以說(shuō)硬件加速的本質(zhì)就是使用GPU代替CPU完成Graphic Buffer繪制工作,以實(shí)現(xiàn)更好的性能券册,Android從4.0開(kāi)始默認(rèn)開(kāi)啟了硬件加速频轿,但還有一些API不支持硬件加速,因此需要手動(dòng)關(guān)閉硬件加速烁焙。
需要注意的是航邢,軟件繪制使用的Skia庫(kù),但這不代表Skia不支持硬件加速骄蝇,從Android 8開(kāi)始膳殷,我們可以選擇使用Skia進(jìn)行硬件加速,Android 9開(kāi)始就默認(rèn)使用Skia來(lái)進(jìn)行硬件加速九火。Skia的硬件加速主要是通過(guò) copybit 模塊調(diào)用OpenGL或者SKia來(lái)實(shí)現(xiàn)赚窃。

圖像緩沖區(qū)

Android中的圖像生產(chǎn)者OpenGL册招,SkiaVulkan將繪制的數(shù)據(jù)存放在圖像緩沖區(qū)中勒极,Android中的圖像消費(fèi)SurfaceFlinger從圖像緩沖區(qū)將數(shù)據(jù)取出是掰,進(jìn)行加工及合成
那么圖像緩沖區(qū)我們又需要注意哪些內(nèi)容呢?

黃油計(jì)劃

優(yōu)化是無(wú)止境的,Google 在 2012 年的 I/O 大會(huì)上宣布了 Project Butter 黃油計(jì)劃辱匿,并且在 Android 4.1 中正式開(kāi)啟了這個(gè)機(jī)制键痛。

VSYNC信號(hào)

VSYNC(Vertical Synchronization)是理解 Project Butter 的核心。對(duì)于 Android 4.0匾七,CPU 可能會(huì)因?yàn)樵诿ζ渌氖虑樾醵蹋瑢?dǎo)致沒(méi)來(lái)得及處理 UI 繪制。
為了解決這個(gè)問(wèn)題昨忆,系統(tǒng)在收到VSync信號(hào)后丁频,將馬上開(kāi)始下一幀的渲染。即一旦收到VSync通知(16ms觸發(fā)一次)扔嵌,CPUGPU 才立刻開(kāi)始計(jì)算然后把數(shù)據(jù)寫(xiě)入buffer限府。如下圖

CPU/GPU根據(jù)VSYNC信號(hào)同步處理數(shù)據(jù),可以讓CPU/GPU有完整的16ms時(shí)間來(lái)處理數(shù)據(jù)痢缎,減少了jank胁勺。
一句話總結(jié),VSync同步使得CPU/GPU充分利用了16.6ms時(shí)間独旷,減少jank署穗。

三緩沖機(jī)制

Android 4.0之前,Android采用雙緩沖機(jī)制嵌洼,讓繪制和顯示器擁有各自的bufferGPU 始終將完成的一幀圖像數(shù)據(jù)寫(xiě)入到 Back Buffer案疲,而顯示器使用 Frame Buffer,當(dāng)屏幕刷新時(shí)麻养,Frame Buffer 并不會(huì)發(fā)生變化褐啡,當(dāng)Back buffer準(zhǔn)備就緒后,它們才進(jìn)行交換鳖昌。

但是如果界面比較復(fù)雜备畦,CPU/GPU的處理時(shí)間較長(zhǎng) 超過(guò)了16.6ms呢,雙緩沖機(jī)制會(huì)帶來(lái)什么問(wèn)題许昨?如下圖:

  • 在第二個(gè)時(shí)間段內(nèi)懂盐,但卻因 GPU 還在處理 B 幀,緩存沒(méi)能交換糕档,導(dǎo)致 A 幀被重復(fù)顯示莉恼。
  • B完成后,又因?yàn)槿狈?code>VSync信號(hào),它只能等待下一個(gè)signal的來(lái)臨俐银。于是在這一過(guò)程中尿背,有一大段時(shí)間是被浪費(fèi)的。
  • 當(dāng)下一個(gè)VSync出現(xiàn)時(shí)悉患,CPU/GPU馬上執(zhí)行操作(A幀)残家,且緩存交換榆俺,相應(yīng)的顯示屏對(duì)應(yīng)的就是B售躁。這時(shí)看起來(lái)就是正常的。只不過(guò)由于執(zhí)行時(shí)間仍然超過(guò)16ms茴晋,導(dǎo)致下一次應(yīng)該執(zhí)行的緩沖區(qū)交換又被推遲了——如此循環(huán)反復(fù)陪捷,便出現(xiàn)了越來(lái)越多的“Jank”。

三緩沖就是在雙緩沖機(jī)制基礎(chǔ)上增加了一個(gè)Graphic Buffer緩沖區(qū)诺擅,這樣可以最大限度的利用空閑時(shí)間市袖,帶來(lái)的壞處是多使用的一個(gè)Graphic Buffer所占用的內(nèi)存。


三緩沖機(jī)制有效利用了等待vysnc的時(shí)間烁涌,可以幫助我們減少了jank

RenderThread

經(jīng)過(guò) Android 4.1Project Butter 黃油計(jì)劃之后苍碟,Android 的渲染性能有了很大的改善。不過(guò)你有沒(méi)有注意到這樣一個(gè)問(wèn)題撮执,雖然利用了 GPU 的圖形高性能運(yùn)算微峰,但是從計(jì)算 DisplayList,到通過(guò) GPU 繪制到 Frame Buffer抒钱,整個(gè)計(jì)算和繪制都在 UI 主線程中完成蜓肆。

UI 線程任務(wù)過(guò)于繁重。如果整個(gè)渲染過(guò)程比較耗時(shí)谋币,可能造成無(wú)法響應(yīng)用戶(hù)的操作仗扬,進(jìn)而出現(xiàn)卡頓的情況。GPU 對(duì)圖形的繪制渲染能力更勝一籌蕾额,如果使用 GPU 并在不同線程繪制渲染圖形早芭,那么整個(gè)流程會(huì)更加順暢。

正因如此诅蝶,在 Android 5.0 引入兩個(gè)比較大的改變退个。一個(gè)是引入了 RenderNode 的概念,它對(duì) DisplayList 及一些 View 顯示屬性都做了進(jìn)一步封裝秤涩。另一個(gè)是引入了 RenderThread帜乞,所有的 GL 命令執(zhí)行都放到這個(gè)線程上,渲染線程在 RenderNode 中存有渲染幀的所有信息筐眷,可以做一些屬性動(dòng)畫(huà)黎烈,這樣即便主線程有耗時(shí)操作的時(shí)候也可以保證動(dòng)畫(huà)流程。

圖像消費(fèi)者

SurfaceFlingerAndroid系統(tǒng)中最重要的一個(gè)圖像消費(fèi)者,Activity繪制的界面圖像照棋,都會(huì)傳遞到SurfaceFlinger來(lái)资溃,SurfaceFlinger的作用主要是接收GraphicBuffer,然后交給HWComposer或者OpenGL做合成烈炭,合成完成后溶锭,SurfaceFlinger會(huì)把最終的數(shù)據(jù)提交給FrameBuffer

SurfaceFlinger是圖像數(shù)據(jù)的消費(fèi)者符隙。在應(yīng)用程序請(qǐng)求創(chuàng)建surface的時(shí)候趴捅,SurfaceFlinger會(huì)創(chuàng)建一個(gè)LayerLayerSurfaceFlinger操作合成的基本單元霹疫。所以拱绑,一個(gè)surface對(duì)應(yīng)一個(gè)Layer
當(dāng)應(yīng)用程序把繪制好的GraphicBuffer數(shù)據(jù)放入BufferQueue后丽蝎,接下來(lái)的工作就是SurfaceFlinger來(lái)完成了猎拨。

系統(tǒng)會(huì)有多個(gè)應(yīng)用程序,一個(gè)程序有多個(gè)BufferQueue隊(duì)列屠阻。SurfaceFlinger就是用來(lái)決定何時(shí)以及怎么去管理和顯示這些隊(duì)列的红省。
SurfaceFlinger請(qǐng)求HAL硬件層,來(lái)決定這些Buffer是硬件來(lái)合成還是自己通過(guò)OpenGL來(lái)合成国觉。
最終把合成后的buffer數(shù)據(jù)吧恃,展示在屏幕上。

總結(jié)

總得來(lái)說(shuō)蛉加,Android圖像渲染機(jī)制是一個(gè)生產(chǎn)者消費(fèi)者的模型蚜枢,如下圖所示:

  • onMeasureonLayout計(jì)算出view的大小和擺放的位置针饥,這都是UI線程要做的事情厂抽,在draw方法中進(jìn)行繪制,但此時(shí)是沒(méi)有真正去繪制丁眼。而是把繪制的指令封裝為displayList,進(jìn)一步封裝為RenderNode筷凤,在同步給RenderThread
  • RenderThread通過(guò)dequeue拿到graphic buffersurfaceFlinger的緩沖區(qū))苞七,根據(jù)繪制指令直接操作OpenGL的繪制接口藐守,最終通過(guò)GPU設(shè)備把繪制指令渲染到了離屏緩沖區(qū)graphic buffer
  • 完成渲染后蹂风,把緩沖區(qū)交還給SurfaceFlingerBufferQueue卢厂。SurfaceFlinger會(huì)通過(guò)硬件設(shè)備進(jìn)行layer的合成,最終展示到屏幕惠啄。

作者:程序員江同學(xué)
鏈接:https://juejin.cn/post/7088100181261942792
如有侵權(quán)慎恒,請(qǐng)聯(lián)系刪除任内!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市融柬,隨后出現(xiàn)的幾起案子死嗦,更是在濱河造成了極大的恐慌,老刑警劉巖粒氧,帶你破解...
    沈念sama閱讀 206,126評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件越除,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡外盯,警方通過(guò)查閱死者的電腦和手機(jī)摘盆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)门怪,“玉大人骡澈,你說(shuō)我怎么就攤上這事锅纺≈揽眨” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,445評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵囤锉,是天一觀的道長(zhǎng)坦弟。 經(jīng)常有香客問(wèn)我,道長(zhǎng)官地,這世上最難降的妖魔是什么酿傍? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,185評(píng)論 1 278
  • 正文 為了忘掉前任,我火速辦了婚禮驱入,結(jié)果婚禮上赤炒,老公的妹妹穿的比我還像新娘。我一直安慰自己亏较,他們只是感情好莺褒,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著雪情,像睡著了一般遵岩。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上巡通,一...
    開(kāi)封第一講書(shū)人閱讀 48,970評(píng)論 1 284
  • 那天尘执,我揣著相機(jī)與錄音,去河邊找鬼宴凉。 笑死誊锭,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的弥锄。 我是一名探鬼主播丧靡,決...
    沈念sama閱讀 38,276評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼签孔,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了窘行?” 一聲冷哼從身側(cè)響起饥追,我...
    開(kāi)封第一講書(shū)人閱讀 36,927評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎罐盔,沒(méi)想到半個(gè)月后但绕,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,400評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡惶看,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評(píng)論 2 323
  • 正文 我和宋清朗相戀三年捏顺,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片纬黎。...
    茶點(diǎn)故事閱讀 37,997評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡幅骄,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出本今,到底是詐尸還是另有隱情拆座,我是刑警寧澤,帶...
    沈念sama閱讀 33,646評(píng)論 4 322
  • 正文 年R本政府宣布冠息,位于F島的核電站挪凑,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏逛艰。R本人自食惡果不足惜躏碳,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望散怖。 院中可真熱鬧菇绵,春花似錦、人聲如沸镇眷。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,204評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)偏灿。三九已至丹诀,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間翁垂,已是汗流浹背铆遭。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,423評(píng)論 1 260
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留沿猜,地道東北人枚荣。 一個(gè)月前我還...
    沈念sama閱讀 45,423評(píng)論 2 352
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像啼肩,于是被迫代替她去往敵國(guó)和親橄妆。 傳聞我的和親對(duì)象是個(gè)殘疾皇子衙伶,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評(píng)論 2 345

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

  • UI 優(yōu)化系列專(zhuān)題慌随,來(lái)聊一聊 Android 渲染相關(guān)知識(shí)芬沉,主要涉及 UI 渲染背景知識(shí)、如何優(yōu)化 UI 渲染兩部...
    godliness閱讀 8,949評(píng)論 2 31
  • 前言 在上一篇文章 《Android圖形渲染原理(上)》中阁猜,詳細(xì)的講解了圖像消費(fèi)者丸逸,我們已經(jīng)了解了Android中...
    子者不語(yǔ)閱讀 1,219評(píng)論 0 4
  • 對(duì)于Android開(kāi)發(fā)者來(lái)說(shuō),我們或多或少有了解過(guò)Android圖像顯示的知識(shí)點(diǎn)剃袍,剛剛學(xué)習(xí)Android開(kāi)發(fā)的人會(huì)...
    子者不語(yǔ)閱讀 1,437評(píng)論 0 6
  • 寫(xiě)在前面 作為一名android開(kāi)發(fā)人員接觸學(xué)習(xí)flutter已有小半年了黄刚,無(wú)論是widget配置構(gòu)建響應(yīng)式ui的...
    CheetahYCH閱讀 1,686評(píng)論 0 6
  • 丟幀和卡頓 卡頓,是字面意思上來(lái)講民效,就是畫(huà)面不流暢憔维,即頁(yè)面刷新不連貫。Android系統(tǒng)默認(rèn)的頁(yè)面刷新頻率是60幀...
    zackyG閱讀 1,455評(píng)論 7 9