新增至 Android 的所有新像素格式都必須包含在 Android 介面定義語言 (AIDL) 和 Android 硬體緩衝區 (AHB) 中。AIDL 和 AHB 設有嚴格的穩定性和標準化要求,因此在擴充功能時,必須謹慎進行。所有新的像素格式都必須附在 Android 開放原始碼計畫裡,且所有更新都必須經過 AIDL 和 AHB 專家個別確認。在平台上將任何新像素格式標準化時,這項謹慎確認程序是一項重要因素。
本頁概述必要的 Android 開放原始碼計畫程式碼變更,以及在 Android 開放原始碼計畫中新增像素格式所需的程序。
新增新的像素格式之前,請下載來源並上傳修補程式,如提交修補程式所述。在 AIDL 中新增像素格式
新增對新像素格式的支援時,需要變更 AIDL 中的兩個 PixelFormat.aidl
檔案。如需 AIDL 原始碼,請參閱 hardware/interfaces/graphics/common/aidl/
。
如要將新的 Pixel 格式新增至 AIDL,請按照下列步驟操作:
- 請按照現有的程式碼慣例,將新的像素格式附加為
PixelFormat.aidl
中PixelFormat
列舉的結尾新項目,並將項目的 16 進位值設為比前一個項目多一個。將程式碼變更與先前的項目進行比對。請參閱以下RGBA_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,
變更
PixelFormat.aidl
後建構程式碼時,系統會顯示以下錯誤訊息:android_developer:~/android/aosp-main: 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.
-
如要清除這項錯誤,請按照錯誤訊息中指定的方式執行下列指令,變更
aidl_api
目錄中的PixelFormat.aidl
:m android.hardware.graphics.common-update-api
執行上述指令可更新正確的檔案,以便正常建構。
在 AHB 中新增像素格式
新增對新像素格式的支援必須變更 hardware_buffer.h
和 AHardwareBuffer.cpp
。如需 AHB 原始碼,請參閱 frameworks/native/libs/nativewindow
。
如要在 AHB 中新增正式像素,請按照下列步驟操作:
- 在
hardware_buffer.h
中,將新的像素格式附加為AHardwareBuffer_Format
列舉的結尾處的新項目。遵守現有的程式碼慣例。以
RGBA_8888
像素格式為例,請新增下列新的像素格式項目:/** * Corresponding formats: * Vulkan: VK_FORMAT_R8G8B8A8_UNORM * OpenGL ES: GL_RGBA8 */ AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM = 1,
請注意,新的像素格式會在 AHB 中指定名稱,開頭必須是
AHARDWAREBUFFER_FORMAT_
,後面接著頻道縮寫和位元深度,結尾則是編碼。這個列舉項目必須具有與PixelFormat.aidl
相同的十六進位值。像素格式應包含一或兩個相關聯的 Vulkan 或 OpenGL ES 格式。在適當情況下指定相關格式。如果沒有相關格式,請指定
N/A
。 -
如果像素格式具有相關的 OpenGL ES 格式,請將該格式新增至 CTS 的選用測試。如要這麼做,請使用
FORMAT_CASE(...)
和GL_FORMAT_CASE(...)
為新格式,將新的 GL 格式新增至AHBFormatAsString(int32_t format)
中的AHardwareBufferGLTest.cpp
,如下所示:const char* AHBFormatAsString(int32_t format) { switch (format) { ... FORMAT_CASE(R8G8B8A8_UNORM); ... GL_FORMAT_CASE(GL_RGB8); } return ""; }
-
接下來,在
AHardwareBufferGLTest.cpp
中新增測試,如下所示: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);
至少指定一組
AHardwareBuffer_Desc
值。視需要新增更多值。 -
在
AHardwareBuffer.cpp
中找出其中的靜態斷言結尾:// ---------------------------------------------------------------------------- // Validate hardware_buffer.h and PixelFormat.aidl agree // ----------------------------------------------------------------------------
使用
PixelFormat::
列舉 (而非HAL_PIXEL_FORMAT
常數) 為新像素格式附加新的static_assert
。與「在 AIDL 新增像素格式」一文中所述的RGBA_8888
像素格式範例,新增像素格式項目,如下所示:static_assert(static_cast
(aidl::android::hardware::graphics::common::PixelFormat::RGBA_8888) == AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM, "HAL and AHardwareBuffer pixel format don't match"); -
在
AHardwareBufferTest.cpp
的PrintAhbFormat()
結尾處附加新像素格式,即可將新像素格式新增至適當的測試。請遵循現有的程式碼慣例,如下所示:void PrintAhbFormat(std::ostream& os, uint64_t format) { switch (format) { ... FORMAT_CASE(R8G8B8A8_UNORM); default: os << "unknown"; break; } }
-
在
HardwareBuffer.java
中將新的像素格式新增至HardwareBuffer
SDK:將新的項目附加至@IntDef
。例如,RGBA_8888
格式的項目如下所示:@Retention(RetentionPolicy.SOURCE) @IntDef(prefix = { "RGB", "BLOB", "YCBCR_", "D_", "DS_", "S_" }, value = { ... RGBA_8888, })
如果元件值未經過正規化處理,請在變數名稱中明確指出值。例如,僅限無正負號整數 16 位元紅色通道的變數名稱必須為
R_16UI
,而包含其他無正負號整數 16 位元綠色管道格式的相同格式必須為RG_16UI16UI
。 -
在
HardwareBuffer.java
中,將新的像素格式新增為static int
,方法是在@Format
結尾附加新的公開成員變數:@Format ... /** Format: 8 bits each red, green, blue, alpha */ public static final int RGBA_8888 = 0x1;
此列舉項目的十六進位值必須與
PixelFormat.aidl
和hardware_buffer.h
相同。依循現有慣例。 -
嘗試使用這些程式碼變更進行建構時,會產生建構錯誤:
android_developer:~/android/aosp-main: 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. ****************************** ...
如要清除這項錯誤,請按照錯誤訊息中指定的方式執行下列指令,變更
current.txt
:m api-stubs-docs-non-updatable-update-current-api
執行上述指令會更新正確的檔案,以便正常進行建構。
-
將新的像素格式附加至
HardwareBufferTest.java
中的paramsForTestCreateOptionalFormats()
結尾,藉此將新像素格式新增至 Java 測試,如下所示:private static Object[] paramsForTestCreateOptionalFormats() { return new Integer[]{ HardwareBuffer.RGBA_8888 };
在 Window System 整合中新增像素格式
如要將新像素格式用於圖形 API 中的框架緩衝區格式,請將該格式新增至相關圖形 API 的適當視窗系統整合 (WSI)。對於使用 Vulkan API 的應用程式或系統程序,請更新 Vulkan Swapchain。 如果是使用 OpenGL ES API 的應用程式或系統程序,請更新 EGL API。
針對新的像素格式調整 Vulkan WSI
更新 Vulkan WSI,如下所示:-
在
swapchain.cpp
中,將新情況新增至GetNativePixelFormat(VkFormat format)
函式: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; }
- 如果像素格式需要 Vulkan 擴充功能才能運作,請查詢 Vulkan 擴充功能。如果是執行個體端擴充功能,請使用
instance_data
,如下所示:bool colorspace_ext = instance_data.hook_extensions.test(ProcHook::EXT_swapchain_colorspace);
如要使用裝置端擴充功能,請使用下列方式:
bool rgba10x6_formats_ext = false; uint32_t exts_count; const auto& driver = GetData(pdev).driver; driver.EnumerateDeviceExtensionProperties(pdev, nullptr, &exts_count, nullptr); std::vector
props(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 會處理向
swapchain.cpp
公開執行個體或裝置擴充功能所需的基礎架構。初始變更清單不需要從 Vulkan 載入器正確設定擴充功能。 - 接著,請列舉格式和色彩空間組合:
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}); }
您必須瞭解相容的格式和色彩空間組合。
- 將新格式新增至位於
external/deqp
的dEQP-VK
。 - 您可以從現有來源推斷所需的變更,或向 Android 支援團隊尋求資訊,藉此更新
vktApiExternalMemoryTests.cpp
和vktExternalMemoryUtil.cpp
中的 Vulkan 相容性測試。
EGL 對新像素格式所做的變更
請依照下列方式更新 EGL:
- 在
getNativePixelFormat()
函式中,修改if-else
樹狀結構,以便傳回新像素格式的 AIDL 列舉。請參考RGBA_8888
像素格式的範例:if (a == 0) { ... } else { if (componentType == EGL_COLOR_COMPONENT_TYPE_FIXED_EXT) { if (colorDepth > 24) { ... } else { *format = PixelFormat::RGBA_8888; } } else { ... } }
- 如要在 dEQP 中新增格式,請在
androidFormats
列舉中新增項目,如下所示:static const GLenum androidFormats[] = { ... GL_RGBA8, ... };
提交更新
請按照「提供者」一節的說明,建立變更清單並與適當團隊分享。