เพิ่มรูปแบบพิกเซลใหม่ให้กับ Android

รูปแบบพิกเซลใหม่ทั้งหมดที่เพิ่มลงใน Android จะต้องรวมอยู่ใน Android Interface Definition Language (AIDL) และใน Android Hardware Buffer (AHB) AIDL และ AHB มีข้อกำหนดด้านเสถียรภาพและมาตรฐานที่เข้มงวด ซึ่งจำเป็นต้องมีกระบวนการที่ระมัดระวังเมื่อขยายฟังก์ชันการทำงาน รูปแบบพิกเซลใหม่ทั้งหมดจะต้องลงจอดใน AOSP และการอัปเดตทั้งหมดจะต้องได้รับการยืนยันเป็นรายบุคคลโดยผู้เชี่ยวชาญของ AIDL และ AHB กระบวนการยืนยันอย่างรอบคอบนี้เป็นปัจจัยสำคัญในการกำหนดมาตรฐานรูปแบบพิกเซลใหม่บนแพลตฟอร์ม

หน้านี้สรุปการเปลี่ยนแปลงโค้ด AOSP ที่จำเป็นและกระบวนการที่จำเป็นสำหรับการเพิ่มรูปแบบพิกเซลใหม่บน AOSP

ก่อนที่จะเพิ่มรูปแบบพิกเซลใหม่ ให้ดาวน์โหลดซอร์สและอัปโหลดแพตช์ตามที่ระบุไว้ใน การส่งแพตช์

เพิ่มรูปแบบพิกเซลใหม่ให้กับ AIDL

การเพิ่มการรองรับรูปแบบพิกเซลใหม่จำเป็นต้องเปลี่ยนแปลงไฟล์ PixelFormat.aidl ทั้งสองไฟล์ที่อยู่ใน AIDL ดู hardware/interfaces/graphics/common/aidl/ สำหรับซอร์สโค้ด AIDL

หากต้องการเพิ่มพิกเซลใหม่ที่เป็นทางการให้กับ AIDL ให้ทำตามขั้นตอนเหล่านี้:

  1. เพิ่มรูปแบบพิกเซลใหม่ต่อท้ายรายการใหม่ต่อท้าย PixelFormat enum ใน PixelFormat.aidl โดยปฏิบัติตามระเบียบโค้ดที่มีอยู่ และตั้งค่าเลขฐานสิบหกสำหรับรายการของคุณให้มากกว่ารายการก่อนหน้าหนึ่งรายการ จับคู่การเปลี่ยนแปลงรหัสของคุณกับรายการก่อนหน้า ดูตัวอย่างต่อไปนี้สำหรับรายการรูปแบบพิกเซล 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.
    
  2. หากต้องการล้างข้อผิดพลาดนี้ ให้รันคำสั่งต่อไปนี้ ตามที่ระบุไว้ในข้อความแสดงข้อผิดพลาด เพื่อเปลี่ยน PixelFormat.aidl ในไดเร็กทอรี aidl_api :

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

    การรันคำสั่งด้านบนจะอัพเดตไฟล์ที่ถูกต้องเพื่อให้สามารถสร้างได้ตามปกติ

เพิ่มรูปแบบพิกเซลใหม่ให้กับ AHB

การเพิ่มการรองรับรูปแบบพิกเซลใหม่จำเป็นต้องเปลี่ยนแปลง hardware_buffer.h และ AHardwareBuffer.cpp ดู frameworks/native/libs/nativewindow สำหรับซอร์สโค้ด AHB

