Freigeben über


Automatische Bildschirm-Umschaltung

Wichtig

Einige Informationen beziehen sich auf ein Vorabversionsprodukt, das vor der kommerziellen Veröffentlichung erheblich geändert werden kann. Microsoft übernimmt keine Gewährleistungen, ausdrücklich oder konkludent in Bezug auf die hier bereitgestellten Informationen.

Dieser Artikel beschreibt die Funktion der automatischen Bildschirmumschaltung (ADS), die Unterstützung dafür bietet, dass der interne Bildschirm eines Laptops nahtlos zwischen einer integrierten GPU (iGPU) und einer diskreten GPU (dGPU) umgeschaltet werden kann. ADS ist ein optionales WDDM-Feature, das ab Windows 11, Version 24H2 Update 2025.01D (WDDM 3.2) unterstützt wird.

In diesem Artikel:

  • GPU0 bezieht sich auf die GPU, mit der das integrierte Panel derzeit verbunden ist.
  • GPU1 bezieht sich auf die GPU, zu der das Panel gewechselt werden soll.

Überblick

Einige freigegebene Laptops verfügen über ein Multiplexer-Gerät (Mux), das es dem internen Panel ermöglicht, zwischen der integrierten GPU (iGPU) und der diskreten GPU (dGPU) zu wechseln. Der Grafiktreiber steuert derzeit den Wechsel in diesen Laptops ohne Wissen des Betriebssystems, was zu einigen unerwünschten Benutzererlebnissen führt.

ADS lässt zu, dass das Betriebssystem die Verwendung eines Mux-Geräts im System steuert, um zwischen der iGPU und der dGPU umzuschalten, wenn es auf das interne Panel zugreift. Daher kann das Betriebssystem eine bessere Benutzererfahrung bieten.

Die erste Version von ADS unterstützt nur die Umschaltung des internen Panels zwischen iGPU und dGPU. In Zukunft könnte diese Funktion erweitert werden, um auch das Muxen von externen Konnektoren in Laptops zu unterstützen.

Design auf hoher Ebene

Allgemein muss das System sicherstellen, dass der Inhalt des internen Panels während des Umschaltens ohne Flackern/Glitch angezeigt wird. Das Betriebssystem schränkt diese Funktionalität nicht auf ein bestimmtes Anzeigeprotokoll ein. Dieser Artikel konzentriert sich auf die Implementierung von ADS mit eDP, aber es gibt mehr Branchenstandards, die verwendet werden können (z. B. MIPI oder DSI). Das Design einer Plattform kann ein anderes Anzeigeverbindungsprotokoll verwenden, wenn es dieselbe Benutzererfahrung ohne Änderungen am Betriebssystem erzielen kann.

In den Unterabschnitten in diesem Abschnitt werden Designaspekte des Features identifiziert und der Ansatz auf hoher Ebene für jeden Aspekt detailliert beschrieben.

Steuerung des Mux-Geräts

Um Abhängigkeiten zwischen den iGPU- und dGPU-Grafiktreibern zu reduzieren, wird der Mux als separates Gerät verfügbar gemacht, das vom Betriebssystem unabhängig von den Grafiktreibern gesteuert werden kann. Die Vorteile dieses Ansatzes sind:

  1. Die Komplexität des Grafiktreibers wird reduziert, da der Treiber nicht wissen muss, wie er die verschiedenen Mux-Geräte, die ein OEM verwenden könnte, steuern soll.
  2. Dadurch werden Abhängigkeiten zwischen Grafiktreibern reduziert oder beseitigt, was die Abhängigkeit von Treiberupdates verringert und es OEMs erleichtert, GPUs und Multiplexer auszuwählen.
  3. Das Betriebssystem kann den Mux wechseln, wenn kein Grafiktreiber verfügbar ist.

Offenlegung des Mux-Geräts

Da es sich bei dieser Lösung um einen Mux zwischen der internen iGPU und der dGPU handelt, ergibt es Sinn, das Mux über ACPI freizugeben.

Funktionalität des Mux-Treibers

Der Mux-Treiber muss die folgenden hohen funktionalen Anforderungen erfüllen:

  1. Er muss den Status des Mux, das Ziel, das aktuell das interne Panel steuert, und alle Funktionalitäten bereitstellen.
  2. Sie muss eine Möglichkeit bieten, einen Schalter auszulösen und den Status des Schalters zu melden.

Weitere Informationen über das Mux ACPI Gerät und seine Methoden finden Sie unter ACPI.

Um einen nahtlosen Switch auszuführen, erfordert das Mux-Gerät während des GPU-Switches jederzeit die folgenden Bedingungen:

  1. Stromversorgung des Panels. Das Mux stellt jederzeit Anforderungen an die Stromversorgung des Panels durch eine der GPUs. Es ist ok, dass beide GPUs gleichzeitig die Panelleistung bereitstellen.
  2. Helligkeitssteuerungssignale von beiden GPUs beim Umschalten.
  3. Helligkeitspegel (pulsweitenmoduliert) von beiden GPUs beim Umschalten.

Der Mux wechselt die folgenden Informationen zwischen den beiden GPUs und dem Panel:

  1. Helligkeitssteuerungssignal
  2. Helligkeitspegel (pulsweitenmoduliert)
  3. DisplayPort (DP) Aux-Leitung
  4. HPD-Leitung (Hot Plug Detection)
  5. DP-Datenleitung

Das Mux muss die Fähigkeit haben, zu schalten, wenn das Panel nicht aktiv ist. Zumindest bei der internen Umschaltung des Panels sollte das Mux beim Umschalten keine HPD-Signale an die GPU triggern.

Das Mux sollte vom GPU-Treiber niemals die ACPI-Methoden aufrufen.

Automatische Bildschirm-Umschaltung DDI

Es wurden mehrere DDIs hinzugefügt, um die Anforderungen des Mux zu erfüllen. Es gibt fünf verschiedene Punkte, an denen das Betriebssystem die DDIs eines Treibers während eines Mux-Wechsels aufruft, wobei die folgenden Funktionen verwendet werden. Die verschiedenen Aufrufe hängen von der Phase des Wechsels ab und davon, ob der Treiber die GPU steuert, die aktuell die Kontrolle über den Bildschirm hat.

DDI Beschreibung
DxgkDdiDisplayMuxPreSwitchAway Aufruf des Treibers, der aktuell mit dem Bildschirm verbunden ist. Dieser Aufruf informiert den Treiber darüber, dass das System plant, die Anzeige auf eine andere GPU (von GPU0 zu GPU1) zu wechseln.
DxgkDdiDisplayMuxPreSwitchAwayGetPrivateData Aufruf, um alle privaten Umschaltdaten von dem Treiber zu sammeln, der aktuell mit dem Panel verbunden ist (von GPU0).
DxgkDdiDisplayMuxPreSwitchTo Rufen Sie den Fahrer an, der zurzeit nicht mit dem Display verbunden ist. Dieser Aufruf informiert den Treiber, dass das Betriebssystem plant, die Anzeige auf diese GPU (zu GPU1) zu wechseln.
DxgkDdiDisplayMuxSwitchCanceled Rufen Sie den Fahrer an, um anzugeben, dass die Umschaltsequenz abgebrochen wurde, bevor der Wechsel abgeschlossen wurde.
DxgkDdiDisplayMuxPostSwitchAway Der Mux-Switch ist abgeschlossen, und der GPU0-Treiber ist nicht mehr mit dem Display verbunden.
DxgkDdiDisplayMuxPostSwitchToPhase1 Das Mux-Switching ist abgeschlossen und der Treiber von GPU1 ist nun mit dem Bildschirm verbunden. Dieser Treiber sollte jetzt Phase 1-Aufgaben ausführen.
DxgkDdiDisplayMuxPostSwitchToPhase2 Das Mux-Switching ist abgeschlossen und der Treiber von GPU1 ist nun mit dem Bildschirm verbunden. Dieser Treiber sollte jetzt Phase 2-Aufgaben ausführen.
DxgkDdiDisplayMuxUpdateState Wird beim Start des Adapters und bei der Rückkehr in den D0-Stromversorgungszustand aufgerufen, um dem Treiber den aktuellen Mux-Status mitzuteilen.

Es gibt explizite Aktionen, die der Treiber in jeder Phase ausführen muss. Diese Aktionen werden weiter unten in diesem Artikel beschrieben.

Eine vollständige Liste der ADS-bezogenen DDI-Aktualisierungen finden Sie unter WDDM DDI-Änderungen für die automatische Umschaltung des Bildschirms.

Austausch von Daten zwischen GPU0 und GPU1

Es kann Fälle geben, in denen eine bessere Benutzererfahrung erstellt werden kann, wenn:

  • GPU0 und GPU1 stammen aus demselben IHV.
  • GPU0 kann Informationen zur Anzeigekonfiguration, die für das Betriebssystem nicht transparent ist, an GPU1 übergeben.

Ein Datenblob wird durch eine GUID beschrieben, die der GPU1-Treiber schnell identifizieren kann, wenn er den Datenblob versteht. Auf hoher Ebene ruft das Betriebssystem GPU0 auf, um die GUID des Blobs und die Daten vor dem Wechsel abzurufen, und gibt sie an GPU1 weiter, bevor es aufgefordert wird, HPD in den Bildschirm einzublenden.

Der GPU1-Treiber ist für Folgendes verantwortlich:

  • Prüfen Sie, ob er die GUID des Blobs versteht.
  • Überprüfen der einzelnen Datenelemente im Blob, um schädliche Auswirkungen von falsch formatierten Daten im Blob zu vermeiden.

Interoperabilität der Treiber

Wenn ein WDDM-Treiber ADS unterstützt, muss er ADS unabhängig davon unterstützen, auf welchem OEM-System es ausgeführt wird oder auf welcher anderen GPU im System.

Die Switch-Sequenz

Obwohl es technisch möglich sein könnte, die Nutzung der GPU zu beenden, wenn der Treiber der GPU gestoppt wird, wird dieses Szenario derzeit nicht unterstützt. Die Umschaltung wird also nur durchgeführt, wenn auf beiden GPUs Treiber geladen sind, die die Umschalt-DDI unterstützen.

