Création d’une application compositor personnalisée pour les moniteurs montés sur la tête et spécialisés

L’API Windows.Devices.Display.Core est une API Windows Runtime (WinRT) de bas niveau pour les compositeurs tiers et les composants Windows internes qui se trouvent sous toutes les autres API publiques pour énumérer, configurer et piloter des adaptateurs d’affichage et des cibles d’affichage dans Windows. L’idée est de traiter le contrôleur d’affichage comme un moteur distinct, analogue au moteur 3D et au moteur multimédia sur le GPU. Cette API est responsable des opérations suivantes :

  • Réponse aux requêtes sur le matériel d’affichage (telles que les fonctionnalités et les modes d’affichage possibles)
  • Réponses aux requêtes relatives à la configuration actuelle
  • Définition des propriétés sur le matériel d’affichage (par exemple, les modes d’affichage)
  • Configuration du matériel d’affichage (résolution des moniteurs connectés, format de câble, etc.)
  • Allocation et analyse de surfaces GPU spéciales appelées primaires
  • Autoriser l’interopérabilité entre Direct3D et les API Windows.Devices.Display.Core (par exemple, les surfaces de partage, les clôtures)

Il vaut la peine d’appeler ce que Windows.Devices.Display.Core n’est pas :

  • Il ne s’agit pas d’une API utilisée par des jeux ou des applications pour afficher du contenu dans une fenêtre. Les applications utilisent toujours DXGI, XAML, API de composition, GDI, etc.
  • Il ne s’agit pas d’une API utilisée par des jeux ou des applications pour afficher le contenu en plein écran. Les applications utilisent toujours DXGI, les applications Win32 utilisent toujours des HWND et les applications UWP affichent toujours du contenu dans un CoreWindow.

Cette API est destinée aux applications compositor qui pilotent uniquement du matériel spécialisé.

Diagramme montrant les couches architecturales d’API pour les affichages spécialisés.

Scénarios de création de compositeurs personnalisés

Les API Windows.Devices.Display.Core sont appropriées pour les utiliser dans les scénarios suivants :

  • Les affichages de réalité virtuelle et augmentée qui nécessitent un compositeur propriétaire pour piloter directement le contrôleur d’affichage et recevoir un contrôle précis sur le minutage et la configuration du mode distincts du bureau Windows.
  • Scénarios matériels d’affichage spécialisés qui nécessitent un contrôle dédié sur un affichage dans un paramètre commercial. Par exemple, dans les cas où le bureau Windows ne peut pas s’afficher correctement sur un tel affichage en raison d’un warping matériel, d’affichages de nuances de gris, etc.
  • Scénarios « appliance » spécialisés dans lesquels un moniteur peut être entièrement dédié à une application sans interférence de l’expérience de bureau Windows sur une longue période (par exemple, un moniteur vidéo dédié).

L’API effectue cette opération en procédant comme suit :

  • Fournir un contrôle précis sur les informations en mode d’affichage complet, notamment le format de câble, HDR, etc.
  • L’utilisation de clôtures pour synchroniser la présentation permet à un compositeur de chaîner la présentation entre les processus ou les sous-composants avec presque aucune surcharge de performances.
  • Amélioration de la possibilité d’interroger et de configurer le réseau vidéo présent sous-jacent (VidPN) pour permettre aux composants système et aux composants de composition de bas niveau d’effectuer des opérations plus complexes de manière moins sujettes aux erreurs et plus extensibles.

Notez que cette API n’est destinée qu’à un ensemble très spécifique de cas d’utilisation tiers avec du matériel spécialisé. Son utilisation est très restreinte au matériel qui se déclare en ayant besoin des fonctionnalités de cette API. Par conséquent, un certain degré de connaissance des concepts matériels est attendu des développeurs, et les partenaires doivent contacter Directement Microsoft pour vous aider à résoudre les problèmes.

Spécifications matérielles et logicielles

Les compositeurs personnalisés tiers peuvent uniquement acquérir des écrans qui ont été prédéfinits en tant qu’écrans montés sur la tête (HMD) ou « spécialisés ». Cette désignation doit être fournie de l’une des deux manières suivantes :

  • Extension EDID - Les appareils d’affichage personnalisés conçus pour une utilisation permanente en tant que HMD, moniteurs de rayons X, murs vidéo ou autres scénarios spécialisés doivent implémenter l’extension MICROSOFT EDID pour les écrans montés sur la tête et spécialisés.
  • Remplacement de l’utilisateur - Pour les installations matérielles personnalisées à l’aide de moniteurs prêts à l’emploi, Windows fournit un bouton bascule d’interface utilisateur pour concevoir des moniteurs comme « spécialisés ».

