Wszystkie nowe formaty pikseli dodane do Androida muszą być uwzględnione w języku definiowania interfejsu Androida (AIDL) i w buforze sprzętowym Androida (AHB). AIDL i AHB mają rygorystyczne wymagania dotyczące stabilności i standaryzacji, które wymagają starannego procesu rozszerzania funkcjonalności. Wszystkie nowe formaty pikseli muszą być dostępne w AOSP, a wszystkie aktualizacje muszą być indywidualnie potwierdzane przez ekspertów ds. AIDL i AHB. Ten proces dokładnego potwierdzania jest ważnym czynnikiem w standaryzacji nowych formatów pikseli na platformie.
Na tej stronie opisujemy niezbędne zmiany w kodzie AOSP i proces dodawania nowych formatów pikseli w AOSP.
Zanim dodasz nowy format piksela, pobierz źródło i prześlij poprawki zgodnie z instrukcjami w sekcji Przesyłanie poprawek.
Dodawanie nowego formatu pikseli do AIDL
Dodanie obsługi nowego formatu pikseli wymaga wprowadzenia zmian w obu plikach PixelFormat.aidl znajdujących się w AIDL. Kod źródłowy AIDL znajdziesz w sekcji
hardware/interfaces/graphics/common/aidl/.
Aby dodać nowy format piksela do AIDL, wykonaj te czynności:
-  Dodaj nowy format piksela jako nowy wpis na końcu wyliczenia 
PixelFormatw plikuPixelFormat.aidlzgodnie z dotychczasową konwencją kodowania i ustaw wartość szesnastkową wpisu o 1 większą od poprzedniego wpisu. Dopasuj zmiany w kodzie do poprzednich wpisów. Oto przykład wpisu w przypadku formatu pikselaRGBA_8888:/** * 32-bit format that has 8-bit R, G, B, and A components, in that order, * from the lowest memory address to the highest memory address. * * The component values are unsigned normalized to the range [0, 1], whose * interpretation is defined by the dataspace. */ RGBA_8888 = 0x1,
Po wprowadzeniu zmian w
PixelFormat.aidli skompilowaniu kodu pojawia się ten komunikat o błędzie:android_developer:~/android/aosp-android-latest-release: m ... ############################################################################### # ERROR: AIDL API change detected # ############################################################################### Above AIDL file(s) has changed. Run `m android.hardware.graphics.common-update-api` to reflect the changes to the current version so that it is reviewed by android-aidl-api-council@google.com And then you need to change dependency on android.hardware.graphics.common-V(n)-* to android.hardware.graphics.common-V(n+1)-* to use new APIs.
 - 
  
Aby usunąć ten błąd, uruchom to polecenie zgodnie z komunikatem o błędzie, aby zmienić
PixelFormat.aidlw kataloguaidl_api:m android.hardware.graphics.common-update-api
Uruchomienie powyższego polecenia powoduje zaktualizowanie odpowiedniego pliku, aby można było go normalnie utworzyć.
 
