Tất cả các định dạng pixel mới được thêm vào Android phải có trong Ngôn ngữ định nghĩa giao diện Android (AIDL) và trong Vùng đệm phần cứng Android (AHB). AIDL và AHB có các yêu cầu nghiêm ngặt về độ ổn định và tiêu chuẩn hoá, nên cần phải thực hiện một quy trình cẩn thận khi mở rộng chức năng. Tất cả định dạng pixel mới phải được đưa vào AOSP và tất cả bản cập nhật 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 kỹ lưỡng 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 định dạng pixel mới trên AOSP.
Trước khi thêm định dạng pixel mới, hãy tải nguồn xuống rồi tải bản vá lên như đã nêu 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ị hex cho mục của bạn lớn hơn một so với mục trước đó. So khớp các thay đổi về mã với các mục nhập trước đó. Hãy xem ví dụ sau đây cho mục nhập đị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,
Bạn sẽ thấy thông báo lỗi sau đây khi tạo mã sau khi thực hiện các thay đổi đối với
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.
-
Để 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
Việc chạy lệnh trên sẽ cập nhật đúng tệp để có thể tạo bản dựng 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 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 dưới dạng một mục mới vào cuối enumAHardwareBuffer_Format
. Hãy tuân theo các quy ước lập trình hiện có.Sử dụng ví dụ về định dạng pixel
RGBA_8888
, hãy thêm mục nhập đị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 chữ viết tắt của kênh và độ sâu bit, rồi kết thúc bằng mã hoá. Mục nhập enum này phải có cùng giá trị hex như giá trị trongPixelFormat.aidl
.Định dạng pixel dự kiến phải 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 khi thích hợp. Nếu không có định dạng liên kết nào, 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ó liên kết với định dạng OpenGL ES. Để 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ư sau: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 chương trình kiểm thử mới vào
AHardwareBufferGLTest.cpp
như sau: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 tập hợp 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 nhận định tĩnh có trong:// ---------------------------------------------------------------------------- // Validate hardware_buffer.h and PixelFormat.aidl agree // ----------------------------------------------------------------------------
Thêm
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
từ phần Thêm định dạng pixel mới vào AIDL, thêm mục nhập đị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 bài 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
. Hãy làm theo quy ước lập trình 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ẽ hiển thị như sau:@Retention(RetentionPolicy.SOURCE) @IntDef(prefix = { "RGB", "BLOB", "YCBCR_", "D_", "DS_", "S_" }, value = { ... RGBA_8888, })
Nếu giá trị thành phần không được chuẩn hoá chưa ký, hãy chỉ định giá trị một cách rõ ràng trong tên biến. Ví dụ: tên biến cho định dạng chỉ kênh màu đỏ 16 bit số nguyên chưa ký phải là
R_16UI
và cùng định dạng với định dạng kênh màu xanh lục 16 bit số nguyên chưa ký bổ sung 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 thêm một biến thành viê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 nhập enum này phải có cùng giá trị hex với giá trị của
PixelFormat.aidl
vàhardware_buffer.h
. Tuân theo các quy ước hiện có. -
Nếu cố gắng tạo bản dựng bằng các thay đổi mã này, bạn sẽ gặp lỗi bản dựng:
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. ****************************** ...
Để 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
Việc chạy lệnh trên sẽ cập nhật đúng tệp để có thể tạo bản dựng bình thường.
-
Thêm định dạng pixel mới vào các chương trình 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 tính năng 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 vùng đệm khung trong API đồ hoạ, hãy thêm định dạng đó vào dịch vụ 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 Chuỗi hoán đổi Vulkan. Đối với ứ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.
Thay đổi về Vulkan WSI cho các định dạng pixel mới
Cập nhật Vulkan WSI 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 các tiện ích bên, hãy sử dụng
instance_data
, như sau:bool colorspace_ext = instance_data.hook_extensions.test(ProcHook::EXT_swapchain_colorspace);
Đối với các tiện ích phía thiết bị, hãy sử dụng các thông tin 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 thực thể hoặc tiện ích thiết bị cho
swapchain.cpp
. Bạn không cần danh sách thay đổi ban đầu để thiết lập đúng cách 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 quy trình Kiểm thử tuân thủ Vulkan trong
vktApiExternalMemoryTests.cpp
vàvktExternalMemoryUtil.cpp
bằng cách suy luận các thay đổi bắt buộc từ nguồn hiện có hoặc liên hệ với nhóm hỗ trợ Android để biết thông tin.
Thay đổi của EGL đối với các đị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 nội dung cập nhật
Hãy làm theo phần Dành cho cộng tác viên để tạo danh sách thay đổi và chia sẻ với nhóm thích hợp.