ב-Android 13 נוספה ספרייה סטטית שניתן להגדיר על ידי הספקים, שנקראת libtonemap
. הספרייה הזו מגדירה פעולות של מיפוי גוונים, והיא משותפת לתהליך SurfaceFlinger ולהטמעות של Hardware Composer (HWC).
התכונה הזו מאפשרת ליצרני ציוד מקורי להגדיר ולשתף את האלגוריתמים שלהם למיפוי גוונים של תצוגה בין המסגרת לבין הספקים, וכך לצמצם את חוסר ההתאמה במיפוי הגוונים.
לפני Android 13, פעולות המיפוי של גווני התצוגה לא היו משותפות בין HWC, SurfaceFlinger והאפליקציות. בהתאם לנתיב העיבוד, תוכן HDR הוביל לחוסר התאמה באיכות התמונה, כאשר תוכן ה-HDR הותאם לגוון במרחב פלט בדרכים שונות. ניתן היה לראות זאת בתרחישים כמו סיבוב המסך, שבהם אסטרטגיית ההרכבה משתנה בין ה-GPU ל-DPU, ובהבדלים בהתנהגות הרינדור בין TextureView לבין SurfaceView.
בדף הזה מתוארים הממשק, ההתאמה האישית ופרטי האימות של ספריית libtonemap
.
ממשק לספריית מיפוי הגוונים
הספרייה libtonemap
מכילה הטמעות שמגובות על ידי מעבד (CPU) ו-shaders של SkSL, שאפשר לחבר ל-SurfaceFlinger לצורך קומפוזיציה של קצה עורפי של GPU, ול-HWC לצורך יצירת טבלת חיפוש (LUT) של מיפוי גוונים. נקודת הכניסה ל-libtonemap
היא android::tonemap::getToneMapper()
, שמחזירה אובייקט שמטמיע את הממשק ToneMapper
.
הממשק ToneMapper
תומך ביכולות הבאות:
יצירת טבלת מיפוי לטונאינג
הממשק
ToneMapper::lookupTonemapGain
הוא הטמעה של ה-shader שהוגדר ב-libtonemap_LookupTonemapGain()
ב-CPU. ה-LUT הזה משמש את בדיקות היחידה במסגרת, ושותפים יכולים להשתמש בו כדי לקבל עזרה ביצירת LUT של מיפוי גוונים בצינור עיבוד הנתונים של הצבעים.הפונקציה
libtonemap_LookupTonemapGain()
מקבלת ערכי צבעים במרחב ליניארי מוחלט ולא מנורמלי, גם ב-RGB ליניארי וגם ב-XYZ, ומחזירה ערך float שמתאר את המכפיל של צבעי הקלט במרחב ליניארי.יצירת שובר SkSL
הממשק
ToneMapper::generateTonemapGainShaderSkSL()
מחזיר מחרוזת של שדרן SkSL, בהתאם למרחב הנתונים של המקור והיעד. ה-shader של SkSL מחובר להטמעה של Skia עבורRenderEngine
, רכיב ההרכבה המואץ על ידי GPU ל-SurfaceFlinger. ה-shader מחובר גם ל-libhwui
, כדי שאפשר יהיה לבצע מיפוי גוונים מ-HDR ל-SDR ביעילות עבורTextureView
. מאחר שהמחרוזת שנוצרת מוטמעת בשיידרים אחרים של SkSL שבהם Skia משתמשת, השיידר חייב לפעול בהתאם לכללים הבאים:- למחרוזת ה-shader חייבת להיות נקודת כניסה עם החתימה
float libtonemap_LookupTonemapGain(vec3 linearRGB, vec3 xyz)
, כאשרlinearRGB
הוא הערך של הניטים המוחלטים של הפיקסלים ב-RGB במרחב ליניארי, ו-xyz
הואlinearRGB
שהומר ל-XYZ. - כל שיטות העזר שמשמשות את מחרוזת ה-shader חייבות לכלול את המחרוזת
libtonemap_
בתור הקידומת, כדי שלא יהיו התנגשויות בהגדרות של ה-shader במסגרת. באופן דומה, תחילית שלin_libtonemap_
חייבת להופיע לפני תבניות קלט.
- למחרוזת ה-shader חייבת להיות נקודת כניסה עם החתימה
יצירת מדים של SkSL
הממשק
ToneMapper::generateShaderSkSLUniforms()
מחזיר את הערכים הבאים, בהתאם למטא-נתוניםstruct
שמתארים מטא-נתונים מסטנדרטים שונים של HDR ומתנאים שונים של תצוגה:רשימה של מערכות אחידות (uniforms) שמקושרות על ידי שדרן SkSL.
הערכים האחידים
in_libtonemap_displayMaxLuminance
ו-in_libtonemap_inputMaxLuminance
. הערכים האלה משמשים את ה-shaders של המסגרת כשהם משנים את קנה המידה של הקלט ל-libtonemap
, ומנרמלים את הפלט לפי הצורך.
נכון לעכשיו, תהליך היצירה של פורמטים אחידים לא תלוי במרחב הנתונים של הקלט והפלט.
התאמה אישית
ההטמעה לדוגמה של הספרייה libtonemap
מניבה תוצאות מקובלות. עם זאת, מכיוון שהאלגוריתם של מיפוי הטונים שמשמש את ה-GPU יכול להיות שונה מזה שמשמש את ה-DPU, שימוש בהטמעת העזרה עלול לגרום לרטט בתרחישים מסוימים, כמו אנימציית הסיבוב. התאמה אישית יכולה לפתור בעיות כאלה באיכות התמונה שספציפיות לספק.
מומלץ מאוד ליצרני ציוד מקורי לשנות את ההטמעה של libtonemap
כדי להגדיר תת-מחלקה משלהם של ToneMapper
, שתוחזר על ידי getToneMapper()
.
כששותפים מבצעים התאמה אישית של ההטמעה, הם צריכים לבצע אחת מהפעולות הבאות:
- לשנות את ההטמעה של
libtonemap
ישירות. - מגדירים ספרייה סטטית משלהם, מקמפלים את הספרייה כקובץ עצמאי ומחליפים את הקובץ
.a
של הספרייהlibtonemap
בקובץ שנוצר מהספרייה בהתאמה אישית.
הספקים לא צריכים לשנות קוד ליבה, אבל מספר ספקים צריכים להעביר פרטים על אלגוריתמי המיפוי של הטונים ב-DPU כדי לבצע הטמעה תקינה.
אימות
כדי לאמת את ההטמעה:
להפעיל סרטוני HDR במסך בכל תקני HDR שמערכת התצוגה תומכת בהם, כמו HLG, HDR10, HDR10+ או DolbyVision.
משנים את מצב ה-GPU composition כדי לוודא שאין הבהוב שגלוי למשתמש.
משתמשים בפקודה
adb
הבאה כדי להחליף את הרכב ה-GPU:adb shell service call SurfaceFlinger 1008 i32 <0 to enable HWC composition, 1 to force GPU composition>
בעיות נפוצות
הבעיות הבאות עשויות להתרחש בהטמעה הזו:
פסילה נגרמת כאשר יעד הרינדור שמשמש את ה-GPU ליצירת קומפוזיציה הוא בעל דיוק נמוך יותר מהערך הרגיל של תוכן HDR. לדוגמה, פסי צבע יכולים להופיע כשהטמעת HWC תומכת בפורמטים אטומים של 10 ביט ל-HDR, כמו RGBA1010102 או P010, אבל דורשת שהרכבת ה-GPU תכתוב בפורמט של 8 ביט, כמו RGBA8888, כדי לתמוך ב-alpha.
אם ה-DPU פועל ברמת דיוק שונה מזו של ה-GPU, יכול להיות שיהיה שינוי צבע עדין בגלל הבדלים בקידוד.
כל אחת מהבעיות האלה קשורה להבדלים היחסיים בדיוק של החומרה הבסיסית. פתרון נפוץ הוא לוודא שיש שלב של דיטירציה בנתיבים עם רמת הדיוק הנמוכה יותר, כדי שהבדלים ברמת הדיוק יהיו פחות גלויים לעין.