Surface e SurfaceHolder

Os objetos de superfície permitem que os apps renderizem imagens para serem apresentadas nas telas. As interfaces SurfaceHolder permitem que os apps editem e controlem superfícies.

Superfície

Uma superfície é uma interface para que um produtor troque buffers com um consumidor.

O BufferQueue para uma superfície de exibição geralmente é configurado para bufferização tripla. Os buffers são alocados sob demanda. Portanto, se o produtor gerar buffers lentamente, por exemplo, a 30 qps em uma tela de 60 qps, pode haver apenas dois buffers alocados na fila. A alocação de buffers sob demanda ajuda a minimizar o consumo de memória. É possível conferir um resumo dos buffers associados a cada camada na saída dumpsys SurfaceFlinger.

A maioria dos clientes renderiza em superfícies usando OpenGL ES ou Vulkan. No entanto, alguns clientes renderizam em superfícies usando uma tela.

Renderização de tela

A implementação da tela é fornecida pela Skia Graphics Library. Se você quiser desenhar um retângulo, chame a API Canvas, que define bytes em um buffer de maneira adequada. Para garantir que um buffer não seja atualizado por dois clientes ao mesmo tempo ou gravado enquanto é exibido, bloqueie o buffer para acessá-lo. Use os comandos abaixo para trabalhar com as travas de tela:

  • lockCanvas() bloqueia o buffer para renderização na CPU e retorna uma tela para usar na renderização.
  • unlockCanvasAndPost() desbloqueia o buffer e envia para o compositor.
  • lockHardwareCanvas() bloqueia o buffer para renderização na GPU e retorna uma tela para usar na renderização.

Na primeira vez que o produtor solicita um buffer de uma BufferQueue, o buffer é alocado e inicializado como zero. A inicialização é necessária para evitar o compartilhamento acidental de dados entre processos. No entanto, se você reutilizar um buffer, o conteúdo anterior ainda estará presente. Se você chamar lockCanvas() e unlockCanvasAndPost() repetidamente sem renderizar nada, o produtor vai alternar entre os frames renderizados anteriormente.

O código de bloqueio/desbloqueio da superfície mantém uma referência ao buffer renderizado anteriormente. Se você especificar uma região suja ao travar a superfície, ela vai copiar os pixels não sujos do buffer anterior. O SurfaceFlinger ou o HWC normalmente processam o buffer. No entanto, como só precisamos ler o buffer, não é necessário esperar pelo acesso exclusivo.

SurfaceHolder

Um SurfaceHolder é uma interface que o sistema usa para compartilhar a propriedade de superfícies com apps. Alguns clientes que trabalham com superfícies querem um SurfaceHolder, porque as APIs para receber e definir parâmetros de superfície são implementadas por um SurfaceHolder. Uma SurfaceView contém um SurfaceHolder.

A maioria dos componentes que interagem com uma visualização envolve um SurfaceHolder. Algumas outras APIs, como a MediaCodec, operam na própria superfície.