Architettura e componenti

Nota

Per le app in Windows 10, è consigliabile usare le API Windows.UI.Composition anziché DirectComposition. Per altre info, vedi Modernizzare l'app desktop usando il livello visivo.

In questo argomento vengono descritti i componenti che costituiscono Microsoft DirectComposition. È costituita dalle sezioni seguenti.

Componenti software

DirectComposition è costituito dai seguenti componenti software principali.

  • Libreria di applicazioni in modalità utente (dcomp.dll) che implementa l'API pubblica basata su Component Object Model (COM).
  • Motore di composizione in modalità utente (dwmcore.dll) ospitato nel processo di Gestione finestre desktop (DWM) (dwm.exe) ed esegue la composizione desktop effettiva.
  • Un database oggetto in modalità kernel (parte di win32k.sys) che effettua il marshalling dei comandi dall'applicazione al motore di composizione.

Una singola istanza del motore di composizione gestisce gli alberi di composizione DirectComposition per tutte le applicazioni e l'albero di composizione DWM, che rappresenta l'intero desktop. Sia il database oggetti in modalità kernel che il motore di composizione in modalità utente vengono create un'istanza una volta per sessione, quindi un computer Terminal Server con più utenti ha più istanze di entrambi i componenti.

Il diagramma seguente illustra i componenti principali di DirectComposition e il modo in cui sono correlati tra loro.

Architettura di primo livello di directcomposition

Libreria di applicazioni

La libreria di applicazioni DirectComposition è un'API pubblica basata su COM con un singolo punto di ingresso flat esportato da dcomp.dll e restituisce un puntatore di interfaccia a un oggetto dispositivo. L'oggetto dispositivo, a sua volta, dispone di metodi per la creazione di tutti gli altri oggetti, ognuno dei quali è rappresentato da un puntatore di interfaccia. Tutte le interfacce DirectComposition ereditano da e implementano completamente l'interfaccia IUnknown . Tutti i metodi che accettano interfacce DirectComposition controllano se l'interfaccia viene implementata all'interno di dcomp.dll o se viene implementata da un altro componente. Poiché DirectComposition non è estendibile, i metodi che accettano interfacce come parametri restituiscono E_INVALIDARG se le interfacce non vengono implementate in dcomp.dll. L'API non richiede privilegi speciali; può essere chiamato dai processi in esecuzione al livello di accesso più basso. Tuttavia, poiché l'API non funziona nella sessione 0, non è adatta per i servizi. In questi termini, l'API DirectComposition è simile ad altre API Microsoft DirectX, in particolare Direct2D, Microsoft Direct3D e Microsoft DirectWrite.

Poiché il motore di composizione è progettato esclusivamente per l'esecuzione asincrona, le proprietà degli oggetti nell'API DirectComposition sono di sola scrittura. Tutte le proprietà hanno metodi setter, ma non metodi getter. La lettura delle proprietà non è solo a elevato utilizzo di risorse, ma può anche essere imprecisa perché qualsiasi valore restituito dal motore di composizione può diventare immediatamente non valido. Ciò può verificarsi se, ad esempio, un'animazione indipendente è associata alla proprietà che viene letta.

L'API è thread-safe. Un'applicazione può chiamare qualsiasi metodo da qualsiasi thread in qualsiasi momento. Tuttavia, poiché molti metodi API devono essere chiamati in una determinata sequenza, senza alcuna sincronizzazione un'applicazione può riscontrare un comportamento imprevedibile a seconda del modo in cui i thread si interleave. Ad esempio, se due thread modificano la stessa proprietà dello stesso oggetto in valori diversi contemporaneamente, l'applicazione non può prevedere quale dei due valori sarà il valore finale della proprietà. Analogamente, se due thread chiamano Commit nello stesso dispositivo, nessuno dei due thread ottiene un comportamento realmente transazionale perché una chiamata a Commit in un thread insemetterà il batch di tutti i comandi emessi da entrambi i thread, non solo quello che ha chiamato Commit.

Il sistema mantiene tutto lo stato interno per ogni oggetto dispositivo. Se un'applicazione crea due o più oggetti dispositivo DirectComposition, l'applicazione può mantenere batch indipendenti e altri stati tra i due.

Tutti gli oggetti DirectComposition hanno affinità dell'oggetto dispositivo; Gli oggetti creati da un particolare oggetto dispositivo possono essere utilizzati solo con tale oggetto dispositivo e possono essere associati solo ad altri oggetti creati dallo stesso oggetto dispositivo. In altre parole, ogni oggetto dispositivo è un'isola separata di funzionalità non contigua. L'unica eccezione è la classe visiva, che consente la compilazione di alberi visivi in cui un oggetto visivo può appartenere a un oggetto dispositivo diverso da quello padre. Ciò consente scenari in cui un'applicazione e un controllo possono gestire un singolo albero di composizione senza dover condividere un singolo oggetto dispositivo DirectComposition.

Motore di composizione

Il motore di composizione DirectComposition viene eseguito in un processo dedicato, separato da qualsiasi processo dell'applicazione. Un singolo processo di composizione, dwm.exe, supporta ogni applicazione in una sessione. Ogni applicazione può creare due alberi visivi per ogni finestra proprietaria. Tutti gli alberi vengono effettivamente implementati come sottoalberi di una struttura ad albero visuale più grande che comprende anche le strutture di composizione di DWM. DWM costruisce un albero visivo di grandi dimensioni per ogni desktop in una sessione. Ecco i vantaggi principali di questa architettura:

  • Il motore di composizione ha accesso a tutte le bitmap dell'applicazione e agli alberi visivi, che consente l'interoperabilità e la composizione delle finestre tra processi.
  • Il motore di composizione viene eseguito in un processo di sistema attendibile separato da qualsiasi processo dell'applicazione, consentendo alle applicazioni con diritti di accesso limitati di comporre contenuti protetti in modo sicuro.
  • Il motore di composizione può rilevare quando una determinata finestra è completamente occlusa ed evitare di sprecare risorse CPU e GPU (Graphics Processing Unit) che compongono per la finestra.
  • Il motore di composizione può comporre direttamente nel buffer nascosto dello schermo, evitando la necessità di una copia aggiuntiva necessaria per i motori di composizione per processo.
  • Tutte le applicazioni condividono un singolo dispositivo Direct3D per la composizione, che offre un notevole risparmio di memoria

