Android 13 presenta una biblioteca estática configurable por el proveedor llamada libtonemap
, que define operaciones de mapeo de tonos y se comparte con el proceso SurfaceFlinger y las implementaciones de Hardware Composer (HWC). Esta característica permite a los OEM definir y compartir sus algoritmos de asignación de tonos de pantalla entre el marco y los proveedores, lo que reduce la falta de coincidencia en la asignación de tonos.
Antes de Android 13, las operaciones de mapeo de tonos específicos de la pantalla no se compartían entre HWC, SurfaceFlinger y las aplicaciones. Dependiendo de la ruta de renderizado, para el contenido HDR, esto generaba discrepancias en la calidad de la imagen, donde el tono del contenido HDR se asignaba a un espacio de salida de diferentes maneras. Esto fue perceptible en escenarios como la rotación de la pantalla, donde la estrategia de composición cambia entre la GPU y la DPU, y en las diferencias en el comportamiento de renderizado entre TextureView y SurfaceView.
Esta página describe la interfaz, la personalización y los detalles de validación de la biblioteca libtonemap
.
Interfaz para la biblioteca de mapeo de tonos
La biblioteca libtonemap
contiene implementaciones respaldadas por CPU y sombreadores SkSL, que SurfaceFlinger puede conectar para la composición del backend de GPU y HWC para generar una tabla de búsqueda de mapeo de tonos (LUT). El punto de entrada a libtonemap
es android::tonemap::getToneMapper()
, que devuelve un objeto que implementa la interfaz ToneMapper
.
La interfaz ToneMapper
admite las siguientes capacidades:
Generar una LUT de mapeo de tonos
La interfaz
ToneMapper::lookupTonemapGain
es una implementación de CPU del sombreador definido enlibtonemap_LookupTonemapGain()
. Esto se utiliza en las pruebas unitarias del marco y los socios pueden utilizarlo para obtener ayuda a la hora de generar una LUT de mapeo de tonos dentro de su canal de color.libtonemap_LookupTonemapGain()
toma valores de color en un espacio lineal absoluto y no normalizado, tanto en RGB lineal como en XYZ, y devuelve un flotante que describe cuánto multiplicar los colores de entrada en el espacio lineal.Generar un sombreador SkSL
La interfaz
ToneMapper::generateTonemapGainShaderSkSL()
devuelve una cadena de sombreador SkSL, dado un espacio de datos de origen y destino. El sombreador SkSL está conectado a la implementación Skia paraRenderEngine
, el componente de composición acelerado por GPU para SurfaceFlinger. El sombreador también está conectado alibhwui
, de modo que el mapeo de tonos HDR a SDR se puede realizar de manera eficiente paraTextureView
. Debido a que la cadena generada está integrada en otros sombreadores SkSL utilizados por Skia, el sombreador debe cumplir con las siguientes reglas:- La cadena de sombreado debe tener un punto de entrada con la firma
float libtonemap_LookupTonemapGain(vec3 linearRGB, vec3 xyz)
, dondelinearRGB
es el valor de las nits absolutas de los píxeles RGB en el espacio lineal yxyz
eslinearRGB
convertido a XYZ. - Cualquier método auxiliar utilizado por la cadena de sombreado debe tener el prefijo
libtonemap_
para que las definiciones del sombreador de marco no entren en conflicto. De manera similar, los uniformes de entrada deben tener el prefijoin_libtonemap_
.
- La cadena de sombreado debe tener un punto de entrada con la firma
Generar uniformes SkSL
La interfaz
ToneMapper::generateShaderSkSLUniforms()
devuelve lo siguiente, dada unastruct
de metadatos que describe metadatos de diferentes estándares HDR y condiciones de visualización:Una lista de uniformes vinculados por un sombreador SkSL.
Los valores uniformes
in_libtonemap_displayMaxLuminance
yin_libtonemap_inputMaxLuminance
. Estos valores son utilizados por los sombreadores del marco al escalar la entrada alibtonemap
y normalizar la salida según corresponda.
Actualmente, el proceso de generación de uniformes es independiente del espacio de datos de entrada y salida.
Personalización
La implementación de referencia de la biblioteca libtonemap
produce resultados aceptables. Sin embargo, debido a que el algoritmo de mapeo de tonos usado por la composición de GPU puede diferir del usado por la composición de DPU, el uso de la implementación de referencia puede causar parpadeos en algunos escenarios, como la animación de rotación. La personalización puede resolver estos problemas de calidad de imagen específicos del proveedor.
Se recomienda encarecidamente a los OEM que anulen la implementación de libtonemap
para definir su propia subclase ToneMapper
, que es devuelta por getToneMapper()
. Al personalizar la implementación, se espera que los socios realicen una de las siguientes acciones:
- Modifique la implementación de
libtonemap
directamente. - Defina su propia biblioteca estática, compile la biblioteca como independiente y reemplace el archivo
.a
de la bibliotecalibtonemap
con el generado a partir de su biblioteca personalizada.
Los proveedores no necesitan modificar ningún código del kernel, pero varios proveedores deben comunicar detalles sobre los algoritmos de mapeo de tonos de la DPU para una implementación adecuada.
Validación
Siga estos pasos para validar su implementación:
Reproduzca videos HDR en la pantalla de cualquier estándar HDR compatible con su sistema de visualización , como HLG, HDR10, HDR10+ o DolbyVision.
Cambie la composición de la GPU para asegurarse de que no haya ningún parpadeo perceptible por el usuario.
Utilice el siguiente comando
adb
para alternar la composición de la GPU:adb shell service call SurfaceFlinger 1008 i32 <0 to enable HWC composition, 1 to force GPU composition>
Problemas comunes
Los siguientes problemas pueden ocurrir con esta implementación:
Las bandas se producen cuando el objetivo de renderizado utilizado por la composición de GPU tiene una precisión menor que el valor típico para el contenido HDR. Por ejemplo, las bandas pueden ocurrir cuando una implementación de HWC admite formatos opacos de 10 bits para HDR, como RGBA1010102 o P010, pero requiere que la composición de GPU escriba en un formato de 8 bits, como RGBA8888, para admitir alfa.
Un cambio de color sutil es causado por diferencias de cuantificación si la DPU opera con una precisión diferente a la de la GPU.
Cada uno de estos problemas está relacionado con las diferencias relativas de precisión del hardware subyacente. Una solución típica es garantizar que haya un paso de oscilación en las rutas de menor precisión, lo que hace que cualquier diferencia de precisión sea menos perceptible para los humanos.