Fügen Sie Android neue Pixelformate hinzu

Alle neuen Pixelformate, die zu Android hinzugefügt werden, müssen in der Android Interface Definition Language (AIDL) und im Android Hardware Buffer (AHB) enthalten sein. AIDL und AHB haben strenge Stabilitäts- und Standardisierungsanforderungen, die einen sorgfältigen Prozess bei der Erweiterung der Funktionalität erfordern. Alle neuen Pixelformate müssen in AOSP landen und alle Aktualisierungen müssen einzeln von AIDL- und AHB-Experten bestätigt werden. Dieser Prozess der sorgfältigen Bestätigung ist ein wichtiger Faktor bei der Standardisierung aller neuen Pixelformate auf der Plattform.

Auf dieser Seite werden die notwendigen AOSP-Codeänderungen und der Prozess beschrieben, der zum Hinzufügen neuer Pixelformate auf AOSP erforderlich ist.

Bevor Sie ein neues Pixelformat hinzufügen, laden Sie die Quelle herunter und laden Sie Patches hoch, wie unter „Einreichen von Patches“ beschrieben.

Fügen Sie AIDL ein neues Pixelformat hinzu

Das Hinzufügen der Unterstützung für ein neues Pixelformat erfordert Änderungen an beiden PixelFormat.aidl Dateien in AIDL. Den AIDL-Quellcode finden Sie hardware/interfaces/graphics/common/aidl/ .

Gehen Sie folgendermaßen vor, um AIDL ein neues Pixelformal hinzuzufügen:

  1. Hängen Sie das neue Pixelformat als neuen Eintrag an das Ende der PixelFormat Enumeration in PixelFormat.aidl an, indem Sie der bestehenden Codekonvention folgen und den Hexadezimalwert für Ihren Eintrag so festlegen, dass er um eins höher ist als der vorherige Eintrag. Passen Sie Ihre Codeänderungen an die vorherigen Einträge an. Sehen Sie sich das folgende Beispiel für den RGBA_8888 Pixelformateintrag an:
    /**
     * 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,
    

    Die folgende Fehlermeldung wird angezeigt, wenn Sie den Code erstellen, nachdem Sie Änderungen an PixelFormat.aidl vorgenommen haben:

    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. Um diesen Fehler zu beheben, führen Sie den folgenden Befehl aus, wie in der Fehlermeldung angegeben, um PixelFormat.aidl im Verzeichnis aidl_api zu ändern:

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

    Durch Ausführen des obigen Befehls wird die richtige Datei aktualisiert, um einen normalen Build durchführen zu können.

Fügen Sie AHB ein neues Pixelformat hinzu

Das Hinzufügen der Unterstützung für ein neues Pixelformat erfordert Änderungen an hardware_buffer.h und AHardwareBuffer.cpp . Den AHB-Quellcode finden Sie unter frameworks/native/libs/nativewindow .

Gehen Sie folgendermaßen vor, um AHB ein neues Pixelformal hinzuzufügen:

  1. Hängen Sie in hardware_buffer.h das neue Pixelformat als neuen Eintrag an das Ende der Aufzählung AHardwareBuffer_Format an. Befolgen Sie die bestehenden Codekonventionen.

    Fügen Sie anhand des Pixelformatbeispiels RGBA_8888 den neuen Pixelformateintrag wie folgt hinzu:

    /**
     * Corresponding formats:
     *   Vulkan: VK_FORMAT_R8G8B8A8_UNORM
     *   OpenGL ES: GL_RGBA8
     */
    AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM = 1,
    

    Beachten Sie, dass das neue Pixelformat in AHB einen Namen erhält, der mit AHARDWAREBUFFER_FORMAT_ beginnen muss, gefolgt von den Kanalabkürzungen und Bittiefen und endend mit der Kodierung. Dieser Enumerationseintrag muss denselben Hexadezimalwert haben wie der in PixelFormat.aidl .

    Es wird erwartet, dass das Pixelformat eines oder beide der zugehörigen Vulkan- oder OpenGL ES- Formate aufweist. Geben Sie gegebenenfalls das zugehörige Format an. Wenn kein zugehöriges Format vorhanden ist, geben Sie N/A an.

  2. Fügen Sie das Pixelformat zu optionalen Tests unter CTS hinzu, wenn es über ein zugehöriges OpenGL ES-Format verfügt. Fügen Sie dazu das neue GL-Format zu AHardwareBufferGLTest.cpp in AHBFormatAsString(int32_t format) mit FORMAT_CASE(...) und GL_FORMAT_CASE(...) für das neue Format hinzu, wie folgt:

    const char* AHBFormatAsString(int32_t format) {
      switch (format) {
          ...
          FORMAT_CASE(R8G8B8A8_UNORM);
          ...
          GL_FORMAT_CASE(GL_RGB8);
      }
      return "";
    }
    
  3. Fügen Sie als Nächstes einen neuen Test zu AHardwareBufferGLTest.cpp hinzu, wie folgt:

    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);
    

    Geben Sie mindestens einen Satz von AHardwareBuffer_Desc Werten an. Fügen Sie bei Bedarf weitere Werte hinzu.

  4. Suchen Sie in AHardwareBuffer.cpp nach dem Ende der statischen Zusicherungen in:

    // ----------------------------------------------------------------------------
    // Validate hardware_buffer.h and PixelFormat.aidl agree
    // ----------------------------------------------------------------------------
    

    Hängen Sie ein neues static_assert für das neue Pixelformat an, indem Sie die PixelFormat:: Enumeration und nicht die Konstante HAL_PIXEL_FORMAT verwenden. Fügen Sie unter Verwendung des gleichen Beispiels für das RGBA_8888 Pixelformat aus „Neues Pixelformat zu AIDL hinzufügen“ den neuen Pixelformateintrag wie folgt hinzu:

    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. Fügen Sie das neue Pixelformat zu den entsprechenden Tests hinzu, indem Sie das neue Pixelformat an das Ende von PrintAhbFormat() in AHardwareBufferTest.cpp anhängen. Befolgen Sie die bestehende Codekonvention, wie unten gezeigt:

    void PrintAhbFormat(std::ostream& os, uint64_t format) {
        switch (format) {
            ...
            FORMAT_CASE(R8G8B8A8_UNORM);
            default: os << "unknown"; break;
        }
    }
    
  6. Fügen Sie das neue Pixelformat zum HardwareBuffer SDK in HardwareBuffer.java hinzu: indem Sie einen neuen Eintrag an @IntDef anhängen. Der Eintrag für das Format RGBA_8888 sieht beispielsweise wie folgt aus:

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

    Wenn die Komponentenwerte nicht vorzeichenlos normalisiert sind, geben Sie den Wert explizit im Variablennamen an. Beispielsweise muss der Variablenname für ein vorzeichenloses, ganzzahliges 16-Bit-Format nur für den roten Kanal R_16UI sein, und das gleiche Format mit einem zusätzlichen vorzeichenlosen ganzzahligen 16-Bit-Format für den grünen Kanal muss RG_16UI16UI sein.

  7. Fügen Sie das neue Pixelformat als static int in HardwareBuffer.java hinzu, indem Sie am Ende von @Format eine neue öffentliche Mitgliedsvariable anhängen:

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

    Dieser Enumerationseintrag muss denselben Hexadezimalwert wie der von PixelFormat.aidl und hardware_buffer.h haben. Befolgen Sie bestehende Konventionen.

  8. Der Versuch, mit diesen Codeänderungen zu erstellen, erzeugt einen Build-Fehler:

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

    Um diesen Fehler zu beheben, führen Sie den folgenden Befehl aus, wie in der Fehlermeldung angegeben, um current.txt zu ändern:

    m api-stubs-docs-non-updatable-update-current-api
    

    Durch Ausführen des obigen Befehls wird die richtige Datei aktualisiert, um einen normalen Build durchführen zu können.

  9. Fügen Sie das neue Pixelformat zu den Java-Tests hinzu, indem Sie das neue Pixelformat an das Ende von paramsForTestCreateOptionalFormats() in HardwareBufferTest.java anhängen, wie folgt:

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

