Android'e yeni piksel biçimleri ekleme

Android'e eklenen tüm yeni piksel biçimleri Android Arayüz Tanımlama Dili (AIDL) ve Android Donanım Arabelleği (AHB). AIDL ve AHB'nin katı kararlılık ve standartlaştırma koşulları, işlevselliği genişletirken dikkatli bir süreç gerektirir. 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 onay süreci, platformdaki yeni piksel biçimlerinin standartlaştırılmasında önemli bir faktördür.

Bu sayfada, gerekli AOSP kod değişiklikleri ve AOSP'ye yeni piksel biçimleri eklemek için gereken işlem özetlenmiştir.

Yeni bir piksel biçimi eklemeden önce kaynağı indirin ve yamaları şurada açıklandığı gibi yükleyin: Yama gönderme.

AIDL'ye yeni bir piksel biçimi ekleme

Yeni bir piksel biçimi desteği eklemek için hem AIDL'de PixelFormat.aidl dosya bulunuyor. AIDL kaynak kodu için hardware/interfaces/graphics/common/aidl/ bölümüne bakın.

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

  1. Yeni piksel biçimini şu kampanyadaki PixelFormat sıralamasının sonuna yeni bir giriş olarak ekleyin: PixelFormat.aidl Mevcut kod kuralını uygulayarak ve girişinizin onaltılık değerini bir veya daha fazla olacak şekilde ayarlayarak (önceki girişten daha iyi). Kod değişikliklerinizi önceki girişlerle eşleştirin. Aşağıdaki örneğe bakın RGBA_8888 piksel biçimi girişi için:
    /**
     * 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-android-latest-release: 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ı temizlemek için hata mesajında belirtildiği gibi aşağıdaki komutu çalıştırarak PixelFormat.aidl aidl_api dizininde:

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

    Yukarıdaki komut çalıştırıldığında, normal şekilde derleme yapabilmek için doğru dosya güncellenir.

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üne bakın.

AHB'ye yeni bir piksel resmi eklemek için aşağıdaki adımları izleyin:

  1. hardware_buffer.h ürününde, yeni piksel biçimini AHardwareBuffer_Format sıralaması. Mevcut kod kurallarını uygulayın.

    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 sıralama girişi, PixelFormat.aidl içindeki ile aynı onaltılık değerdir.

    Piksel biçimiyle, ilişkilendirilmiş bir veya ikisine birden sahip olması beklenir. Vulkan veya OpenGL ES biçimindedir. Uygun durumlarda ilişkili biçimi belirtin. İlişkilendirilmiş bir biçim yoksa belirtin N/A

  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 AHardwareBufferGLTest.cpp FORMAT_CASE(...) ile AHBFormatAsString(int32_t format) içinde ve yeni biçim için GL_FORMAT_CASE(...) aşağıda gösterilmiştir:

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

    AHardwareBuffer_Desc değerden oluşan en az bir grup 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
    // ----------------------------------------------------------------------------
    

    Şunu kullanarak yeni piksel biçimi için yeni bir static_assert ekleyin: PixelFormat:: sıralaması (HAL_PIXEL_FORMAT sabitiyle değil). Aynı örnek, şuradan gelen RGBA_8888 piksel biçimi için kullanılır: AIDL'ye yeni bir piksel biçimi ekleyin, 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 kuralını izleyin:

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

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

    Bileşen değerleri normalleştirilmiş olarak işaretlenmemişse değeri açık bir şekilde belirtin ifadesini girin. Ö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. Yeni piksel biçimini static int olarak ekleyin HardwareBuffer.java, @Format sonuna yeni bir herkese açık üye değişkeni ekleyebilirsiniz:

    @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 kuralları uygulayın.

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

    android_developer:~/android/aosp-android-latest-release: 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 belirtilen şekilde aşağıdaki komutu çalıştırın: değiştirmek için current.txt:

    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 içindeki paramsForTestCreateOptionalFormats() öğesinin sonuna ekleyerek Java testlerine ekleyin. Bu işlem aşağıdaki gibi gösterilmiştir:

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

Pencere sistemi entegrasyonuna yeni bir piksel biçimi ekleme

Yeni piksel biçimini Gratis API'sını kullanıyorsanız, dosyayı alakalı Grafik API'sı. Vulkan API'yi kullanan bir uygulama veya sistem işlemi için Vulkan Swapchain'i güncelleyin. OpenGL ES API kullanan bir uygulama veya sistem işlemi için EGL API'si.

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

Vulkan WSI'yı aşağıdaki şekilde güncelleyin:
  1. swapchain.cpp içindeki GetNativePixelFormat(VkFormat format) işlevine yeni bir durum 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 aşağıdaki gibi gösterilen instance_data simgesini kullanın:
    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'e göstermek için gereken altyapıyı yönetir. İlk değişiklik listesinin uzantıların Vulkan yükleyicisinden doğru şekilde ayarlanmasını sağlayın.

  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 adresindeki dEQP-VK alanına ekleyin.
  5. Vulkan Uygunluk Testlerini şurada güncelleyin: vktApiExternalMemoryTests.cpp ve vktExternalMemoryUtil.cpp Mevcut kaynaktan gerekli değişiklikleri çıkartarak veya Android desteğinizle iletişime geçerek inceleyebilirsiniz.

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

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

  1. getNativePixelFormat() fonksiyonunda, if-else ağacını, yeni piksel biçimi için AIDL sıralamasını 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 değeri, aşağıdaki gibi gösterilir:
    static const GLenum androidFormats[] =
    {
      ...
      GL_RGBA8,
      ...
    };
    

Güncellemenizi gönderme

Takip et Katkıda bulunanlar için ve bunları uygun ekiple paylaşmaya hazır olun.