Все новые форматы пикселей, добавляемые в 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-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.
Чтобы устранить эту ошибку, выполните следующую команду, как указано в сообщении об ошибке, чтобы изменить
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-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. ****************************** ...
Чтобы устранить эту ошибку, выполните следующую команду, указанную в сообщении об ошибке, чтобы изменить
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. Для приложения или системного процесса, использующего Vulkan API, обновите 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, ... };
Отправьте свое обновление
Следуйте инструкциям для участников , чтобы составить списки изменений и поделиться ими с соответствующей командой.