Implementowanie interfejsu HAL dla kompozytora sprzętowego

Komponent sprzętowy (HWC) HAL łączy warstwy otrzymane z SurfaceFlinger, co zmniejsza ilość operacji komponowania wykonywanych przez OpenGL ES (GLES) i procesor graficzny.

HWC wyodrębnia obiekty, takie jak nakładki i blitry 2D, do elementów złożonych i komunikuje się ze specjalistycznym sprzętem do kompozycji okien, w oknach złożonych. Użyj HWC do składania okien zamiast składania przez SurfaceFlinger z GPU. Większość GPU nie jest zoptymalizowana pod kątem oraz kiedy GPU tworzy warstwy SurfaceFlinger, aplikacje nie mogą używać GPU do własnego renderowania.

Implementacje HWC powinny obsługiwać:

  • Co najmniej 4 nakładki:
    • Pasek postępu
    • Pasek systemu
    • Aplikacja
    • Tapeta/tło
  • warstwy większe niż wyświetlacz (np. tapeta).
  • Równoczesne mnożenie wstępnie na piksel i mieszanie alfa na poszczególnych płaszczyznach mieszanie alfa
  • Ścieżka sprzętowa do odtwarzania chronionego filmu
  • Kolejność pakowania RGBA, formaty YUV oraz kafelki, wiry i kroki usługi

Aby wdrożyć HWC:

  1. wdrożyć nieoperacyjne urządzenie HWC i wysłać całą pracę z kompozycji do GLES.
  2. Zaimplementuj algorytm, który stopniowo przekaże kompozycję do HWC. Możesz na przykład przydzielić do nakładki tylko 3 lub 4 pierwsze powierzchnie. systemu HWC.
  3. Optymalizacja HWC. Może to obejmować:
    • Wybieramy platformy, które maksymalizują obciążenie procesora graficznego wysyła je do systemu HWC.
    • Wykrywanie, czy ekran się aktualizuje. Jeśli nie, przekaż dostęp do GLES, a nie do HWC, aby oszczędzać energię. Gdy ekran ponownie się zaktualizuje, kontynuuj przenoszenie kompozycji do HWC.
    • Przygotowanie do typowych zastosowań, takich jak:
      • Ekran główny zawierający pasek stanu, pasek systemu i aplikację okno i animowane tapety
      • Gry pełnoekranowe w orientacji pionowej i poziomej
      • Film pełnoekranowy z napisami i odtwarzaniem kontrola
      • Chronione odtwarzanie wideo
      • Tryb wielu okien podzielony na ekran

Podstawowe elementy sprzętowe HWC

HWC udostępnia 2 elementy: warstwy i wyświetlacze, które reprezentują kompozycję i jej interakcję z urządzeniami wyświetlającymi. HWC zapewnia też kontrolę nad VSYNC oraz wywołanie zwrotne do SurfaceFlinger, aby powiadomić go o wystąpieniu zdarzenia VSYNC.

Interfejs HIDL

Android 8.0 i nowsze używają Interfejs HIDL o nazwie Composer HAL, i połączenia IPC z HWC i SurfaceFlinger. Interfejs HAL Composer zastępuje stary interfejs hwcomposer2.h. Jeśli dostawcy podają kod HAL usługi Composer po wdrożeniu HWC, Composer HAL bezpośrednio akceptuje wywołania HIDL SurfaceFlinger. Jeśli dostawcy udostępniają starszą implementację HWC, Composer HAL wczytuje wskaźniki funkcji z pliku hwcomposer2.h, i przekierowywanie wywołań HIDL do wywołań wskaźnika funkcji.

HWC udostępnia funkcje umożliwiające określenie właściwości danego wyświetlacza, przełączanie się między różnymi konfiguracjami wyświetlacza (np. rozdzielczość 4K lub 1080p) i trybami kolorów (np. domyślny kolor lub prawdziwy sRGB) oraz włączanie, wyłączanie wyświetlacza lub przełączanie go w tryb niskiego poboru mocy (jeśli jest obsługiwany).

Wskaźniki funkcji

Jeśli dostawcy implementują interfejs HAL usługi Composer bezpośrednio, SurfaceFlinger wywołuje jej funkcje za pomocą interfejsu HIDL IPC. Aby na przykład utworzyć warstwę, SurfaceFlinger wywołuje createLayer() na liście HAL usługi Composer.

Jeśli dostawcy wdrożą interfejs hwcomposer2.h, HAL usługi Composer we wskaźnikach funkcji hwcomposer2.h. W komentarzach hwcomposer2.h funkcje interfejsu HWC są określane nazwami w formacie małej litery, które nie występują w interfejsie jako pola nazwane. Prawie każda funkcja jest ładowana przez żądanie wskaźnik funkcji za pomocą parametru getFunction dostarczonego przez hwc2_device_t Na przykład funkcja createLayer jest wskaźnikiem funkcji typu HWC2_PFN_CREATE_LAYER, który jest zwracana, gdy wyliczana wartość HWC2_FUNCTION_CREATE_LAYER jest przekazano do getFunction.

