Compartir a través de


Conmutador automático de pantalla

Importante

Parte de la información hace referencia a un producto de versión preliminar que puede sufrir importantes modificaciones antes de que se publique la versión comercial. Microsoft no proporciona ninguna garantía, expresa o implícita, con respecto a la información proporcionada aquí.

En este artículo se describe la función de conmutador automático de pantalla (ADS), que permite cambiar sin problemas el panel interno de un portátil entre una GPU integrada (iGPU) y una GPU discreta (dGPU). ADS es una característica opcional de WDDM, compatible a partir de Windows 11, versión 24H2 actualización 2025.01D (WDDM 3.2).

En este artículo:

  • GPU0 se refiere a la GPU a la que está conectado actualmente el panel integrado.
  • GPU1 se refiere a la GPU a la que se va a cambiar el panel.

Información general

Algunos portátiles lanzados tienen un dispositivo multiplexor (mux) que permite conmutar el panel interno entre la GPU integrada (iGPU) y la GPU discreta (dGPU). En la actualidad, el controlador de gráficos activa y ejecuta el cambio en estos portátiles sin que el sistema operativo tenga conocimiento de ello, lo que provoca algunas experiencias de usuario no deseadas.

ADS permite que el sistema operativo controle el uso de un dispositivo MUX en el sistema para cambiar entre la iGPU y dGPU al escanear hacia el panel interno. Por tanto, el sistema operativo puede proporcionar una mejor experiencia de usuario.

La versión inicial de ADS solo admite la Conmutador del panel interno entre la iGPU y la dGPU. En el futuro, esta función podría ampliarse para soportar también la Conmutador de conectores externos en portátiles.

Diseño de alto nivel

En general, el sistema tiene que asegurarse de que el contenido del panel interno se muestre sin parpadeos o problemas mientras se está realizando la conmutación. El sistema operativo no restringe esta funcionalidad a ningún protocolo de visualización en particular. Este artículo se centra en cómo implementar ADS con eDP, pero hay más estándares de la industria que se pueden utilizar (por ejemplo, MIPI o DSI). Un diseño de plataforma puede usar otro protocolo de conexión de pantalla si puede lograr la misma calidad de experiencia sin ningún cambio adicional en el sistema operativo.

Las subsecciones de esta sección identifican los aspectos de diseño de la función y detallan el enfoque de alto nivel para cada aspecto.

Control del dispositivo mux

Para reducir las dependencias entre los controladores de gráficos iGPU y dGPU, el multiplexor se expone como un dispositivo independiente que el sistema operativo puede controlar sin depender de los controladores de gráficos. Las ventajas de este enfoque son:

  1. Reduce la complejidad del controlador gráfico, ya que este no necesita saber cómo controlar cada mux diferente que un OEM pueda utilizar.
  2. Reduce o elimina las dependencias entre controladores gráficos, lo que reduce las actualizaciones de controladores y facilita a los OEM la selección de GPU y muxes.
  3. El sistema operativo puede cambiar el multiplexor cuando no hay un controlador de gráficos disponible.

Exposición del dispositivo MUX

Dado que esta solución es para la multiplexación entre la iGPU interna y la dGPU, tiene sentido exponer el conmutador a través de ACPI.

Funcionalidad del controlador mux

El controlador mux debe cumplir los siguientes requisitos funcionales de alto nivel:

  1. Debe proporcionar el estado del multiplexor, indicar qué destino está controlando actualmente el panel interno, y cualquier límite de capacidades.
  2. Debe proporcionar una forma de activar un conmutador e informar del estado del conmutador.

Para obtener más información sobre el dispositivo mux ACPI y sus métodos, consulte ACPI.

Para realizar una Conmutador sin interrupciones, el dispositivo mux requiere las siguientes condiciones en todo momento durante la Conmutador de la GPU:

  1. Alimentación del panel. En cualquier momento, el mux necesita que la energía del panel sea suministrada por cualquiera de las GPU. Es aceptable que ambas GPU proporcionen la alimentación del panel al mismo tiempo.
  2. Señales de control habilitadas por brillo desde ambas GPU al alternar.
  3. Nivel de brillo (modulado por ancho de pulso) de ambas GPU al alternar.

El mux conmuta la siguiente información entre las dos GPUs y el panel:

  1. Señal de control con capacidad de brillo
  2. Nivel de brillo (modulación por ancho de pulso)
  3. Línea auxiliar de DisplayPort (DP)
  4. Línea de detección de conexión frecuente (HPD)
  5. Línea de datos DP

El multiplexor debe poder cambiar cuando el panel no está activo. Para al menos el cambio de panel interno, el MUX no debería activar ninguna señal HPD a la GPU durante el cambio.

El controlador de la GPU nunca debe llamar a los métodos ACPI de MUX.

Conmutador automático de pantalla DDI

Se añaden varios DDIs para cumplir con los requisitos del mux. Durante un cambio de multiplexor, hay cinco puntos diferentes en los que el sistema operativo invoca las DDIs de un controlador utilizando las siguientes funciones. Las distintas llamadas dependen de la etapa del conmutador y de si el controlador está controlando la GPU que actualmente tiene el control de la pantalla.

DDI Descripción
DxgkDdiDisplayMuxPreSwitchAway Llamada al controlador actualmente conectado a la pantalla. Esta llamada informa al controlador de que el sistema planea cambiar la pantalla a otra GPU (de GPU0 a GPU1).
DxgkDdiDisplayMuxPreSwitchAwayGetPrivateData Llame para recopilar los datos del conmutador privado del controlador conectado actualmente al panel (de la GPU0).
DxgkDdiDisplayMuxPreSwitchTo Llamada al controlador actualmente no conectado a la pantalla. Esta llamada informa al controlador que el sistema operativo está planeando cambiar la pantalla a esta GPU (a GPU1).
DxgkDdiDisplayMuxSwitchCanceled Llame al controlador para indicar que la secuencia del conmutador se canceló antes de que se completara el conmutador.
DxgkDdiDisplayMuxPostSwitchAway El conmutador mux se ha completado y el driver de la GPU0 ya no está conectado a la pantalla.
DxgkDdiDisplayMuxPostSwitchToPhase1 El conmutador mux se ha completado y el driver de GPU1 está ahora conectado a la pantalla. Este controlador debería realizar ahora las tareas de la fase 1.
DxgkDdiDisplayMuxPostSwitchToPhase2 El conmutador mux se ha completado y el controlador de la GPU1 está ahora conectado a la pantalla. Este controlador debería realizar ahora las tareas de la fase 2.
DxgkDdiDisplayMuxUpdateState Se llama al inicio del adaptador y vuelve al estado de alimentación D0 para que el controlador conozca el estado de MUX actual.

Hay acciones explícitas que el controlador necesita completar en cada etapa. Estas acciones se describen más adelante en este artículo.

Para obtener una lista completa de las actualizaciones DDI relacionadas con ADS, consulte Cambios de DDI de WDDM para el Cambio automático de pantalla

Compartir datos entre GPU0 y GPU1

Puede haber casos en los que una mejor experiencia de usuario se puede construir cuando:

  • GPU0 y GPU1 son del mismo IHV.
  • La GPU0 puede pasar información a la GPU1 sobre la configuración de la pantalla que es opaca al SO.

Un blob de datos se describe mediante un GUID que el driver de GPU1 puede identificar rápidamente si entiende el blob de datos. A nivel general, el sistema operativo llama a GPU0 para obtener el GUID del blob y los datos antes del cambio y los pasa a GPU1 antes de que se le pida HPD en la pantalla.

El controlador de GPU1 es responsable de:

  • Comprobar que comprende el GUID del blob.
  • Validar cada elemento de datos del blob para evitar efectos perjudiciales de los datos mal formateados en el blob.

Interoperabilidad de controladores

Si un controlador WDDM es compatible con ADS, debe serlo con independencia del sistema OEM en el que se ejecute o de cuál sea la otra GPU del sistema.

La secuencia del cambio

Aunque podría ser técnicamente posible cambiar de una GPU cuando el controlador de esa GPU se detiene, este escenario no está soportado actualmente. Por lo tanto, el cambio solo se realiza cuando ambas GPU tienen controladores cargados que soportan la interfaz de dispositivo de conmutación (DDI).

