扒一扒安卓的渲染原理
導語:
在測試流暢度的過程中,必不可免的要與FPS,Jank等指標接觸,但為了加深理解,今天來簡單扒一扒安卓的渲染原理;
PerfDog使用Jank作為來代表遊戲流暢度的指標,詳情可以看
APP&遊戲需要關注Jank卡頓嗎?
一.CPU與GPU結構
現在大部分移動端都會配有CPU(中央處理器)和GPU(圖形處理器),有的現在還有一塊NPU用於處理智慧運算。來簡單看一下他們的結構;
綠色的是計算單元(ALU),
橙紅色的是儲存單元,
橙黃色的是控制單元。
CPU需要很強的通用性來處理各種不同的資料型別,同時又要進行復雜的數學和邏輯運算,所以使得CPU的內部結構異常複雜;
CPU被Cache佔據了大量空間,還有很多複雜的控制邏輯和諸多優化電路,其實計算能力只是CPU很小的一部分,在早期的時候,CPU除了做邏輯計算外,還負責記憶體管理、圖形顯示等操作因此在實際運算的時候效能會大打折扣,而且還不能顯示覆雜的圖形,完全不能滿足現在3D遊戲的要求;所以GPU應運而生。
GPU面對的則是型別高度統一的、相互無依賴的大規模資料和不需要被打斷的純淨的計算環境,所以結構也大不相同。
GPU採用了數量眾多的計算單元和超長的流水線,但只有非常簡單的控制邏輯並省去了Cache,GPU將計算機系統所需要的顯示資訊進行轉換驅動,並向顯示器提供行掃描訊號,控制顯示器的正確顯示,主要負責圖形顯示部分的工作。
二.Android系統繪圖機制
現在的安卓終端通常在一個典型顯示系統中首先由CPU發出影像繪製指令要讓GPU去畫一個樣式,但CPU不能直接和GPU通訊,也要遵守相應的規則,就和現在我們幹什麼事都要走個流程一樣的嘛,不能亂套;所以CPU要先向OpenGL ES傳送一些指令,表達要畫一個樣式,Opengl ES是一組介面API,**通過這些API可以操作驅動,讓GPU達到各種各樣的操作;GPU接收到這些命令,開始柵格化處理,把樣式顯示到螢幕中;
現在我們把應用加到顯示流程裡面來
在Android應用層通過LayoutInflater把佈局XML檔案對映成物件載入到記憶體中,此時這個UI物件含有大小,位置啦等等資訊。然後CPU從記憶體中取出這個UI物件,再經過運算處理成多維的向量圖形,然後交給GPU去柵格化成點陣圖,顯示到螢幕上;
簡單介紹一下向量圖和點陣圖
向量圖:由一個函式來描述,這個函式描述了此圖如何生成
點陣圖:由畫素點矩陣來描述
Android系統每隔16ms就重新繪製一次Activity,所以要求應用必須在16ms內完成螢幕重新整理的全部邏輯操作,這樣才能達到每秒60幀(60FPS),然而這個每秒幀數的引數由手機硬體所決定,現在大多數手機螢幕重新整理率是60赫茲(是每秒中的週期性變動重複次數的計量),如果超過了16ms就會出現所謂的丟幀(1000ms/60=16.66ms)
三.一幀影像完整渲染過程
在Android應用程式視窗裡麵包含了很多檢視(View)元素,這些元素是以樹形結構來組織,最終構成所謂檢視樹的結構;
在繪製一個Android應用程式視窗的UI之前,要確定它裡面的各個子View元素在父元素裡面的大小以及位置。確定各個子View元素在父View元素裡面的大小以及位置的過程又稱為測量過程和佈局過程。Android應用程式視窗的UI渲染過程可以分為
Measure(測量)、Layout(佈局)和Draw(繪製)
三個階段(由ViewRootImpl類的performTraversals()方法發起)
測量——遞迴(深度優先)確定所有檢視的大小(高、寬)
佈局——遞迴(深度優先)確定所有檢視的位置
繪製——在畫布canvas上繪製應用程式視窗所有的檢視
經過多次繪製後,這一幀內要顯示的所有view都已經被繪製完畢,注意繪製View層次結構這些操作是在圖形緩衝區中繪製完成的;
此時就要把這個圖形緩衝區被交給SurfaceFlinger服務
SurfaceFlinger服務概述:
SurfaceFlinger服務和其他系統服務一樣是在Android系統的System程式裡被啟動並執行在其中的,主要負責統一管理裝置中Android系統的幀緩衝區(Frame Buffer,簡單理解為螢幕所顯示出來的所有圖形效果都是由它統一管理的),在SurfaceFlinger服務啟動的過程中會自動建立兩個執行緒:其中一個執行緒用於監控控制檯事件,另外一個執行緒則用於渲染系統的UI;
Android應用程式為了能夠將自己的UI繪製在系統的幀緩衝區上,就需要將UI資料傳遞SurfaceFlinger服務並告知自己具體的UI資料(例如要繪製UI的區域、位置等資訊),
Android應用程式與SurfaceFlinger服務是執行在不同的程式中,所以相互間通過Binder機制進行通訊,
大致可以分為3步:
1.首先是建立一個到SurfaceFlinger服務的連線,
2通過這個連線來建立一個Surface,
3.請求SurfaceFlinger服務渲染該Surface(在Android應用的每個視窗對應一個畫布(Canvas),也可以理解為Android應用程式的一個視窗)
在APP層我們對於這部分的無法進行任何的優化,這是ROOM做的工作。
簡單來說就是當Android應用層在圖形緩衝區中繪製好View層次結構後,應用層通過Binder機制與SurfaceFlinger通訊並藉助一塊匿名共享記憶體會把這個圖形緩衝區會被交給SurfaceFlinger服務。因為單純的匿名共享記憶體在傳遞多個視窗資料時缺乏有效的管理,所以匿名共享記憶體就被抽象為一個更上流的資料結構SharedClient,在每個SharedClient中,最多有31個SharedBufferStack,每個SharedBufferStack都對應一個Surface即一個視窗。
幀快取有個地址,是在記憶體裡。我們通過不停的向frame buffer中寫入資料, 顯示控制器就自動的從frame buffer中取資料並顯示出來。全部的圖形都共享記憶體中同一個幀快取。
四.VSync機制
為了減少卡頓,Android 4.1(JB)中已經開始引入VSync(垂直同步)機制
簡單來說就是CPU/GPU會接收vsync訊號,Android系統每隔16ms發出Vsync訊號,觸發對UI 進行渲染(即每16ms顯示一幀)
在16ms內需要完成兩項任務:將UI 物件轉換為一系列多邊形和紋理(柵格化)和CPU傳遞處理資料到GPU。
但即使引入垂直同步機制也不是非常完美,如果某些原因導致CPU和GPU渲染某一幀畫面的時間超過16ms時,Vsync垂直同步機制會讓硬體顯示器等待,直到GPU完成柵格化操作,這就直接導致這一幀畫面多停留了16ms甚至更長時間,讓使用者看起來畫面停頓。
相關文章
- 扒一扒安卓渲染原理安卓
- 扒一扒PROMISE的原理,大家不要怕!Promise
- 扒一扒 Jetpack Compose 實現原理Jetpack
- 扒一扒React計算狀態的原理React
- 扒一扒「清華系」的 AI 安防大佬們AI
- 扒一扒 EventServiceProvider 原始碼IDE原始碼
- 扒一扒ELF檔案
- 扒一扒Kotlin協程的底褲Kotlin
- 扒一扒Bean注入到Spring的那些姿勢BeanSpring
- 扒一扒程式語言排行榜
- 扒一扒我們生活中常見的品牌小程式
- 扒扒戀愛這些事
- 用大資料扒一扒蔡徐坤的真假流量粉大資料
- BEM實戰之扒一扒淘票票頁面
- 扒一扒@Retryable註解,很優雅,有點意思!
- 防扒
- 扒一扒谷歌諾貝爾獎得主背後八卦谷歌
- 扒一扒這個註解,我發現還有點意思。
- 非得從零開始學習?扒一扒強化學習的致命缺陷強化學習
- 扒一扒JVM的垃圾回收機制,下次面試你準備好了嗎JVM面試
- 從“掃月亮”到“掃福字”,扒一扒背後的支付寶AR框架體系框架
- 扒一下Redis的配置檔案Redis
- 日入50000元,扒扒抖音本地生活小程式的變現模式模式
- 人剛畢業,顛覆整個AI界:扒一扒Sora兩帶頭人博士論文AISora
- 深扒京東物流的家底兒
- 扒光 Handler,趕緊來瞧一瞧
- 怎麼用python扒網頁?Python網頁
- 扒了扒Q1重點新遊,現在手遊要拼周更和薄利多銷了
- 性感的Promise,擁抱ta然後扒光taPromise
- 《吃透MQ系列》之扒開Kafka的神祕面紗MQKafka
- 扒勒索病毒史,聊真CDP與準CDP
- 扒了手機監控木馬後臺!
- SiteSucker pro 最新漢化版,Mac扒站神器Mac
- 一文帶你深扒ClassLoader核心,揭開它的神祕面紗!
- 從X86指令深扒JVM的位移操作JVM
- 素材火基於thinkphp開發,免費扒模板PHP
- 智東西:救命呼吸機缺口難補!一文扒開供應鏈真相
- 【Python】從0開始寫爬蟲——轉身扒豆瓣電影Python爬蟲