فرمت های پیکسل جدید را به اندروید اضافه کنید

تمام فرمت‌های پیکسل جدید اضافه شده به اندروید باید در زبان تعریف رابط اندروید (AIDL) و در بافر سخت‌افزاری اندروید (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 ، فرمت پیکسل جدید را به عنوان یک ورودی جدید به انتهای enum 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
    // ----------------------------------------------------------------------------
    

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

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

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

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

    @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 ، که به صورت زیر نشان داده شده است، به تست‌های جاوا اضافه کنید:

    private static Object[] paramsForTestCreateOptionalFormats() {
      return new Integer[]{
          HardwareBuffer.RGBA_8888
      };
    
یک فرمت پیکسل جدید به ادغام سیستم پنجره اضافه کنید

برای استفاده از فرمت پیکسل جدید به عنوان فرمت فریم‌بافر در یک API گرافیکی، آن را به Window System Integration (WSI) مناسب برای API گرافیکی مربوطه اضافه کنید. برای یک برنامه یا فرآیند سیستمی که از Vulkan API استفاده می‌کند، Vulkan Swapchain را به‌روزرسانی کنید. برای یک برنامه یا فرآیند سیستمی که از OpenGL ES API استفاده می‌کند، EGL API را به‌روزرسانی کنید.

تغییرات Vulkan WSI برای فرمت‌های جدید پیکسل

WSI مربوط به Vulkan را به صورت زیر به‌روزرسانی کنید:

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

    گوگل زیرساخت مورد نیاز برای نمایش یک نمونه یا افزونه دستگاه به 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 به‌روزرسانی کنید.

تغییرات EGL برای فرمت‌های جدید پیکسل

EGL را به صورت زیر به‌روزرسانی کنید:

  1. در تابع getNativePixelFormat() ، درخت if-else را طوری تغییر دهید که 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، یک ورودی جدید به enum مربوط به androidFormats اضافه کنید، که به صورت زیر نشان داده شده است:
    static const GLenum androidFormats[] =
    {
      ...
      GL_RGBA8,
      ...
    };
    
به‌روزرسانی خود را ارسال کنید

برای مشارکت‌کنندگان ، فهرست تغییرات خود را ایجاد کنید و آنها را با تیم مناسب به اشتراک بگذارید.