Freigeben über


Erstellen einer benutzerdefinierten Kompositor-App für head-mounted und spezialisierte Monitore

Die Windows.Devices.Display.Core-API ist eine low-level Windows-Runtime (WinRT)-API für Drittanbieter und interne Windows-Komponenten, die sich unter allen anderen öffentlichen APIs zum Aufzählen, Konfigurieren und Steuern von Anzeigeadaptern und Anzeigezielen in Windows befinden. Die Idee besteht darin, den Anzeigecontroller als separates Modul zu behandeln, analog zum 3D-Modul und zum Medienmodul auf der GPU. Diese API ist für Folgendes verantwortlich:

  • Beantworten von Abfragen zur Anzeigehardware (z. B. Funktionen und mögliche Anzeigemodi)
  • Beantworten von Abfragen zur aktuellen Konfiguration
  • Festlegen von Eigenschaften auf der Anzeigehardware (z. B. Anzeigemodi)
  • Konfigurieren der Anzeigehardware (auflösung der angeschlossenen Monitore, deren Drahtformat usw.)
  • Zuordnen und Scannen spezieller GPU-Oberflächen, die als Primaren bezeichnet werden
  • Zulassen der Interoperabilität zwischen Direct3D und den Windows.Devices.Display.Core-APIs (z. B. Freigeben von Oberflächen, Zaunen)

Es lohnt sich, herauszurufen, was Windows.Devices.Display.Core nicht ist:

  • Es handelt sich nicht um eine API, die von Spielen oder Apps zum Anzeigen von Inhalten in einem Fenster verwendet wird. Apps verwenden weiterhin DXGI, XAML, Kompositions-APIs, GDI usw.
  • Es handelt sich nicht um eine API, die von Spielen oder Apps zum Anzeigen von Inhalten im Vollbildmodus verwendet wird. Apps verwenden weiterhin DXGI, Win32-Apps verwenden weiterhin HWNDs, und UWP-Apps zeigen immer Inhalte in einem CoreWindow an.

Diese API ist nur für Kompositor-Apps vorgesehen, die spezielle Hardware steuern.

Diagramm mit API-Architekturebenen für spezialisierte Displays.

Szenarien zum Erstellen benutzerdefinierter Kompositor

Die Windows.Devices.Display.Core-APIs eignen sich für die Verwendung in den folgenden Szenarien:

  • Virtuelle und Augmented Reality-Displays, die einen proprietären Kompositor benötigen, um den Anzeigecontroller direkt zu steuern und fein abgestimmte Kontrolle über die Anzeigedauer und Moduskonfiguration zu erhalten, die vom Windows-Desktop getrennt ist.
  • Spezielle Anzeigehardwareszenarien, die eine dedizierte Kontrolle über eine Anzeige in einer kommerziellen Einstellung erfordern. In Fällen, in denen der Windows-Desktop aufgrund von Hardwareverzerrungen, Graustufenanzeigen usw. nicht ordnungsgemäß auf einer solchen Anzeige gerendert werden kann.
  • Spezielle "Appliance"-Szenarien, in denen ein Monitor einer App ohne Störungen der Windows-Desktoperfahrung über einen längeren Zeitraum vollständig zugeordnet werden kann (z. B. ein dedizierter Videomonitor).

Die API führt dies durch:

  • Bereitstellen einer fein abgestimmten Kontrolle über die Vollständiganzeigemodusinformationen, einschließlich Drahtformat, HDR usw.
  • Die Verwendung von Zäunen zum Synchronisieren von Präsentationen ermöglicht es einem Kompositor, die Präsentation über Prozesse oder Unterkomponenten hinweg zu verketten, wobei nahezu kein Leistungsaufwand besteht.
  • Verbessern der Möglichkeit, das zugrunde liegende Video Present Network (VidPN) abzufragen und zu konfigurieren, damit sowohl Systemkomponenten als auch Komponenten auf niedriger Ebene komplexere Vorgänge auf weniger fehleranfällige und erweiterbarere Weise ausführen können.

Beachten Sie, dass diese API nur für einen sehr spezifischen Satz von Anwendungsfällen von Drittanbietern mit spezieller Hardware vorgesehen ist. Die Verwendung ist stark auf Hardware beschränkt, die selbst die Funktionalität dieser API benötigt. Daher wird ein gewisses Maß an Vertrautheit mit Hardwarekonzepten von Entwicklern erwartet, und Partner sollten sich direkt an Microsoft wenden, um Bei Problemen zu helfen.

Hardware- und Softwareanforderungen

