Surface y SurfaceHolder

Los objetos de superficie permiten que las apps rendericen imágenes para que se presenten en pantallas. Las interfaces de SurfaceHolder permiten que las apps editen y controlen las plataformas.

Superficie

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

Por lo general, el BufferQueue para una superficie de visualización se configura para el triple 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 de lienzo

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

  • lockCanvas() bloquea el búfer para renderizar en la CPU y muestra 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 muestra un lienzo para usar en el dibujo.

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 accidental. Sin embargo, si reutilizas un búfer, el contenido anterior seguirá presente. Si llamas a lockCanvas() y unlockCanvasAndPost() de forma reiterada 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 no sincronizada cuando bloqueas la superficie, se copian los píxeles no sincronizados del búfer anterior. Por lo general, SurfaceFlinger o HWC controlan el búfer, pero como solo necesitamos leer desde el búfer, no es necesario esperar el acceso exclusivo.

SurfaceHolder

Un SurfaceHolder es una interfaz que el sistema usa para compartir la propiedad de las plataformas con las apps. Algunos clientes que trabajan con plataformas desean un SurfaceHolder, ya que las APIs para obtener y establecer parámetros de plataforma 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 incluyen un SurfaceHolder. Algunas otras APIs, como MediaCodec, operan en la propia superficie.