W systemie Android 13 wprowadzono konfigurowalną przez dostawcę bibliotekę statyczną o nazwie libtonemap
, która definiuje operacje mapowania tonów i jest współdzielona z procesami SurfaceFlinger i implementacjami Hardware Composer (HWC). Ta funkcja umożliwia producentom OEM definiowanie i udostępnianie algorytmów mapowania tonów wyświetlacza pomiędzy platformą a dostawcami, zmniejszając niedopasowanie w mapowaniu tonów.
Przed Androidem 13 operacje mapowania tonów specyficzne dla wyświetlacza nie były współdzielone między HWC, SurfaceFlinger i aplikacjami. W zależności od ścieżki renderowania treści HDR prowadziło to do niedopasowania jakości obrazu, w przypadku którego tony treści HDR były na różne sposoby mapowane do przestrzeni wyjściowej. Było to zauważalne w scenariuszach takich jak rotacja ekranu, gdzie strategia kompozycji zmienia się pomiędzy GPU a DPU, oraz w różnicach w zachowaniu renderowania pomiędzy StructureView i SurfaceView.
Na tej stronie opisano interfejs, dostosowywanie i szczegóły sprawdzania poprawności biblioteki libtonemap
.
Interfejs do biblioteki mapowania tonów
Biblioteka libtonemap
zawiera implementacje wspierane przez procesor i moduły cieniujące SkSL, które mogą być podłączone przez SurfaceFlinger w celu komponowania zaplecza GPU oraz przez HWC w celu wygenerowania tabeli przeglądowej mapowania tonów (LUT). Punktem wejścia do libtonemap
jest android::tonemap::getToneMapper()
, który zwraca obiekt implementujący interfejs ToneMapper
.
Interfejs ToneMapper
obsługuje następujące możliwości:
Wygeneruj tabelę LUT mapowania tonów
Interfejs
ToneMapper::lookupTonemapGain
jest implementacją CPU modułu cieniującego zdefiniowanego wlibtonemap_LookupTonemapGain()
. Jest to wykorzystywane w testach jednostkowych w ramach i może być wykorzystywane przez partnerów do pomocy przy generowaniu tablicy LUT mapującej tony w ich potoku kolorów.libtonemap_LookupTonemapGain()
pobiera wartości kolorów w bezwzględnej, nieznormalizowanej przestrzeni liniowej, zarówno w liniowym RGB, jak i XYZ, i zwraca liczbę zmiennoprzecinkową opisującą, jak bardzo należy pomnożyć wejściowe kolory w przestrzeni liniowej.Wygeneruj moduł cieniujący SkSL
Interfejs
ToneMapper::generateTonemapGainShaderSkSL()
zwraca ciąg modułu cieniującego SkSL, biorąc pod uwagę źródłową i docelową przestrzeń danych. Moduł cieniujący SkSL jest podłączony do implementacji Skia dlaRenderEngine
, komponentu do komponowania akcelerowanego przez GPU dla SurfaceFlinger. Moduł cieniujący jest również podłączony dolibhwui
, dzięki czemu można efektywnie wykonać mapowanie tonów HDR-na-SDR dlaTextureView
. Ponieważ wygenerowany ciąg znaków jest osadzony w innych modułach cieniujących SkSL używanych przez Skia, moduł cieniujący musi przestrzegać następujących zasad:- Ciąg modułu cieniującego musi mieć punkt wejścia z sygnaturą
float libtonemap_LookupTonemapGain(vec3 linearRGB, vec3 xyz)
, gdzielinearRGB
to wartość bezwzględnych nitów pikseli RGB w przestrzeni liniowej, axyz
tolinearRGB
przekonwertowane na XYZ. - Wszelkie metody pomocnicze używane przez ciąg modułu cieniującego muszą być poprzedzone ciągiem
libtonemap_
, aby definicje modułu cieniującego platformy nie powodowały konfliktów. Podobnie mundury wejściowe muszą być poprzedzone prefiksemin_libtonemap_
.
- Ciąg modułu cieniującego musi mieć punkt wejścia z sygnaturą
Wygeneruj mundury SkSL
Interfejs
ToneMapper::generateShaderSkSLUniforms()
zwraca następujące informacje, biorąc pod uwagęstruct
metadanych opisującą metadane z różnych standardów HDR i warunków wyświetlania:Lista mundurów powiązanych z modułem cieniującym SkSL.
Jednolite wartości
in_libtonemap_displayMaxLuminance
iin_libtonemap_inputMaxLuminance
. Wartości te są używane przez shadery frameworka podczas skalowania danych wejściowych dolibtonemap
i normalizowania danych wyjściowych, jeśli ma to zastosowanie.
Obecnie proces generowania uniformów jest niezależny od wejściowej i wyjściowej przestrzeni danych.
Dostosowywanie
Referencyjna implementacja biblioteki libtonemap
daje akceptowalne wyniki. Jednakże, ponieważ algorytm mapowania tonów używany przez kompozycję GPU może różnić się od algorytmu używanego przez kompozycję DPU, użycie implementacji referencyjnej może powodować migotanie w niektórych scenariuszach, takich jak animacja obrotu. Dostosowanie może rozwiązać problemy związane z jakością obrazu, specyficzne dla dostawcy.
Zdecydowanie zachęca się producentów OEM do zastąpienia implementacji libtonemap
w celu zdefiniowania własnej podklasy ToneMapper
, która jest zwracana przez getToneMapper()
. Podczas dostosowywania wdrożenia oczekuje się, że partnerzy wykonają jedną z następujących czynności:
- Zmodyfikuj bezpośrednio implementację
libtonemap
. - Zdefiniuj własną bibliotekę statyczną, skompiluj ją jako samodzielną i zamień plik
.a
bibliotekilibtonemap
na plik wygenerowany z własnej biblioteki.
Dostawcy nie muszą modyfikować żadnego kodu jądra, ale wielu dostawców musi przekazać szczegółowe informacje na temat algorytmów mapowania tonów DPU, aby zapewnić prawidłową implementację.
Walidacja
Wykonaj poniższe kroki, aby sprawdzić poprawność implementacji:
Odtwarzaj filmy HDR na ekranie dowolnego standardu HDR obsługiwanego przez Twój system wyświetlania , np. HLG, HDR10, HDR10+ lub DolbyVision.
Przełącz kompozycję procesora graficznego, aby upewnić się, że nie ma zauważalnego przez użytkownika migotania.
Użyj następującego polecenia
adb
, aby przełączyć kompozycję GPU:adb shell service call SurfaceFlinger 1008 i32 <0 to enable HWC composition, 1 to force GPU composition>
Powszechne problemy
W przypadku tej implementacji mogą wystąpić następujące problemy:
Pasmowanie powstaje, gdy cel renderowania używany przez kompozycję procesora graficznego ma niższą precyzję niż typowa wartość dla treści HDR. Na przykład pasma mogą wystąpić, gdy implementacja HWC obsługuje nieprzezroczyste 10-bitowe formaty HDR, takie jak RGBA1010102 lub P010, ale wymaga, aby kompozycja procesora graficznego zapisywała w formacie 8-bitowym, takim jak RGBA8888, aby obsługiwać alfa.
Subtelne przesunięcie kolorów jest spowodowane różnicami w kwantyzacji, jeśli procesor DPU działa z inną precyzją niż procesor graficzny.
Każdy z tych problemów jest związany ze względnymi różnicami w precyzji podstawowego sprzętu. Typowym obejściem jest zapewnienie kroku ditheringu na ścieżkach o niższej precyzji, dzięki czemu wszelkie różnice w precyzji będą mniej zauważalne dla człowieka.