Grafiki

Ikona HAL Grafiki na Androida

Platforma Android oferuje różne interfejsy API do renderowania grafiki 2D i 3D, które współpracują z implementacjami sterowników graficznych przez producentów. Dlatego warto dobrze poznać działanie tych interfejsów API. Ta strona przedstawia warstwę abstrakcji sprzętu graficznego (HAL), na której są budowane te sterowniki. Zanim przejdziesz do tej sekcji, zapoznaj się z tymi warunkami:

canvas (termin ogólny), Canvas (element interfejsu API)
Płótno to powierzchnia do rysowania, która obsługuje łączenie rzeczywistych bitów z pikselową mapą bitową lub obiektem Surface. Canvas zawiera metody standardowego rysowania bitmap, linii, kół, prostokątów, tekstu itp., a także jest powiązany z bitmapą lub powierzchnią. Płótno to najprostszy sposób rysowania obiektów 2D na ekranie. Klasa podstawowa to Canvas.
drawable
Rysunek to skompilowany zasób wizualny, który może być używany jako tło, tytuł lub inna część ekranu. Element rysowalny jest zwykle wczytywany do innego elementu interfejsu użytkownika, na przykład jako obraz tła. Obiekt drawable nie może odbierać zdarzeń, ale przypisuje różne inne właściwości, takie jak stan i harmonogram, aby umożliwić korzystanie z podklas, takich jak obiekty animacji czy biblioteki obrazów. Wiele obiektów do rysowania jest wczytywanych z plików zasobów do rysowania. Są to pliki XML lub bitmapy opisujące obraz. Zasoby do rysowania są kompilowane do podklas android.graphics.drawable. Więcej informacji o elementach do rysowania i innych zasobach znajdziesz w artykule Zasoby.
zasób layoutu
Zasób układu to plik XML opisujący układ ekranu aktywności. Więcej informacji znajdziesz w artykule Zasoby układu.
nine-patch (9-patch, NinePatch)
Nine-Patch to bitmapowy zasób, którego rozmiar można zmieniać. Można go używać do tworzenia tła lub innych obrazów na urządzeniu. Więcej informacji znajdziesz w artykule Nine-patch.
OpenGL ES
OpenGL ES to wieloplatformowy interfejs API do renderowania grafiki 2D i 3D. Android udostępnia biblioteki OpenGL ES do akceleracji sprzętowej w renderowaniu 3D. W przypadku renderowania 2D prostszym rozwiązaniem jest użycie płótna. Interfejs OpenGL ES jest dostępny w pakiecie Native Development Kit (NDK) na Androida. Pakiety android.opengl i javax.microedition.khronos.opengles udostępniają funkcje OpenGL ES.
surface (termin ogólny), Surface (element interfejsu API)
Powierzchnia reprezentuje blok pamięci, który jest łączony z ekranem. Powierzchnia zawiera płótno do rysowania i zawiera różne metody pomocnicze do rysowania warstw oraz do zmiany rozmiaru obiektu Surface. Zamiast klasy Surface użyj klasy SurfaceView.
surface view (generic term), SurfaceView (element interfejsu API)
Widok powierzchni to obiekt View, który otacza obiekt Surface do rysowania i wyświetla metody służące do dynamicznego określania jego rozmiaru i formatu. Widok powierzchni umożliwia wyświetlanie niezależnie od wątku interfejsu w przypadku operacji wymagających dużej ilości zasobów, takich jak gry czy podgląd na kamerze, ale w efekcie zużywa dodatkową pamięć. Widok powierzchni obsługuje zarówno grafikę na płótnie, jak i OpenGL ES. Klasą podstawową obiektu SurfaceView jest SurfaceView.
theme
Motyw to zestaw właściwości, takich jak rozmiar tekstu i kolor tła, które razem definiują różne domyślne ustawienia wyświetlania. Android udostępnia kilka standardowych motywów, które są wymienione w R.style i poprzedzielane znakiem Theme_.
view (termin ogólny), View (element interfejsu API)
Widok rysuje prostokątny obszar na ekranie i obsługuje kliknięcia, naciśnięcia klawiszy i inne zdarzenia interakcji. Klasa View jest klasą podstawową dla większości komponentów układu aktywności lub ekranu dialogowego, takich jak pola tekstowe i okna. Obiekt View otrzymuje wywołania od obiektu nadrzędnego (patrz ViewGroup), aby narysować siebie, i informuje obiekt nadrzędny o swoim preferowanym rozmiarze i lokalizacji, które mogą nie być respektowane przez obiekt nadrzędny. Więcej informacji znajdziesz na stronie View.
grupa widoku (termin ogólny), ViewGroup (element interfejsu API)
Grupa widoków zawiera zestaw podrzędnych widoków. Grupa widoków odpowiada za określanie położenia widoków podrzędnych i ich rozmiaru, a także wywoływanie ich do rysowania w odpowiednich przypadkach. Niektóre grupy widoków są niewidoczne i służą tylko do tworzenia układu, a inne mają interfejs własny, np. listę z przewijaniem. Grupy widoku znajdują się w pakiecie widget, ale rozszerzają klasę ViewGroup.
wyświetlanie hierarchii
Hierarchia widoków to układ obiektów widoku i grupy widoków, który definiuje interfejs użytkownika dla każdego komponentu aplikacji. Hierarchia składa się z grup widoków zawierających co najmniej 1 widok podrzędny lub grupę widoków. Aby debugować i optymalizować hierarchię widoku, możesz wyświetlić jej wizualizację za pomocą przeglądarki hierarchii, która jest dostarczana z pakietem Android SDK.
Vulkan
Vulkan to interfejs API o niskim obciążeniu, przeznaczony do obsługi wydajnej grafiki 3D.
widżet
Widżet to jeden z zestawu w pełni zaimplementowanych podklas widoku, które renderują elementy formularza i inne komponenty interfejsu, takie jak pole tekstowe lub menu wyskakujące. Widget jest w pełni zaimplementowany, dlatego obsługuje pomiary, rysowanie i reagowanie na zdarzenia ekranu. Widżety znajdują się w pakiecie android.widget.
window (termin ogólny), Window (element interfejsu API)
W aplikacji na Androida okno to obiekt pochodzący z klasy abstrakcyjnej Window, która określa elementy ogólnego okna, takie jak wygląd i styl, tekst na pasku tytułu oraz lokalizacja i zawartość menu. Dialogi i zadania korzystają z implementacji klasy Window do renderowania obiektu Window. Nie musisz implementować klasy Window ani używać okien w aplikacji.

