概覽#
官方簡介:Android-Graphics
-
Image Stream Producers:圖形生產者,用來生成圖形緩衝區,以供圖形消費者使用。例如 OpenGL ES、Canvas 2D 和 mediaserver 視頻解碼器。
-
Native Framework:Libgui 庫,包含了圖形系統底層的基本元素,例如 Surface、BufferQueue、GraphicBufferConsumer、GraphicBufferProducer、SurfaceComposer 等等。
-
Window Positioning:WindowManager,用來控制 window 對象,window 為一組 view 對象的集合。它為 SurfaceFlinger 提供緩衝區和窗口元數據,而 SurfaceFlinger 可使用這些信息將 Surface 合成到屏幕。
-
Image Stream Consumers:圖形消費者,包括 SurfaceFlinger 和一些圖形應用。
- 圖形流的最常見消費者是 SurfaceFlinger,該系統服務會消耗當前可見的 Surface,並使用 WindowManager 中提供的信息將它們合成到顯示部分。SurfaceFlinger 使用 OpenGL 和 Hardware Composer 來合成一組 Surface。
- 一些 OpenGL ES 應用也可以做為消費者,例如相機應用會消費相機預覽圖像流。非 GL 應用也可以是消費者,例如 ImageReader 類。
-
HAL:顯示子系統的硬體抽象實現,包括 Hardware Composer 和 Gralloc。
- SurfaceFlinger 可以將某些合成工作委託給 Hardware Composer,以分擔 OpenGL 和 GPU 上的工作量。這時,SurfaceFlinger 只是充當另一個 OpenGL ES 客戶端,Hardware Composer 則進行圖形渲染的工作。Hardware Composer 必須支持事件,其中之一是 VSYNC(另一個是支持即插即用 HDMI 的熱插拔)。
- Gralloc 用來分配圖形生產方請求的內存。
BufferQueue#
官方簡介:Android-BufferQueue
左側的對象是生成圖形緩衝區的渲染器,如主屏幕、狀態欄和系統界面。SurfaceFlinger 是合成器,而 Hardware Composer 是製作器。BufferQueue 是 Android 圖形系統很重要的組成部分,它負責數據的傳遞:
圖中的 producer 和 consumer 運行在不同的進程裡,BufferQueue 是將緩衝區池與隊列相結合的數據結構,它使用 Binder IPC 在進程之間傳遞緩衝區。幾個重要函數如下:
- producers 透過 BufferQueue 請求一塊空閒的緩存區 (GraphicBuffer): IGraphicBufferProducer.dequeueBuffer 方法
- 往緩存區 (GraphicBuffer) 填充了數據 (繪製等) 後,producers 將緩存區 (GraphicBuffer) 入隊列到 BufferQueue 中: IGraphicBufferProducer.queueBuffer 方法
- consumer 從 BufferQueue 中出隊列一塊緩存區 (GraphicBuffer): IGraphicBufferConsumer.acquireBuffer 方法
- consumer 消費完畢後 (典型的是 SurfaceFlinger 合成數據) 將緩存區 (GraphicBuffer) 返回給隊列: IGraphicBufferConsumer.releaseBuffer 方法
其中 IGraphicBufferProducer 是 BufferQueue 的生產者接口,實現類是 BufferQueueProducer 生產者類;IGraphicBufferConsumer 是 BufferQueue 的消費者接口,實現類是 BufferQueueConsumer 消費者類。
SurfaceFlinger#
SurfaceFlinger 用來管理消費當前可見的 Surface, 所有被渲染的可見 Surface 都會被 SurfaceFlinger 透過 WindowManager 提供的信息合成 (使用 OpenGL 和 HardWare Composer) 提交到屏幕的後緩衝區,等待屏幕的下個 Vsync 信號到來,再顯示到屏幕上。SufaceFlinger 透過屏幕後緩衝區與屏幕建立聯繫,同時透過 Surface 與上層建立聯繫,起到了一个承上启下的作用。
SurfaceFlinger 工作流程
SurfaceFlinger 的 registerCallback 時的this就是 SurfaceFlinger 對 ComposerCallback 接口的實現。
-
onHotplugReceived
熱插拔事件,顯示屏幕連接或者斷開時回調
-
onRefreshReceived
接收底層 HWComposer 的刷新請求,實現方法如下:
void SurfaceFlinger::onRefreshReceived(int sequenceId, hwc2_display_t /*display*/) { Mutex::Autolock lock(mStateLock); if (sequenceId !=getBE().mComposerSequenceId) { return; } repaintEverythingLocked(); } void SurfaceFlinger::repaintEverythingLocked() { android_atomic_or(1, &mRepaintEverything); //觸發刷新,重新合成顯示 signalTransaction(); }
-
onVsyncReceived
Vsync 事件上報,接收底層硬體上報的垂直同步信號。
為什麼需要垂直同步信號,參考https://juejin.cn/post/6863756420380196877#heading-1
合成方式#
- Client 合成
將各個 Layer 的內容用 GPU 渲染到暫存緩衝區中,最後將暫存緩衝區傳送到顯示硬體,Client 合成,採用 RenderEngine 進行合成
- Device 合成
硬體合成器進行合成 HWComposer,其合成方式是將各個 Layer 的數據全部傳給顯示硬體,並告知它從不同的緩衝區讀取屏幕不同部分的數據
HWC 相關圖表#
合成圖表#
Dump 信息#
adb shell dumpsys SurfaceFlinger
圖層#
圖層(Layer)是合成的最重要單元;每個圖層都有一組屬性,用於定義它與其他層的交互方式。Layer 在每一層中的代碼的實現不一樣,基本上 Layer 的理念都是一樣的。
frameworks/native/services/surfaceflinger
├── Layer.h
├── Layer.cpp
├── ColorLayer.h
├── ColorLayer.cpp
├── BufferLayer.h
└── BufferLayer.cpp
總結#
整個圖形顯示系統可以簡單地分為圖形和顯示兩個系統理解。
- 圖形系統,提供繪圖和圖形處理的支持。無論是 2D 的 Skia,還是 3D 的 OpenGLES,還有各種圖片解碼庫
- 顯示系統,圖形繪製好後,需要顯示,就需要合併窗口,這個時候就需要用到 Surfaceflinger,上層的顯示系統有 View、ActivityManagerService 和 WindowManagerService 組成。一個窗口就是一個 Surface,Surfacedlinger 使用 Layer 去描述一個窗口。