Surface et SurfaceHolder

Les objets de surface permettent aux applications d'afficher des images à l'écran. Les interfaces SurfaceHolder permettent aux applications de modifier et de contrôler les surfaces.

Surface

Une surface est une interface permettant à un producteur d'échanger des tampons avec un consommateur.

La BufferQueue d'une surface d'affichage est généralement configurée pour la triple mise en mémoire tampon. Les tampons sont alloués à la demande. Par conséquent, si le producteur génère des tampons suffisamment lentement, par exemple à 30 FPS sur un écran 60 FPS, il ne peut y avoir que deux tampons alloués dans la file d'attente. L'allocation de tampons à la demande permet de réduire la consommation de mémoire. Vous pouvez consulter un récapitulatif des tampons associés à chaque calque dans la sortie dumpsys SurfaceFlinger.

La plupart des clients effectuent le rendu sur des surfaces à l'aide d'OpenGL ES ou de Vulkan. Toutefois, certains clients génèrent des éléments graphiques sur des surfaces à l'aide d'un canevas.

Rendu du canevas

L'implémentation du canevas est fournie par la bibliothèque graphique Skia. Si vous souhaitez dessiner un rectangle, vous appelez l'API Canvas, qui définit correctement les octets dans un tampon. Pour vous assurer qu'un tampon n'est pas mis à jour par deux clients en même temps ou qu'il n'est pas écrit pendant son affichage, verrouillez le tampon pour y accéder. Utilisez les commandes suivantes pour travailler avec les verrous de canevas:

  • lockCanvas() verrouille le tampon pour le rendu sur le processeur et renvoie un canevas à utiliser pour le dessin.
  • unlockCanvasAndPost() déverrouille le tampon et l'envoie au compositeur.
  • lockHardwareCanvas() verrouille le tampon pour le rendu sur le GPU et renvoie un canevas à utiliser pour le dessin.

La première fois que le producteur demande un tampon à un BufferQueue, le tampon est alloué et initialisé à zéro. L'initialisation est nécessaire pour éviter de partager des données par inadvertance entre les processus. Toutefois, si vous réutilisez un tampon, les contenus précédents sont toujours présents. Si vous appelez lockCanvas() et unlockCanvasAndPost() de manière répétée sans rien dessiner, le producteur alterne les frames précédemment affichés.

Le code de verrouillage/déverrouillage de la surface conserve une référence à la mémoire tampon précédemment affichée. Si vous spécifiez une région modifiée lorsque vous verrouillez la surface, elle copie les pixels non modifiés du tampon précédent. SurfaceFlinger ou HWC gère généralement le tampon. Toutefois, comme nous n'avons besoin que de lire à partir du tampon, il n'est pas nécessaire d'attendre un accès exclusif.

SurfaceHolder

Un SurfaceHolder est une interface utilisée par le système pour partager la propriété des surfaces avec les applications. Certains clients qui travaillent avec des surfaces veulent un SurfaceHolder, car les API permettant d'obtenir et de définir des paramètres de surface sont implémentées via un SurfaceHolder. Une SurfaceView contient un SurfaceHolder.

La plupart des composants qui interagissent avec une vue impliquent un SurfaceHolder. D'autres API, telles que MediaCodec, fonctionnent sur la surface elle-même.