La siguiente secuencia es una vista de alto nivel de toda la secuencia de Conmutador cuando el panel está activo, donde GPU0 y GPU1 representan la iGPU y la dGPU, respectivamente. GPU0 está actualmente conectado al panel interno a través del multiplexor y queremos cambiar para que GPU1 envíe la señal al panel.

  1. Se realiza una llamada de conmutación a nivel de API.
  2. El SO recopila atributos del estado interno actual del panel (HDR, modo, frecuencia de actualización, etc.) y comprueba el modo de visualización temporal.
  3. El sistema operativo deshabilita la realización de cualquier topología de visualización debido a los HPD de cualquier GPU del sistema.
  4. El sistema operativo llama a DxgkDdiDisplayMuxPreSwitchTo del controlador de GPU1 y pasa el nivel de brillo actual. El controlador debe hacer lo siguiente solo si la tapa está abierta:
    • Encienda el panel.
    • Establecer la señal de brillo habilitada.
    • Establecer el nivel de brillo que pasó el sistema operativo.
  5. El sistema operativo deshabilita la llamada a DxgkDdiQueryConnectionChange en GPU0 para asegurarse de que el estado de HPD de la tapa no se pueda procesar hasta después del cambio del conmutador MUX.
  6. El sistema operativo llama a la DDI DxgkDdiDisplayMuxPreSwitchAway del controlador de GPU0. El conductor debe:
    • Si la tapa está activa, habilite PSR1 (actualización automática del panel 1) en el panel y asegúrese de que no se deshabilite hasta que el sistema operativo solicite su desactivación más adelante en la secuencia.
    • Agregar un paquete a su lista de modificaciones de conexión con ConnectionStatus de DXGK_CONNECTION_CHANGE establecido en MonitorStatusDisconnected y MonitorConnect.MonitorConnectFlags.DisplayMuxConnectionChange establecido en 1.
    • GPU0 no puede agregar ningún paquete de cambios de conexión para el destino de tapa a su cola. El sistema operativo verifica el fallo si este ocurre.
    • Devuelve el tamaño de cualquier blob de datos ADS privado (GUID y datos) al SO. Si se produce un error en el controlador GPU0 en esta llamada, debe asegurarse de que los paquetes de estado de conexión ADS que haya colocado en la cola se eliminen antes de devolver el control.
  7. Si el controlador de GPU0 devolvió un tamaño de datos privado distinto de cero, el sistema operativo asigna ese tamaño y lo pasa a la devolución de llamada DxgkDdiDisplayMuxPreSwitchAwayGetPrivateData para obtener los datos del conmutador privado.
  8. El SO llama al método ACPI del mux para cambiar de GPU0 a GPU1.
  9. El sistema operativo permite que se vuelva a llamar a DxgkDdiQueryConnectionChange de la GPU.
  10. El sistema operativo llama a DxgkDdiQueryConnectionChanges de la GPU0 para procesar el paquete de conexión MonitorStatusDisconnected con DisplayMuxConnectionChange establecido en 1.
  11. El sistema operativo llama a DxgkddiSettimingsfromvidpn de GPU0 para desactivar la ruta de acceso de la pantalla desde la que se va a cambiar. El controlador de la GPU0 debe:
    • Apagar el panel.
    • Desactivar la señal de brillo.
    • Dejar de enviar el nivel de brillo a MUX.
  12. El sistema operativo procesa la salida de pantalla. No desencadena un cambio de topología para evitar cambios de topología innecesarios.
  13. El sistema operativo llama a la devolución de llamada DxgkDdiDisplayMuxPostSwitchToPhase1 de la GPU1 y pasa cualquier blob privado de ADS obtenido de la GPU0. El conductor debe:
    • Determinar si la tapa está abierta o cerrada.
    • Añadir el paquete a su lista de cambios de conexión con DXGK_CONNECTION_CHANGE:
      • MonitorConnect.MonitorConnectFlags.DisplayMuxConnectionChange bit configurado.
      • ConnectionStatus establecido en MonitorStatusConnected si la tapa está abierta o MonitorStatusDisconnected si la tapa está cerrada.
    • Si la tapa está cerrada, apagar la alimentación y habilitar la señal de brillo para el panel.
  14. Si el sistema operativo aún no ha llamado a DxgkDdiQueryAdapterInfo con DXGKQAITYPE_INTEGRATED_DISPLAY_DESCRIPTOR2 para el destino interno de GPU1, lo hace. Como resultado de esta llamada, el SO llama también a DxgkDdiQueryDeviceDescriptor.
  15. El sistema operativo llama a DxgkDdiQueryConnectionChange de la GPU1 para procesar el evento en su lista de cambios de conexión. Esta llamada da como resultado que se invoque DxgkDdiQueryDeviceDescriptor para el nuevo monitor que se está conectando mediante HPD.
  16. El sistema operativo permite cambios en la topología de visualización debido a los HPD.
  17. El SO procesará asíncronamente los paquetes de conexión de GPU0 y GPU1 con DisplayMuxConnectionChange a 1.
  18. Si la GPU1 pone en cola MonitorStatusConnected:
    • El SO llama a las funciones DWM de GPU1 para enumerar los modos.
    • DxgkddiSettimingsfromvidpn se llama en la GPU1 para activar la ruta de acceso de pantalla.
    • DWM renderiza y presenta el fotograma en la ruta de visualización en GPU1.
    • El SO espera a que el primer frame se haga visible.
  19. El sistema operativo llama a la devolución de llamada DxgkDdiDisplayMuxPostSwitchToPhase2 de la GPU1, donde el controlador debe desactivar PSR1 para la pantalla si MonitorStatusConnected se ha puesto en cola por la GPU1, de lo contrario, no debería hacer nada.
  20. El sistema operativo llama a DxgkDdiDisplayMuxPreSwitchAway de la GPU0. Aunque no hay acciones esperadas del controlador, esta llamada es útil para cualquier limpieza de controladores o contabilidad relacionada con el cambio.
  21. El SO recoge los atributos del estado interno actual del panel. Si el estado del panel difiere del guardado previamente, el SO activa la telemetría.

Esta secuencia de Conmutador es la misma para iGPU->dGPU y dGPU->iGPU. Puede haber casos para cambiar el mux cuando el panel está inactivo. En ese caso, esta secuencia no es necesaria y el SO puede simplemente llamar a métodos ACPI en el mux para conmutar.

La mayor parte del SO no sabe que el driver está en modo PSR. Como resultado, el controlador sigue necesitando generar sincronizaciones Vsync, notificar los reportar los volteos como completados, etc., aunque el usuario no vea que esto sucede.

Proceso de recuperación

Si se produce un error durante cualquier fase de la secuencia de conmutación, se lleva a cabo la siguiente limpieza:

  1. El sistema operativo llama a DxgkDdiDisplayMuxSwitchCanceled de la GPU0 si se llamó correctamente a DxgkDdiDisplayMuxPreSwitchAway de la GPU0, pero no se ha llamado a suDxgkDdiDisplayMuxPostSwitchAway.
  2. El sistema operativo llama a DxgkDdiDisplayMuxSwitchCanceled de la GPU1 si se llamó correctamente a DxgkDdiDisplayMuxPreSwitchTo de la GPU1, pero no se ha llamado a su DxgkDdiDisplayMuxPostSwitchToPhase2
  3. El SO vuelve a habilitar los cambios de topología de pantalla si están deshabilitados.
  4. El sistema operativo vuelve a habilitar la llamada a DxgkDdiQueryConnectionChange en la GPU0 si estaba deshabilitada.
  5. El SO sondea la conectividad de la tapa en la GPU a la que está conectada la tapa.
  6. El sistema operativo inicia un reinicio de la configuración de pantalla (SDC). El controlador que tiene el panel conectado a través de MUX (devuelto desde DxgkDdiDisplayMuxSwitchCanceled) debe asegurarse de que PSR está deshabilitado.

Eventos inusuales que pueden ocurrir durante el cambio

  • El usuario conecta o desconecta un monitor.

    Como parte de la secuencia de conmutación, deshabilitamos el procesamiento del sistema operativo de los eventos HPD. De este modo, cualquier HPD se pone en cola y se procesa junto con la llegada de la tapa en una operación atómica.

  • Otra aplicación llama a SDC durante el cambio

    Mientras el cambio está en proceso, las llamadas a SDC se bloquean y se ejecutarán después de procesar el cambio.

  • El controlador se deshabilita durante el cambio

    Cuando se detiene un controlador, se producen errores en las llamadas de la secuencia de conmutadores y se activa la secuencia de recuperación. La sección PnPStop también detalla cómo se asegura de que la pantalla esté siempre visible.

