افزودن قالب‌های پیکسل جدید به Android

همه قالب‌های پیکسل جدید اضافه‌شده به Android باید در زبان تعریف واسط Android (AIDL) و در بافر سخت‌افزار Android (AHB) گنجانده شوند. AIDL و AHB الزامات پایداری و استانداردسازی سخت‌گیرانه‌ای دارند که فرایند دقیقی را هنگام گسترش عملکرد ضروری می‌سازد. همه قالب‌های پیکسل جدید باید در AOSP قرار بگیرند و همه به‌روزرسانی‌ها باید به‌طور جداگانه توسط کارشناسان AIDL و AHB تأیید شوند. این فرایند تأیید دقیق عامل مهمی در استانداردسازی هر قالب پیکسل جدید در پلاتفرم است.

این صفحه تغییرات لازم در کد AOSP و فرایند موردنیاز برای افزودن قالب‌های پیکسل جدید در AOSP را شرح می‌دهد.

قبل‌از افزودن قالب پیکسل جدید، منبع را بارگیری کنید و وصله‌ها را همان‌طور که در ارسال وصله‌ها شرح داده شده است بارگذاری کنید.

افزودن قالب پیکسل جدید به AIDL

افزودن پشتیبانی از قالب پیکسل جدید مستلزم تغییر در هر دو فایل PixelFormat.aidl واقع در AIDL است. برای کد منبع AIDL، به hardware/interfaces/graphics/common/aidl/ مراجعه کنید.

برای افزودن قالب پیکسل جدید به AIDL، این مراحل را دنبال کنید:

  1. قالب پیکسل جدید را به‌عنوان ورودی جدید به انتهای شمارش PixelFormat در 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-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. برای پاک کردن این خطا، فرمان زیر را، همان‌طور که در پیام خطا مشخص شده است، اجرا کنید تا PixelFormat.aidl در دایرکتوری aidl_api تغییر کند:

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

    اجرای دستور بالا فایل صحیح را به‌روز می‌کند تا بتوانید به‌طور معمول بسازید.

افزودن قالب پیکسل جدید به AHB

افزودن پشتیبانی برای قالب پیکسل جدید نیازمند تغییراتی در hardware_buffer.h و AHardwareBuffer.cpp است. برای کد منبع AHB، frameworks/native/libs/nativewindow را ببینید.

برای افزودن قالب پیکسل جدید به AHB، این مراحل را دنبال کنید:

  1. در hardware_buffer.h، قالب پیکسل جدید را به‌عنوان ورودی جدید به انتهای عدد ثابت AHardwareBuffer_Format اضافه کنید. از قراردادهای کد موجود پیروی کنید.

    بااستفاده از مثال قالب پیکسل 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. اگر قالب پیکسل دارای قالب OpenGL ES مرتبط است، آن را به آزمایش اختیاری تحت CTS اضافه کنید. برای انجام این کار، قالب 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
    // ----------------------------------------------------------------------------
    

    بااستفاده از تعداد ثابت HAL_PIXEL_FORMAT و نه با شمارش PixelFormat::، یک static_assert جدید برای قالب پیکسل جدید اضافه کنید. بااستفاده از همان مثال برای قالب پیکسل RGBA_8888 از قالب پیکسل جدیدی به 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. با افزودن ورودی جدید به @IntDef، قالب پیکسل جدید را به کیت توسعه نرم‌افزار HardwareBuffer در HardwareBuffer.java اضافه کنید: برای مثال، ورودی قالب RGBA_8888 به‌صورت زیر نشان داده می‌شود:

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

    اگر مقادیر عنصر بدون علامت نرمال‌سازی‌شده نیستند، مقدار را به‌طور صریح در نام متغیر نشان دهید. برای مثال، نام متغیر برای قالب فقط کانال قرمز ۱۶ بیتی عدد صحیح بدون علامت باید R_16UI باشد، و همان قالب با قالب کانال سبز ۱۶ بیتی عدد صحیح بدون علامت اضافی باید RG_16UI16UI باشد.

  7. قالب پیکسل جدید را به‌عنوان static int در HardwareBuffer.java اضافه کنید با افزودن متغیر عضو عمومی جدید در انتهای @Format:

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

    این ورودی شمارشی باید مقدار شانزده‌شانزدهی یکسانی با مقدار PixelFormat.aidl و hardware_buffer.h داشته باشد. از قراردادهای موجود پیروی کنید.

  8. تلاش برای ساخت با این تغییرات کد، خطای ساخت ایجاد می‌کند:

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

    برای پاک کردن این خطا، فرمان زیر را، همان‌طور که در پیام خطا مشخص شده است، اجرا کنید تا current.txt تغییر کند:

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

    اجرای دستور بالا فایل صحیح را به‌روز می‌کند تا بتوانید به‌طور معمول بسازید.

  9. قالب پیکسل جدید را با افزودن قالب پیکسل جدید به انتهای paramsForTestCreateOptionalFormats() در HardwareBufferTest.java به آزمایش‌های Java اضافه کنید، به‌صورت زیر نشان داده شده است:

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

افزودن قالب پیکسل جدید به یکپارچه‌سازی «سیستم پنجره»

برای استفاده از قالب پیکسل جدید به‌عنوان قالب یک قاب‌بافر در یک میانای برنامه‌سازی کاربردی گرافیکی، آن را به «یکپارچه‌سازی سیستم پنجره» (WSI) مناسب برای میانای برنامه‌سازی کاربردی گرافیکی مربوطه اضافه کنید. برای برنامه یا فرایند سیستمی که از 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 برای قالب‌های پیکسل جدید

«فهرست استثناهای جهانی» را به‌صورت زیر به‌روز کنید:

  1. در تابع getNativePixelFormat() ، درخت if-else را اصلاح کنید تا شمارش AIDL را برای قالب پیکسل جدید برگرداند.

    بااستفاده از مثال برای قالب پیکسل 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,
      ...
    };
    

ارسال به‌روزرسانی

برای همیاران را دنبال کنید تا فهرست‌های تغییراتتان را ایجاد کنید و آن‌ها را با تیم مناسب هم‌رسانی کنید.