Thêm các định dạng pixel mới vào Android

Tất cả các định dạng pixel mới được thêm vào Android phải được đưa vào 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 hóa, đòi hỏi phải có 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 phải có trong AOSP và tất cả cá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ẻ. Quá 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 hóa mọi định dạng pixel mới trên nền tảng.

Trang này phác thảo những thay đổi mã AOSP cần thiết 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 định dạng pixel mới, hãy tải xuống nguồn và tải lên các bản vá như được nêu trong Gửi bản vá .

Thêm định dạng pixel mới vào AIDL

Việc thêm hỗ trợ cho định dạng pixel mới yêu cầu thay đổi đối với cả hai tệp PixelFormat.aidl nằm trong AIDL. Xem hardware/interfaces/graphics/common/aidl/ để biết mã nguồn AIDL.

Để thêm pixel chính thức mới vào AIDL, hãy làm theo các bước sau:

  1. Thêm định dạng pixel mới dưới dạng mục nhập mới vào cuối enum PixelFormat trong PixelFormat.aidl bằng cách tuân theo quy ước mã hiện có và đặt giá trị hex cho mục nhập của bạn lớn hơn một mục nhập trước đó. Khớp các thay đổi mã của bạn với các mục trước đó. Xem ví dụ sau để biết mục nhập định dạng pixel 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,
    

    Thông báo lỗi sau đây xuất hiện khi bạn 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.
    
  2. Để xóa 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ục aidl_api :

    m android.hardware.graphics.common-update-api
    

    Chạy lệnh trên sẽ cập nhật đúng file để có thể build bình thường.

Thêm định dạng pixel mới vào AHB

Việc thêm hỗ trợ cho định dạng pixel mới yêu cầu thay đổi đối với hardware_buffer.hAHardwareBuffer.cpp . Xem frameworks/native/libs/nativewindow để biết mã nguồn AHB.

