La classe BufferQueue connecte les composants qui génèrent des tampons de données graphiques ( producteurs ) aux composants qui acceptent les données pour affichage ou traitement ultérieur ( consommateurs ). Presque tout ce qui déplace des tampons de données graphiques à travers le système repose sur BufferQueue.
L'allocateur de mémoire Gralloc effectue des allocations de tampon et est implémenté via deux interfaces HIDL spécifiques au fournisseur (voir hardware/interfaces/graphics/allocator/
et hardware/interfaces/graphics/mapper/
). La fonction allocate()
prend les arguments attendus (largeur, hauteur, format de pixel) ainsi qu'un ensemble d'indicateurs d'utilisation.
Producteurs et consommateurs BufferQueue
Les consommateurs créent et possèdent la structure de données BufferQueue et peuvent exister dans des processus différents de ceux de leurs producteurs. Lorsqu'un producteur a besoin d'un tampon, il demande un tampon libre à BufferQueue en appelant dequeueBuffer()
, en spécifiant la largeur, la hauteur, le format de pixel et les indicateurs d'utilisation des tampons. Le producteur remplit ensuite le tampon et le renvoie dans la file d'attente en appelant queueBuffer()
. Ensuite, le consommateur acquiert le tampon acquireBuffer()
et utilise le contenu du tampon. Lorsque le consommateur a terminé, il renvoie le tampon dans la file d'attente en appelant releaseBuffer()
. Le cadre de synchronisation contrôle la façon dont les tampons se déplacent dans le pipeline graphique Android.
Certaines caractéristiques de la BufferQueue, telles que le nombre maximal de tampons qu'elle peut contenir, sont déterminées conjointement par le producteur et le consommateur. Cependant, BufferQueue alloue des tampons selon ses besoins. Les tampons sont conservés à moins que les caractéristiques ne changent ; par exemple, si un producteur demande des tampons d'une taille différente, les anciens tampons sont libérés et de nouveaux tampons sont alloués à la demande.
Le contenu du tampon n'est jamais copié par BufferQueue, car déplacer autant de données est inefficace. Au lieu de cela, les tampons sont toujours passés par un handle.
Suivi de BufferQueue avec Systrace
Pour comprendre comment les tampons graphiques se déplacent, utilisez Systrace , un outil qui enregistre l'activité de l'appareil sur une courte période. Le code graphique au niveau du système est bien instrumenté, tout comme une grande partie du code de l'infrastructure d'application pertinente.
Pour utiliser Systrace, activez les balises gfx
, view
et sched
. Les objets BufferQueue sont affichés dans la trace. Par exemple, si vous prenez une trace pendant que la vidéo de lecture de Grafika (SurfaceView) est en cours d'exécution, la ligne intitulée SurfaceView vous indique combien de tampons ont été mis en file d'attente à un moment donné.
La valeur augmente pendant que l'application est active, ce qui déclenche le rendu des images par le décodeur MediaCodec. La valeur diminue pendant que SurfaceFlinger travaille et consomme des tampons. Lors de l'affichage d'une vidéo à 30 ips, la valeur de la file d'attente varie de 0 à 1 car l'affichage à ~ 60 ips peut suivre la source. SurfaceFlinger ne se réveille que lorsqu'il y a du travail à faire, pas 60 fois par seconde. Le système essaie d'éviter le travail et désactive VSYNC si rien ne met à jour l'écran.
Si vous passez à la lecture de la vidéo de Grafika (TextureView) et saisissez une nouvelle trace, vous voyez une ligne intitulée com.android.grafika
/ com.android.grafika.PlayMovieActivity
. Il s'agit de la couche principale de l'interface utilisateur, qui est une autre BufferQueue. Étant donné que TextureView s'affiche dans la couche d'interface utilisateur plutôt que dans une couche distincte, toutes les mises à jour vidéo sont affichées ici.
Gralloc
L'allocateur Gralloc HAL hardware/libhardware/include/hardware/gralloc.h
effectue des allocations de tampon via des drapeaux d'utilisation. Les indicateurs d'utilisation incluent des attributs tels que :
- Combien de fois la mémoire sera accessible à partir du logiciel (CPU)
- La fréquence d'accès à la mémoire à partir du matériel (GPU)
- Si la mémoire sera utilisée comme texture OpenGL ES (GLES)
- Si la mémoire sera utilisée par un encodeur vidéo
Par exemple, si le format de tampon d'un producteur spécifie RGBA_8888
pixels et que le producteur indique que le tampon sera accessible à partir du logiciel (ce qui signifie qu'une application touchera des pixels sur le processeur), Gralloc crée un tampon avec 4 octets par pixel dans l'ordre RGBA. Si à la place, un producteur spécifie que son tampon ne sera accessible qu'à partir du matériel et en tant que texture GLES, Gralloc peut faire tout ce que le pilote GLES veut, comme l'ordre BGRA, les mises en page non linéaires et les formats de couleurs alternatifs. Autoriser le matériel à utiliser son format préféré peut améliorer les performances.
Certaines valeurs ne peuvent pas être combinées sur certaines plates-formes. Par exemple, l'indicateur d'encodeur vidéo peut nécessiter des pixels YUV. L'ajout d'un accès logiciel et la spécification RGBA_8888
échouent.
Le handle renvoyé par Gralloc peut être passé entre les processus via Binder.
Tampons protégés
L'indicateur d'utilisation de GRALLOC_USAGE_PROTECTED
permet au tampon graphique d'être affiché uniquement via un chemin protégé par le matériel. Ces plans de superposition sont le seul moyen d'afficher le contenu DRM (les tampons protégés par DRM ne sont pas accessibles par SurfaceFlinger ou le pilote OpenGL ES).
La vidéo protégée par DRM ne peut être présentée que sur un plan de superposition. Les lecteurs vidéo qui prennent en charge le contenu protégé doivent être implémentés avec SurfaceView. Les logiciels s'exécutant sur du matériel non protégé ne peuvent ni lire ni écrire dans le tampon ; les chemins protégés par matériel doivent apparaître sur la superposition Hardware Composer (c'est-à-dire que les vidéos protégées disparaissent de l'écran si Hardware Composer passe à la composition OpenGL ES).
Pour plus de détails sur le contenu protégé, voir DRM .