Szczegółowa dokumentacja funkcji HAL i przekazywania funkcji HWC w usłudze Composer można znaleźć w sekcji composer. Szczegółową dokumentację dotyczącą wskaźników funkcji HWC znajdziesz w hwcomposer2.h.

Uchwyty do tworzenia warstw i wyświetlania

Warstwy i wyświetlacze są manipulowane przy użyciu uchwytów wygenerowanych przez HWC. Uchwyty są nieprzezroczyste dla SurfaceFlinger.

Gdy SurfaceFlinger tworzy nową warstwę, wywołuje funkcję createLayer, który zwraca typ Layer dla wartości bezpośrednich lub hwc2_layer_t w przypadku implementacji przekazywania. Kiedy SurfaceFlinger modyfikuje właściwość warstwy, SurfaceFlinger przekazuje wartość hwc2_layer_t do odpowiedniej funkcji modyfikacji oraz wszelkie inne informacje niezbędne do jej wprowadzenia. Typ hwc2_layer_t jest wystarczająco duży, aby przechowywać wskaźnik lub indeks.

Fizyczne wyświetlacze są tworzone przez podłączenie. Gdy fizyczny wyświetlacz jest HWC tworzy nick i przekazuje go do usługi SurfaceFlinger. przez wywołanie zwrotne Hotplug. Wyświetlacze wirtualne są tworzone przez SurfaceFlinger Wywołuję createVirtualDisplay(), aby poprosić o wyświetlenie. Jeśli HWC obsługuje wirtualną kompozycję wyświetlacza, zwraca uchwyt. Następnie SurfaceFlinger przekazuje kompozycję wyświetlaczy do urządzenia HWC. Jeśli HWC nie obsługuje funkcji wirtualnych kompozycję wyświetlania, SurfaceFlinger tworzy nick i komponuje wyświetlacz.

Wyświetl operacje tworzenia kompozycji

Raz na VSYNC, SurfaceFlinger aktywuje się, jeśli ma nową zawartość do wieloskładnikową. Nowe treści mogą być nowymi buforami obrazów z aplikacji lub zmianą właściwości co najmniej jednej warstwy. Gdy SurfaceFlinger go aktywuje:

  1. Obsługuje transakcje (jeśli występują).
  2. Włącza nowe bufory graficzne (jeśli są dostępne).
  3. Jeśli w kroku 1 lub 2 nastąpiła zmiana treści wyświetlanych na ekranie, zostanie utworzona nowa kompozycja.

Aby wykonać nową kompozycję, SurfaceFlinger tworzy niszczy warstwy lub modyfikuje ich stany (stosownie do przypadku). Są one też aktualizowane warstw z ich bieżącą zawartością, używając wywołań takich jak setLayerBuffer lub setLayerColor. Gdy wszystkie warstwy zostaną zaktualizowany, SurfaceFlinger wywołuje validateDisplay, który informuje HWC, aby zbadać stan warstw i określić, jak koncentracja i kontynuować. Domyślnie SurfaceFlinger próbuje skonfigurować każdą warstwę w taki sposób, aby warstwa była skomponowana przez HWC; chociaż w niektórych gdy SurfaceFlinger łączy warstwy za pomocą kreacji zastępczej GPU.

Po wywołaniu funkcji validateDisplay funkcja SurfaceFlinger wywołuje funkcję getChangedCompositionTypes, aby sprawdzić, czy przed wykonaniem kompozycji HWC chce zmienić typ kompozycji warstw. Aby zaakceptować zmiany, SurfaceFlinger wywołuje acceptDisplayChanges

Jeśli jakiekolwiek warstwy są oznaczone do skompilowania przez SurfaceFlingera, narzędzie to skompiluje je do bufora docelowego. Następnie SurfaceFlinger wywołuje funkcję setClientTarget, aby przekazać bufor do wyświetlacza, dzięki czemu bufor może być wyświetlany na ekranie lub dalej łączony z warstwami, które nie zostały oznaczone do kompozycji przez SurfaceFlinger. Jeśli żadne warstwy nie są oznaczone dla SurfaceFlinger pomija etap tworzenia kompozycji.

Na koniec SurfaceFlinger wywołuje metodę presentDisplay, aby to określić. zespół HWC dokończ proces kompozycji i wyświetli efekt końcowy.

Wiele reklam displayowych

