Las capas y las pantallas son dos primitivos que representan el trabajo de composición y las interacciones con el hardware de la pantalla.
Capas
Una capa es la unidad de composición más importante. Una capa es una combinación de una superficie y una instancia de SurfaceControl
. Cada capa tiene un conjunto de propiedades que definen cómo interactúa con otras capas. Las propiedades de la capa se describen en la siguiente tabla.
Propiedad | Descripción |
---|---|
posicional | Define dónde aparece la capa en su visualización. Incluye información como las posiciones de los bordes de una capa y su orden Z en relación con otras capas (si debe estar delante o detrás de otras capas). |
Contenido | Define cómo se debe presentar el contenido mostrado en la capa dentro de los límites definidos por las propiedades posicionales. Incluye información como recortar (para expandir una parte del contenido para llenar los límites de la capa) y transformar (para mostrar contenido girado o invertido). |
Composición | Define cómo se debe componer la capa con otras capas. Incluye información como el modo de fusión y un valor alfa para toda la capa para la composición alfa . |
Mejoramiento | Proporciona información que no es estrictamente necesaria para componer correctamente la capa, pero que puede ser utilizada por el dispositivo Hardware Composer (HWC) para optimizar la forma en que realiza la composición. Incluye información como la región visible de la capa y qué parte de la capa se ha actualizado desde el fotograma anterior. |
Pantallas
Una pantalla es otra unidad importante de composición. Un sistema puede tener varias pantallas y se pueden agregar o quitar pantallas durante las operaciones normales del sistema. Las pantallas se agregan/eliminan a solicitud del HWC o a solicitud del marco. El dispositivo HWC solicita que se agreguen o eliminen pantallas cuando se conecta o desconecta una pantalla externa del dispositivo, lo que se denomina conexión en caliente . Los clientes solicitan pantallas virtuales , cuyos contenidos se representan en un búfer fuera de la pantalla en lugar de en una pantalla física.
Pantallas virtuales
SurfaceFlinger admite una pantalla interna (integrada en el teléfono o tableta), pantallas externas (como un televisor conectado a través de HDMI) y una o más pantallas virtuales que hacen que la salida compuesta esté disponible dentro del sistema. Las pantallas virtuales se pueden utilizar para grabar la pantalla o enviarla a través de una red. Los fotogramas generados para una pantalla virtual se escriben en un BufferQueue.
Las pantallas virtuales pueden compartir el mismo conjunto de capas que la pantalla principal (la pila de capas) o tener su propio conjunto. No hay VSYNC para una pantalla virtual, por lo que VSYNC para la pantalla interna activa la composición para todas las pantallas.
En las implementaciones de HWC que las admiten, las pantallas virtuales se pueden componer con OpenGL ES (GLES), HWC o tanto GLES como HWC. En implementaciones que no son compatibles, las pantallas virtuales siempre se componen utilizando GLES.
Estudio de caso: registro de pantalla
El comando screenrecord
permite al usuario grabar todo lo que aparece en la pantalla como un archivo .mp4
en el disco. Para implementar esto, el sistema recibe cuadros compuestos de SurfaceFlinger, los escribe en el codificador de video y luego escribe los datos de video codificados en un archivo. Los códecs de vídeo se gestionan mediante un proceso independiente ( mediaserver
), por lo que grandes buffers de gráficos tienen que moverse por el sistema. Para hacerlo más desafiante, el objetivo es grabar video de 60 fps a máxima resolución. La clave para que esto funcione de manera eficiente es BufferQueue.
La clase MediaCodec
permite que una aplicación proporcione datos como bytes sin procesar en búferes o a través de una superficie. Cuando screenrecord
solicita acceso a un codificador de video, el proceso mediaserver
crea un BufferQueue, se conecta al lado del consumidor y luego pasa el lado del productor a screenrecord
como superficie.
Luego, la utilidad screenrecord
le pide a SurfaceFlinger que cree una pantalla virtual que refleje la pantalla principal (es decir, que tenga todas las mismas capas) y le indique que envíe la salida a la superficie que proviene del proceso mediaserver
. En este caso, SurfaceFlinger es el productor de buffers y no el consumidor.
Una vez completada la configuración, screenrecord
se activa cuando aparecen los datos codificados. A medida que las aplicaciones dibujan, sus buffers viajan a SurfaceFlinger, que los compone en un único buffer que se envía directamente al codificador de video en el proceso mediaserver
. Los fotogramas completos nunca se ven en el proceso screenrecord
. Internamente, el proceso mediaserver
tiene su propia forma de mover los buffers y también pasa datos por identificador, minimizando la sobrecarga.
Estudio de caso: simular pantallas secundarias
WindowManager puede pedirle a SurfaceFlinger que cree una capa visible para la cual SurfaceFlinger actúa como consumidor de BufferQueue. También es posible pedirle a SurfaceFlinger que cree una pantalla virtual, para la cual SurfaceFlinger actúa como productor de BufferQueue.
Si conecta una pantalla virtual a una capa visible, se crea un bucle cerrado donde la pantalla compuesta aparece en una ventana. Esa ventana ahora es parte de la salida compuesta, por lo que en la siguiente actualización la imagen compuesta dentro de la ventana también muestra el contenido de la ventana. Para ver esto en acción, habilite las opciones de desarrollador en Configuración , seleccione Simular pantallas secundarias y habilite una ventana. Para ver las pantallas secundarias en acción, use screenrecord
para capturar el acto de habilitar la pantalla y luego reprodúzcalo cuadro por cuadro.