Mapeamento de tom de luminância HDR para uma faixa compatível com SDR

O Android 13 apresenta uma biblioteca estática configurável pelo fornecedor chamada libtonemap , que define as operações de mapeamento de tom e é compartilhada com o processo SurfaceFlinger e as implementações do Hardware Composer (HWC). Esse recurso permite que os OEMs definam e compartilhem seus algoritmos de mapeamento de tom de exibição entre a estrutura e os fornecedores, diminuindo a incompatibilidade no mapeamento de tom.

Antes do Android 13, as operações de mapeamento de tom específicas da tela não eram compartilhadas entre HWC, SurfaceFlinger e aplicativos. Dependendo do caminho de renderização, para o conteúdo HDR, isso levava a incompatibilidades na qualidade da imagem, em que o conteúdo HDR era mapeado para um espaço de saída de maneiras diferentes. Isso foi perceptível em cenários como rotação de tela, onde a estratégia de composição muda entre GPU e DPU, e em diferenças no comportamento de renderização entre TextureView e SurfaceView.

Esta página descreve a interface, personalização e detalhes de validação da biblioteca libtonemap .

Interface para a biblioteca de mapeamento de tom

A biblioteca libtonemap contém implementações com suporte de CPU e sombreadores SkSL, que podem ser conectados por SurfaceFlinger para composição de back-end de GPU e pelo HWC para gerar uma tabela de consulta de mapeamento de tom (LUT). O ponto de entrada para libtonemap é android::tonemap::getToneMapper() , que retorna um objeto que implementa a interface ToneMapper .

A interface ToneMapper suporta os seguintes recursos:

  • Gerar uma LUT de mapeamento de tom

    A interface ToneMapper::lookupTonemapGain é uma implementação de CPU do shader definido em libtonemap_LookupTonemapGain() . Isso é usado por testes de unidade na estrutura e pode ser usado por parceiros para obter assistência na geração de uma LUT de mapeamento de tom dentro de seu pipeline de cores.

    libtonemap_LookupTonemapGain() recebe valores de cores em espaço linear absoluto e não normalizado, tanto em RGB linear quanto em XYZ, e retorna um float descrevendo quanto multiplicar as cores de entrada no espaço linear.

  • Gerar um sombreador SkSL

    A interface ToneMapper::generateTonemapGainShaderSkSL() retorna uma string de shader SkSL, dado um espaço de dados de origem e destino. O shader SkSL está conectado à implementação Skia para RenderEngine , o componente de composição acelerado por GPU para SurfaceFlinger. O sombreador também é conectado ao libhwui , para que o mapeamento de tom HDR para SDR possa ser executado com eficiência para TextureView . Como a string gerada é incorporada a outros sombreadores SkSL usados ​​pelo Skia, o sombreador deve seguir as seguintes regras:

    • A string do shader deve ter um ponto de entrada com a assinatura float libtonemap_LookupTonemapGain(vec3 linearRGB, vec3 xyz) , onde linearRGB é o valor dos nits absolutos dos pixels RGB no espaço linear e xyz é linearRGB convertido em XYZ.
    • Quaisquer métodos auxiliares usados ​​pela sequência de shader devem ser prefixados com a string libtonemap_ para que as definições de shader de estrutura não entrem em conflito. Da mesma forma, os uniformes de entrada devem ser prefixados com in_libtonemap_ .
  • Gerar uniformes SkSL

    A interface ToneMapper::generateShaderSkSLUniforms() retorna o seguinte, dado uma struct de metadados que descreve metadados de diferentes padrões HDR e condições de exibição:

    • Uma lista de uniformes vinculados a um sombreador SkSL.

    • Os valores uniformes in_libtonemap_displayMaxLuminance e in_libtonemap_inputMaxLuminance . Esses valores são usados ​​por sombreadores de estrutura ao dimensionar a entrada em libtonemap e normalizar a saída conforme aplicável.

    Atualmente, o processo de geração de uniformes é independente do espaço de dados de entrada e saída.

Costumização

A implementação de referência da biblioteca libtonemap produz resultados aceitáveis. No entanto, como o algoritmo de mapeamento de tom usado pela composição da GPU pode diferir daquele usado pela composição da DPU, o uso da implementação de referência pode causar oscilação em alguns cenários, como a animação de rotação. A personalização pode resolver esses problemas de qualidade de imagem específicos do fornecedor.

Os OEMs são fortemente encorajados a substituir a implementação de libtonemap para definir sua própria subclasse ToneMapper , que é retornada por getToneMapper() . Ao personalizar a implementação, espera-se que os parceiros façam o seguinte:

  • Modifique a implementação de libtonemap diretamente.
  • Defina sua própria biblioteca estática, compile a biblioteca como autônoma e substitua o arquivo .a da biblioteca libtonemap por aquele gerado a partir de sua biblioteca personalizada.

Os fornecedores não precisam modificar nenhum código de kernel, mas vários fornecedores devem comunicar detalhes sobre os algoritmos de mapeamento de tom DPU para implementação adequada.

Validação

Siga estas etapas para validar sua implementação:

  1. Reproduza vídeos HDR na tela de qualquer padrão HDR compatível com seu sistema de exibição , como HLG, HDR10, HDR10+ ou DolbyVision.

  2. Alterne a composição da GPU para garantir que não haja cintilação perceptível pelo usuário.

    Use o seguinte comando adb para alternar a composição da GPU:

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

Problemas comuns

Os seguintes problemas podem ocorrer com esta implementação:

  • As faixas são causadas quando o destino de renderização usado pela composição da GPU é de precisão menor do que o valor típico do conteúdo HDR. Por exemplo, bandas podem ocorrer quando uma implementação HWC oferece suporte a formatos opacos de 10 bits para HDR, como RGBA1010102 ou P010, mas requer que a composição da GPU grave em um formato de 8 bits, como RGBA8888, para oferecer suporte a alfa.

  • Uma mudança sutil de cor é causada por diferenças de quantização se a DPU operar com uma precisão diferente da GPU.

Cada um desses problemas está relacionado às diferenças relativas de precisão do hardware subjacente. Uma solução típica é garantir que haja uma etapa de pontilhamento nos caminhos de precisão mais baixos, tornando as diferenças de precisão menos perceptíveis por humanos.