Die folgende Sequenz ist eine Übersicht über die gesamte Umschaltsequenz, wenn das Panel aktiv ist, wobei GPU0 und GPU1 die iGPU bzw. dGPU darstellen. GPU0 ist aktuell über das Mux mit dem internen Panel verbunden und wir möchten auf GPU1 umschalten, die das Panel abfragt.

  1. Auf der API-Ebene wird ein Switch-Aufruf gemacht.
  2. Das Betriebssystem sammelt Attribute des aktuellen internen Panelzustands (HDR, Modus, Aktualisierungsrate usw.) und sucht nach temporärem Anzeigemodus.
  3. Das Betriebssystem deaktiviert die Ausführung jeglicher Bildschirm-Topologie aufgrund von HPDs von jeder GPU im System.
  4. Das Betriebssystem ruft die Funktion DxgkDdiDisplayMuxPreSwitchTo des GPU1-Treibers auf und übergibt die aktuelle Helligkeitsstufe. Der Fahrer sollte folgendes nur ausführen, wenn der Deckel geöffnet ist:
    • Schalten Sie die Stromversorgung des Panels ein.
    • Legen Sie das Signal für die Helligkeit fest.
    • Legen Sie die Helligkeitsstufe fest, die das Betriebssystem übergeben hat.
  5. Das Betriebssystem deaktiviert den Aufruf von DxgkDdiQueryConnectionChange auf GPU0, um sicherzustellen, dass lid HPD away erst nach der Mux-Umschaltung verarbeitet werden kann.
  6. Das Betriebssystem ruft das DDI des GPU0-Treibers DxgkDdiDisplayMuxPreSwitchAway auf. Der Treiber muß Folgendes tun:
    • Wenn das Lid aktiv ist, PSR1 (Panel Self Refresh 1) auf dem Panel aktivieren und sicherstellen, dass es nicht deaktiviert wird, bis das Betriebssystem später in der Sequenz die Deaktivierung anfragt.
    • Ein Paket zu seiner Verbindungsänderungsliste hinzufügen, wobei DXGK_CONNECTION_CHANGE's ConnectionStatus auf MonitorStatusDisconnected und MonitorConnect.MonitorConnectFlags.DisplayMuxConnectionChange auf 1 festgelegt ist.
    • GPU0 kann keine Verbindungsänderungspakete für das Lid-Ziel in seine Warteschlange aufnehmen. Das Betriebssystem prüft, ob es dies tut.
    • Die Größe eines privaten ADS-Datenblobs (GUID und Daten) an das Betriebssystem zurückgeben. Wenn der GPU0-Treiber diesen Aufruf fehlschlägt, muss er sicherstellen, dass alle ADS-Verbindungsstatuspakete, die er in die Warteschlange gestellt hat, vor der Rückkehr entfernt werden.
  7. Wenn der GPU0-Treiber eine private Datengröße ungleich Null zurückgegeben hat, weist das Betriebssystem diese Größe zu und übergibt sie an den DxgkDdiDisplayMuxPreSwitchAwayGetPrivateData Callback von GPU0, um die privaten Schalterdaten zu erhalten.
  8. Der Mux wird vom Betriebssystem über die ACPI-Methode aufgerufen, um von GPU0 auf GPU1 umzuschalten.
  9. Das Betriebssystem ermöglicht den erneuten Aufruf der Methode DxgkDdiQueryConnectionChange von GPU0.
  10. Das Betriebssystem ruft GPU0's DxgkDdiQueryConnectionChanges auf, um das MonitorStatusDisconnected Verbindungspaket mit DisplayMuxConnectionChange auf 1 festgelegt zu verarbeiten.
  11. Das Betriebssystem ruft GPU0's DxgkddiSettimingsfromvidpn auf, um den Pfad des Bildschirms, von dem umgeschaltet wird, zu deaktivieren. Der Treiber von GPU0 muss Folgendes tun:
    • Das Panel ausschalten.
    • Deaktivieren Sie das Helligkeitssignal.
    • Die Helligkeitsstufe nicht mehr an den Mux senden.
  12. Das Betriebssystem verarbeitet den Abgang des Bildschirms. Es löst keine Topologieänderung aus, um unnötige Topologieänderungen zu vermeiden.
  13. Das Betriebssystem ruft den DxgkDdiDisplayMuxPostSwitchToPhase1 Callback von GPU1 auf und übergibt dabei einen beliebigen privaten Blob von ADS, den es von GPU0 abgerufen hat. Der Treiber muß Folgendes tun:
    • Ermitteln Sie, ob der Deckel geöffnet oder geschlossen ist.
    • Fügen Sie das Paket mit DXGK_CONNECTION_CHANGE's zu seiner Verbindungsänderungsliste hinzu:
      • MonitorConnect.MonitorConnectFlags.DisplayMuxConnectionChange Bit festgelegt.
      • ConnectionStatus festgelegt auf MonitorStatusConnected, wenn das Lid offen ist oder MonitorStatusDisconnected, wenn das Lid geschlossen ist.
    • Wenn das Lid geschlossen ist, schalten Sie die Stromversorgung und das Helligkeitsaktivierungssignal für das Panel aus.
  14. Wenn das Betriebssystem noch nicht DxgkDdiQueryAdapterInfo mit DXGKQAITYPE_INTEGRATED_DISPLAY_DESCRIPTOR2 für das interne Ziel von GPU1 aufgerufen hat, tut es dies. Als Ergebnis dieses Aufrufs ruft das Betriebssystem auch DxgkDdiQueryDeviceDescriptor auf.
  15. Das Betriebssystem ruft den DxgkDdiQueryConnectionChange von GPU1 auf, um das Ereignis in seiner Verbindungsänderungsliste zu verarbeiten. Dieser Aufruf führt dazu, dass DxgkDdiQueryDeviceDescriptor für den neuen Monitor aufgerufen wird, der mit HPD verbunden ist.
  16. Das Betriebssystem ermöglicht die Änderung der Bildschirm-Topologie aufgrund von HPDs.
  17. Das Betriebssystem wird die Verbindungspakete von GPU0 und GPU1 asynchron verarbeiten, wobei DisplayMuxConnectionChange auf 1 festgelegt ist.
  18. Wenn GPU1 in der Warteschlange MonitorStatusConnected:
    • Das Betriebssystem ruft die DWM-Funktionen von GPU1 auf, um Modi aufzulisten.
    • DxgkddiSettimingsfromvidpn wird auf GPU1 aufgerufen, um den Bildschirm-Pfad zu aktivieren.
    • DWM rendert und präsentiert das Bild auf dem Bildschirm auf GPU1.
    • Das Betriebssystem wartet, bis der erste Frame sichtbar gemacht wird.
  19. Das Betriebssystem ruft den DxgkDdiDisplayMuxPostSwitchToPhase2 Callback von GPU1 auf, bei dem der Treiber PSR1 für den Bildschirm ausschalten sollte, wenn MonitorStatusConnected von GPU1 in die Warteschlange gestellt wurde; andernfalls sollte er nichts tun.
  20. Das Betriebssystem ruft den DxgkDdiDisplayMuxPreSwitchAway von GPU0 auf. Es werden zwar keine Aktionen vom Treiber erwartet, aber dieser Aufruf ist nützlich für Bereinigungen des Treibers oder für die Buchhaltung im Zusammenhang mit dem Umschalten.
  21. Das Betriebssystem sammelt die Attribute des aktuellen internen Zustands des Panels. Wenn sich der Panelstatus von dem zuvor gespeicherten Zustand unterscheidet, löst das Betriebssystem Telemetrie aus.

Diese Schaltsequenz ist für iGPU->dGPU und dGPU->iGPU identisch. Es kann vorkommen, dass der Mux umgeschaltet werden muss, wenn das Panel inaktiv ist. In diesem Fall ist diese Sequenz nicht erforderlich, und das Betriebssystem kann nur ACPI-Methoden auf dem Mux aufrufen, um zu wechseln.

Der Großteil des Betriebssystems weiß nicht, dass sich der Treiber im PSR-Modus befindet. Daher muss der Treiber immer noch Vsync-Synchronisierungen generieren, Vervollständigungen von Flips melden usw., auch wenn der Benutzer diese Vorgänge nicht sieht.

Wiederherstellungsprozess

Wenn während einer Phase der Sequenz ein Fehler auftritt, wird die folgende Bereinigung durchgeführt:

  1. Das Betriebssystem ruft die Funktion DxgkDdiDisplayMuxSwitchCancled von GPU0 auf, wenn die Funktion DxgkDdiDisplayMuxPreSwitchAway von GPU0 erfolgreich aufgerufen wurde, aber die Funktion DxgkDdiDisplayMuxPostSwitchAway nicht aufgerufen wurde.
  2. Das Betriebssystem ruft GPU1's DxgkDdiDisplayMuxSwitchCanceled auf, wenn GPU1's DxgkDdiDisplayMuxPreSwitchTo erfolgreich aufgerufen wurde, aber dessen DxgkDdiDisplayMuxPostSwitchToPhase2 nicht aufgerufen wurde.
  3. Das Betriebssystem aktiviert Änderungen der Anzeigetopologie erneut, wenn sie deaktiviert sind.
  4. Das Betriebssystem aktiviert den Aufruf von DxgkDdiQueryConnectionChange auf GPU0 wieder, wenn dieser deaktiviert ist.
  5. Das Betriebssystem fragt auf der GPU, an die das Lid angeschlossen ist, die Konnektivität des Lids ab.
  6. Das Betriebssystem triggert einen Reset der Bildschirm-Konfiguration (SDC). Der Treiber, an den das Panel über den Mux (zurückgegeben von DxgkDdiDisplayMuxSwitchCanceled) angeschlossen ist, muss sicherstellen, dass PSR deaktiviert ist.

Ungewöhnliche Ereignisse, die während der Umstellung auftreten können

  • Externer Benutzer schließt einen Monitor an oder entfernt ihn

    Als Teil der Sequenz zum Umschalten deaktivieren wir die Verarbeitung von HPD Ereignissen durch das Betriebssystem. Auf diese Weise werden alle HPD-Ereignisse in eine Warteschlange gestellt und zusammen mit dem Lid in einer einzigen atomaren Operation verarbeitet.

  • Eine andere App ruft SDC während der Umstellung auf.

    Während der Umschaltung werden Aufrufe an SDC blockiert und erst nach der Verarbeitung der Umschaltung ausgeführt.

  • Treiber wird während des Wechsels deaktiviert

    Wenn ein Treiber angehalten wird, schlagen die Aufrufe in der Switch-Sequenz fehl und die Recovery-Sequenz wird aktiviert. Im Abschnitt PnPStop wird auch beschrieben, wie sichergestellt wird, dass die Seite immer sichtbar ist.

Szenarien zum Schließen des Lids

Allgemein könnte der Treiber einen der folgenden Ansätze verwenden, um Ereignisse beim Öffnen/Schließen des Lids zu erkennen:

Für WDDM allgemein müssen die Treiber jedoch den DxgkDdiNotifyAcpiEvent Ansatz verwenden, da dieser die Möglichkeit bietet, den Dxgkrnl Status und den Treiberstatus zu synchronisieren. In Anbetracht der Tatsache, dass sowohl iGPU als auch dGPU in einer Sequenz zum Umschalten GPU1 sein können, ergibt es Sinn, dass alle ADS-Treiber den Status des Lids verfolgen, auch wenn das Lid nicht umgeschaltet wird.

Sobald das Betriebssystem das Ereignis DisplayMuxConnectionChange von GPU0 verarbeitet, geht es davon aus, dass GPU0 den Status des Lid-Ziels nicht mehr besitzt und daher keine weiteren Pakete zum Verbindungsstatus für dieses Ziel mehr liefern kann, bis das Lid zurückgeschaltet wird. Wenn GPU0 dies tut, führt das Betriebssystem einen Bug-Check durch. Sobald das Betriebssystem die DisplayMuxConnectionChange von GPU1 verarbeitet hat, betrachtet es GPU1 als Besitzer des Lid Status. Alle Ereignisse zum Öffnen oder Schließen des Lids zwischen diesen beiden Ereignissen können ignoriert werden, da von GPU1 erwartet wird, dass sie den Status des Lids kennt und das korrekte DisplayMuxConnectionChange-Paket liefert.

