Menambahkan format piksel baru ke Android

Semua format piksel baru yang ditambahkan ke Android harus disertakan dalam Android Interface Definition Language (AIDL) dan dalam Android Hardware Buffer (AHB). AIDL dan AHB memiliki persyaratan standarisasi dan stabilitas yang ketat yang memerlukan proses yang cermat saat memperluas fungsi. Semua format piksel baru harus diluncurkan di AOSP dan semua update harus dikonfirmasi satu per satu oleh pakar AIDL dan AHB. Proses konfirmasi yang cermat ini merupakan faktor penting dalam menstandarkan format piksel baru di platform.

Halaman ini menguraikan perubahan kode AOSP yang diperlukan dan proses yang diperlukan untuk menambahkan format piksel baru di AOSP.

Sebelum menambahkan format piksel baru, download sumber dan upload patch seperti yang diuraikan dalam Mengirim patch.

Menambahkan format piksel baru ke AIDL

Menambahkan dukungan untuk format piksel baru memerlukan perubahan pada kedua file PixelFormat.aidl yang berada dalam AIDL. Lihat hardware/interfaces/graphics/common/aidl/ untuk kode sumber AIDL.

Untuk menambahkan formal piksel baru ke AIDL, ikuti langkah-langkah berikut:

  1. Tambahkan format piksel baru sebagai entri baru ke akhir enum PixelFormat di PixelFormat.aidl dengan mengikuti konvensi kode yang ada dan menetapkan nilai hex untuk entri Anda menjadi satu lebih banyak dari entri sebelumnya. Cocokkan perubahan kode Anda dengan entri sebelumnya. Lihat contoh berikut untuk entri format piksel 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,
    

    Pesan error berikut terlihat saat Anda mem-build kode setelah melakukan perubahan pada 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. Untuk menghapus error ini, jalankan perintah berikut, seperti yang ditentukan dalam pesan error, untuk mengubah PixelFormat.aidl di direktori aidl_api:

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

    Dengan menjalankan perintah di atas, file yang benar akan diperbarui agar dapat di-build secara normal.

Menambahkan format piksel baru ke AHB

Menambahkan dukungan untuk format piksel baru memerlukan perubahan pada hardware_buffer.h dan AHardwareBuffer.cpp. Lihat frameworks/native/libs/nativewindow untuk kode sumber AHB.

Untuk menambahkan piksel formal baru ke AHB, ikuti langkah-langkah berikut:

  1. Di hardware_buffer.h, tambahkan format piksel baru sebagai entri baru ke akhir enum AHardwareBuffer_Format. Ikuti konvensi kode yang ada.

    Dengan menggunakan contoh format piksel RGBA_8888, tambahkan entri format piksel baru sebagai berikut:

    /**
     * Corresponding formats:
     *   Vulkan: VK_FORMAT_R8G8B8A8_UNORM
     *   OpenGL ES: GL_RGBA8
     */
    AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM = 1,
    

    Perhatikan bahwa format piksel baru diberi nama di AHB, yang harus dimulai dengan AHARDWAREBUFFER_FORMAT_, diikuti dengan singkatan saluran dan kedalaman bit, dan diakhiri dengan encoding. Entri enum ini harus memiliki nilai heksadesimal yang sama dengan yang ada di PixelFormat.aidl.

    Format piksel diharapkan memiliki satu atau kedua format Vulkan atau OpenGL ES terkait. Tentukan format terkait jika perlu. Jika tidak ada format terkait, tentukan N/A.

  2. Tambahkan format piksel ke pengujian opsional di CTS, jika memiliki format OpenGL ES terkait. Untuk melakukannya, tambahkan format GL baru ke AHardwareBufferGLTest.cpp dalam AHBFormatAsString(int32_t format) dengan FORMAT_CASE(...) dan GL_FORMAT_CASE(...) untuk format baru, yang ditampilkan sebagai berikut:

    const char* AHBFormatAsString(int32_t format) {
      switch (format) {
          ...
          FORMAT_CASE(R8G8B8A8_UNORM);
          ...
          GL_FORMAT_CASE(GL_RGB8);
      }
      return "";
    }
    
  3. Selanjutnya, tambahkan pengujian baru ke AHardwareBufferGLTest.cpp, yang ditampilkan sebagai berikut:

    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);
    

    Tentukan minimal satu kumpulan nilai AHardwareBuffer_Desc. Tambahkan nilai lainnya jika diperlukan.

  4. Di AHardwareBuffer.cpp, temukan akhir pernyataan statis yang ditemukan dalam:

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

    Tambahkan static_assert baru untuk format piksel baru, menggunakan enum PixelFormat::, bukan dengan konstanta HAL_PIXEL_FORMAT. Dengan menggunakan contoh yang sama untuk format piksel RGBA_8888 dari Menambahkan format piksel baru ke AIDL, tambahkan entri format piksel baru sebagai berikut:

    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. Tambahkan format piksel baru ke pengujian yang sesuai, dengan menambahkan format piksel baru ke akhir PrintAhbFormat() di AHardwareBufferTest.cpp. Ikuti konvensi kode yang ada, seperti yang ditunjukkan di bawah:

    void PrintAhbFormat(std::ostream& os, uint64_t format) {
        switch (format) {
            ...
            FORMAT_CASE(R8G8B8A8_UNORM);
            default: os << "unknown"; break;
        }
    }
    
  6. Tambahkan format piksel baru ke HardwareBuffer SDK di HardwareBuffer.java: dengan menambahkan entri baru ke @IntDef. Misalnya, entri untuk format RGBA_8888 ditampilkan sebagai berikut:

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

    Jika nilai komponen tidak dinormalisasi tanpa tanda tangan, tunjukkan nilai secara eksplisit dalam nama variabel. Misalnya, nama variabel untuk format khusus saluran merah bilangan bulat tanpa tanda tangan 16-bit harus R_16UI, dan format yang sama dengan format saluran hijau bilangan bulat tanpa tanda tangan 16-bit tambahan harus RG_16UI16UI.

  7. Tambahkan format piksel baru sebagai static int di HardwareBuffer.java, dengan menambahkan variabel anggota publik baru di akhir @Format:

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

    Entri enum ini harus memiliki nilai heksadesimal yang sama dengan nilai dari PixelFormat.aidl dan hardware_buffer.h. Ikuti konvensi yang ada.

  8. Mencoba mem-build dengan perubahan kode ini akan menghasilkan error build:

    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.
    ******************************
    ...
    

    Untuk menghapus error ini, jalankan perintah berikut, seperti yang ditentukan dalam pesan error, untuk mengubah current.txt:

    m api-stubs-docs-non-updatable-update-current-api
    

    Dengan menjalankan perintah di atas, file yang benar akan diperbarui agar dapat di-build secara normal.

  9. Tambahkan format piksel baru ke pengujian Java, dengan menambahkan format piksel baru ke akhir paramsForTestCreateOptionalFormats() di HardwareBufferTest.java, yang ditampilkan sebagai berikut:

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

