מיפוי גוונים של בהירות HDR לטווח תואם ל-SDR

ב-Android 13 מוצגת ספרייה סטטית שניתנת להגדרה על ידי הספק, שנקראת libtonemap. הספרייה הזו מגדירה פעולות של מיפוי גוונים ומשותפת לתהליך SurfaceFlinger וליישומים של Hardware Composer (HWC). התכונה הזו מאפשרת ליצרני ציוד מקורי (OEM) להגדיר ולשתף את האלגוריתמים שלהם למיפוי גוונים בין המסגרת לבין הספקים, וכך לצמצם את אי ההתאמה במיפוי הגוונים.

ב-Android מגרסה 12 ומטה, פעולות מיפוי טונים ספציפיות לתצוגה לא שותפו בין 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 במעבד (CPU) שהוגדר ב-libtonemap_LookupTonemapGain. הפונקציה הזו משמשת לבדיקות יחידה במסגרת העבודה, ושותפים יכולים להשתמש בה כדי לקבל עזרה ביצירת LUT למיפוי טונים בתוך צינור העיבוד של הצבעים.

    libtonemap_LookupTonemapGain מקבלת ערכי צבע במרחב ליניארי לא מנורמל, גם ב-RGB ליניארי וגם ב-XYZ, ומחזירה ערך float שמתאר בכמה צריך להכפיל את צבעי הקלט במרחב ליניארי.

  • יצירת הצללה של SkSL

    הממשק ToneMapper::generateTonemapGainShaderSkSL מחזיר מחרוזת של הצללה ב-SkSL, בהינתן מרחב נתונים של מקור ויעד. ה-shader של SkSL מחובר להטמעה של Skia עבור RenderEngine, רכיב ההרכבה שמואץ על ידי GPU עבור SurfaceFlinger. ה-shader מחובר גם ל-libhwui, כדי שמיפוי הגוונים מ-HDR ל-SDR יוכל להתבצע ביעילות עבור TextureView. מכיוון שהמחרוזת שנוצרת מוטמעת ב-shaders אחרים של SkSL שמשמשים את Skia, ה-shader חייב לעמוד בכללים הבאים:

    • מחרוזת ה-shader צריכה לכלול נקודת כניסה עם החתימה float libtonemap_LookupTonemapGain(vec3 linearRGB, vec3 xyz), כאשר linearRGB הוא הערך של הניטים המוחלטים של פיקסלי ה-RGB במרחב לינארי ו-xyz הוא linearRGB שהומר ל-XYZ.
    • לכל שיטות העזר שמשמשות את מחרוזת ה-Shader צריך להוסיף את הקידומת libtonemap_ כדי שלא יהיה ניגוד בין הגדרות ה-Shader של המסגרת. באופן דומה, התחילית של מדים לקלט צריכה להיות in_libtonemap_.
  • יצירת משתנים אחידים של SkSL

    הממשק ToneMapper::generateShaderSkSLUniforms מחזיר את הנתונים הבאים, בהינתן מטא-נתונים struct שמתארים מטא-נתונים מתקני HDR שונים ותנאי תצוגה שונים:

    • רשימה של משתנים אחידים שקשורים ל-shader של SkSL.

    • הערכים האחידים in_libtonemap_displayMaxLuminance ו-in_libtonemap_inputMaxLuminance. הערכים האלה משמשים את הצללות של המסגרת כשמבצעים שינוי גודל של הקלט ל-libtonemap, וכשמבצעים נורמליזציה של הפלט לפי הצורך.

      תהליך יצירת המדים לא תלוי במרחב הנתונים של הקלט והפלט.

התאמה אישית

הטמעת ההפניה של הספרייה libtonemap מניבה תוצאות מקובלות. עם זאת, מכיוון שהאלגוריתם למיפוי גוונים שמשמש להרכבה ב-GPU יכול להיות שונה מזה שמשמש להרכבה ב-DPU, שימוש בהטמעה לדוגמה עלול לגרום להבהוב בתרחישים מסוימים, כמו אנימציית סיבוב. התאמה אישית יכולה לפתור בעיות כאלה באיכות התמונה שספציפיות לספק.

מומלץ מאוד ליצרני ציוד מקורי (OEM) לבטל את ההטמעה של libtonemap כדי להגדיר מחלקת משנה משלהם ToneMapper, שמוחזרת על ידי getToneMapper. כשמבצעים התאמה אישית של ההטמעה, השותפים צריכים לבצע אחת מהפעולות הבאות:

  • לשנות את ההטמעה של libtonemap ישירות.
  • להגדיר ספרייה סטטית משלהם, לקמפל את הספרייה כספרייה עצמאית ולהחליף את קובץ .a של ספריית libtonemap בקובץ שנוצר מהספרייה המותאמת אישית שלהם.

הספקים לא צריכים לשנות קוד ליבה, אבל כמה ספקים צריכים להעביר פרטים על אלגוריתמים של מיפוי טונים של DPU כדי להבטיח הטמעה תקינה.

אימות

כדי לאמת את ההטמעה:

  1. הפעלה של סרטוני HDR במסך בכל תקן HDR שמערכת התצוגה תומכת בו, כמו HLG,‏ HDR10,‏ HDR10+‎ או DolbyVision.

  2. כדאי להפעיל או להשבית את ההגדרה 'הוספת שכבות על ידי GPU' כדי לוודא שלא יהיו הבהובים שמשתמשים יוכלו לראות.

    משתמשים בפקודה 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 כדי לתמוך באלפא.

  • שינוי צבע עדין נגרם כתוצאה מהבדלים בכמות המידע אם ה-DPU פועל ברמת דיוק שונה מזו של ה-GPU.

כל אחת מהבעיות האלה קשורה להבדלים בדיוק היחסי של החומרה הבסיסית. פתרון עקיף טיפוסי הוא לוודא שיש שלב של דית'רינג (dithering) בנתיבים עם דיוק נמוך יותר, כך שההבדלים בדיוק פחות מורגשים.