Wenn das Betriebssystem der Ansicht ist, dass der Treiber das Panel besitzt

In der folgenden Tabelle werden die Sequenzphasen beschrieben, in denen das Betriebssystem eine GPU als Besitzer des Panels betrachtet. Die besitzende GPU kann Verbindungsänderungen mit Hilfe der Switch-Sequenz melden. Die Schrittnummern stammen aus der zuvor beschriebenen Umschaltsequenz.

Stufe zu Stufe zu Welche GPU steuert das Panel
Vor dem Wechsel Schritt 5 GPU0
Schritt 6 Schritt 12 Keine GPU
Schritt 13 Nach dem Wechsel GPU1

Das Betriebssystem prüft, ob es ein Paket mit Verbindungsänderungen in der Warteschlange des Treibers für ein gemixtes Ziel sieht, wenn die GPU das Panel nicht steuert.

Steuerung der Panel-Selbstaktualisierung (PSR)

Die ADS Funktion verwendet PSR, um Störungen beim Übergang zu vermeiden. Insbesondere wird PSR1 (Vollbildaktualisierungsmodus) verwendet, damit GPU0 und GPU1 nicht aushandeln müssen, welcher PSR-Modus verwendet werden soll.

Auch innerhalb von PSR1 gibt es optionale Features, die das Panel unterstützen sollte.

Sink Funktionalität Details Sink offengelegt über
DPCD & eDP-Version Aktivieren Sie eDP v1.3 oder höher. DPCD
PSR Funktionalität und Version Sink unterstützt Version 1. DPCD 00070h Bit 7:0
Unterstützung von VSC SDP zur Übermittlung des PSR Status Nur für PSR; Sink muss mindestens Revision 2 mit bis zu 8 gültigen Bytes unterstützen, um den PSR Status und den CRC Wert zu übermitteln. DPCD 170
Sink muss den PSR-bezogenen Status ordnungsgemäß melden Sink muss den Status offenlegen, z.B. Link CRC-Fehler, RFB Storage-Fehler, Selbstrefresh-Status des Sink-Geräts, maximale Anzahl der Resync-Frames, letzte tatsächliche Sync-Latenz in Sink und zuletzt empfangenes PSR-SDP. DPCD 2008h, 2009h, 200Ah spiegeln den korrekten Status des Sinks wider.

Wenn GPU1 als Element eines DxgkddiSettimingsfromvidpn-Aufrufs des Betriebssystems ein Link-Training durchführt, kennt der Treiber die von GPU0 verwendete DP-Lane und Bandbreiteneinstellung nicht und muss daher eine vollständige Sequenz für das Link-Training durchführen, anstatt ein schnelles Link-Training. Das Betriebssystem wird keine PSR-Richtlinien zwischen den GPUs aushandeln, daher muss das Panel alle PSR-Versionen und -Features unterstützen, die von den GPUs verwendet werden. Beispielsweise muss das Panel ein Szenario unterstützen, in dem GPU0 PSR2 mit einigen festgelegten Features verwenden kann, dann wird PSR1 für den Switch verwendet, dann kann GPU1 PSR2 mit einem anderen Satz von Features verwenden.

Sicherstellen, dass das Panel während des Wechsels im PSR-Modus bleibt

Wenn GPU1 einen Modus auf dem Panel festlegt, gibt es keine Garantie dafür, dass die Link-Attribute, die von GPU1 festgelegt werden, während sich das Panel im PSR befindet, mit dem PSR-Eingangsmodus übereinstimmen. So können sich beispielsweise die Bildwiederholfrequenz oder die aktive Größe ändern. DP oder andere Branchenstandards liefern heute keine Möglichkeit für das Panel, zu melden, dass es das Panel im PSR-Modus halten kann, während Link-Attribute geändert werden. Langfristig möchten wir daran arbeiten, diese Funktion der DP-Spezifikation hinzuzufügen. Solange das nicht der Fall ist, muss der OEM für ein ADS-fähiges System eine TCon/Panel/Mux-Kombination auswählen, die im PSR bleiben kann, während sich die Link-Attribute (z.B. Bildwiederholrate, aktive Größe) zwischen zwei beliebigen Kombinationen im EDID ändern. Dieser Ansatz stellt sicher, dass PSR während des Wechsels aktiv bleiben kann.

Damit der ADS HLK-Test verifizieren kann, dass PSR während des Umschaltvorgangs beibehalten wird, möchten wir, dass das Betriebssystem weiß, ob PSR nicht aktiv war, nachdem GPU1 den Modus getestet hat. Eine Herausforderung besteht darin, dass nicht definiert ist, wie ein Panel reagieren soll, wenn es PSR während des Link-Trainings nicht unterstützen kann.

Als Element von DxgkDdiDisplayMuxPostSwitchToPhase2 gibt der Treiber einen booleschen Wert in pWasPanelInPSR zurück, um dem Betriebssystem mitzuteilen, ob er festgestellt hat, dass das Panel nicht im PSR war.

EDID des internen Panels

Damit das Betriebssystem das vorgesehene Verhalten beim Auswählen von Anzeigemodi und Topologien für unterschiedlich angeschlossene Monitore bereitstellt, müssen beide GPUs die EDID/DisplayId für die interne Anzeige melden. Diese Anforderung stellt sicher, dass die CCD-Datenbank, in der Anzeigemodi und Topologien gespeichert werden, dieselben Einstellungen auswählen, unabhängig davon, welche GPU die interne Anzeige steuert.

Die EDID, die die Treiber an das Betriebssystem melden, sollte die EDID sein, die über den Aux-Befehl vom Panel abgefragt wird, ohne dass änderungen erforderlich sind.

Aktuell ruft das Betriebssystem DxgkDdiQueryAdapterInfo(DXGKQAITYPE_INTEGRATED_DISPLAY_DESCRIPTOR2) auf, wenn es einen Treiber startet, der ein internes Panel liefert. Wenn der Mux von diesem integrierten Ziel weggeschaltet ist, kann der Treiber nicht mit dem Panel kommunizieren, um die erforderlichen Informationen zu sammeln. Die Lösung besteht darin, dass das Betriebssystem den Aufruf von DxgkDdiQueryAdapterInfo(DXGKQAITYPE_INTEGRATED_DISPLAY_DESCRIPTOR2) verzögert, wenn ein Treiber gestartet wird und der Mux von seinem internen Ziel weggeschaltet wird, bis der Mux zum ersten Mal auf das interne Ziel umgeschaltet wird.

Wie das Betriebssystem entscheidet, ob die ADS Funktion auf einem System aktiviert ist und die Umschaltung zugelassen wird

Das Betriebssystem führt die folgende Liste der Prüfungen aus, um festzustellen, ob ADS auf einem System verfügbar ist. Alle Prüfungen müssen wahr sein, damit ADS unterstützt wird.

  1. Es gibt eine GPU, die als integrierter Hybrid (DXGK_DRIVERCAPS.HybridIntegrated) markiert ist, die:
  2. Es gibt eine GPU, die als diskreter Hybrid (DXGK_DRIVERCAPS.HybridDiscrete) markiert ist, der:
  3. Der Mux ACPI-Name, der von der ACPI DMID-Methode aus Schritt 1 und 2 zurückgegeben wird, stimmt überein.
  4. Der Mux ACPI Gerät hat ACPI DMQU, DMCF und DMSL Methoden.
  5. Der Mux ACPI DMQU-Methode hat den ACPI-Namen des internen Panel-Ziels von einer der GPUs zurückgegeben.
  6. ADS unterstützt derzeit nur Systeme mit einem einzigen internen Panel.
  7. Entweder:
    1. GPU0, GPU1 und Mux ACPI liefern alle volle ADS-Unterstützung.
    2. GPU0, GPU1 und Mux ACPI liefern alle entweder experimentelle oder volle ADS-Unterstützung und der Registrierungsschlüssel EnableMDMExperimentalFeature ist festgelegt.

Die Bedingungen 1 und 2 bedeuten, dass beide Adapter gestartet sein müssen, damit der Mux umgeschaltet werden kann.

Kontrolle der Qualität des Rollouts von ADS-Funktionen

Damit ADS eine gute Benutzererfahrung bietet, müssen alle folgenden Komponenten einwandfrei zusammenarbeiten:

  1. Der Bildschirm des Betriebssystems zeigt die Mux-Funktionalität an.
  2. Die ACPI-Methoden der Plattform für die Mux-Umschaltung.
  3. Der Mux-Umschaltfunktionalität des Bildschirms in den iGPU- und dGPU-Treibern.

Um den IHV/OEMs zu helfen, in ihren Releases Code in nicht-chirurgischer Qualität zu haben, können sie eine der folgenden Stufen der ADS-Unterstützung bereitstellen:

  • Keine Unterstützung: Der Treiber unterstützt keine ADS-Funktionen.
  • Entwicklungsunterstützung: Der Treiber unterstützt ADS, aber die Implementierung des Treibers befindet sich noch in der Entwicklung und sollte nicht über diesen Zweck hinaus verwendet werden.
  • Experimentelle Unterstützung: Der Treiber unterstützt ADS, hat aber noch nicht die Lieferqualität erreicht. Das Betriebssystem aktiviert ADS nicht standardmäßig, kann aber so konfiguriert werden, dass es aktiviert wird.
  • Volle Unterstützung: Der Treiber unterstützt ADS in Lieferqualität. Das Betriebssystem ist der Ansicht, dass der Treiber ADS unterstützt.

Anzeigeattribute, die nach einem Bildschirmwechsel unverändert bleiben sollen

Ein Anzeigeschalter sollte keines der folgenden Anzeigeattribute ändern:

  1. Desktopauflösung
  2. VidPn-Pfad (einschließlich VidPn-Quellmodus, Zielmodus, Skalierung und so weiter)
  3. DPI
  4. Nachtlicht-Einstellung
  5. Gamma
  6. Topologie anzeigen
  7. HDR ein/aus
  8. SDR-Weißwert
  9. Farbprofil
  10. OPM-Zieltyp des Monitors
  11. Bildschirmhelligkeit

Passende GPU-Caps für einen nahtlosen Wechsel

Um dem Benutzer ein nahtloses Wechseln zu ermöglichen, sollte das Display nach dem Schalter wie vor dem Schalter gleich konfiguriert werden. Es gibt bestimmte GPU-Features, für deren Verhalten beide GPUs die gleiche Unterstützung benötigen. Wenn zum Beispiel eine GPU HDR unterstützt und die andere nicht, wäre ein Wechsel bei aktiviertem HDR auf einer GPU nicht nahtlos.

In der folgenden Tabelle sind GPU-Anzeigefunktionen und -features aufgeführt und die Ausrichtungsanforderungen zwischen den beiden GPUs beschrieben.

