Implementación de hardware Composer HAL

El Composer de hardware (HWC) HAL compone las capas recibidas de SurfaceFlinger, lo que reduce la cantidad de composición que realizan OpenGL ES (GLES) y la GPU.

El HWC abstrae objetos, como superposiciones y blitters 2D, en superficies compuestas y se comunica con hardware de composición de ventanas especializado en ventanas compuestas. Use el HWC para componer ventanas en lugar de tener compuesto SurfaceFlinger con la GPU. La mayoría de las GPU no están optimizadas para la composición y, cuando la GPU compone capas desde SurfaceFlinger, las aplicaciones no pueden usar la GPU para su propia representación.

Las implementaciones de HWC deben admitir:

  • Al menos cuatro superposiciones:
    • Barra de estado
    • Barra de sistema
    • aplicación
    • Fondo de pantalla/fondo
  • Capas que son más grandes que la pantalla (por ejemplo, un fondo de pantalla)
  • Mezcla alfa por píxel premultiplicada y mezcla alfa por plano simultáneas
  • Ruta de hardware para reproducción de video protegida
  • Orden de empaque RGBA, formatos YUV y propiedades de mosaico, swizzling y stride

Para implementar el HWC:

  1. Implemente un HWC no operativo y envíe todo el trabajo de composición a GLES.
  2. Implemente un algoritmo para delegar la composición al HWC de forma incremental. Por ejemplo, delegue solo las primeras tres o cuatro superficies al hardware de superposición del HWC.
  3. Optimizar el HWC. Esto puede incluir:
    • Seleccionar superficies que maximicen la carga quitada de la GPU y enviarlas al HWC.
    • Detectar si la pantalla se está actualizando. Si no es así, delegue la composición a GLES en lugar de HWC para ahorrar energía. Cuando la pantalla se actualice nuevamente, continúe descargando la composición al HWC.
    • Preparación para casos de uso comunes como:
      • La pantalla de inicio, que incluye la barra de estado, la barra del sistema, la ventana de la aplicación y los fondos de pantalla en vivo
      • Juegos a pantalla completa en modo vertical y horizontal
      • Video de pantalla completa con subtítulos y control de reproducción
      • Reproducción de video protegida
      • Multiventana de pantalla dividida

primitivos de HWC

El HWC proporciona dos primitivas, capas y visualizaciones , para representar el trabajo de composición y su interacción con el hardware de visualización. El HWC también proporciona control sobre VSYNC y una devolución de llamada a SurfaceFlinger para notificarlo cuando ocurre un evento VSYNC.

interfaz HIDL

Android 8.0 y versiones posteriores usan una interfaz HIDL llamada Composer HAL para IPC encuadernado entre HWC y SurfaceFlinger. Composer HAL reemplaza la interfaz heredada hwcomposer2.h . Si los proveedores proporcionan una implementación Composer HAL del HWC, Composer HAL acepta directamente llamadas HIDL de SurfaceFlinger. Si los proveedores proporcionan una implementación heredada de HWC, Composer HAL carga punteros de función desde hwcomposer2.h , reenviando llamadas HIDL a llamadas de puntero de función.

El HWC proporciona funciones para determinar las propiedades de una pantalla dada; para cambiar entre diferentes configuraciones de pantalla (como resolución 4k o 1080p) y modos de color (como color nativo o sRGB real); y para encender, apagar o poner la pantalla en un modo de bajo consumo, si es compatible.

Punteros de función

Si los proveedores implementan Composer HAL directamente, SurfaceFlinger llama a sus funciones a través de HIDL IPC. Por ejemplo, para crear una capa, SurfaceFlinger llama a createLayer() en Composer HAL.

Si los proveedores implementan la interfaz hwcomposer2.h , Composer HAL llama a los punteros de función hwcomposer2.h . En los comentarios de hwcomposer2.h , se hace referencia a las funciones de interfaz de HWC mediante nombres lowerCamelCase que no existen en la interfaz como campos con nombre. Casi todas las funciones se cargan solicitando un puntero de función mediante getFunction proporcionado por hwc2_device_t . Por ejemplo, la función createLayer es un puntero de función de tipo HWC2_PFN_CREATE_LAYER , que se devuelve cuando el valor enumerado HWC2_FUNCTION_CREATE_LAYER se pasa a getFunction .