Escenarios de cierre de tapa

El controlador generalmente podría utilizar cualquiera de los siguientes enfoques para detectar eventos de apertura/cierre de tapa:

Sin embargo, para WDDM en general, los controladores deben usar el enfoque de DxgkDdiNotifyAcpiEvent porque permite que Dxgkrnl y el estado del controlador estén sincronizados. Dado que tanto iGPU como dGPU pueden ser la GPU1 en una secuencia de conmutadores, tiene sentido que todos los controladores ADS supervisen el estado de la tapa incluso cuando se cambia fuera de ella.

Una vez que el sistema operativo procesa el evento DisplayMuxConnectionChange de GPU0, considera que GPU0 ya no controla el estado de la tapa y, por tanto, GPU0 no puede notificar más paquetes de estado de conexión para ese destino hasta que se vuelva a cambiar la tapa. Si la GPU0 lo hace, el sistema operativo realizará una comprobación de errores. Una vez que el sistema operativo procesa DisplayMuxConnectionChange desde la GPU1, considera que la GPU1 es la responsable del estado de la tapa. Se puede omitir cualquier evento de apertura o cierre de tapa entre esos dos eventos, ya que se espera que la GPU1 conozca el estado de la tapa e informe del paquete DisplayMuxConnectionChange correcto.

Cuando el SO considera que el controlador es el propietario del panel

La siguiente tabla describe las etapas de secuencia en las que el SO considera que una GPU es propietaria del panel. La GPU propietaria puede reportar cambios conectivos usando la secuencia de Conmutador. Los números de paso proceden de la secuencia de cambios descrita anteriormente.

De etapa A etapa Qué GPU controla el panel
Antes de cambiar Paso 5 GPU0
Paso 6 Paso 12 Sin GPU
Paso 13 Después de cambiar GPU1

El sistema operativo realiza una comprobación de errores si ve un paquete de cambios de conexión en la cola del controlador para un objetivo multiplexado cuando el panel no está bajo el control de la GPU.

Control del actualización automática del panel (PSR)

La función ADS utiliza PSR para evitar fallos durante la transición. En concreto, se utiliza PSR1 (modo de actualización a pantalla completa) para que GPU0 y GPU1 no tengan que negociar qué modo de PSR utilizar.

Incluso dentro de PSR1, hay características opcionales que el panel debería admitir.

Capacidad de recepción Detalles Receptor expuesto mediante
Versión de DPCD y eDP Se expone eDP v1.3 o superior. DPCD
Capacidad y versión de PSR El receptor admitirá la versión 1. DPCD 00070h bit 7:0
Compatibilidad con VSC SDP para transmitir el estado de PSR Solo para PSR; el receptor admitirá al menos la revisión 2 con hasta 8 bytes válidos para transmitir el estado de PSR y el valor de CRC. DPCD 170
El receptor deberá notificar correctamente el estado relacionado con PSR. El receptor expondrá el estado; por ejemplo, el error de CRC del enlace, el error de almacenamiento RFB, el estado de actualización automática del dispositivo receptor, el número máximo de marcos de resincronización, la última latencia de sincronización real en el receptor y el último SDP de PSR recibido. DPCD 2008h, 2009h, 200Ah reflejarán el estado correcto del receptor.

Cuando GPU1 realiza el entrenamiento de enlace como parte de una llamada DxgkddiSettimingsfromvidpn desde el sistema operativo, el controlador no conoce la configuración de ancho de banda y de los carriles DP usada por GPU0, por lo que tiene que realizar una secuencia de entrenamiento de enlace completa en lugar de un entrenamiento rápido de enlace. El SO no va a negociar ninguna política de PSR entre las GPUs, por lo que el panel necesita soportar todas las versiones y características de PSR que las GPUs vayan a utilizar. Por ejemplo, el panel tiene que soportar un escenario en el que la GPU0 podría utilizar PSR2 con algunas características establecidas, a continuación, PSR1 se utilizará para el conmutador, a continuación, la GPU1 podría utilizar PSR2 con un conjunto diferente de características.

Asegurar que el panel permanece en PSR durante el cambio

Cuando la GPU1 establece un modo en el panel, no hay ninguna garantía de que los atributos de vínculo establecidos por la GPU1 mientras el panel esté en PSR coincidirán con el modo de entrada de PSR. Por ejemplo, la frecuencia de actualización o el tamaño activo podrían cambiar. En la actualidad, DP u otros estándares del sector no tienen forma de que el panel informe de que puede mantener el panel en PSR mientras se cambian los atributos de vínculo. A largo plazo, queremos trabajar para añadir esta capacidad a la especificación DP. Hasta ese momento, para un sistema habilitado para ADS, el OEM tiene que elegir una combinación TCon/panel/Mux que pueda permanecer en PSR mientras que los atributos de vínculo (por ejemplo, frecuencia de actualización, tamaño de activo) cambian entre dos combinaciones expuestas en el EDID. Este enfoque garantiza que PSR se pueda mantener activo durante la transición.

Para que la prueba de ADS HLK compruebe que PSR se mantiene durante el proceso de cambio, nos gustaría que el sistema operativo sepa si el PSR no estaba activo después de que GPU1 pruebe el modo. Un desafío es que no se define cómo reaccionará un panel si no puede admitir PSR durante el entrenamiento del enlace.

Como parte de DxgkDdiDisplayMuxPostSwitchToPhase2, el controlador devuelve un valor booleano en pWasPanelInPSR para informar al sistema operativo si detectó que el panel no estaba en PSR.

EDID del panel interno

Para que el sistema operativo proporcione el comportamiento esperado al seleccionar modos de visualización y topologías con diferentes monitores conectados, se requiere que ambas GPU informen del EDID/DisplayId de la pantalla interna. Este requisito garantiza que la base de datos CCD que almacena los modos de visualización y las topologías seleccionará la misma configuración independientemente de la GPU que controle la pantalla interna.

El EDID que los controladores informan al sistema operativo, debe ser el EDID que se consulta desde el panel mediante el comando aux sin ninguna modificación.

Actualmente, el sistema operativo llamará a DxgkDdiQueryAdapterInfo(DXGKQAITYPE_INTEGRATED_DISPLAY_DESCRIPTOR2) al iniciar un controlador que informe de un panel interno. Si el mux se desvía de ese objetivo integrado, el controlador no puede comunicarse con el panel para recopilar la información necesaria. La solución es que cuando se inicia un controlador y MUX se aleja de su destino interno, el sistema operativo retrasa la llamada a DxgkDdiQueryAdapterInfo(DXGKQAITYPE_INTEGRATED_DISPLAY_DESCRIPTOR2) hasta que el MUX se cambie por primera vez al destino interno.

Cómo decide el sistema operativo si la función ADS está habilitada en un sistema y se permite el cambio

El sistema operativo realiza la siguiente lista de comprobaciones para determinar si ADS está disponible en un sistema. Todas las comprobaciones deben ser verdaderas para que ADS sea compatible.

  1. Hay una GPU marcada como integrada híbrida (DXGK_DRIVERCAPS.HybridIntegrated) que:
  2. Hay una GPU marcada como híbrida discreta (DXGK_DRIVERCAPS. HybridDiscrete) que:
  3. El nombre de la ACPI de MUX devuelto del método DMID ACPI en los pasos 1 y 2 coincide.
  4. El dispositivo ACPI mux tiene métodos ACPI DMQU, DMCF y DMSL.
  5. El método DMQU de ACPI de MUX devolvió el nombre de ACPI del destino del panel interno desde una de las GPU.
  6. ADS actualmente solo soporta sistemas con un único panel interno.
  7. Tener instaladas localmente una de las siguientes:
    1. GPU0, GPU1, y Mux ACPI todos reportan soporte completo de ADS.
    2. GPU0, GPU1 y Mux ACPI informan de una compatibilidad ya sea experimental o completa con ADS y la clave del registro EnableMDMExperimentalFeature está configurada.

Las condiciones 1 y 2 implican que ambos adaptadores deben iniciarse para que el mux se conmute.

Controlar la calidad del despliegue de características de ADS