Menambahkan format piksel baru ke integrasi Sistem Jendela

Untuk menggunakan format piksel baru sebagai format untuk framebuffer dalam API grafis, tambahkan ke Window System Integration (WSI) yang sesuai untuk API grafis yang relevan. Untuk proses aplikasi atau sistem yang menggunakan Vulkan API, update Swapchain Vulkan. Untuk proses aplikasi atau sistem yang menggunakan OpenGL ES API, update EGL API.

Perubahan WSI Vulkan untuk format piksel baru

Perbarui WSI Vulkan sebagai berikut:
  1. Tambahkan kasus baru ke fungsi GetNativePixelFormat(VkFormat format) di 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. Buat kueri ekstensi Vulkan jika format piksel memerlukan ekstensi Vulkan agar dapat berfungsi. Misalnya, ekstensi sisi, gunakan instance_data, yang ditampilkan sebagai berikut:
    bool colorspace_ext = instance_data.hook_extensions.test(ProcHook::EXT_swapchain_colorspace);
    

    Untuk ekstensi sisi perangkat, gunakan hal berikut:

    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 menangani infrastruktur yang diperlukan untuk mengekspos instance atau ekstensi perangkat ke swapchain.cpp. Daftar perubahan awal tidak diperlukan agar ekstensi disiapkan dengan benar dari loader Vulkan.

  3. Selanjutnya, hitung pasangan format dan ruang warna:
    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});
    }
    

    Anda harus memiliki pengetahuan tentang pasangan format dan ruang warna yang kompatibel.

  4. Tambahkan format baru ke dEQP-VK yang terletak di external/deqp.
  5. Perbarui Pengujian Kepatuhan Vulkan di vktApiExternalMemoryTests.cpp dan vktExternalMemoryUtil.cpp dengan menyimpulkan perubahan yang diperlukan dari sumber yang ada atau menghubungi dukungan Android untuk mendapatkan informasi.

Perubahan EGL untuk format piksel baru

Update EGL sebagai berikut:

  1. Dalam fungsi getNativePixelFormat(), ubah hierarki if-else untuk menampilkan enum AIDL untuk format piksel baru. Menggunakan contoh untuk format piksel RGBA_8888:
    if (a == 0) {
      ...
    } else {
      if (componentType == EGL_COLOR_COMPONENT_TYPE_FIXED_EXT) {
          if (colorDepth > 24) {
              ...
          } else {
              *format = PixelFormat::RGBA_8888;
          }
      } else {
        ...
      }
    }
    
  2. Untuk menambahkan format baru ke dEQP, tambahkan entri baru ke enum androidFormats, yang ditunjukkan sebagai berikut:
    static const GLenum androidFormats[] =
    {
      ...
      GL_RGBA8,
      ...
    };
    

Kirim pembaruan Anda

Ikuti Untuk kontributor untuk membuat daftar perubahan dan membagikannya kepada tim yang sesuai.