Implementar a HAL do Hardware Composer

As camadas compostas HAL do Hardware Composer (HWC) recebidas SurfaceFlinger, reduzindo a quantidade de composição OpenGL ES (GLES) e o desempenho da GPU.

O HWC abstrai objetos, como sobreposições e blitters 2D, para compor superfícies e se comunica com hardware de composição de janela especializado para janelas compostas. Use o HWC para compor janelas em vez de ter composição do SurfaceFlinger com a GPU. A maioria das GPUs não é otimizada composição e quando a GPU compõe camadas SurfaceFlinger, os apps não podem usar a GPU para a própria renderização.

As implementações de HWC precisam oferecer suporte a:

  • Pelo menos quatro sobreposições:
    • Barra de status
    • Barra do sistema
    • App
    • Plano de fundo/plano de fundo
  • Camadas maiores que a tela (por exemplo, um plano de fundo)
  • Mesclagem alfa pré-multiplicada simultânea por pixel e por plano mistura alfa
  • Caminho de hardware para reprodução de vídeo protegida
  • Ordem de empacotamento RGBA, formatos YUV, ladrilhos, swizzling e stride propriedades

Para implementar a HWC:

  1. Implementar uma HWC não operacional e enviar todo o trabalho de composição para GLES.
  2. Implementar um algoritmo para delegar a composição ao HWC gradualmente. Por exemplo, delegue apenas as três ou quatro primeiras superfícies à sobreposição hardware do HWC.
  3. Otimizar a HWC. Isso pode incluir:
    • Selecionar superfícies que maximizam a carga retirada da GPU ao HWC.
    • Detectando se a tela está sendo atualizada. Se não estiver, delegue para o GLES em vez da HWC para economizar energia. Quando a tela for atualizado novamente, continue a descarregar a composição no HWC.
    • Preparar-se para casos de uso comuns, como:
      • A tela inicial, que inclui a barra de status, a barra do sistema, o app janela e planos de fundo interativos,
      • Jogos em tela cheia nos modos retrato e paisagem
      • Vídeo em tela cheia com legendas e reprodução controle
      • Reprodução de vídeos protegida
      • Janela dividida em tela dividida
.

Primitivos de HWC

O HWC fornece dois primitivos, camadas e telas, para representam o trabalho de composição e a interação dele com o hardware de tela. O O HWC também oferece controle sobre VSYNC e um callback para o SurfaceFlinger para notificá-lo quando ocorrer um evento VSYNC.

Interface HIDL

O Android 8.0 e versões mais recentes usam interface HIDL chamada HAL do Composer para IPC vinculada entre o HWC e o SurfaceFlinger. A HAL do Composer substitui interface hwcomposer2.h legada. Se os fornecedores fornecerem uma HAL do Composer implementação do HWC, a HAL do Composer aceita diretamente chamadas HIDL do com o SurfaceFlinger. Se os fornecedores fornecerem uma implementação legada de HWC, o Composer A HAL carrega ponteiros de função de hwcomposer2.h. encaminhar chamadas HIDL para chamadas de ponteiro de função.

O HWC oferece funções para determinar as propriedades de uma determinada tela. para alternar entre diferentes configurações de tela (como 4K ou 1080p resolução) e modos de cor (como cor nativa ou sRGB verdadeiro); e transformar a tela ligada, desligada ou em um modo de baixo consumo de energia, se compatível.

Ponteiros de função

Se os fornecedores implementarem a HAL do Composer diretamente, o SurfaceFlinger chamará as funções dele. por meio do HIDL IPC. Por exemplo, para criar uma camada, o SurfaceFlinger chama createLayer() no HAL do Composer.

