Surface e SurfaceHolder

Gli oggetti Surface consentono alle app di eseguire il rendering delle immagini da presentare sugli schermi. Le interfacce SurfaceHolder consentono alle app di modificare e controllare le piattaforme.

Surface

Una surface è un'interfaccia che consente a un producer di scambiare buffer con un consumer.

La BufferQueue per una superficie di visualizzazione è in genere configurata per il buffering triplo. I buffer vengono allocati su richiesta, quindi se il produttore genera buffer abbastanza lentamente, ad esempio a 30 fps su un display a 60 fps, nella coda potrebbero essere allocati solo due buffer. L'allocazione dei buffer su richiesta consente di minimizzare il consumo di memoria. Puoi vedere un riepilogo dei buffer associati a ogni livello nell'output dumpsys SurfaceFlinger.

La maggior parte dei client esegue il rendering su superfici utilizzando OpenGL ES o Vulkan. Tuttavia, alcuni client eseguono il rendering su piattaforme utilizzando una tela.

Rendering della tela

L'implementazione della tela è fornita dalla Skia Graphics Library. Se vuoi disegnare un rettangolo, chiami l'API Canvas, che imposta i byte in un buffer in modo appropriato. Per assicurarti che un buffer non venga aggiornato da due client contemporaneamente o su cui non venga scritto durante la visualizzazione, bloccalo per accedervi. Utilizza i seguenti comandi per lavorare con le serrature della tela:

  • lockCanvas() blocca il buffer per il rendering sulla CPU e restituisce un Canvas da utilizzare per il disegno.
  • unlockCanvasAndPost() sblocca il buffer e lo invia al compositore.
  • lockHardwareCanvas() blocca il buffer per il rendering sulla GPU e restituisce un canvas da utilizzare per il disegno.

La prima volta che il produttore richiede un buffer da una BufferQueue, il buffer viene allocato e inizializzato a zero. L'inizializzazione è necessaria per evitare di condividere inavvertitamente i dati tra i processi. Tuttavia, se riutilizzi un buffer, i contenuti precedenti sono ancora presenti. Se chiami ripetutamente lockCanvas() e unlockCanvasAndPost() senza disegnare nulla, il produttore passa da un frame all'altro tra quelli precedentemente visualizzati.

Il codice di blocco/sblocco della superficie mantiene un riferimento al buffer visualizzato in precedenza. Se specifichi una regione non aggiornata quando blocchi la superficie, vengono copiati i pixel non aggiornati dal buffer precedente. In genere, SurfaceFlinger o HWC gestiscono il buffer, ma poiché dobbiamo solo leggere dal buffer, non è necessario attendere l'accesso esclusivo.

SurfaceHolder

Un SurfaceHolder è un'interfaccia utilizzata dal sistema per condividere la proprietà delle superfici con le app. Alcuni client che lavorano con le piattaforme richiedono un SurfaceHolder, poiché le API per ottenere e impostare i parametri delle piattaforme sono implementate tramite un SurfaceHolder. Un SurfaceView contiene un SurfaceHolder.

La maggior parte dei componenti che interagiscono con una visualizzazione coinvolge un SurfaceHolder. Alcune altre API, come MediaCodec, operano sulla stessa piattaforma.