Dodawanie nowego formatu piksela do AHB
Dodanie obsługi nowego formatu pikseli wymaga zmian w plikach hardware_buffer.h i AHardwareBuffer.cpp.
Kod źródłowy AHB znajdziesz w sekcji frameworks/native/libs/nativewindow.
Aby dodać do AHB nowy format piksela, wykonaj te czynności:
- W pliku 
hardware_buffer.hdodaj nowy format piksela jako nowy wpis na końcu wyliczeniaAHardwareBuffer_Format. Przestrzegaj dotychczasowych konwencji kodowania.Korzystając z
RGBA_8888przykładowego formatu piksela, dodaj nowy wpis formatu piksela w ten sposób:/** * Corresponding formats: * Vulkan: VK_FORMAT_R8G8B8A8_UNORM * OpenGL ES: GL_RGBA8 */ AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM = 1,
Pamiętaj, że nowy format piksela ma w AHB nazwę, która musi zaczynać się od znaku
AHARDWAREBUFFER_FORMAT_, po którym następują skróty kanałów i głębokość bitowa, a kończy się kodowaniem. Ten wpis wyliczeniowy musi mieć taką samą wartość szesnastkową jak w przypadku parametruPixelFormat.aidl.Format pikseli powinien mieć powiązany format Vulkan lub OpenGL ES albo oba te formaty. W razie potrzeby podaj powiązany format. Jeśli nie ma powiązanego formatu, określ
N/A. - 
Dodaj format piksela do opcjonalnych testów w ramach CTS, jeśli ma on powiązany format OpenGL ES. Aby to zrobić, dodaj nowy format GL do
AHardwareBufferGLTest.cppwAHBFormatAsString(int32_t format)zFORMAT_CASE(...)iGL_FORMAT_CASE(...)dla nowego formatu, jak pokazano poniżej:const char* AHBFormatAsString(int32_t format) { switch (format) { ... FORMAT_CASE(R8G8B8A8_UNORM); ... GL_FORMAT_CASE(GL_RGB8); } return ""; } - 
Następnie dodaj nowy test do
AHardwareBufferGLTest.cpp, jak pokazano poniżej:class RGBA8Test : public AHardwareBufferGLTest {}; // Verify that if we can allocate an RGBA8 AHB we can render to it. TEST_P(RGBA8Test, Write) { AHardwareBuffer_Desc desc = GetParam(); desc.usage = AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER; if (!SetUpBuffer(desc)) { return; } ASSERT_NO_FATAL_FAILURE(SetUpFramebuffer(desc.width, desc.height, 0, kBufferAsRenderbuffer)); ASSERT_NO_FATAL_FAILURE( SetUpProgram(kVertexShader, kColorFragmentShader, kPyramidPositions, 0.5f)); glDrawArrays(GL_TRIANGLES, 0, kPyramidVertexCount); ASSERT_EQ(GLenum{GL_NO_ERROR}, glGetError()); } INSTANTIATE_TEST_CASE_P( SingleLayer, RGBA8Test, ::testing::Values( AHardwareBuffer_Desc{57, 33, 1, AHARDWAREBUFFER_FORMAT_R16G16_UINT, 0, 0, 0, 0}), &GetTestName);Określ co najmniej 1 zestaw wartości
AHardwareBuffer_Desc. W razie potrzeby dodaj więcej wartości. - 
W
AHardwareBuffer.cppznajdź koniec statycznych asercji:// ---------------------------------------------------------------------------- // Validate hardware_buffer.h and PixelFormat.aidl agree // ----------------------------------------------------------------------------
Dołącz nowy tag
static_assertdla nowego formatu piksela, używając wyliczeniaPixelFormat::, a nie stałejHAL_PIXEL_FORMAT. Korzystając z tego samego przykładu formatu pikselaRGBA_8888z sekcji Dodawanie nowego formatu piksela do AIDL, dodaj nowy wpis formatu piksela w ten sposób:static_assert(static_cast
(aidl::android::hardware::graphics::common::PixelFormat::RGBA_8888) == AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM, "HAL and AHardwareBuffer pixel format don't match");  - 
Dodaj nowy format piksela do odpowiednich testów, dołączając go na końcu
PrintAhbFormat()wAHardwareBufferTest.cpp. Postępuj zgodnie z dotychczasową konwencją kodowania, jak pokazano poniżej:void PrintAhbFormat(std::ostream& os, uint64_t format) { switch (format) { ... FORMAT_CASE(R8G8B8A8_UNORM); default: os << "unknown"; break; } } - 
Dodaj nowy format piksela do pakietu SDK
HardwareBufferwHardwareBuffer.java: dodaj nowy wpis do@IntDef. Na przykład wpis dotyczący formatuRGBA_8888wygląda tak:@Retention(RetentionPolicy.SOURCE) @IntDef(prefix = { "RGB", "BLOB", "YCBCR_", "D_", "DS_", "S_" }, value = { ... RGBA_8888, })Jeśli wartości komponentów nie są znormalizowane bez znaku, podaj wartość w nazwie zmiennej. Na przykład nazwa zmiennej dla formatu tylko 16-bitowego kanału czerwonego bez znaku musi mieć postać
R_16UI, a ten sam format z dodatkowym 16-bitowym kanałem zielonym bez znaku musi mieć postaćRG_16UI16UI. - 
Dodaj nowy format piksela jako
static intwHardwareBuffer.java, dodając nową publiczną zmienną członkowską na końcu@Format:@Format ... /** Format: 8 bits each red, green, blue, alpha */ public static final int RGBA_8888 = 0x1;
Ten wpis wyliczeniowy musi mieć taką samą wartość szesnastkową jak wpis z
PixelFormat.aidlihardware_buffer.h. Przestrzegaj dotychczasowych konwencji. - 
Próba skompilowania tych zmian w kodzie spowoduje błąd kompilacji:
android_developer:~/android/aosp-android-latest-release: m ... ****************************** You have tried to change the API from what has been previously approved. To make these errors go away, you have two choices: 1. You can add '@hide' javadoc comments (and remove @SystemApi/@TestApi/etc) to the new methods, etc. shown in the above diff. 2. You can update current.txt and/or removed.txt by executing the following command: m api-stubs-docs-non-updatable-update-current-api To submit the revised current.txt to the main Android repository, you will need approval. ****************************** ...Aby usunąć ten błąd, uruchom to polecenie zgodnie z komunikatem o błędzie, aby zmienić
current.txt:m api-stubs-docs-non-updatable-update-current-api
Uruchomienie powyższego polecenia powoduje zaktualizowanie odpowiedniego pliku, aby można było go normalnie utworzyć.
 - 
  
