Surface et SurfaceHolder

Les objets Surface permettent aux applications d'afficher des images sur les écrans. 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.

Les surfaces d'affichage utilisent généralement des BufferQueues configurées 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 de 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 minimiser 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 Vulkan. Cependant, certains clients effectuent le rendu sur des surfaces à l'aide d'un canevas.

Rendu du canevas

La bibliothèque graphique Skia fournit l'implémentation du canevas. Si vous souhaitez dessiner un rectangle, vous appelez l'API Canvas, qui définit les octets d'un tampon de manière appropriée. Pour vous assurer qu'un tampon n'est pas mis à jour par deux clients à la fois ou qu'il n'est pas écrit pendant qu'il est affiché, verrouillez-le pour y accéder. Utilisez les commandes suivantes pour travailler avec les verrouillages 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 involontairement des données entre les processus. Toutefois, si vous réutilisez un tampon, le contenu précédent est toujours présent. Si vous appelez lockCanvas() et unlockCanvasAndPost() à plusieurs reprises sans rien dessiner, le producteur alterne entre les frames précédemment affichées.

Le code de verrouillage/déverrouillage de la surface conserve une référence au tampon précédemment rendu. Si vous spécifiez une région sale lors du verrouillage de la surface, les pixels non sales sont copiés à partir du tampon précédent. SurfaceFlinger ou HWC gèrent généralement le tampon, mais comme vous n'avez besoin que de lire à partir du tampon, il n'est pas nécessaire d'attendre un accès exclusif.

SurfaceHolder

SurfaceHolder est une interface utilisée par le système pour partager la propriété des surfaces avec les applications. Certains clients qui fonctionnent avec des surfaces souhaitent un SurfaceHolder, car les API permettant d'obtenir et de définir les 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.