Để thêm pixel chính thức mới vào AHB, hãy làm theo các bước sau:

  1. Trong hardware_buffer.h , hãy thêm định dạng pixel mới làm mục nhập mới vào cuối enum AHardwareBuffer_Format . Thực hiện theo các quy ước mã hiện có.

    Sử dụng ví dụ về định dạng pixel RGBA_8888 , 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,
    

    Lưu ý rằng định dạng pixel mới được đặt tên bằng AHB, tên này phải bắt đầu bằng AHARDWAREBUFFER_FORMAT_ , theo sau là tên viết tắt của kênh và độ sâu bit và kết thúc bằng mã hóa. Mục nhập enum này phải có cùng giá trị hex như trong PixelFormat.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 liên quan khi thích hợp. Nếu không có định dạng liên quan nào tồn tại, hãy chỉ định N/A .

  2. Thêm định dạng pixel vào thử nghiệm tùy chọn trong CTS, nếu nó có định dạng OpenGL ES được 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 trong AHBFormatAsString(int32_t format) với FORMAT_CASE(...)GL_FORMAT_CASE(...) cho định dạng mới, được hiển thị như sau:

    const char* AHBFormatAsString(int32_t format) {
      switch (format) {
          ...
          FORMAT_CASE(R8G8B8A8_UNORM);
          ...
          GL_FORMAT_CASE(GL_RGB8);
      }
      return "";
    }
    
  3. Tiếp theo, thêm một thử nghiệm mới vào AHardwareBufferGLTest.cpp , hiển thị 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 bộ giá trị AHardwareBuffer_Desc . Thêm nhiều giá trị hơn nếu cần.

  4. Trong AHardwareBuffer.cpp , tìm phần cuối của các xác nhận tĩnh được tìm thấy trong:

    // ----------------------------------------------------------------------------
    // Validate hardware_buffer.h and PixelFormat.aidl agree
    // ----------------------------------------------------------------------------
    

    Thêm một static_assert mới cho định dạng pixel mới, sử dụng PixelFormat:: enum chứ không phải với hằng số HAL_PIXEL_FORMAT . Sử dụng ví dụ tương tự cho định dạng pixel RGBA_8888 từ 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");
    
  5. Thêm định dạng pixel mới vào các thử nghiệm thích hợp bằng cách thêm định dạng pixel mới vào cuối PrintAhbFormat() trong AHardwareBufferTest.cpp . Thực hiện theo quy ước mã hiện có, như được hiển thị bên dưới:

    void PrintAhbFormat(std::ostream& os, uint64_t format) {
        switch (format) {
            ...
            FORMAT_CASE(R8G8B8A8_UNORM);
            default: os << "unknown"; break;
        }
    }
    
  6. Thêm định dạng pixel mới vào SDK HardwareBuffer trong HardwareBuffer.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ạng RGBA_8888 được hiển thị 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 hóa không dấu thì hãy chỉ ra 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 không dấu phải là R_16UI và định dạng tương tự với định dạng kênh màu xanh lục 16 bit số nguyên không dấu bổ sung phải là RG_16UI16UI .

  7. Thêm định dạng pixel mới dưới dạng static int trong HardwareBuffer.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ị hex từ PixelFormat.aidlhardware_buffer.h . Thực hiện theo các quy ước hiện có.

  8. Việc cố gắng xây dựng bằng những thay đổi mã này sẽ tạo ra lỗi xây 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.
    ******************************
    ...
    

    Để xóa 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
    

    Chạy lệnh trên sẽ cập nhật đúng file để có thể build bình thường.

  9. Thêm định dạng pixel mới vào các thử nghiệm Java, bằng cách thêm định dạng pixel mới vào cuối paramsForTestCreateOptionalFormats() trong HardwareBufferTest.java , được hiển thị như sau:

    private static Object[] paramsForTestCreateOptionalFormats() {
      return new Integer[]{
          HardwareBuffer.RGBA_8888
      };
    

Thêm định dạng pixel mới vào 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 đồ họa, hãy thêm nó vào Tích hợp hệ thống cửa sổ (WSI) thích hợp cho API đồ họa 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 .

Vulkan WSI thay đổi cho các định dạng pixel mới

Cập nhật Vulkan WSI như sau:
  1. Thêm một trường hợp mới vào hàm GetNativePixelFormat(VkFormat format) trong swapchain.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;
    }
    
  2. Truy vấn tiện ích mở rộng Vulkan nếu định dạng pixel yêu cầu tiện ích mở rộng Vulkan hoạt động. Đối với các phần mở rộng bên của phiên bản, hãy sử dụng instance_data , được hiển thị như sau:
    bool colorspace_ext = instance_data.hook_extensions.test(ProcHook::EXT_swapchain_colorspace);
    

    Đối với tiện ích mở rộng phía thiết bị, hãy sử dụng như 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 mở rộng thiết bị cho swapchain.cpp . Danh sách thay đổi ban đầu không bắt buộc phải có các tiện ích mở rộng được thiết lập chính xác từ trình tải Vulkan.

  3. Tiếp theo, 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.

  4. Thêm định dạng mới vào dEQP-VK nằm ở external/deqp .
  5. Cập nhật Kiểm tra sự phù hợp của Vulkan trong vktApiExternalMemoryTests.cppvktExternalMemoryUtil.cpp bằng cách suy ra những thay đổi bắt buộc từ nguồn hiện có hoặc liên hệ với bộ phận hỗ trợ Android của bạn để biết thông tin.

Thay đổi EGL cho các định dạng pixel mới

Cập nhật EGL như sau:

  1. Trong hàm getNativePixelFormat() , hãy sửa đổi cây if-else để trả về enum AIDL cho định dạng pixel mới. Sử dụng ví dụ cho định dạng pixel RGBA_8888 :
    if (a == 0) {
      ...
    } else {
      if (componentType == EGL_COLOR_COMPONENT_TYPE_FIXED_EXT) {
          if (colorDepth > 24) {
              ...
          } else {
              *format = PixelFormat::RGBA_8888;
          }
      } else {
        ...
      }
    }
    
  2. Để thêm định dạng mới vào dEQP, hãy thêm mục nhập mới vào enum androidFormats , hiển thị như sau:
    static const GLenum androidFormats[] =
    {
      ...
      GL_RGBA8,
      ...
    };
    

Gửi bản cập nhật của bạn

Theo dõi Dành cho những người đóng góp để cập nhật danh sách thay đổi của bạn và chia sẻ chúng với nhóm thích hợp.