หากต้องการเพิ่มพิกเซลใหม่อย่างเป็นทางการให้กับ AHB ให้ทำตามขั้นตอนเหล่านี้:

  1. ใน hardware_buffer.h ให้ผนวกรูปแบบพิกเซลใหม่เป็นรายการใหม่ที่ส่วนท้ายของ AHardwareBuffer_Format enum ปฏิบัติตามแบบแผนโค้ดที่มีอยู่

    ใช้ตัวอย่างรูปแบบพิกเซล 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

  2. เพิ่มรูปแบบพิกเซลในการทดสอบเสริมภายใต้ CTS หากมีรูปแบบ OpenGL ES ที่เกี่ยวข้อง เมื่อต้องการทำเช่นนี้ ให้เพิ่มรูปแบบ GL ใหม่ลงใน AHardwareBufferGLTest.cpp ใน AHBFormatAsString(int32_t format) พร้อมด้วย FORMAT_CASE(...) และ GL_FORMAT_CASE(...) สำหรับรูปแบบใหม่ ดังแสดงดังต่อไปนี้:

    const char* AHBFormatAsString(int32_t format) {
      switch (format) {
          ...
          FORMAT_CASE(R8G8B8A8_UNORM);
          ...
          GL_FORMAT_CASE(GL_RGB8);
      }
      return "";
    }
    
  3. ถัดไป เพิ่มการทดสอบใหม่ให้กับ 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 อย่างน้อยหนึ่งชุด เพิ่มค่าเพิ่มเติมหากจำเป็น

  4. ใน AHardwareBuffer.cpp ให้ค้นหาจุดสิ้นสุดของการยืนยันแบบคงที่ที่พบภายใน:

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

    ผนวก static_assert ใหม่สำหรับรูปแบบพิกเซลใหม่ โดยใช้ PixelFormat:: enum และไม่ใช่ด้วยค่าคงที่ HAL_PIXEL_FORMAT ใช้ตัวอย่างเดียวกันสำหรับรูปแบบพิกเซล RGBA_8888 จาก Add a new pixel format to AIDL ให้เพิ่มรายการรูปแบบพิกเซลใหม่ดังนี้:

    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. เพิ่มรูปแบบพิกเซลใหม่ให้กับการทดสอบที่เหมาะสม โดยเพิ่มรูปแบบพิกเซลใหม่ต่อท้าย PrintAhbFormat() ใน AHardwareBufferTest.cpp ปฏิบัติตามแบบแผนโค้ดที่มีอยู่ ดังที่แสดงด้านล่าง:

    void PrintAhbFormat(std::ostream& os, uint64_t format) {
        switch (format) {
            ...
            FORMAT_CASE(R8G8B8A8_UNORM);
            default: os << "unknown"; break;
        }
    }
    
  6. เพิ่มรูปแบบพิกเซลใหม่ให้กับ HardwareBuffer SDK ใน HardwareBuffer.java : โดยต่อท้ายรายการใหม่ไปที่ @IntDef ตัวอย่างเช่น รายการสำหรับรูปแบบ RGBA_8888 จะแสดงดังต่อไปนี้:

    @Retention(RetentionPolicy.SOURCE)
    @IntDef(prefix = { "RGB", "BLOB", "YCBCR_", "D_", "DS_", "S_" }, value = {
      ...
      RGBA_8888,
    })
    

    หากค่าส่วนประกอบไม่ได้รับการปรับให้เป็นมาตรฐาน ให้ระบุค่าอย่างชัดเจนในชื่อตัวแปร ตัวอย่างเช่น ชื่อตัวแปรสำหรับรูปแบบช่องสีแดง 16 บิตจำนวนเต็มที่ไม่ได้ลงนามเท่านั้น ต้องเป็น R_16UI และรูปแบบเดียวกันกับรูปแบบช่องสีเขียว 16 บิตจำนวนเต็มที่ไม่ได้ลงนามเพิ่มเติม ต้องเป็น RG_16UI16UI

  7. เพิ่มรูปแบบพิกเซลใหม่เป็น static int ใน HardwareBuffer.java โดยการต่อท้ายตัวแปรสมาชิกสาธารณะใหม่ที่ส่วนท้ายของ @Format :

    @Format
    ...
    /** Format: 8 bits each red, green, blue, alpha */
    public static final int RGBA_8888 = 0x1;
    

    รายการ enum นี้ต้องมีค่าฐานสิบหกเหมือนกับค่าจาก PixelFormat.aidl และ hardware_buffer.h ปฏิบัติตามอนุสัญญาที่มีอยู่

  8. การพยายามสร้างด้วยการเปลี่ยนแปลงโค้ดเหล่านี้ทำให้เกิดข้อผิดพลาดในการสร้าง:

    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
    

    การรันคำสั่งด้านบนจะอัพเดตไฟล์ที่ถูกต้องเพื่อให้สามารถสร้างได้ตามปกติ

  9. เพิ่มรูปแบบพิกเซลใหม่ให้กับการทดสอบ Java โดยการผนวกรูปแบบพิกเซลใหม่ต่อท้าย paramsForTestCreateOptionalFormats() ใน HardwareBufferTest.java ดังแสดงดังต่อไปนี้:

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