La struttura ad albero visuale è una struttura mantenuta. L'API DirectComposition espone i metodi per modificare la struttura in batch di modifiche elaborate in modo atomico. L'oggetto radice nell'API DirectComposition è l'oggetto dispositivo, che funge da factory per tutti gli altri oggetti DirectComposition e contiene un metodo denominato Commit. Il motore di composizione non riflette le modifiche apportate dall'applicazione alla struttura ad albero visuale fino a quando l'applicazione non chiama Commit, a quel punto tutte le modifiche apportate dall'ultimo commit vengono elaborate come singola transazione.

Il requisito di chiamare Commit è simile al concetto di "frame", ad eccezione del fatto che, poiché il motore di composizione viene eseguito in modo asincrono, può presentare diversi fotogrammi tra le chiamate a Commit. In DirectComposition un frame è una singola iterazione del motore di composizione e l'intervallo impiegato da un'applicazione tra due chiamate a Commit viene chiamato batch.

DirectComposition esegue il batch di tutte le chiamate dell'applicazione all'API DirectComposition. Il database oggetto kernel, implementato nel driver di sessione win32k.sys, archivia tutte le informazioni sullo stato associate alle chiamate API.

Il motore di composizione produce un frame per ogni vuoto verticale nello schermo. Il frame viene avviato in un campo vuoto verticale e punta al successivo vuoto verticale. All'avvio del frame, il motore di composizione preleva tutti i batch in sospeso e include i relativi comandi in tale frame. I batch vengono inseriti in una coda in sospeso quando l'applicazione chiama Commit e la coda in sospeso viene scaricata in modo atomico all'inizio del frame. Pertanto, esiste un singolo punto nel tempo che contrassegna l'inizio di un frame. Tutti i batch inviati prima di questo punto vengono inclusi nel frame, mentre tutti i batch inviati dopo devono attendere l'elaborazione del frame successivo. Il ciclo di composizione completo è il seguente:

  1. Stimare l'ora del successivo vuoto verticale.
  2. Recuperare tutti i batch in sospeso.
  3. Elaborare i batch recuperati.
  4. Aggiornare tutte le animazioni usando il tempo stimato nel passaggio 1.
  5. Determinare le aree dello schermo che devono essere ricreate.
  6. Ri-comporre le aree dirty.
  7. Presentare il frame capovolgendo i buffer indietro e anteriore per ogni schermo.
  8. Se non è stato composto nulla e presentato nei passaggi 6 e 7, attendere il commit di un batch.
  9. Attendere il successivo vuoto verticale.

Se sono presenti più monitor collegati a una singola scheda video, il motore di composizione usa lo spazio verticale del monitor primario per guidare il ciclo di composizione e impostare i tempi di campionamento dell'animazione. Ogni monitor è rappresentato da una catena di capovolgimento a schermo intero separata; il motore di composizione ripete i passaggi 6 e 7 per ogni monitor, in modo round robin, usando un singolo dispositivo Direct3D. Se sono presenti anche più schede video, il motore di composizione usa un dispositivo Direct3D separato per ogni scheda video nei passaggi 6 e 7.

I fotogrammi di composizione vengono pianificati per iniziare sempre con uno spazio verticale, come illustrato nella figura seguente.

pianificazione dei fotogrammi di composizione

Se il motore di composizione non ha alcun lavoro da eseguire perché l'albero di composizione non è cambiato, il thread di composizione rimane in sospensione durante l'attesa di un nuovo batch. Quando viene inviato un nuovo batch, il thread di composizione si riattiva ma torna immediatamente in sospensione fino al successivo vuoto verticale. Questo comportamento garantisce tempi di inizio e fine prevedibili dei fotogrammi per le applicazioni e per il motore di composizione.

Il motore di composizione pubblica i tempi di presentazione dei fotogrammi e la frequenza dei fotogrammi corrente. La pubblicazione di queste informazioni consente alle applicazioni di stimare il tempo di presentazione per i propri batch, che a sua volta consente la sincronizzazione delle animazioni. In particolare, un'applicazione può usare una combinazione di statistiche dei fotogrammi dal motore di composizione e un modello cronologico del tempo impiegato dal thread dell'interfaccia utente per produrre un batch, per determinare il tempo di campionamento per le proprie animazioni.

Ad esempio, all'inizio del batch dell'applicazione illustrato nella figura precedente, l'applicazione può eseguire una query sul motore di composizione per determinare l'ora esatta della presentazione del frame successivo. L'applicazione può quindi usare l'ora corrente, insieme alle informazioni sui batch precedenti prodotti, per determinare se l'applicazione può completare il batch corrente prima del successivo vuoto verticale. Di conseguenza, l'applicazione usa il tempo di presentazione dell'intervallo come ora di campionamento per le proprie animazioni. Se l'applicazione determina che è improbabile completare il lavoro nel campo verticale corrente, l'applicazione può usare il tempo di campionamento successivo come ora di campionamento, usando le informazioni sulla frequenza dei fotogrammi restituite dal motore di composizione per calcolare tale tempo.

Concetti relativi a DirectComposition