Implémenter Hardware Composer HAL

Les couches composites HAL de Hardware Composer (HWC) reçues de SurfaceFlinger, ce qui réduit la quantité de composition OpenGL ES (GLES) et les performances du GPU

Le HWC extrait des objets, tels que des superpositions et des blitters 2D, en objets composites et communique avec du matériel spécialisé pour la composition de fenêtres des fenêtres composites. Utilisez le HWC pour des fenêtres composites au lieu d'avoir Composition SurfaceFlinger avec le GPU La plupart des GPU ne sont pas optimisés pour la composition. Lorsque le GPU compose des calques à partir de SurfaceFlinger, les applications ne peuvent pas utiliser le GPU pour leur propre rendu.

Les implémentations HWC doivent être compatibles avec:

  • Au moins quatre superpositions:
    • Barre d'état
    • Barre système
    • Application
    • Fond d'écran/Arrière-plan
  • Calques plus grands que l'écran (par exemple, un fond d'écran)
  • Mélange alpha prémultiplié simultané par pixel et par plan
  • Chemin matériel pour la lecture vidéo protégée
  • Ordre de conditionnement RVBA, formats YUV et mosaïque, tourbillon et foulée propriétés

Pour implémenter le matériel:

  1. Implémentez un HWC non opérationnel et envoyez toutes les tâches de composition à GLES :
  2. Implémentez un algorithme pour déléguer progressivement la composition au matériel. Par exemple, déléguez uniquement les trois ou quatre premières surfaces à la superposition. le matériel du HWC.
  3. Optimisez le matériel. Cela peut inclure:
    • Choisir des surfaces qui maximisent la charge retirée du GPU et en les envoyant au HWC.
    • Détecter si l'écran est en cours de mise à jour. Si ce n’est pas le cas, déléguez la composition dans GLES au lieu du matériel pour économiser de l'énergie. Lorsque l'écran des mises à jour, continuez à décharger la composition vers le matériel.
    • Se préparer aux cas d'utilisation courants tels que:
      • Écran d'accueil, qui comprend la barre d'état, la barre système, la fenêtre de l'application et les fonds d'écran animés
      • Jeux plein écran en mode portrait et paysage
      • Vidéo plein écran avec sous-titres et lecture contrôle
      • Lecture de vidéos protégées
      • Écran partagé multifenêtre

Primitives HWC

Le HWC fournit deux primitives, les couches et les écrans, pour représenter le travail de composition et son interaction avec le matériel d'affichage. La Le matériel permet également de contrôler VSYNC et de rappeler SurfaceFlinger. pour l'avertir lorsqu'un événement VSYNC se produit.

Interface HIDL

Android 8.0 et les versions ultérieures utilisent une interface HIDL appelée HAL Composer pour l'IPC liée entre le HWC et SurfaceFlinger. Le HAL de Composer remplace ancienne interface hwcomposer2.h. Si les fournisseurs fournissent une HAL pour Composer du HWC, Composer HAL accepte directement les appels HIDL de SurfaceFlinger. Si les fournisseurs proposent une ancienne implémentation du matériel, Composer HAL charge les pointeurs de fonction à partir de hwcomposer2.h, transférer des appels HIDL en appels de pointeurs de fonction.

Le HWC fournit des fonctions pour déterminer les propriétés d'un affichage donné. à Basculer entre différentes configurations d'affichage (4K ou 1080p, par exemple) la résolution) et les modes de couleur (couleur native ou vrai sRVB, par exemple) ; et pour activer ou désactiver l'écran s'allume, l'éteint ou passe en mode d'économie d'énergie, le cas échéant.

Pointeurs de fonction

Si les fournisseurs implémentent directement l'HAL de Composer, SurfaceFlinger appelle ses fonctions via HIDL IPC. Par exemple, pour créer une couche, SurfaceFlinger appelle createLayer() sur le HAL Composer.

