Все новые форматы пикселей, добавляемые в 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; } }
Добавьте новый формат пикселей в
HardwareBuffer
SDK в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 };
Добавить новый формат пикселей в интеграцию с оконной системой
Чтобы использовать новый формат пикселей в качестве формата фреймбуфера в графическом API, добавьте его в соответствующую интеграцию оконной системы (WSI) для соответствующего графического API. Для приложения или системного процесса, использующего API Vulkan, обновите Vulkan Swapchain. Для приложения или системного процесса, использующего 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, если формат пикселей требует расширения 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::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 обеспечивает инфраструктуру, необходимую для предоставления расширения экземпляра или устройства файлу 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 для новых форматов пикселей
Добавьте новый случай в функцию 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; }
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
.vktApiExternalMemoryTests.cpp
и vktExternalMemoryUtil.cpp
, выведя необходимые изменения из существующего источника или обратившись в службу поддержки Android за информацией.Обновите 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, ... };
Отправьте свое обновление
Подпишитесь на рассылку для авторов , чтобы они могли ускорить составление списков изменений и поделиться ими с соответствующей командой.