Mit Oberflächenobjekten können Apps Bilder rendern, die auf Bildschirmen angezeigt werden. SurfaceHolder-Schnittstellen ermöglichen es Apps, Oberflächen zu bearbeiten und zu steuern.
Surface
Eine Surface ist eine Schnittstelle, über die ein Producer Buffers mit einem Consumer austauschen kann.
Die BufferQueue für eine Displayoberfläche ist in der Regel für das Dreifach-Buffering konfiguriert. Buffers werden auf Anfrage zugewiesen. Wenn der Produzent Buffers also langsam genug generiert, z. B. mit 30 fps auf einem Display mit 60 fps, befinden sich möglicherweise nur zwei zugewiesene Buffers in der Warteschlange.
Durch die Bereitstellung von Puffern auf Anfrage lässt sich der Arbeitsspeicherverbrauch minimieren. In der dumpsys SurfaceFlinger
-Ausgabe sehen Sie eine Zusammenfassung der mit jeder Ebene verknüpften Buffers.
Die meisten Clients rendern mit OpenGL ES oder Vulkan auf Oberflächen. Einige Clients rendern jedoch mithilfe eines Canvas auf Oberflächen.
Canvas-Rendering
Die Canvas-Implementierung wird von der Skia Graphics Library bereitgestellt. Wenn Sie ein Rechteck zeichnen möchten, rufen Sie die Canvas API auf, die die Bytes in einem Buffer entsprechend festlegt. Damit ein Puffer nicht von zwei Clients gleichzeitig aktualisiert oder während der Anzeige darauf geschrieben wird, sperren Sie den Puffer für den Zugriff. Verwenden Sie die folgenden Befehle, um mit Canvas-Sperren zu arbeiten:
lockCanvas()
sperrt den Framebuffer für das Rendering auf der CPU und gibt einen Canvas zurück, der zum Zeichnen verwendet wird.unlockCanvasAndPost()
löst den Puffer und sendet ihn an den Compositor.lockHardwareCanvas()
sperrt den Framebuffer für das Rendering auf der GPU und gibt ein Canvas zurück, das zum Zeichnen verwendet werden kann.
Wenn der Erzeuger zum ersten Mal einen Puffer von einer BufferQueue anfordert, wird der Puffer zugewiesen und auf null initialisiert. Die Initialisierung ist erforderlich, um zu vermeiden, dass Daten versehentlich zwischen Prozessen geteilt werden. Wenn Sie einen Puffer jedoch wiederverwenden, sind die vorherigen Inhalte weiterhin vorhanden. Wenn Sie wiederholt lockCanvas()
und unlockCanvasAndPost()
aufrufen, ohne etwas zu zeichnen, wechselt der Producer zwischen zuvor gerenderten Frames.
Der Code zum Sperren/Entsperren der Oberfläche speichert einen Verweis auf den zuvor gerenderten Puffer. Wenn Sie beim Sperren der Oberfläche einen geänderten Bereich angeben, werden die nicht geänderten Pixel aus dem vorherigen Puffer kopiert. SurfaceFlinger oder HWC verwalten normalerweise den Puffer. Da wir aber nur aus dem Puffer lesen müssen, müssen wir nicht auf den exklusiven Zugriff warten.
SurfaceHolder
Ein SurfaceHolder ist eine Schnittstelle, über die das System die Inhaberschaft von Oberflächen für Apps freigibt. Für einige Clients, die mit Oberflächen arbeiten, ist ein SurfaceHolder erforderlich, da APIs zum Abrufen und Festlegen von Oberflächenparametern über einen SurfaceHolder implementiert werden. Eine SurfaceView enthält einen SurfaceHolder.
Die meisten Komponenten, die mit einer Ansicht interagieren, umfassen einen SurfaceHolder. Einige andere APIs wie MediaCodec arbeiten auf der Oberfläche selbst.