Benutzerdefinierte Kompositor von Drittanbietern können nur Displays erwerben, die als head-mounted Displays (HMDs) oder "spezialisierte" Displays festgelegt wurden. Diese Bezeichnung muss auf eine von zwei Arten bereitgestellt werden:

  • EDID-Erweiterung – Benutzerdefinierte Anzeigegeräte, die für die dauerhafte Verwendung als HMDs, Röntgenmonitore, Videowände oder andere spezielle Szenarien entwickelt wurden, sollten die Microsoft EDID-Erweiterung für kopfmontierte und spezialisierte Displays implementieren.
  • Benutzerüberschreibung – Bei benutzerdefinierten Hardwareinstallationen mit standardmäßigen Monitoren bietet Windows einen Benutzeroberflächenschalter zum Entwerfen von Monitoren als "spezialisiert".

Displays dürfen nicht als HMDs oder spezialisierte Displays festgelegt werden, indem die EDID in der Software überschrieben wird.

Hinweis

Spezialisierte Displays sind nur ab Windows 10, Version 2004, verfügbar und erfordern Windows 10 Enterprise, Windows 10 Pro for Workstations oder Windows 10 IoT Enterprise.

Roadmap für die Implementierung eines benutzerdefinierten Kompositors

Die Implementierung eines benutzerdefinierten Kompositors kann in mehrere Phasen unterteilt werden:

  • Aufzählen und Auffinden zugeordneter HMDs oder spezialisierter Displays
  • Besitz der ausgewählten Displays erwerben
  • Konfigurieren von Modi für alle ausgewählten Anzeigen
  • Erstellen von Ressourcen für die Darstellung von Frames auf den Displays
  • Rendern von Inhalten und Planen einer Framepräsentation
API Zweck und Zielgruppe
DisplayInformation Wird zum Abrufen von Rendering- und Layouteigenschaften für ein CoreWindow-Element verwendet.
HdmiDisplayInformation Xbox-only-API zum Aufzählen und Festlegen eines eingeschränkten Satzes von Modi. Hochspezialisiert für Xbox-Medien-App-Szenarien.
DisplayMonitor Wird zum Abfragen von Eigenschaften eines physischen Monitorgeräts verwendet. Macht keine Laufzeitinformationen darüber verfügbar, wie ein Monitor konfiguriert oder aktuell vom Betriebssystem verwendet wird.
EnumDisplayDevices, EnumDisplayMonitors, EnumDisplaySettingsEx Ältere Win32-APIs zum Abfragen von HMONITORs, GDI-Geräten und physischen Monitorzuordnungen. Die hier zurückgegebenen Informationen werden hochgradig virtualisiert und für anwendungskompatibilität verwaltet.
Direct3D Wird zum Rendern von Pixelinhalten in GPU-Oberflächen und zur Berechnung auf einer GPU verwendet.
DXGI-Swapchains Wird für fensterlose und rahmenlose Vollbildpräsentationen verwendet. App-Swapchaininhalte fließen durch den Systemkompositor, DWM.
DXGI-Ausgabeaufzählung Stellt DXGI-Wrapper um HMONITORs bereit.
QueryDisplayConfig, SetDisplayConfig, DisplayConfigGetDeviceInfo, DisplayConfigSetDeviceInfo Win32-APIs zum Konfigurieren der Anzeigetopologie. Stellt keinen Mechanismus zum Aufzählen mehrerer Modi bereit, verfügt jedoch über eine vielzahl von Informationen zu aktuellen Konfigurationen und Einstellungen. Nicht alle neueren Eigenschaften eines Modus werden von diesen APIs verfügbar gemacht.
Windows.Devices.Display.Core (dieses Dokument) Wird zum Aufzählen von Zielen, Zum Aufzählen von Modi, zum Konfigurieren von Modi, zum Zuordnen von GPU-Oberflächen für die Präsentation und zum Darstellen von Inhalten für die Anzeige verwendet.

Übersicht über die Anzeigekonfiguration

Physische Hardwareaufzählung

Die Windows.Devices.Display.Core-API verfügt über verschiedene Objekte zur Darstellung physischer Hardwareobjekte. Ein DisplayAdapter ist in der Regel (aber nicht immer) ein physisches Hardwaregerät, z. B. eine MIT PCI Express verbundene GPU oder eine integrierte GPU auf einer CPU. DisplayTarget-Objekte stellen die physischen Anschlüsse (z. B. HDMI, VGA, DisplayPort usw.) dar, die über die GPU verbunden werden können. Dies kann interne, nicht benutzerfreundliche Verbindungen für Geräte mit internen Monitoren (Laptops, Tablets usw.) umfassen. Möglicherweise gibt es mehr DisplayTarget-Objekte , die in der Software dargestellt werden, als ein Benutzer gleichzeitig eine Verbindung herstellen kann. Da der DisplayPort-Verbindungsstandard z. B. daisy-Verkettung zulässt, führen GPU-Treiber in der Regel mehrere DisplayPort-Ziele pro physischen Port auf, um verkettete Monitore zu berücksichtigen.

