BufferQueue i Gralloc

Klasa BufferQueue łączy komponenty, które generują bufory danych graficznych (producenci), z komponentami, które przyjmują dane do wyświetlania lub dalszego przetwarzania (konsumenci). Prawie wszystko, co przesuwa bufory danych graficznych w systemie, opiera się na BufferQueue.

Modułowy przydział pamięci Gralloc wykonuje przydziały buforów i jest implementowany za pomocą dwóch interfejsów HIDL (zob. hardware/interfaces/graphics/allocator/hardware/interfaces/graphics/mapper/). Funkcja allocate() przyjmuje oczekiwane argumenty (szerokość, wysokość, format pikseli) oraz zestaw flag użycia.

Producenci i konsumenci kolejki buforowej

Strukturę danych BufferQueue tworzą i posiadają konsumenci, którzy mogą występować w różnych procesach niż ich producenci. Gdy producent potrzebuje bufora, prosi o wolny bufor z poziomu BufferQueue, wywołując funkcję dequeueBuffer() i określając szerokość, wysokość, format pikseli i flagi użycia buforów. Następnie producent wypełnia bufor i zwraca go do kolejki, wywołując funkcję queueBuffer(). Następnie konsument pobiera bufor za pomocą acquireBuffer() i korzysta z jego zawartości. Gdy konsument skończy, zwróci bufor do kolejki, wywołując funkcję releaseBuffer(). Framework synchronizacji kontroluje sposób przesyłania danych z buforów przez ścieżkę przetwarzania graficznego Androida.

Niektóre cechy BufferQueue, takie jak maksymalna liczba buforów, są określane wspólnie przez producenta i konsumenta. Jednak BufferQueue przydziela bufory w miarę potrzeb. Bufory są zachowywane, chyba że ich właściwości ulegną zmianie. Jeśli na przykład producent zażąda buforów o innym rozmiarze, stare bufory zostaną zwolnione, a nowe zostaną przydzielone na żądanie.

Treści bufora nigdy nie są kopiowane przez BufferQueue, ponieważ przenoszenie tak dużej ilości danych jest nieefektywne. Zamiast tego bufory są zawsze przekazywane za pomocą uchwytu.

Śledzenie kolejki buforowej za pomocą Systrace

Aby dowiedzieć się, jak działają bufory grafiki, użyj narzędzia Systrace, które rejestruje aktywność urządzenia w krótkim czasie. Kod graficzny na poziomie systemu jest dobrze zinstrumentowany, podobnie jak większość kodu odpowiedniego frameworka aplikacji.

Aby korzystać z Systrace, włącz tagi gfx, viewsched. W wykresie wyświetlają się obiekty BufferQueue. Jeśli na przykład wykonasz śledzenie, gdy działa aplikacja Grafika's Play video (SurfaceView), w wierszu z nazwą SurfaceView zobaczysz, ile buforów było w danym momencie w kolejce.

Wartość rośnie, gdy aplikacja jest aktywna, co powoduje renderowanie klatek przez dekoder MediaCodec. Wartość maleje, gdy SurfaceFlinger działa i zużywa bufory. Gdy wyświetlasz film z częstotliwością 30 FPS, wartość kolejki waha się od 0 do 1, ponieważ wyświetlacz z częstotliwością około 60 FPS może nadążać za źródłem. SurfaceFlinger jest uruchamiany tylko wtedy, gdy jest coś do zrobienia, a nie 60 razy na sekundę. System stara się unikać pracy i wyłącza VSync, jeśli nic nie aktualizuje ekranu.

Jeśli przełączysz się na film z gry Grafika (TextureView) i uzyskasz nowy ślad, zobaczysz wiersz z oznaczeniem com.android.grafika / com.android.grafika.PlayMovieActivity. Jest to główna warstwa interfejsu użytkownika, czyli inny element BufferQueue. Ponieważ TextureView renderuje się do warstwy interfejsu użytkownika, a nie do osobnej warstwy, wszystkie aktualizacje oparte na filmie są wyświetlane tutaj.

Gralloc

Moduł alokacji Gralloc HALhardware/libhardware/include/hardware/gralloc.hwykonuje przydzielanie buforów za pomocą flag użycia. Flagi wykorzystania obejmują atrybuty takie jak:

  • jak często oprogramowanie będzie korzystać z pamięci (procesor);
  • Jak często pamięć będzie używana przez sprzęt (GPU)
  • Określa, czy pamięć ma być używana jako tekstura OpenGL ES (GLES).
  • czy pamięć będzie używana przez koder wideo;

Jeśli na przykład format bufora producenta określa RGBA_8888 pikseli, a producent wskazuje, że dostęp do bufora będzie uzyskiwany z oprogramowania (co oznacza, że aplikacja będzie modyfikować piksele na procesorze), Gralloc utworzy bufor z 4 bajtami na piksel w kolejności R-G-B-A. Jeśli zamiast tego producent określi, że bufor będzie dostępny tylko z poziomu sprzętu i jako tekstura GLES, Gralloc może robić wszystko, co chce sterownik GLES, np. sortowanie BGRA, nieliniowe układy przemieszania i alternatywne formaty kolorów. Zezwalanie sprzętowi na używanie preferowanego formatu może poprawić wydajność.

Na niektórych platformach nie można łączyć niektórych wartości. Na przykład flaga kodera wideo może wymagać pikseli YUV, więc dodanie dostępu do oprogramowania i ustawienie parametru RGBA_8888 spowoduje błąd.

Identyfikator zwrócony przez Gralloc może być przekazywany między procesami za pomocą Bindera.

Chronione bufory

Flaga użycia Gralloc GRALLOC_USAGE_PROTECTED umożliwia wyświetlanie bufora graficznego tylko przez ścieżkę chronioną przez sprzęt. Te płaszczyzny nakładek to jedyny sposób na wyświetlanie treści chronionych przez DRM (bufory chronione przez DRM nie są dostępne dla SurfaceFlingera ani sterownika OpenGL ES).

Filmy chronione DRM mogą być wyświetlane tylko na warstwie nakładki. Odtwarzacze wideo, które obsługują treści chronione, muszą być wdrażane za pomocą SurfaceView. Oprogramowanie działające na niezabezpieczonym sprzęcie nie może odczytywać ani zapisywać bufora. Ścieżki chronione przez sprzęt muszą być widoczne w nakładce skompilowanego sprzętowo kodu. Oznacza to, że chronione filmy znikają z ekranu, gdy skompilowany sprzętowo kod przełączy się na kompozycję OpenGL ES.

Szczegółowe informacje o treściach chronionych znajdziesz w artykule DRM.