Se os fornecedores implementarem a interface hwcomposer2.h, a HAL do Composer chamadas em ponteiros de função hwcomposer2.h. Em hwcomposer2.h comentários, As funções de interface HWC são referenciados por nomes bottomCamelCase que não existem na interface como campos nomeados. Quase todas as funções são carregadas ao solicitar um ponteiro de função usando o getFunction fornecido pelo hwc2_device_t. Por exemplo, a função createLayer é um ponteiro de função do tipo HWC2_PFN_CREATE_LAYER, que é retornado quando o valor enumerado HWC2_FUNCTION_CREATE_LAYER é transmitido para getFunction.

Para consultar a documentação detalhada sobre as funções HAL do Composer e passagem de funções HWC funções, consulte composer. Para acessar a documentação detalhada ponteiros da função HWC, consulte a hwcomposer2.h

Alças de camada e exibição

As camadas e telas são manipuladas por alças geradas pelo HWC. As alças são opacas para o SurfaceFlinger.

Quando o SurfaceFlinger cria uma nova camada, ele chama createLayer, que retorna do tipo Layer para ou hwc2_layer_t para implementações de passagem. Quando O SurfaceFlinger modifica uma propriedade dessa camada, e o SurfaceFlinger passa o valor hwc2_layer_t na função de modificação adequada além de outras informações necessárias para fazer a modificação. O O tipo hwc2_layer_t é grande o suficiente para conter um ponteiro ou um índice.

Telas físicas são criadas com a conexão por hotplug. Quando uma tela física é conectado, o HWC cria um identificador e o transmite para o SurfaceFlinger pelo callback do hotplug. Telas virtuais criadas pelo SurfaceFlinger chamando createVirtualDisplay() para solicitar uma exibição. Se o dispositivo HWC oferece suporte à composição de exibição virtual, ele retorna um identificador. Em seguida, o SurfaceFlinger delega a composição das telas para o HWC. Se a HWC não oferecer suporte a composição de exibição, o SurfaceFlinger cria o identificador e compõe a tela.

Mostrar operações de composição

Uma vez por VSYNC, o SurfaceFlinger é ativado se tiver um novo conteúdo para compor. Esse novo conteúdo pode ser novos buffers de imagem de apps ou uma mudança nas propriedades de uma ou mais camadas. Quando o SurfaceFlinger acorda:

  1. Processa transações, se houver.
  2. Trava novos buffers gráficos, se presentes.
  3. Executa uma nova composição se a etapa 1 ou 2 resultar em uma mudança ao conteúdo de exibição.

Para realizar uma nova composição, o SurfaceFlinger cria e destrói camadas ou modifica os estados das camadas, conforme aplicável. Ele também atualiza camadas com seus conteúdos atuais, usando chamadas como setLayerBuffer ou setLayerColor. Depois que todas as camadas são atualizadas, o SurfaceFlinger chama validateDisplay, que instrui o HWC a examinar o estado das camadas e determinar como a composição vai prosseguir. Por padrão, o SurfaceFlinger tenta configurar todas as camadas. de forma que a camada seja composta pelo HWC; embora, em alguns circunstâncias, o SurfaceFlinger compõe camadas usando o substituto da GPU.

Após a chamada para validateDisplay, o SurfaceFlinger chama getChangedCompositionTypes para ver se o hardware quiser que qualquer um dos tipos de composição da camada seja alterado antes de realizar a composição. Para aceitar as mudanças, o SurfaceFlinger chama acceptDisplayChanges:

Se alguma camada estiver marcada para a composição do SurfaceFlinger, o SurfaceFlinger e os compõe no buffer de destino. O SurfaceFlinger chama setClientTarget para fornecer o buffer à tela, para que o buffer possa ser mostrado na tela ou composto com camadas que não foram marcadas para a composição do SurfaceFlinger. Se nenhuma camada estiver marcada para Composição do SurfaceFlinger, o SurfaceFlinger ignora a etapa de composição.

Por fim, o SurfaceFlinger chama presentDisplay para informar ao HWC que ele precisa concluir o processo de composição e mostrar o resultado final.

Várias telas

