Las capas y las pantallas son dos elementos 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 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 que se muestra 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 rotado 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 de 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 múltiples pantallas y las pantallas se pueden agregar o quitar durante las operaciones normales del sistema. Las pantallas se agregan/eliminan a pedido del HWC o a pedido 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 una pantalla física.
pantallas virtuales
SurfaceFlinger admite una pantalla interna (integrada en el teléfono o la 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 usar para grabar la pantalla o enviar la pantalla a través de una red. Los marcos 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 combinar con OpenGL ES (GLES), HWC o tanto GLES como HWC. En implementaciones no compatibles, las pantallas virtuales siempre se componen mediante GLES.
Estudio de caso: registro de pantalla
El comando screenrecord
le 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 video son administrados por un proceso separado ( mediaserver
), por lo que los búferes de gráficos grandes 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 hacer 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 de regreso a screenrecord
como una superficie.
Luego, la utilidad screenrecord
le pide a SurfaceFlinger que cree una pantalla virtual que refleje la pantalla principal (es decir, tiene todas las mismas capas) y la dirige para enviar la salida a la superficie que proviene del proceso mediaserver
. En este caso, SurfaceFlinger es el productor de búfer en lugar del consumidor.
Una vez completada la configuración, screenrecord
se activa cuando aparecen los datos codificados. A medida que las aplicaciones dibujan, sus búferes viajan a SurfaceFlinger, que los compone en un solo búfer que se envía directamente al codificador de video en el proceso mediaserver
. El proceso screenrecord
nunca ve los fotogramas completos. Internamente, el proceso mediaserver
tiene su propia forma de mover los búferes que también pasa los datos por identificador, lo que minimiza 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 aparece la pantalla compuesta 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 pantallas secundarias en acción, use screenrecord
para capturar el acto de habilitar la pantalla y luego reprodúzcala cuadro por cuadro.