O Android 13 introduz um modelo estático 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).
Com esse recurso, OEMs podem definir e compartilhar o mapeamento de tons de telas.
algoritmos entre a estrutura e os fornecedores, diminuindo a incompatibilidade de tom
mapeamento.
Antes do Android 13, mapeamento de tons específico de tela operações não foram compartilhadas entre o HWC, o SurfaceFlinger e os apps. Dependendo no caminho de renderização, para conteúdo HDR, isso causava inconsistências na qualidade da imagem, em que o conteúdo HDR foi mapeado para um espaço de saída de maneiras diferentes. Isso foi perceptível em cenários como rotação da tela, em que a composição mudanças de estratégia entre a GPU e a DPU e as diferenças na renderização entre TextureView e SurfaceView.
Esta página descreve a interface, personalização e detalhes de validação do
libtonemap
.
Interface para a biblioteca de mapeamento de tons
O libtonemap
contém implementações suportadas pela CPU e sombreadores de SkSL, que podem ser
conectado pelo SurfaceFlinger para a composição do back-end de GPU e pelo HWC para
gerar uma tabela de consulta de mapeamento de tons (LUT). O ponto de entrada para libtonemap
é android::tonemap::getToneMapper()
, que retorna um objeto que
implementa a interface ToneMapper
.
A interface ToneMapper
é compatível com os seguintes recursos:
Gerar uma LUT com mapeamento de tons
A interface
ToneMapper::lookupTonemapGain
é uma CPU implementação do sombreador definido emlibtonemap_LookupTonemapGain()
. Isso é usado por testes de unidade no framework e pode ser usado por parceiros para assistência para gerar uma LUT de mapeamento de tons dentro do pipeline de cores.libtonemap_LookupTonemapGain()
aceita valores de cor em valores absolutos, espaço linear não normalizado, tanto em RGB linear quanto em XYZ, e retorna um ponto flutuante descrevendo o quanto multiplicar as cores de entrada no espaço linear.Gerar um sombreador da SkSL
A interface
ToneMapper::generateTonemapGainShaderSkSL()
retorna uma String de sombreador da SkSL, considerando um espaço de dados de origem e destino. O sombreador SkSL é conectado à implementação com Skia paraRenderEngine
, o componente de composição acelerado por GPU para o SurfaceFlinger. O shader também é conectado alibhwui
, para que o mapeamento de tons de HDR para SDR possa ser feito de forma eficiente paraTextureView
. Como a string gerada está alinhada a outros sombreadores de SkSL usados pelo Skia, o sombreador precisa aderir às seguintes regras:- A string de sombreador precisa ter um ponto de entrada com o
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. - Os métodos auxiliares usados pela string do sombreador precisam ser prefixados com
a string
libtonemap_
para que as definições de sombreador do framework não entrem em conflito. Da mesma forma, os uniformes de entrada precisam ter o prefixoin_libtonemap_
.
- A string de sombreador precisa ter um ponto de entrada com o
assinatura
Gerar uniformes da SkSL
A interface
ToneMapper::generateShaderSkSLUniforms()
retorna o seguindo, considerando umstruct
de metadados que descreve metadados de diferentes HDRs e condições de exibição:Uma lista de uniformes vinculados por um sombreador da SkSL.
Os valores uniformes
in_libtonemap_displayMaxLuminance
ein_libtonemap_inputMaxLuminance
. Esses valores são usados por sombreadores de framework ao escalonar a entrada paralibtonemap
e normalizar a saída como aplicável.
Atualmente, o processo de geração de uniformes é independente da entrada e o espaço de dados de saída.
Personalização
A implementação de referência da biblioteca libtonemap
produz resultados aceitáveis. No entanto,
porque o algoritmo de mapeamento de tons usado pela composição da GPU pode ser diferente
pela composição da DPU, o uso da implementação de referência pode causar
oscilar em alguns cenários,
como na animação de rotação. A personalização pode
resolver 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 devem realizar uma das
seguintes:
- Modificar a implementação de
libtonemap
diretamente. - Definir a própria biblioteca estática, compilar a biblioteca como autônoma e
substitua o arquivo
.a
da bibliotecalibtonemap
pelo gerado a partir das biblioteca.
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 implementação.
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 (página em inglês) como HLG, HDR10, HDR10+ ou DolbyVision.
Alterne a composição da GPU para garantir que não haja oscilação perceptível ao 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 essa implementação:
As faixas são causadas quando o destino de renderização usado pela composição da GPU é menor que precisão do que o valor típico para conteúdo HDR. Por exemplo, as faixas podem ser ocorre quando uma implementação de HWC oferece suporte a 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 a alfa.
Uma mudança de cor sutil será causada por diferenças de quantização se a DPU opera com uma precisão diferente da GPU.
Cada um desses problemas está relacionado às diferenças de precisão relativa dos valores ao hardware subjacente. Uma solução alternativa típica é garantir que haja um pontilhamento nos caminhos de precisão mais baixos, tornando as diferenças de precisão menos humanas perceptíveis.