הוסף פורמטים חדשים של פיקסלים לאנדרואיד

כל פורמטי הפיקסלים החדשים שנוספו ל-Android חייבים להיכלל בשפת ההגדרה של ממשק אנדרואיד (AIDL) וב- Android Hardware Buffer (AHB) . ל-AIDL ול-AHB יש דרישות יציבות וסטנדרטיזציה קפדניות המחייבות תהליך זהיר בעת הרחבת הפונקציונליות. כל פורמטי הפיקסלים החדשים חייבים לנחות ב-AOSP וכל העדכונים חייבים להיות מאושרים בנפרד על ידי מומחי AIDL ו-AHB. תהליך זה של אישור קפדני הוא גורם חשוב בסטנדרטיזציה של כל פורמט פיקסל חדש בפלטפורמה.

דף זה מתאר את השינויים הדרושים בקוד AOSP ואת התהליך הנדרש להוספת פורמטים חדשים של פיקסלים ב-AOSP.

לפני הוספת פורמט פיקסל חדש, הורד את המקור והעלה תיקונים כפי שמתואר בשליחת תיקונים .

הוסף פורמט פיקסל חדש ל-AIDL

הוספת תמיכה בפורמט פיקסל חדש דורשת שינויים בשני קבצי PixelFormat.aidl הממוקמים בתוך AIDL. ראה hardware/interfaces/graphics/common/aidl/ לקוד המקור של AIDL.

כדי להוסיף רשמי פיקסל חדש ל-AIDL, בצע את השלבים הבאים:

  1. הוסף את פורמט הפיקסלים החדש כערך חדש לסוף ה- PixelFormat enum ב- PixelFormat.aidl על-ידי ביצוע מוסכמות הקוד הקיימת והגדרת ערך ה-hex עבור הערך שלך להיות אחד יותר מהערך הקודם. התאם את שינויי הקוד שלך לערכים הקודמים. ראה את הדוגמה הבאה עבור ערך פורמט הפיקסל 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 הזה חייב להיות אותו ערך hex כמו זה ב- 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;
    

    לערך ה-enum הזה חייב להיות אותו ערך hex כמו זה של 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
      };
    

הוסף פורמט פיקסלים חדש לשילוב מערכת Windows

כדי להשתמש בפורמט הפיקסלים החדש כפורמט ל-framebuffer ב-API גרפי, הוסף אותו ל-Windows System Integration (WSI) המתאים עבור ה-API הגרפי הרלוונטי. עבור אפליקציה או תהליך מערכת המשתמשים ב-Vulkan API, עדכן את Vulkan Swapchain. עבור אפליקציה או תהליך מערכת המשתמשים ב- OpenGL ES API, עדכן את EGL API.

שינויים בוולקן 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;
        }
    }
    

    גוגל מטפלת בתשתית הנדרשת כדי לחשוף מופע או הרחבת מכשיר ל- 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 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, הוסף ערך חדש ל- androidFormats enum, המוצג כדלקמן:
    static const GLenum androidFormats[] =
    {
      ...
      GL_RGBA8,
      ...
    };
    

שלח את העדכון שלך

עקוב אחר תורמים כדי ליצור את רשימות השינויים שלך ולשתף אותן עם הצוות המתאים.