Todos os novos formatos de pixel adicionados ao Android devem ser incluídos na Android Interface Definition Language (AIDL) e no Android Hardware Buffer (AHB) . O AIDL e o AHB possuem requisitos rígidos de estabilidade e padronização que exigem um processo cuidadoso ao estender a funcionalidade. Todos os novos formatos de pixel devem chegar ao AOSP e todas as atualizações devem ser confirmadas individualmente pelos especialistas da AIDL e AHB. Este processo de confirmação cuidadosa é um fator importante na padronização de quaisquer novos formatos de pixel na plataforma.
Esta página descreve as alterações necessárias no código AOSP e o processo necessário para adicionar novos formatos de pixel no AOSP.
Antes de adicionar um novo formato de pixel, baixe a fonte e carregue os patches conforme descrito em Enviando patches .Adicione um novo formato de pixel ao AIDL
Adicionar suporte para um novo formato de pixel requer alterações em ambos os arquivos PixelFormat.aidl
localizados no AIDL. Consulte hardware/interfaces/graphics/common/aidl/
para obter o código-fonte AIDL.
Para adicionar um novo pixel formal ao AIDL, siga estas etapas:
- Anexe o novo formato de pixel como uma nova entrada ao final da enumeração
PixelFormat
emPixelFormat.aidl
seguindo a convenção de código existente e definindo o valor hexadecimal de sua entrada como um a mais que a entrada anterior. Combine as alterações do seu código com as entradas anteriores. Consulte o exemplo a seguir para a entrada de formato 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,
A seguinte mensagem de erro é vista quando você cria o código após fazer alterações em
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.
Para eliminar esse erro, execute o seguinte comando, conforme especificado na mensagem de erro, para alterar
PixelFormat.aidl
no diretórioaidl_api
:m android.hardware.graphics.common-update-api
A execução do comando acima atualiza o arquivo correto para poder construir normalmente.
Adicione um novo formato de pixel ao AHB
Adicionar suporte para um novo formato de pixel requer alterações em hardware_buffer.h
e AHardwareBuffer.cpp
. Consulte frameworks/native/libs/nativewindow
para o código-fonte do AHB.
Para adicionar um novo pixel formal ao AHB, siga estas etapas:
- Em
hardware_buffer.h
, anexe o novo formato de pixel como uma nova entrada ao final da enumeraçãoAHardwareBuffer_Format
. Siga as convenções de código existentes.Usando o exemplo de formato de pixel
RGBA_8888
, adicione a nova entrada de formato de pixel da seguinte forma:/** * Corresponding formats: * Vulkan: VK_FORMAT_R8G8B8A8_UNORM * OpenGL ES: GL_RGBA8 */ AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM = 1,
Observe que o novo formato de pixel recebe um nome em AHB, que deve começar com
AHARDWAREBUFFER_FORMAT_
, seguido pelas abreviações dos canais e profundidades de bits, e terminando com a codificação. Esta entrada enum deve ter o mesmo valor hexadecimal que emPixelFormat.aidl
.Espera-se que o formato de pixel tenha um ou ambos os formatos Vulkan ou OpenGL ES associados. Especifique o formato associado quando apropriado. Se não existir nenhum formato associado, especifique
N/A
. Adicione o formato de pixel ao teste opcional no CTS, se tiver um formato OpenGL ES associado. Para fazer isso, adicione o novo formato GL a
AHardwareBufferGLTest.cpp
emAHBFormatAsString(int32_t format)
comFORMAT_CASE(...)
eGL_FORMAT_CASE(...)
para o novo formato, mostrado a seguir:const char* AHBFormatAsString(int32_t format) { switch (format) { ... FORMAT_CASE(R8G8B8A8_UNORM); ... GL_FORMAT_CASE(GL_RGB8); } return ""; }
Em seguida, adicione um novo teste a
AHardwareBufferGLTest.cpp
, mostrado a seguir: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);
Especifique pelo menos um conjunto de valores
AHardwareBuffer_Desc
. Adicione mais valores, se necessário.Em
AHardwareBuffer.cpp
, encontre o final das afirmações estáticas encontradas em:// ---------------------------------------------------------------------------- // Validate hardware_buffer.h and PixelFormat.aidl agree // ----------------------------------------------------------------------------
Acrescente um novo
static_assert
para o novo formato de pixel, usando oPixelFormat::
enum e não com a constanteHAL_PIXEL_FORMAT
. Usando o mesmo exemplo para o formato de pixelRGBA_8888
de Adicionar um novo formato de pixel ao AIDL , adicione a nova entrada de formato de pixel da seguinte maneira:static_assert(static_cast
(aidl::android::hardware::graphics::common::PixelFormat::RGBA_8888) == AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM, "HAL and AHardwareBuffer pixel format don't match"); Adicione o novo formato de pixel aos testes apropriados, anexando o novo formato de pixel ao final de
PrintAhbFormat()
emAHardwareBufferTest.cpp
. Siga a convenção de código existente, conforme mostrado abaixo:void PrintAhbFormat(std::ostream& os, uint64_t format) { switch (format) { ... FORMAT_CASE(R8G8B8A8_UNORM); default: os << "unknown"; break; } }
Adicione o novo formato de pixel ao SDK
HardwareBuffer
emHardwareBuffer.java
: anexando uma nova entrada a@IntDef
. Por exemplo, a entrada para o formatoRGBA_8888
é mostrada a seguir:@Retention(RetentionPolicy.SOURCE) @IntDef(prefix = { "RGB", "BLOB", "YCBCR_", "D_", "DS_", "S_" }, value = { ... RGBA_8888, })
Se os valores dos componentes não forem normalizados sem sinal, indique o valor explicitamente no nome da variável. Por exemplo, o nome da variável para um formato somente de canal vermelho de 16 bits de número inteiro não assinado deve ser
R_16UI
, e o mesmo formato com um formato de canal verde de 16 bits de número inteiro não assinado adicional deve serRG_16UI16UI
.Adicione o novo formato de pixel como um
static int
emHardwareBuffer.java
anexando uma nova variável de membro público no final de@Format
:@Format ... /** Format: 8 bits each red, green, blue, alpha */ public static final int RGBA_8888 = 0x1;
Esta entrada enum deve ter o mesmo valor hexadecimal de
PixelFormat.aidl
ehardware_buffer.h
. Siga as convenções existentes.- Tentar compilar com essas alterações de código gera um erro de compilação:
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. ****************************** ...
Para limpar esse erro, execute o seguinte comando, conforme especificado na mensagem de erro, para alterar
current.txt
:m api-stubs-docs-non-updatable-update-current-api
A execução do comando acima atualiza o arquivo correto para poder construir normalmente.
Adicione o novo formato de pixel aos testes Java, anexando o novo formato de pixel ao final de
paramsForTestCreateOptionalFormats()
emHardwareBufferTest.java
, mostrado a seguir:private static Object[] paramsForTestCreateOptionalFormats() { return new Integer[]{ HardwareBuffer.RGBA_8888 };
Adicione um novo formato de pixel à integração do Windows System
Para usar o novo formato de pixel como formato para um framebuffer em uma API gráfica, adicione-o ao WSI (Window System Integration) apropriado para a API gráfica relevante. Para um aplicativo ou processo de sistema usando a API Vulkan, atualize o Vulkan Swapchain. Para um aplicativo ou processo do sistema usando a API OpenGL ES, atualize a API EGL .
Mudanças no Vulkan WSI para novos formatos de pixel Atualize o Vulkan WSI da seguinte forma: Adicione um novo caso à função GetNativePixelFormat(VkFormat format)
em 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;
}
- Consulte a extensão Vulkan se o formato de pixel exigir que uma extensão Vulkan funcione. Para extensões laterais de instância, use
instance_data
, mostrado a seguir:
bool colorspace_ext = instance_data.hook_extensions.test(ProcHook::EXT_swapchain_colorspace);
Para extensões laterais do dispositivo, use o seguinte:
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;
}
}
O Google cuida da infraestrutura necessária para expor uma instância ou extensão de dispositivo a swapchain.cpp
. A lista de alterações inicial não é necessária para que as extensões sejam configuradas corretamente no carregador Vulkan.
- A seguir, enumere os pares de formato e espaço de cores:
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});
}
Você deve ter conhecimento do formato compatível e dos pares de espaços de cores.
- Adicione o novo formato ao
dEQP-VK
localizado em external/deqp
. - Atualize os testes de conformidade Vulkan em
vktApiExternalMemoryTests.cpp
e vktExternalMemoryUtil.cpp
inferindo as alterações necessárias da fonte existente ou entrando em contato com o suporte do Android para obter informações.
Mudanças de EGL para novos formatos de pixel
Adicione um novo caso à função GetNativePixelFormat(VkFormat format)
em 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
, mostrado a seguir:bool colorspace_ext = instance_data.hook_extensions.test(ProcHook::EXT_swapchain_colorspace);
Para extensões laterais do dispositivo, use o seguinte:
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; } }
O Google cuida da infraestrutura necessária para expor uma instância ou extensão de dispositivo a swapchain.cpp
. A lista de alterações inicial não é necessária para que as extensões sejam configuradas corretamente no carregador 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}); }
Você deve ter conhecimento do formato compatível e dos pares de espaços de cores.
dEQP-VK
localizado em external/deqp
.vktApiExternalMemoryTests.cpp
e vktExternalMemoryUtil.cpp
inferindo as alterações necessárias da fonte existente ou entrando em contato com o suporte do Android para obter informações.Atualize o EGL da seguinte forma:
- Na função
getNativePixelFormat()
, modifique a árvoreif-else
para retornar a enumeração AIDL para o novo formato de pixel. Usando o exemplo para o formato de pixelRGBA_8888
:if (a == 0) { ... } else { if (componentType == EGL_COLOR_COMPONENT_TYPE_FIXED_EXT) { if (colorDepth > 24) { ... } else { *format = PixelFormat::RGBA_8888; } } else { ... } }
- Para adicionar o novo formato ao dEQP, adicione uma nova entrada ao enum
androidFormats
, mostrado a seguir:static const GLenum androidFormats[] = { ... GL_RGBA8, ... };
Envie sua atualização
Siga para que os colaboradores criem suas listas de alterações e as compartilhem com a equipe apropriada.