Livelli e visualizzazioni sono due elementi primitivi che rappresentano la composizione e interazioni con l'hardware del display.
Livelli
Un livello è l'unità più importante della composizione. Un livello è una combinazione di una superficie e un'istanza di SurfaceControl
. Ogni livello ha un insieme di proprietà
definiscono le modalità di interazione con gli altri strati. Le proprietà dei livelli sono descritte nella tabella di seguito.
Proprietà | Descrizione |
---|---|
Di posizione | Definisce dove viene visualizzato il livello. Include informazioni come le posizioni dei bordi di un livello e il relativo ordine Z rispetto ad altri livelli (se deve essere davanti o dietro altri livelli). |
Contenuti | Definisce come devono essere presentati i contenuti visualizzati sul livello all'interno dei limiti definiti dalle proprietà di posizione. Sono incluse informazioni come il ritaglio (per espandere una parte dei contenuti in modo da riempire i limiti del livello) e la trasformazione (per mostrare contenuti ruotati o capovolti). |
Composizione | Definisce in che modo il livello deve essere composto con altri livelli. Sono incluse informazioni come la modalità di miscelazione e un valore alfa a livello di livello per il compositing alpha. |
Ottimizzazione | Fornisce informazioni non strettamente necessarie per comporre correttamente il livello, ma che può essere utilizzato dal dispositivo HWC (Hardware Composer) per ottimizzare il rendimento della composizione. Include informazioni come regione visibile del livello e quale parte è stata aggiornato dal frame precedente. |
Display
Un'altra unità di composizione importante è la visualizzazione. Un sistema può avere più display è possibile aggiungere o rimuovere display durante le normali operazioni di sistema. I display vengono aggiunti/rimossi su richiesta dell'HWC o del framework. Il dispositivo HWC richiede che i display vengano aggiunti o rimossi quando un display esterno viene connesso o disconnesso dal dispositivo, ovvero il hotplugging. I client richiedono display virtuali, i cui contenuti vengono sottoposti a rendering in un buffer fuori schermo invece che su un display fisico.
Display virtuali
Flinger di superficie supporta un display interno (integrato nello smartphone o il tablet), display esterni (ad esempio un televisore collegato tramite HDMI) e uno o più display virtuali che rendono disponibile l'output composito all'interno del sistema. I display virtuali possono essere utilizzati per registrare lo schermo o inviarlo su una rete. I frame generati per un display virtuale vengono scritti in una BufferQueue.
I display virtuali possono condividere lo stesso insieme di livelli del display principale (la serie di livelli) o avere un proprio insieme. Non esiste VSYNC per un display virtuale, quindi VSYNC per il display interno attiva la composizione per tutti i display.
Sulle implementazioni HWC che le supportano, i display possono essere combinati con OpenGL ES (GLES), HWC o con entrambi i sistemi GLES e HWC. Nelle implementazioni non supportate, i display virtuali vengono sempre compositi utilizzando o
Case study: record dello schermo
Il comando screenrecord
consente all'utente di registrare tutto ciò che viene visualizzato sullo schermo come file .mp4
sul disco. Per implementarlo, il sistema riceve frame compositi
SurfaceFlinger, li scrive nel codificatore video, quindi scrive il codice codificato
dati video in un file. I codec video sono gestiti da un processo distinto (mediaserver
), pertanto i buffer grafici di grandi dimensioni devono spostarsi all'interno del sistema. Per rendere la sfida più difficile, l'obiettivo è registrare video a 60 f/s a
massima risoluzione. Il segreto per far funzionare tutto in modo efficiente è BufferQueue.
La classe MediaCodec
consente a un'app di fornire dati come byte non elaborati nei buffer,
o attraverso una superficie. Quando screenrecord
richiede l'accesso a un codificatore video, il processo screenrecord
crea una BufferQueue, si connette al lato consumer e poi passa il lato producer a screenrecord
come superficie.
L'utilità screenrecord
chiede quindi a SurfaceFlinger di creare un display virtuale che rispecchi il display principale (ovvero che abbia tutti gli stessi livelli) e lo incarica di inviare l'output alla superficie proveniente dal processo mediaserver
. In questo caso, SurfaceFlinger è il produttore
di buffer anziché il consumatore.
Al termine della configurazione, screenrecord
si attiva quando
vengono visualizzati i dati codificati. Quando le app vengono disegnate, i relativi buffer vengono inviati a SurfaceFlinger, che li compone in un unico buffer inviato direttamente all'encoder video nel processo mediaserver
. I frame completi non vengono mai visti dal processo screenrecord
. Internamente,
Il processo mediaserver
ha un modo diverso per spostare i buffer
passa anche i dati per handle, riducendo al minimo l'overhead.
Case study: simulazione di display secondari
WindowManager può chiedere a SurfaceFlinger di creare un livello visibile per il quale SurfaceFlinger funge da consumer BufferQueue. Puoi anche chiedere SurfaceFlinger per creare un display virtuale per il quale SurfaceFlinger agisce come il producer BufferQueue.
Se colleghi un display virtuale a un livello visibile, viene creato un loop chiuso
in cui la schermata composita viene visualizzata in una finestra. Questa finestra fa ora parte dell'output composito, quindi al successivo aggiornamento l'immagine composita all'interno della finestra mostra anche i contenuti della finestra. Per vedere come funziona, attiva
Opzioni sviluppatore in Impostazioni, seleziona
Simula display secondari e attiva una finestra. Per vedere
display secondari in azione, usa screenrecord
per immortalare l'atto
di attivare il display e di riprodurlo fotogramma per fotogramma.