Fügen Sie der Windows-Systemintegration ein neues Pixelformat hinzu

Um das neue Pixelformat als Format für einen Framebuffer in einer Grafik-API zu verwenden, fügen Sie es der entsprechenden Window System Integration (WSI) für die entsprechende Grafik-API hinzu. Aktualisieren Sie für eine App oder einen Systemprozess, die die Vulkan-API verwenden, die Vulkan-Swapchain. Aktualisieren Sie für eine App oder einen Systemprozess, die die OpenGL ES-API verwenden, die EGL- API.

Vulkan WSI-Änderungen für neue Pixelformate

Aktualisieren Sie das Vulkan WSI wie folgt:
  1. Fügen Sie der Funktion GetNativePixelFormat(VkFormat format) in swapchain.cpp einen neuen Fall hinzu:

    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. Fragen Sie die Vulkan-Erweiterung ab, wenn das Pixelformat für die Funktion eine Vulkan-Erweiterung erfordert. Für Seitenerweiterungen verwenden Sie beispielsweise instance_data , wie folgt dargestellt:
    bool colorspace_ext = instance_data.hook_extensions.test(ProcHook::EXT_swapchain_colorspace);
    

    Verwenden Sie für geräteseitige Erweiterungen Folgendes:

    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 verwaltet die Infrastruktur, die erforderlich ist, um eine Instanz oder Geräteerweiterung für swapchain.cpp verfügbar zu machen. Die anfängliche Änderungsliste ist nicht erforderlich, damit die Erweiterungen vom Vulkan-Loader korrekt eingerichtet werden.

  3. Listen Sie als Nächstes die Format- und Farbraumpaare auf:
    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});
    }
    

    Sie müssen über Kenntnisse der kompatiblen Format- und Farbraumpaare verfügen.

  4. Fügen Sie das neue Format zu dEQP-VK hinzu, das sich unter external/deqp befindet.
  5. Aktualisieren Sie die Vulkan-Konformitätstests in vktApiExternalMemoryTests.cpp und vktExternalMemoryUtil.cpp , indem Sie die erforderlichen Änderungen aus der vorhandenen Quelle ableiten oder sich für Informationen an Ihren Android-Support wenden.

EGL-Änderungen für neue Pixelformate

Aktualisieren Sie die EGL wie folgt:

  1. Ändern Sie in der Funktion getNativePixelFormat() den if-else Baum, um die AIDL-Enumeration für das neue Pixelformat zurückzugeben. Am Beispiel für das Pixelformat RGBA_8888 :
    if (a == 0) {
      ...
    } else {
      if (componentType == EGL_COLOR_COMPONENT_TYPE_FIXED_EXT) {
          if (colorDepth > 24) {
              ...
          } else {
              *format = PixelFormat::RGBA_8888;
          }
      } else {
        ...
      }
    }
    
  2. Um das neue Format zu dEQP hinzuzufügen, fügen Sie einen neuen Eintrag zur androidFormats Enumeration hinzu, der wie folgt angezeigt wird:
    static const GLenum androidFormats[] =
    {
      ...
      GL_RGBA8,
      ...
    };
    

Senden Sie Ihr Update

Folgen Sie den Mitwirkenden, um Ihre Änderungslisten zu erweitern und sie mit dem entsprechenden Team zu teilen.