Gráficos

Ícono del HAL de gráficos de Android

El framework de Android ofrece una variedad de APIs de renderización de gráficos para 2D y 3D que interactúan con las implementaciones de los fabricantes de controladores de gráficos, por lo que es importante comprender bien cómo funcionan esas APIs a un nivel superior. En esta página, se presenta la capa de abstracción de hardware (HAL) de gráficos en la que se compilan esos controladores. Antes de continuar con esta sección, familiarízate con los siguientes términos:

canvas (término genérico), Canvas (elemento de la API)
Un lienzo es una superficie de dibujo que controla la composición de los bits reales en un mapa de bits o un objeto Surface. La clase Canvas tiene métodos para el dibujo estándar por computadora de mapas de bits, líneas, círculos, rectángulos, texto, etc., y está vinculada a un mapa de bits o una superficie. Un lienzo es la manera más sencilla de dibujar objetos en 2D en la pantalla. La clase base es Canvas.
elemento de diseño
Un elemento de diseño es un recurso visual compilado que se puede usar como fondo, título o otra parte de la pantalla. Los elementos de diseño se cargan normalmente en otro elemento de la IU, por ejemplo, como imagen de fondo. Un elemento de diseño no puede recibir eventos, pero asigna varias otras propiedades, como estado y programación, para habilitar subclases como objetos de animación o bibliotecas de imágenes. Muchos objetos de diseño se cargan desde archivos de recursos de elementos de diseño: archivos XML o de mapa de bits que describen la imagen. Los recursos de elementos de diseño se compilan en subclases de android.graphics.drawable. Para obtener más información sobre los elementos de diseño y otros recursos, consulta la Descripción general de los recursos de la app.
recurso de diseño
Un recurso de diseño es un archivo XML que describe el diseño de una pantalla de actividad. Para obtener más información, consulta Recurso de diseño.
nine-patch (9-patch, NinePatch)
Una imagen nine-patch es un recurso de mapa de bits de tamaño ajustable que se puede usar para fondos u otras imágenes en el dispositivo. Para obtener más información, consulta Nine-patch.
OpenGL ES
OpenGL ES es una API multiplataforma para renderizar gráficos 2D y 3D. Android proporciona bibliotecas de OpenGL ES para el procesamiento en 3D acelerado por hardware. En el caso del procesamiento en 2D, un lienzo es la opción más simple. OpenGL ES está disponible en el kit de desarrollo nativo (NDK) de Android. Los paquetes android.opengl y javax.microedition.khronos.opengles exponen la funcionalidad de OpenGL ES.
superficie (término genérico), Surface (elemento de la API)
Una superficie representa un bloque de memoria que se compone en la pantalla. Una superficie contiene un lienzo para dibujar y proporciona varios métodos que ayudan a dibujar capas y cambiar el tamaño del objeto Surface. Usa la clase SurfaceView en lugar de la clase Surface directamente.
vista de superficie (término genérico), SurfaceView (elemento de la API)
Una vista de superficie es un objeto View que une un objeto Surface para dibujar y expone métodos para especificar su tamaño y formato de forma dinámica. Una vista de superficie proporciona una forma de dibujar independientemente del subproceso de la IU para operaciones que requieren un uso intensivo de los recursos, como juegos o vistas previas de cámara, pero, como resultado, utiliza memoria adicional. Una vista de superficie admite gráficos de lienzo y OpenGL ES. La clase base para un objeto SurfaceView es SurfaceView.
tema
Un tema es un conjunto de propiedades, como el tamaño del texto y el color de fondo, que se agrupan para definir varios parámetros de configuración de visualización predeterminados. Android proporciona algunos temas estándar, que se enumeran en R.style y comienzan con Theme_.
vista (término genérico), View (elemento de la API)
Una vista dibuja un área rectangular en la pantalla y controla los clics, las combinaciones de teclas y otros eventos de interacción. La clase View es la clase base para la mayoría de los componentes de diseño de una pantalla de actividad o diálogo, como cuadros de texto y ventanas. Un objeto View recibe llamadas de su objeto principal (consulta ViewGroup) para dibujarse y le informa a su objeto principal sobre su tamaño y ubicación preferidos, que el objeto principal podría no respetar. Para obtener más información, consulta View.
grupo de vistas (término genérico), ViewGroup (elemento de la API)
Un grupo de vistas agrupa un conjunto de vistas secundarias. El grupo de vistas es responsable de decidir dónde se ubican las vistas secundarias y qué tan grandes pueden ser, así como de llamar a cada una para que se genere cuando sea apropiado. Algunos grupos de vistas son invisibles y son solo para diseño, mientras que otros tienen una IU intrínseca, como un cuadro de lista de desplazamiento. Los grupos de vistas se encuentran en el paquete android.widget, pero extienden la clase ViewGroup.
jerarquía de vistas
Una jerarquía de vistas es una disposición de objetos de vista y de grupo de vistas que define la interfaz del usuario para cada componente de una app. La jerarquía consiste en grupos de vistas que contienen una o más vistas secundarias o grupos de vistas. Puedes obtener una representación visual de una jerarquía de vistas para la depuración y optimización con el Visor de jerarquías que se proporciona con el SDK de Android.
Vulkan
Vulkan es una API multiplataforma de baja sobrecarga para gráficos 3D de alto rendimiento.
widget
Un widget es una de las subclases de vista completamente implementadas que renderizan elementos de formulario y otros componentes de la IU, como un cuadro de texto o un menú emergente. Dado que un widget se implementa por completo, controla la medición, la generación y la respuesta a los eventos de la pantalla. Los widgets se encuentran en el paquete android.widget.
ventana (término genérico), Window (elemento de la API)
En una app para Android, una ventana es un objeto derivado de la clase abstracta Window que especifica los elementos de una ventana genérica, como el aspecto, el texto de la barra de título y la ubicación y el contenido de los menús. Los diálogos y las actividades usan una implementación de la clase Window para renderizar un objeto Window. No necesitas implementar la clase Window ni usar ventanas en tu app.