Les affichages peuvent ne pas être désignés comme des HMD ou des affichages spécialisés en remplaçant l’EDID dans les logiciels.

Remarque

Les affichages spécialisés sont disponibles uniquement à partir de Windows 10, version 2004 et nécessitent des Windows 10 Entreprise, des Windows 10 Professionnel pour les stations de travail ou des Windows 10 IoT Entreprise.

Feuille de route pour l’implémentation d’un compositeur personnalisé

L’implémentation d’un compositeur personnalisé peut être divisée en plusieurs étapes :

  • Énumérer et découvrir les HMD associés ou les affichages spécialisés
  • Acquérir la propriété des affichages sélectionnés
  • Configurer les modes pour tous les affichages sélectionnés
  • Créer des ressources pour présenter des images aux affichages
  • Afficher le contenu et planifier la présentation d’images
API Objectif et public cible
DisplayInformation Permet de récupérer les propriétés de rendu et de disposition d’un CoreWindow.
HdmiDisplayInformation API Xbox uniquement pour l’énumération et la définition d’un ensemble limité de modes. Scénarios d’application multimédia Xbox hautement spécialisés.
DisplayMonitor Utilisé pour interroger les propriétés d’un appareil de surveillance physique. N’expose pas d’informations d’exécution sur la façon dont un moniteur est configuré ou actuellement utilisé par le système d’exploitation.
EnumDisplayDevices, EnumDisplayMonitors, EnumDisplaySettingsEx API Win32 héritées pour l’interrogation de HMONITORs, d’appareils GDI et de mappages de moniteurs physiques. Les informations retournées ici sont hautement virtualisées et gérées pour la compatibilité des applications.
Direct3D Utilisé pour le rendu du contenu de pixels dans des surfaces GPU et l’exécution de calculs sur un GPU.
Chaînes d’échange DXGI Utilisé pour la présentation en plein écran fenêtré et sans bordure. Le contenu de la chaîne d’échange d’application transite par le compositeur système, DWM.
Énumération de sortie DXGI Fournit des wrappers DXGI autour de HMONITORs.
QueryDisplayConfig, SetDisplayConfig, DisplayConfigGetDeviceInfo, DisplayConfigSetDeviceInfo API Win32 pour la configuration de la topologie d’affichage. Fournit aucun mécanisme pour énumérer plusieurs modes, mais dispose d’un ensemble complet d’informations sur la configuration et les paramètres actuels. Toutefois, toutes les propriétés plus récentes d’un mode ne sont pas exposées par ces API.
Windows.Devices.Display.Core (ce document) Utilisé pour énumérer des cibles, énumérer des modes, configurer des modes, allouer des surfaces GPU pour la présentation et présenter du contenu aux affichages.

Vue d’ensemble de la configuration d’affichage

Énumération matérielle physique

L’API Windows.Devices.Display.Core a différents objets pour représenter des objets matériels physiques. Un DisplayAdapter est généralement (mais pas toujours) un périphérique matériel physique, tel qu’un GPU connecté à PCI Express ou un GPU intégré sur un processeur. Les objets DisplayTarget représentent les connecteurs physiques (par exemple, HDMI, HDMI, DISPLAYPort, etc.) qui peuvent être connectés à partir du GPU. Cela peut inclure des connexions internes non visibles par l’utilisateur pour les appareils avec des moniteurs internes (ordinateurs portables, tablettes, etc.). Il peut y avoir plus d’objets DisplayTarget représentés dans le logiciel qu’un utilisateur peut se connecter physiquement à la fois. Par exemple, étant donné que la norme de connexion DisplayPort autorise le chaînage daisy-chaining, les pilotes GPU énumèrent généralement plusieurs cibles DisplayPort par port physique afin de tenir compte des moniteurs chaînés.

Illustration de la topologie matérielle pour les adaptateurs d’affichage et les cibles d’affichage.

Objets pour définir des modes

Pour énumérer des objets DisplayTarget, définir et interroger des modes, etc. les connexions aux objets DisplayTarget sont représentées avec des objets DisplayPath. Les groupes de chemins affichant le même contenu (groupes clones) sont représentés par DisplayView, et ceux-ci sont agrégés dans un DisplayState. Un objet DisplayState peut donc représenter un ensemble complet d’états de mode qui peut être envoyé aux pilotes pour plusieurs moniteurs.

Illustration de la topologie de mode avec chemin d’affichage, affichage d’affichage et objets d’état d’affichage.

État atomique pour la configuration et l’énumération du mode

