כל הפורמטים החדשים של הפיקסלים שנוספו ל-Android חייבים להיכלל בשפת הגדרה לבניית ממשק Android (AIDL) ובAndroid Hardware Buffer (AHB). ל-AIDL ול-AHB יש דרישות קפדניות של יציבות וסטנדרטיזציה, שמחייבות תהליך זהיר כשמגדילים את הפונקציונליות. כל הפורמטים החדשים של הפיקסלים חייבים להיכנס ל-AOSP, וכל העדכונים חייבים לקבל אישור בנפרד על ידי מומחי AIDL ו-AHB. תהליך האישור הזה הוא גורם חשוב ביצירת סטנדרטים לפורמטים חדשים של פיקסלים בפלטפורמה.
בדף הזה מפורטים השינויים הנדרשים בקוד של AOSP והתהליך הנדרש להוספת פורמטים חדשים של פיקסלים ב-AOSP.
לפני שמוסיפים פורמט פיקסלים חדש, צריך להוריד את המקור ולהעלות תיקונים כפי שמתואר בקטע שליחת תיקונים.הוספת פורמט פיקסלים חדש ל-AIDL
כדי להוסיף תמיכה בפורמט פיקסלים חדש, צריך לבצע שינויים בשני הקבצים PixelFormat.aidl
שנמצאים ב-AIDL. קוד המקור של AIDL זמין ב-hardware/interfaces/graphics/common/aidl/
.
כדי להוסיף פורמט פיקסל חדש ל-AIDL:
- מוסיפים את פורמט הפיקסלים החדש כרשומה חדשה בסוף המאפיין המסווג (enum)
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,
הודעת השגיאה הבאה מופיעה כשמפעילים את ה-build של הקוד אחרי שמבצעים שינויים ב-
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
הרצת הפקודה שלמעלה מעדכנת את הקובץ הנכון כדי שאפשר יהיה לבצע build באופן תקין.
הוספת פורמט פיקסלים חדש ל-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; } }
-
מוסיפים את פורמט הפיקסלים החדש ל-SDK של
HardwareBuffer
בקטע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
. פועלים לפי המוסכמות קיימות. -
ניסיון לבצע build עם השינויים האלה בקוד יגרום לשגיאת build:
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
הרצת הפקודה שלמעלה מעדכנת את הקובץ הנכון כדי שאפשר יהיה לבצע build באופן תקין.
-
מוסיפים את פורמט הפיקסלים החדש לבדיקות Java. לשם כך, מוסיפים את פורמט הפיקסלים החדש בסוף השדה
paramsForTestCreateOptionalFormats()
בקובץHardwareBufferTest.java
, כפי שמתואר בהמשך:private static Object[] paramsForTestCreateOptionalFormats() { return new Integer[]{ HardwareBuffer.RGBA_8888 };
הוספת פורמט פיקסלים חדש לשילוב עם Window System
כדי להשתמש בפורמט הפיקסלים החדש כפורמט של framebuffer ב-API של גרפיקה, צריך להוסיף אותו לשילוב המתאים של מערכת החלונות (WSI) ל-API הגרפיקה הרלוונטי. באפליקציה או בתהליך מערכת שמשתמשים ב-Vulkan API, מעדכנים את Vulkan Swapchain. באפליקציה או בתהליך מערכת שמשתמשים ב-OpenGL ES API, צריך לעדכן את ה-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 לפורמטים חדשים של פיקסלים
מעדכנים את ה-EGL באופן הבא:
- בפונקציה
getNativePixelFormat()
, משנים את העץif-else
כך שיחזיר את המאפיין enum של 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, ... };
שליחת העדכון
פועלים לפי ההוראות במאמר למשתתפים בפרויקט כדי ליצור את רשימות השינויים ולשתף אותן עם הצוות המתאים.