O Android 10 oferece suporte a várias telas físicas. Ao projetar uma implementação de HWC destinada ao uso no Android 7.0 e versões mais recentes, há algumas restrições que não estão presentes na definição de HWC:

  • Suponha que haja exatamente uma tela interna. Os dados tela é aquela que o hotplug inicial informa durante inicialização. Depois que a tela interna é conectada, não é possível ser desconectados.
  • Além da tela interna, qualquer número de monitores externos pode estar conectado por hotplug durante a operação normal do dispositivo. O framework presume que todos os hotplugs após a primeira tela interna são telas externas, portanto, se houver mais telas internas forem adicionadas, elas serão categorizadas incorretamente como Display.TYPE_HDMI em vez de Display.TYPE_BUILT_IN.

Enquanto as operações do SurfaceFlinger descritas acima são realizadas por tela, elas são realizadas sequencialmente para todas as telas ativas, mesmo que o conteúdo de apenas uma tela seja atualizado.

Por exemplo, se o monitor externo for atualizado, a sequência será:

// In Android 9 and lower:

// Update state for internal display
// Update state for external display
validateDisplay(<internal display>)
validateDisplay(<external display>)
presentDisplay(<internal display>)
presentDisplay(<external display>)

// In Android 10 and higher:

// Update state for internal display
// Update state for external display
validateInternal(<internal display>)
presentInternal(<internal display>)
validateExternal(<external display>)
presentExternal(<external display>)

Composição de tela virtual

A composição da tela virtual é semelhante à da tela externa composição. A diferença entre a composição da tela virtual e as formas físicas composição da exibição é que as telas virtuais enviam saídas para um buffer Gralloc, e não na tela. O Hardware Composer (HWC) grava a saída em um buffer, fornece o limite de conclusão e envia o buffer para um consumidor (como o codificador de vídeo, GPU, CPU e assim por diante). Telas virtuais podem usar 2D/blitter ou se o pipeline de exibição fizer gravações na memória.

Modos

Cada frame está em um dos três modos depois que o SurfaceFlinger chama o método HWC validateDisplay():

  • GLES: a GPU compõe todas as camadas, gravando diretamente no buffer de saída. A HWC não está envolvida na composição.
  • MIXED: a GPU compõe algumas camadas no framebuffer, e o HWC compõe o framebuffer e as camadas restantes, gravando diretamente no buffer de saída.
  • HWC: HWC compõe todas as camadas e grava diretamente ao buffer de saída.

Formato de saída

Os formatos de saída do buffer de exibição virtual dependem do modo:

  • Modo GLES: o driver EGL define o buffer de saída. em dequeueBuffer(), normalmente RGBA_8888. O consumidor precisa ser capaz de aceitar o formato de saída definido pelo driver ou a e o buffer não pode ser lido.
  • Modos MIXED e HWC: se o consumidor precisar de CPU acesso, o consumidor define o formato. Caso contrário, o formato será IMPLEMENTATION_DEFINED, e o Gralloc define o melhor formato com base as flags de uso. Por exemplo, Gralloc define um formato YCbCr se o consumidor o codificador de vídeo e o HWC possam gravar o formato de forma eficiente.
.

Limites de sincronização

As cercas de sincronização (sync) são um aspecto crucial do sistema gráfico do Android. Os limites permitem que o trabalho da CPU ocorra de maneira independente do trabalho simultâneo da GPU. o bloqueio de dados somente quando há uma dependência verdadeira.

Por exemplo, quando um app envia um buffer que está sendo produzido em a GPU também envia um objeto de limite de sincronização. Essa cerca sinaliza quando A GPU terminou de gravar no buffer.

O HWC exige que a GPU termine de gravar buffers antes que os buffers sejam exibidos. As cercas de sincronização são transmitidas pelo pipeline gráfico com buffers e sinalizam quando os buffers são gravados. Antes que um buffer seja mostrado, o HWC verifica se a cerca de sincronização sinalizou e, se sim, exibe o buffer.

Para mais informações sobre limites de sincronização, consulte Hardware Composer Integração.