Para ADS para proporcionar una buena experiencia de usuario, todos los siguientes componentes tienen que trabajar juntos sin problemas:

  1. La funcionalidad mux de pantalla del sistema operativo.
  2. Los métodos de ACPI de la plataforma para el cambio de MUX.
  3. La funcionalidad de Conmutador mux de pantalla en los controladores iGPU y dGPU.

Para ayudar a los IHV/OEM a tener código de calidad no apto para envío en las versiones, pueden exponer cualquiera de los siguientes niveles de soporte para ADS:

  • Sin soporte: el controlador no admite ninguna funcionalidad ADS.
  • Soporte de desarrollo: el controlador admite ADS, pero la implementación del controlador aún está en fase de desarrollo y no debe utilizarse más allá de este propósito.
  • Soporte experimental: el controlador admite ADS, pero aún no tiene la calidad de lanzamiento. El sistema operativo no activará ADS por defecto, pero puede configurarse para que lo haga.
  • Soporte completo: el controlador admite ADS a calidad de envío. El SO considera que el driver soporta ADS.

Mostrar atributos que deben permanecer sin cambios después de un cambio de pantalla

Un conmutador de pantalla no debería cambiar ninguno de los siguientes atributos de pantalla:

  1. Resolución del escritorio
  2. Ruta de VidPn (incluidos el modo de origen VidPn, el modo de destino, la escala, etc.)
  3. ppp
  4. Ajuste de luz nocturna
  5. Gamma
  6. Topología de pantalla
  7. Activación/desactivación de HDR
  8. Nivel de blanco de SDR
  9. Perfil de color
  10. Tipo objetivo de monitor OPM
  11. Brillo de la pantalla

Igualación de capacidades de la GPU para una experiencia de cambio sin interrupciones

Para proporcionar al usuario una experiencia de cambio sin problemas, la pantalla debe configurarse igual después del cambio que antes del cambio. Hay ciertas funciones de la GPU que ambas GPUs necesitan el mismo soporte para lograr este comportamiento. Por ejemplo, si una GPU admite HDR y la otra no, un cambio cuando HDR está habilitado en una GPU no sería fluido.

En la siguiente tabla se enumeran las funciones y características de visualización de la GPU y se describen los requisitos de alineación entre las dos GPU.

Característica GPUs requeridas para tener soporte sin fisuras
HDR Si el panel admite HDR, ambas GPU deben o bien admitir HDR fp16 o no admitir HDR.
Cursor Hw No. El SO se adapta a las diferentes características del cursor sin interrupciones visibles para el usuario.
MPO No. El sistema operativo se adapta a las diferentes características del MPO sin interrupción visible para el usuario.
PSR Ambas GPU tienen que soportar esta característica.
EDID/DisplayID Ambas GPU tienen que exponer el mismo EDID/DisplayId.
Límites de brillo Ambas GPUs tienen que admitir la misma interfaz de brillo y los mismos límites de brillo.
Niveles de brillo Ambas GPU necesitan exponer los mismos niveles e intervalos de brillo.
Solución Ambas GPU deben admitir los mismos modos de fuente y resolución de destino.
Frecuencias de actualización Consulte Problema si la GPU1 no admite la frecuencia de actualización a la que GPU0 está ejecutando el panel para obtener más información.
Frecuencia de actualización dinámica No. El sistema operativo se adapta a las diferentes frecuencias de actualización virtual.
Frecuencia de actualización variable Consulte Problema si la GPU1 no admite la frecuencia de actualización a la que GPU0 está ejecutando el panel para obtener más información.

Problema si GPU1 no admite la frecuencia de actualización a la que GPU0 tiene configurado el panel.

Si la GPU1 no admite el mismo modo que la GPU0, es probable que el modo reducido se almacene en la base de datos de topología de pantalla. Entonces, cuando el sistema cambie de nuevo a la GPU0, se establecerá el modo reducido. Por ejemplo, si la GPU0 soporta 120Hz pero la GPU1 solo soporta 60Hz entonces la siguiente secuencia podría suceder:

  1. El sistema está configurado para que la GPU0 controle la pantalla y el modo sea 120Hz.
  2. El usuario cambia manualmente a GPU1.
  3. La base de datos de topología de pantalla tiene 120Hz almacenado para la pantalla, pero GPU1 no lo soporta, por lo que el sistema operativo elige 60Hz.
  4. Se establece 60 Hz y se almacena en la base de datos de topología de pantalla.
  5. El usuario cambia manualmente a la GPU0.
  6. La base de datos de topología de pantalla lee 60 Hz de la base de datos.

Para ofrecer la mejor experiencia, un OEM debe seleccionar una iGPU y una dGPU que admitan la frecuencia de actualización máxima del panel interno. Si eso no es posible y una GPU no puede soportar la frecuencia de actualización máxima del panel, entonces la GPU que sí soporta la frecuencia de actualización del panel debe soportar la función Windows Dynamic Refresh Rate (DRR) con rangos que incluyan:

  • La frecuencia de actualización máxima de la otra GPU.
  • La frecuencia de actualización más alta del panel interno.

Por ejemplo, si el panel puede soportar 300Hz y la iGPU solo puede soportar 60Hz entonces la dGPU tiene que soportar VRR con un rango de al menos 60Hz a 300Hz.

En resumen, el requisito ADS para la frecuencia de actualización es o bien:

  1. La iGPU y la dGPU admiten la frecuencia de actualización máxima del panel interno.
  2. La GPU que admite la frecuencia de actualización máxima del panel interno debe ser capaz de soportar DRR en un rango que vaya desde la frecuencia de actualización más alta que la otra GPU puede soportar hasta la frecuencia de actualización máxima del panel interno.

HDR y Dolby Vision

El sistema operativo establece el mismo estado HDR/Dolby Vision en el panel interno de la GPU1 después del cambio que el establecido en el panel interno de la GPU0 antes del cambio. El usuario no debería notar ningún cambio.

Luz nocturna

La luz nocturna se implementa a través de las DDI de gamma o matriz de colores WDDM. En ambos casos, el sistema operativo establece los mismos niveles de luz nocturna a través de GPU1 después del cambio, tal como lo hizo con GPU0 antes del cambio.

Perfil de color

El sistema operativo aplica el mismo perfil de color al panel después del cambio que el aplicado antes del cambio.

Visualización de la pantalla de comprobación de errores

Actualmente el sistema operativo permite mostrar la pantalla de comprobación de errores en dispositivos no POST. Cuando se produce una comprobación de errores el SO:

  • No cambia el MUX.
  • Utiliza el soporte actual del SO para mostrar la pantalla de comprobación de errores.

Al evaluar posibles destinos para mostrar la comprobación de errores, el sistema operativo omite los destinos conectados a una MUX que está cambiado a otro destino.

Hay un pequeño período de tiempo en el que se procesó el HPD lejos de GPU0, pero el HPD de GPU1 aún no está completamente procesado. Si se produce una comprobación de errores durante este periodo, el usuario no verá la comprobación de errores. Si se produce una comprobación de errores en el pequeño período de tiempo en el que PSR todavía está habilitado, el controlador que controla la pantalla debe asegurarse de que el panel no está en modo PSR cuando el sistema operativo llama a DxgkDdiSystemDisplayEnable.

Algoritmo adaptativo de brillo de contenido

En un mundo ideal, el algoritmo de adaptación de contenido utilizado por ambas GPUs debería producir el mismo efecto. Sin embargo, es probable que no se produzca el mismo efecto y que el usuario note una diferencia al cambiar el panel interno.

Datos de brillo

Para garantizar que el usuario no note un cambio de brillo debido al cambio, todos los atributos de brillo expuestos por la GPU0 y la GPU1 tienen que ser idénticos. Este requisito garantiza que cualquier nivel de brillo antes del cambio en GPU0 se mantenga en GPU1 después del cambio.

Para ello, los controladores de GPU0 y GPU1 tienen que:

  1. Utilizar la misma interfaz de brillo, ya sea DXGK_BRIGHTNESS_INTERFACE_2 o DXGK_BRIGHTNESS_INTERFACE_3, siendo muy recomendable la versión 3.
  2. Para la interfaz de brillo v3, ambos controladores necesitan exponer el brillo basado en nits o sin calibrar.
  3. Para la interfaz de brillo v2, ambos controladores tienen que devolver exactamente los mismos niveles de brillo posibles de GetPossibleBrightness.
  4. Para la interfaz de brillo v3, ambos controladores tienen que devolver exactamente los mismos rangos; es decir, cada controlador debe devolver estructuras DXGK_BRIGHTNESS_GET_NIT_RANGES_OUT idénticas desde GetNitRanges.
  5. Las tablas internas que utiliza el controlador para convertir los niveles de brillo suministrados por el sistema operativo en ajustes específicos del panel deben ser las mismas.