Si les fournisseurs implémentent l'interface hwcomposer2.h, l'HAL Composer dans les pointeurs de fonction hwcomposer2.h. Dans hwcomposer2.h commentaires, Les fonctions de l'interface HWC sont désignés par des noms en minuscule CamelCase qui n'existent pas dans l'interface sous forme de champs nommés. Presque toutes les fonctions sont chargées en demandant pointeur de fonction utilisant getFunction fourni par hwc2_device_t Par exemple, la fonction createLayer est un pointeur de fonction de type HWC2_PFN_CREATE_LAYER, qui est affiché lorsque la valeur énumérée HWC2_FUNCTION_CREATE_LAYER est transmis à getFunction.

Pour obtenir une documentation détaillée sur les fonctions HAL de Composer et le transfert de fonction HWC fonctions, consultez la section composer. Pour une documentation détaillée pointeurs de fonction HWC, consultez le hwcomposer2.h

Poignées de calque et d'affichage

Les calques et les écrans sont manipulés par des identifiants générés par le HWC. Les poignées sont opaques pour SurfaceFlinger.

Lorsque SurfaceFlinger crée une couche, il appelle createLayer, qui renvoie un type Layer pour les implémentations directes ou hwc2_layer_t pour les implémentations de passthrough. Quand ? SurfaceFlinger modifie une propriété de ce calque, qui transmet la valeur hwc2_layer_t dans la fonction de modification appropriée ; ainsi que toute autre information nécessaire à la modification. La Le type de hwc2_layer_t est suffisamment grand pour contenir un pointeur ou un de l'index.

Les écrans physiques sont créés grâce au branchement à chaud. Lorsqu'un écran physique est branché à un chaud, le HWC crée une poignée et la transmet à SurfaceFlinger via le rappel Hotplug. Les écrans virtuels sont créés par SurfaceFlinger en appelant createVirtualDisplay() pour demander un affichage. Si le matériel prend en charge la composition d'écran virtuel, elle renvoie un handle. Ensuite, SurfaceFlinger délègue la composition des écrans au HWC. Si le HWC n'est pas compatible avec la composition d'écran virtuel, SurfaceFlinger crée la poignée et compose l'écran.

Afficher les opérations de composition

Une fois par VSYNC, SurfaceFlinger s'active s'il reçoit un nouveau contenu composite. Ce nouveau contenu peut être de nouveaux tampons d'image d'applications ou une modification des propriétés d'une ou de plusieurs calques. Lorsque SurfaceFlinger l'active :

  1. Gère les transactions, le cas échéant.
  2. Ajoute de nouveaux tampons graphiques, s'ils sont présents.
  3. Effectue une nouvelle composition, si l'étape 1 ou 2 a entraîné une modification au contenu d'affichage.

Pour effectuer une nouvelle composition, SurfaceFlinger crée et détruit les calques ou modifie leur état, le cas échéant. Elle met également à jour des couches avec leur contenu actuel, à l'aide d'appels comme setLayerBuffer ou setLayerColor. Une fois que toutes les couches sont mis à jour, SurfaceFlinger appelle validateDisplay, ce qui indique le HWC pour examiner l'état des couches et déterminer comment la composition continuer. Par défaut, SurfaceFlinger tente de configurer chaque couche de sorte que la couche soit composée par le HWC ; mais dans certains SurfaceFlinger compose des couches via le GPU de remplacement.

Après l'appel de validateDisplay, SurfaceFlinger appelle getChangedCompositionTypes pour voir si le matériel souhaite que l'un des types de composition des calques soit modifié avant d'effectuer la la composition. Pour accepter les modifications, SurfaceFlinger appelle acceptDisplayChanges

Si des calques sont marqués pour la composition SurfaceFlinger, SurfaceFlinger les compose dans le tampon cible. SurfaceFlinger appelle ensuite setClientTarget pour fournir le tampon à l'écran afin que le tampon peut être affiché à l'écran ou composé de couches qui n'ont pas été marquées pour la composition SurfaceFlinger. Si aucun calque n'est marqué pour Dans la composition SurfaceFlinger, SurfaceFlinger contourne l'étape de composition.

Enfin, SurfaceFlinger appelle presentDisplay pour indiquer le matériel pour terminer le processus de composition et afficher le résultat final.

Écrans multiples

