BufferQueue et Gralloc

La classe BufferQueue connecte les composants qui génèrent des tampons de données graphiques (producteurs) aux composants qui acceptent les données à afficher ou à traiter ultérieurement (consommateurs). Presque tout ce qui déplace des tampons de données graphiques dans le système repose sur BufferQueue.

L'outil d'allocation de mémoire Gralloc effectue des allocations de tampons 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() accepte les arguments attendus (largeur, hauteur, format de pixel) ainsi qu'un ensemble d'indicateurs d'utilisation.

Producteurs et consommateurs de 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'une mémoire tampon, il demande une mémoire tampon libre à BufferQueue en appelant dequeueBuffer(), en spécifiant la largeur, la hauteur, le format de pixel et les indicateurs d'utilisation des mémoires tampons. Le producteur remplit ensuite le tampon et le renvoie à la file d'attente en appelant queueBuffer(). Ensuite, le consommateur acquiert le tampon avec acquireBuffer() et utilise le contenu du tampon. Lorsque le consommateur a terminé, il renvoie le tampon à la file d'attente en appelant releaseBuffer(). Le framework de synchronisation contrôle la façon dont les tampons se déplacent dans le pipeline graphique Android.

Certaines caractéristiques de la file d'attente de tampons, telles que le nombre maximal de tampons qu'elle peut contenir, sont déterminées conjointement par le producteur et le consommateur. Toutefois, BufferQueue alloue des tampons à mesure qu'il en a besoin. Les tampons sont conservés, sauf si leurs caractéristiques 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 des tampons n'est jamais copié par BufferQueue, car déplacer autant de données est inefficace. Au lieu de cela, les tampons sont toujours transmis par un gestionnaire.

Suivre 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 la majeure partie du code du framework d'application pertinent.

Pour utiliser Systrace, activez les balises gfx, view et sched. Les objets BufferQueue sont affichés dans la trace. Par exemple, si vous effectuez une analyse pendant l'exécution de la lecture vidéo de Grafika (SurfaceView), la ligne intitulée SurfaceView indique le nombre de tampons mis en file d'attente à un moment donné.

La valeur augmente lorsque l'application est active, ce qui déclenche le rendu des images par le décodeur MediaCodec. La valeur diminue lorsque SurfaceFlinger est en cours d'exécution et consomme des tampons. Lorsque vous affichez une vidéo à 30 FPS, la valeur de la file d'attente varie de 0 à 1, car l'affichage à environ 60 FPS peut suivre la source. SurfaceFlinger ne se réveille que lorsqu'il y a du travail à effectuer, et non 60 fois par seconde. Le système tente d'éviter le travail et désactive VSYNC si rien ne met à jour l'écran.

Si vous passez à la vidéo de jeu de Grafika (TextureView) et que vous récupérez une nouvelle trace, une ligne intitulée com.android.grafika / com.android.grafika.PlayMovieActivity s'affiche. Il s'agit de la couche d'UI principale, qui est un autre BufferQueue. Étant donné que TextureView effectue le rendu dans la couche d'interface utilisateur plutôt que dans une couche distincte, toutes les mises à jour basées sur la vidéo sont affichées ici.

Gralloc

L'allocateur HAL Gralloc hardware/libhardware/include/hardware/gralloc.h effectue des allocations de tampons via des indicateurs d'utilisation. Les indicateurs d'utilisation incluent les attributs suivants:

  • Fréquence d'accès à la mémoire à partir d'un logiciel (processeur)
  • Fréquence d'accès à la mémoire depuis le matériel (GPU)
  • Indique si la mémoire sera utilisée comme texture OpenGL ES (GLES)
  • Indique 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 d'un logiciel (ce qui signifie qu'une application touchera les pixels du processeur), Gralloc crée un tampon de 4 octets par pixel dans l'ordre R-G-B-A. Si un producteur spécifie que son tampon ne sera accessible que depuis le matériel et en tant que texture GLES, Gralloc peut effectuer toutes les opérations souhaitées par le pilote GLES, telles que l'ordre BGRA, les mises en page non linéaires et les formats de couleur 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 de l'encodeur vidéo peut nécessiter des pixels YUV. L'ajout d'un accès logiciel et la spécification de RGBA_8888 échouent donc.

La poignée renvoyée par Gralloc peut être transmise entre les processus via Binder.

Tampons protégés

L'indicateur d'utilisation Gralloc GRALLOC_USAGE_PROTECTED permet de n'afficher le tampon graphique que via un chemin protégé par matériel. Ces plans de superposition sont le seul moyen d'afficher du contenu DRM (les tampons protégés par DRM ne sont pas accessibles par SurfaceFlinger ni par le pilote OpenGL ES).

Les vidéos protégées par DRM ne peuvent être présentées que sur un plan de superposition. Les lecteurs vidéo compatibles avec le contenu protégé doivent être implémentés avec SurfaceView. Les logiciels exécutés sur du matériel non protégé ne peuvent pas lire ni écrire le tampon. Les chemins protégés par matériel doivent apparaître sur la superposition du 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 en savoir plus sur le contenu protégé, consultez DRM.