Mit Android 13 wird eine vom Anbieter konfigurierbare statische Bibliothek namens libtonemap
eingeführt, die Tonzuordnungsvorgänge definiert und mit den SurfaceFlinger-Prozess- und HWC-Implementierungen (Hardware Composer) geteilt wird.
Mit dieser Funktion können OEMs ihre Display-Tonmapping-Algorithmen zwischen dem Framework und den Anbietern definieren und teilen, um Abweichungen bei der Tonzuordnung zu verringern.
Vor Android 13 wurden anzeigespezifische Tone Mapping-Vorgänge nicht von HWC, SurfaceFlinger und Apps gemeinsam genutzt. Je nach Renderingpfad führte dies bei HDR-Inhalten zu Abweichungen bei der Bildqualität, da die HDR-Inhalte auf unterschiedliche Weise in einen Ausgaberaum umgewandelt wurden. Dies war z. B. in Szenarien wie der Bildschirmdrehung wahrnehmbar, bei denen sich die Kompositionsstrategie zwischen GPU und DPU änderte, und in Unterschieden beim Renderingverhalten zwischen TextureView und SurfaceView.
Auf dieser Seite werden die Benutzeroberfläche, die Anpassung und die Validierung der libtonemap
-Bibliothek beschrieben.
Schnittstelle für die Tone Mapping-Bibliothek
Die Bibliothek libtonemap
enthält CPU-gestützte Implementierungen und SkSL-Shader, die von SurfaceFlinger für die GPU-Back-End-Zusammensetzung und von der HWC zum Generieren einer Tone Mapping-Lookup-Tabelle (LUT) eingebunden werden können. Der Einstiegspunkt für libtonemap
ist android::tonemap::getToneMapper()
. Diese Funktion gibt ein Objekt zurück, das die Schnittstelle ToneMapper
implementiert.
Die ToneMapper
-Schnittstelle unterstützt die folgenden Funktionen:
Tone-Mapping-LUT generieren
Die Schnittstelle
ToneMapper::lookupTonemapGain
ist eine CPU-Implementierung des inlibtonemap_LookupTonemapGain()
definierten Shaders. Dieser wird von Unit-Tests im Framework verwendet und kann von Partnern zur Unterstützung beim Generieren einer Tonmapping-LUT in ihrer Farbpipeline verwendet werden.libtonemap_LookupTonemapGain()
nimmt Farbwerte im absoluten, nicht normalisierten linearen Raum sowohl in linearem RGB als auch in XYZ entgegen und gibt einen Float-Wert zurück, der angibt, um wie viel die Eingabefarben im linearen Raum multipliziert werden sollen.SkSL-Shader generieren
Die Schnittstelle
ToneMapper::generateTonemapGainShaderSkSL()
gibt einen SkSL-Shaderstring mit einem Quell- und Zieldatenraum zurück. Der SkSL-Shader ist in die Skia-Implementierung fürRenderEngine
eingesteckt, die GPU-beschleunigte Compositing-Komponente für SurfaceFlinger. Der Shader ist auch mitlibhwui
verbunden, damit das HDR-zu-SDR-Tone Mapping fürTextureView
effizient durchgeführt werden kann. Da der generierte String in andere von Skia verwendete SkSL-Shader eingebettet ist, muss der Shader den folgenden Regeln entsprechen:- Der Shader-String muss einen Einstiegspunkt mit der Signatur
float libtonemap_LookupTonemapGain(vec3 linearRGB, vec3 xyz)
haben. Dabei istlinearRGB
der Wert der absoluten Nits der RGB-Pixel im linearen Raum undxyz
istlinearRGB
in XYZ umgewandelt. - Allen vom Shader-String verwendeten Hilfsmethoden muss der String
libtonemap_
vorangestellt werden, damit Framework-Shaderdefinitionen nicht in Konflikt stehen. Ebenso müssen Eingabeuniformen das Präfixin_libtonemap_
haben.
- Der Shader-String muss einen Einstiegspunkt mit der Signatur
SkSL-Uniformen generieren
Die Schnittstelle
ToneMapper::generateShaderSkSLUniforms()
gibt Folgendes zurück, wenn ein Metadaten-struct
angegeben ist, das Metadaten aus verschiedenen HDR-Standards und Anzeigebedingungen beschreibt:Eine Liste von Uniformen, die an einen SkSL-Shader gebunden sind.
Die einheitlichen Werte
in_libtonemap_displayMaxLuminance
undin_libtonemap_inputMaxLuminance
. Diese Werte werden von Framework-Shadern verwendet, wenn die Eingabe nachlibtonemap
skaliert und die Ausgabe entsprechend normalisiert wird.
Derzeit ist der Prozess der Uniformerstellung unabhängig vom Ein- und Ausgabedatenraum.
Personalisierung
Die Referenzimplementierung der libtonemap
-Bibliothek liefert akzeptable Ergebnisse. Da sich der von der GPU-Zusammensetzung verwendete Tonzuordnungsalgorithmus jedoch von dem der DPU-Zusammensetzung unterscheiden kann, kann die Verwendung der Referenzimplementierung in einigen Szenarien, z. B. bei der Rotationsanimation, zu Flackern führen. Mithilfe von Anpassungen können solche anbieterspezifischen Probleme mit der Bildqualität behoben werden.
OEMs wird dringend empfohlen, die Implementierung von libtonemap
zu überschreiben, um eine eigene ToneMapper
-Unterklasse zu definieren, die von getToneMapper()
zurückgegeben wird.
Bei der Anpassung der Implementierung müssen Partner einen der folgenden Schritte ausführen:
- Implementierung von
libtonemap
direkt ändern. - Sie können eine eigene statische Bibliothek definieren, die Bibliothek als eigenständiges Programm kompilieren und die Datei
.a
derlibtonemap
-Bibliothek durch die aus der benutzerdefinierten Bibliothek generierte Datei ersetzen.
Anbieter müssen keinen Kernelcode ändern, aber mehrere Anbieter müssen Details zu den DPU-Tone-Mapping-Algorithmen für eine ordnungsgemäße Implementierung kommunizieren.
Zertifizierungsstufe
So prüfen Sie Ihre Implementierung:
Spielen Sie HDR-Videos auf Bildschirmen mit HDR-Standards ab, die Ihr Anzeigesystem unterstützt, z. B. HLG, HDR10, HDR10+ oder DolbyVision.
Aktivieren oder deaktivieren Sie die GPU-Komposition, damit kein für den Nutzer wahrnehmbares Flimmern auftritt.
Verwenden Sie den folgenden
adb
-Befehl, um die GPU-Zusammensetzung ein-/auszuschalten:adb shell service call SurfaceFlinger 1008 i32 <0 to enable HWC composition, 1 to force GPU composition>
Häufige Probleme
Bei dieser Implementierung können folgende Probleme auftreten:
Banding tritt auf, wenn das von der GPU-Zusammensetzung verwendete Renderingziel eine geringere Genauigkeit aufweist als der typische Wert für HDR-Inhalte. Zum Beispiel kann Banding auftreten, wenn eine HWC-Implementierung opaker 10-Bit-Formate für HDR wie RGBA1010102 oder P010 unterstützt, aber die GPU-Zusammensetzung in ein 8-Bit-Format wie RGBA8888 schreibt, um Alpha zu unterstützen.
Eine subtile Farbverschiebung wird durch Quantisierungsunterschiede verursacht, wenn die DPU mit einer anderen Genauigkeit als die GPU arbeitet.
Jedes dieser Probleme hängt mit den relativen Differenzen bei der Genauigkeit der zugrunde liegenden Hardware zusammen. Eine gängige Lösung besteht darin, in den Pfaden mit niedrigerer Präzision einen Dithering-Schritt vorzusehen, wodurch Abweichungen bei der Präzision für den Betrachter weniger wahrnehmbar sind.