Android'e yeni piksel biçimleri ekleme

Android'e eklenen tüm yeni piksel biçimleri Android Arayüz Tanımlama Dili'ne (AIDL) ve Android Donanım Arabelleği'ne (AHB) dahil edilmelidir. AIDL ve AHB, işlevselliğin kapsamını genişletirken dikkatli bir süreç gerektiren katı kararlılık ve standartlaştırma şartlarına sahiptir. Tüm yeni piksel biçimleri AOSP'ye eklenmeli ve tüm güncellemeler AIDL ve AHB uzmanları tarafından ayrı ayrı onaylanmalıdır. Bu dikkatli onaylama süreci, platformdaki yeni piksel biçimlerini standartlaştırmada önemli bir faktördür.

Bu sayfada, gerekli AOSP kodu değişiklikleri ve AOSP'ye yeni piksel biçimleri eklemek için gereken süreç özetlenmektedir.

Yeni bir piksel biçimi eklemeden önce kaynağı indirin ve yama gönderme bölümünde açıklandığı şekilde yamaları yükleyin.

AIDL'ye yeni bir piksel biçimi ekleme

Yeni bir piksel biçimi için destek eklemek, AIDL'de bulunan her iki PixelFormat.aidl dosyasında da değişiklik yapılmasını gerektirir. AIDL kaynak kodu için hardware/interfaces/graphics/common/aidl/ adresine bakın.