Funktion GPUs für nahtlose Unterstützung erforderlich
HDR Wenn das Panel HDR unterstützt, dann müssen beide GPUs entweder fp16 HDR unterstützen oder HDR nicht unterstützen.
Hw-Cursor Nein. Das Betriebssystem passt sich an verschiedene Cursoreigenschaften ohne sichtbare Unterbrechungen für den Benutzer an.
MPO Nein. Das Betriebssystem passt sich an verschiedene MPO-Features an, ohne dass der Benutzer sichtbare Unterbrechungen bemerkt.
PSR Beide GPUs müssen dieses Feature unterstützen.
EDID/DisplayID Beide GPUs müssen dieselbe EDID/DisplayId verfügbar machen.
Helligkeits-Caps Beide GPUs müssen die gleiche Helligkeitsschnittstelle und Helligkeitsgrenzen unterstützen.
Helligkeitsstufen Beide GPUs müssen dieselben Helligkeitsstufen und Intervalle verfügbar machen.
Lösung Beide GPUs müssen die gleichen Quellmodi und die gleiche Zielauflösung unterstützen.
Bildwiederholraten Siehe Problem, wenn GPU1 die Bildwiederholrate nicht unterstützt, mit der GPU0 das Panel ausführt für weitere Informationen.
Dynamische Aktualisierungsrate Nein. Das Betriebssystem passt sich an die Unterstützung verschiedener virtueller Aktualisierungsraten an.
Variable Bildwiederholrate Siehe Problem, wenn GPU1 die Bildwiederholrate nicht unterstützt, mit der GPU0 das Panel ausführt für weitere Informationen.

Problem, wenn GPU1 die Bildwiederholrate nicht unterstützt, mit der GPU0 das Panel ausführt

Wenn GPU1 denselben Modus wie GPU0 nicht unterstützt, wird der eingeschränkte Modus wahrscheinlich in der Anzeigetopologiedatenbank gespeichert. Wenn das System dann wieder auf GPU0 umschaltet, wird der reduzierte Modus festgelegt. Wenn GPU0 beispielsweise 120Hz unterstützt, aber GPU1 nur 60Hz unterstützt, kann die folgende Sequenz auftreten:

  1. Das System ist so konfiguriert, dass GPU0 die Anzeige steuert und der Modus 120Hz beträgt.
  2. Der Benutzer wechselt manuell zu GPU1.
  3. Die Display-Topologiedatenbank hat 120Hz für das Display gespeichert, aber GPU1 unterstützt dies nicht, deshalb wählt das Betriebssystem 60Hz.
  4. 60Hz wird festgelegt und in der Anzeigetopologiedatenbank gespeichert.
  5. Der Benutzer wechselt manuell zurück zu GPU0.
  6. Die Bildschirm-Topologiedatenbank liest 60 Hz aus der Datenbank.

Um die beste Erfahrung zu bieten, sollte ein OEM eine iGPU und dGPU auswählen, die beide die maximale Bildwiederholfrequenz des internen Panels unterstützen. Wenn das nicht möglich ist und eine GPU die maximale Bildwiederholrate des Bildschirms nicht unterstützen kann, muss die GPU, die die Bildwiederholrate des Bildschirms unterstützt, die Funktion Windows Dynamic Refresh Rate (DRR) mit folgenden Bereichen unterstützen:

  • Die höchste Bildwiederholrate der anderen GPU.
  • Die höchste Bildwiederholrate des internen Bildschirms.

Wenn das Panel beispielsweise 300 Hz unterstützen kann und die iGPU nur 60 Hz unterstützen kann, muss die dGPU VRR mit einem Bereich von mindestens 60 Hz bis 300 Hz unterstützen.

Zusammenfassend lässt sich sagen, dass die ADS-Anforderung für die Bildwiederholrate entweder ist:

  1. iGPU und dGPU unterstützen die maximale Bildwiederholrate des internen Panels.
  2. Die GPU, die die maximale Bildwiederholrate des internen Bildschirms unterstützt, muss DRR in einem Bereich zwischen der höchsten Bildwiederholrate, die die andere GPU unterstützen kann, und der maximalen Bildwiederholrate des internen Bildschirms unterstützen.

HDR und Dolby Vision

Das Betriebssystem legt auf dem internen Panel auf GPU1 nach dem Wechsel den gleichen HDR/Dolby Vision Status fest, wie er auf dem internen Panel auf GPU0 vor dem Wechsel festgelegt war. Der Benutzer sollte keine Änderungen bemerken.

Nachtlicht

Nightlight wird über WDDM Gamma oder Farbmatrix-DDIs implementiert. In beiden Fällen legt das Betriebssystem über GPU1 nach dem Wechsel die gleichen Nachtlicht-Level fest wie bei GPU0 vor dem Wechsel.

Farbprofil

Das Betriebssystem wendet nach dem Umschalten dasselbe Farbprofil auf das Panel an wie vor dem Umschalten.

Anzeige des Bildschirms für den Bug-Check

Aktuell unterstützt das Betriebssystem die Anzeige des Bildschirms für den Bug-Check auf Geräten, die nicht von POST stammen. Wenn ein Bug-Check auftritt, schaltet das Betriebssystem:

  • Der Mux wird nicht umgeschaltet.
  • Verwendet die aktuelle Betriebssystemunterstützung zum Anzeigen des Fehlerüberprüfungsbildschirms.

Bei der Auswertung möglicher Ziele für die Anzeige des Bug-Checks überspringt das Betriebssystem alle Ziele, die mit einem Mux verbunden sind, der auf ein anderes Ziel umgeschaltet ist.

Es gibt eine kleine Zeitspanne, in der das HPD von GPU0 verarbeitet wurde, das HPD von GPU1 aber noch nicht vollständig verarbeitet ist. Wenn während dieses Zeitraums eine Fehlerüberprüfung auftritt, wird der Benutzer die Fehlerüberprüfung nicht sehen. Wenn in dem kleinen Zeitraum, in dem PSR noch aktiviert ist, ein Bug-Check auftritt, sollte der Treiber, der den Bildschirm steuert, sicherstellen, dass sich das Panel nicht im PSR-Modus befindet, wenn das Betriebssystem DxgkDdiSystemDisplayEnable aufruft.

Algorithmus für die adaptive Helligkeit

In einer idealen Welt sollte der von beiden GPUs verwendete inhaltsadaptive Algorithmus den gleichen Effekt erzeugen. Der gleiche Effekt wird jedoch wahrscheinlich nicht eintreten und der Benutzende könnte einen Unterschied bemerken, wenn das interne Panel umgeschaltet wird.

Helligkeitsdaten

Um sicherzustellen, dass der Benutzer aufgrund des Schalters keine Helligkeitsänderung bemerkt, müssen alle Helligkeitsattribute, die von GPU0 und GPU1 verfügbar gemacht werden, identisch sein. Diese Anforderung stellt sicher, dass jede Helligkeitsstufe vor der Umschaltung auf GPU0 auch auf GPU1 nach der Umschaltung unterstützt wird.

Dazu müssen die Treiber für GPU0 und GPU1 dies tun:

  1. Verwenden Sie dieselbe Helligkeitsschnittstelle, entweder DXGK_BRIGHTNESS_INTERFACE_2 oder DXGK_BRIGHTNESS_INTERFACE_3, wobei Version 3 dringend empfohlen wird.
  2. Für die Brightness v3-Schnittstelle müssen beide Treiber entweder die nits-basierte oder die unkalibrierte Helligkeit anzeigen.
  3. Für die Brightness v2-Schnittstelle müssen beide Treiber genau die gleichen möglichen Helligkeitsstufen von GetPossibleBrightness zurückgeben.
  4. Für die Brightness v3-Schnittstelle müssen beide Treiber genau die gleichen Bereiche zurückgeben, d.h. jeder Treiber sollte identische DXGK_BRIGHTNESS_GET_NIT_RANGES_OUT Strukturen von GetNitRanges zurückgeben.
  5. Die internen Tabellen, die der Treiber verwendet, um vom Betriebssystem bereitgestellte Helligkeitsstufen in panelspezifische Einstellungen zu konvertieren, müssen identisch sein.

In den meisten Laptops erhält der GPU-Treiber einige oder alle dieser Helligkeitsstufendaten von der Plattform auf nicht standardmäßige Weise. Wir erwarten, dass dieser Plattform-zu-GPU-Datenaustausch möglicherweise erweitert werden muss, um diese Anforderungen zu erfüllen.

Obwohl die Brightness-Schnittstelle beim Start des Adapters abgefragt wird, ruft das Betriebssystem keine der DDIs der Brightness-Schnittstelle auf, bis das interne Panel HPD'ed ist. HPD erfolgt, nachdem der Mux auf die GPU geschaltet wurde, so dass der Treiber zu diesem Zeitpunkt Zugriff auf die EDID des internen Panels hat.

Wir wissen, dass es IHV-spezifische Möglichkeiten für den Treiber gibt, die Panelhelligkeit für Panels festzulegen, die PWM nicht unterstützen. Diese Methode macht es jedoch für den TCon komplizierter, da er die Helligkeit möglicherweise auf eine andere IHV-spezifische Weise unterstützen muss, je nachdem, welche GPU über den Mux angeschlossen ist.

Boot-Konfiguration des Mux

Die Systemfirmware steuert, welche GPU zur Systemstartzeit mit dem internen Panel verbunden ist. Das Betriebssystem speichert, welche GPU zuletzt in der Steuerung des Panels war. Während der Sequenz zum Booten schaltet das Betriebssystem den Mux bei Bedarf um, damit die richtige GPU das Panel steuert.

Um ein Boot-Image beizubehalten, wenn ein Mux-Switch erforderlich ist, wird der Wechsel nur ausgeführt, wenn:

  • Beide GPUs werden eingeschaltet.
  • Das Betriebssystem ist von der Boot-Grafikkarte, die die Ausgabe steuert, zur DWM/Shell, die die Ausgabe steuert, übergegangen.

Die Umschaltung erfolgt also nach dem DxgkddiSettimingsfromvidpn-Aufruf auf der GPU, die das interne Panel steuert, und der Benutzer wird eine eingefrorene Seite sehen, während sich das Panel während der Umschaltung im PSR befindet.

Bereitstellung von Mux-Informationen für den Treiber

Dieses Feature ist absichtlich so konzipiert, dass das Betriebssystem den Treiber aufruft, um die Informationen bereitzustellen, anstatt einen Rückruf bereitzustellen, den der Treiber jederzeit aufrufen kann. Mit dieser Methode wird verhindert, dass der Treiber verwechselt wird, wenn er den Betriebssystemstatus während einer Switchsequenz abfragt.

Das Betriebssystem ruft das DDI DxgkDdiDisplayMuxUpdateState des Treibers auf, um dem Treiber den aktuellen Status des Mux in den folgenden Fällen mitzuteilen:

  1. Beim Start des Treibers, was dem Treiber die Möglichkeit bietet, zeitraubende Sequenzen zur Abfrage zu vermeiden, wenn das Panel nicht angeschlossen ist.
  2. Bei der Rückkehr zu D0 von Dx. Bei der Rückkehr aus bestimmten Stromversorgungszuständen (z.B. Ruhezustand) muss die Firmware den Mux möglicherweise zurücksetzen; daher kennt der Treiber den Status nicht.

