Os objetos de superfície permitem que os apps renderizem imagens para serem apresentadas em telas. As interfaces SurfaceHolder permitem que os apps editem e controlem superfícies.
Superfície
Uma superfície é uma interface para um produtor trocar buffers com um consumidor.
As superfícies de exibição geralmente usam BufferQueues configurados para
buffer triplo. Os buffers são alocados sob demanda. Portanto, se o produtor gerar buffers lentamente, como a 30 fps em uma tela de 60 fps, 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 da tela
A Skia Graphics Library (link em inglês) fornece a implementação da tela. Se você quiser desenhar um retângulo, chame a API Canvas, que define bytes em um buffer adequadamente. Para garantir que um buffer não seja atualizado por dois clientes ao mesmo tempo ou gravado enquanto está sendo exibido, bloqueie o buffer para acessá-lo. Use os comandos a seguir para trabalhar com bloqueios de tela:
lockCanvas()
bloqueia o buffer para renderização na CPU e retorna uma tela para uso no desenho.unlockCanvasAndPost()
desbloqueia o buffer e o envia ao compositor.lockHardwareCanvas()
bloqueia o buffer para renderização na GPU e retorna uma tela para uso no desenho.
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 inadvertido 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 desenhar nada, o produtor vai alternar entre 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 bloquear a superfície, ela vai copiar os pixels não sujos do buffer anterior. O SurfaceFlinger ou o HWC geralmente processam o buffer, mas como você só precisa ler do buffer, não é necessário esperar o 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. Outras APIs, como MediaCodec, operam na própria superfície.