Livelli e display

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.