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.