Ebenen und Displays sind zwei Primitiva, die die Kompositionsarbeit und die Interaktionen mit der Displayhardware darstellen.
Ebenen
Eine Ebene ist die wichtigste Einheit für die Komposition. Eine Ebene ist eine Kombination aus einer Oberfläche und einer Instanz von SurfaceControl
.
Jede Ebene hat eine Reihe von Eigenschaften, die definieren, wie sie mit anderen Ebenen interagiert. Die Layereigenschaften werden in der folgenden Tabelle beschrieben:
Attribut | Beschreibung |
---|---|
Positionsbezogen | Legt fest, wo die Ebene auf dem Display angezeigt wird. Enthält Informationen wie die Positionen der Kanten einer Ebene und ihre Z-Reihenfolge relativ zu anderen Ebenen (ob sie vor oder hinter anderen Ebenen liegen soll). |
Inhalt | Definiert, wie Inhalte, die auf der Ebene angezeigt werden, innerhalb der durch die Positionseigenschaften definierten Grenzen dargestellt werden sollen. Enthält Informationen wie „Zuschneiden“ (um einen Teil des Inhalts so zu vergrößern, dass er die Grenzen der Ebene ausfüllt) und „Transformieren“ (um gedrehte oder gespiegelte Inhalte anzuzeigen). |
Komposition | Definiert, wie die Ebene mit anderen Ebenen kombiniert werden soll. Enthält Informationen wie den Mischmodus und einen ebenenweiten Alphawert für das Alpha-Compositing. |
Optimierung | Enthält Informationen, die nicht unbedingt erforderlich sind, um die Ebene korrekt zusammenzusetzen, die aber vom Hardware Composer (HWC) des Geräts verwendet werden können, um die Zusammensetzung zu optimieren. Enthält Informationen wie den sichtbaren Bereich des Layers und den Teil des Layers, der seit dem vorherigen Frame aktualisiert wurde. |
Displays
Ein Display ist eine weitere wichtige Einheit der Komposition. Ein System kann mehrere Displays haben und Displays können während des normalen Systembetriebs hinzugefügt oder entfernt werden. Displays werden auf Anfrage des HWC oder des Frameworks hinzugefügt oder entfernt. Das HWC-Gerät fordert an, dass Displays hinzugefügt oder entfernt werden, wenn ein externes Display mit dem Gerät verbunden oder davon getrennt wird. Dies wird als Hotplugging bezeichnet. Clients fordern virtuelle Displays an, deren Inhalte in einem Off-Screen-Puffer statt auf einem physischen Display gerendert werden.
Virtuelle Displays
SurfaceFlinger unterstützt ein internes Display (im Smartphone oder Tablet), externe Displays (z. B. ein über HDMI angeschlossener Fernseher) und ein oder mehrere virtuelle Displays, die zusammengesetzte Ausgaben im System verfügbar machen. Virtuelle Displays können verwendet werden, um den Bildschirm aufzuzeichnen oder über ein Netzwerk zu senden. Für ein virtuelles Display generierte Frames werden in eine BufferQueue geschrieben.
Virtuelle Displays können dieselben Ebenen wie das Hauptdisplay (der Ebenenstapel) oder eigene Ebenen haben. Für ein virtuelles Display gibt es kein VSync. Das VSync für das interne Display löst daher die Komposition für alle Displays aus.
Auf HWC-Implementierungen, die sie unterstützen, können virtuelle Displays mit OpenGL ES (GLES), HWC oder sowohl GLES als auch HWC zusammengesetzt werden. Bei nicht unterstützten Implementierungen werden virtuelle Displays immer mit GLES zusammengesetzt.
Fallstudie: Bildschirmaufzeichnung
Mit dem Befehl screenrecord
kann der Nutzer alles, was auf dem Bildschirm angezeigt wird, als MP4-Datei auf der Festplatte aufzeichnen. Dazu empfängt das System zusammengesetzte Frames von SurfaceFlinger, schreibt sie in den Video-Encoder und schreibt dann die codierten Videodaten in eine Datei. Die Video-Codecs werden von einem separaten Prozess (mediaserver
) verwaltet, sodass große Grafikpuffer im System verschoben werden müssen. Um die Herausforderung zu erhöhen, soll das Video mit 60 fps in voller Auflösung aufgenommen werden. Der Schlüssel für eine effiziente Funktionsweise ist BufferQueue.
Die Klasse MediaCodec
ermöglicht einer App, Daten als Rohbytes in Puffern oder über eine Oberfläche bereitzustellen. Wenn screenrecord
Zugriff auf einen Video-Encoder anfordert, erstellt der mediaserver
-Prozess eine BufferQueue, stellt eine Verbindung zur Consumer-Seite her und gibt die Producer-Seite dann als Oberfläche an screenrecord
zurück.
Das screenrecord
-Dienstprogramm fordert SurfaceFlinger dann auf, ein virtuelles Display zu erstellen, das das Hauptdisplay spiegelt (d. h. alle Ebenen sind identisch), und leitet die Ausgabe an die Oberfläche weiter, die vom mediaserver
-Prozess stammt. In diesem Fall ist SurfaceFlinger der Ersteller von Puffern und nicht der Nutzer.
Nach Abschluss der Konfiguration wird screenrecord
ausgelöst, wenn die codierten Daten angezeigt werden. Wenn Apps gerendert werden, werden ihre Puffer an SurfaceFlinger gesendet, das sie in einem einzigen Puffer zusammenfasst, der direkt an den Video-Encoder im mediaserver
-Prozess gesendet wird. Die vollständigen Frames werden vom screenrecord
-Prozess nie gesehen. Intern verschiebt der mediaserver
-Prozess Puffer auf eigene Weise, wobei Daten auch per Handle übergeben werden, um den Overhead zu minimieren.
Fallstudie: Sekundäre Displays simulieren
Der WindowManager kann SurfaceFlinger auffordern, eine sichtbare Ebene zu erstellen, für die SurfaceFlinger als BufferQueue-Consumer fungiert. Es ist auch möglich, SurfaceFlinger zu bitten, ein virtuelles Display zu erstellen, für das SurfaceFlinger als BufferQueue-Producer fungiert.
Wenn Sie ein virtuelles Display mit einer sichtbaren Ebene verbinden, entsteht eine geschlossene Schleife, in der der zusammengesetzte Bildschirm in einem Fenster angezeigt wird. Dieses Fenster ist jetzt Teil der zusammengesetzten Ausgabe. Beim nächsten Aktualisieren des zusammengesetzten Bildes im Fenster werden also auch die Fensterinhalte angezeigt. Um das in Aktion zu sehen, aktivieren Sie die Entwickleroptionen in den Einstellungen, wählen Sie Sekundäre Displays simulieren aus und aktivieren Sie ein Fenster. Um sekundäre Displays in Aktion zu sehen, verwenden Sie screenrecord
, um das Aktivieren des Displays aufzuzeichnen und dann Frame für Frame wiederzugeben.