Los objetos de superficie permiten que las aplicaciones representen imágenes para presentarlas en las pantallas. Las interfaces SurfaceHolder permiten que las aplicaciones editen y controlen superficies.
Superficie
Una superficie es una interfaz para que un productor intercambie buffers con un consumidor.
El BufferQueue para una superficie de visualización generalmente está configurado para almacenamiento en búfer triple. Los búferes se asignan según demanda, por lo que si el productor genera búferes lo suficientemente lento, como a 30 fps en una pantalla de 60 fps, es posible que solo haya dos búferes asignados en la cola. La asignación de búferes según demanda ayuda a minimizar el consumo de memoria. Puede ver un resumen de los buffers asociados con cada capa en la salida dumpsys SurfaceFlinger
.
La mayoría de los clientes renderizan en superficies usando OpenGL ES o Vulkan . Sin embargo, algunos clientes renderizan sobre superficies utilizando un lienzo.
Representación de lienzo
La implementación del lienzo la proporciona Skia Graphics Library . Si desea dibujar un rectángulo, llame a la API de Canvas, que establece bytes en un búfer de manera adecuada. Para asegurarse de que dos clientes no actualicen un búfer a la vez o no escriban en él mientras se muestra, bloquee el búfer para acceder a él. Utilice los siguientes comandos para trabajar con bloqueos de lienzo:
-
lockCanvas()
bloquea el búfer para renderizar en la CPU y devuelve un lienzo para usar en el dibujo. -
unlockCanvasAndPost()
desbloquea el búfer y lo envía al compositor. -
lockHardwareCanvas()
bloquea el búfer para renderizar en la GPU y devuelve un lienzo para usar en el dibujo.
La primera vez que el productor solicita un búfer de BufferQueue, el búfer se asigna y se inicializa a cero. La inicialización es necesaria para evitar compartir datos entre procesos sin darse cuenta. Sin embargo, si reutiliza un búfer, el contenido anterior todavía está presente. Si llamas repetidamente lockCanvas()
y unlockCanvasAndPost()
sin dibujar nada, el productor alterna entre fotogramas renderizados previamente.
El código de bloqueo/desbloqueo de superficie mantiene una referencia al búfer renderizado previamente. Si especifica una región sucia al bloquear la superficie, copia los píxeles no sucios del búfer anterior. SurfaceFlinger o HWC normalmente manejan el búfer; pero como sólo necesitamos leer del búfer, no hay necesidad de esperar por el acceso exclusivo.
Soporte de superficie
Un SurfaceHolder es una interfaz que el sistema utiliza para compartir la propiedad de superficies con aplicaciones. Algunos clientes que trabajan con superficies quieren un SurfaceHolder, porque las API para obtener y establecer parámetros de superficie se implementan a través de un SurfaceHolder. Un SurfaceView contiene un SurfaceHolder.
La mayoría de los componentes que interactúan con una vista implican un SurfaceHolder. Algunas otras API, como MediaCodec, operan en la propia superficie.