Dodaj nowy format piksela do testów w Javie, dołączając go na końcu
paramsForTestCreateOptionalFormats()wHardwareBufferTest.java, jak pokazano poniżej:private static Object[] paramsForTestCreateOptionalFormats() { return new Integer[]{ HardwareBuffer.RGBA_8888 }; 
Dodawanie nowego formatu piksela do integracji z systemem okien
Aby użyć nowego formatu pikseli jako formatu bufora ramki w interfejsie API grafiki, dodaj go do odpowiedniej integracji systemu okien (WSI) dla danego interfejsu API grafiki. W przypadku aplikacji lub procesu systemowego korzystającego z interfejsu Vulkan API zaktualizuj łańcuch wymiany Vulkan. W przypadku aplikacji lub procesu systemowego korzystającego z interfejsu OpenGL ES API zaktualizuj interfejs EGL API.
Zmiany w Vulkan WSI dotyczące nowych formatów pikseli
Zaktualizuj interfejs Vulkan WSI w ten sposób:
- 
Dodaj nowy przypadek do funkcji
GetNativePixelFormat(VkFormat format)w sekcjiswapchain.cpp:android::PixelFormat GetNativePixelFormat(VkFormat format) { ... switch (format) { ... case VK_FORMAT_R8G8B8A8_UNORM: native_format = PixelFormat::RGBA_8888; break; ... default: ALOGV("unsupported swapchain format %d", format); break; } return native_format; } - Sprawdź, czy format piksela wymaga rozszerzenia Vulkan do działania.
W przypadku rozszerzeń bocznych użyj znaku 
instance_data, jak pokazano poniżej:bool colorspace_ext = instance_data.hook_extensions.test(ProcHook::EXT_swapchain_colorspace);
W przypadku rozszerzeń po stronie urządzenia użyj tych elementów:
bool rgba10x6_formats_ext = false; uint32_t exts_count; const auto& driver = GetData(pdev).driver; driver.EnumerateDeviceExtensionProperties(pdev, nullptr, &exts_count, nullptr); std::vectorprops(exts_count); driver.EnumerateDeviceExtensionProperties(pdev, nullptr, &exts_count, props.data()); for (uint32_t i = 0; i < exts_count; i++) { VkExtensionProperties prop = props[i]; if (strcmp(prop.extensionName, VK_EXT_RGBA10X6_FORMATS_EXTENSION_NAME) == 0) { rgba10x6_formats_ext = true; } } Google zarządza infrastrukturą potrzebną do udostępniania rozszerzenia instancji lub urządzenia
swapchain.cpp. Początkowa lista zmian nie musi mieć prawidłowo skonfigurowanych rozszerzeń z ładowarki Vulkan. - Następnie wymień pary formatu i przestrzeni kolorów:
desc.format = AHARDWAREBUFFER_FORMAT_R10G10B10A10_UNORM; if (AHardwareBuffer_isSupported(&desc) && rgba10x6_formats_ext) { all_formats.emplace_back( VkSurfaceFormatKHR{VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR}); if (colorspace_ext) { all_formats.emplace_back( VkSurfaceFormatKHR{VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16, VK_COLOR_SPACE_PASS_THROUGH_EXT}); all_formats.emplace_back( VkSurfaceFormatKHR{VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16, VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT}); }Musisz znać zgodne formaty i przestrzenie kolorów.
 - Dodaj nowy format do 
dEQP-VKznajdującego się wexternal/deqp. - Zaktualizuj testy zgodności z Vulkanem w 
vktApiExternalMemoryTests.cppivktExternalMemoryUtil.cpp, wywnioskowując wymagane zmiany z istniejącego źródła lub kontaktując się z zespołem pomocy Androida w celu uzyskania informacji. 
Zmiany w EGL w przypadku nowych formatów pikseli
Zaktualizuj EGL w ten sposób:
- W funkcji
getNativePixelFormat()zmodyfikuj drzewoif-else, aby zwracało wyliczenie AIDL dla nowego formatu pikseli.Na przykładzie
RGBA_8888formatu piksela:if (a == 0) { ... } else { if (componentType == EGL_COLOR_COMPONENT_TYPE_FIXED_EXT) { if (colorDepth > 24) { ... } else { *format = PixelFormat::RGBA_8888; } } else { ... } } - Aby dodać nowy format do dEQP, dodaj nowy wpis do wyliczenia
androidFormatsw ten sposób:static const GLenum androidFormats[] = { ... GL_RGBA8, ... }; 
Przesyłanie aktualizacji
Postępuj zgodnie z instrukcjami w sekcji Dla współtwórców, aby tworzyć listy zmian i udostępniać je odpowiedniemu zespołowi.