Para obtener documentación detallada sobre las funciones HAL de Composer y las funciones de transferencia de funciones HWC, consulte composer . Para obtener documentación detallada sobre los punteros de funciones de HWC, consulte hwcomposer2.h .

Controles de capa y visualización

Las capas y las visualizaciones se manipulan mediante identificadores generados por el HWC. Los controles son opacos para SurfaceFlinger.

Cuando SurfaceFlinger crea una nueva capa, llama a createLayer , que devuelve el tipo Layer para implementaciones directas o hwc2_layer_t para implementaciones de transferencia. Cuando SurfaceFlinger modifica una propiedad de esa capa, SurfaceFlinger pasa el valor hwc2_layer_t a la función de modificación adecuada junto con cualquier otra información necesaria para realizar la modificación. El tipo hwc2_layer_t es lo suficientemente grande como para contener un puntero o un índice.

Las pantallas físicas se crean conectando en caliente. Cuando una pantalla física se conecta en caliente, el HWC crea un identificador y pasa el identificador a SurfaceFlinger a través de la devolución de llamada de conexión en caliente. SurfaceFlinger crea pantallas virtuales llamando a createVirtualDisplay() para solicitar una pantalla. Si el HWC admite la composición de visualización virtual, devuelve un identificador. Luego, SurfaceFlinger delega la composición de las pantallas al HWC. Si el HWC no admite la composición de pantalla virtual, SurfaceFlinger crea el identificador y compone la pantalla.

Operaciones de composición de pantalla

Una vez por VSYNC, SurfaceFlinger se activa si tiene contenido nuevo para componer. Este nuevo contenido puede ser nuevos búferes de imágenes de aplicaciones o un cambio en las propiedades de una o más capas. Cuando SurfaceFlinger lo despierta:

  1. Maneja las transacciones, si las hay.
  2. Bloquea los nuevos búferes gráficos, si los hay.
  3. Realiza una nueva composición, si el paso 1 o 2 resultó en un cambio en el contenido de la pantalla.

Para realizar una nueva composición, SurfaceFlinger crea y destruye capas o modifica los estados de las capas, según corresponda. También actualiza las capas con su contenido actual mediante llamadas como setLayerBuffer o setLayerColor . Después de actualizar todas las capas, SurfaceFlinger llama a validateDisplay , que le indica al HWC que examine el estado de las capas y determine cómo procederá la composición. De forma predeterminada, SurfaceFlinger intenta configurar cada capa de modo que la capa esté compuesta por el HWC; aunque en algunas circunstancias, las capas compuestas de SurfaceFlinger se superponen a la GPU.

Después de la llamada a validateDisplay , SurfaceFlinger llama a getChangedCompositionTypes para ver si el HWC quiere que se cambie alguno de los tipos de composición de capa antes de realizar la composición. Para aceptar los cambios, SurfaceFlinger llama a acceptDisplayChanges .

Si alguna capa está marcada para la composición de SurfaceFlinger, SurfaceFlinger las compone en el búfer de destino. Luego, SurfaceFlinger llama a setClientTarget para proporcionar el búfer a la pantalla para que el búfer se pueda mostrar en la pantalla o se pueda combinar con capas que no se han marcado para la composición de SurfaceFlinger. Si no hay capas marcadas para la composición de SurfaceFlinger, SurfaceFlinger omite el paso de composición.

Finalmente, SurfaceFlinger llama a presentDisplay para indicarle al HWC que complete el proceso de composición y muestre el resultado final.

Múltiples pantallas

