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 przenosi bufory danych graficznych w systemie, opiera się na kolejce buforowej.
Modułowa funkcja alokacji pamięci Gralloc wykonuje alokacje buforów i jest implementowana za pomocą dwóch interfejsów HIDL (patrz hardware/interfaces/graphics/allocator/
i 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, a mogą oni działać w innych procesach niż ich producenci. Gdy producent potrzebuje bufora, prosi o wolny bufor z BufferQueue, wywołując funkcję dequeueBuffer()
, która określa 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()
. Ramka synchronizacji kontroluje sposób przesyłania buforów przez architekturę graficzną Androida.
Niektóre cechy kolejki buforowej, takie jak maksymalna liczba buforów, są określane wspólnie przez producenta i konsumenta. Jednak kolejka buforów 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.
BufferQueue nigdy nie kopiuje zawartości bufora, 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
, view
i sched
. Obiekty BufferQueue są wyświetlane w wyświetleniu.
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 to konieczne, 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, która jest kolejną kolejką buforową. 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.h
wykonuje przydzielanie buforów za pomocą flag użycia. Flagi wykorzystania obejmują atrybuty takie jak:
- jak często oprogramowanie (procesor) będzie korzystać z pamięci;
- Jak często pamięć będzie używana przez sprzęt (GPU)
- Określa, czy pamięć będzie 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 przełączania 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 określenie wartości 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 sprzętowo muszą być widoczne w nakładce kompozytora sprzętowego (czyli chronione filmy znikają z ekranu, gdy kompozytor sprzętowy przełączy się na kompozycję OpenGL ES).
Szczegółowe informacje o treściach chronionych znajdziesz w artykule DRM.