Surface 和 SurfaceHolder

應用程式可透過 Surface 物件轉譯要在螢幕上顯示的圖像, 且可透過 SurfaceHolder 介面編輯及控制 Surface。

Surface

Surface 是產生者與取用者交換緩衝區的介面。

顯示 Surface 通常會使用為三重緩衝設定的 BufferQueue。緩衝區是依需求分配,因此如果產生者產生緩衝區的速度不夠快,例如在 60 FPS 的螢幕上以 30 FPS 的速度產生緩衝區,佇列中可能只會分配兩個緩衝區。視需要配置緩衝區有助於盡可能降低記憶體用量。您可以查看 dumpsys SurfaceFlinger 輸出內容中各圖層相關聯的緩衝區摘要。

大多數用戶端在 Surface 上轉譯內容時,會使用 OpenGL ESVulkan。不過,部分用戶端會使用畫布轉譯至 Surface 上。

畫布轉譯

Skia Graphics Library 提供畫布實作。如要繪製矩形,請呼叫 Canvas API,在緩衝區中適當設定位元組。為確保緩衝區不會有兩個用戶端同時更新,或在顯示時遭寫入,存取前請鎖定緩衝區。請使用下列指令處理畫布鎖定:

  • lockCanvas() 會鎖定緩衝區,以便在 CPU 上進行轉譯,並傳回用於繪圖的 Canvas。
  • unlockCanvasAndPost() 會解鎖緩衝區,並傳送至合成器。
  • lockHardwareCanvas() 會鎖定緩衝區,以便在 GPU 上進行轉譯,並傳回用於繪圖的畫布。

產生者首次向 BufferQueue 要求緩衝區時,系統會分配緩衝區並初始化為零。初始化作業是必要步驟,可避免程序之間不慎共用資料。不過,如果重複使用緩衝區,先前的內容仍會存在。如果重複呼叫 lockCanvas()unlockCanvasAndPost(),但未繪製任何內容,生產者會在先前轉譯的影格之間循環。

Surface 鎖定/解除鎖定程式碼會保留先前轉譯緩衝區的參照。如果在鎖定 Surface 時指定骯髒區域,系統會從先前的緩衝區複製非髒區像素。SurfaceFlinger 或 HWC 通常會處理緩衝區,但由於您只需要從緩衝區讀取資料,因此不必等待專屬存取權。

SurfaceHolder

SurfaceHolder 是系統用來與應用程式共用 Surface 擁有權的介面。部分使用 Surface 的用戶端需要 SurfaceHolder,因為取得及設定介面參數的 API 是透過 SurfaceHolder 實作。SurfaceView 包含 SurfaceHolder。

與檢視區塊互動的大多數元件都涉及 SurfaceHolder。部分 API (例如 MediaCodec) 則直接操作 Surface。