Diese Fälle sowie die normalen DDIs, die an der Sequenz beteiligt sind, sorgen dafür, dass der Treiber jederzeit feststellen kann, in welche Richtung ein Mux geschaltet ist, wenn die GPU aktiv ist.

In der ersten Version dieser Funktion ist nicht geplant, den Mux zu wechseln, wenn das interne Panel nicht aktiv ist, so dass alle Schalter die gleiche Sequenz durchlaufen.

Startzeit des Adapters

Wenn ein Treiber startet, muss er auf Polling-Anfragen des Betriebssystems reagieren. Der Treiber könnte versuchen, durch Kommunikationsversuche zu ermitteln, ob der Mux auf ihn umgeschaltet ist, aber das könnte zeitaufwendig oder unzuverlässig sein. Als Teil der GPU-Startsequenz ruft das Betriebssystem die DxgkDdiDisplayMuxUpdateState DDI für jedes Ziel auf, das mit einem Mux verbunden ist, und zeigt an, ob er auf dieses Ziel umgeschaltet ist.

Wenn ein Treiber startet, muss er auf Polling-Anfragen des Betriebssystems reagieren. Der Treiber könnte versuchen, zu ermitteln, ob der Mux durch die Kommunikation mit dem Betriebssystem auf ihre GPU umgestellt ist, dies kann jedoch zeitaufwändig oder unzuverlässig sein.

Stattdessen ruft das Betriebssystem als Element der GPU Startsequenz DxgkDdiDisplayMuxUpdateState für jedes Ziel auf, das mit einem Mux verbunden ist, und zeigt an, ob der Mux auf dieses Ziel umgeschaltet ist. Das Betriebssystem liefert dem Treiber die Meldung, ob der Mux auf die GPU des Treibers umgeschaltet ist, bevor es irgendwelche Polling-DDIs aufruft.

Der ADS-Treiber liefert dem Betriebssystem weiterhin das interne Panel auf die gleiche Weise, wobei das Betriebssystem DxgkDdiQueryAdapterInfo(DXGKQAITYPE_INTEGRATED_DISPLAY_DESCRIPTOR2) aufruft, um die Details des internen Panels abzufragen. Der Treiber muss sicherstellen, dass DXGK_CHILD_CAPABILITIES.HpdAwareness für jedes an einen Mux angeschlossene Ziel auf HpdAwarenessInterruptible festgelegt ist.

D0-Übergang

Immer, wenn eine GPU mit einem angeschlossenen Mux aus einem Zustand niedriger Leistung in den eingeschalteten Zustand zurückkehrt, ruft das Betriebssystem DxgkDdiDisplayMuxUpdateState auf, um dem Treiber mitzuteilen, ob der Mux mit seinem Ziel verbunden ist oder auf die andere GPU umgeschaltet wurde.

Startsequenz

Die folgende Sequenz zum Booten verdeutlicht ADS-spezifische Aspekte. In dieser Sequenz startet das System mit:

  • Der iGPU, der mit dem Mux verbunden ist.
  • Die letzte Konfiguration des Benutzers vor dem Neustart war, dass der Mux mit der dGPU verbunden ist.

Die Startsequenz ist von Natur aus asynchron, sodass diese Sequenz nur als Beispiel dient.

  1. Das System schaltet sich ein und die iGPU ist über den Mux mit dem Panel verbunden.
  2. Die iGPU zeigt den Startbildschirm auf dem Panel an.
  3. Windows lädt und zeigt die Boot-Animation auf dem internen Lid an.
  4. Aufgrund von _DEP sowohl auf der iGPU als auch auf der dGPU wird der Mux-Treiber des Betriebssystems vor den beiden GPU-Treibern gestartet. Der Mux-Treiber verwendet ACPI-Aufrufe, um sicherzustellen, dass der Mux ordnungsgemäß konfiguriert ist. Der Mux-Treiber überprüft, ob die ACPI-Mux-Implementierung ADS-Anforderungen erfüllt.
  5. Dxgkrnl ruft DxgkDdiAddDevice für die iGPU auf.
  6. Dxgkrnl ruft DxgkDdiQueryInterface(DXGK_DISPLAYMUX_INTERFACE) für die iGPU auf. Auch wenn das aktuelle System ADS nicht unterstützt, gibt der Treiber seine Schnittstelle zurück, wenn es ADS unterstützt.
  7. Dxgkrnl ruft DxgkDdiDisplayMuxGetDriverSupportLevel auf, um den ADS-Unterstützungslevel des Treibers zu erhalten.
  8. Dxgkrnl ruft DxgkDdiDisplayMuxReportPresence(TRUE) auf, um der iGPU mitzuteilen, dass das System über einen funktionierenden ADS Mux verfügt.
  9. Dxgkrnl ruft DxgkDdiStartDevice auf. Der iGPU-Treiber gibt die Anzahl der untergeordneten Elemente einschließlich des VidPn-Ziels für das interne Panel zurück.
  10. Dxgkrnl ruft DxgkDdiDisplayMuxGetRuntimeStatus auf, um zu prüfen, ob die iGPU ADS unterstützt und ob der Treiber alle erforderlichen Informationen vom System erhalten hat.
  11. Dxgkrnl ruft DxgkDdiQueryChildStatus für jedes untergeordnete Element auf, das die iGPU bereitstellt.
  12. Sobald Dxgkrnl das der iGPU untergeordnete Element findet, das mit dem Mux verbunden ist, ruft es DxgkDdiDisplayMuxUpdateState auf, um der iGPU mitzuteilen, dass der Mux mit diesem Ziel verbunden ist.
  13. Da die iGPU einen angeschlossenen internen Monitor ausgesetzt hat, legt Dxgkrnl mit DxgkddiSettimingsfromvidpn einen Modus auf der iGPU fest.
  14. Dxgkrnl startet den dGPU-Treiber und wiederholt dann die Schritte 5-12 für die dGPU.
  15. Dxgkrnl stellt fest, dass die iGPU, die dGPU und der Mux korrekt konfiguriert sind und erstellt daher ein Mux-Paar und die Eigenschaften der PnP-Geräte-Schnittstelle für das Mux-Paar.
  16. Dxgkrnl liest die letzte Mux-Konfiguration aus der Registrierung. Da die letzte Konfiguration dGPU war, startet Dxgkrnl nun die zuvor beschriebene Sequenz zur Umschaltung des Mux auf die dGPU.

Panel-Treiber

Die Monitor-Panel-Treiber werden auf der Grundlage der aus der EDID generierten PnP-Hardware-ID geladen. Da die EDID unverändert bleibt, wird der Paneltreiber geladen, wenn beide GPU das interne Panel steuern. Beide Treiber stellen die gleiche Helligkeitsfunktionalität zur Verfügung. Dementsprechend sollte der Ladevorgang kein Problem verursachen, und der Paneltreiber muss nicht wissen, welche GPU den Mux steuert.

Identifizieren Sie die Ziele, die ein Mux steuert

Wenn das Betriebssystem den Treiber startet, ruft es die Funktion DxgkDdiQueryChildRelations des Treibers auf, um Informationen über die untergeordneten Elemente abzufragen. Der Treiber füllt die DXGK_CHILD_DESCRIPTOR Struktur für jedes untergeordnete Ziel aus. Das AcpiUid Mitglied ist als der Wert definiert, der von der _ADR-Methode unter diesem Kind im ACPI Namespace zurückgegeben wird, was dem Betriebssystem die Möglichkeit bietet, den ACPI-Namen für dieses Kind zu finden.

Für ADS definieren wir eine ACPI DMID-Methode, die sich unter dem untergeordneten ACPI Namespace für das Ziel befinden muss. Diese DMID-Methode gibt den ACPI-Namen des Mux-Geräts zurück. Sie bietet dem Betriebssystem die Möglichkeit, den Mux ACPI-Namen für das Ziel zu finden.

PnP stoppt den Adapter, der zu einem Ziel scannt

Der Mux wird vom Betriebssystem nicht umgeschaltet, wenn die GPU, die auf das interne Panel zugreift, gestoppt wird. In den folgenden Szenarien werden die verschiedenen Fälle erläutert, in dem eine GPU beendet wird.

  1. GPU0 ist der Post. Sie ist mit dem internen Panel verbunden und wird angehalten.

    In diesem Fall übernimmt der Basic Display Driver (BDD) den aktuell aktiven Modus auf GPU0 und setzt die Aktualisierung des Bildschirms fort.

  2. GPU0 ist der Post, aber GPU1 ist mit dem internen Panel verbunden. GPU0 ist gestoppt.

    Aufgrund des aktuellen Designs des Betriebssystems wird der BDD auf GPU0 gestartet, was dazu führt, dass ein Geisterbildschirm geliefert wird und in der CPL des Bildschirms erscheint.

  3. GPU1 ist nicht der Post und ist mit dem internen Panel verbunden. GPU1 ist gestoppt.

    Aufgrund des aktuellen Betriebssystemdesigns wird BDD nicht auf GPU1 gestartet, daher kann der Benutzer das Panel nicht sehen.

  4. GPU1 ist nicht der Post. GPU0 ist mit dem internen Panel verbunden und GPU1 ist gestoppt.

    Es erfolgt kein Wechsel, und nichts passiert. GPU0 wird weiterhin auf dem Bildschirm des Panels angezeigt.

Szenarien 2 und 3 schaffen eine schlechte Benutzererfahrung. Das ADS-Feature ändert das Verhalten, um diese beiden Fälle zu beheben.

Plug-In/externe GPUs werden nicht unterstützt.

Wir glauben nicht, dass es einen Anwendungsfall für dieses Feature mit Plug-In-GPUs gibt.

ADS ist nur auf einzelne interne Panels beschränkt

Die erste Version von ADS unterstützt nur einzelne interne Panels. Das Feature wird jedoch auf eine Weise entwickelt, die es ermöglicht, in Zukunft mit minimalen Treiberänderungen externe und mehrere interne Displays zu verbinden, wenn dies vom Betriebssystem unterstützt wird.

Aktuelle Änderungen der POST-Adapter-Richtlinie

Das Betriebssystem hatte zuvor einige Richtlinien für den POST-Adapter. Beispielsweise war der POST-Adapter der einzige Adapter, der interne Ziele offenlegen konnte. Diese Arten von Einschränkungen werden mit der Einführung von ADS aus dem Betriebssystem entfernt.

Visuelle Effekte bei der Monitorankunft deaktivieren

Wenn in Windows 11 ein Monitor angeschlossen wird, hat die Shell/DWM eine Animationssequenz. Diese Animation ist in Anzeigeschalterszenarien deaktiviert.

PnP-Bonk deaktivieren

Wenn ein Monitor hinzugefügt oder entfernt wird, gibt das PnP-System einen "Bonk"-Sound wieder, um den Benutzer zu benachrichtigen. Dieser "Bonk" wird in Szenarien mit Bildschirmwechsel deaktiviert.

App-Benachrichtigungen

