Tous les nouveaux formats de pixels ajoutés à Android doivent être inclus dans le langage AIDL (Android Interface Definition Language) et dans le tampon matériel Android (AHB) . L'AIDL et l'AHB ont des exigences strictes en matière de stabilité et de normalisation qui nécessitent un processus minutieux lors de l'extension des fonctionnalités. Tous les nouveaux formats de pixels doivent atterrir dans AOSP et toutes les mises à jour doivent être confirmées individuellement par les experts AIDL et AHB. Ce processus de confirmation minutieuse est un facteur important dans la normalisation de tout nouveau format de pixel sur la plateforme.
Cette page décrit les modifications nécessaires du code AOSP et le processus requis pour ajouter de nouveaux formats de pixels sur AOSP.
Avant d'ajouter un nouveau format de pixel, téléchargez la source et téléchargez les correctifs comme indiqué dans Soumission 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 des deux fichiers PixelFormat.aidl
situés dans AIDL. Voir hardware/interfaces/graphics/common/aidl/
pour le code source AIDL.
Pour ajouter un nouveau pixel formel à 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 de plus que l'entrée précédente. Faites correspondre vos modifications de code aux entrées précédentes. Voir 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 créez le code après avoir apporté des modifications à
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 effacer cette erreur, exécutez la commande suivante, comme spécifié 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 met à jour le fichier correct pour pouvoir construire 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 de hardware_buffer.h
et AHardwareBuffer.cpp
. Voir frameworks/native/libs/nativewindow
pour 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
. Suivez 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 reçoit un nom en AHB, qui doit commencer par
AHARDWAREBUFFER_FORMAT_
, suivi des abréviations de canal 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 devrait avoir l'un ou les deux formats associés Vulkan ou OpenGL ES . Précisez le format associé le cas échéant. Si aucun format associé n'existe, précisez
N/A
. Ajoutez le format de pixel aux tests facultatifs sous 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, affiché comme suit :const char* AHBFormatAsString(int32_t format) { switch (format) { ... FORMAT_CASE(R8G8B8A8_UNORM); ... GL_FORMAT_CASE(GL_RGB8); } return ""; }
Ensuite, ajoutez un nouveau test à
AHardwareBufferGLTest.cpp
, affiché comme suit :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
. Ajoutez plus de valeurs si nécessaire.Dans
AHardwareBuffer.cpp
, recherchez la fin des assertions statiques trouvées dans :// ---------------------------------------------------------------------------- // Validate hardware_buffer.h and PixelFormat.aidl agree // ----------------------------------------------------------------------------
Ajoutez un nouveau
static_assert
pour le nouveau format de pixel, en utilisant l'énumérationPixelFormat::
et non avec la constanteHAL_PIXEL_FORMAT
. En utilisant le même exemple pour le format de pixelRGBA_8888
de Add a new pixel format to 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
s'affiche 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 variable pour un format de canal rouge de 16 bits entier non signé uniquement doit être
R_16UI
, et le même format avec un format de canal vert de 16 bits entier non signé supplémentaire doit êtreRG_16UI16UI
.Ajoutez le nouveau format de pixel en tant
static int
dansHardwareBuffer.java
, en ajoutant une nouvelle variable 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
. Suivez les conventions existantes.- Toute tentative de build avec ces modifications de code génère une erreur de build :
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 spécifié 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 correct pour pouvoir construire normalement.
Ajoutez le nouveau format de pixel aux tests Java, en ajoutant le nouveau format de pixel à la fin de
paramsForTestCreateOptionalFormats()
dansHardwareBufferTest.java
, comme suit :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 d'un framebuffer dans une API graphique, ajoutez-le au Window System Integration (WSI) approprié pour l'API graphique appropriée. Pour une application ou un processus système utilisant l'API Vulkan, mettez à jour la Vulkan Swapchain. Pour une application ou un processus système utilisant l’API OpenGL ES, mettez à jour l’API EGL .
Modifications de Vulkan WSI pour les nouveaux formats de pixels Mettez à jour le Vulkan WSI comme suit : Ajoutez un nouveau cas à la fonction GetNativePixelFormat(VkFormat format)
dans 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;
}
- Recherchez l'extension Vulkan si le format de pixel nécessite une extension Vulkan pour fonctionner. Pour les extensions côté instance, utilisez
instance_data
, affichées comme suit :
bool colorspace_ext = instance_data.hook_extensions.test(ProcHook::EXT_swapchain_colorspace);
Pour les extensions côté appareil, utilisez ce qui suit :
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 de périphérique à swapchain.cpp
. La liste de modifications initiale n'est pas nécessaire pour que les extensions soient correctement configurées à partir du chargeur Vulkan.
- Ensuite, énumérez les paires de format et d'espace colorimétrique :
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 d’espaces colorimétriques compatibles.
- Ajoutez le nouveau format à
dEQP-VK
situé dans external/deqp
. - Mettez à jour les tests de conformité Vulkan dans
vktApiExternalMemoryTests.cpp
et vktExternalMemoryUtil.cpp
en déduisant les modifications requises à partir de la source existante ou en contactant votre support Android pour obtenir des informations.
Modifications EGL pour les nouveaux formats de pixels
Ajoutez un nouveau cas à la fonction GetNativePixelFormat(VkFormat format)
dans 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; }
instance_data
, affichées comme suit :bool colorspace_ext = instance_data.hook_extensions.test(ProcHook::EXT_swapchain_colorspace);
Pour les extensions côté appareil, utilisez ce qui suit :
bool rgba10x6_formats_ext = false; uint32_t exts_count; const auto& driver = GetData(pdev).driver; driver.EnumerateDeviceExtensionProperties(pdev, nullptr, &exts_count, nullptr); std::vectorprops(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 de périphérique à swapchain.cpp
. La liste de modifications initiale n'est pas nécessaire pour que les extensions soient correctement configurées à partir du chargeur Vulkan.
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 d’espaces colorimétriques compatibles.
dEQP-VK
situé dans external/deqp
.vktApiExternalMemoryTests.cpp
et vktExternalMemoryUtil.cpp
en déduisant les modifications requises à partir de la source existante ou en contactant votre support Android pour obtenir des informations.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 nouvelle entrée à l'énumération
androidFormats
, affichée comme suit :static const GLenum androidFormats[] = { ... GL_RGBA8, ... };
Soumettez votre mise à jour
Suivez Pour les contributeurs pour faire tourner vos listes de modifications et les partager avec l'équipe appropriée.