Struktura synchronizacji wyraźnie opisuje zależności między przy wykonywaniu różnych operacji asynchronicznych w systemie graficznym Androida. Struktura udostępnia interfejs API, który umożliwia komponentom wskazywanie momentów zwolnienia buforów. Platforma zapewnia również umożliwia przekazywanie podstawowych elementów synchronizacji między sterownikami w jądrze do przestrzeni użytkownika i między procesami w tej przestrzeni.
Aplikacja może na przykład umieszczać w kolejce zadania do wykonania w GPU. Procesor graficzny zaczyna rysować ten obraz. Chociaż obraz nie został narysowany, do pamięci, wskaźnik bufora jest przekazywany do okna kompozytora wraz z ogrodzeniem, które wskazuje, kiedy układ GPU . Kompozytor okien rozpoczyna przetwarzanie z wyprzedzeniem i przekazuje pracę kontrolerowi ekranu. W podobny sposób procesor trzeba wykonać wcześniej. Gdy GPU zakończy działanie, kontroler wyświetlacza od razu wyświetli obraz.
Platforma synchronizacji pozwala też wdrażającym zasobów synchronizacji w ich własnych komponentach sprzętowych. Pamiętaj też, że zapewnia wgląd w potok graficzny, co ułatwia i debugowaniu.
Jawna synchronizacja
Bezpośrednia synchronizacja umożliwia producentom i konsumentom korzystanie z buforów graficznych sygnalizuje zakończenie, używając bufora. Aktualna synchronizacja w środowisku jądra systemu operacyjnego.
Zalety bezpośredniej synchronizacji:
- Mniejsze różnice w zachowaniu między urządzeniami
- Lepsza obsługa debugowania
- Ulepszone dane testowe
Platforma synchronizacji ma 3 typy obiektów:
sync_timeline
sync_pt
sync_fence
sync_timeline
sync_timeline
to monotonicznie rosnąca oś czasu,
dostawcy powinni wdrożyć dla każdej instancji sterownika, np. kontekst GL,
lub np. kontroler wyświetlacza 2D. Liczba operacji: sync_timeline
do jądra systemu dla określonego urządzenia.
sync_timeline
zapewnia gwarancje dotyczące kolejności działań
i umożliwia korzystanie ze sprzętu.
Przestrzegaj tych wskazówek przy implementacji sync_timeline
:
- Aby uprościć, podaj przydatne nazwy wszystkich kierowców, osi czasu i płodów i debugowaniu.
- Wdróż
timeline_value_str
ipt_value_str
operatory na osi czasu, aby dane wyjściowe debugowania były bardziej czytelne. - Zaimplementuj funkcję wypełnienia (
driver_data
), aby zapewnić biblioteki przestrzeni użytkownika. takich jak biblioteka GL, w razie potrzeby dostęp do prywatnych danych osi czasu.data_driver
umożliwia dostawcom przekazywanie informacji o stałychsync_fence
isync_pts
do tworzenia wierszy poleceń na ich podstawie. - Nie zezwalaj przestrzeni użytkownika na bezpośrednie tworzenie lub sygnalizowanie ogrodzenia. Wyraźnie tworzenie sygnałów/płodów skutkuje atakiem typu DoS, wstrzymuje działanie potoku.
- Nie uzyskuj dostępu do usług
sync_timeline
,sync_pt
lubsync_fence
. Interfejs API udostępnia wszystkie wymagane funkcji.
synchronizacja_pt
sync_pt
to pojedyncza wartość lub punkt na
sync_timeline
Punkt
ma 3 stany: aktywny, sygnalizowany i błąd. Punkty zaczynają się w stanie aktywnym
i przejściu do stanu
sygnalizowania lub błędu. Jeśli na przykład obraz
konsument nie potrzebuje już bufora, pojawia się sygnał sync_pt
dzięki czemu producent obrazów wie, że można znowu zapisać w buforze.
granica_synchronizacji
sync_fence
to zbiór wartości sync_pt
często
mają różne elementy nadrzędne sync_timeline
(np. dla wyświetlacza
kontroler i GPU). sync_fence
, sync_pt
i
sync_timeline
to główne podstawowe elementy, których sterowniki i przestrzeń użytkownika
komunikują się z nimi. Gdy pojawi się sygnał,
polecenia wydane przed ogrodzeniem są zapewne ukończone, ponieważ
sterownik jądra lub blok sprzętowy wykonuje polecenia po kolei.
Platforma synchronizacji umożliwia wielu konsumentom lub producentom sygnalizowanie, że
zakończyło działanie przy użyciu bufora, przekazując informacje o zależności za pomocą jednej funkcji
. Ogrodzenia są wspierane przez deskryptor pliku i przekazywane z
z jednego jądra systemu operacyjnego. Na przykład ogrodzenie może zawierać dwa
Wartości sync_pt
, które oznaczają występowanie 2 osobnych obrazów klienta
czytanie bufora. Gdy ogrodzenie jest sygnalizowane, producenci obrazu wiedzą,
przez konsumentów.
Ogrodzenia, takie jak wartości sync_pt
, zaczynają być aktywne i zmieniają stan w zależności od tego,
na stan ich punktów. Jeśli wszystkie wartości sync_pt
zostaną zasygnalizowane,
sync_fence
otrzymuje sygnał. Jeśli sync_pt
spadnie
w stan błędu, cały element sync_fence
zawiera stan błędu.
Członkostwa w domenie sync_fence
nie można zmienić po tym, jak ogrodzenie jest
Utworzono. Aby uzyskać więcej niż jeden punkt ogrodzenia, scalanie
polega na tym, że do trzeciego ogrodzenia dodaje się punkty z dwóch różnych płotów.
Jeśli jeden z tych punktów był sygnalizowany na początkowym ogrodzeniu, a drugi nie,
Trzecie ogrodzenie też nie będzie zasygnalizowane.
Aby wdrożyć synchronizację jawną, podaj te informacje:
- Podsystem jądra wykorzystujący platformę synchronizacji
dla konkretnego sterownika sprzętowego. Kierowcy, którzy muszą mieć świadomość płotu,
wszystko, co uzyskuje dostęp do narzędzia Hardware Composer lub się z nim komunikuje.
Kluczowe pliki obejmują:
- Implementacja podstawowa:
kernel/common/include/linux/sync.h
kernel/common/drivers/base/sync.c
- Dokumentacja na
kernel/common/Documentation/sync.txt
- Biblioteka do komunikacji z przestrzenią jądra w
platform/system/core/libsync
- Implementacja podstawowa:
- Dostawca musi zapewnić odpowiednią synchronizację
ogrodzenia jako parametry do
validateDisplay()
orazpresentDisplay()
w funkcji HAL. - Dwa rozszerzenia GL związane z ogrodzeniami (
EGL_ANDROID_native_fence_sync
) iEGL_ANDROID_wait_sync
) oraz obsługa ogrodzenia w grafice. sterownika.
Studium przypadku: wdrażanie sterowników dla reklam displayowych
Aby użyć interfejsu API obsługującego funkcję synchronizacji,
opracować sterownik wyświetlacza z funkcją bufora wyświetlacza. Przed
jeśli istniała platforma synchronizacji, ta funkcja otrzymałaby funkcję dma-buf
obiektów, umieścić te bufory na wyświetlaczu i blokować je, gdy bufor jest widoczny. Dla:
przykład:
/* * assumes buffer is ready to be displayed. returns when buffer is no longer on * screen. */ void display_buffer(struct dma_buf *buffer);
W przypadku platformy synchronizacji funkcja display_buffer
jest bardziej złożona. Po umieszczeniu bufora na wyświetlaczu zostaje on powiązany
ogrodzeniem wskazującym, kiedy bufor będzie gotowy. Możesz dodać do kolejki
i rozpocząć pracę po usunięciu płotu.
Dodawanie do kolejki i rozpoczynanie pracy po usunięciu płotu niczego nie blokuje. Natychmiast zwracasz własne ogrodzenie, co gwarantuje, że bufor zostanie wyłączony. Gdy umieszczasz bufory w kolejce, jądro wyświetla zależności w ramach platformy synchronizacji:
/* * 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);
Integracja z synchronizacją
Ta sekcja wyjaśnia, jak zintegrować platformę synchronizacji przestrzeni jądra z elementów platformy Androida i sterowników, które muszą się komunikować i otwierać przed sobą nawzajem. Obiekty przestrzeni jądra są reprezentowane jako deskryptory plików w przestrzeń użytkownika.
Konwencje integracji
Postępuj zgodnie z konwencjami interfejsu HAL Androida:
- Jeśli interfejs API udostępnia deskryptor pliku odnoszący się do elementu
sync_pt
, sterownik dostawcy lub kod HAL korzystający z interfejsu API musi zamykać deskryptor pliku. - Jeśli sterownik dostawcy lub HAL przekazuje deskryptor pliku zawierający
sync_pt
do funkcji interfejsu API, sterownik dostawcy lub HAL nie mogą zamknij deskryptor pliku. - Aby nadal korzystać z deskryptora pliku ogrodzenia, sterownika dostawcy lub HAL musi zduplikować deskryptor.
Nazwa obiektu ogrodzenia zmienia się za każdym razem, gdy przechodzi przez BufferQueue.
Obsługa jądra systemu operacyjnego sprawia, że ogrodzenie może mieć nazwane ciągi znaków dla nazw,
platforma używa nazwy okna i indeksu bufora umieszczonego w kolejce do nazwy
ogrodzenie, na przykład SurfaceView:0
. Ten
jest pomocne w debugowaniu w celu identyfikacji źródła zakleszczeń w postaci pojawiających się nazw
w danych wyjściowych /d/sync
i raportach o błędach.
Integracja ANativeWindow
ANativeWindow wykrywa ogrodzenie. dequeueBuffer
,
queueBuffer
i cancelBuffer
mają parametry ogrodzenia.
Integracja z platformą OpenGL ES
Integracja synchronizacji OpenGL ES korzysta z dwóch rozszerzeń EGL:
EGL_ANDROID_native_fence_sync
umożliwia opakuj lub utwórz natywne deskryptory plików Android fence wEGLSyncKHR
obiektów.EGL_ANDROID_wait_sync
zezwala na stoiska po stronie GPU a nie po stronie CPU, przez co GPU będzie czekaćEGLSyncKHR
.EGL_ANDROID_wait_sync
rozszerzenie jest takie samo jakEGL_KHR_wait_sync
.
Aby korzystać z tych rozszerzeń niezależnie, zaimplementuj tag
EGL_ANDROID_native_fence_sync
rozszerzenie i powiązane
i obsługą jądra systemu operacyjnego. Następnie włącz: EGL_ANDROID_wait_sync
w sterowniku. EGL_ANDROID_native_fence_sync
rozszerzenie składa się z odrębnego natywnego obiektu ogrodzenia EGLSyncKHR
typu. Dlatego rozszerzenia, które dotyczą obecnych EGLSyncKHR
,
typy obiektów nie muszą być stosowane do typu EGL_ANDROID_native_fence
z obiektami, co pozwala uniknąć
niechcianych interakcji.
Rozszerzenie EGL_ANDROID_native_fence_sync
korzysta z odpowiedniego kodu natywnego
atrybutu deskryptora pliku zabezpieczeń, który można ustawić tylko podczas tworzenia,
nie mogą być wysyłane bezpośrednio z istniejącego obiektu synchronizacji. Ten atrybut
można ustawić na jeden z dwóch trybów:
- Prawidłowy deskryptor pliku ogrodzenia opakowuje istniejący kod natywny
Deskryptor pliku Android fence w obiekcie
EGLSyncKHR
. - -1 tworzy natywny deskryptor pliku Android fence z tagu
EGLSyncKHR
obiekt.
Użyj wywołania funkcji DupNativeFenceFD()
, aby wyodrębnić parametr
Obiekt EGLSyncKHR
z deskryptora natywnego pliku Android fence.
Efekt jest taki sam jak w przypadku zapytania o atrybut set, ale jest zgodny z
konwencja, zgodnie z którą odbiorca zamyka ogrodzenie (co oznacza duplikat,
). Na koniec zniszczenie obiektu EGLSyncKHR
zostaje zamknięte
z atrybutem ogrodzenia wewnętrznego.
Integracja z usługą Hardware Composer
Narzędzie Hardware Composer obsługuje trzy typy blokad synchronizacji:
- Zdobywanie progów jest przekazywane wraz z buforami wejściowymi do
połączenia
setLayerBuffer
isetClientTarget
. Reprezentują one oczekujący zapis w buforze i muszą sygnalizować przed SurfaceFlinger lub HWC próbuje odczytać dane z powiązanego bufora w wykonać kompozycję. - Zwalnianie ogrodzenia jest pobierane po wywołaniu
presentDisplay
za pomocą wywołaniagetReleaseFences
. Reprezentują one oczekujący odczyt z poprzedniego bufora w tej samej warstwie. O wyzwalanie sygnałów ogrodzenia, gdy HWC nie korzysta już z poprzedniego bufora bo bieżący bufor zastąpił poprzedni bufor na wyświetlaczu. Blokady wersji są przekazywane z powrotem do aplikacji razem z poprzednimi buforami, zostaną zastąpione w bieżącej kompozycji. Aplikacja musi poczekać do rozluźnić granicę przed zapisaniem w buforze nowej zawartości, które zostały im zwrócone. - Zwracane są ogrodzenia, po jednym na klatkę, w ramach parametru
połączenie z numerem
presentDisplay
. Prezentuj ogrodzenia, pokazując, kiedy kompozycja tej klatki zakończy się lub na przemian, gdy nie jest już potrzebny wynik kompozycji poprzedniej klatki. Fizyczne wyświetla się,presentDisplay
zwraca ogrodzenie obecne, gdy na ekranie zostanie wyświetlona bieżąca ramka. Po zwróceniu ogrodzenia bezpiecznie jest ponownie zapisać w buforze docelowym SurfaceFlinger, jeśli mają zastosowanie. W przypadku wyświetlaczy wirtualnych obecne ogrodzenia są zwracane, gdy są do odczytu z bufora wyjściowego.