L’API Windows.Devices.Display.Core est conçue pour s’assurer que les compositeurs peuvent acquérir l’accès à différents états d’affichage du système de manière atomique et avec des comportements d’obsolescence bien définis. Cela est important, car les GPU sont des ressources partagées, avec des contraintes de bande passante et d’alimentation très serrées. Dans les systèmes modernes, les appareils peuvent arriver/quitter à tout moment et d’autres choses peuvent avoir un impact sur la liste des modes d’affichage disponibles (par exemple, ancrage/désapprouchage, états de veille, autre composant changeant de modes sur un autre chemin). Par conséquent, il est important que les compositeurs soient résilients aux modifications apportées à la configuration du système à l’aide de l’API Windows.Devices.Display.Core et qu’ils suivent les modèles recommandés pour la configuration de l’état.

L’API Windows.Devices.Display.Core fournit donc un modèle simple de validation de modification de modification transactionnelle, similaire à une base de données. Les clients peuvent lire atomiquement un objet DisplayState pour les appareils d’affichage dans le système. Tous les objets sont immuables ou fournissent des API bien définies pour revenir à l’état de mise à jour/validation sur le système. Les modifications ne sont pas apportées tant que DisplayState.TryApply n’est pas appelé, ce qui « valide » les modifications apportées au système. La validation/l’application de modifications à un DisplayState échoue sans impact ni réussit avec les modifications complètes appliquées.

Pour tirer parti des fonctionnalités d’atomicité de l’API :

  • Écrivez une logique de configuration en mode dans une boucle de nouvelle tentative.
  • Créez un DisplayState au début de la configuration du mode, à l’intérieur de chaque boucle.
  • Utilisez l’indicateur FailIfStateChanged lors de l’appel de DisplayState.TryApply pour détecter que l’état du système n’est plus le même que lors de la création de DisplayState. Cela vous permet de réessayer l’opération. Si l’opération échoue avec SystemStateChanged, réessayez la boucle entière.
  • Ne mélangez pas d’autres API (DXGI, GDI, etc.) qui lisent ou modifient l’état avec l’utilisation des API Windows.Devices.Display.Core, car elles n’ont peut-être pas les mêmes garanties d’atomicité.
#include <winrt\Windows.Devices.Display.Core.h>
using namespace winrt::Windows::Devices::Display::Core;
...

// Create a DisplayManager
DisplayManager manager = DisplayManager::Create(DisplayManagerOptions::EnforceSourceOwnership);

// Loop around trying to acquire a target and set a mode
bool shouldRetry;
do
{
    shouldRetry = false;

    // ... Find the target that you want to use
    auto targets = manager.GetCurrentTargets();
    DisplayTarget selectedTarget = ...;

    auto stateCreationResult = manager.TryAcquireTargetsAndCreateEmptyState(
        winrt::single_threaded_vector<DisplayTarget>({ selectedTarget }));

    if (stateCreationResult.ErrorCode() != DisplayManagerResult::Success)
    {
        winrt::check_hresult(stateCreationResult.ExtendedErrorCode());
    }

    auto state = stateCreationResult.State();
    DisplayPath newPath = state.ConnectTarget(selectedTarget);

    // ... Configure the path

    auto applyResult = state.TryApply(DisplayStateApplyOptions::FailIfStateChanged);

    if (applyResult.Status() == DisplayStateOperationStatus::SystemStateChanged)
    {
        shouldRetry = true;
    }
    else if (applyResult.Status() != DisplayStateOperationStatus::Success)
    {
        winrt::check_hresult(applyResult.ExtendedErrorCode());
    }

} while (shouldRetry);

Les API suivantes lisent l’état atomiquement à partir du système :

Les API suivantes valident l’état sur le système :

  • DisplayManager
    • TryAcquireTarget/ReleaseTarget (et acquisition de cibles avec TryAcquireTargetsAnd* méthodes) Acquiert la propriété de DisplayTargets à partir du système.
  • DisplayState
    • TryApply met à jour l’état d’affichage actuel du système en définissant ou en désactivant les modes sur toutes les cibles appartenant au système, via les pilotes d’affichage.

Limitations connues

L’API Windows.Devices.Display.Core présente plusieurs limitations connues (à partir de Windows 10, version 2004) :

  • Les pilotes d’affichage indirects (par exemple Miracast, adaptateurs d’affichage USB, pilotes logiciels) ne peuvent pas être traités actuellement. DisplayManager.CreateDisplayDevice échoue lorsqu’un adaptateur d’affichage indirect est passé.

Exemple de code

Pour obtenir un exemple d’application, consultez l’exemple de compositeur personnalisé Windows.Devices.Display.Core.