Android에 추가된 모든 새로운 픽셀 형식은 Android 인터페이스 정의 언어(AIDL)와 Android 하드웨어 버퍼(AHB)에 포함되어야 합니다. AIDL과 AHB에는 기능을 확장할 때 신중한 프로세스가 필요한 엄격한 안정성 및 표준화 요구사항이 있습니다. 모든 새로운 픽셀 형식은 AOSP에 포함되어야 하며 모든 업데이트는 AIDL 전문가와 AHB 전문가가 개별적으로 확인해야 합니다. 이러한 신중한 확인 프로세스는 플랫폼에서 새로운 픽셀 형식을 표준화하는 데 중요한 요소입니다.
이 페이지에서는 필요한 AOSP 코드 변경사항과 AOSP에서 새로운 픽셀 형식을 추가하는 데 필요한 프로세스를 간략하게 설명합니다.
새로운 픽셀 형식을 추가하기 전에 소스를 다운로드하고 패치 제출에 설명된 대로 패치를 업로드하세요.AIDL에 새 픽셀 형식 추가
새 픽셀 형식 지원을 추가하려면 AIDL 내에 있는 PixelFormat.aidl
파일 두 개를 모두 변경해야 합니다. AIDL 소스 코드는 hardware/interfaces/graphics/common/aidl/
을 참고하세요.
AIDL에 새 픽셀 형식을 추가하려면 다음 단계를 따르세요.
- 기존 코드 규칙을 따르고 항목의 16진수 값을 이전 항목보다 1 크게 설정하여
PixelFormat.aidl
의PixelFormat
enum 끝에 새 픽셀 형식을 새로운 항목으로 추가합니다. 코드 변경사항을 이전 항목과 일치시킵니다.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.
-
이 오류를 해결하려면 오류 메시지에 지정된 대로 다음 명령어를 실행하여
aidl_api
디렉터리의PixelFormat.aidl
을 변경합니다.m android.hardware.graphics.common-update-api
위의 명령어를 실행하면 정상적으로 빌드할 수 있도록 올바른 파일이 업데이트됩니다.
AHB에 새 픽셀 형식 추가
새 픽셀 형식 지원을 추가하려면 hardware_buffer.h
및 AHardwareBuffer.cpp
를 변경해야 합니다.
AHB 소스 코드는 frameworks/native/libs/nativewindow
를 참고하세요.
AHB에 새 픽셀 형식을 추가하려면 다음 단계를 따르세요.
hardware_buffer.h
에서AHardwareBuffer_Format
enum 끝에 새 픽셀 형식을 새로운 항목으로 추가합니다. 기존 코드 규칙을 따릅니다.RGBA_8888
픽셀 형식 예를 사용하여 새 픽셀 형식 항목을 다음과 같이 추가하세요./** * Corresponding formats: * Vulkan: VK_FORMAT_R8G8B8A8_UNORM * OpenGL ES: GL_RGBA8 */ AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM = 1,
새 픽셀 형식은 AHB에서 이름이 지정되며
AHARDWAREBUFFER_FORMAT_
으로 시작하고 그 뒤에 채널 약어와 비트 심도가 오고 인코딩으로 끝나야 합니다. 이 enum 항목에는PixelFormat.aidl
의 값과 동일한 16진수 값이 있어야 합니다.픽셀 형식은 연결된 Vulkan이나 OpenGL ES 형식 중 하나 또는 둘 다를 보유할 것으로 예상됩니다. 적절한 경우 연결된 형식을 지정하세요. 연결된 형식이 없으면
N/A
를 지정합니다.-
연결된 OpenGL ES 형식이 있다면 CTS 아래 선택적 테스트에 픽셀 형식을 추가합니다. 이렇게 하려면 다음과 같이 새 형식의
FORMAT_CASE(...)
및GL_FORMAT_CASE(...)
를 사용하여 새 GL 형식을AHBFormatAsString(int32_t format)
의AHardwareBufferGLTest.cpp
에 추가합니다.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 // ----------------------------------------------------------------------------
HAL_PIXEL_FORMAT
상수가 아닌PixelFormat::
enum을 사용하여 새 픽셀 형식의 새static_assert
를 추가합니다. AIDL에 새 픽셀 형식 추가의 동일한RGBA_8888
픽셀 형식 예를 사용하여 다음과 같이 새 픽셀 형식 항목을 추가합니다.static_assert(static_cast
(aidl::android::hardware::graphics::common::PixelFormat::RGBA_8888) == AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM, "HAL and AHardwareBuffer pixel format don't match"); -
새 픽셀 형식을
AHardwareBufferTest.cpp
의PrintAhbFormat()
끝에 추가하여 새 픽셀 형식을 적절한 테스트에 추가합니다. 기존 코드 규칙을 따릅니다(아래 참고).void PrintAhbFormat(std::ostream& os, uint64_t format) { switch (format) { ... FORMAT_CASE(R8G8B8A8_UNORM); default: os << "unknown"; break; } }
-
새 항목을
@IntDef
에 추가하여 새 픽셀 형식을HardwareBuffer.java
의HardwareBuffer
SDK에 추가합니다. 예를 들어RGBA_8888
형식의 항목은 다음과 같습니다.@Retention(RetentionPolicy.SOURCE) @IntDef(prefix = { "RGB", "BLOB", "YCBCR_", "D_", "DS_", "S_" }, value = { ... RGBA_8888, })
구성요소 값이 부호 없이 정규화되지 않은 경우 변수 이름에 값을 명시적으로 표시합니다. 예를 들어 부호 없는 정수 16비트 빨간색 채널 전용 형식의 변수 이름은
R_16UI
여야 하고 부호 없는 정수 16비트 녹색 채널 형식이 추가된 동일한 형식은RG_16UI16UI
여야 합니다. -
새 공개 멤버 변수를
@Format
끝에 추가하여 새 픽셀 형식을HardwareBuffer.java
에static int
로 추가합니다.@Format ... /** Format: 8 bits each red, green, blue, alpha */ public static final int RGBA_8888 = 0x1;
이 enum 항목에는
PixelFormat.aidl
및hardware_buffer.h
의 값과 동일한 16진수 값이 있어야 합니다. 기존 규칙을 따릅니다. -
이러한 코드 변경사항으로 빌드하려고 하면 다음과 같이 빌드 오류가 발생합니다.
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
위의 명령어를 실행하면 정상적으로 빌드할 수 있도록 올바른 파일이 업데이트됩니다.
-
다음과 같이 새 픽셀 형식을
HardwareBufferTest.java
의paramsForTestCreateOptionalFormats()
끝에 추가하여 Java 테스트에 새 픽셀 형식을 추가합니다.private static Object[] paramsForTestCreateOptionalFormats() { return new Integer[]{ HardwareBuffer.RGBA_8888 };
Window System Integration에 새 픽셀 형식 추가
그래픽 API에서 프레임 버퍼의 형식으로 새 픽셀 형식을 사용하려면 관련 그래픽 API의 적절한 Window System Integration(WSI)에 추가하세요. Vulkan API를 사용하는 앱 또는 시스템 프로세스의 경우 Vulkan Swapchain을 업데이트합니다. OpenGL ES API를 사용하는 앱 또는 시스템 프로세스의 경우 EGL API를 업데이트하세요.
새 픽셀 형식을 위한 Vulkan WSI 변경사항
다음과 같이 Vulkan WSI를 업데이트하세요.-
swapchain.cpp
의GetNativePixelFormat(VkFormat format)
함수에 새 사례를 추가합니다.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}); }
호환되는 형식과 색상 공간 쌍에 관한 지식이 있어야 합니다.
external/deqp
에 있는dEQP-VK
에 새 형식을 추가합니다.- 기존 소스에서 필요한 변경사항을 추론하거나 Android 지원팀에 문의하여
vktApiExternalMemoryTests.cpp
및vktExternalMemoryUtil.cpp
에서 Vulkan 적합성 테스트를 업데이트합니다.
새 픽셀 형식을 위한 EGL 변경사항
다음과 같이 EGL을 업데이트하세요.
getNativePixelFormat()
함수에서 새 픽셀 형식의 AIDL enum을 반환하도록if-else
트리를 수정합니다. 다음과 같이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
enum에 새 항목을 추가합니다.static const GLenum androidFormats[] = { ... GL_RGBA8, ... };
업데이트 제출
기여자를 따라 변경 목록을 작성하고 담당팀과 공유하세요.