En la mayoría de los portátiles, el controlador de la GPU obtiene algunos o todos estos datos de nivel de brillo de la plataforma de una forma no estándar. Esperamos que este intercambio de datos entre plataforma y GPU tenga que ampliarse para cumplir estos requisitos.

Aunque la interfaz de brillo se consulta en el momento de inicio del adaptador, el sistema operativo no llamará a ninguna de las DDI de la interfaz de brillo hasta que el panel interno se active mediante HPD. HPD se produce después de que el MUX se cambie a la GPU de modo que el controlador tenga acceso al EDID del panel interno en ese instante.

Entendemos que hay formas específicas de IHV para que el controlador establezca el brillo del panel para los paneles que no admiten PWM. Sin embargo, este método añade complicaciones para TCon, ya que podría tener que admitir la obtención del brillo de una manera específica de IHV, que varía según la GPU conectada a través del MUX.

Configuración de arranque del mux

El firmware del sistema controla qué GPU está conectada al panel interno al iniciarse el sistema. El SO almacena qué GPU controló el panel por última vez. A continuación, durante la secuencia de arranque, el sistema operativo cambia el multiplexor si es necesario para que la GPU correcta controle el panel.

Para conservar cualquier imagen de arranque cuando sea necesario un cambio de MUX, el cambio solo se realiza cuando:

  • Ambas GPUs están encendidas.
  • El sistema operativo ha pasado de controlar la salida mediante gráficos de arranque a controlarla mediante DWM/shell.

Por lo tanto, el cambio se produce después de la llamada a DxgkddiSettimingsfromvidpn en la GPU que controla el panel interno, y el usuario experimentará una pantalla congelada mientras el panel está en PSR durante el cambio.

Proporcionar información mux al controlador

Esta función está diseñada específicamente para que el sistema operativo llame al controlador para proporcionar la información, en lugar de ofrecer un callback al que el controlador puede llamar en cualquier momento. Este método evita que el controlador se confunda si consulta el estado del SO durante una secuencia de Conmutador.

El sistema operativo invoca al controlador DxgkDdiDisplayMuxUpdateState DDI a fin de proporcionarle el estado actual del mux en los siguientes casos:

  1. Al iniciar el controlador, lo que permite al controlador evitar secuencias de sondeo oportunas cuando el panel no está conectado.
  2. Al regresar a D0 desde Dx. Al regresar de algunos estados de energía (por ejemplo, hibernación), el firmware podría tener que restablecer el multiplexor; por lo tanto, el controlador puede no conocer el estado.

Estos casos, junto con los DDIs normales implicados en la secuencia de conmutación, garantizan que el controlador pueda determinar de qué manera se conmuta un multiplexor en cualquier momento en que la GPU está activa.

En la primera versión de esta función, no hay planes para conmutar el mux cuando el panel interno no está activo, por lo que todos los cambios seguirán la misma secuencia.

Hora de inicio del adaptador

Cuando se inicia un controlador, este debe responder a las peticiones de sondeo del sistema operativo. El controlador podría intentar detectar si el MUX ha cambiado a ellas intentando comunicarse, pero eso podría llevar mucho tiempo o no ser confiable. Como parte de la secuencia de inicio de la GPU, el sistema operativo llama a la DDI DxgkDdiDisplayMuxUpdateState para cada destino que está conectado a una MUX e indica si se ha cambiado a ese destino.

Cuando se inicia un controlador, este debe responder a las peticiones de sondeo del sistema operativo. El controlador podría intentar descubrir si el mux está cambiado a su GPU comunicándose con el sistema operativo, pero eso podría ser lento o poco fiable.

En su lugar, como parte de la secuencia de inicio de la GPU, el sistema operativo llama a DxgkDdiDisplayMuxUpdateState para cada destino que está conectado a un multiplexor e indica si dicho multiplexor está conmutado a ese destino. El sistema operativo informa al controlador si el MUX ha cambiado a la GPU del controlador antes de llamar a cualquier DDI de sondeo.

El controlador de ADS sigue informando del panel interno al sistema operativo de la misma manera, donde el sistema operativo llama a DxgkDdiQueryAdapterInfo(DXGKQAITYPE_INTEGRATED_DISPLAY_DESCRIPTOR2) para consultar los detalles del panel interno. El controlador debe asegurarse de que DXGK_CHILD_CAPABILITIES.HpdAwareness se establezca en HpdAwarenessInterruptible para cualquier destino conectado a un MUX.

Transición de D0

Cada vez que una GPU con un multiplexor conectado se reactiva a un estado activo desde un estado de baja potencia, el sistema operativo llama a DxgkDdiDisplayMuxUpdateState para indicar al controlador si el multiplexor está conectado a su objetivo o ha sido cambiado a la otra GPU.

Secuencia de arranque

La siguiente secuencia de arranque destaca aspectos específicos de ADS. En esta secuencia, el sistema arranca con:

  • La iGPU conectada al MUX.
  • La última configuración del usuario antes del reinicio fue que el mux estaba conectado a la dGPU.

La secuencia de arranque es de naturaleza asíncrona, por lo que esta secuencia es solo a modo de ejemplo.

  1. El sistema se enciende y el iGPU está conectado al panel a través del multiplexor.
  2. La iGPU muestra la pantalla de arranque en el panel.
  3. Windows carga y muestra la animación de arranque en la tapa interna.
  4. Debido a _DEP en iGPU y dGPU, el controlador de MUX del sistema operativo se inicia antes de cualquier controlador de GPU. El controlador del mux usa llamadas ACPI para asegurarse de que el mux está configurado correctamente. El controlador mux verifica que la implementación ACPI mux cumple los requisitos ADS.
  5. Dxgkrnl llama a DxgkDdiAddDevice para la iGPU.
  6. Dxgkrnl llama a DxgkDdiQueryInterface(DXGK_DISPLAYMUX_INTERFACE) para la iGPU. Incluso si el sistema actual no admite ADS, el controlador devuelve su interfaz si admite ADS.
  7. Dxgkrnl llama a DxgkDdiDisplayMuxGetDriverSupportLevel para obtener el nivel de compatibilidad de ADS del controlador.
  8. Dxgkrnl llama a DxgkDdiDisplayMuxReportPresence(TRUE) para que la iGPU sepa que el sistema tiene un MUX de ADS funcionando.
  9. Dxgkrnl llama a DxgkDdiStartDevice. El controlador de iGPU devuelve el número de subcomponentes, incluido el destino de VidPn para el panel interno.
  10. Dxgkrnl llama a DxgkDdiDisplayMuxGetRuntimeStatus para comprobar si la iGPU admite el ADS y si el controlador obtuvo toda la información requerida del sistema.
  11. Dxgkrnl llama a DxgkDdiQueryChildStatus para cada elemento secundario que expone la iGPU.
  12. Una vez que Dxgkrnl encuentra el elemento secundario notificado por la iGPU que está conectado al MUX, llama a DxgkDdiDisplayMuxUpdateState para informar a la iGPU de que el MUX está conectado a ese destino.
  13. Dado que la iGPU expone un monitor conectado internamente, Dxgkrnl establece un modo en la iGPU mediante DxgkddiSettimingsfromvidpn.
  14. Dxgkrnl inicia el controlador dGPU, luego repite los pasos 5-12 para la dGPU.
  15. Dxgkrnl detecta que la iGPU, la dGPU y el mux están configurados correctamente, por lo que crea un par de mux y establece las propiedades de la interfaz de dispositivo PnP para el mismo.
  16. Dxgkrnl lee la última configuración mux del registro. Dado que la última configuración era dGPU, Dxgkrnl ahora inicia la secuencia del conmutador MUX descrita anteriormente para cambiar el MUX a la dGPU.

Controladores de panel

Los controladores del panel del monitor se cargan basándose en el ID de hardware PnP generado a partir del EDID. Dado que el EDID sigue siendo el mismo, el controlador de panel se carga cuando cualquiera de las GPU controla el panel interno. Ambos controladores expondrán la misma funcionalidad de brillo. Por lo tanto, la carga no debería causar ningún problema y el controlador del panel no necesitará saber qué GPU está a cargo del multiplexor.