Los desarrolladores de apps dibujan imágenes en la pantalla de tres maneras: con Canvas, OpenGL ES o Vulkan.

Componentes gráficos de Android

Sin importar qué API de renderización usen los desarrolladores, todo se renderiza en una superficie. La superficie representa el lado del productor de una fila de búferes que SurfaceFlinger suele consumir. Cada ventana que se crea en la plataforma de Android está respaldada por una superficie. SurfaceFlinger compone todas las superficies visibles renderizadas en la pantalla.

En el siguiente diagrama, se muestra cómo funcionan juntos los componentes clave:

Componentes de renderización de imágenes

Figura 1: Cómo se renderizan las superficies

Los componentes principales se describen en las siguientes secciones.

Productores de transmisiones de imágenes

Un productor de transmisiones de imágenes puede ser cualquier elemento que produzca búferes gráficos para el consumo. Entre los ejemplos, se incluyen OpenGL ES, Canvas 2D y los decodificadores de video de mediaserver.

Consumidores de transmisiones de imágenes

El consumidor más común de transmisiones de imágenes es SurfaceFlinger, el servicio del sistema que consume las superficies visibles actualmente y las compone en la pantalla con la información que proporciona el Administrador de ventanas. SurfaceFlinger es el único servicio que puede modificar el contenido de la pantalla. SurfaceFlinger usa OpenGL y Hardware Composer (HWC) para componer un grupo de superficies.

Otras apps de OpenGL ES también pueden consumir transmisiones de imágenes, como la app de cámara que consume una transmisión de imágenes de vista previa de la cámara. Las apps que no son de GL también pueden ser consumidores, por ejemplo, la clase ImageReader.

Hardware Composer

