Gli oggetti di superficie consentono alle app di eseguire il rendering delle immagini da visualizzare sugli schermi. Le interfacce SurfaceHolder consentono alle app di modificare e controllare le superfici.
Surface
Una superficie è un'interfaccia che consente a un producer di scambiare buffer con un consumer.
Le superfici di visualizzazione in genere utilizzano BufferQueue configurate per
il triple buffering. 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, potrebbero essere allocati solo due buffer nella coda.
L'allocazione dei buffer on demand contribuisce a
ridurre al minimo il consumo di memoria. Puoi visualizzare un riepilogo dei buffer associati
a ogni livello nell'output dumpsys SurfaceFlinger
.
La maggior parte dei client esegue il rendering sulle superfici utilizzando OpenGL ES o Vulkan. Tuttavia, alcuni client eseguono il rendering sulle superfici utilizzando un canvas.
Rendering del canvas
La libreria grafica Skia fornisce l'implementazione del canvas. 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 che non venga scritto durante la visualizzazione, bloccalo per accedervi. Utilizza i seguenti comandi per lavorare con i blocchi del canvas:
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
la condivisione involontaria di dati tra processi. Tuttavia, se riutilizzi un buffer,
i contenuti precedenti sono ancora presenti. Se chiami ripetutamente
lockCanvas()
e unlockCanvasAndPost()
senza
disegnare nulla, il produttore scorre i frame sottoposti a rendering in precedenza.
Il codice di blocco/sblocco della superficie mantiene un riferimento al buffer precedentemente sottoposto a rendering. Se specifichi una regione modificata quando blocchi la superficie, copia i pixel non modificati dal buffer precedente. SurfaceFlinger o HWC in genere gestiscono il buffer, ma poiché devi 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 funzionano con le superfici vogliono un SurfaceHolder, perché le API per ottenere e impostare i parametri della superficie vengono implementate tramite un SurfaceHolder. Una SurfaceView contiene un SurfaceHolder.
La maggior parte dei componenti che interagiscono con una visualizzazione coinvolge un SurfaceHolder. Altre API, come MediaCodec, operano sulla superficie stessa.