Identifica los objetivos que controla un mux

Cuando el sistema operativo inicia el controlador, llama a DxgkDdiQueryChildRelations del controlador para consultar información sobre los elementos secundarios notificados. El controlador rellena la estructura DXGK_CHILD_DESCRIPTOR para cada elemento secundario. El miembro AcpiUid se define como el valor devuelto por el método _ADR de ese nodo hijo en el espacio de nombres ACPI, lo que permite al sistema operativo encontrar el nombre ACPI para ese nodo hijo.

Para ADS, definimos un método DMID ACPI que debe estar bajo el espacio de nombres ACPI secundario para el destino. Este método DMID devuelve el nombre ACPI del dispositivo mux. Permite que el sistema operativo busque el nombre mux ACPI para el destino.

PnP deteniendo el adaptador que está escaneando hacia un objetivo

El sistema operativo no cambiará el multiplexor cuando se detiene la GPU que está enviando la imagen al panel interno. Los siguientes escenarios repasan los diferentes casos en los que se detiene una GPU.

  1. GPU0 es el POST. Está conectada al panel interno y se detiene.

    En este caso, el Básico Display Driver (BDD) toma el control del modo actualmente activo en la GPU0 y continúa actualizando la pantalla.

  2. GPU0 es el POST, pero la GPU1 está conectada al panel interno. GPU0 se detiene.

    Debido al diseño actual del sistema operativo, BDD se inicia en la GPU0, lo que provoca que se informe de un monitor fantasma y este aparezca en el Panel de control de pantalla.

  3. GPU1 no es el POST y está conectada al panel interno. GPU1 se detiene.

    Debido al diseño actual del sistema operativo, el BDD no se inicia en la GPU1 y, por tanto, el usuario no podrá ver el panel.

  4. GPU1 no es el POST. GPU0 está conectado al panel interno y GPU1 está detenido.

    No se produce ningún cambio y no ocurre nada. GPU0 sigue apareciendo en el panel.

Los escenarios 2 y 3 crean una mala experiencia para el usuario. La función ADS cambia el comportamiento para solucionar estos dos casos.

No se admiten GPU externas/de complemento

No creemos que haya ningún caso de uso para esta función con GPUs plugin.

ADS está limitado solo a paneles internos individuales

La primera versión de ADS solo admite paneles internos únicos. Sin embargo, la característica está diseñada de una manera que le permite apoyar muxing pantallas externas e internas múltiples (cuando es compatible con el sistema operativo) en el futuro con cambios mínimos en el controlador.

Cambios en la política actual del adaptador POST

Anteriormente, el SO tenía algunas políticas relativas al adaptador POST. Por ejemplo, el adaptador POST era el único adaptador que podía exponer destinos internos. Este tipo de restricciones se eliminan del SO con la introducción de ADS.

Deshabilitar los efectos visuales de llegada del monitor

Cuando se conecta un monitor en Windows 11, el shell/DWM tiene una secuencia de animación. Esta animación se desactiva en escenarios de cambio de pantalla.

Deshabilitar PnP bonk

Cuando se agrega o quita un monitor, el sistema PnP reproduce un sonido "bonk" para notificar al usuario. Este 'bonk' está desactivado en situaciones de cambio de pantalla.

Notificaciones de las aplicaciones

Cuando ocurre un cambio de pantalla, el sistema sigue los procedimientos habituales para la eliminación y llegada de HPD. Por lo tanto, todas las notificaciones normales de la aplicación se activan normalmente; por ejemplo, la notificación PnP para el HPD out y el HPD in y los mensajes de ventana WM_DISPLAYCHANGE.

API para activar el interruptor

El plan es tener una API pública para que el sistema operativo y el panel de control de IHV puedan activar el cambio.

Dado que el panel interno solo está conectado a una única GPU, las API de visualización funcionan como se espera junto con la funcionalidad Win+P.

Prueba HLK

Si un controlador de GPU o firmware ACPI indica que es totalmente compatible con ADS, debe superar las pruebas ADS HLK en un sistema compatible con ADS.

Panel interno de HPDing de la GPU cuando el MUX se cambia fuera de esa GPU

El sistema operativo inicia una comprobación de errores cuando un panel interno se notifica como conectado por un controlador, pero ese MUX está actualmente cambiado a otro controlador.

Transición CA/CC

Para la primera versión de la característica ADS, el sistema operativo no almacenará una configuración de mux de CA frente a CC y no activará un cambio de mux durante una transición de CA <a CC>.

Transiciones de alimentación del sistema

La principal preocupación con las transiciones de energía es cuando el firmware restablece el estado del MUX (por ejemplo, durante la hibernación), y al reanudar desde la alimentación, el MUX no se cambia al panel en el que estaba antes de la transición de energía.

El enfoque inicial era cambiar el multiplexor de nuevo a la dGPU después de encender tanto la iGPU como la dGPU. El problema con este enfoque es que, dependiendo de diferentes eventos asíncronos, el resultado podría ser múltiples cambios de modo.

El enfoque actualizado para ayudar a simplificar la experiencia del usuario consiste en que el sistema cambie nuevamente el multiplexor al destino esperado mientras tanto la iGPU como la dGPU están en reposo, evitando así múltiples cambios de modo.

Secuencia de transición de alimentación

El siguiente ejemplo describe una transición de energía de hibernación en un sistema ADS.

  1. El sistema está configurado con el mux conectado a la dGPU.
  2. El sistema entra en hibernación.
  3. Tanto la iGPU como la dGPU se transfieren al estado de energía D3.
  4. El sistema se apaga.
  5. El usuario enciende el sistema.
  6. El firmware configura el MUX a la iGPU y la secuencia de arranque de la pantalla de la iGPU en el panel interno.
  7. Dxgkrnl lee la configuración pasada del mux (dGPU en este caso), y la compara a la posición actual del mux usando ACPI (iGPU en este caso). Dxgkrnl llama a la ACPI para cambiar el MUX a la dGPU.
  8. Dxgkrnl cambia la iGPU a D0, y luego llama aDxgkDdiDisplayMuxUpdateState de la iGPU para informar al controlador de que el MUX no está conectado.
  9. Dxgkrnl cambia la dGPU a D0, y luego llama aDxgkDdiDisplayMuxUpdateState de la dGPU para informar al controlador de que el MUX está conectado.
  10. Dxgkrnl fija un modo en el dGPU.

Sistemas Todos en Uno AIO

Cualquier sistema AIO que quiera admitir ADS debe tener el panel interno expuesto como un tipo de destino interno en ambas GPU.

Dispositivo de ACPI de MUX

El OEM es responsable de agregar el dispositivo multiplexor en el espacio de nombres ACPI y proporcionar los métodos necesarios para operar el multiplexor.

El controlador de la GPU nunca debe llamar a los métodos ACPI del mux porque el dispositivo mux podría encontrarse en cualquier lugar del árbol ACPI. La recomendación es localizar el multiplexor debajo del antecesor compartido más cercano de ambas GPUs.

Los dispositivos mux actuales solo soportan dos entradas y no esperamos que los futuros muxes soporten más que eso, por lo que el diseño puede asumir dos entradas y una única salida para cada mux.

El dispositivo mux nunca puede detenerse mientras el sistema está en ejecución. Es un dispositivo del sistema oculto.

Métodos ACPI del dispositivo mux

Solo el conjunto de controladores de un dispositivo ACPI puede llamar para evaluar los métodos ACPI del dispositivo. Por lo tanto, para llamar a métodos del dispositivo MUX para cambiar el MUX, el sistema operativo debe tener un controlador cargado para el dispositivo MUX. Por este motivo, el sistema operativo ahora proporciona un controlador MUX de pantalla como controlador para todos los MUX de conmutador de pantalla.

Un dispositivo mux debe tener los siguientes métodos:

  • _HID identifica el dispositivo mux por ID de hardware. Hemos reservado "MSFT0005" para el multiplexor de pantalla ACPI.
  • DMQU (Display Mux Query) devuelve el estado actual del mux.
  • DMCF (configuración de MUX de pantalla) configura el Mux.

Método _HID (Hardware ID)

Argumentos:

Ninguna

Devuelve:

