Mit Surface-Objekten können Apps Bilder rendern, die auf Bildschirmen angezeigt werden sollen. Mit SurfaceHolder-Schnittstellen können Apps Surfaces bearbeiten und steuern.
Surface
Eine Surface ist eine Schnittstelle für einen Producer, um Puffer mit einem Consumer auszutauschen.
Für Displays werden in der Regel BufferQueues verwendet, die für Triple-Buffering konfiguriert sind. Puffer werden bei Bedarf zugewiesen. Wenn der Producer Puffer langsam genug generiert, z. B. mit 30 fps auf einem Display mit 60 fps, sind möglicherweise nur zwei zugewiesene Puffer in der Warteschlange vorhanden.
Durch die bedarfsgesteuerte Zuweisung von Puffern lässt sich der Arbeitsspeicherverbrauch minimieren. Eine Zusammenfassung der Puffer, die mit den einzelnen Layern verknüpft sind, finden Sie in der dumpsys SurfaceFlinger
-Ausgabe.
Die meisten Clients rendern auf Oberflächen mit OpenGL ES oder Vulkan. Einige Clients rendern jedoch Oberflächen mithilfe eines Canvas.
Canvas-Rendering
Die Skia Graphics Library stellt die Canvas-Implementierung bereit. Wenn Sie ein Rechteck zeichnen möchten, rufen Sie die Canvas API auf, die die Bytes in einem Puffer entsprechend festlegt. Damit ein Puffer nicht gleichzeitig von zwei Clients aktualisiert oder während der Anzeige beschrieben wird, müssen Sie ihn sperren, um darauf zuzugreifen. Verwenden Sie die folgenden Befehle, um mit Canvas-Sperren zu arbeiten:
lockCanvas()
sperrt den Puffer für das Rendern auf der CPU und gibt ein Canvas-Objekt zurück, das zum Zeichnen verwendet werden kann.unlockCanvasAndPost()
entsperrt den Puffer und sendet ihn an den Compositor.lockHardwareCanvas()
sperrt den Puffer für das Rendern auf der GPU und gibt einen Canvas zurück, der für das Zeichnen verwendet werden kann.
Wenn der Producer zum ersten Mal einen Puffer aus einer BufferQueue anfordert, wird der Puffer zugewiesen und mit Nullen initialisiert. Die Initialisierung ist erforderlich, um zu vermeiden, dass Daten versehentlich zwischen Prozessen geteilt werden. Wenn Sie einen Puffer wiederverwenden, sind die vorherigen Inhalte jedoch weiterhin vorhanden. Wenn Sie lockCanvas()
und unlockCanvasAndPost()
wiederholt aufrufen, ohne etwas zu zeichnen, wechselt der Producer zwischen zuvor gerenderten Frames.
Der Code zum Sperren/Entsperren der Oberfläche behält einen Verweis auf den zuvor gerenderten Puffer bei. Wenn Sie beim Sperren der Oberfläche eine „dirty region“ angeben, werden die nicht geänderten Pixel aus dem vorherigen Puffer kopiert. Normalerweise wird der Puffer von SurfaceFlinger oder HWC verarbeitet. Da Sie aber nur aus dem Puffer lesen müssen, ist es nicht erforderlich, auf den exklusiven Zugriff zu warten.
SurfaceHolder
Ein SurfaceHolder ist eine Schnittstelle, die das System verwendet, um die Inhaberschaft von Oberflächen mit Apps zu teilen. Einige Clients, die mit Oberflächen arbeiten, benötigen einen SurfaceHolder, 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, verwenden einen SurfaceHolder. Einige andere APIs, z. B. MediaCodec, arbeiten direkt mit der Oberfläche.