Os objetos de superfície permitem que os aplicativos renderizem imagens a serem apresentadas nas telas. As interfaces SurfaceHolder permitem que os aplicativos editem e controlem superfícies.
Superfície
Uma superfície é uma interface para um produtor trocar buffers com um consumidor.
O BufferQueue para uma superfície de exibição é normalmente configurado para armazenamento em buffer triplo. Os buffers são alocados sob demanda, portanto, se o produtor gerar buffers devagar o suficiente, 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. Você pode ver um resumo dos buffers associados a cada camada na saída do 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 do canvas é fornecida pela Skia Graphics Library . Se você quiser desenhar um retângulo, chame a API do Canvas, que define os bytes em um buffer adequadamente. Para garantir que um buffer não seja atualizado por dois clientes ao mesmo tempo ou gravado enquanto estiver sendo exibido, bloqueie o buffer para acessá-lo. Use os seguintes comandos para trabalhar com bloqueios de tela:
-
lockCanvas()
bloqueia o buffer para renderização na CPU e retorna um Canvas a ser usado para desenho. -
unlockCanvasAndPost()
desbloqueia o buffer e o envia ao compositor. -
lockHardwareCanvas()
bloqueia o buffer para renderização na GPU e retorna uma tela a ser usada para desenho.
Na primeira vez que o produtor solicita um buffer de um BufferQueue, o buffer é alocado e inicializado em 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 repetidamente lockCanvas()
e unlockCanvasAndPost()
sem desenhar nada, o produtor alternará entre os quadros renderizados anteriormente.
O código de bloqueio/desbloqueio de superfície mantém uma referência ao buffer renderizado anteriormente. Se você especificar uma região suja ao bloquear a superfície, ela copiará os pixels não sujos do buffer anterior. SurfaceFlinger ou HWC normalmente manipulam o buffer; mas como só precisamos ler do buffer, não há necessidade de esperar pelo acesso exclusivo.
Suporte de Superfície
Um SurfaceHolder é uma interface que o sistema usa para compartilhar a propriedade de superfícies com aplicativos. Alguns clientes que trabalham com superfícies desejam um SurfaceHolder, porque as APIs para obter e definir parâmetros de superfície são implementadas por meio de um SurfaceHolder. Um SurfaceView contém um SurfaceHolder.
A maioria dos componentes que interagem com uma exibição envolve um SurfaceHolder. Algumas outras APIs, como MediaCodec, operam na própria superfície.