Wenn ein Bildschirm umgeschaltet wird, durchläuft das System die regulären Code-Pfade für das Entfernen von HPD und die Ankunft von HPD. Daher werden alle normalen Anwendungsbenachrichtigungen wie gewohnt ausgelöst, z.B. die PnP-Benachrichtigung für das HPD-Aus und das HPD-Ein und die WM_DISPLAYCHANGE-Fenstermeldungen.

API zum Auslösen des Switches

Der Plan besteht darin, über eine öffentliche API zu verfügen, damit das Betriebssystem und die IHV-Systemsteuerung den Switch auslösen können.

Da das interne Panel immer nur mit einer einzigen GPU verbunden ist, funktionieren die Bildschirm-APIs und die Win+P-Funktionalität wie erwartet.

HLK test

Wenn ein GPU-Treiber oder eine ACPI-Firmware volle ADS-Unterstützung liefert, muss er die ADS HLK-Tests auf einem ADS-fähigen System bestehen.

GPU HPDing internes Panel, wenn der Mux von dieser GPU weggeschaltet wird

Das Betriebssystem löst einen Bug-Check aus, wenn ein internes Panel von einem Treiber als angeschlossen gemeldet wird, während der Mux aktuell von diesem Treiber weggewechselt ist.

AC/DC-Übergang

Bei der ersten Version der ADS Funktion speichert das Betriebssystem keine AC vs. DC Mux-Einstellung und löst keinen Mux-Wechsel bei einem AC <-> DC Übergang aus.

Stromversorgungsübergänge im System

Das Hauptproblem bei Stromversorgungsübergängen besteht darin, dass die Firmware den Status des Mux zurücksetzt (z.B. Ruhezustand) und der Mux bei der Wiederaufnahme der Stromversorgung nicht auf das Panel umgeschaltet wird, das er vor dem Stromversorgungsübergang war.

Der ursprüngliche Ansatz bestand darin, den Mux zurück auf die dGPU zurückzuschalten, nachdem sowohl die iGPU als auch die dGPU eingeschaltet wurden. Das Problem mit diesem Ansatz besteht darin, dass je nach unterschiedlichen asynchronen Ereignissen das Ergebnis möglicherweise mehrere Modusänderungen darstellt.

Der aktualisierte Ansatz zur Optimierung der Benutzererfahrung besteht darin, dass das System den Mux wieder auf das erwartete Ziel umstellt, während sowohl die iGPU als auch die dGPU einschlafen, wodurch mehrere Modusänderungen vermieden werden.

Sequenz des Stromversorgungsübergangs

Das folgende Beispiel beschreibt einen Stromversorgungsübergang in den Ruhezustand auf einem ADS-System.

  1. Das System ist mit einem an die dGPU angeschlossenen Mux konfiguriert.
  2. Das System wechselt in den Ruhezustand.
  3. Sowohl die iGPU als auch die dGPU werden auf D3-Leistung umgestellt.
  4. Das System schaltet sich aus.
  5. Der Benutzer aktiviert das System.
  6. Die Firmware konfiguriert den Mux auf die iGPU und die iGPU zeigt die Boot-Sequenz auf dem internen Bildschirm an.
  7. Dxgkrnl liest die letzte Mux-Konfiguration (in diesem Fall dGPU) und vergleicht sie mit der aktuellen Mux-Position über ACPI (in diesem Fall iGPU). Dxgkrnl ruft dann ACPI auf, um den Mux auf die dGPU umzuschalten.
  8. Dxgkrnl schaltet iGPU auf D0 um und ruft dann iGPU'sDxgkDdiDisplayMuxUpdateState auf, um den Treiber zu informieren, dass der Mux nicht mit ihm verbunden ist.
  9. Dxgkrnl setzt die dGPU auf D0 und ruft dann DxgkDdiDisplayMuxUpdateState der dGPU auf, um dem Treiber mitzuteilen, dass der Mux mit ihr verbunden ist.
  10. Dxgkrnl legt einen Modus auf der dGPU fest.

All In One-Systeme (AIO)

Jedes AIO-System, das ADS unterstützen möchte, muss das interne Panel als internen Zieltyp auf beiden GPUs anzeigen.

Mux ACPI Gerät

Der OEM ist dafür verantwortlich, das Mux-Gerät im ACPI-Namespace hinzuzufügen und die erforderlichen Methoden für den Betrieb des Mux bereitzustellen.

Der GPU-Treiber sollte niemals die ACPI-Methoden des Mux aufrufen, da sich das Mux-Gerät an einer beliebigen Stelle im ACPI-Baum befinden könnte. Es wird empfohlen, den Mux unter dem nächsten gemeinsamen Vorfahren der beiden GPUs zu platzieren.

Aktuelle Mux-Geräte unterstützen nur zwei Eingaben, und wir erwarten nicht, dass zukünftige Muxe mehr unterstützen, sodass das Design zwei Eingaben und eine einzelne Ausgabe für jeden Mux annehmen kann.

Der Mux Gerät kann niemals angehalten werden, während das System ausgeführt wird. Es ist ein ausgeblendetes Systemgerät.

Der Mux Gerät ACPI Methoden

Nur der Stack des Treibers für ein ACPI-Gerät kann ACPI-Methoden auf dem Gerät aufrufen und auswerten. Um Mux-Geräte-Methoden aufzurufen, um den Mux zu schalten, muss das Betriebssystem daher einen Treiber für das Mux-Gerät geladen haben. Aus diesem Grund stellt das Betriebssystem jetzt einen Bildschirm Mux-Treiber als Treiber für alle Bildschirm Switch Muxes zur Verfügung.

Ein Mux-Gerät muss über die folgenden Methoden verfügen:

  • _HID identifiziert das Mux-Gerät anhand der Hardware-ID. Wir haben 'MSFT0005' für den ACPI Bildschirm Mux reserviert.
  • DMQU (Display Mux Query) gibt den aktuellen Status des Mux zurück.
  • DMCF (Display Mux Configure) konfiguriert den Mux.

Methode _HID (Hardware ID)

Argumente:

Nichts

Rückgaben:

Eine ASCII-Zeichenfolge, die die Hardware-ID "MSFT0005" enthält.

Methode DMQU (Display Mux Query)

In einer zukünftigen Version werden wir voraussichtlich zusätzliche Informationen zur Abfrage hinzufügen. Um in Zukunft zusätzliche Abfragen zu aktivieren, wird Arg0 verwendet, um den Abfragetyp anzugeben. Wenn die DMQU-Methode einen Abfragetyp nicht versteht, sollte sie als nicht unterstützt fehlschlagen.

Argumente:

Arg0: Eine ganze Zahl, die den Abfragetyp angibt. In der folgenden Tabelle sind die Abfragetypwerte und deren Bedeutungen aufgeführt.

Abfrage Typ Wert Bedeutung
1 Aktuellen Switchstatus abfragen
2 Abfragen des Mux ADS-Unterstützungslevels
3 Abfragen des ersten GPU-Untergeordneten, mit dem der Mux verbunden ist
4 Abfragen des zweiten GPU-Untergeordneten, an den der Mux angeschlossen ist

Rückgaben:

Wenn die Methode den angegebenen Abfragetyp versteht, sollte sie die entsprechenden Daten zurückgeben, wie in der folgenden Tabelle beschrieben. Wenn die Methode den angegebenen Abfragetyp nicht versteht, sollte sie eine leere Zeichenfolge zurückgeben.

Wert des Abfragetypes Daten zurückgeben
1 ASCII-Zeichenfolge, die den ACPI-Namen des untergeordneten GPU-Geräts enthält, auf das der Mux aktuell geschaltet ist.
2 Ganzzahl, die den Grad der ADS-Unterstützung angibt. Weitere Informationen finden Sie in der nächsten Tabelle.
3 ASCII-Zeichenfolge, die den ACPI-Namen des ersten untergeordneten GPU-Geräts enthält, an das der Mux angeschlossen ist.
4 ASCII-Zeichenfolge, die den ACPI-Namen des zweiten untergeordneten GPU Geräts enthält, an das der Mux angeschlossen ist.

In der folgenden Tabelle sind die ADS-Unterstützungsebenenwerte und deren Bedeutungen aufgeführt, wenn der Abfragetyp 2 ist.

Zurückgegebene Daten Bedeutung
0 Keine Unterstützung
1 Entwicklungsunterstützung. Systeme können mit dieser Einstellung ausgeliefert werden, ohne die HLK-Tests zu bestehen, da ADS standardmäßig auf Kundensystemen deaktiviert wird.
2 Experimentelle Unterstützung. Systeme können mit dieser Einstellung ausgeliefert werden, ohne die HLK-Tests zu bestehen, da ADS standardmäßig auf Kundensystemen deaktiviert wird.
3 Vollständiger Support. ADS wird auf diesem System standardmäßig aktiviert, wenn es mit vollständig unterstützten Grafiktreibern gekoppelt ist. Das System muss ADS HLK-Tests bestehen, um ausgeliefert zu werden.

Methode DMCF (Display Mux Configure)

Argumente:

Arg0: ASCII-Name des ACPI GPU untergeordneten Geräts, auf das der Mux umschalten soll.

Rückgaben:

Der Integerwert 0 bedeutet Erfolg; ein Wert ungleich Null bedeutet einen Fehler. Der OEM kann den Wert ungleich Null für eine bessere Diagnose definieren.

GPU-Gerät ACPI-Methoden

Bevor ein Grafiktreiber für eine GPU gestartet wird, muss das System wissen, ob das mux ACPI device funktioniert und in welchem Zustand es sich befindet. Dazu muss der Treiber des ACPI Mux Geräts bereits gestartet sein. Das System verwendet die ACPI _DEP-Methode im ACPI-Namespace jeder GPU, um die Geräteverbindung zu garantieren.

Wenn eine GPU bereits über eine _DEP-Methode verfügt, sollte sie den ACPI-Namen des Mux-Geräts in die zurückgegebene Abhängigkeitsliste aufnehmen. Wenn die GPU noch nicht über eine _DEP Methode verfügt, sollte sie eine hinzufügen.

Damit die ACPI-Firmware die Abhängigkeit einer GPU vom Mux nur dann meldet, wenn das Betriebssystem ADS unterstützt, wird eine ACPI _OSI Abfrage hinzugefügt. Die ACPI-Firmware kann diese Abfrage verwenden, um nach ADS-Unterstützung zu suchen. Betriebssystem-Versionen, die ADS unterstützen, liefern die Unterstützung, indem sie true an den _OSI(“DisplayMux”) ACPI-Befehl zurückgeben.

GPU untergeordnete Geräte ACPI-Methoden

Für jedes Ziel, das mit einem Mux verbunden ist, stellt das ACPI-Gerät dieses untergeordneten Geräts eine ACPI-Methode bereit, die den ACPI-Namen des Mux-Geräts zurückgibt, mit dem es verbunden ist. Einzelheiten finden Sie unter Identifizieren Sie die Ziele, die ein Mux kontrolliert.

Methode DMID (Display Mux Identifier)

Argumente:

Nichts

Rückgaben:

ASCII-Zeichenfolge, die den ACPI-Namen des ACPI-Mux-Geräts enthält, mit dem dieser Ausgang verbunden ist

Beispiel

