O Android 13 introduz uma biblioteca estática
configurável pelo fornecedor chamada libtonemap
, que define operações de mapeamento de tons e é compartilhada
com o processo SurfaceFlinger e as implementações do Hardware Composer (HWC).
Esse recurso permite que os OEMs definam e compartilhem os algoritmos de mapeamento de tons de telas entre o framework e os fornecedores, o que diminui a incompatibilidade nos mapeamentos.
Antes do Android 13, as operações de mapeamento de tons específicas da tela não eram compartilhadas entre o HWC, o SurfaceFlinger e os apps. Dependendo do caminho de renderização, para conteúdo HDR, isso resultou em incompatibilidades na qualidade da imagem, em que o conteúdo HDR foi mapeado para um espaço de saída de maneiras diferentes. Isso era perceptível em cenários como a rotação da tela, em que a estratégia de composição muda entre a GPU e a DPU, e em diferenças no comportamento de renderização entre TextureView e SurfaceView.
Esta página descreve a interface, a personalização e os detalhes de validação da biblioteca libtonemap
.
Interface para a biblioteca de mapeamento de tons.
A biblioteca libtonemap
contém implementações com suporte de CPU e shaders SkSL, que podem ser
conectados pelo SurfaceFlinger para composição de back-end de GPU e pelo HWC para
gerar uma tabela de pesquisa (LUT) de mapeamento de tons. O ponto de entrada para libtonemap
é android::tonemap::getToneMapper()
, que retorna um objeto que
implementa a interface ToneMapper
.
A interface ToneMapper
oferece suporte aos seguintes recursos:
Gerar uma LUT de mapeamento de tons
A interface
ToneMapper::lookupTonemapGain
é uma implementação de CPU do shader definido emlibtonemap_LookupTonemapGain()
. Isso é usado por testes de unidade no framework e pode ser usado por parceiros para ajudar a gerar uma LUT de mapeamento de tons no pipeline de cores.libtonemap_LookupTonemapGain()
usa valores de cor em espaço linear absoluto e não normalizado, tanto em RGB linear quanto em XYZ, e retorna um ponto flutuante que descreve o quanto multiplicar as cores de entrada no espaço linear.Gerar um shader SkSL
A interface
ToneMapper::generateTonemapGainShaderSkSL()
retorna uma string de shader SkSL, considerando um espaço de dados de origem e destino. O sombreador SkSL é conectado à implementação do Skia paraRenderEngine
, o componente de composição acelerada por GPU para o SurfaceFlinger. O shader também é conectado aolibhwui
para que o mapeamento de tons HDR para SDR possa ser realizado de maneira eficiente paraTextureView
. Como a string gerada é incorporada a outros shaders SkSL usados pelo Skia, o shader precisa obedecer às seguintes regras:- A string do shader precisa ter um ponto de entrada com a
assinatura
float libtonemap_LookupTonemapGain(vec3 linearRGB, vec3 xyz)
, em quelinearRGB
é o valor dos nits absolutos dos pixels RGB no espaço linear exyz
élinearRGB
convertido em XYZ. - Todos os métodos auxiliares usados pela string do shader precisam ser prefixados com
a string
libtonemap_
para que as definições de shader da estrutura não entrem em conflito. Da mesma forma, os uniformes de entrada precisam ser prefixados comin_libtonemap_
.
- A string do shader precisa ter um ponto de entrada com a
assinatura
Gerar uniformes SkSL
A interface
ToneMapper::generateShaderSkSLUniforms()
retorna o seguinte, considerando umstruct
de metadados que descreve metadados de diferentes padrões de HDR e condições de exibição:Uma lista de uniformes vinculados por um shader SkSL.
Os valores uniformes
in_libtonemap_displayMaxLuminance
ein_libtonemap_inputMaxLuminance
. Esses valores são usados pelos shaders do framework ao dimensionar a entrada paralibtonemap
e normalizar a saída, conforme aplicável.
No momento, o processo de geração de distribuições uniformes é independente do espaço de dados de entrada e saída.
Personalização
A implementação de referência da biblioteca libtonemap
produz resultados aceitáveis. No entanto, como o algoritmo de mapeamento de tons usado pela composição da GPU pode ser diferente 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.
É altamente recomendável que os OEMs substituam a implementação de libtonemap
para
definir a própria subclasse ToneMapper
, que é retornada por getToneMapper()
.
Ao personalizar a implementação, os parceiros precisam fazer uma das seguintes ações:
- Modifique a implementação de
libtonemap
diretamente. - Defina a própria biblioteca estática, compile a biblioteca como independente e
substitua o arquivo
.a
da bibliotecalibtonemap
pelo gerado na biblioteca personalizada.
Os fornecedores não precisam modificar nenhum código do kernel, mas vários fornecedores precisam comunicar detalhes sobre os algoritmos de mapeamento de tons da DPU para uma implementação adequada.
Validação
Siga estas etapas para validar sua implementação:
Reproduza vídeos em HDR na tela de qualquer padrão HDR compatível com seu sistema de exibição, como HLG, HDR10, HDR10+ ou DolbyVision.
Ative/desative a composição da GPU para garantir que não haja oscilação perceptível ao usuário.
Use o seguinte comando
adb
para ativar ou desativar 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 essa implementação:
O efeito de bandas ocorre quando o destino de renderização usado pela composição da GPU tem uma precisão menor do que o valor típico para conteúdo HDR. Por exemplo, o efeito pode ocorrer quando uma implementação do HWC é compatível com formatos opacos de 10 bits para HDR, como RGBA1010102 ou P010, mas exige que a composição da GPU grave em um formato de 8 bits, como RGBA8888, para oferecer suporte ao 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 de precisão relativa do hardware subjacente. Uma solução alternativa comum é garantir que haja uma etapa de dithering nos caminhos de menor precisão, tornando as diferenças de precisão menos perceptíveis para os humanos.