Android 10 admite varias pantallas físicas. Al diseñar una implementación de HWC destinada a su uso en Android 7.0 y versiones posteriores, existen algunas restricciones que no están presentes en la definición de HWC:

  • Se supone que hay exactamente una pantalla interna . La pantalla interna es la pantalla que informa el hotplug inicial durante el arranque. Una vez que la pantalla interna se conecta en caliente, no se puede desconectar.
  • Además de la pantalla interna, cualquier cantidad de pantallas externas se pueden conectar en caliente durante el funcionamiento normal del dispositivo. El marco asume que todos los hotplugs después de la primera pantalla interna son pantallas externas, por lo que si se agregan más pantallas internas, se clasifican incorrectamente como Display.TYPE_HDMI en lugar de Display.TYPE_BUILT_IN .

Si bien las operaciones de SurfaceFlinger descritas anteriormente se realizan por pantalla, se realizan secuencialmente para todas las pantallas activas, incluso si se actualiza el contenido de una sola pantalla.

Por ejemplo, si se actualiza la pantalla externa, la secuencia es:

// In Android 9 and lower:

// Update state for internal display
// Update state for external display
validateDisplay(<internal display>)
validateDisplay(<external display>)
presentDisplay(<internal display>)
presentDisplay(<external display>)

// In Android 10 and higher:

// Update state for internal display
// Update state for external display
validateInternal(<internal display>)
presentInternal(<internal display>)
validateExternal(<external display>)
presentExternal(<external display>)

Composición de la pantalla virtual

La composición de la pantalla virtual es similar a la composición de la pantalla externa. La diferencia entre la composición de la pantalla virtual y la composición de la pantalla física es que las pantallas virtuales envían la salida a un búfer Gralloc en lugar de a la pantalla. Hardware Composer (HWC) escribe la salida en un búfer, proporciona la valla de finalización y envía el búfer a un consumidor (como el codificador de video, la GPU, la CPU, etc.). Las pantallas virtuales pueden usar 2D/blitter o superposiciones si la canalización de pantalla escribe en la memoria.

Modos

Cada cuadro se encuentra en uno de los tres modos después de que SurfaceFlinger llama al método de HWC validateDisplay() :

  • GLES : la GPU compone todas las capas y escribe directamente en el búfer de salida. El HWC no está involucrado en la composición.
  • MIXTO : la GPU compone algunas capas en el búfer de fotogramas y HWC compone el búfer de fotogramas y las capas restantes, escribiendo directamente en el búfer de salida.
  • HWC : HWC compone todas las capas y escribe directamente en el búfer de salida.

Formato de salida

Los formatos de salida del búfer de visualización virtual dependen de su modo:

  • Modo GLES : el controlador EGL establece el formato del búfer de salida en dequeueBuffer() , generalmente RGBA_8888 . El consumidor debe poder aceptar el formato de salida que establece el controlador o el búfer no se puede leer.
  • Modos MIXED y HWC : si el consumidor necesita acceso a la CPU, el consumidor establece el formato. De lo contrario, el formato es IMPLEMENTATION_DEFINED y Gralloc establece el mejor formato en función de las marcas de uso. Por ejemplo, Gralloc establece un formato YCbCr si el consumidor es un codificador de video y HWC puede escribir el formato de manera eficiente.

Vallas de sincronización

Las vallas de sincronización (sync) son un aspecto crucial del sistema de gráficos de Android. Las vallas permiten que el trabajo de la CPU proceda independientemente del trabajo simultáneo de la GPU, bloqueándose solo cuando hay una verdadera dependencia.

Por ejemplo, cuando una aplicación envía un búfer que se está produciendo en la GPU, también envía un objeto de valla de sincronización. Esta valla señala cuando la GPU ha terminado de escribir en el búfer.

El HWC requiere que la GPU termine de escribir los búferes antes de que se muestren. Las vallas de sincronización se pasan a través de la canalización de gráficos con búferes y señalan cuando se escriben los búferes. Antes de que se muestre un búfer, el HWC verifica si la valla de sincronización ha señalado y, si es así, muestra el búfer.

Para obtener más información acerca de las vallas de sincronización, consulte Integración de Hardware Composer .