เพิ่มรูปแบบพิกเซลใหม่ให้กับการรวมระบบ Window

หากต้องการใช้รูปแบบพิกเซลใหม่เป็นรูปแบบสำหรับ framebuffer ใน API กราฟิก ให้เพิ่มลงใน Window System Integration (WSI) ที่เหมาะสมสำหรับ API กราฟิกที่เกี่ยวข้อง สำหรับแอปหรือกระบวนการของระบบที่ใช้ Vulkan API ให้อัปเดต Vulkan Swapchain สำหรับแอปหรือกระบวนการของระบบที่ใช้ OpenGL ES API ให้อัปเดต EGL API

การเปลี่ยนแปลง Vulkan WSI สำหรับรูปแบบพิกเซลใหม่

อัพเดต Vulkan WSI ดังต่อไปนี้:
  1. เพิ่มกรณีใหม่ให้กับฟังก์ชัน GetNativePixelFormat(VkFormat format) ใน 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. ค้นหาส่วนขยาย 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

  3. จากนั้น ระบุคู่รูปแบบและสเปซสี:
    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});
    }
    

    คุณต้องมีความรู้เกี่ยวกับคู่รูปแบบและสเปซสีที่เข้ากันได้

  4. เพิ่มรูปแบบใหม่ให้กับ dEQP-VK ซึ่งอยู่ที่ external/deqp
  5. อัปเดตการทดสอบความสอดคล้องของ Vulkan ใน vktApiExternalMemoryTests.cpp และ vktExternalMemoryUtil.cpp โดยการอนุมานการเปลี่ยนแปลงที่จำเป็นจากแหล่งที่มาที่มีอยู่หรือติดต่อฝ่ายสนับสนุน Android ของคุณเพื่อขอข้อมูล

การเปลี่ยนแปลง EGL สำหรับรูปแบบพิกเซลใหม่

อัพเดต EGL ดังนี้:

  1. ในฟังก์ชัน getNativePixelFormat() ให้แก้ไขแผนผัง if-else เพื่อส่งคืน AIDL enum สำหรับรูปแบบพิกเซลใหม่ ใช้ตัวอย่างสำหรับรูปแบบพิกเซล RGBA_8888 :
    if (a == 0) {
      ...
    } else {
      if (componentType == EGL_COLOR_COMPONENT_TYPE_FIXED_EXT) {
          if (colorDepth > 24) {
              ...
          } else {
              *format = PixelFormat::RGBA_8888;
          }
      } else {
        ...
      }
    }
    
  2. หากต้องการเพิ่มรูปแบบใหม่ให้กับ dEQP ให้เพิ่มรายการใหม่ลงใน androidFormats enum ซึ่งแสดงดังนี้:
    static const GLenum androidFormats[] =
    {
      ...
      GL_RGBA8,
      ...
    };
    

ส่งการอัปเดตของคุณ

ติดตาม สำหรับผู้มีส่วนร่วม เพื่อหมุนรายการการเปลี่ยนแปลงของคุณและแบ่งปันกับทีมที่เหมาะสม