Es la abstracción de hardware para el subsistema de visualización. SurfaceFlinger puede delegar cierto trabajo de composición en el HWC para descargar trabajo de OpenGL y la GPU. SurfaceFlinger actúa como un cliente más de OpenGL ES. Por lo tanto, cuando SurfaceFlinger compone de forma activa uno o dos búferes en un tercero, por ejemplo, usa OpenGL ES. Esto hace que la composición consuma menos energía que si la GPU realizara todos los cálculos.

El HAL de Hardware Composer realiza la otra mitad del trabajo y es el punto central de toda la renderización de gráficos de Android. El HWC debe admitir eventos, uno de los cuales es VSync (otro es la conexión en caliente para la compatibilidad con HDMI plug-and-play).

Gralloc

El asignador de memoria de gráficos (Gralloc) es necesario para asignar la memoria que solicitan los productores de imágenes. Para obtener más información, consulta BufferQueue y Gralloc.

Flujo de datos

En el siguiente diagrama, se muestra la canalización de gráficos de Android:

flujo de datos de gráficos

Figura 2: Flujo de datos gráficos a través de Android.

Los objetos de la izquierda son renderizadores que producen búferes gráficos, como la pantalla principal, la barra de estado y la IU del sistema. SurfaceFlinger es el compositor y HWC es el compositor.

BufferQueue

Las BufferQueues proporcionan la unión entre los componentes gráficos de Android. Se trata de un par de colas que median el ciclo constante de búferes del productor al consumidor. Después de que los productores entregan sus búferes, SurfaceFlinger se encarga de componer todo en la pantalla.

En el siguiente diagrama, se ilustra el proceso de comunicación de BufferQueue:

Proceso de comunicación de BufferQueue

Figura 3: Proceso de comunicación de BufferQueue.

BufferQueue contiene la lógica que une a los productores y consumidores de transmisiones de imágenes. Algunos ejemplos de productores de imágenes son las vistas previas de la cámara que produce el HAL de la cámara o los juegos de OpenGL ES. Algunos ejemplos de consumidores de imágenes son SurfaceFlinger o cualquier otra app que muestre una transmisión de OpenGL ES, como la app de la cámara que muestra el visor de la cámara.

BufferQueue es una estructura de datos que combina un grupo de búferes con una cola y usa la comunicación entre procesos (IPC) de Binder para pasar búferes entre procesos. La interfaz del productor, o lo que le pasas a alguien que quiere generar búferes gráficos, es IGraphicBufferProducer (parte de SurfaceTexture). BufferQueue se suele usar para renderizar en una Surface y consumir con un GL Consumer, entre otras tareas.

BufferQueue puede operar en tres modos diferentes:

Modo similar al síncrono
De forma predeterminada, BufferQueue opera en un modo similar al síncrono, en el que cada búfer que ingresa del productor sale en el consumidor. En este modo, nunca se descarta ningún búfer. Y si el productor es demasiado rápido y crea búferes más rápido de lo que se vacían, se bloquea y espera a que haya búferes libres.
modo sin bloqueo
BufferQueue también puede operar en un modo no bloqueante en el que genera un error en lugar de esperar un búfer en esos casos. En este modo, tampoco se descarta ningún búfer. Esto es útil para evitar posibles bloqueos en el software de la aplicación que tal vez no comprenda las complejas dependencias del framework de gráficos.
Modo de descarte
BufferQueue se puede configurar para descartar búferes antiguos en lugar de generar errores o esperar. Por ejemplo, si se realiza la renderización de GL en una vista de textura y se dibuja lo más rápido posible, se deben descartar los búferes.

Para realizar la mayor parte de este trabajo, SurfaceFlinger actúa como otro cliente de OpenGL ES. Por lo tanto, cuando SurfaceFlinger compone de forma activa uno o dos búferes en un tercero, por ejemplo, usa OpenGL ES.

La HAL de Hardware Composer realiza la otra mitad del trabajo. Este HAL actúa como el punto central para toda la renderización de gráficos de Android.