Una cadena ASCII que contiene el ID del hardware, que es 'MSFT0005'.

Método DMQU (mostrar consulta MUX)

En una futura versión, esperamos añadir información adicional a la consulta. Para permitir consultas adicionales en el futuro, se utiliza Arg0 para indicar el tipo de consulta. Si el método DMQU no entiende un tipo de consulta, debe declarar el método como no admitido.

Argumentos:

Arg0: Un número entero que especifica el tipo de consulta. La siguiente tabla enumera los valores de tipo de consulta y sus significados.

Valor del tipo de consulta Significado
1 Consulta el estado actual del interruptor
2 Consulta el nivel de soporte de ADS para MUX
3 Consulta el primer nodo de GPU al que está conectado el MUX
4 Consulta la segunda unidad secundaria de GPU a la que está conectado el multiplexor

Devuelve:

Si el método entiende el tipo de consulta especificado, debe devolver los datos apropiados como se indica en la siguiente tabla. Si el método no entiende el tipo de consulta especificado, debe devolver una cadena vacía.

Valor del tipo de consulta Devolver datos
1 Cadena ASCII que contiene el nombre de ACPI del dispositivo secundario de la GPU al que se cambia actualmente el MUX.
2 Número entero que representa el nivel de soporte de ADS. Consulte la siguiente tabla para obtener más detalles.
3 Cadena ASCII que contiene el nombre ACPI del primer dispositivo hijo de GPU al que se conecta el multiplexor.
4 Cadena ASCII que contiene el nombre ACPI del segundo dispositivo hijo de la GPU al que está conectado el multiplexor.

La siguiente tabla enumera los valores del nivel de soporte ADS y sus significados cuando el tipo de consulta es 2.

Datos devueltos Significado
0 No se admite
1 Soporte de desarrollo Los sistemas pueden enviarse con esta configuración sin pasar ninguna de las pruebas HLK, ya que ADS se deshabilitará de forma predeterminada en los sistemas de clientes.
2 Soporte experimental. Los sistemas pueden enviarse con esta configuración sin pasar ninguna de las pruebas HLK, ya que ADS se deshabilitará de forma predeterminada en los sistemas de clientes.
3 Totalmente compatible. ADS se activará por defecto en este sistema si está emparejado con controladores gráficos totalmente compatibles. El sistema debe superar las pruebas de ADS HLK para su envío.

Método DMCF (mostrar configuración de MUX)

Argumentos:

Arg0: nombre ASCII del dispositivo secundario de GPU ACPI al que debe cambiar el multiplexor.

Devuelve:

El número entero 0 significa éxito; un valor distinto de cero indica fallo. El OEM puede definir el valor distinto de cero para un mejor diagnóstico.

Métodos ACPI para dispositivos GPU

Antes de iniciar un controlador gráfico para una GPU, el sistema necesita saber si el dispositivo mux ACPI está funcionando y cuál es su estado actual. Para ello, ya se debe haber iniciado el controlador del dispositivo MUX de la ACPI. El sistema utiliza el método ACPI _DEP dentro del espacio de nombres ACPI de cada GPU para garantizar la relación del dispositivo.

Si una GPU ya tiene un método _DEP, debe añadir el nombre ACPI del dispositivo mux a la lista de dependencias devuelta. Si la GPU aún no tiene un método _DEP, debería añadir uno.

Para que el firmware de ACPI declare la dependencia de una GPU en el MUX solo si el sistema operativo lo admite como una capacidad de ADS, se introduce una consulta _OSI de ACPI. El firmware ACPI puede utilizar esta consulta para comprobar la compatibilidad con ADS. Las versiones del sistema operativo que admiten ADS informarán de la compatibilidad devolviendo un valor verdadero al comando _OSI(“DisplayMux”) de ACPI.

Métodos ACPI del dispositivo secundario de la GPU

Para cada destino conectado a un MUX, el dispositivo de ACPI de ese elemento secundario expone un método ACPI que devuelve el nombre de ACPI del dispositivo MUX al que está conectado. Para obtener más información, consulte Identificar los objetivos que un mux controla.

Método DMID (mostrar identificador de MUX)

Argumentos:

Ninguna

Devuelve:

Cadena ASCII que contiene el nombre ACPI del dispositivo mux ACPI al que está conectada esta salida

Ejemplo

El siguiente ejemplo muestra cómo se configura y administra un sistema con dos GPUs (GPU0 y GPU1) y un mux dentro del marco ACPI.

  • El nombre ACPI del dispositivo mux es 'SB.MUX1'.

  • Para GPU0:

    • El nombre ACPI de la GPU0 es 'SB.PCI0.GFX0'.
    • Expone el destino VidPn 0x40f04, que notifica un valor de DXGK_CHILD_DESCRIPTOR.AcpiUid de 0x400.
    • El nombre del dispositivo secundario ACPI correspondiente al destino conectado al mux es 'SB.PCI0.GFX0.DD1F'.
    • El método ACPI _ADR bajo 'SB.PCI0.GFX0.DD1F' devuelve 0x400. Este valor devuelto es la forma en que el sistema operativo sabe que este dispositivo ACPI corresponde al destino VidPn 0x40f04.
    • El método ACPI DMID bajo 'SB.PCI0.GFX0.DD1F' devuelve 'SB.MUX1'.
  • Para GPU1:

    • El nombre ACPI de la GPU1 es 'SB.PCI0.PEG0.PEGP'.
    • Expone el destino VidPn 0x1103, que notifica de un valor de DXGK_CHILD_DESCRIPTOR.AcpiUid de 0x100.
    • El nombre del dispositivo secundario ACPI correspondiente al destino conectado al multiplexor es 'SB.PCI0.PEG0.PEGP.EDP1'.
    • El método ACPI _ADR bajo 'SB.PCI0.PEG0.PEGP.EDP1' devuelve 0x100. Este valor devuelto es el medio por el cual el sistema operativo identifica que este dispositivo ACPI corresponde al destino VidPn 0x1103.
    • El método ACPI DMID bajo 'SB.PCI0.PEG0.PEGP.EDP1' devuelve 'SB.MUX1'.
  • El sistema operativo sabe que el objetivo de GPU0 0x40f04 y el objetivo de GPU1 0x1103 están conectados al mismo mux con el nombre ACPI 'SB.MUX1'.

  • Si GPU1 está actualmente conectado al panel, el sistema operativo puede cambiar el mux a GPU0 llamando al método DMCF en SB.MUX1 pasando SB.PCI0.GFX0.DD1F

El siguiente código de lenguaje máquina ACPI corresponde a las partes relevantes del ejemplo. El pseudocódigo para la lógica de la plataforma está delimitado por <>.


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")
            }
        }
    }
}

Cambios de API

La función ADS añade la siguiente funcionalidad a la API pública:

  1. Enumerar los dispositivos mux del sistema.
  2. Consultar información sobre el MUX; por ejemplo, a qué destinos está conectado y a qué destino se ha cambiado actualmente.
  3. Desencadenar un conmutador MUX.
  4. Cómo detectar cuándo se ha cambiado el multiplexor.

Enumerar los dispositivos mux del sistema

Las aplicaciones pueden usar API generales de plug and play para buscar interfaces de dispositivos que representen un MUX de pantalla funcional. Los componentes en modo de usuario pueden usar Windows.Devices.Enumeration.DeviceInformation. Tanto C# como C++ pueden utilizarse con estas API para enumerar los dispositivos mux.

// 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);

Interfaz IDisplayMuxDevice

Se agrega la interfaz IDisplayMuxDevice para representar el dispositivo MUX.

El siguiente código muestra cómo enumerar los dispositivos mux de visualización, consultar sus estados, cambiar el destino de visualización activo y reaccionar a los cambios de estado mediante las API de tiempo de ejecución de Windows.

#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);
    }
}

Cambios en WDDM DDI para el cambio automático de pantalla

Esta sección describe las adiciones y cambios realizados en el DDI de WDDM para soportar ADS. Estos cambios están disponibles a partir de Windows 11, versión 24H2 actualización 2025.01D (WDDM 3.2).

Consulta de la interfaz de soporte de ADS de KMD

Se añade la estructura de interfaz DXGK_DISPLAYMUX_INTERFACE_2. Contiene las llamadas del sistema operativo al controlador necesarias para admitir ADS versión 2. El sistema operativo consulta la interfaz ADS compatible del controlador al iniciar el controlador, con InterfaceType establecido en GUID_WDDM_INTERFACE_DISPLAYMUX_2.