Deweloperzy aplikacji wyświetlają obrazy na ekranie na 3 sposoby: za pomocą Canvas, OpenGL ES lub Vulkan.

Komponenty graficzne Androida

Niezależnie od tego, którego interfejsu API do renderowania używają deweloperzy, wszystko jest renderowane na powierzchni. Powierzchnia reprezentuje stronę producenta kolejki buforowej, która jest często używana przez SurfaceFlinger. Każde okno utworzone na platformie Android jest obsługiwane przez powierzchnię. Wszystkie wyrenderowane widoczne powierzchnie są łączone na wyświetlaczu przez SurfaceFlingera.

Ten schemat pokazuje, jak współpracują ze sobą najważniejsze komponenty:

komponenty do renderowania obrazów;

Rysunek 1. Sposób renderowania powierzchni.

Główne elementy:

Producenci strumienia obrazów

Producentem strumienia obrazów może być wszystko, co tworzy bufory graficzne do wykorzystania. Przykłady to dekodery OpenGL ES, Canvas 2D i mediaserver.

Odbiorcy strumienia obrazów

Najczęstszym odbiorcą strumieni obrazów jest SurfaceFlinger, usługa systemowa, która pobiera aktualnie widoczne powierzchnie i z użyciem informacji dostarczonych przez menedżera okien komponuje je na wyświetlaczu. SurfaceFlinger to jedyna usługa, która może modyfikować zawartość wyświetlacza. SurfaceFlinger do tworzenia grupy powierzchni używa OpenGL i komponenta sprzętowego.

Strumienie obrazów mogą też używać inne aplikacje OpenGL ES, np. aplikacja aparatu, która korzysta ze strumienia obrazu podglądu aparatu. Aplikacje inne niż GL mogą też być konsumentami, np. klasa ImageReader.

Komponowanie sprzętu

