Android 圖形系統(tǒng)(Graphics)

最近開發(fā)遇到問題待诅,ImageView設置visibility未顯示统求。這時View已經(jīng)post到主線程顯示,并且父view可以正常顯示挖息。懷疑是系統(tǒng)顯示問題于是對顯示系統(tǒng)進行了學習梳理金拒。

本文將從三個方面介紹Android 圖形系統(tǒng)。

一套腹、圖形系統(tǒng)簡介

1.1 Android 繪制基礎

  1. 系統(tǒng)繪制的是什么绪抛?
    圖形緩沖區(qū),也叫Buffer 电禀。應用層的View樹最終會轉換成Buffer幢码,置于BufferQueue中被繪制。
  2. 繪制的位置在哪里尖飞?
    應用端會把一切內容渲染到surface上症副,最終顯示到LCD/OLED顯示屏
  3. 如何把圖像繪制到屏幕?

    繪制任務由應用發(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)者和消費者模式啄骇,五層依次介紹:

  1. Image Stream Producers :
    ? view每次執(zhí)行l(wèi)ockCanvas->draw->unlockCanvas痴鳄,會存入一幀數(shù)據(jù)進入BufferQueue中
  2. Native Framework:
    ? Buffer的生成和BufferQueue數(shù)據(jù)跨進程傳遞
  3. WindowManager:
    ? 計算窗口大小,位置等缸夹,同時也會將相應的參數(shù)設置給SurfaceFlinger痪寻,比如Window的z-order和大小等。
  4. Image stream consumers :
    ? SurfaceFlinger虽惭,消耗當前可見的 Surface橡类,作為Layer的管理著,同是也是BufferQueue的消費者趟妥,當每個Layer的生產(chǎn)者繪制完一幀時猫态,會通知SurfaceFlinger。
  5. HAL:
    ? Gralloc: 圖形內存分配器,分配圖像生產(chǎn)方請求的內存
    ? Hardware Composer:硬件混合渲染器,合成SurfaceFlinger里面的Layer披摄,并顯示

二亲雪、圖形組件與繪制流程

2.1 2D/3D繪圖流程

2D rendering path

2D繪制:Canvas api / view 的子類 (button ,list)/自定義view


3D rendering path

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導致卡頓。

? hwui硬件加速繪制:使用GUP繪制, Android4.0及以后默認開啟硬件加速渲染善炫。5.0以后把渲染拆分成了兩個線程:主線程負責記錄渲染指令撩幽,渲染線程負責通過OpenGL ES完成渲染,兩個線程并發(fā)執(zhí)行箩艺。

注意:并非所有 2D 繪制操作都支持硬件加速窜醉,可能會影響部分自定義視圖或繪制調用。詳情見:Android硬件加速
? OpenGL ES : OpenGL 三維圖形 API 的子集艺谆,針對手機榨惰、PDA和游戲主機等嵌入式設備而設計。在異步線程直接通過OpenGL ES進行渲染静汤,一般適用于游戲琅催、視頻播放等獨立場景

2.3 圖形組件WMS

WindowManagerService(WMS)窗口管理服務居凶,管理系統(tǒng)中所有的窗口。
? 管理window (view的容器)
? Window與surface對應恢暖,一塊顯示區(qū)域排监。添加一個window狰右,就是 WMS 為其分配一塊 Surface 的過程杰捂。

? WindowManager為 SurfaceFlinger 提供窗口元數(shù)據(jù)(window metadata)

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相對應班利。

屏幕上的每一幀圖像都是多個surface合成后的結果:
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流程相對比較復雜對其進行具象后的流程如下兩張圖所示:



?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末厘灼,一起剝皮案震驚了整個濱河市夹纫,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌设凹,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,013評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件茅姜,死亡現(xiàn)場離奇詭異闪朱,居然都是意外死亡,警方通過查閱死者的電腦和手機钻洒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,205評論 2 382
  • 文/潘曉璐 我一進店門奋姿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人素标,你說我怎么就攤上這事称诗。” “怎么了头遭?”我有些...
    開封第一講書人閱讀 152,370評論 0 342
  • 文/不壞的土叔 我叫張陵寓免,是天一觀的道長。 經(jīng)常有香客問我计维,道長袜香,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,168評論 1 278
  • 正文 為了忘掉前任鲫惶,我火速辦了婚禮蜈首,結果婚禮上,老公的妹妹穿的比我還像新娘欠母。我一直安慰自己欢策,他們只是感情好,可當我...
    茶點故事閱讀 64,153評論 5 371
  • 文/花漫 我一把揭開白布赏淌。 她就那樣靜靜地躺著踩寇,像睡著了一般。 火紅的嫁衣襯著肌膚如雪猜敢。 梳的紋絲不亂的頭發(fā)上姑荷,一...
    開封第一講書人閱讀 48,954評論 1 283
  • 那天盒延,我揣著相機與錄音,去河邊找鬼鼠冕。 笑死添寺,一個胖子當著我的面吹牛,可吹牛的內容都是我干的懈费。 我是一名探鬼主播计露,決...
    沈念sama閱讀 38,271評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼憎乙!你這毒婦竟也來了票罐?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 36,916評論 0 259
  • 序言:老撾萬榮一對情侶失蹤泞边,失蹤者是張志新(化名)和其女友劉穎该押,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體阵谚,經(jīng)...
    沈念sama閱讀 43,382評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡蚕礼,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,877評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了梢什。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片奠蹬。...
    茶點故事閱讀 37,989評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖嗡午,靈堂內的尸體忽然破棺而出囤躁,到底是詐尸還是另有隱情,我是刑警寧澤荔睹,帶...
    沈念sama閱讀 33,624評論 4 322
  • 正文 年R本政府宣布狸演,位于F島的核電站,受9級特大地震影響应媚,放射性物質發(fā)生泄漏严沥。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,209評論 3 307
  • 文/蒙蒙 一中姜、第九天 我趴在偏房一處隱蔽的房頂上張望消玄。 院中可真熱鬧,春花似錦丢胚、人聲如沸翩瓜。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,199評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽兔跌。三九已至,卻和暖如春峡蟋,著一層夾襖步出監(jiān)牢的瞬間坟桅,已是汗流浹背华望。 一陣腳步聲響...
    開封第一講書人閱讀 31,418評論 1 260
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留仅乓,地道東北人赖舟。 一個月前我還...
    沈念sama閱讀 45,401評論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像夸楣,于是被迫代替她去往敵國和親宾抓。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,700評論 2 345

推薦閱讀更多精彩內容