(DXGK_DISPLAYMUX_INTERFACE contiene las llamadas de SO a controlador necesarias para admitir la versión 1 de la función ADS. Esta versión se utilizó durante la versión preliminar de ADS).

Funciones de KMD para admitir ADS

KMD implementa las siguientes funciones para admitir ADS. Dxgkrnl obtiene la interfaz funcional ADS de KMD a través de una llamada a DxgkddiQueryInterface de KMD.

Capacidad de ADS para informar sobre controladores

El controlador informa de su nivel de compatibilidad con ADS cuando el sistema operativo llama a su DDI DxgkDdiDisplayMuxGetDriverSupportLevel. Si el controlador no implementa la interfaz de DXGK_DISPLAYMUX_INTERFACE, el sistema operativo considera que el nivel de compatibilidad es DXGK_DISPLAYMUX_SUPPORT_LEVEL_NONE.

El controlador debe informar de su nivel de compatibilidad con ADS independientemente del sistema en el que se esté ejecutando. El nivel de compatibilidad notificado por el controlador debe basarse únicamente en el controlador. El controlador no debe tener en cuenta ninguno de los siguientes criterios a la hora de informar sobre su nivel de compatibilidad con ADS:

  1. OEM del sistema.
  2. Cualquier otra GPU del sistema.
  3. La presencia o no del dispositivo ACPI mux.
  4. La presencia o no de las entradas ACPI bajo el nodo ACPI de la GPU.

Actualización de los destinos de informes al iniciar la adaptación

Cuando se inicia el adaptador, notifica todos sus dispositivos secundarios a través de la DDI DxgkDdiQueryChildRelations. El informe incluye cualquier destino interno conectado a un MUX. Un destino interno incluye el campo DXGK_CHILD_CAPABILITIES.Type.IntegratedDisplayChild.DescriptorLength.

Se produce un problema si el multiplexor se cambia a la otra GPU al iniciarse el adaptador. En esta situación, el controlador no puede comunicarse con el panel interno para consultar el tamaño EDID/DisplayId. Por lo tanto, un controlador que expone la interfaz GUID_WDDM_INTERFACE_DISPLAYMUX_2 debe establecer DXGK_CHILD_CAPABILITIES.Type.IntegratedDisplayChild.DescriptorLength en cero al iniciar el adaptador si el MUX no está actualmente cambiado a la GPU del controlador. De lo contrario, el sistema operativo produce un error en el inicio del adaptador.

El SO actualiza su información interna sobre el tamaño del descriptor interno en la primera operación de Conmutador mux.

Actualización por cambio de conexión

Como se mencionó anteriormente, hay una manera específica de ADS para notificar el estado del panel interno durante una secuencia automática de cambio de pantalla. Para indicar que un paquete de cambios de conexión forma parte de una secuencia de cambios de ADS, el indicador DisplayMuxConnectionChange se agrega a DXGK_CONNECTION_MONITOR_CONNECT_FLAGS. Cuando se establece DisplayMuxConnectionChange, indica que el estado de conexiónMonitorStatusConnected o MonitorStatusDisconnected está relacionado con un cambio de pantalla automático.

DisplayMuxConnectionChange solo se debe usar durante un cambio ADS y no debe usarse para ningún otro propósito. Debe usarse en los siguientes casos de ADS:

  • Mientras el controlador está procesando DxgkDdiDisplayMuxPreSwitchAway.

    Si el panel interno está conectado, el controlador debe agregar un paquete DXGK_CONNECTION_CHANGE a su lista de cambios de conexión con DXGK_CONNECTION_CHANGE.ConnectionStatus establecido en MonitorStatusDisconnected y DXGK_CONNECTION_CHANGE.MonitorConnect.MonitorConnectFlags.DisplayMuxConnectionChange establecido en 1. Estos ajustes indican al SO que el controlador ha liberado el control del panel interno.

  • Mientras el controlador procesa DxgkDdiDisplayMuxPostSwitchToPhase1.

    • El controlador debe determinar primero si el panel interno está conectado.
    • Si el panel interno está conectado, el controlador debe agregar un paquete DXGK_CONNECTION_CHANGE a su lista de cambios de conexión con DXGK_CONNECTION_CHANGE.ConnectionStatus establecido en MonitorStatusConnected y DXGK_CONNECTION_CHANGE.MonitorConnect.MonitorConnectFlags.DisplayMuxConnectionChange establecido en 1.
    • Si el panel interno no está conectado, el controlador debe agregar un paquete DXGK_CONNECTION_CHANGE a su lista de cambios de conexión con DXGK_CONNECTION_CHANGE.ConnectionStatus establecido en MonitorStatusDisconnected y DXGK_CONNECTION_CHANGE.MonitorConnect.MonitorConnectFlags.DisplayMuxConnectionChange establecido en 1.
  • Mientras el controlador está procesando DxgkDdiDisplayMuxSwitchCanceled.

  • En el caso de que una solicitud de sondeo de destino llegue durante un cambio, DisplayMuxConnectionChange solo debe establecerse para los paquetes de cambios de conexión que se agregan desde DxgkDdiDisplayMuxPreSwitchAway, DxgkDdiDisplayMuxPostSwitchToPhase1 o DxgkDdiDisplayMuxSwitchCanceled.

Guía actualizada para DxgkDdiSystemDisplayEnable

Cuando se invoca la DDI DxgkDdiSystemDisplayEnable(/windows-hardware/drivers/ddi/dispmprt/nc-dispmprt-dxgkddi_system_display_enable) de un controlador de ADS, el controlador debe asegurarse de que PSR esté deshabilitado al final de su llamada a la DDI DxgkDdiSystemDisplayEnable.

Guía de OEM

Hay varios aspectos de la función ADS que están por debajo del nivel que controla el SO en la plataforma. Es esencial que los OEM se aseguren de que funciona correctamente. La siguiente lista resume algunos de los puntos clave que los OEM deben tener en cuenta:

  • Tanto el controlador híbrido integrado como el híbrido discreto tienen que ser compatibles con ADS.
  • El MUX seleccionado para la plataforma puede controlarse a través de ACPI.
  • Los métodos _HID, DMQU y DMCF bajo el dispositivo MUX y los dispositivos ACPI secundarios de la GPU para los destinos internos se implementan y tienen el método DMID ACPI.
  • Ambos dispositivos ACPI de las GPU deben tener _DEP para indicar su dependencia del dispositivo ACPI de MUX.
  • La interfaz de brillo, las capacidades y los intervalos expuestos por ambas GPUs coinciden exactamente.
  • Como se detalla en la sección Datos de brillo, se recomienda encarecidamente la interfaz de brillo v3 en lugar de la interfaz de brillo V2.
  • Si se utiliza un controlador de panel de monitor, el código debe ser independiente de la GPU; es decir, se puede utilizar la misma lógica cuando cualquiera de las dos GPU controla el panel.
  • Al menos para un mux interno, el acto de cambiar el mux no debe generar un evento HPD.
  • Si el OEM quiera desactivar el mux en un sistema, el método DMQU ACPI debería devolver 0 cuando se llama con Arg0 establecido en 2.
  • El mux debe ser capaz de conmutar entre GPUs incluso cuando los drivers están en bajo consumo. En este caso, no se utilizará PSR.
  • Cuando el mux cambia de una GPU a otra, el brillo del panel debe mantenerse sin fallos de brillo. Existen múltiples formas de hacerlo, entre las que se incluyen las siguientes. El OEM es responsable de garantizar que el sistema mantenga el brillo en todos los cambios.
    • Utilice el control de brillo basado en DisplayPort Aux Nits.
    • Use un Tcon con reconstrucción PWM para evitar cualquier problema de brillo.
  • El panel y el Tcon que se usan pueden permanecer en actualización automática (PSR1 para eDP) cuando la configuración del enlace anterior y posterior al cambio se expone mediante el EDID y es compatible con la iGPU y la dGPU. Esto incluye, pero no se limita a:
    • Frecuencia de actualización
    • Tamaño activo
    • Número de carriles eDP utilizados y ancho de banda por carril
    • Configuración de DSC de eDP
    • Versión utilizada de VSC SDP eDP
    • Versión y características de PSR usadas para escenarios sin cambio