Abstrakcyjna warstwa sprzętowa dla podsystemu wyświetlacza. SurfaceFlinger może delegować niektóre zadania związane z kompozycją do kompozytora sprzętowego, aby odciążyć OpenGL i kartę graficzną. SurfaceFlinger działa jak zwykły klient OpenGL ES. Gdy więc SurfaceFlinger aktywnie łączy jeden lub dwa bufory w trzeci, korzysta z OpenGL ES. Dzięki temu kompozycja będzie wymagać mniej mocy niż gdyby GPU wykonywał wszystkie obliczenia.

Moduł sprzętowy Composer HAL wykonuje drugą połowę pracy i jest centralnym punktem do renderowania grafiki na Androidzie. Komponent Hardware Composer musi obsługiwać zdarzenia, w tym VSYNC (inne to hotplug dla obsługi HDMI typu „plug and play”).

Gralloc

Do przydzielania pamięci żądanej przez producentów obrazu potrzebny jest moduł alokacji pamięci graficznej (Gralloc). Więcej informacji znajdziesz w artykule Gralloc HAL.

Przepływ danych

Schemat ścieżki przetwarzania grafiki w Androidzie:

przepływ danych graficznych.

Rysunek 2. Przepływ danych graficznych w Androidzie

Obiekty po lewej stronie to moduły renderujące, które tworzą bufory graficzne, takie jak ekran główny, pasek stanu i interfejs systemu. SurfaceFlinger jest kompozytorem, a Hardware Composer jest kompozytorem.

BufferQueue

kolejki buforowe stanowią element łączący komponenty graficzne Androida. To para kolejek, które pośredniczą w ciągłym cyklu buforów od producenta do konsumenta. Gdy producenci przekażą swoje bufory, SurfaceFlinger będzie odpowiedzialny za złożenie wszystkich elementów na wyświetlaczu.

Proces komunikacji z koleją buforów przedstawia diagram poniżej.

Proces komunikacji z kolejka bufora

Rysunek 3. Proces komunikacji z koleją buforów

BufferQueue zawiera logikę, która łączy ze sobą producentów strumienia obrazów i odbiorców strumienia obrazów. Przykładami producentów obrazów są podglądy aparatu tworzone przez HAL aparatu lub gry OpenGL ES. Przykładami konsumentów obrazu są aplikacja SurfaceFlinger lub inna aplikacja wyświetlająca strumień OpenGL ES, na przykład aplikacja aparatu wyświetlająca wizjer aparatu.

Struktura danych BufferQueue łączy pulę buforów z koleją i używa Binder IPC do przekazywania buforów między procesami. Interfejs producenta, czyli to, co przekazujesz użytkownikowi, który chce generować bufory graficzne, to IGraphicBufferProducer (część SurfaceTexture). Kolejka buforów jest często używana do renderowania na powierzchni i do obsługi interfejsu GLConsumer.

BufferQueue może działać w 3 trybach:

Tryb podobny do synchronicznego – domyślnie kolejka buforowa działa w trybie podobnym do synchronicznego, w którym każdy bufor pochodzący od producenta jest wysyłany do konsumenta. W tym trybie nie jest odrzucany żaden bufor. Jeśli producent jest zbyt szybki i tworzy bufory szybciej niż są one wykorzystywane, zablokuje się i będzie czekać na puste bufory.

Tryb niezablokowany – kolejka buforowa może też działać w trybie niezablokowanym, w którym zamiast czekać na bufor generuje błąd. W tym trybie żaden bufor nie jest odrzucany. Jest to przydatne, aby uniknąć potencjalnych blokad w oprogramowaniu, które może nie rozumieć złożonych zależności w ramach graficznych.

Tryb odrzucania – na koniec kolejka buforów może być skonfigurowana tak, aby odrzucać stare bufory zamiast generować błędy lub czekać. Jeśli na przykład renderujesz GL do widoku tekstury i rysujesz tak szybko, jak to możliwe, musisz odrzucić bufory.

Aby wykonać większość tych zadań, SurfaceFlinger działa jako kolejny klient OpenGL ES. Gdy SurfaceFlinger aktywnie komponuje jeden lub dwa bufory w trzecim, używa OpenGL ES.

Drugą połowę pracy wykonuje sterownik sprzętowy HAL. Ten HAL pełni rolę centralnego punktu dla wszystkich funkcji renderowania grafiki na Androidzie.