AIDL'ye yeni bir piksel resmi eklemek için şu adımları izleyin:

  1. Mevcut kod kuralını uygulayarak ve girişinizin onaltılık değerini önceki girişten bir fazla olacak şekilde ayarlayarak yeni piksel biçimini PixelFormat.aidl içindeki PixelFormat enum'un sonuna yeni bir giriş olarak ekleyin. Kod değişikliklerinizi önceki girişlerle eşleştirin. RGBA_8888 piksel biçimi girişi için aşağıdaki örneğe bakın:
    /**
     * 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 dosyasında değişiklik yaptıktan sonra kodu derlediğinizde aşağıdaki hata mesajı gösterilir:

    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. Bu hatayı düzeltmek için hata mesajında belirtildiği gibi aşağıdaki komutu çalıştırarak aidl_api dizininde PixelFormat.aidl değerini değiştirin:

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

    Yukarıdaki komutu çalıştırarak normal şekilde derlenebilmesi için doğru dosyayı güncelleyin.

AHB'ye yeni bir piksel biçimi ekleme

Yeni bir piksel biçimi için destek eklemek hardware_buffer.h ve AHardwareBuffer.cpp dosyalarında değişiklik yapılmasını gerektirir. AHB kaynak kodu için frameworks/native/libs/nativewindow bölümünü inceleyin.

AHB'ye yeni bir piksel biçimi eklemek için aşağıdaki adımları uygulayın:

  1. hardware_buffer.h içinde, yeni piksel biçimini AHardwareBuffer_Format enum'unun sonuna yeni bir giriş olarak ekleyin. Mevcut kod kurallarına uyun.

    RGBA_8888 piksel biçimi örneğini kullanarak yeni piksel biçimi girişini aşağıdaki gibi ekleyin:

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

    Yeni piksel biçimine AHB'de bir ad verildiğini unutmayın. Bu ad AHARDWAREBUFFER_FORMAT_ ile başlamalı, ardından kanal kısaltmaları ve bit derinlikleri gelmelidir. Ardından kodlama gelmelidir. Bu enum girişi, PixelFormat.aidl ile aynı onaltılık değere sahip olmalıdır.

    Piksel biçiminin, ilişkili bir Vulkan veya OpenGL ES biçiminin birine veya her ikisine de sahip olması beklenir. Gerektiğinde ilişkili biçimi belirtin. İlişkili bir biçim yoksa N/A değerini belirtin.

  2. Piksel biçimini, ilişkili bir OpenGL ES biçimi varsa CTS altındaki isteğe bağlı testlere ekleyin. Bunu yapmak için yeni GL biçimini AHBFormatAsString(int32_t format) içindeki AHardwareBufferGLTest.cpp alanına FORMAT_CASE(...) ve yeni biçim için GL_FORMAT_CASE(...) ile ekleyin. Aşağıda gösterildiği gibi:

    const char* AHBFormatAsString(int32_t format) {
      switch (format) {
          ...
          FORMAT_CASE(R8G8B8A8_UNORM);
          ...
          GL_FORMAT_CASE(GL_RGB8);
      }
      return "";
    }
    
  3. Daha sonra, AHardwareBufferGLTest.cpp uygulamasına aşağıdaki gibi yeni bir test ekleyin:

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

    En az bir AHardwareBuffer_Desc değer grubu belirtin. Gerekirse daha fazla değer ekleyin.

  4. AHardwareBuffer.cpp işlevinde, aşağıda bulunan statik onaylamaların sonunu bulun:

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

    Yeni piksel biçimi için HAL_PIXEL_FORMAT sabit değerini değil, PixelFormat:: enum değerini kullanarak yeni bir static_assert ekleyin. AIDL'ye yeni piksel biçimi ekleme bölümündeki RGBA_8888 piksel biçimi örneğini kullanarak yeni piksel biçimi girişini aşağıdaki gibi ekleyin:

    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. Yeni piksel biçimini AHardwareBufferTest.cpp içindeki PrintAhbFormat() öğesinin sonuna ekleyerek uygun testlere ekleyin. Aşağıda gösterildiği gibi mevcut kod kurallarını uygulayın:

    void PrintAhbFormat(std::ostream& os, uint64_t format) {
        switch (format) {
            ...
            FORMAT_CASE(R8G8B8A8_UNORM);
            default: os << "unknown"; break;
        }
    }
    
  6. Yeni piksel biçimini HardwareBuffer.java'deki HardwareBuffer SDK'sına ekleyin: @IntDef'e yeni bir giriş ekleyerek. Örneğin, RGBA_8888 biçimi için giriş aşağıdaki gibi gösterilir:

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

    Bileşen değerleri imzalanmamışsa normalleştirilmemişse değeri değişken adında açıkça belirtin. Örneğin, işaretsiz tam sayı 16 bit yalnızca kırmızı kanal biçiminin değişken adı R_16UI, ek bir işaretsiz tam sayı 16 bit yeşil kanal biçimi içeren aynı biçimin adı ise RG_16UI16UI olmalıdır.

  7. @Format'in sonuna yeni bir herkese açık üye değişkeni ekleyerek yeni piksel biçimini HardwareBuffer.java içinde static int olarak ekleyin:

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

    Bu enum girişi, PixelFormat.aidl ve hardware_buffer.h ile aynı onaltılık değere sahip olmalıdır. Mevcut kurallara uyun.

  8. Bu kod değişiklikleriyle derleme yapmaya çalıştığınızda derleme hatası oluşur:

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

    Bu hatayı temizlemek için hata mesajında belirtildiği gibi aşağıdaki komutu çalıştırarak current.txt değerini değiştirin:

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

    Yukarıdaki komutu çalıştırarak normal şekilde derlenebilmesi için doğru dosyayı güncelleyin.

  9. Yeni piksel biçimini HardwareBufferTest.java bölgesindeki paramsForTestCreateOptionalFormats() öğesinin sonuna aşağıdaki gibi ekleyerek Java testlerine yeni piksel biçimini ekleyin:

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

Pencere sistemi entegrasyonuna yeni bir piksel biçimi ekleme

Yeni piksel biçimini bir grafik API'sindeki çerçeve önbelleği biçimi olarak kullanmak için ilgili grafik API'si için uygun Pencere Sistemi Entegrasyonu'na (WSI) ekleyin. Vulkan API'yi kullanan bir uygulama veya sistem işlemi için Vulkan Swapchain'i güncelleyin. OpenGL ES API'yi kullanan bir uygulama veya sistem işlemi için EGL API'yi güncelleyin.

Yeni piksel biçimleri için Vulkan WSI değişiklikleri

Vulkan WSI'yi aşağıdaki şekilde güncelleyin:
  1. swapchain.cpp işlevinde GetNativePixelFormat(VkFormat format) işlevine yeni bir büyük/küçük harf ekleyin:

    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. Piksel biçiminin çalışması için Vulkan uzantısı gerekiyorsa Vulkan uzantısını sorgulayın. Örneğin, yan uzantılar için instance_data simgesini kullanın. Bu simge aşağıdaki gibi gösterilir:
    bool colorspace_ext = instance_data.hook_extensions.test(ProcHook::EXT_swapchain_colorspace);
    

    Cihaz tarafı uzantılar için aşağıdakileri kullanın:

    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, bir örneği veya cihaz uzantısını swapchain.cpp kullanıcılarına sunmak için gereken altyapıyı gerçekleştirir. Vulkan yükleyicisinden uzantıların doğru şekilde ayarlanması için ilk değişiklik listesi gerekli değildir.

  3. Ardından, biçim ve renk alanı çiftlerini listeleyin:
    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});
    }
    

    Uyumlu biçim ve renk alanı çiftleri hakkında bilgi sahibi olmanız gerekir.

  4. Yeni biçimi, external/deqp konumunda bulunan dEQP-VK öğesine ekleyin.
  5. Gerekli değişiklikleri mevcut kaynaktan belirleyerek veya bilgi için Android destek ekibiyle iletişime geçerek vktApiExternalMemoryTests.cpp ve vktExternalMemoryUtil.cpp içinde Vulkan Uygunluk Testlerini güncelleyin.

Yeni piksel biçimleri için EGL değişiklikleri

EGL'yi aşağıdaki gibi güncelleyin:

  1. getNativePixelFormat() işlevinde, if-else ağacını yeni piksel biçimi için AIDL enum'unu döndürecek şekilde değiştirin. RGBA_8888 piksel biçimi örneğini kullanarak:
    if (a == 0) {
      ...
    } else {
      if (componentType == EGL_COLOR_COMPONENT_TYPE_FIXED_EXT) {
          if (colorDepth > 24) {
              ...
          } else {
              *format = PixelFormat::RGBA_8888;
          }
      } else {
        ...
      }
    }
    
  2. Yeni biçimi dEQP'ye eklemek için androidFormats enum'una aşağıdaki gibi yeni bir giriş ekleyin:
    static const GLenum androidFormats[] =
    {
      ...
      GL_RGBA8,
      ...
    };
    

Güncellemenizi gönderme

Değişiklik listelerinizi oluşturmak ve uygun ekiple paylaşmak için Katkıda bulunanlar için bölümünü inceleyin.