映射 HDR 亮度與 SDR 相容範圍

Android 13 導入名為 libtonemap 的供應商可設定靜態程式庫,定義色調對應作業,並與 SurfaceFlinger 程序和硬體合成器 (HWC) 實作項目共用。這項功能可讓原始設備製造商在架構和供應商之間定義及共用顯示色調對應演算法,減少色調對應不符的情況。

在 Android 13 之前,HWC、SurfaceFlinger 和應用程式之間不會共用顯示器專屬的色調對應作業。視算繪路徑而定,這會導致 HDR 內容的影像品質不一致,因為 HDR 內容會以不同方式色調對應至輸出空間。在螢幕旋轉等情況下,這種差異會很明顯,因為組合策略會在 GPU 和 DPU 之間變更,而且 TextureView 和 SurfaceView 之間的算繪行為也會有所不同。

本頁說明 libtonemap 程式庫的介面、自訂項目和驗證詳細資料。

色調對應程式庫的介面

libtonemap 程式庫包含 CPU 支援的實作項目和 SkSL 著色器,SurfaceFlinger 可插入這些項目,用於 GPU 後端合成,HWC 則可插入這些項目,用於產生色調對應查閱表 (LUT)。libtonemap 的進入點是 android::tonemap::getToneMapper(),會傳回實作 ToneMapper 介面的物件。

ToneMapper 介面支援下列功能:

  • 產生色調對應 LUT

    介面 ToneMapper::lookupTonemapGainlibtonemap_LookupTonemapGain() 中定義的著色器 CPU 實作項目。架構中的單元測試會使用這個方法,合作夥伴也可以使用這個方法,在色彩管道中產生色調對應 LUT。

    libtonemap_LookupTonemapGain() 會接收絕對、未標準化的線性空間中的顏色值 (線性 RGB 和 XYZ),並傳回浮點數,說明線性空間中輸入顏色要乘上的值。

  • 生成 SkSL 著色器

    介面 ToneMapper::generateTonemapGainShaderSkSL() 會傳回 SkSL 著色器字串,並提供來源和目的地資料空間。SkSL 著色器會插入 Skia 實作項目,用於 RenderEngine,這是 SurfaceFlinger 的 GPU 加速合成元件。著色器也會插入 libhwui,以便有效率地對 TextureView 執行 HDR 到 SDR 的色調對應。由於產生的字串會內嵌至 Skia 使用的其他 SkSL 著色器,因此著色器必須遵守下列規則:

    • 著色器字串必須具有 float libtonemap_LookupTonemapGain(vec3 linearRGB, vec3 xyz) 簽章的進入點,其中 linearRGB 是線性空間中 RGB 像素的絕對亮度值,而 xyz 是轉換為 XYZ 的 linearRGB
    • 著色器字串使用的任何輔助方法都必須加上 libtonemap_ 字串前置字元,以免架構著色器定義發生衝突。同樣地,輸入制服必須以 in_libtonemap_ 為前置字串。
  • 產生 SkSL 統一資源

    介面 ToneMapper::generateShaderSkSLUniforms() 會傳回下列項目,並提供中繼資料 struct,說明不同 HDR 標準和顯示條件的中繼資料:

    • SkSL 著色器所繫結的制服清單。

    • 一致值 in_libtonemap_displayMaxLuminancein_libtonemap_inputMaxLuminance。架構著色器會在將輸入內容縮放至 libtonemap 時使用這些值,並視需要將輸出內容正規化。

    目前,產生制服的程序與輸入和輸出資料空間無關。

自訂

libtonemap 程式庫的參考實作會產生可接受的結果。不過,由於 GPU 合成使用的色調對應演算法可能與 DPU 合成使用的演算法不同,因此在某些情況下 (例如旋轉動畫),使用參考實作可能會導致閃爍。自訂功能可解決這類供應商專屬的影像品質問題。

強烈建議 OEM 覆寫 libtonemap 的實作項目,定義自己的 ToneMapper 子類別,該子類別會由 getToneMapper() 傳回。自訂實作項目時,合作夥伴應執行下列其中一項操作:

  • 直接修改 libtonemap 的實作方式。
  • 自行定義靜態程式庫、將程式庫編譯為獨立程式庫,然後將 libtonemap 程式庫的 .a 檔案替換為從自訂程式庫產生的檔案。

供應商不需要修改任何核心程式碼,但多個供應商必須溝通 DPU 色調對應演算法的詳細資料,才能正確實作。

驗證

請按照下列步驟驗證導入作業:

  1. 顯示系統支援的任何 HDR 標準螢幕上播放 HDR 影片,例如 HLG、HDR10、HDR10+ 或 DolbyVision。

  2. 切換 GPU 合成,確保使用者不會察覺閃爍。

    使用下列 adb 指令切換 GPU 合成:

    adb shell service call SurfaceFlinger 1008 i32 <0 to enable HWC composition,
    1 to force GPU composition>
    
    

常見問題

這種做法可能會導致下列問題:

  • 當 GPU 合成作業使用的算繪目標精確度低於 HDR 內容的典型值時,就會產生色帶。舉例來說,如果 HWC 實作支援 HDR 的不透明 10 位元格式 (例如 RGBA1010102 或 P010),但需要 GPU 合成寫入 RGBA8888 等 8 位元格式來支援 Alpha,就可能發生帶狀現象。

  • 如果 DPU 的運作精確度與 GPU 不同,就會因量化差異而產生細微的色彩變化。

這些問題都與基礎硬體的相對精確度差異有關。常見的解決方法是確保低精確度路徑中有抖動步驟,讓任何精確度差異較不易被人察覺。