SurfaceFlinger and RenderThread
intro
在 Android 系統中,畫面呈現是使用者體驗的核心。從應用程式呼叫 Canvas.drawXXX() 或 OpenGL ES API 開始,到最終畫面被顯示在螢幕上,這個過程涉及 應用層 → Framework → HAL → Kernel → Display 的完整鏈路。
其中,兩個極為重要的角色是:
- RenderThread —— 應用程式內部的專屬渲染執行緒,負責將 UI 或 GPU 指令轉換為圖形緩衝區 (Buffer)。
- SurfaceFlinger —— Android 系統層的合成服務 (System Service),負責將多個應用的圖層 (Surface) 合成,並送往螢幕。
簡單來說:
- RenderThread 負責「畫出一張張圖片」(per-surface rendering)。
- SurfaceFlinger 負責「把所有圖片拼在一起」(global composition)。
圖形系統總覽
Android 的圖形系統包含以下幾個層級:
- 應用層
- Java/Kotlin 程式呼叫 UI API (如 View.invalidate())。
- 或使用 OpenGL / Vulkan 直接繪製。
- 渲染層
- RenderThread 處理應用的渲染邏輯。
- 將畫面繪製到 GraphicBuffer,並交給 Surface。
- 合成層
- SurfaceFlinger 收集各應用的 Surface,決定畫面合成策略 (OpenGL / Hardware Composer)。
- 最終合成單一 FrameBuffer。
- 顯示層
- HWComposer (HWC) 與 Display Driver,將畫面送到螢幕。
應用層 (App)
|
v
RenderThread (繪製至 Surface)
|
v
SurfaceFlinger (全域合成)
|
v
HWComposer (硬體合成)
|
v
Display (螢幕)
RenderThread:應用內的渲染執行緒
- RenderThread 的角色
- 在 Android 5.0 (Lollipop) 引入,目的是 減少 UI 延遲。
- 將渲染任務從 UI Thread (主執行緒) 分離,避免因 GC 或主執行緒卡頓而影響流暢度。
- 使用 OpenGL ES / Skia / Vulkan 進行 GPU 加速繪製。
- RenderThread 運作流程
- 應用呼叫 invalidate() → Framework 標記需要重繪。
- Choreographer 在下一個 VSync 信號到來時,通知 RenderThread 準備繪製。
- RenderThread 收集繪製命令 (DisplayList)。
- 執行 Skia/OpenGL 指令,繪製到 GraphicBuffer。
- Buffer 透過 BufferQueue 傳送給 SurfaceFlinger。
UI Thread (事件/邏輯) → DisplayList
|
v
RenderThread
|
GPU/Skia 繪製 → GraphicBuffer
|
v
Surface (BufferQueue)
- RenderThread 的優勢
- 降低延遲:渲染與 UI 邏輯並行。
- 更穩定的幀率:避免 UI Thread 卡住影響畫面更新。
- 靈活性:支援 Skia、OpenGL、Vulkan 等不同後端。
SurfaceFlinger:系統級合成服務
- SurfaceFlinger 的角色
- Android 的 System Service,運行在 system_server。
- 職責是 合成所有應用的 Surface,並輸出到螢幕。
- 相當於「全域畫布管理者」。
- Surface 與 BufferQueue
- 每個應用的視窗 (Activity) 對應一個 Surface。
- Surface 內部透過 BufferQueue 與 SurfaceFlinger 溝通:
- 應用 RenderThread → 生產者 (Producer)
- SurfaceFlinger → 消費者 (Consumer)
- SurfaceFlinger 的核心工作
- 收集 Buffer
- 從不同應用的 BufferQueue 收取最新的 GraphicBuffer。
- 決定合成策略
- 軟體合成:使用 OpenGL ES。
- 硬體合成:交由 HWComposer。
- 合成圖層
- 依照 Z-Order、透明度、Clip 等屬性,疊加多個圖層。
- 輸出到螢幕
- 通知 Display HAL 更新 FrameBuffer。
App1 (RenderThread) → Surface1 (BufferQueue)
App2 (RenderThread) → Surface2 (BufferQueue)
App3 (RenderThread) → Surface3 (BufferQueue)
|
v
SurfaceFlinger
(決定 Z-Order / 合成策略)
|
v
HWComposer
|
v
Display
VSync 與幀同步
Android 的渲染必須與螢幕刷新同步,否則會出現 畫面撕裂 (Tearing) 或 掉幀 (Jank)。
- VSync 信號
- 硬體每次刷新螢幕時發送信號。
- Android Framework 透過 Choreographer 捕捉 VSync。
- 時間線
T0:VSync 發送 → 通知 RenderThread 準備繪製。
T1:RenderThread 完成繪製 → BufferQueue 交給 SurfaceFlinger。
T2:SurfaceFlinger 在下一次 VSync 前完成合成 → 提交給 HWC。
T3:螢幕刷新,顯示最新畫面。
|---VSync0---|---VSync1---|---VSync2---|
^ ^ ^
應用繪製 SurfaceFlinger 螢幕刷新
SurfaceFlinger 與 HWComposer 的合作
- 軟體合成 (GL Composition)
- SurfaceFlinger 使用 OpenGL 將各層合成到一個 FrameBuffer。
- 適用於 GPU 效率較高的場景。
- 硬體合成 (HWC)
- 將部分圖層交由 Display Controller 直接合成。
- 節省 GPU 能耗。
- 常用於播放影片、顯示系統 UI。
- 混合模式
- 部分圖層 GPU 合成,部分圖層硬體合成。
- SurfaceFlinger 動態選擇最優解。
Z-Order 與透明度管理
SurfaceFlinger 需要處理多層 Surface 疊加:
- Z-Order:決定哪個視窗在前 (如 Dialog 蓋在 Activity 上)。
- 透明度:支援半透明視窗、陰影效果。
- 裁剪 (Clip):只顯示部分區域 (如系統狀態列)。
這些資訊由 WindowManagerService (WMS) 提供,SurfaceFlinger 依此進行合成。
效能與挑戰
- 效能瓶頸
- 應用渲染過慢 → Frame Miss。
- SurfaceFlinger 合成過慢 → 掉幀。
- Triple Buffering
- Android 採用 三重緩衝,減少等待時間。
- 保證應用、SurfaceFlinger、Display 之間不卡住。
- 低延遲模式
- 遊戲/VR 應用需要降低延遲,可能採用 Direct Composition。
Use case study
- 應用卡頓 (UI Thread 卡住)
- RenderThread 無法及時接收繪製命令 → 畫面停頓。
- 視訊播放 (硬體合成)
- 視訊 Surface 可直接交由 HWC,避免 GPU 重複合成,節能省電。
- 全螢幕遊戲
- 使用 RenderThread + OpenGL 繪製,SurfaceFlinger 直接將單一 Surface 輸出,減少額外合成。
Summary
- RenderThread:應用內部的渲染專用執行緒,降低延遲並提升幀率穩定性。
- SurfaceFlinger:系統級的合成服務,負責將多應用的 Surface 合成,並輸出到螢幕。
- VSync 與 BufferQueue:確保畫面更新與顯示同步,避免撕裂與掉幀。
- HWComposer:降低 GPU 負擔,提高能效。