Aggiungi nuovi formati pixel ad Android

Tutti i nuovi formati pixel aggiunti ad Android devono essere inclusi nell'Android Interface Definition Language (AIDL) e nell'Android Hardware Buffer (AHB) . AIDL e AHB hanno severi requisiti di stabilità e standardizzazione che richiedono un processo attento quando si estende la funzionalità. Tutti i nuovi formati pixel devono arrivare in AOSP e tutti gli aggiornamenti devono essere confermati individualmente dagli esperti AIDL e AHB. Questo processo di attenta conferma è un fattore importante per standardizzare eventuali nuovi formati pixel sulla piattaforma.

Questa pagina descrive le modifiche necessarie al codice AOSP e il processo richiesto per aggiungere nuovi formati pixel su AOSP.

Prima di aggiungere un nuovo formato pixel, scarica l'origine e carica le patch come indicato in Invio delle patch .

Aggiungi un nuovo formato pixel ad AIDL

L'aggiunta del supporto per un nuovo formato pixel richiede modifiche a entrambi i file PixelFormat.aidl situati all'interno di AIDL. Vedi hardware/interfaces/graphics/common/aidl/ per il codice sorgente AIDL.

Per aggiungere un nuovo pixel formale ad AIDL, attenersi alla seguente procedura:

  1. Aggiungi il nuovo formato pixel come nuova voce alla fine dell'enumerazione PixelFormat in PixelFormat.aidl seguendo la convenzione del codice esistente e impostando il valore esadecimale per la voce in modo che sia uno in più rispetto alla voce precedente. Abbina le modifiche al codice alle voci precedenti. Vedere l'esempio seguente per la voce del formato pixel 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,
    

    Il seguente messaggio di errore viene visualizzato quando crei il codice dopo aver apportato modifiche a 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. Per eliminare questo errore, esegui il comando seguente, come specificato nel messaggio di errore, per modificare PixelFormat.aidl nella directory aidl_api :

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

    L'esecuzione del comando precedente aggiorna il file corretto per poterlo compilare normalmente.

Aggiungi un nuovo formato pixel ad AHB

L'aggiunta del supporto per un nuovo formato pixel richiede modifiche a hardware_buffer.h e AHardwareBuffer.cpp . Vedi frameworks/native/libs/nativewindow per il codice sorgente AHB.

Per aggiungere un nuovo pixel formale ad AHB, attenersi alla seguente procedura:

  1. In hardware_buffer.h , aggiungi il nuovo formato pixel come nuova voce alla fine dell'enumerazione AHardwareBuffer_Format . Seguire le convenzioni del codice esistenti.

    Utilizzando l'esempio del formato pixel RGBA_8888 , aggiungi la nuova voce del formato pixel come segue:

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

    Tieni presente che al nuovo formato pixel viene assegnato un nome in AHB, che deve iniziare con AHARDWAREBUFFER_FORMAT_ , seguito dalle abbreviazioni del canale e dalla profondità di bit e terminare con la codifica. Questa voce enum deve avere lo stesso valore esadecimale di quella in PixelFormat.aidl .

    Si prevede che il formato pixel abbia uno o entrambi i formati Vulkan o OpenGL ES associati. Specificare il formato associato, ove appropriato. Se non esiste alcun formato associato, specificare N/A .

  2. Aggiungi il formato pixel al test facoltativo in CTS, se ha un formato OpenGL ES associato. Per fare ciò, aggiungi il nuovo formato GL a AHardwareBufferGLTest.cpp in AHBFormatAsString(int32_t format) con FORMAT_CASE(...) e GL_FORMAT_CASE(...) per il nuovo formato, mostrato come segue:

    const char* AHBFormatAsString(int32_t format) {
      switch (format) {
          ...
          FORMAT_CASE(R8G8B8A8_UNORM);
          ...
          GL_FORMAT_CASE(GL_RGB8);
      }
      return "";
    }
    
  3. Successivamente, aggiungi un nuovo test a AHardwareBufferGLTest.cpp , mostrato come segue:

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

    Specificare almeno un set di valori AHardwareBuffer_Desc . Aggiungi più valori se necessario.

  4. In AHardwareBuffer.cpp , trova la fine degli assert statici trovati all'interno di:

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

    Aggiungi un nuovo static_assert per il nuovo formato pixel, utilizzando PixelFormat:: enum e non con la costante HAL_PIXEL_FORMAT . Utilizzando lo stesso esempio per il formato pixel RGBA_8888 in Aggiungi un nuovo formato pixel a AIDL , aggiungi la nuova voce del formato pixel come segue:

    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. Aggiungi il nuovo formato pixel ai test appropriati, aggiungendo il nuovo formato pixel alla fine di PrintAhbFormat() in AHardwareBufferTest.cpp . Seguire la convenzione del codice esistente, come mostrato di seguito:

    void PrintAhbFormat(std::ostream& os, uint64_t format) {
        switch (format) {
            ...
            FORMAT_CASE(R8G8B8A8_UNORM);
            default: os << "unknown"; break;
        }
    }
    
  6. Aggiungi il nuovo formato pixel all'SDK HardwareBuffer in HardwareBuffer.java : aggiungendo una nuova voce a @IntDef . Ad esempio, la voce per il formato RGBA_8888 viene visualizzata come segue:

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

    Se i valori dei componenti non sono normalizzati senza segno, indicare il valore esplicitamente nel nome della variabile. Ad esempio, il nome della variabile per un formato solo canale rosso a 16 bit intero senza segno deve essere R_16UI e lo stesso formato con un formato canale verde a 16 bit intero senza segno aggiuntivo deve essere RG_16UI16UI .

  7. Aggiungi il nuovo formato pixel come static int in HardwareBuffer.java , aggiungendo una nuova variabile membro pubblica alla fine di @Format :

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

    Questa voce enum deve avere lo stesso valore esadecimale di PixelFormat.aidl e hardware_buffer.h . Seguire le convenzioni esistenti.

  8. Il tentativo di compilare con queste modifiche al codice genera un errore di compilazione:

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

    Per eliminare questo errore, esegui il comando seguente, come specificato nel messaggio di errore, per modificare current.txt :

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

    L'esecuzione del comando precedente aggiorna il file corretto per poterlo compilare normalmente.

  9. Aggiungi il nuovo formato pixel ai test Java, aggiungendo il nuovo formato pixel alla fine di paramsForTestCreateOptionalFormats() in HardwareBufferTest.java , mostrato come segue:

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

