Android में नए पिक्सल फ़ॉर्मैट जोड़ना

Android में जोड़े गए सभी नए पिक्सल फ़ॉर्मैट को Android इंटरफ़ेस डेफ़िनिशन लैंग्वेज (एआईडीएल) और Android हार्डवेयर बफ़र (AHB). AIDL और AHB के लिए, स्थिरता और स्टैंडर्ड से जुड़ी ज़रूरी शर्तें सख्त होती हैं. इसलिए, इनकी सुविधाओं को बढ़ाते समय सावधानी बरतने की ज़रूरत होती है. सभी नए पिक्सल फ़ॉर्मैट, एओएसपी में ही होने चाहिए साथ ही, सभी अपडेट की पुष्टि एआईडीएल और एएचबी विशेषज्ञों से अलग-अलग करनी होगी. प्लैटफ़ॉर्म पर किसी भी नए पिक्सल फ़ॉर्मैट को स्टैंडर्ड बनाने के लिए, ध्यान से पुष्टि करने की यह प्रोसेस एक अहम फ़ैक्टर है.

इस पेज पर, AOSP कोड में किए जाने वाले ज़रूरी बदलावों के बारे में बताया गया है. साथ ही, AOSP पर नए पिक्सल फ़ॉर्मैट जोड़ने की प्रक्रिया के बारे में भी बताया गया है.

नया पिक्सल फ़ॉर्मैट जोड़ने से पहले, सोर्स डाउनलोड करें और यहां बताए गए तरीके से पैच अपलोड करें पैच सबमिट करना.

एआईडीएल में नया पिक्सल फ़ॉर्मैट जोड़ें

नए पिक्सल फ़ॉर्मैट के लिए सहायता जोड़ने के लिए, AIDL में मौजूद दोनों PixelFormat.aidl फ़ाइलों में बदलाव करना ज़रूरी है. यहां जाएं: hardware/interfaces/graphics/common/aidl/ के लिए GA4 प्रॉपर्टी सेट अप करें.

एआईडीएल में नया पिक्सल फ़ॉर्मल जोड़ने के लिए, यह तरीका अपनाएं:

  1. मौजूदा कोड कॉन्वेंशन का पालन करके, PixelFormat.aidl में PixelFormat enum के आखिर में, नए पिक्सल फ़ॉर्मैट को नई एंट्री के तौर पर जोड़ें. साथ ही, अपनी एंट्री के लिए हेक्स वैल्यू को पिछली एंट्री से एक ज़्यादा पर सेट करें. कोड में किए गए बदलावों को पिछली एंट्री से मैच करें. 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 या ओपनजीएल स्पैनिश फ़ॉर्मैट. जहां ज़रूरी हो वहां उससे जुड़ा फ़ॉर्मैट बताएं. अगर कोई संबंधित फ़ॉर्मैट मौजूद नहीं है, तो N/A.

  2. अगर इमेज में OpenGL ES फ़ॉर्मैट से जुड़ा हुआ है, तो सीटीएस के तहत वैकल्पिक जांच में पिक्सल फ़ॉर्मैट को जोड़ें. ऐसा करने के लिए, AHBFormatAsString(int32_t format) में AHardwareBufferGLTest.cpp के लिए नया GL फ़ॉर्मैट जोड़ें. साथ ही, नए फ़ॉर्मैट के लिए 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 पिक्सल फ़ॉर्मैट के लिए भी उसी उदाहरण का इस्तेमाल किया जा रहा है: एआईडीएल में नया पिक्सल फ़ॉर्मैट जोड़ें, नई पिक्सेल प्रारूप प्रविष्टि को इस तरह जोड़ें:

    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.java में, HardwareBuffer SDK टूल में नया पिक्सल फ़ॉर्मैट जोड़ें: @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 टेस्ट में नया पिक्सल फ़ॉर्मैट जोड़ें. इसके लिए, HardwareBufferTest.java में paramsForTestCreateOptionalFormats() के आखिर में नया पिक्सल फ़ॉर्मैट जोड़ें. इसे इस तरह दिखाया गया है:

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

विंडो सिस्टम इंटिग्रेशन में नया पिक्सल फ़ॉर्मैट जोड़ें

नए पिक्सल फ़ॉर्मैट को ग्राफ़िक्स एपीआई में फ़्रेमबफ़र के फ़ॉर्मैट के तौर पर इस्तेमाल करने के लिए, उसे काम के ग्राफ़िक्स एपीआई के लिए सही विंडो सिस्टम इंटिग्रेशन (डब्ल्यूएसआई) में जोड़ें. Vulkan API का इस्तेमाल करने वाले ऐप्लिकेशन या सिस्टम प्रोसेस के लिए, 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. मौजूदा सोर्स से ज़रूरी बदलावों का अनुमान लगाकर या जानकारी के लिए Android सहायता टीम से संपर्क करके, vktApiExternalMemoryTests.cpp और vktExternalMemoryUtil.cpp में Vulkan Conformance Tests को अपडेट करें.

नए पिक्सल फ़ॉर्मैट के लिए 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,
      ...
    };
    

अपडेट सबमिट करें

फ़ॉलो करें योगदान देने वालों के लिए ताकि आप अपनी परिवर्तन सूचियों को स्पिन अप कर सकें और उन्हें उचित टीम के साथ शेयर कर सकें.