Все новые форматы пикселей, добавляемые в Android, должны быть включены в язык определения интерфейса Android (AIDL) и в аппаратный буфер Android (AHB) . AIDL и AHB предъявляют строгие требования к стабильности и стандартизации, что требует тщательного процесса при расширении функциональности. Все новые форматы пикселей должны быть включены в AOSP, и все обновления должны быть индивидуально подтверждены экспертами по AIDL и AHB. Этот процесс тщательного подтверждения является важным фактором стандартизации любых новых форматов пикселей на платформе.
На этой странице описаны необходимые изменения в коде AOSP и процесс добавления новых форматов пикселей в AOSP.
Перед добавлением нового формата пикселей загрузите исходный код и загрузите исправления, как описано в разделе «Отправка исправлений» .
В AIDL добавлен новый формат пикселей.
Для добавления поддержки нового формата пикселей необходимо внести изменения в оба файла PixelFormat.aidl , расположенные в AIDL. Исходный код AIDL можно найти в hardware/interfaces/graphics/common/aidl/ .
Чтобы добавить новый формат пикселей в AIDL, выполните следующие действия:
- Добавьте новый формат пикселей в качестве новой записи в конец перечисления
PixelFormatв файлеPixelFormat.aidl, следуя существующему соглашению о кодировании и установив шестнадцатеричное значение для вашей записи на единицу больше, чем у предыдущей записи. Согласуйте ваши изменения кода с предыдущими записями. См. следующий пример для записи формата пикселей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.
Для устранения этой ошибки выполните следующую команду, указанную в сообщении об ошибке, чтобы изменить
PixelFormat.aidlв каталогеaidl_api:m android.hardware.graphics.common-update-api
Выполнение указанной выше команды обновляет необходимый файл, что позволяет выполнить сборку в обычном режиме.
Добавить новый формат пикселей в AHB
Для добавления поддержки нового формата пикселей требуются изменения в файлах hardware_buffer.h и AHardwareBuffer.cpp . Исходный код AHB можно найти в frameworks/native/libs/nativewindow .
Чтобы добавить новый формат пикселей в AHB, выполните следующие действия:
- В
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 или OpenGL ES . Укажите связанный формат, если это необходимо. Если связанный формат отсутствует, укажите
N/A. Добавьте формат пикселей в необязательное тестирование в рамках CTS, если для него существует связанный формат OpenGL ES. Для этого добавьте новый формат GL в файл
AHardwareBufferGLTest.cppвAHBFormatAsString(int32_t format)сFORMAT_CASE(...)иGL_FORMAT_CASE(...)для нового формата, как показано ниже:const char* AHBFormatAsString(int32_t format) { switch (format) { ... FORMAT_CASE(R8G8B8A8_UNORM); ... GL_FORMAT_CASE(GL_RGB8); } return ""; }Далее добавьте новый тест в файл
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. При необходимости добавьте другие значения.В файле
AHardwareBuffer.cppнайдите конец статических утверждений, расположенных внутри:// ---------------------------------------------------------------------------- // Validate hardware_buffer.h and PixelFormat.aidl agree // ----------------------------------------------------------------------------
Добавьте новый
static_assertдля нового формата пикселей, используяPixelFormat::, а не константуHAL_PIXEL_FORMAT. Используя тот же пример для формата пикселейRGBA_8888из раздела «Добавление нового формата пикселей в AIDL» , добавьте запись о новом формате пикселей следующим образом:static_assert(static_cast
(aidl::android::hardware::graphics::common::PixelFormat::RGBA_8888) == AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM, "HAL and AHardwareBuffer pixel format don't match"); Добавьте новый формат пикселей в соответствующие тесты, указав его в конце функции
PrintAhbFormat()в файлеAHardwareBufferTest.cpp. Следуйте существующему соглашению об использовании кода, как показано ниже:void PrintAhbFormat(std::ostream& os, uint64_t format) { switch (format) { ... FORMAT_CASE(R8G8B8A8_UNORM); default: os << "unknown"; break; } }Добавьте новый формат пикселей в SDK
HardwareBufferвHardwareBuffer.java, добавив новую запись в аннотацию@IntDef. Например, запись для форматаRGBA_8888выглядит следующим образом:@Retention(RetentionPolicy.SOURCE) @IntDef(prefix = { "RGB", "BLOB", "YCBCR_", "D_", "DS_", "S_" }, value = { ... RGBA_8888, })Если значения компонентов не нормализованы как беззнаковые, укажите значение явно в имени переменной. Например, имя переменной для формата только красного канала с 16-битным беззнаковым целым числом должно быть
R_16UI, а для того же формата с дополнительным 16-битным беззнаковым целым числом для зеленого канала —RG_16UI16UI.Добавьте новый формат пикселей в виде
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. Следуйте существующим соглашениям.- Попытка сборки с этими изменениями в коде приводит к ошибке сборки:
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
Выполнение указанной выше команды обновляет необходимый файл, что позволяет выполнить сборку в обычном режиме.
Добавьте новый формат пикселей в Java-тесты, указав его в конце метода
paramsForTestCreateOptionalFormats()вHardwareBufferTest.java, как показано ниже:private static Object[] paramsForTestCreateOptionalFormats() { return new Integer[]{ HardwareBuffer.RGBA_8888 };
Добавьте новый формат пикселей в интеграцию с Windows System.
Чтобы использовать новый формат пикселей в качестве формата буфера кадров в графическом API, добавьте его в соответствующий файл интеграции с оконной системой (WSI) для соответствующего графического API. Для приложения или системного процесса, использующего API Vulkan, обновите цепочку обмена Vulkan. Для приложения или системного процесса, использующего API OpenGL ES, обновите API EGL .
Изменения в Vulkan WSI для новых форматов пикселей.
Обновите файл Vulkan WSI следующим образом:
Добавьте новый вариант в функцию
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; }- Если для работы формата пикселей требуется расширение 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::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 обеспечивает инфраструктуру, необходимую для предоставления доступа к расширению экземпляра или устройства через
swapchain.cpp. Первоначальный список изменений не требуется для корректной настройки расширений загрузчиком 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}); }Необходимо обладать знаниями о совместимых парах форматов и цветовых пространств.
- Добавьте новый формат в
dEQP-VK, расположенный по адресуexternal/deqp. - Обновите тесты на соответствие стандарту Vulkan в файлах
vktApiExternalMemoryTests.cppиvktExternalMemoryUtil.cpp, определив необходимые изменения на основе существующего исходного кода или обратившись за информацией в службу поддержки Android.
Изменения в EGL для новых форматов пикселей.
Обновите EGL следующим образом:
- В функции
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 { ... } } - Чтобы добавить новый формат в dEQP, добавьте новую запись в перечисление
androidFormats, как показано ниже:static const GLenum androidFormats[] = { ... GL_RGBA8, ... };
Отправьте ваше обновление
Чтобы участники проекта могли создавать свои списки изменений и делиться ими с соответствующей командой, воспользуйтесь соответствующей ссылкой.