In Android 13 wird eine vom Anbieter konfigurierbare statische Bibliothek namens libtonemap
eingeführt, die Tonmapping-Vorgänge definiert und für den SurfaceFlinger-Prozess und die Hardware Composer-Implementierungen (HWC) freigegeben wird.
Mit dieser Funktion können OEMs ihre Display-Tonmapping-Algorithmen im Framework definieren und mit den Anbietern teilen, um Abweichungen beim Tonmapping zu verringern.
Vor Android 13 wurden displayspezifische Tonmapping-Vorgänge nicht zwischen HWC, SurfaceFlinger und Apps geteilt. 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 in Szenarien wie der Bildschirmdrehung spürbar, bei denen sich die Kompositionstrategie zwischen der GPU und der DPU ändert, sowie in Unterschieden beim Rendering-Verhalten zwischen TextureView und SurfaceView.
Auf dieser Seite werden die Benutzeroberfläche, die Anpassung und die Validierungsdetails der libtonemap
-Bibliothek beschrieben.
Schnittstelle zur Tonmapping-Bibliothek
Die Bibliothek libtonemap
enthält CPU-gestützte Implementierungen und SkSL-Shader, die von SurfaceFlinger für die GPU-Backend-Komposition und von der HWC zum Generieren einer LUT (Look-Up-Table) für das Tonmapping 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
-Benutzeroberfläche unterstützt die folgenden Funktionen:
LUT für das Tonmapping 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 bei der Generierung 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-Shader-String zurück, wenn ein Quell- und ein Zieldatenraum angegeben werden. Der SkSL-Shader wird in die Skia-Implementierung fürRenderEngine
eingebunden, die GPU-beschleunigte Kompositionierungskomponente 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. - Alle vom Shader-String verwendeten Hilfsmethoden müssen mit dem String
libtonemap_
vorangestellt werden, damit es nicht zu Konflikten mit den Shaderdefinitionen des Frameworks kommt. Ebenso müssen Eingabeuniformen mit dem Präfixin_libtonemap_
beginnen.
- 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 Uniforms, die von einem SkSL-Shader gebunden sind.
Die einheitlichen Werte
in_libtonemap_displayMaxLuminance
undin_libtonemap_inputMaxLuminance
. Diese Werte werden von Framework-Shadern verwendet, um die Eingabe auflibtonemap
zu skalieren und die Ausgabe gegebenenfalls zu normalisieren.
Derzeit ist das Generieren von Uniformen unabhängig vom Eingabe- und Ausgabedatenraum.
Personalisierung
Die Referenzimplementierung der libtonemap
-Bibliothek liefert akzeptable Ergebnisse. Da sich der von der GPU-Komposition verwendete Tonmapping-Algorithmus jedoch von dem der DPU-Komposition unterscheiden kann, kann die Verwendung der Referenzimplementierung in einigen Fällen zu Flimmern führen, z. B. bei der Drehanimation. 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 eine der folgenden Optionen auswählen:
- Ändern Sie die Implementierung von
libtonemap
direkt. - 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-Tonmapping-Algorithmen für eine ordnungsgemäße Implementierung mitteilen.
Zertifizierungsstufe
So prüfen Sie Ihre Implementierung:
HDR-Videos können auf dem Bildschirm in allen HDR-Standards wiedergegeben werden, die von deinem Displaysystem unterstützt werden, z. B. HLG, HDR10, HDR10+ oder DolbyVision.
Aktivieren oder deaktivieren Sie die GPU-Komposition, damit kein für den Nutzer wahrnehmbares Flimmern auftritt.
Mit dem folgenden
adb
-Befehl können Sie die GPU-Zusammensetzung umschalten: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 die folgenden Probleme auftreten:
Banding tritt auf, wenn das von der GPU-Komposition verwendete Renderziel eine geringere Präzision als der typische Wert für HDR-Inhalte hat. Banding kann beispielsweise auftreten, wenn eine HWC-Implementierung opake 10-Bit-Formate für HDR wie RGBA1010102 oder P010 unterstützt, aber die GPU-Komposition 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 Präzisionsunterschieden 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.