כל הפורמטים החדשים של הפיקסלים שנוספו ל-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:
- מוסיפים את פורמט הפיקסלים החדש כרשומה חדשה בסוף המאפיין
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-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
הרצת הפקודה שלמעלה מעדכנת את הקובץ הנכון כדי שאפשר יהיה לבצע 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
, מחפשים את סוף טענות הנכונות (assertions) הסטטיים שנמצאים בתוך:// ---------------------------------------------------------------------------- // 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-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 };
הוספת פורמט פיקסלים חדש לשילוב של מערכת החלונות
כדי להשתמש בפורמט הפיקסלים החדש כפורמט של 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, ... };
שליחת העדכון
פועלים לפי ההוראות במאמר למשתתפים כדי ליצור את רשימות השינויים ולשתף אותן עם הצוות המתאים.