Tous les nouveaux formats de pixel ajoutés à Android doivent être inclus dans le langage de définition d'interface Android (AIDL) et dans le tampon matériel Android (AHB). L'AIDL et l'AHB ont des exigences strictes en matière de stabilité et de standardisation qui nécessitent un processus minutieux lors de l'extension des fonctionnalités. Tous les nouveaux formats de pixels doivent être intégrés à AOSP, et toutes les mises à jour doivent être confirmées individuellement par des experts AIDL et AHB. Ce processus de confirmation minutieuse est un facteur important pour la standardisation de tout nouveau format de pixel sur la plate-forme.
Cette page décrit les modifications de code AOSP nécessaires et le processus requis pour ajouter de nouveaux formats de pixel sur AOSP.
Avant d'ajouter un format de pixel, téléchargez la source et importez les correctifs comme indiqué dans la section Envoyer des correctifs.Ajouter un nouveau format de pixel à AIDL
L'ajout de la prise en charge d'un nouveau format de pixel nécessite des modifications dans les deux fichiers PixelFormat.aidl
situés dans AIDL. Consultez hardware/interfaces/graphics/common/aidl/
pour obtenir le code source AIDL.
Pour ajouter une nouvelle forme de pixel à AIDL, procédez comme suit:
- Ajoutez le nouveau format de pixel en tant que nouvelle entrée à la fin de l'énumération
PixelFormat
dansPixelFormat.aidl
en suivant la convention de code existante et en définissant la valeur hexadécimale de votre entrée sur une valeur supérieure à celle de l'entrée précédente. Faites correspondre vos modifications de code aux entrées précédentes. Consultez l'exemple suivant pour l'entrée de format de pixelRGBA_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,
Le message d'erreur suivant s'affiche lorsque vous compilez le code après avoir modifié
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.
-
Pour corriger cette erreur, exécutez la commande suivante, comme indiqué dans le message d'erreur, pour modifier
PixelFormat.aidl
dans le répertoireaidl_api
:m android.hardware.graphics.common-update-api
L'exécution de la commande ci-dessus permet de mettre à jour le fichier approprié afin de pouvoir compiler normalement.
Ajouter un nouveau format de pixel à AHB
L'ajout de la prise en charge d'un nouveau format de pixel nécessite des modifications dans hardware_buffer.h
et AHardwareBuffer.cpp
.
Consultez frameworks/native/libs/nativewindow
pour obtenir le code source AHB.
Pour ajouter un nouveau pixel formel à AHB, procédez comme suit:
- Dans
hardware_buffer.h
, ajoutez le nouveau format de pixel en tant que nouvelle entrée à la fin de l'énumérationAHardwareBuffer_Format
. Respectez les conventions de code existantes.À l'aide de l'exemple de format de pixel
RGBA_8888
, ajoutez la nouvelle entrée de format de pixel comme suit:/** * Corresponding formats: * Vulkan: VK_FORMAT_R8G8B8A8_UNORM * OpenGL ES: GL_RGBA8 */ AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM = 1,
Notez que le nouveau format de pixel est associé à un nom en AHB, qui doit commencer par
AHARDWAREBUFFER_FORMAT_
, suivi des abréviations des canaux et des profondeurs de bits, et se terminer par l'encodage. Cette entrée d'énumération doit avoir la même valeur hexadécimale que celle dePixelFormat.aidl
.Le format de pixel doit avoir un ou deux formats Vulkan ou OpenGL ES associés. Spécifiez le format associé, le cas échéant. Si aucun format associé n'existe, spécifiez
N/A
. -
Ajoutez le format de pixel aux tests facultatifs dans CTS, s'il est associé à un format OpenGL ES. Pour ce faire, ajoutez le nouveau format GL à
AHardwareBufferGLTest.cpp
dansAHBFormatAsString(int32_t format)
avecFORMAT_CASE(...)
etGL_FORMAT_CASE(...)
pour le nouveau format, comme indiqué ci-dessous:const char* AHBFormatAsString(int32_t format) { switch (format) { ... FORMAT_CASE(R8G8B8A8_UNORM); ... GL_FORMAT_CASE(GL_RGB8); } return ""; }
-
Ajoutez ensuite un nouveau test à
AHardwareBufferGLTest.cpp
, comme illustré ci-dessous: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);
Spécifiez au moins un ensemble de valeurs
AHardwareBuffer_Desc
. Si nécessaire, ajoutez d'autres valeurs. -
Dans
AHardwareBuffer.cpp
, recherchez la fin des assertions statiques trouvées dans:// ---------------------------------------------------------------------------- // Validate hardware_buffer.h and PixelFormat.aidl agree // ----------------------------------------------------------------------------
Ajoutez un nouvel élément
static_assert
pour le nouveau format de pixel, à l'aide de l'énumérationPixelFormat::
et non avec la constanteHAL_PIXEL_FORMAT
. En utilisant le même exemple pour le format de pixelRGBA_8888
de la section Ajouter un format de pixel à AIDL, ajoutez la nouvelle entrée de format de pixel comme suit:static_assert(static_cast
(aidl::android::hardware::graphics::common::PixelFormat::RGBA_8888) == AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM, "HAL and AHardwareBuffer pixel format don't match"); -
Ajoutez le nouveau format de pixel aux tests appropriés en ajoutant le nouveau format de pixel à la fin de
PrintAhbFormat()
dansAHardwareBufferTest.cpp
. Suivez la convention de code existante, comme indiqué ci-dessous:void PrintAhbFormat(std::ostream& os, uint64_t format) { switch (format) { ... FORMAT_CASE(R8G8B8A8_UNORM); default: os << "unknown"; break; } }
-
Ajoutez le nouveau format de pixel au SDK
HardwareBuffer
dansHardwareBuffer.java
: en ajoutant une nouvelle entrée à@IntDef
. Par exemple, l'entrée pour le formatRGBA_8888
est présentée comme suit:@Retention(RetentionPolicy.SOURCE) @IntDef(prefix = { "RGB", "BLOB", "YCBCR_", "D_", "DS_", "S_" }, value = { ... RGBA_8888, })
Si les valeurs des composants ne sont pas normalisées sans signe, indiquez la valeur explicitement dans le nom de la variable. Par exemple, le nom de la variable pour un format de canal rouge 16 bits entier non signé uniquement doit être
R_16UI
, et le même format avec un format de canal vert 16 bits entier non signé supplémentaire doit êtreRG_16UI16UI
. -
Ajoutez le nouveau format de pixel en tant que
static int
dansHardwareBuffer.java
, en ajoutant une nouvelle variable de membre publique à la fin de@Format
:@Format ... /** Format: 8 bits each red, green, blue, alpha */ public static final int RGBA_8888 = 0x1;
Cette entrée d'énumération doit avoir la même valeur hexadécimale que celle de
PixelFormat.aidl
ethardware_buffer.h
. Respectez les conventions existantes. -
Toute tentative de compilation avec ces modifications de code génère une erreur de compilation:
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. ****************************** ...
Pour effacer cette erreur, exécutez la commande suivante, comme indiqué dans le message d'erreur, pour modifier
current.txt
:m api-stubs-docs-non-updatable-update-current-api
L'exécution de la commande ci-dessus met à jour le fichier approprié pour permettre la compilation normale.
-
Ajoutez le nouveau format de pixel aux tests Java en ajoutant le nouveau format de pixel à la fin de
paramsForTestCreateOptionalFormats()
dansHardwareBufferTest.java
, comme illustré ci-dessous:private static Object[] paramsForTestCreateOptionalFormats() { return new Integer[]{ HardwareBuffer.RGBA_8888 };
Ajouter un nouveau format de pixel à l'intégration du système Windows
Pour utiliser le nouveau format de pixel comme format de framebuffer dans une API de graphisme, ajoutez-le à l'intégration de système Windows (WSI, Window System Integration) appropriée pour cette API. Pour une application ou un processus système utilisant l'API Vulkan, mettez à jour le swapchain Vulkan. Pour une application ou un processus système utilisant l'API OpenGL ES, mettez à jour l'API EGL.
Modifications apportées à Vulkan WSI pour les nouveaux formats de pixel
Mettez à jour le WSI Vulkan comme suit :-
Ajoutez un cas à la fonction
GetNativePixelFormat(VkFormat format)
dansswapchain.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; }
- Interrogez l'extension Vulkan si le format de pixel nécessite une extension Vulkan pour fonctionner.
Pour les extensions côté instance, utilisez
instance_data
, comme suit :bool colorspace_ext = instance_data.hook_extensions.test(ProcHook::EXT_swapchain_colorspace);
Pour les extensions côté appareil, utilisez les éléments suivants:
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 gère l'infrastructure requise pour exposer une instance ou une extension d'appareil à
swapchain.cpp
. La liste de modifications initiale n'est pas nécessaire pour configurer correctement les extensions à partir du chargeur Vulkan. - Ensuite, énumérez les paires de format et de couleur :
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}); }
Vous devez connaître les paires de formats et de jeux de couleurs compatibles.
- Ajoutez le nouveau format à
dEQP-VK
, situé dansexternal/deqp
. - Mettez à jour les tests de conformité Vulkan dans
vktApiExternalMemoryTests.cpp
etvktExternalMemoryUtil.cpp
en inférant les modifications requises à partir de la source existante ou en contactant l'assistance Android pour en savoir plus.
Modifications des EGL pour les nouveaux formats de pixel
Mettez à jour l'EGL comme suit:
- Dans la fonction
getNativePixelFormat()
, modifiez l'arborescenceif-else
pour renvoyer l'énumération AIDL pour le nouveau format de pixel. En utilisant l'exemple du format de pixelRGBA_8888
:if (a == 0) { ... } else { if (componentType == EGL_COLOR_COMPONENT_TYPE_FIXED_EXT) { if (colorDepth > 24) { ... } else { *format = PixelFormat::RGBA_8888; } } else { ... } }
- Pour ajouter le nouveau format à dEQP, ajoutez une entrée à l'énumération
androidFormats
, comme suit :static const GLenum androidFormats[] = { ... GL_RGBA8, ... };
Envoyer votre mise à jour
Suivez les instructions de la section Pour les contributeurs pour créer vos listes de modifications et les partager avec l'équipe appropriée.