Tất cả các định dạng pixel mới được thêm vào Android đều phải có trong Ngôn ngữ định nghĩa giao diện Android (AIDL) và trong Bộ đệm phần cứng Android (AHB). AIDL và AHB có các yêu cầu nghiêm ngặt về tính ổn định và tiêu chuẩn hoá, đòi hỏi một quy trình cẩn thận khi mở rộng chức năng. Tất cả các định dạng pixel mới đều phải nằm trong AOSP và tất cả các bản cập nhật đều phải được các chuyên gia AIDL và AHB xác nhận riêng lẻ. Quy trình xác nhận cẩn thận này là một yếu tố quan trọng trong việc chuẩn hoá mọi định dạng pixel mới trên nền tảng.
Trang này trình bày những thay đổi cần thiết về mã AOSP và quy trình cần thiết để thêm các định dạng pixel mới trên AOSP.
Trước khi thêm một định dạng pixel mới, hãy tải nguồn xuống và tải các bản vá lên như mô tả trong phần Gửi bản vá.Thêm định dạng pixel mới vào AIDL
Để thêm tính năng hỗ trợ cho một định dạng pixel mới, bạn cần thay đổi cả hai tệp PixelFormat.aidl
nằm trong AIDL. Hãy xem hardware/interfaces/graphics/common/aidl/
để biết mã nguồn AIDL.
Để thêm một pixel mới vào AIDL, hãy làm theo các bước sau:
- Nối định dạng pixel mới dưới dạng một mục mới vào cuối enum
PixelFormat
trongPixelFormat.aidl
bằng cách làm theo quy ước mã hiện có và đặt giá trị thập lục phân cho mục của bạn nhiều hơn một so với mục trước đó. Đối chiếu các thay đổi về mã với các mục nhập trước đó. Hãy xem ví dụ sau đây về mục định dạng pixelRGBA_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,
Thông báo lỗi sau đây sẽ xuất hiện khi bạn tạo mã sau khi thay đổi
PixelFormat.aidl
: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.
-
Để xoá lỗi này, hãy chạy lệnh sau (như được chỉ định trong thông báo lỗi) để thay đổi
PixelFormat.aidl
trong thư mụcaidl_api
:m android.hardware.graphics.common-update-api
Khi chạy lệnh trên, tệp chính xác sẽ được cập nhật để có thể tạo bản dựng một cách bình thường.
Thêm định dạng pixel mới vào AHB
Để thêm tính năng hỗ trợ cho một định dạng pixel mới, bạn cần thay đổi hardware_buffer.h
và AHardwareBuffer.cpp
.
Hãy xem frameworks/native/libs/nativewindow
để biết mã nguồn AHB.
Để thêm một định dạng pixel mới vào AHB, hãy làm theo các bước sau:
- Trong
hardware_buffer.h
, hãy thêm định dạng pixel mới làm một mục mới vào cuối enumAHardwareBuffer_Format
. Tuân thủ các quy ước hiện có về mã.Sử dụng ví dụ về định dạng pixel
RGBA_8888
, hãy thêm mục định dạng pixel mới như sau:/** * Corresponding formats: * Vulkan: VK_FORMAT_R8G8B8A8_UNORM * OpenGL ES: GL_RGBA8 */ AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM = 1,
Xin lưu ý rằng định dạng pixel mới được đặt tên trong AHB, tên này phải bắt đầu bằng
AHARDWAREBUFFER_FORMAT_
, theo sau là các từ viết tắt của kênh và độ sâu bit, đồng thời kết thúc bằng mã hoá. Mục enum này phải có cùng giá trị thập lục phân với giá trị trongPixelFormat.aidl
.Định dạng pixel dự kiến sẽ có một hoặc cả hai định dạng Vulkan hoặc OpenGL ES được liên kết. Chỉ định định dạng được liên kết (nếu có). Nếu không có định dạng nào được liên kết, hãy chỉ định
N/A
. -
Thêm định dạng pixel vào quy trình kiểm thử không bắt buộc trong CTS, nếu định dạng đó có định dạng OpenGL ES liên kết. Để thực hiện việc này, hãy thêm định dạng GL mới vào
AHardwareBufferGLTest.cpp
trongAHBFormatAsString(int32_t format)
bằngFORMAT_CASE(...)
vàGL_FORMAT_CASE(...)
cho định dạng mới, như minh hoạ dưới đây:const char* AHBFormatAsString(int32_t format) { switch (format) { ... FORMAT_CASE(R8G8B8A8_UNORM); ... GL_FORMAT_CASE(GL_RGB8); } return ""; }
-
Tiếp theo, hãy thêm một kiểm thử mới vào
AHardwareBufferGLTest.cpp
, như minh hoạ dưới đây: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);
Chỉ định ít nhất một nhóm giá trị
AHardwareBuffer_Desc
. Thêm các giá trị khác nếu cần. -
Trong
AHardwareBuffer.cpp
, hãy tìm phần cuối của các câu lệnh xác nhận tĩnh có trong:// ---------------------------------------------------------------------------- // Validate hardware_buffer.h and PixelFormat.aidl agree // ----------------------------------------------------------------------------
Nối một
static_assert
mới cho định dạng pixel mới, sử dụng enumPixelFormat::
chứ không phải hằng sốHAL_PIXEL_FORMAT
. Sử dụng cùng một ví dụ cho định dạng pixelRGBA_8888
trong phần Thêm định dạng pixel mới vào AIDL, hãy thêm mục định dạng pixel mới như sau:static_assert(static_cast
(aidl::android::hardware::graphics::common::PixelFormat::RGBA_8888) == AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM, "HAL and AHardwareBuffer pixel format don't match"); -
Thêm định dạng pixel mới vào các kiểm thử thích hợp bằng cách thêm định dạng pixel mới vào cuối
PrintAhbFormat()
trongAHardwareBufferTest.cpp
. Tuân theo quy ước mã hiện có, như minh hoạ dưới đây:void PrintAhbFormat(std::ostream& os, uint64_t format) { switch (format) { ... FORMAT_CASE(R8G8B8A8_UNORM); default: os << "unknown"; break; } }
-
Thêm định dạng pixel mới vào SDK
HardwareBuffer
trongHardwareBuffer.java
: bằng cách thêm một mục mới vào@IntDef
. Ví dụ: mục nhập cho định dạngRGBA_8888
sẽ xuất hiện như sau:@Retention(RetentionPolicy.SOURCE) @IntDef(prefix = { "RGB", "BLOB", "YCBCR_", "D_", "DS_", "S_" }, value = { ... RGBA_8888, })
Nếu các giá trị thành phần không được chuẩn hoá chưa ký, hãy chỉ rõ giá trị trong tên biến. Ví dụ: tên biến cho định dạng chỉ có kênh màu đỏ 16 bit là số nguyên không dấu phải là
R_16UI
và định dạng tương tự có thêm định dạng kênh màu xanh lục 16 bit là số nguyên không dấu phải làRG_16UI16UI
. -
Thêm định dạng pixel mới dưới dạng
static int
trongHardwareBuffer.java
, bằng cách nối một biến thành phần công khai mới vào cuối@Format
:@Format ... /** Format: 8 bits each red, green, blue, alpha */ public static final int RGBA_8888 = 0x1;
Mục enum này phải có cùng giá trị thập lục phân với giá trị trong
PixelFormat.aidl
vàhardware_buffer.h
. Tuân theo các quy ước hiện có. -
Nếu cố gắng tạo bằng những thay đổi về mã này, bạn sẽ gặp lỗi khi tạo:
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. ****************************** ...
Để xoá lỗi này, hãy chạy lệnh sau (như được chỉ định trong thông báo lỗi) để thay đổi
current.txt
:m api-stubs-docs-non-updatable-update-current-api
Khi chạy lệnh trên, tệp chính xác sẽ được cập nhật để có thể tạo bản dựng một cách bình thường.
-
Thêm định dạng pixel mới vào các kiểm thử Java bằng cách thêm định dạng pixel mới vào cuối
paramsForTestCreateOptionalFormats()
trongHardwareBufferTest.java
, như sau:private static Object[] paramsForTestCreateOptionalFormats() { return new Integer[]{ HardwareBuffer.RGBA_8888 };
Thêm định dạng pixel mới vào chế độ tích hợp Hệ thống cửa sổ
Để sử dụng định dạng pixel mới làm định dạng cho bộ đệm khung trong API đồ hoạ, hãy thêm định dạng đó vào chế độ Tích hợp hệ thống cửa sổ (WSI) thích hợp cho API đồ hoạ có liên quan. Đối với một ứng dụng hoặc quy trình hệ thống sử dụng API Vulkan, hãy cập nhật Vulkan Swapchain. Đối với một ứng dụng hoặc quy trình hệ thống sử dụng API OpenGL ES, hãy cập nhật API EGL.
Các thay đổi về WSI của Vulkan đối với các định dạng pixel mới
Cập nhật WSI Vulkan như sau:-
Thêm một trường hợp mới vào hàm
GetNativePixelFormat(VkFormat format)
trongswapchain.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; }
- Truy vấn tiện ích Vulkan nếu định dạng pixel yêu cầu tiện ích Vulkan hoạt động.
Đối với tiện ích bên, hãy sử dụng
instance_data
, như minh hoạ dưới đây:bool colorspace_ext = instance_data.hook_extensions.test(ProcHook::EXT_swapchain_colorspace);
Đối với các tiện ích bên thiết bị, hãy sử dụng những tiện ích sau:
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 xử lý cơ sở hạ tầng cần thiết để hiển thị một phiên bản hoặc tiện ích thiết bị cho
swapchain.cpp
. Danh sách thay đổi ban đầu không bắt buộc phải thiết lập đúng các tiện ích từ trình tải Vulkan. - Tiếp theo, hãy liệt kê các cặp định dạng và không gian màu:
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}); }
Bạn phải có kiến thức về các cặp định dạng và không gian màu tương thích.
- Thêm định dạng mới vào
dEQP-VK
nằm tạiexternal/deqp
. - Cập nhật các Bài kiểm tra mức độ tuân thủ Vulkan trong
vktApiExternalMemoryTests.cpp
vàvktExternalMemoryUtil.cpp
bằng cách suy luận những thay đổi cần thiết từ nguồn hiện có hoặc liên hệ với nhóm hỗ trợ Android để biết thông tin.
Các thay đổi về EGL đối với định dạng pixel mới
Cập nhật EGL như sau:
- Trong hàm
getNativePixelFormat()
, hãy sửa đổi câyif-else
để trả về enum AIDL cho định dạng pixel mới. Sử dụng ví dụ cho định dạng pixelRGBA_8888
:if (a == 0) { ... } else { if (componentType == EGL_COLOR_COMPONENT_TYPE_FIXED_EXT) { if (colorDepth > 24) { ... } else { *format = PixelFormat::RGBA_8888; } } else { ... } }
- Để thêm định dạng mới vào dEQP, hãy thêm một mục mới vào enum
androidFormats
, như sau:static const GLenum androidFormats[] = { ... GL_RGBA8, ... };
Gửi thông tin cập nhật
Làm theo hướng dẫn trong phần Dành cho cộng tác viên để tạo danh sách thay đổi và chia sẻ danh sách đó với nhóm phù hợp.