إضافة تنسيقات بكسل جديدة إلى Android

يجب تضمين جميع تنسيقات البكسل الجديدة التي تمت إضافتها إلى Android في لغة تعريف واجهة Android (AIDL) وفي التخزين المؤقت لأجهزة Android (AHB) تفرض واجهة برمجة التطبيقات AIDL وواجهة AHB متطلبات صارمة للاستقرار والتوحيد تتطلّب اتّباع عملية مدروسة عند توسيع نطاق الوظائف. يجب أن يتم طرح جميع تنسيقات البكسل الجديدة في AOSP ويجب أن يؤكّد خبراء AIDL وAHB كل التحديثات بشكلٍ فردي. إنّ عملية التأكيد الدقيقة هذه هي عامل مهم في توحيد أي تنسيقات جديدة للبكسل على الصعيد المنصة.

توضِّح هذه الصفحة التغييرات اللازمة في رمز AOSP والعملية المطلوبة لإضافة تنسيقات بكسل جديدة على AOSP.

قبل إضافة تنسيق بكسل جديد، نزِّل المصدر وحمِّل الرموز البرمجية كما هو موضّح في مقالة إرسال الرموز البرمجية.

إضافة تنسيق بكسل جديد إلى تنسيق AIDL

تتطلّب إضافة دعم لتنسيق بكسل جديد إجراء تغييرات على كل من ملفَي PixelFormat.aidl ضمن AIDL. عرض hardware/interfaces/graphics/common/aidl/ لرمز مصدر 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 اطّلِع على 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_، يليها اختصارات القناة وبت وعمقها، وتنتهي بالترميز. يجب أن يحتوي إدخال التعداد هذا على نفس القيمة السداسية العشرية التي وردت في 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
    // ----------------------------------------------------------------------------
    

    أضِف static_assert جديدًا لتنسيق البكسل الجديد، باستخدام التعداد PixelFormat:: وليس باستخدام الثابت HAL_PIXEL_FORMAT. يتم استخدام المثال نفسه لتنسيق 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. أضِف تنسيق البكسل الجديد إلى حزمة تطوير البرامج (SDK) لنظام التشغيل "HardwareBuffer" في 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;
    

    يجب أن يحتوي إدخال التعداد هذا على القيمة الست عشرية نفسها لتلك الواردة من 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. أضِف تنسيق البكسل الجديد إلى اختبارات Java، وذلك من خلال إلحاق تنسيق البكسل الجديد بنهاية paramsForTestCreateOptionalFormats() في HardwareBufferTest.java، كما هو موضّح أدناه:

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

إضافة تنسيق بكسل جديد إلى دمج نظام Windows

لاستخدام تنسيق البكسل الجديد كتنسيق للمخزن المؤقت للإطارات في واجهة برمجة التطبيقات للرسومات، فقم بإضافتها إلى تكامل نظام النوافذ (WSI) المناسب لواجهة برمجة التطبيقات وواجهة برمجة التطبيقات للرسومات. بالنسبة إلى عملية تطبيق أو نظام تستخدم واجهة برمجة التطبيقات Vulkan، عليك تعديل سلسلة التبديل Vulkan Swapchain. بالنسبة إلى عملية تطبيق أو نظام باستخدام واجهة برمجة التطبيقات OpenGL ES API، عليك تعديل EGL.

تغييرات 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 لتنسيقات البكسل الجديدة

عدِّل 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 التعداد، على النحو التالي:
    static const GLenum androidFormats[] =
    {
      ...
      GL_RGBA8,
      ...
    };
    

إرسال التعديل

متابعة للمساهمين لتدوير قوائم التغييرات الخاصة بك ومشاركتها مع الفريق المناسب.