Mapowanie tonów w zakresie luminancji HDR do zakresu zgodnego z SDR

Android 13 wprowadza konfigurowaną przez dostawcę bibliotekę statyczną libtonemap, która definiuje operacje mapowania tonów i jest udostępniana procesowi SurfaceFlinger i implementacje Hardware Composer (HWC). Ta funkcja umożliwia OEM-om zdefiniowanie i udostępnianie algorytmów mapowania tonacji wyświetlania między frameworkiem a dostawcami, co zmniejsza niezgodności w mapowaniu tonacji.

Przed Androidem 13 operacje mapowania tonacji dla poszczególnych wyświetlaczy nie były udostępniane między HWC, SurfaceFlingerem i aplikacjami. W zależności od ścieżki renderowania w przypadku treści HDR mogło to prowadzić do niezgodności w jakości obrazu, ponieważ treści HDR były mapowane tonowo na przestrzeń wyjściową na różne sposoby. Było to widoczne w sytuacjach takich jak obrót ekranu, gdzie strategia kompozycji zmienia się między GPU a DPU, a także przy różnicach w renderowaniu w obiektach TextureView i SurfaceView.

Na tej stronie opisujemy interfejs, dostosowywanie i szczegóły weryfikacji biblioteki libtonemap.

interfejs biblioteki mapowania tonów;

Biblioteka libtonemap zawiera implementacje obsługiwane przez procesor oraz cieniowanie SkSL, które można podłączyć przez SurfaceFlinger do tworzenia kompozycji w backendzie GPU oraz przez HWC do generowania tabeli wyszukiwania 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 te funkcje:

  • Generowanie LUT do mapowania tonalnego

    Interfejs ToneMapper::lookupTonemapGain to implementacja procesora cieniowania zdefiniowany w libtonemap_LookupTonemapGain(). Jest on używany w testach jednostkowych w ramach struktury i może być używany przez partnerów do pomocy w generowaniu mapowania tonów LUT w ramach potoku kolorów.

    Funkcja libtonemap_LookupTonemapGain() przyjmuje wartości kolorów w bezwzględnej, nienormalizowanej przestrzeni liniowej, zarówno w RGB, jak i w XYZ, i zwraca wartość typu float, która określa, o ile należy pomnożyć wejściowe kolory w przestrzeni liniowej.

  • Wygeneruj program do cieniowania SkSL

    Interfejs ToneMapper::generateTonemapGainShaderSkSL() zwraca ciąg cieniowania SSH dla podanej źródłowej i docelowej przestrzeni danych. Moduł cieniowania SkSL jest podłączony do implementacji Skia dla RenderEngine, czyli komponentu do komponowania z akceleracją za pomocą GPU, platformy SurfaceFlinger. Jest on też podłączony do libhwui, aby można było efektywnie przeprowadzić mapowanie tonacji HDR na SDR w przypadku TextureView. Wygenerowany ciąg znaków jest wbudowany w inne shadery SkSL używane przez Skię, więc shader musi przestrzegać tych zasad:

    • Ciąg cieniowania musi mieć punkt wejścia z podpisem float libtonemap_LookupTonemapGain(vec3 linearRGB, vec3 xyz), gdzie linearRGB to wartość bezwzględnych nitów pikseli RGB w przestrzeni liniowej, a xyz to wartość linearRGB przekształcona na XYZ.
    • Wszystkie metody pomocnicze używane przez ciąg shadera muszą mieć przedrostek libtonemap_, aby definicje shadera w ramach nie powodowały konfliktów. Analogicznie, określenie uniformy wejściowe musi mieć poprzedzony prefiksem in_libtonemap_.
  • Generowanie jednolitej odzieży w SkSL

    Interfejs ToneMapper::generateShaderSkSLUniforms() zwraca te informacje, jeśli metadane struct opisują metadane z różnych standardów HDR i warunków wyświetlania:

    • Lista uniformów objętych cieniowaniem SkSL.

    • Jednolite wartości in_libtonemap_displayMaxLuminance i in_libtonemap_inputMaxLuminance. Wartości te są używane przez cieniowanie platformy podczas skalowania danych wejściowych do typu libtonemap i normalizacji danych wyjściowych w odpowiedni sposób.

    Obecnie proces generowania jednolitych jednostek jest niezależny od przestrzeni danych wejściowych i wyjściowych.

Dostosowywanie

Referencyjna implementacja biblioteki libtonemap daje akceptowalne wyniki. Ponieważ jednak algorytm mapowania tonów wykorzystywany przez kompozycje GPU może się różnić od algorytmu stosowanego w kompozycji DPU, użycie referencyjnej implementacji może w niektórych sytuacjach powodować migotanie, np. w przypadku animacji obracania. Dzięki niej można rozwiązać problemy z jakością obrazu związane z konkretnym dostawcą.

Zdecydowanie zachęcamy producentów OEM do zastąpienia implementacji libtonemap w celu zdefiniowania własnej podklasy ToneMapper, która jest zwracana przez funkcję getToneMapper(). Podczas dostosowywania implementacji partnerzy muszą wykonać jedną z tych czynności:

  • Bezpośrednio zmień implementację elementu libtonemap.
  • zdefiniować własną stałą bibliotekę, skompilować ją jako samodzielną i zastąpić plik libtonemap biblioteki .a plikiem wygenerowanym z niestandardowej biblioteki.

Dostawcy nie muszą modyfikować żadnego kodu jądra, ale wielu z nich musi podać szczegółowe informacje o algorytmach mapowania tonów DPU, aby umożliwić ich prawidłową implementację.

Weryfikacja

Aby zweryfikować implementację:

  1. Odtwarzaj filmy HDR na ekranie zgodnie ze standardami HDR, które są obsługiwane przez system wyświetlacza, np. HLG, HDR10, HDR10+ czy DolbyVision.

  2. Włącz lub wyłącz kompozycję GPU, aby mieć pewność, że nie widać migotania.

    Aby przełączyć kompozycję GPU, użyj tego polecenia adb:

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

Typowe problemy

W przypadku takiej implementacji mogą wystąpić te problemy:

  • Paski powstają, gdy cel renderowania używany przez kompozycję GPU ma mniejszą dokładność niż typowa wartość w przypadku treści HDR. Pasy mogą się pojawiać, gdy implementacja HWC obsługuje nieprzezroczyste formaty 10-bitowe HDR, takie jak RGBA1010102 lub P010, ale wymaga, aby kompozycja procesora graficznego zapisywała w formacie 8-bitowym, takim jak RGBA8888, aby obsługiwać kanał alfa.

  • Subtelne przesunięcie kolorów jest spowodowane różnicami w kwantyzacji, jeśli DPU działa z inną precyzją niż GPU.

Każdy z tych problemów jest związany z względnymi różnicami w dokładności sprzętu. Typowym obejściem jest zapewnienie, aby na ścieżkach o niższej dokładności występował krok ditherowania, dzięki czemu różnice w dokładności są mniej zauważalne dla człowieka.