Android 10 obsługuje wiele ekranów fizycznych. Podczas projektowania implementacji HWC przeznaczonej do użytku na Androidzie 7.0 oznacza, że w definicji HWC nie występują pewne ograniczenia:

  • Zakłada się, że jest dokładnie 1 wyświetlacz wewnętrzny. Mechanizm jest wyświetlany podczas uruchamianie. Po podłączeniu wewnętrznego wyświetlacza do zasilania nie można zostaną odłączone.
  • Oprócz wewnętrznego wyświetlacza można podłączyć do zasilania dowolną liczbę wyświetlaczy zewnętrznych. podczas normalnego działania urządzenia. Framework zakłada, że wszystkie urządzenia zewnętrzne po pierwszym wewnętrznym ekranie są urządzeniami zewnętrznymi, więc jeśli dodasz więcej ekranów wewnętrznych, zostaną one nieprawidłowo sklasyfikowane jako Display.TYPE_HDMI zamiast Display.TYPE_BUILT_IN.

Chociaż opisane powyżej operacje SurfaceFlinger są wykonywane na wyświetlacz, są realizowane po kolei dla wszystkich aktywnych wyświetlaczy, , nawet jeśli treść tylko jednego wyświetlacza jest zaktualizowana.

Jeśli na przykład wyświetlacz zewnętrzny jest aktualizowany, kolejność jest następująca:

// In Android 9 and lower:

// Update state for internal display
// Update state for external display
validateDisplay(<internal display>)
validateDisplay(<external display>)
presentDisplay(<internal display>)
presentDisplay(<external display>)

// In Android 10 and higher:

// Update state for internal display
// Update state for external display
validateInternal(<internal display>)
presentInternal(<internal display>)
validateExternal(<external display>)
presentExternal(<external display>)

Wirtualna kompozycja wyświetlacza

Struktura wyświetlacza wirtualnego jest podobna do tej na wyświetlaczu zewnętrznym kompozycji. Różnica między kompozycją zasobów displayowych wirtualnych a fizyczną Struktura obrazu polega na tym, że ekrany wirtualne wysyłają dane wyjściowe do bufora Gralloca. zamiast na ekran. Hardware Composer (HWC) zapisuje dane wyjściowe w buforze, zapewnia ogrodzenie dopełnienia i wysyła bufor do konsumenta (np. koder wideo, GPU, CPU itd.). Wyświetlacze wirtualne mogą używać 2D/Blitter lub nakładek, jeśli potok wyświetlania zapisuje dane w pamięci.

Tryby

Po wywołaniu przez SurfaceFlingera metody validateDisplay() HWC każdy obraz jest w jednym z 3 trybów:

  • GLES – GPU łączy wszystkie warstwy, zapisując dane bezpośrednio do bufora wyjściowego. HWC nie uczestniczy w kompozycji.
  • MIESZANE – GPU nakłada niektóre warstwy na Framebuffer, i HWC komponują bufor klatek i pozostałe warstwy, bezpośrednio w buforze wyjściowym.
  • HWC – HWC łączy wszystkie warstwy i zapisuje je bezpośrednio w buforze wyjściowym.

Format wyjściowy

Formaty wyjściowe bufora wyświetlacza wirtualnego zależą od ich trybu:

  • Tryb GLES – sterownik EGL ustawia bufor wyjściowy. w formacie dequeueBuffer(), zwykle RGBA_8888. Konsument musi być w stanie zaakceptować format wyjściowy ustawiany przez sterownik lub Nie można odczytać bufora.
  • Tryby mieszane i HWC – czy konsument potrzebuje CPU konsument ustawia format. W przeciwnym razie format to IMPLEMENTATION_DEFINED, a Gralloc ustawia najlepszy format na podstawie flag użycia. Na przykład Gralloc ustawia format YCbCr, jeśli konsument koder wideo i urządzenie HWC potrafią skutecznie zapisać format.

Ogrodzenia podczas synchronizacji

Bariery związane z synchronizacją są kluczowym aspektem grafiki Androida. systemu. Ogrodzenia umożliwiają procesorowi działanie niezależnie od równoległego działania GPU, blokując je tylko wtedy, gdy istnieje prawdziwa zależność.

Na przykład, gdy aplikacja przesyła bufor tworzony GPU, przesyła też obiekt blokady synchronizacji. To ogrodzenie sygnalizuje, gdy Procesor graficzny zakończył zapisywanie w buforze.

HWC wymaga, aby GPU ukończyło zapisywanie buforów przed ich wyświetleniem. Ogrodzenia synchronizacji przechodzą przez potok graficzny z buforami i sygnalizują zapisy buforów. Zanim wyświetli bufor, HWC sprawdza, czy sygnał synchronizacji został wysłany. Jeśli tak, wyświetla bufor.

Więcej informacji o ogrodach synchronizacji znajdziesz w artykule Integracja z komponentem Hardware Composer.