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

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

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

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

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

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

برای افزودن یک پیکسل رسمی جدید به 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_ شروع شود، سپس اختصارات کانال و عمق بیت و با رمزگذاری ختم شود. این ورودی enum باید همان مقدار هگز را در PixelFormat.aidl داشته باشد.

    انتظار می رود فرمت پیکسل دارای یکی یا هر دو فرمت Vulkan یا OpenGL ES مرتبط باشد. در صورت لزوم قالب مرتبط را مشخص کنید. اگر هیچ قالب مرتبطی وجود ندارد، N/A را مشخص کنید.

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

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

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

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

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

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

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

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

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

    برای پاک کردن این خطا، دستور زیر را همانطور که در پیام خطا مشخص شده است اجرا کنید تا 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 گرافیکی، آن را به یکپارچه سازی سیستم پنجره (WSI) مناسب برای API گرافیکی مربوطه اضافه کنید. برای فرآیند برنامه یا سیستمی که از 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});
    }
    

    شما باید از فرمت سازگار و جفت های colorspace آگاهی داشته باشید.

  4. قالب جدید را به dEQP-VK واقع در external/deqp اضافه کنید.
  5. تست‌های انطباق Vulkan را در vktApiExternalMemoryTests.cpp و vktExternalMemoryUtil.cpp با استنباط تغییرات مورد نیاز از منبع موجود یا تماس با پشتیبانی Android خود برای کسب اطلاعات، به‌روزرسانی کنید.

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

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، یک ورودی جدید به enum androidFormats اضافه کنید که به صورت زیر نشان داده شده است:
    static const GLenum androidFormats[] =
    {
      ...
      GL_RGBA8,
      ...
    };
    

به روز رسانی خود را ارسال کنید

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