Android 10 est compatible avec plusieurs écrans physiques. Lors de la conception d'une implémentation HWC destinée à être utilisée sur Android 7.0 et plus élevée, certaines restrictions ne sont pas présentes dans la définition HWC:

  • Nous partons du principe qu'il y a exactement un écran interne. L'écran interne est celui que le hotplug initial signale au démarrage. Une fois l'écran interne branché à chaud, être déconnectés.
  • En plus de l'écran interne, un nombre illimité d'écrans externes peut être connecté en mode "hot-plug" pendant le fonctionnement normal de l'appareil. Le framework part du principe que tous les prises électriques situées après le premier écran interne sont des écrans externes. des écrans internes sont ajoutés, ils sont classés de manière incorrecte comme Display.TYPE_HDMI au lieu de Display.TYPE_BUILT_IN

Bien que les opérations SurfaceFlinger décrites ci-dessus soient effectuées elles sont effectuées de manière séquentielle pour tous les écrans actifs, même si le contenu d'un seul affichage est mis à jour.

Par exemple, si l'écran externe est mis à jour, la séquence est la suivante:

// In Android 9 and lower:

// Update state for internal display
// Update state for external display
validateDisplay(<internal display>)
validateDisplay(<external display>)
presentDisplay(<internal display>)
presentDisplay(<external display>)

// In Android 10 and higher:

// Update state for internal display
// Update state for external display
validateInternal(<internal display>)
presentInternal(<internal display>)
validateExternal(<external display>)
presentExternal(<external display>)

Composition de l'écran virtuel

La composition de l'écran virtuel est semblable à celle de l'écran externe la composition. Différence entre la composition de l'écran virtuel et la composition physique La composition de l'affichage est que les écrans virtuels envoient la sortie vers un tampon Gralloc au lieu de l'écran. Hardware Composer (HWC) écrit la sortie dans un tampon, fournit la clôture et envoie le tampon à un consommateur (par exemple, encodeur vidéo, GPU, CPU, etc.). Les écrans virtuels peuvent utiliser la 2D/blitter ou se superpose si le pipeline d'affichage écrit en mémoire.

Modes

Chaque frame se trouve dans l'un des trois modes suivants après que SurfaceFlinger a appelé la méthode HWC validateDisplay() :

  • GLES : le GPU compile toutes les couches, en écrivant directement dans le tampon de sortie. Le matériel n'est pas impliqué dans la composition.
  • MIXÉ : le GPU compile certaines couches avec le Le framebuffer et HWC composent le framebuffer et les couches restantes. en écrivant directement dans le tampon de sortie.
  • HWC : HWC compose toutes les couches et écrit directement dans le tampon de sortie.

Format de sortie

Les formats de sortie du tampon d'affichage virtuel dépendent de leur mode:

  • Mode GLES : le pilote EGL définit le tampon de sortie. au format dequeueBuffer(), généralement RGBA_8888. Le client doit pouvoir accepter le format de sortie défini par le pilote ou le tampon ne peut pas être lu.
  • Modes MIXTE et HWC : si le consommateur a besoin d'un processeur le client définit le format. Sinon, le format est IMPLEMENTATION_DEFINED, et Gralloc définit le meilleur format en fonction les options d'utilisation. Par exemple, Gralloc définit un format YCbCr si l'utilisateur l'encodeur vidéo et le HWC peuvent écrire le format efficacement.

Limites de synchronisation

Les barrières de synchronisation sont un aspect crucial des éléments graphiques Android. du système d'exploitation. Les clôtures permettent au processeur de fonctionner indépendamment du travail simultané du GPU, uniquement lorsqu'il existe une véritable dépendance.

Par exemple, lorsqu'une application envoie un tampon généré sur le GPU, il envoie également un objet de clôture de synchronisation. Cette barrière indique quand le GPU a terminé d'écrire dans le tampon.

Le HWC exige que le GPU termine l'écriture des tampons avant que les tampons ne soient affiché. Les barrières de synchronisation sont transmises via le pipeline graphique avec des tampons et signaler l'écriture des tampons. Avant l'affichage d'un tampon, le HWC vérifie si la barrière de synchronisation a signalé et, le cas échéant, il affiche le tampon.

Pour en savoir plus sur les barrières de synchronisation, consultez la page Hardware Composer Intégration.