Все новые форматы пикселей, добавленные в Android, должны быть включены в Android Interface Definition Language (AIDL) и в Android Hardware Buffer (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
из Add a new pixel format to 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 };
Добавить новый формат пикселей в интеграцию с системой Windows
Чтобы использовать новый формат пикселей в качестве формата для буфера кадров в графическом API, добавьте его в соответствующую Window System Integration (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, ... };
Отправьте свое обновление
Подпишитесь на рассылку для участников , чтобы они могли составить свои списки изменений и поделиться ими с соответствующей командой.