Im folgenden Beispiel wird veranschaulicht, wie ein System mit zwei GPUs (GPU0 und GPU1) und einem Mux im ACPI-Framework eingerichtet und verwaltet wird.

  • Der ACPI-Name des Mux-Geräts lautet "SB. MUX1'.

  • Für GPU0:

    • Der ACPI-Name von GPU0 lautet "SB. PCI0. GFX0'.
    • Er stellt das VidPn Ziel 0x40f04 dar, das einen DXGK_CHILD_DESCRIPTOR.AcpiUid Wert von 0x400 liefert.
    • Der Name des untergeordneten ACPI-Geräts, das dem mit dem Mux verbundenen Ziel entspricht, lautet 'SB.PCI0.GFX0.DD1F'.
    • Die ACPI-Methode _ADR unter 'SB.PCI0.GFX0.DD1F' gibt 0x400 zurück. Durch diesen Rückgabewert weiß das Betriebssystem, dass dieses ACPI-Gerät dem VidPn-Ziel 0x40f04 entspricht.
    • Die ACPI-Methode DMID unter 'SB.PCI0.GFX0.DD1F' gibt 'SB.MUX1' zurück.
  • Für GPU1:

    • Der ACPI-Name von GPU1 lautet "SB. PCI0. PEG0. PEGP'.
    • Sie stellt das VidPn Ziel 0x1103 dar, das einen DXGK_CHILD_DESCRIPTOR.AcpiUid Wert von 0x100 liefert.
    • Der Name des untergeordneten ACPI-Geräts, das dem mit dem Mux verbundenen Ziel entspricht, lautet 'SB.PCI0.PEG0.PEGP.EDP1'.
    • Die ACPI-Methode _ADR unter 'SB.PCI0.PEG0.PEGP.EDP1' gibt 0x100 zurück. Dieser Rückgabewert zeigt, wie das Betriebssystem erkennt, dass dieses ACPI-Gerät dem VidPn-Ziel 0x1103 entspricht.
    • Die ACPI-Methode DMID unter 'SB.PCI0.PEG0.PEGP.EDP1' gibt 'SB.MUX1' zurück.
  • Das Betriebssystem weiß, dass das Ziel von GPU0 0x40f04 und das Ziel von GPU1 0x1103 mit demselben Mux verbunden sind, der den ACPI-Namen 'SB.MUX1' trägt.

  • Wenn GPU1 aktuell mit dem Panel verbunden ist, kann das Betriebssystem den Mux auf GPU0 umschalten, indem es die DMCF-Methode unter 'SB.MUX1' aufruft und 'SB.PCI0.GFX0.DD1F' übergibt.

Der folgende ACPI-Computersprachencode ist für die relevanten Teile des Beispiels vorgesehen. Der Pseudocode für die Plattformlogik ist von <> umgeben.


DefinitionBlock
{
    Device (MUX1) // This is _SB_.MUX1
    {
        Name (_HID, "MSFT0007")  // _HID: Hardware ID

        Method (DMQU, 1, Serialized)  // DMQU: Display Mux Query
        {
            Switch (ToInteger(Arg0))
            {
                Case (1)
                {
                    If (<Mux is in error>)
                    {
                        Return ("")
                    }
                    If (<Mux switched to GPU0>)
                    {
                        Return ("_SB_.PCI0.GFX0.DD1F")
                    }
                    Else
                    {
                        Return ("_SB_.PCI0.PEG0.PEGP.EDP1")
                    }
                }
                Case (2) 
                {
                    Return (1)  // Mux only has developmental support
                }
                Case (3)
                {
                    If (<Mux is in error>)
                    {
                        Return ("")
                    }
                    Return ("_SB_.PCI0.GFX0.DD1F")
                }
                Case (4)
                {
                    If (<Mux is in error>)
                    {
                        Return ("")
                    }
                    Return ("_SB_.PCI0.PEG0.PEGP.EDP1")
                }

            }
            // Unknown type
            Return ("")
        }

        Method (DMCF, 1, Serialized)  // DMCF: Display Mux Configure
        {
            If (<Arg0 does not match either of the GPU children this mux is connected to>)
            {
                Return (1) // Failure, use 1 to indicate this particular failure
            }

            // Switch the mux

            If (<Mux switch was successful>)
            {
                Return (0) // Success
            }
            Else
            {
                Return (2) // Failure, use 2 to indicate this particular failure
            }
        }
    }

    Scope (_SB_.PCI0.GFX0) // ACPI Device for GPU0
    {
        Method (_DEP, 0, NotSerialized)  // _DEP: Dependency on Mux device
        {
            If (_OSI(“DisplayMux”))
            {
                Return (Package {"_SB_.MUX1"})
            }
            Else
            {
                Return (Package (0x00){})
            }
        }

        Device (DD1F) // SB.PCI0.GFX0.DD1F which is child of GPU that is connected to the Mux
        {
            Name (_ADR, 0x400)  // _ADR: Matches the AcpiUid driver reports for the target connected to mux
            Method (DMID, 0, NotSerialized)  // DMID: ACPI name of the mux this target is connected to
            {
                Return ("_SB_.MUX1")
            }
        }
    }

    Scope (_SB_.PCI0.PEG0.PEGP) // ACPI Device for GPU1
    {
        Method (_DEP, 0, NotSerialized)  // _DEP: Dependency on Mux device
        {
            If (_OSI(“DisplayMux”))
            {
                Return (Package {"_SB_.MUX1"})
            }
            Else
            {
                Return (Package (0x00){})
            }
        }

        Device (EDP1) // SB.PCI0.PEG0.PEGP.EDP1 which is child of GPU that is connected to the Mux
        {
            Name (_ADR, 0x100)  // _ADR: Matches the AcpiUid driver reports for the target connected to mux
            Method (DMID, 0, NotSerialized)  // DMID: ACPI name of the mux this target is connected to
            {
                Return ("_SB_.MUX1")
            }
        }
    }
}

API-Änderungen

Die ADS-Funktion fügt die folgenden öffentlichen API-Funktionen hinzu:

  1. Zählen Sie die Mux-Geräte im System auf.
  2. Abfragen von Informationen über den Mux, z.B. mit welchen Zielen er verbunden ist und auf welches Ziel er aktuell geschaltet ist.
  3. Triggern Sie einen Mux-Wechsel.
  4. Wie man erkennt, wenn der Mux umgeschaltet wurde.

Aufzählen Sie die Mux-Geräte im System

Anwendungen können allgemeine Plug-and-Play-APIs verwenden, um Geräteschnittstellen zu finden, die einen funktionierenden Bildschirm Mux darstellen. Benutzer-Modus-Komponenten können Windows.Devices.Enumeration.DeviceInformation verwenden. C# oder C++ können mit diesen APIs verwendet werden, um Mux-Geräte auflisten zu können.

// Display Mux device interface
// {93c33929-3180-46d3-8aab-008c84ad1e6e}
DEFINE_GUID(GUID_DEVINTERFACE_DISPLAYMUX, 0x93c33929, 0x3180, 0x46d3, 0x8a, 0xab, 0x00, 0x8c, 0x84, 0xad, 0x1e, 0x6e);

IDisplayMuxDevice interface

Die Schnittstelle IDisplayMuxDevice wird hinzugefügt, um das Mux Gerät zu repräsentieren.

Der folgende Code demonstriert, wie Sie mit Hilfe der Windows Runtime APIs Display Mux Geräte auflisten, ihren Status abfragen, das aktive Ziel des Bildschirms wechseln und auf Statusänderungen reagieren.

#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Devices.Enumeration.h>
#include <winrt/Windows.Foundation.Collections.h>
#include <winrt/Windows.Devices.Display.Core.h>

#include <string>
#include <sstream>
#include <iomanip>
#include <windows.h>

namespace winrt
{
using namespace winrt::Windows::Foundation;
using namespace winrt::Windows::Foundation::Collections;
using namespace winrt::Windows::Devices::Enumeration;
using namespace winrt::Windows::Devices::Display;
using namespace winrt::Windows::Devices::Display::Core;
} // namespace winrt

void SwitchDisplayMuxTarget()
{
    // PnP device interface search string for Mux device interface
    std::wstring muxDeviceSelector = L"System.Devices.InterfaceClassGuid:=\"{93c33929-3180-46d3-8aab-008c84ad1e6e}\" AND System.Devices.InterfaceEnabled:=System.StructuredQueryType.Boolean#True";

    // Execute the device interface query
    winrt::DeviceInformationCollection deviceInformations = winrt::DeviceInformation::FindAllAsync(muxDeviceSelector, nullptr).get();
    if (deviceInformations.Size() == 0)
    {
        printf("No DisplayMux devices\n");
        return;
    }
    printf("%ld display mux devices found\n\n", deviceInformations.Size());

    // Only one mux in first release but here is generic code for multiple
    for (unsigned int i = 0; i < deviceInformations.Size(); i++)
    {
        printf("Display Mux device %ld :\n", i);

        // Get the device interface so we can query the info
        winrt::DeviceInformation deviceInfo = deviceInformations.GetAt(i);

        // Get the device id
        std::wstring deviceId = deviceInfo.Id().c_str();
        printf("    Device ID string : %S \n", deviceId.c_str());

        // Create the DisplayMuxDevice object
        auto displayMuxDevice = winrt::DisplayMuxDevice::FromIdAsync(deviceId).get();
        if (!displayMuxDevice)
        {
            printf("Failed to create DisplayMuxDevice object");
            continue;
        }

        // Check if DisplayMux is active
        auto displayMuxActive = displayMuxDevice.IsActive();
        printf("    DisplayMux state : %s \n", displayMuxActive ? "Active" : "Inactive");
        if (!displayMuxActive)
        {
            continue;
        }

        // Register for call back when the state of the DisplayMux changes
        UINT changeCount = 0;
        auto token = displayMuxDevice.Changed([&changeCount](auto, auto Args) -> HRESULT {
            changeCount++;
            return S_OK;
        });

        // Find targets connected to the DisplayMux and the current target
        auto targetsList = displayMuxDevice.GetAvailableMuxTargets();
        winrt::DisplayTarget currentTarget = displayMuxDevice.CurrentTarget();

        // Switch the display mux to the other target
        // NOTE SetPreferredTarget() is a sync method so use .get() to wait for the operation to complete
        printf("\n");
        if (currentTarget == targetsList.GetAt(0))
        {
            printf("DisplayMux currently connected to first target\n");
            displayMuxDevice.SetPreferredTarget(targetsList.GetAt(1)).get();
            printf("Calling SetPreferredTarget to switch DisplayMux to second target\n");
        }
        else if (currentTarget == targetsList.GetAt(1))
        {
            printf("DisplayMux currently connected to second target\n");
            displayMuxDevice.SetPreferredTarget(targetsList.GetAt(0)).get();
            printf("Calling SetPreferredTarget to switch DisplayMux to first target\n");
        }
        else
        {
            printf("Could not find current target in target list\n");
        }

        // Now read the current position
        currentTarget = displayMuxDevice.CurrentTarget();
        targetsList = displayMuxDevice.GetAvailableMuxTargets();
        if (currentTarget == targetsList.GetAt(0))
        {
            printf("DisplayMux is now currently connected to first target\n");
        }
        else if (currentTarget == targetsList.GetAt(1))
        {
            printf("DisplayMux is now currently connected to second target\n");
        }
        else
        {
            printf("Could not find current target in target list\n");
        }

        // Now unregister for change callback and display the
        displayMuxDevice.Changed(token);
        printf("DisplayMux state change callback was called %ld times\n\n", changeCount);
    }
}

