Das Synchronisierungs-Framework beschreibt explizit Abhängigkeiten zwischen verschiedene asynchrone Vorgänge im Android-Grafiksystem. Das Framework stellt eine API bereit, mit der Komponenten anzeigen können, wann Puffer freigegeben werden. Das Framework ermöglicht die Übergabe von Synchronisierungsprimitiven zwischen Treibern vom Kernel aus. und zwischen den Userspace-Prozessen selbst.
Eine Anwendung kann beispielsweise die Arbeit in der GPU in die Warteschlange stellen. Die GPU beginnt mit dem Zeichnen dieses Bildes. Obwohl das Bild nicht gezeichnet wurde, im Arbeitsspeicher gespeichert, wird der Pufferzeiger an das Fenster übergeben, Compositor zusammen mit einem Zaun, der angibt, wann die GPU Fertigstellen. Die Window Compositor-Verarbeitung beginnt im Voraus und übergibt die Arbeit an den Display-Controller. Analog dazu arbeitet die CPU mit im Voraus erfolgt. Sobald die GPU fertig ist, das Bild sofort angezeigt wird.
Das Synchronisierungs-Framework ermöglicht Implementierern außerdem, in ihren eigenen Hardwarekomponenten. Die Funktion bietet einen Einblick in die Grafikpipeline, Debugging.
Explizite Synchronisierung
Die explizite Synchronisierung ermöglicht Produzenten und Nutzern von Grafikpuffern um zu signalisieren, dass sie die Verwendung eines Puffers beendet haben. Explizite Synchronisierung im Kernel-Space implementiert.
Zu den Vorteilen der expliziten Synchronisierung gehören:
- Geringere Unterschiede im Verhalten der Geräte
- Bessere Unterstützung bei der Fehlerbehebung
- Verbesserte Testmesswerte
Das Synchronisierungs-Framework umfasst drei Objekttypen:
sync_timeline
sync_pt
sync_fence
Zeitachse_synchronisieren
sync_timeline
ist ein kontinuierlich ansteigender Zeitplan,
die Anbieter für jede Treiberinstanz implementieren sollten, z. B. einen GL-Kontext,
Display-Controllers oder 2D-Effekt. sync_timeline
Zähler
Jobs, die für eine bestimmte Hardware an den Kernel gesendet werden.
sync_timeline
garantiert die Reihenfolge der Vorgänge.
und ermöglicht hardwarespezifische Implementierungen.
Beachte bei der Implementierung von sync_timeline
die folgenden Richtlinien:
- Nützliche Namen für Fahrer, Fahrpläne und Zäune angeben Debugging.
timeline_value_str
undpt_value_str
implementieren in Zeitachsen, um die Debugging-Ausgabe besser lesbar zu machen.- Implementiere die Füllung
driver_data
, um Userspace-Bibliotheken bereitzustellen, wie die GL-Bibliothek, Zugriff auf private Zeitachsendaten. Mitdata_driver
können Anbieter Informationen über die unveränderlichensync_fence
undsync_pts
zum Erstellen von Befehlszeilen basierend auf ihnen. - Nutzerbereich darf nicht explizit einen Zaun erstellen oder signalisieren. Ausdrücklich die Erstellung von Signalen/Zäunen zu einem Denial-of-Service-Angriff führt, stoppt die Pipelinefunktionalität.
- Du solltest nicht auf
sync_timeline
,sync_pt
odersync_fence
-Elementen explizit. Die API stellt alle erforderlichen Funktionen.
Synchronisierungsschritt
sync_pt
ist ein einzelner Wert oder Punkt auf einem
sync_timeline
. Ein Punkt
hat drei Status: aktiv, signalisiert und Fehler. Punkte beginnen im Status „Aktiv“
und in den Signal- oder Fehlerstatus übergehen. Wenn beispielsweise ein Bild
Verbraucher keinen Puffer mehr benötigt, wird ein sync_pt
signalisiert
sodass ein Bildersteller weiß,
dass er wieder in den Zwischenspeicher schreiben darf.
fechten
sync_fence
ist eine Sammlung von sync_pt
-Werten.
so oft
haben unterschiedliche übergeordnete sync_timeline
-Elemente, z. B. für das
Controller und GPU). sync_fence
, sync_pt
und
sync_timeline
sind die wichtigsten Primitive,
die Treiber und Userspace
um ihre Abhängigkeiten zu kommunizieren. Wenn ein Zaun signalisiert wird,
Befehle, die vor dem Zaun ausgegeben wurden, sind garantiert vollständig,
einen Kernel-Treiber oder einen Hardwareblock,
führt Befehle der Reihe nach aus.
Mit dem Synchronisierungs-Framework können mehrere Nutzer
die Verwendung eines Puffers abgeschlossen und die Abhängigkeitsinformationen mit einer Funktion übermittelt haben.
. Zäune werden von einem Dateideskriptor gestützt und vom
den Kernel-Bereich zum Userspace. Ein Zaun kann beispielsweise zwei
sync_pt
-Werte, die angeben, wann zwei separate Bildnutzer fertig sind
Puffer zu lesen. Wenn der Zaun signalisiert wird, wissen die Bildersteller, dass sowohl
mit dem Konsumieren fertig.
Zäune wie sync_pt
-Werte starten in den aktiven Status und ändern den Status basierend auf
den Zustand ihrer Standpunkte. Wenn alle sync_pt
-Werte signalisiert werden, wird der Wert
sync_fence
wird signalisiert. Wenn ein sync_pt
fällt
in einen Fehlerstatus versetzt, hat der gesamte sync_fence
einen Fehlerstatus.
Die Mitgliedschaft in einer sync_fence
ist nach dem Zaun nicht mehr veränderbar
erstellt. Um mehr als einen Punkt in einem Zaun zu erhalten,
bei denen Punkte aus zwei unterschiedlichen Zäunen zu einem dritten Zaun hinzugefügt werden.
Wenn einer dieser Punkte im ursprünglichen Zaun signalisiert wurde und der andere nicht,
ist der dritte Zaun nicht
signalisiert.
Um eine explizite Synchronisierung zu implementieren, geben Sie Folgendes an:
- Ein Kernel-Bereich-Subsystem, das das Synchronisierungs-Framework implementiert
für einen bestimmten Hardwaretreiber. Fahrer, die sicherheitshalber sein müssen,
im Allgemeinen alles, was auf den Hardware Composer zugreift oder mit ihm kommuniziert.
Zu den Schlüsseldateien gehören:
<ph type="x-smartling-placeholder">
- </ph>
- Grundlegende Implementierung:
<ph type="x-smartling-placeholder">
- </ph>
kernel/common/include/linux/sync.h
kernel/common/drivers/base/sync.c
- Dokumentation unter
kernel/common/Documentation/sync.txt
- Bibliothek zur Kommunikation mit dem Kernelbereich in
platform/system/core/libsync
- Grundlegende Implementierung:
<ph type="x-smartling-placeholder">
- Der Anbieter muss die entsprechende Synchronisierung
fences als Parameter für
validateDisplay()
undpresentDisplay()
-Funktionen im HAL. - Zwei zaunbezogene GL-Erweiterungen (
EGL_ANDROID_native_fence_sync
) undEGL_ANDROID_wait_sync
) und Zaununterstützung in Grafiken .
Fallstudie: Treiber für Display-Werbung implementieren
Um die API zu verwenden, die die Synchronisierungsfunktion unterstützt,
entwickeln einen Anzeigetreiber
mit einer Anzeigepufferfunktion. Vor dem
Synchronisierungs-Framework vorhanden ist, würde diese Funktion dma-buf
empfangen.
Objekte, diese Puffer auf dem Bildschirm platziert und ihn blockiert, solange der Puffer sichtbar war. Für
Beispiel:
/* * assumes buffer is ready to be displayed. returns when buffer is no longer on * screen. */ void display_buffer(struct dma_buf *buffer);
Mit dem Synchronisierungs-Framework kann die Funktion display_buffer
ist komplexer. Wenn ein Zwischenspeicher angezeigt wird,
durch einen Zaun, der angibt,
wann der Puffer bereit ist. Du kannst dich in die Warteschlange stellen
und beginnen mit der Arbeit, nachdem der Zaun sich geräumt hat.
Wenn Sie die Warteschlange stellen und mit der Arbeit beginnen, nachdem der Zaun geräumt wurde, wird nichts blockiert. Sie stellen sofort Ihren eigenen Zaun um. So wird sichergestellt, dass der Puffer nicht mehr auf dem Display. Wenn Sie Puffer in die Warteschlange stellen, listet der Kernel Abhängigkeiten mit dem Synchronisierungs-Framework:
/* * displays buffer when fence is signaled. returns immediately with a fence * that signals when buffer is no longer displayed. */ struct sync_fence* display_buffer(struct dma_buf *buffer, struct sync_fence *fence);
Integration synchronisieren
In diesem Abschnitt wird erläutert, wie Sie das Framework für die Kernel-Space-Synchronisierung mit des Android-Frameworks und die Treiber, die kommunizieren müssen, miteinander kommunizieren. Kernel-Space-Objekte werden als Dateideskriptoren dargestellt, Userspace.
Integrationskonventionen
Halten Sie sich an die Android-HAL-Schnittstellenkonventionen:
- Wenn die API einen Dateideskriptor bereitstellt, der auf eine
sync_pt
verweist, Der Anbietertreiber oder der HAL, der die API verwendet, muss die Dateibeschreibung schließen. - Wenn der Anbietertreiber oder der HAL einen Dateideskriptor übergibt, der
sync_pt
einer API-Funktion hinzugefügt haben, darf der Anbietertreiber oder der HAL Schließen Sie den Dateideskriptor. - Um den Fence-Dateideskriptor weiterhin zu verwenden, müssen Sie den Anbietertreiber oder den HAL muss den Deskriptor duplizieren.
Ein Fence-Objekt wird jedes Mal umbenannt, wenn es die BufferQueue passiert.
Dank der Kernel-Fence-Unterstützung können Fences Strings für Namen haben, sodass die Synchronisierung
verwendet das Framework den Fensternamen und den Zwischenspeicherindex,
den Zaun, z. B. SurfaceView:0
. Dieses
ist hilfreich bei der Fehlerbehebung, um die Ursache eines Deadlocks zu identifizieren, wenn die Namen angezeigt werden.
in der Ausgabe von /d/sync
und Fehlerberichten.
ANativeWindow-Integration
ANativeWindow ist zaunfähig. dequeueBuffer
,
queueBuffer
und cancelBuffer
haben Fence-Parameter.
OpenGL ES-Integration
Die Integration von OpenGL ES-Synchronisierungen stützt sich auf zwei EGL-Erweiterungen:
- Mit
EGL_ANDROID_native_fence_sync
können Sie native Android-Fence-Dateideskriptoren inEGLSyncKHR
-Objekte. EGL_ANDROID_wait_sync
ermöglicht GPU-seitige Ladevorgänge anstatt auf CPU-Seite. Dadurch wartet die GPU aufEGLSyncKHR
. Die Die ErweiterungEGL_ANDROID_wait_sync
ist mit der ErweiterungEGL_KHR_wait_sync
.
Um diese Erweiterungen unabhängig zu verwenden, implementieren Sie den
EGL_ANDROID_native_fence_sync
-Erweiterung mit dem zugehörigen
Kernel-Unterstützung. Aktivieren Sie als Nächstes die EGL_ANDROID_wait_sync
in Ihrem Treiber installiert haben. Das EGL_ANDROID_native_fence_sync
Die Erweiterung besteht aus einem speziellen nativen Zaun EGLSyncKHR
-Objekt.
Typ. Daher werden Erweiterungen, die für bestehende EGLSyncKHR
gelten,
Objekttypen gelten nicht unbedingt für EGL_ANDROID_native_fence
Objekte und vermeidet unerwünschte Interaktionen.
In der Erweiterung EGL_ANDROID_native_fence_sync
wird eine entsprechende native
Fence-Datei-Deskriptor-Attribut, das nur bei der Erstellung festgelegt werden kann, und
können nicht direkt von einem vorhandenen Synchronisierungsobjekt direkt abgefragt werden. Dieses Attribut
kann auf einen von zwei Modi eingestellt werden:
- Ein gültiger Fence-Dateideskriptor umschließt eine vorhandene native
Android-Fence-Dateideskriptor in einem
EGLSyncKHR
-Objekt. - -1 erstellt einen nativen Android-Fence-Dateideskriptor aus einer
EGLSyncKHR
-Objekt.
Verwenden Sie den Funktionsaufruf DupNativeFenceFD()
, um die
EGLSyncKHR
-Objekt aus dem nativen Android-Fence-Dateideskriptor.
Dies hat das gleiche Ergebnis wie die Abfrage des Attributs set, wird jedoch gemäß den
die Konvention, dass der Empfänger die Abgrenzung schließt (damit das Duplikat
Vorgang). Durch das Löschen des EGLSyncKHR
-Objekts wird schließlich
das Attribut „interner Zaun“.
Hardware Composer-Integration
Der Hardware Composer verarbeitet drei Arten von Synchronisierungszäunen:
- Zäune erfassen werden zusammen mit Eingabepuffern übergeben,
die Aufrufe
setLayerBuffer
undsetClientTarget
. Diese stehen für einen ausstehenden Schreibvorgang in den Zwischenspeicher und müssen vor dem SurfaceFlinger oder die HWC versuchen, aus dem zugehörigen Zwischenspeicher zu lesen, Kompositionen durchzuführen. - Freigabe-Zäune werden nach dem Aufruf von
presentDisplay
über dengetReleaseFences
-Aufruf. Diese stehen für einen ausstehenden Lesevorgang aus dem vorherigen Zwischenspeicher auf derselben Ebene. A Zaunsignale freigeben, wenn die HWC den vorherigen Zwischenspeicher nicht mehr verwendet da der aktuelle Puffer den vorherigen in der Anzeige ersetzt hat. Release-Fences werden zusammen mit den vorherigen Puffern an die App zurückgegeben, wird während der aktuellen Komposition ersetzt. Die App muss warten, bis loslassen, bevor neue Inhalte in den Puffer geschrieben werden, zurückgegeben wurde. - Aktuelle Zäune werden zurückgegeben, einer pro Frame.
den Aufruf von
presentDisplay
. Aktuelle Zäune stellen dar, wann die die Zusammensetzung dieses Frames abgeschlossen ist, oder alternativ, des vorherigen Frames nicht mehr benötigt. Für physische angezeigt wird, gibtpresentDisplay
vorhandene Zäune zurück, wenn der auf dem Bildschirm angezeigt wird. Nach der Rückgabe der aktuellen Zäune wieder in den SurfaceFlinger-Zielpuffer, zutreffend sind. Für virtuelle Anzeigen werden die aktuellen Zäune zurückgegeben, wenn aus dem Ausgabepuffer gelesen werden kann.