أضف تنسيقات بكسل جديدة إلى 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-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_ ، متبوعًا بمختصرات القناة وعمق البت، وينتهي بالتشفير. يجب أن يكون لإدخال التعداد هذا نفس القيمة السداسية الموجودة في 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:: enum وليس مع الثابت 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. أضف تنسيق البكسل الجديد إلى 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;
    

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

قم بتحديث 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,
      ...
    };
    

أرسل التحديث الخاص بك

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