Aggiungi un nuovo formato pixel all'integrazione del sistema Windows

Per utilizzare il nuovo formato pixel come formato per un framebuffer in un'API grafica, aggiungilo all'appropriata Window System Integration (WSI) per l'API grafica pertinente. Per un'app o un processo di sistema che utilizza l'API Vulkan, aggiorna Vulkan Swapchain. Per un'app o un processo di sistema che utilizza l'API OpenGL ES, aggiorna l'API EGL .

Vulkan WSI cambia per nuovi formati pixel

Aggiorna il Vulkan WSI come segue:
  1. Aggiungi un nuovo caso alla funzione GetNativePixelFormat(VkFormat format) in 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. Interroga l'estensione Vulkan se il formato pixel richiede il funzionamento di un'estensione Vulkan. Ad esempio, le estensioni laterali, utilizzare instance_data , mostrato come segue:
    bool colorspace_ext = instance_data.hook_extensions.test(ProcHook::EXT_swapchain_colorspace);
    

    Per le estensioni lato dispositivo, utilizzare quanto segue:

    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 gestisce l'infrastruttura necessaria per esporre un'istanza o un'estensione del dispositivo a swapchain.cpp . L'elenco delle modifiche iniziali non è necessario per la corretta configurazione delle estensioni dal caricatore Vulkan.

  3. Successivamente, enumera le coppie di formato e spazio colore:
    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});
    }
    

    È necessario conoscere il formato compatibile e le coppie di spazi colore.

  4. Aggiungi il nuovo formato a dEQP-VK situato in external/deqp .
  5. Aggiorna i test di conformità Vulkan in vktApiExternalMemoryTests.cpp e vktExternalMemoryUtil.cpp deducendo le modifiche richieste dalla fonte esistente o contattando il supporto Android per informazioni.

EGL cambia per i nuovi formati pixel

Aggiorna l'EGL come segue:

  1. Nella funzione getNativePixelFormat() , modifica l'albero if-else per restituire l'enumerazione AIDL per il nuovo formato pixel. Utilizzando l'esempio per il formato pixel RGBA_8888 :
    if (a == 0) {
      ...
    } else {
      if (componentType == EGL_COLOR_COMPONENT_TYPE_FIXED_EXT) {
          if (colorDepth > 24) {
              ...
          } else {
              *format = PixelFormat::RGBA_8888;
          }
      } else {
        ...
      }
    }
    
  2. Per aggiungere il nuovo formato a dEQP, aggiungi una nuova voce all'enumerazione androidFormats , mostrata come segue:
    static const GLenum androidFormats[] =
    {
      ...
      GL_RGBA8,
      ...
    };
    

Invia il tuo aggiornamento

Segui Per consentire ai contributori di creare elenchi di modifiche e condividerli con il team appropriato.