Surface y SurfaceHolder

Los objetos Surface permiten que las apps rendericen imágenes para presentarlas en pantallas. Las interfaces de SurfaceHolder permiten que las apps editen y controlen superficies.

Superficie

Una superficie es una interfaz para que un productor intercambie búferes con un consumidor.

Por lo general, las superficies de visualización usan BufferQueues configuradas para el triple almacenamiento en búfer. Los búferes se asignan a pedido, por lo que, si el productor genera búferes con la suficiente lentitud, 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 a pedido ayuda a minimizar el consumo de memoria. Puedes ver un resumen de los búferes asociados con cada capa en el resultado de dumpsys SurfaceFlinger.

La mayoría de los clientes renderizan en superficies con OpenGL ES o Vulkan. Sin embargo, algunos clientes renderizan en superficies con un lienzo.

Renderización del lienzo

La biblioteca de gráficos de Skia proporciona la implementación del lienzo. Si quieres dibujar un rectángulo, llamas a la API de Canvas, que establece los bytes en un búfer de forma adecuada. Para garantizar que dos clientes no actualicen un búfer al mismo tiempo ni se escriba en él mientras se muestra, bloquea el búfer para acceder a él. Usa los siguientes comandos para trabajar con los bloqueos de lona:

  • lockCanvas() bloquea el búfer para la renderización en la CPU y devuelve un Canvas para usarlo en el dibujo.
  • unlockCanvasAndPost() desbloquea el búfer y lo envía al compositor.
  • lockHardwareCanvas() bloquea el búfer para el procesamiento en la GPU y devuelve un lienzo para dibujar.

La primera vez que el productor solicita un búfer de un BufferQueue, el búfer se asigna y se inicializa en cero. La inicialización es necesaria para evitar compartir datos entre procesos de forma inadvertida. Sin embargo, si reutilizas un búfer, el contenido anterior seguirá presente. Si llamas a lockCanvas() y unlockCanvasAndPost() repetidamente sin dibujar nada, el productor alterna entre los fotogramas renderizados anteriormente.

El código de bloqueo o desbloqueo de la superficie mantiene una referencia al búfer renderizado anteriormente. Si especificas una región sucia cuando bloqueas la superficie, se copian los píxeles no sucios del búfer anterior. Por lo general, SurfaceFlinger o HWC controlan el búfer, pero, como solo necesitas leerlo, no es necesario esperar el acceso exclusivo.

SurfaceHolder

Un SurfaceHolder es una interfaz que el sistema usa para compartir la propiedad de las superficies con las apps. Algunos clientes que trabajan con superficies quieren un SurfaceHolder, ya que las APIs 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 involucran un SurfaceHolder. Otras APIs, como MediaCodec, operan en la propia superficie.