Abbildung der Hardwaretopologie für Anzeigeadapter und Anzeigeziele.

Objekte für Einstellungsmodi

Zum Aufzählen von DisplayTarget-Objekten , Einstellungs- und Abfragemodi usw. werden Verbindungen mit DisplayTarget-Objekten mit DisplayPath-Objekten dargestellt. Gruppen von Pfaden, die denselben Inhalt (Klongruppen) anzeigen, werden durch DisplayView dargestellt, und diese werden in einem DisplayState aggregiert. Ein DisplayState -Objekt kann daher einen vollständigen Satz von Modusstatus darstellen, der an Treiber für mehrere Monitore gesendet werden kann.

Abbildung der Modustopologie mit Anzeigepfad, Anzeigeansicht und Anzeigezustandsobjekten.

Atomzustand für Die Konfiguration und Aufzählung des Modus

Die Windows.Devices.Display.Core-API wurde entwickelt, um sicherzustellen, dass Kompositor den Zugriff auf verschiedene Systemanzeigezustand atomisch und mit gut definierten Aleness-Verhaltensweisen erhalten können. Dies ist wichtig, da GPUs gemeinsam genutzte Ressourcen mit sehr enger Bandbreite und Leistungseinschränkungen sind. In modernen Systemen können Geräte jederzeit ankommen/verlassen, und andere Dinge können sich auf die Liste der verfügbaren Anzeigemodi auswirken (z. B. Andocken/Abdocken, Energiesparzustände, andere Komponenten, die Modi ändern, auf einem anderen Pfad). Daher ist es wichtig, dass Kompositor widerstandsfähig für Änderungen an der Systemkonfiguration sind, indem sie die Windows.Devices.Display.Core-API verwenden und empfohlene Muster zum Konfigurieren des Zustands befolgen.

Die Windows.Devices.Display.Core-API bietet daher ein einfaches transaktionsbasiertes Read-Modify-Commit-Modell, ähnlich einer Datenbank. Clients können ein DisplayState-Objekt für Anzeigegeräte im System atomisch lesen. Alle Objekte sind entweder unveränderlich oder stellen auch klar definierte APIs zum Aktualisieren/Commit-Zustand zurück zum System bereit. Änderungen werden erst vorgenommen, wenn DisplayState.TryApply aufgerufen wird, wodurch Änderungen am System "commits" vorgenommen werden. Das Commit/Anwenden von Änderungen auf einen DisplayState schlägt entweder ohne Auswirkung fehl oder ist mit den angewendeten vollständigen Änderungen erfolgreich.

So nutzen Sie die Atomitätsfeatures der API:

  • Schreiben Sie eine beliebige Konfigurationslogik für den Modus in einer Wiederholungsschleife.
  • Erstellen Sie einen neuen DisplayState am Anfang der Moduskonfiguration innerhalb jeder Schleife.
  • Verwenden Sie das FailIfStateChanged-Flag beim Aufrufen von DisplayState.TryApply, um zu erkennen, dass der Systemstatus nicht mehr mit dem zeitpunkt der Erstellung des DisplayState-Objekts übereinstimmt. Auf diese Weise können Sie den Vorgang wiederholen. Wenn der Vorgang mit SystemStateChanged fehlschlägt, wiederholen Sie die gesamte Schleife.
  • Mischen Sie keine anderen APIs (DXGI, GDI usw.), die den Zustand mit der Verwendung von Windows.Devices.Display.Core-APIs lesen oder ändern, da sie möglicherweise nicht über die gleichen Atomitätsgarantien verfügen.
#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);

Die folgenden APIs lesen den Zustand atomisch aus dem System:

Die folgenden APIs übernehmen den Status zurück an das System:

  • DisplayManager
  • DisplayState
    • TryApply Aktualisiert den aktuellen Anzeigezustand des Systems, indem Sie Modi für alle eigenen Ziele im System über die Anzeigetreiber festlegen oder löschen.

Bekannte Einschränkungen

Die Windows.Devices.Display.Core-API hat mehrere bekannte Einschränkungen (ab Windows 10, Version 2004):

  • Indirekte Anzeigetreiber (z. B. Miracast, USB-Grafikkarten, Softwaretreiber) können derzeit nicht behoben werden. DisplayManager.CreateDisplayDevice schlägt fehl, wenn ein indirekter Anzeigeadapter übergeben wird.

Beispielcode

Eine Beispielanwendung finden Sie im benutzerdefinierten Beispiel für Windows.Devices.Display.Core.