WDDM DDI-Änderungen für die automatische Umschaltung des Bildschirms

In diesem Abschnitt werden die Ergänzungen und Änderungen beschrieben, die an WDDM DDI vorgenommen wurden, um ADS zu unterstützen. Diese Änderungen sind ab Windows 11, Version 24H2 Update 2025.01D (WDDM 3.2) verfügbar.

Abfragen der KMD-Schnittstelle zur Unterstützung von ADS

Die DXGK_DISPLAYMUX_INTERFACE_2 Schnittstellenstruktur wurde hinzugefügt. Sie enthält die Anforderungen des Betriebssystems an den Treiber, die zur Unterstützung von ADS Version 2 erforderlich sind. Das Betriebssystem fragt beim Treiberstart nach der vom Treiber unterstützten ADS-Schnittstelle ab, wobei InterfaceType auf GUID_WDDM_INTERFACE_DISPLAYMUX_2 festgelegt ist.

(DXGK_DISPLAYMUX_INTERFACE enthält die Betriebssystem-zu-Treiber-Aufrufe, die zur Unterstützung der Version 1 der ADS Funktion erforderlich sind. Diese Version wurde während der Vorabversion von ADS verwendet.)

KMD-Funktionen zur Unterstützung von ADS

KMD implementiert die folgenden Funktionen zur Unterstützung von ADS. Dxgkrnl ruft die ADS-Funktionsschnittstelle von KMD durch einen Aufruf von KMDs DxgkddiQueryInterface ab.

Treiber liefert ADS-Funktionalität

Der Treiber liefert seinen Grad an ADS-Unterstützung, wenn das Betriebssystem sein DxgkDdiDisplayMuxGetDriverSupportLevel DDI aufruft. Wenn der Treiber die Schnittstelle DXGK_DISPLAYMUX_INTERFACE nicht implementiert, betrachtet das Betriebssystem den Unterstützungslevel als DXGK_DISPLAYMUX_SUUPORT_LEVEL_NONE.

Der Treiber sollte die ADS-Supportstufe melden, unabhängig davon, auf welchem System es ausgeführt wird. Der vom Treiber gelieferte Unterstützungsgrad sollte sich nur auf den Treiber beziehen. Der Treiber sollte keines der folgenden Kriterien berücksichtigen, wenn er seinen ADS-Unterstützungsgrad liefert:

  1. Der System-OEM.
  2. Jede andere GPU im System.
  3. Das Vorhandensein oder Nichtvorhandensein des ACPI Mux Geräts.
  4. Das Vorhandensein oder Nichtvorhandensein der ACPI-Einträge unter dem ACPI-Knoten der GPU.

Update für Reporting Ziele beim Start des Adapters

Wenn der Adapter startet, liefert er alle seine untergeordneten Geräte über die DxgkDdiQueryChildRelations DDI. Das Reporting umfasst alle internen Ziele, die mit einem Mux verbunden sind. Ein internes Ziel enthält das Feld DXGK_CHILD_CAPABILITIES.Type.IntegratedDisplayChild.DescriptorLength.

Ein Problem tritt auf, wenn der Mux beim Start des Adapters auf die andere GPU umgeschaltet wird. In dieser Situation kann der Treiber nicht mit dem internen Panel kommunizieren, um die EDID/DisplayId-Größe abzufragen. Daher muss ein Treiber, der die Schnittstelle GUID_WDDM_INTERFACE_DISPLAYMUX_2 zur Verfügung stellt, DXGK_CHILD_CAPABILITIES.Type.IntegratedDisplayChild.DescriptorLength beim Start des Adapters auf Null festlegen, wenn der Mux aktuell nicht auf die GPU des Treibers geschaltet ist. Andernfalls schlägt das Betriebssystem den Adapterstart fehl.

Der Mux aktualisiert seine internen Informationen über die Größe des internen Deskriptors bei der ersten Operation des Mux-Wechsels.

Update bei Verbindungswechsel

Wie bereits erwähnt, gibt es eine ADS-spezifische Möglichkeit, den internen Status des Panels während einer automatischen Sequenz zum Umschalten des Bildschirms zu melden. Um anzuzeigen, dass ein Paket zur Verbindungsänderung Teil einer ADS-Schaltsequenz ist, wird das Flag DisplayMuxConnectionChange zu DXGK_CONNECTION_MONITOR_CONNECT_FLAGS hinzugefügt. Wenn DisplayMuxConnectionChange festgelegt ist, zeigt es an, dass der MonitorStatusConnected oder MonitorStatusDisconnectedVerbindungsstatus mit einem automatischen Bildschirmwechsel zusammenhängt.

DisplayMuxConnectionChange sollte nur während eines ADS-Wechsels und nicht für andere Zwecke verwendet werden. Er sollte in den folgenden ADS-Fällen verwendet werden:

  • Während der Treiber DxgkDdiDisplayMuxPreSwitchAway verarbeitet.

    Wenn das interne Panel verbunden ist, sollte der Treiber ein DXGK_CONNECTION_CHANGE Paket zu seiner Verbindungsänderungsliste hinzufügen, wobei DXGK_CONNECTION_CHANGE.ConnectionStatus auf MonitorStatusDisconnected und DXGK_CONNECTION_CHANGE.MonitorConnect.MonitorConnectFlags.DisplayMuxConnectionChange auf 1 festgelegt wird. Diese Einstellungen geben dem Betriebssystem an, dass der Treiber die Steuerung des internen Panels freigegeben hat.

  • Während der Treiber DxgkDdiDisplayMuxPostSwitchToPhase1 verarbeitet.

    • Der Fahrer sollte zuerst ermitteln, ob das interne Panel angeschlossen ist.
    • Wenn das Panel verbunden ist, sollte der Treiber ein DXGK_CONNECTION_CHANGE-Paket zu seiner Verbindungsänderungsliste hinzufügen, wobei DXGK_CONNECTION_CHANGE.ConnectionStatus auf MonitorStatusConnected und DXGK_CONNECTION_CHANGE.MonitorConnect.MonitorConnectFlags.DisplayMuxConnectionChange auf 1 festgelegt wird.
    • Wenn das Panel nicht verbunden ist, sollte der Treiber ein DXGK_CONNECTION_CHANGE Paket zu seiner Verbindungsänderungsliste hinzufügen, wobei DXGK_CONNECTION_CHANGE.ConnectionStatus auf MonitorStatusDisconnected und DXGK_CONNECTION_CHANGE.MonitorConnect.MonitorConnectFlags.DisplayMuxConnectionChange auf 1 festgelegt ist.
  • Während der Treiber DxgkDdiDisplayMuxSwitchCancled verarbeitet.

  • *Für den Fall, dass während eines Switches eine Anfrage zum Ziel eingeht, sollte DisplayMuxConnectionChange nur für Verbindungsänderungspakete festgelegt werden, die von DxgkDdiDisplayMuxPreSwitchAway, DxgkDdiDisplayMuxPostSwitchToPhase1 oder DxgkDdiDisplayMuxSwitchCanceled hinzugefügt werden.

Aktualisierte Anleitung für DxgkDdiSystemDisplayEnable

Wenn der DDI-Aufruf DxgkDdiSystemDisplayEnable(/windows-hardware/drivers/ddi/dispmprt/nc-dispmprt-dxgkddi_system_display_enable) eines ADS-Treibers aufgerufen wird, muss der Treiber sicherstellen, dass PSR am Ende seines DxgkDdiSystemDisplayEnable DDI-Aufrufs deaktiviert ist.

OEM-Anleitung

Es gibt mehrere Aspekte der ADS Funktion, die unterhalb der Ebene liegen, die das Betriebssystem in der Plattform kontrolliert. Es ist wichtig, dass OEMs sicherstellen, dass sie ordnungsgemäß funktioniert. In der folgenden Liste sind einige der wichtigsten Punkte zusammengefasst, die OEMs berücksichtigen müssen:

  • Sowohl der hybride integrierte als auch der hybride diskrete Treiber müssen ADS unterstützen.
  • Der Mux, der für die Plattform ausgewählt wurde, kann über ACPI gesteuert werden.
  • Die Methoden _HID, DMQU und DMCF unter dem Mux Gerät und den GPU untergeordneten ACPI Geräten für die internen Ziele sind implementiert und verfügen über die DMID ACPI Methode.
  • Die ACPI-Geräte beider GPUs müssen _DEP haben, um ihre Abhängigkeit vom Mux ACPI-Gerät zu kennzeichnen.
  • Die Helligkeits-Schnittstellen/Caps/Bereiche, die von beiden GPUs angezeigt werden, stimmen genau überein.
  • Wie im Abschnitt Helligkeitsdaten beschrieben, wird die Brightness v3-Schnittstelle gegenüber der Brightness V2-Schnittstelle dringend empfohlen.
  • Wenn ein Monitor-Panel-Treiber verwendet wird, sollte der Code GPU-unabhängig sein, d.h. die gleiche Logik kann verwendet werden, wenn eine der beiden GPUs das Panel steuert.
  • Zumindest bei einem internen Mux sollte das Umschalten des Muxes kein HPD Ereignis generieren.
  • Wenn der OEM den Mux in einem System deaktivieren möchte, sollte die DMQU ACPI-Methode 0 zurückgeben, wenn sie mit Arg0 auf 2 festgelegt ist.
  • Der Mux muss zwischen GPUs wechseln können, auch wenn sich die Treiber in geringer Leistung befinden. In diesem Fall wird PSR nicht verwendet.
  • Wenn der Mux von einer GPU auf eine andere umschaltet, sollte die Helligkeit des Panels ohne Helligkeitsschwankungen beibehalten werden. Es gibt mehrere Möglichkeiten, dies zu tun, einschließlich der folgenden Möglichkeiten. Der OEM ist dafür verantwortlich, sicherzustellen, dass das System die Helligkeit über Schalter hinweg beibehält.
    • Verwenden Sie eine DisplayPort Aux Nits basierte Helligkeitssteuerung.
    • Verwenden Sie einen Tcon mit PWM-Rekonstruktion, um Helligkeitsschwankungen zu vermeiden.
  • Das Panel und der verwendete Tcon können im Self-Refresh-Modus bleiben (PSR1 für eDP), wenn die Pre-Switch- und Post-Switch-Link-Konfiguration durch die EDID offengelegt und sowohl von der iGPU als auch der dGPU unterstützt wird. Dies umfasst, ist jedoch nicht auf Folgendes beschränkt:
    • Aktualisierungsrate
    • Aktive Größe
    • Anzahl der verwendeten eDP-Lanes und Lane-Bandbreite
    • eDP DSC-Einstellung
    • verwendete eDP VSC SDP-Version
    • PSR-Version und Funktionen für Nicht-Switch-Szenarien