Asignación de tono de la luminancia HDR a un rango compatible con SDR

Android 13 presenta una biblioteca estática configurable por el proveedor llamada libtonemap, que define las operaciones de asignación de tono y se comparte con el proceso SurfaceFlinger y las implementaciones de Hardware Composer (HWC). Esta función permite que los OEMs definan y compartan sus algoritmos de asignación de tono de visualización entre el framework y los proveedores, lo que disminuye la falta de coincidencia en la asignación de tono.

Antes de Android 13, las operaciones de asignación de tono específicas de la pantalla no se compartían entre HWC, SurfaceFlinger y las apps. Según la ruta de renderización, en el caso del contenido HDR, esto generaba discrepancias en la calidad de la imagen, ya que el contenido HDR se asignaba a un espacio de salida de diferentes maneras. Esto era perceptible en situaciones como la rotación de pantalla, en la que la estrategia de composición cambia entre la GPU y la DPU, y en las diferencias en el comportamiento de renderización entre TextureView y SurfaceView.

En esta página, se describen los detalles de la interfaz, la personalización y la validación de la biblioteca libtonemap.

Interfaz de la biblioteca de asignación de tonos

La biblioteca libtonemap contiene implementaciones respaldadas por la CPU y sombreadores SkSL, que SurfaceFlinger puede conectar para la composición de backend de GPU y HWC para generar una tabla de consulta (LUT) de asignación de tonos. El punto de entrada a libtonemap es android::tonemap::getToneMapper(), que muestra un objeto que implementa la interfaz ToneMapper.

La interfaz ToneMapper admite las siguientes funciones:

  • Cómo generar una LUT de asignación de tonos

    La interfaz ToneMapper::lookupTonemapGain es una implementación de CPU del sombreador definido en libtonemap_LookupTonemapGain(). Las pruebas de unidades del framework lo usan, y los socios pueden usarlo como asistencia para generar una LUT de asignación de tonos dentro de su canalización de color.

    libtonemap_LookupTonemapGain() toma valores de color en un espacio lineal absoluto y no normalizado, tanto en RGB lineal como en XYZ, y muestra un número de punto flotante que describe cuánto se deben multiplicar los colores de entrada en el espacio lineal.

  • Genera un sombreador SkSL

    La interfaz ToneMapper::generateTonemapGainShaderSkSL() muestra una cadena de sombreador SkSL, dado un espacio de datos de origen y destino. El sombreador SkSL está conectado a la implementación de Skia para RenderEngine, el componente de composición acelerado por GPU de SurfaceFlinger. El sombreador también está conectado a libhwui, de modo que la asignación de tonos de HDR a SDR se pueda realizar de manera eficiente para TextureView. Debido a que la cadena generada está intercalada en otros sombreadores de SkSL que usa Skia, el sombreador debe cumplir con las siguientes reglas:

    • La cadena del sombreador debe tener un punto de entrada con la firma float libtonemap_LookupTonemapGain(vec3 linearRGB, vec3 xyz), en la que linearRGB es el valor de los nits absolutos de los píxeles RGB en el espacio lineal y xyz es linearRGB convertido en XYZ.
    • Cualquier método de ayuda que use la cadena de sombreador debe tener el prefijo libtonemap_ para que las definiciones de sombreador del framework no entren en conflicto. Del mismo modo, los uniformes de entrada deben tener el prefijo in_libtonemap_.
  • Genera uniformes de SkSL

    La interfaz ToneMapper::generateShaderSkSLUniforms() muestra lo siguiente, dado un struct de metadatos que describe metadatos de diferentes estándares de HDR y condiciones de visualización:

    • Una lista de uniformes que vincula un sombreador SkSL.

    • Los valores uniformes in_libtonemap_displayMaxLuminance y in_libtonemap_inputMaxLuminance Los sombreadores del framework usan estos valores cuando escalan la entrada a libtonemap y normalizan 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 de libtonemap produce resultados aceptables. Sin embargo, debido a que el algoritmo de asignación de tonos que usa la composición de la GPU puede diferir del que usa la composición de la DPU, el uso de la implementación de referencia puede provocar parpadeo en algunas situaciones, como en la animación de rotación. La personalización puede resolver esos problemas de calidad de la imagen específicos del proveedor.

Se recomienda encarecidamente a los OEMs que anulen la implementación de libtonemap para definir su propia subclase ToneMapper, que muestra getToneMapper(). Cuando personalizan la implementación, se espera que los socios realicen una de las siguientes acciones:

  • Modifica la implementación de libtonemap directamente.
  • Definir su propia biblioteca estática, compilarla como independiente y reemplazar el archivo .a de la biblioteca libtonemap por el que se genera a partir de su biblioteca personalizada

Los proveedores no necesitan modificar ningún código de kernel, pero varios proveedores deben comunicar detalles sobre los algoritmos de asignación de tonos de la DPU para una implementación adecuada.

Validación

Sigue estos pasos para validar la implementación:

  1. Reproduce videos HDR en pantalla de cualquier estándar HDR que admita tu sistema de pantalla, como HLG, HDR10, HDR10+ o Dolby Vision.

  2. Activa o desactiva la composición de la GPU para asegurarte de que no haya parpadeos perceptibles para el usuario.

    Usa el siguiente comando de adb para activar o desactivar 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

Con esta implementación, pueden ocurrir los siguientes problemas:

  • Las bandas se producen cuando el objetivo de renderización que usa la composición de la GPU es de menor precisión que el valor típico del 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 la GPU escriba en un formato de 8 bits, como RGBA8888, para admitir alfa.

  • Un cambio de color sutil se debe a las diferencias de cuantizació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 de precisión relativas del hardware subyacente. Una solución alternativa típica es asegurarse de que haya un paso de dithering en las rutas de precisión más bajas, lo que hace que las diferencias de precisión sean menos perceptibles para las personas.