最近開發(fā)遇到問題待诅,ImageView設置visibility未顯示统求。這時View已經(jīng)post到主線程顯示,并且父view可以正常顯示挖息。懷疑是系統(tǒng)顯示問題于是對顯示系統(tǒng)進行了學習梳理金拒。
本文將從三個方面介紹Android 圖形系統(tǒng)。
一套腹、圖形系統(tǒng)簡介
1.1 Android 繪制基礎
- 系統(tǒng)繪制的是什么绪抛?
圖形緩沖區(qū),也叫Buffer 电禀。應用層的View樹最終會轉換成Buffer幢码,置于BufferQueue中被繪制。 - 繪制的位置在哪里尖飞?
應用端會把一切內容渲染到surface上症副,最終顯示到LCD/OLED顯示屏 -
如何把圖像繪制到屏幕?
繪制任務由應用發(fā)起葫松,通過跨進程方式把Buffer傳到FW層瓦糕,由FW層中的SurfaceFlinger服務調用Linux 硬件驅動最終繪制到硬件屏幕上。
1.2 Android 圖形引擎
圖形系統(tǒng)提供繪圖和圖形處理支持腋么。
Android 框架提供了各種用于 2D 和 3D 圖形渲染的 API咕娄、圖片解碼庫,以及各種Driver支持珊擂。
? 繪圖API:2D引擎 Skia圣勒,3D引擎 OpenGL ES,RenderScript摧扇,OpenCV和Vulkan圣贸。
? 圖片解碼庫:jpg,png扛稽,gif等吁峻。
應用開發(fā)者可通過三種方式將圖像繪制到屏幕:
? Canvas : 2D圖形API,Android View樹實際的繪制者。
? OpenGL ES : 嵌入式設備的OpenGL 三維圖形API子集用含。
? Vulkan :跨平臺的2D和3D繪圖引擎,Android 7.0后支持矮慕,NDK。
1.3 圖形系統(tǒng)架構
整個圖形系統(tǒng)架構是一個生產(chǎn)者和消費者模式啄骇,五層依次介紹:
- Image Stream Producers :
? view每次執(zhí)行l(wèi)ockCanvas->draw->unlockCanvas痴鳄,會存入一幀數(shù)據(jù)進入BufferQueue中 - Native Framework:
? Buffer的生成和BufferQueue數(shù)據(jù)跨進程傳遞 - WindowManager:
? 計算窗口大小,位置等缸夹,同時也會將相應的參數(shù)設置給SurfaceFlinger痪寻,比如Window的z-order和大小等。 - Image stream consumers :
? SurfaceFlinger虽惭,消耗當前可見的 Surface橡类,作為Layer的管理著,同是也是BufferQueue的消費者趟妥,當每個Layer的生產(chǎn)者繪制完一幀時猫态,會通知SurfaceFlinger。 - HAL:
? Gralloc: 圖形內存分配器,分配圖像生產(chǎn)方請求的內存
? Hardware Composer:硬件混合渲染器,合成SurfaceFlinger里面的Layer披摄,并顯示
二亲雪、圖形組件與繪制流程
2.1 2D/3D繪圖流程
2D繪制:Canvas api / view 的子類 (button ,list)/自定義view
3D繪制:應用直接使用OpenGL 接口繪制圖形(PixelFlinger對應的是openGl 1.0 ,GUP driver 對應的是2.0和3.0)
所有情況下的繪圖都渲染到一個包含 GraphicBuffer的Surface上疚膊,當一塊 Surface 顯示在屏幕上時义辕,就是用戶所看到的窗口。
2.2 Canvas/ Skia/ hwui/ OpenGL ES
? Canvas:畫布寓盗,2D圖形API灌砖,Android View樹實際的渲染者。
? Skia繪制:Android4.0之前默認使用傀蚌,主線程通過CPU完成繪圖指令操作基显,在復雜場景下單幀容易超過16ms導致卡頓。
注意:并非所有 2D 繪制操作都支持硬件加速窜醉,可能會影響部分自定義視圖或繪制調用。詳情見:Android硬件加速
? OpenGL ES : OpenGL 三維圖形 API 的子集艺谆,針對手機榨惰、PDA和游戲主機等嵌入式設備而設計。在異步線程直接通過OpenGL ES進行渲染静汤,一般適用于游戲琅催、視頻播放等獨立場景
2.3 圖形組件WMS
WindowManagerService(WMS)窗口管理服務居凶,管理系統(tǒng)中所有的窗口。
? 管理window (view的容器)
? Window與surface對應恢暖,一塊顯示區(qū)域排监。添加一個window狰右,就是 WMS 為其分配一塊 Surface 的過程杰捂。
Android setContentView就是將View設置到widow上。
WMS角色在整個流程的位置:
這里有一個wm命令可以看到window的信息:對手機分辨率棋蚌、像素密度嫁佳、顯示區(qū)域進行設置的命令
2.4 Surface與相關的view
Google 在Android source官網(wǎng)提示:
“ What every developer should know about surfaces, SurfaceHolder, EGLSurface, SurfaceView, GLSurfaceView, SurfaceTexture, TextureView, SurfaceFlinger, and Vulkan.”
這里就對這些控件進行簡單介紹:
Surface
Surface : Handle onto a raw buffer that is being managed by the screen compositor.
Surface 對應一塊屏幕緩沖區(qū)。生產(chǎn)者是: SurfaceTexture谷暮、MediaRecorder 等蒿往,消費者是: OpenGL、MediaPlayer 或 CameraDevice等湿弦。每個window對應一個Surface瓤漏。Canvas或OpenGL ES等最終都渲染到Surface上。
? Flutter在Android平臺上也是直接渲染到Surface颊埃。例如:一個Activity/Dialog都是一個Surface蔬充,它承載了上層的圖形數(shù)據(jù),與SurfaceFlinger側的Layer相對應班利。
Canvas rendering:
Canvas(畫布)實現(xiàn)由 Skia 圖形庫提供饥漫。為了確保兩個客戶端不會同時更新某個緩沖區(qū),使用以下命令處理畫布鎖:
SurfaceView和SurfaceHolder
SurfaceView
使用雙緩沖機制罗标,有自己的 surface庸队,View只是一個透明的占位符,Surface可以在后臺線程中繪制闯割。雙緩沖機制提高渲染效率彻消,獨立線程
繪制,提升流暢性宙拉。適合一些場景:需要界面迅速更新宾尚、UI繪制時間長、對幀率要求較高的情況鼓黔。
SurfaceHolder
提供訪問和控制Surface 相關的方法 央勒。通過SurfaceView的getHolder()函數(shù)可以獲取SurfaceHolder對象,Surface 就在SurfaceHolder對象內澳化。
addCallback(SurfaceHolder.Callbackcallback) /Canvas lockCanvas() /unlockCanvasAndPost(Canvascanvas)
SurfaceTexture/ GLSurfaceView/ TextureView
SurfaceTexture: Surface 和 OpenGL ES (GLES) 紋理(Texture)的組合崔步。將圖像流轉為 OpenGL 外部紋理。
TextureView:持有 SurfaceTexture缎谷,將圖像處理為 OpenGL 紋理更新到 HardwareLayer井濒。
GLSurfaceView:加入 EGL 管理灶似,自帶 GL 上下文和 GL 渲染線程
這些View通常涉及到Android音視頻相關,需要高效的渲染能力瑞你。如下面的SurfaceTexture在camera中的應用酪惭。
GraphicBuffer / BufferQueue
GraphicBuffer
簡稱Buffer, 一個Buffer包含一幀圖像,Buffer由gralloc分配和回收者甲。Buffer 屬性包含:width, height, format, usage等
BufferQueue
BufferQueue 的引入是為了解決顯示和性能問題春感。
? Surface屬于APP進程,Layer屬于系統(tǒng)進程虏缸,如果它們之間只用一個Buffer鲫懒,會存在顯示和性能問題。
? 一些Buffer用于繪制刽辙,一些Buffer用于顯示窥岩,雙方處理完之后,交換一下Buffer宰缤,提高效率颂翼。
? BufferQueue中包含多個Buffer對象。
Android圖形系統(tǒng)包含了兩對生產(chǎn)者和消費者模型慨灭,它們都通過BufferQueue進行連接:
1.Canvas和OpenGL ES生產(chǎn)圖形數(shù)據(jù)朦乏,SurfaceFlinger消費圖形數(shù)據(jù)。
2.SurfaceFlinger合成所有圖層的圖形數(shù)據(jù)缘挑,Display顯示合成結果集歇。
SurfaceFlinger
code:frameworks/native/services/surfaceflinger
? Surface表示APP進程的一個窗口,承載了窗口的圖形數(shù)據(jù)语淘。
? SurfaceFlinger是系統(tǒng)進程合成所有窗口的系統(tǒng)服務诲宇,負責合成所有Surface提供的圖形數(shù)據(jù),然后送顯到屏幕惶翻。
? SurfaceFlinger既是上層應用的消費者姑蓝,又是Display的生產(chǎn)者,起到了承上啟下的作用吕粗。
數(shù)據(jù)流:
合成示意圖:
SurfaceFlinger的啟動流程:
Surface Flinger 服務由init進程啟動纺荧,一個高優(yōu)先級的本地守護進程。SurfaceFlinger啟動流程
Android系統(tǒng)的啟動流程:
可以看到SurfaceFlinger的啟動是和Zygote進程啟動位于同一流程中颅筋。
SurfaceFlinger API
Vsync機制
在介紹Vsync機制之前先介紹兩個重要概念:
屏幕刷新率:屏幕每秒鐘可以刷新多少次宙暇。60HZ刷新率,16.7ms刷新一次议泵。(120HZ/8.3ms)占贫,硬件指標。
GPU 繪制幀率:GPU 每秒能夠合成繪制多少幀先口。
軟件層觸發(fā) View 繪制的時機是隨機的型奥,當下一次屏幕刷新時瞳收,屏幕從 Frame Buffer 中拿到的數(shù)據(jù)還是“幀1”的數(shù)據(jù),導致“丟幀”厢汹。
每隔 16ms 硬件層發(fā)出 vsync 信號螟深,應用層接收到此信號后會觸發(fā)UI 的渲染流程,同時 vsync 信號也會觸發(fā) SurfaceFlinger 讀取Buffer 中的數(shù)據(jù)烫葬,進行合成顯示到屏幕上界弧。
總結:Vsync機制將 CPU 和 GPU 的開始時間與屏幕刷新強行拖拽到同一起跑線
三、Graphics問題總結
Android提供的Graphics流程相對比較復雜對其進行具象后的流程如下兩張圖所示: