Alternância de exibição automática
Importante
Algumas informações estão relacionadas a um produto de pré-lançamento que pode ser substancialmente modificado antes de ser lançado comercialmente. A Microsoft não oferece garantias, expressas ou implícitas, em relação às informações fornecidas aqui.
Este artigo descreve o recurso de alternância de exibição automática (ADS), que fornece suporte para que o painel interno de um notebook seja alternado perfeitamente entre uma GPU integrada (iGPU) e uma GPU discreta (dGPU). ADS é um recurso opcional do WDDM, com suporte a partir do Windows 11, versão 24H2 atualização 2025.01D (WDDM 3.2).
Neste artigo:
- GPU0 refere-se à GPU à qual o painel integrado está conectado no momento.
- GPU1 refere-se à GPU para a qual o painel será alternado.
Visão geral
Alguns laptops lançados têm um dispositivo multiplexer (mux) que permite que o painel interno seja alternado entre a GPU integrada (iGPU) e a GPU discreta (dGPU). Atualmente, o driver gráfico dispara e executa a opção nesses laptops sem qualquer conhecimento do sistema operacional, o que leva a algumas experiências indesejadas do usuário.
O ADS permite que o sistema operacional controle o uso de um dispositivo mux no sistema para alternar entre o iGPU e o dGPU ao direcionar para o painel interno. Portanto, o sistema operacional pode fornecer uma melhor experiência do usuário.
A versão inicial do ADS dá suporte apenas à alternância do painel interno entre o iGPU e o dGPU. No futuro, esse recurso pode ser expandido para dar suporte à multiplexação de conectores externos em laptops também.
Design de alto nível
Em geral, o sistema precisa garantir que o conteúdo do painel interno seja exibido sem interferências enquanto a alternância estiver em andamento. O sistema operacional não restringe essa funcionalidade a nenhum protocolo de exibição específico. Este artigo se concentra em como implementar o ADS com eDP, mas há mais padrões do setor que podem ser usados (por exemplo, MIPI ou DSI). Um design de plataforma pode usar outro protocolo de conexão de exibição se conseguir a mesma experiência sem outras alterações no sistema operacional.
As subseções nesta seção identificam aspectos de design do recurso e detalham a abordagem de alto nível para cada aspecto.
Controle do dispositivo mux
Para reduzir as dependências entre os drivers gráficos iGPU e dGPU, o mux é exposto como um dispositivo separado que o sistema operacional pode controlar independentemente dos drivers gráficos. As vantagens dessa abordagem são:
- Isso reduz a complexidade do driver gráfico porque o driver não precisa saber como controlar cada mux diferente que um OEM pode usar.
- Ele reduz ou elimina dependências entre drivers gráficos, o que reduz as atualizações do driver e torna mais fácil para os OEMs selecionar GPUs e muxes.
- O sistema operacional pode alternar o mux quando um driver gráfico não estiver disponível.
Exposição do dispositivo mux
Como essa solução destina-se ao muxing entre iGPU interno e dGPU, faz sentido expor o mux via ACPI.
Funcionalidade do driver do mux
O driver mux deve atender aos seguintes requisitos funcionais de alto nível:
- Ele deve fornecer o status do mux, qual destino está controlando atualmente o painel interno e os limites de capacidade.
- Ele deve possibilitar ativar um comutador e informar o status do comutador.
Para obter mais informações sobre o dispositivo mux ACPI e seus métodos, consulte ACPI.
Para executar uma alternância perfeita, o dispositivo mux requer as seguintes condições sempre durante a alternância da GPU:
- Potência do painel. O mux sempre precisa que a energia do painel seja fornecida por uma das GPUs. Não há problema em fazer com que ambas as GPUs forneçam o poder do painel ao mesmo tempo.
- Sinais de controle com habilitação de brilho das duas GPUs durante a alternância.
- Nível de brilho (modulado por largura de pulso) das duas GPUs durante a alternância.
O mux alterna as seguintes informações entre as duas GPUs e o painel:
- Sinal de controle com brilho habilitado
- Nível de brilho (modulado por largura de pulso)
- Linha auxiliar da DisplayPort (DP)
- Linha de detecção de hot-plug (HPD)
- Linha de dados DP
O mux deve ter a capacidade de alternar quando o painel não estiver ativo. Pelo menos para a alternância de painel interno, o mux não deve disparar sinais HPD para a GPU ao alternar.
O driver de GPU nunca deve chamar os métodos de ACPI do mux.
DDI de alternância de exibição automática
Vários DDIs são adicionados para atender aos requisitos do mux. Há cinco pontos diferentes que o sistema operacional chama de DDI de um driver. As várias chamadas dependem do estado da alternância e de o driver estar controlando a GPU que atualmente detém o controle da tela.
DDI | Descrição |
---|---|
DxgkDdiDisplayMuxPreSwitchAway | Chame o driver atualmente conectado à exibição. Essa chamada informa ao driver que o sistema está planejando trocar a exibição para uma outra GPU (de GPU0 para GPU1). |
DxgkDdiDisplayMuxPreSwitchAwayGetPrivateData | Solicite a coleta de quaisquer dados de alternância privados do driver atualmente conectado ao painel (da GPU0). |
DxgkDdiDisplayMuxPreSwitchTo | Chame o driver atualmente não conectado à exibição. Esta chamada indica ao driver que o sistema operacional está planejando alternar a exibição para esta GPU (para GPU1). |
DxgkDdiDisplayMuxSwitchCanceled | Chame para o driver para indicar que a sequência de alternância foi cancelada antes da alternância ser concluída. |
DxgkDdiDisplayMuxPostSwitchAway | A alternância do mux foi concluída e o controlador da GPU0 não está mais conectado à tela. |
DxgkDdiDisplayMuxPostSwitchToPhase1 | A alternância do mux foi concluída e o controlador da GPU1 agora está conectado à tela. Esse driver agora deve executar tarefas da fase 1. |
DxgkDdiDisplayMuxPostSwitchToPhase2 | A alternância do mux foi concluída e o controlador da GPU1 agora está conectado à tela. Esse driver agora deve executar tarefas da fase 2. |
DxgkDdiDisplayMuxUpdateState | Chamado no início do adaptador para retornar ao estado de energia D0 e informar o driver sobre o estado atual do mux. |
Há ações explícitas que o driver precisa concluir em cada estágio. Essas ações são descritas posteriormente neste artigo.
Compartilhamento de dados entre GPU0 e GPU1
Pode haver casos em que uma experiência de usuário melhor pode ser criada quando:
- GPU0 e GPU1 são do mesmo IHV.
- A GPU0 pode passar informações para a GPU1 sobre a configuração de exibição que é oculta ao sistema operacional.
Um blob de dados é descrito por um GUID que o driver da GPU1 pode identificar rapidamente se ele entende o blob de dados. De forma geral, o sistema operacional chama a GPU0 para obter o GUID de blob e os dados antes da alternância e os passa para a GPU1 antes que seja solicitado ao HPD na exibição.
O driver da GPU1 é responsável por:
- Verificando se ele entende o GUID do blob.
- Validando cada elemento de dados no blob para evitar efeitos nocivos de dados malformados no blob.
Interoperabilidade do driver
Se um driver WDDM der suporte a ADS, ele precisará dar suporte ao ADS independentemente do sistema OEM em que ele está sendo executado ou qual é a outra GPU no sistema.
A sequência de alternância
Embora seja tecnicamente possível se afastar de uma GPU quando o driver da GPU for interrompido, esse cenário não tem suporte no momento. Portanto, a comutação só é realizada quando ambas as GPUs têm drivers carregados que dão suporte à troca de DDI.
A sequência a seguir é uma exibição de alto nível de toda a sequência de comutadores quando o painel está ativo, em que GPU0 e GPU1 representam a iGPU e a dGPU, respectivamente. A GPU0 está atualmente conectada ao painel interno via mux, e queremos alternar para a GPU1 gerando a saída para o painel.
- Uma chamada de switch é feita no nível da API.
- O sistema operacional coleta atributos do estado atual do painel interno (HDR, modo, taxa de atualização e assim por diante) e verifica o modo de exibição temporário.
- O sistema operacional desabilita a execução de qualquer topologia de exibição devido a HPDs de qualquer GPU no sistema.
- O sistema operacional chama DxgkDdiDisplayMuxPreSwitchTo do driver da GPU1, passando o nível de brilho atual. O driver deve fazer o seguinte somente se a tampa estiver aberta:
- Ligue o painel.
- Defina o sinal de brilho habilitado.
- Defina o nível de brilho que o sistema operacional passou.
- O sistema operacional desabilita a chamada DxgkDdiQueryConnectionChange na GPU0 para garantir que o HPD da tampa não possa ser processado até depois da alternância do mux.
- O sistema operacional chama o DDI DxgkDdiDisplayMuxPreSwitchAway do driver da GPU0. O driver deve:
- Se a tampa estiver ativa, habilite PSR1 (auto-atualização do painel 1) no painel e verifique se ela não está desabilitada até que o sistema operacional solicite desabilitação posteriormente na sequência.
- Adicione um pacote à lista de alterações de conexão com o ConnectionStatus de DXGK_CONNECTION_CHANGE definido como MonitorStatusDisconnected e MonitorConnect.MonitorConnectFlags.DisplayMuxConnectionChange definido como 1.
- A GPU0 não pode adicionar nenhum pacote de alteração de conexão para o destino da tampa na fila. O bug do sistema operacional verifica se ele faz isso.
- Retorne o tamanho de qualquer blob de dados privado da ADS (GUID e dados) para o sistema operacional. Se o driver da GPU0 falhar nessa chamada, ele precisará garantir que todos os pacotes de status de conexão de ADS colocados na fila sejam removidos antes de retornar.
- Se o driver da GPU0 retornar um tamanho de dados privados diferente de zero, o sistema operacional alocará esse tamanho e o passará para a função de retorno de chamada DxgkDdiDisplayMuxPreSwitchAwayGetPrivateData da GPU0 para obter os dados privados da alternância.
- O sistema operacional chama o método ACPI do mux para alternar de GPU0 para GPU1.
- O sistema operacional permite que DxgkDdiQueryConnectionChange da GPU0 seja chamado novamente.
- O sistema operacional chama DxgkDdiQueryConnectionChanges da GPU0 para processar o pacote de conexão MonitorStatusDisconnected com DisplayMuxConnectionChange definido como 1.
- O sistema operacional chama DxgkddiSettimingsfromvidpn da GPU0 para inativar o caminho da exibição que está sendo alternada. O driver da GPU0 deve:
- Desativar a energia do painel.
- Desabilite o sinal de brilho.
- Parar de enviar o nível de brilho para o mux.
- O sistema operacional processa a saída de exibição. Ele não dispara uma alteração de topologia para evitar alterações de topologia desnecessárias.
- O sistema operacional chama o retorno de chamada DxgkDdiDisplayMuxPostSwitchToPhase1 da GPU1, passando qualquer blob privado de ADS obtido da GPU0. O driver deve:
- Determine se a tampa está aberta ou fechada.
- Adicione o pacote à lista de alterações de conexão com DXGK_CONNECTION_CHANGE:
- MonitorConnect.MonitorConnectFlags.DisplayMuxConnectionChange definido.
- ConnectionStatus será definido como MonitorStatusConnected se a tampa estiver aberta ou MonitorStatusDisconnected se a tampa estiver fechada.
- Se a tampa estiver fechada, desative a energia e o sinal de brilho habilitado para o painel.
- Se o sistema operacional ainda não tiver chamado DxgkDdiQueryAdapterInfo com DXGKQAITYPE_INTEGRATED_DISPLAY_DESCRIPTOR2 para o destino interno da GPU1, ele fará isso. Como resultado desta chamada, o sistema operacional também chama DxgkDdiQueryDeviceDescriptor.
- O sistema operacional chama o DxgkDdiQueryConnectionChange da GPU1 para processar o evento na lista de alterações de conexão. Essa chamada resulta em DxgkDdiQueryDeviceDescriptor sendo acionado para a conexão do novo monitor via HPD.
- O sistema operacional permite exibir alterações de topologia devido a HPDs.
- O sistema operacional processará assíncronamente os pacotes de conexão de GPU0 e GPU1 com DisplayMuxConnectionChange definido como 1.
- Se GPU1 enfileirou MonitorStatusConnected:
- O sistema operacional chama as funções DWM do GPU1 para enumerar modos.
- DxgkddiSettimingsfromvidpn é chamado na GPU1 para ativar o caminho de exibição.
- O DWM renderiza e apresenta o quadro no caminho de exibição na GPU1.
- O sistema operacional aguarda que o primeiro quadro fique visível.
- O sistema operacional chama o retorno de chamada DxgkDdiDisplayMuxPostSwitchToPhase2 da GPU1, em que o driver deve desativar o PSR1 para a exibição se MonitorStatusConnected tiver sido enfileirado pela GPU1; caso contrário, ele não deve fazer nada.
- O sistema operacional chama o DxgkDdiDisplayMuxPreSwitchAwayda GPU0. Embora não haja ações esperadas do driver, essa chamada é útil para qualquer limpeza de driver ou manutenção de registros relacionadas à alternância.
- O sistema operacional coleta os atributos do estado atual do painel interno. Se o estado do painel for diferente do que foi salvo anteriormente, o sistema operacional disparará a telemetria.
Essa sequência de troca é a mesma para iGPU->dGPU e dGPU->iGPU. Pode haver casos em que seja necessário alternar o mux quando o painel estiver inativo. Nesse caso, essa sequência não é necessária e o sistema operacional pode simplesmente chamar métodos ACPI no mux para alternar.
A maioria do sistema operacional não sabe que o driver está no modo PSR. Como resultado, o driver ainda precisa gerar sincronizações de Vsync, reportar conclusões de flip, e assim por diante, mesmo que o usuário não veja esses acontecimentos.
Processo de recuperação
Se ocorrer uma falha durante qualquer estágio da sequência de alternância, a seguinte limpeza será realizada:
- O sistema operacional chamará DxgkDdiDisplayMuxSwitchCanceled se o DxgkDdiDisplayMuxPreSwitchAway da GPU0 tiver sido chamado, mas DxgkDisplayMuxPostSwitchAway não tiver sido chamado.
- O sistema operacional chamará DxgkDdiDisplayMuxSwitchCanceled se o DxgkDdiDisplayMuxPreSwitchTo da GPU1 tiver sido chamado, mas DxgkDdiDisplayMuxPostSwitchToPhase2 não tiver sido chamado.
- O sistema operacional habilita novamente as alterações de topologia de exibição se elas estiverem desabilitadas.
- O sistema operacional reativará a chamada de DxgkDdiQueryConnectionChange na GPU0, se essa chamada estiver desabilitada.
- O sistema operacional verifica a conectividade da tampa na GPU à qual a tampa está conectada.
- O sistema operacional dispara uma redefinição da configuração de exibição definida (SDC). O driver que tem o painel conectado por meio do mux (retornado de DxgkDdiDisplayMuxSwitchCanceled) precisa garantir que o PSR esteja desabilitado.
Eventos incomuns que podem acontecer durante a transição
O usuário externo conecta ou desconecta um monitor
Como parte da sequência de troca, desabilitamos o processamento de eventos HPD pelo sistema operacional. Dessa forma, qualquer HPD é enfileirado e processado junto com a tampa, chegando em uma operação atômica.
Outro aplicativo chama SDC durante a alternância
Enquanto a mudança está em processo, as chamadas para SDC são bloqueadas e serão executadas depois que a mudança for processada.
O driver é desabilitado durante a alternância
Quando um driver é interrompido, as chamadas na sequência de alternância falham e a sequência de recuperação é ativada. A seção PnpStop também detalha como garante que a tela fique sempre visível.
Cenários de fechamento da tampa
O driver geralmente pode usar qualquer uma das seguintes abordagens para detectar eventos de abertura/fechamento da tampa:
- Rastreie o estado da tampa em DxgkDdiNotifyAcpiEvent(DxgkPowerStateEvent, PO_CB_LID_SWITCH_STATE)
- Rastreie o estado da tampa no retorno de chamada PoRegisterPowerSettingCallback(GUID_LIDSWITCH_STATE_CHANGE).
- Uma maneira diferente, dependente de plataforma.
No entanto, para o WDDM em geral, os drivers precisam usar a abordagem DxgkDdiNotifyAcpiEvent, pois permite que o estado do Dxgkrnl e o estado do driver estejam sincronizados. Considerando que tanto a iGPU quanto a dGPU podem ser a GPU1 em uma sequência de alternância, faz sentido que todos os drivers de ADS monitorem o estado da tampa, mesmo quando ela é desviada para outro dispositivo.
Depois que o sistema operacional processa o evento DisplayMuxConnectionChange da GPU0, ele considera que a GPU0 não possui mais o estado da tampa e, portanto, a GPU0 não pode relatar mais nenhum pacote de status de conexão para esse alvo até que o estado da tampa seja restaurado. Se a GPU0 fizer isso, o sistema operacional verificará o bug. Depois que o sistema operacional processa o DisplayMuxConnectionChange da GPU1, ele considera a GPU1 como a responsável pelo estado da tampa. Qualquer evento de abertura ou fechamento da tampa pode ser ignorado entre esses dois eventos, pois espera-se que a GPU1 conheça o estado da tampa e relate corretamente o pacote DisplayMuxConnectionChange.
Quando o sistema operacional considera que o driver é proprietário do painel
A tabela a seguir descreve os estágios de sequência nos quais o sistema operacional considera uma GPU como proprietária do painel. A GPU proprietária pode relatar alterações de conectividade usando a sequência de alternância. Os números de etapa são da sequência de comutação descrita anteriormente.
Fase de | Fase para | qual GPU controla o painel |
---|---|---|
Antes da alternância | Etapa 5 | GPU0 |
Etapa 6 | Etapa 12 | Sem GPU |
Etapa 13 | Após a alternância | GPU1 |
O bug do sistema operacional verifica se há um pacote de alteração de conexão na fila do driver para um destino multiplexado quando a GPU não controla a tela.
Controle da atualização automática do painel (PSR)
O recurso ADS usa PSR para evitar falhas durante a transição. Especificamente, o PSR1 (modo de atualização em tela inteira) é usado para que GPU0 e GPU1 não precisem negociar qual modo de PSR usar.
Mesmo dentro do PSR1, há recursos opcionais que o painel precisa suportar.
Capacidade do coletor | Detalhes | Coletor exposto por meio de |
---|---|---|
Versão de DPCD e eDP | Exponha o eDP v1.3 ou posterior. | DPCD |
Funcionalidade e versão do PSR | O coletor deve dar suporte à versão 1. | DPCD 00070h bit 7:0 |
Dar suporte ao SDP do VSC para transmitir o estado do PSR | Somente para PSR, o coletor deve suportar pelo menos a revisão 2 com até 8 bytes válidos para transmitir o estado PSR e o valor CRC. | DPCD 170 |
O coletor deve relatar corretamente o estado relacionado ao PSR | O coletor deve expor o estado; por exemplo, erro de CRC de link, erro de armazenamento de RFB, status de atualização automática do dispositivo do coletor, contagem máxima de quadros ressincronizados, última latência de sincronização real no coletor e SDP PSR recebido pela última vez. | DPCD 2008h, 2009h, 200Ah deve refletir o estado correto do coletor. |
Quando a GPU1 executa o treinamento de link como parte de uma chamada DxgkddiSettimingsfromvidpn do sistema operacional, o driver não conhece a configuração de pistas e largura de banda de DP usada pela GPU0, e precisa realizar uma sequência completa de treinamento de link em vez de um treinamento de link rápido. O sistema operacional não vai negociar nenhuma política de PSR entre as GPUs, portanto, o painel precisa dar suporte a todas as versões e recursos do PSR que as GPUs usarão. Por exemplo, o painel tem que dar suporte a um cenário em que GPU0 pode usar PSR2 com alguns recursos definidos e então PSR1 será usado para a troca e então GPU1 pode usar PSR2 com um conjunto diferente de recursos.
Garantir que o painel permaneça no PSR durante a transição
Quando GPU1 define um modo no painel, não há garantia de que os atributos de link definidos por GPU1 enquanto o painel estiver no PSR corresponderão ao modo de entrada PSR. Por exemplo, a taxa de atualização ou o tamanho ativo podem ser alterados. Atualmente, o DP ou outros padrões do setor não têm uma maneira de o painel relatar que consegue manter o painel no PSR enquanto os atributos de link são alterados. A longo prazo, queremos trabalhar para que essa funcionalidade seja adicionada à especificação de DP. Até que isso aconteça, para um sistema habilitado para ADS, o OEM precisa escolher uma combinação TCon/Painel/Mux que possa permanecer no PSR enquanto os atributos de link (por exemplo, taxa de atualização, tamanho ativo) são alterados entre quaisquer duas combinações expostas no EDID. Essa abordagem garante que o PSR permaneça ativo durante a mudança.
Para que o teste ADS HLK verifique se o PSR foi mantido durante o processo de troca, é necessário que o sistema operacional possa identificar se o PSR não estava ativo após a GPU1 testar esse modo. Um desafio é que não está definido como um painel reagirá se não puder suportar PSR durante o treinamento de link.
Como parte de DxgkDdiDisplayMuxPostSwitchToPhase2, o driver retorna um valor booleano em pWasPanelInPSR para informar ao sistema operacional se detectou que o painel não estava no PSR.
EDID do painel interno
Para que o sistema operacional forneça o comportamento esperado ao selecionar modos de exibição e topologias com monitores diferentes conectados, ambas as GPUs são necessárias para relatar o EDID/DisplayId para a exibição interna. Esse requisito garante que o banco de dados CCD que armazena modos de exibição e topologias escolha essas mesmas configurações, independentemente de qual GPU esteja controlando a exibição interna.
O EDID que os drivers relatam para o sistema operacional deve ser o EDID que é consultado do painel usando o comando auxiliar sem nenhuma modificação.
Atualmente, o sistema operacional chamará DxgkDdiQueryAdapterInfo (DXGKQAITYPE_INTEGRATED_DISPLAY_DESCRIPTOR2) ao iniciar um driver que indica um painel interno. Se o mux for alterado para longe desse destino integrado, o driver não poderá se comunicar com o painel para coletar as informações necessárias. A solução é que, quando um driver é iniciado e o mux é desligado do destino interno, o sistema operacional atrasa a chamada de DxgkDdiQueryAdapterInfo (DXGKQAITYPE_INTEGRATED_DISPLAY_DESCRIPTOR2) até que o mux seja alternado pela primeira vez para o destino interno.
Como o sistema operacional decide se o recurso ADS está ativado em um sistema e se a troca é permitida
O sistema operacional executa a lista de verificações a seguir para determinar se o ADS está disponível em um sistema. Todas as verificações precisam ser verdadeiras para que o ADS tenha suporte.
- Há uma GPU marcada como híbrida integrada (DXGK_DRIVERCAPS. HybridIntegrated) que:
- O driver implementa a interface DXGK_DISPLAYMUX_INTERFACE.
- Verifica o nível de suporte do ADS retornado de DxgkDdiDisplayMuxGetDriverSupportLevel.
- Verifica o status de runtime da ADS de DxgkDdiDisplayMuxGetRuntimeStatus.
- O driver precisa dar suporte aos seguintes DDIs:
- Expõe um destino para o monitor interno com DXGK_CHILD_CAPABILITIES.HpdAwareness definido como HpdAwarenessInterruptible e DXGK_CHILD_DESCRIPTOR.ChildDeviceType definido como TypeIntegratedDisplay.
- No namespace ACPI para o monitor interno, há um método DMID que retorna com êxito um nome ACPI do mux.
- O dispositivo ACPI de GPU tem um método ACPI '_DEP' que retorna o nome correto do mux ACPI como uma dependência.
- Há uma GPU marcada como híbrida discreta (DXGK_DRIVERCAPS. HybridDiscrete) que:
- O driver implementa a interface DXGK_DISPLAYMUX_INTERFACE.
- Verifica o nível de suporte do ADS retornado de DxgkDdiDisplayMuxGetDriverSupportLevel.
- O driver precisa dar suporte aos seguintes DDIs:
- Expõe um destino para o monitor interno com DXGK_CHILD_CAPABILITIES.HpdAwareness definido como HpdAwarenessInterruptible e DXGK_CHILD_DESCRIPTOR.ChildDeviceType definido como TypeIntegratedDisplay.
- No namespace ACPI para o monitor interno, há um método DMID que retorna com êxito um nome ACPI do mux.
- O dispositivo ACPI da GPU tem um método ACPI '_DEP' que retorna o nome correto do ACPI do mux como uma dependência.
- O nome ACPI do mux retornado pelo método ACPI DMID das etapas 1 e 2 corresponde.
- O dispositivo ACPI mux tem métodos ACPI DMQU, DMCF e DMSL.
- O método DMQU do ACPI do mux retornou o nome ACPI de uma das GPUs como destino do painel interno.
- Atualmente, o ADS só dá suporte a sistemas com um único painel interno.
- Ou:
- GPU0, GPU1 e Mux ACPI todos relatam o suporte completo ao ADS.
- GPU0, GPU1 e Mux ACPI relatam suporte a ADS, experimental ou completo, e a chave do registro EnableMDMExperimentalFeature está definida.
As condições 1 e 2 implicam que ambos os adaptadores precisam ser iniciados para que o mux seja alternado.
Controlando a qualidade da implementação de funcionalidades ADS
Para que o ADS forneça uma boa experiência de usuário, todos os seguintes componentes precisam trabalhar juntos perfeitamente:
- A funcionalidade de mux de exibição do sistema operacional.
- Os métodos ACPI da plataforma para a alternância de mux.
- A funcionalidade de alternância de exibição via mux nos drivers iGPU e dGPU.
Para ajudar os IHV/OEMs a ter código de qualidade que não está pronto para produção em versões, eles podem expor qualquer um dos seguintes níveis de suporte para ADS:
- Sem suporte: o driver não dá suporte a nenhuma funcionalidade ADS.
- Suporte ao desenvolvimento: o driver dá suporte ao ADS, mas a implementação do driver ainda está em desenvolvimento e não deve ser usada além dessa finalidade.
- Suporte experimental: o driver oferece suporte para ADS, mas ainda não está em qualidade de produção. O sistema operacional não habilitará o ADS por padrão, mas pode ser configurado para habilitá-lo.
- Suporte completo: o driver dá suporte a ADS na qualidade do navio. O sistema operacional considera que o driver dá suporte a ADS.
Exibir atributos que devem permanecer os mesmos após uma troca de exibição
Um comutador de exibição não deve alterar nenhum dos seguintes atributos de exibição:
- Resolução da área de trabalho
- Caminho do VidPn (incluindo o modo de origem do VidPn, modo de destino do VidPn, dimensionamento e assim por diante)
- DPI
- Configuração de luz noturna
- Gama
- Topologia de exibição
- HDR ativado/desativado
- Nível de branco SDR
- Perfil de cor
- Tipo OPM de destino do monitor
- Brilho de exibição
Correspondência de limites da GPU para uma experiência de alternância perfeita
Para proporcionar ao usuário uma experiência de alternância perfeita, a configuração da tela deve permanecer a mesma após a troca como era antes da troca. Há certos recursos de GPU que ambas as GPUs precisam do mesmo suporte para alcançar esse comportamento. Por exemplo, se uma GPU der suporte ao HDR e a outra não, então uma mudança enquanto o HDR estiver habilitado em uma GPU não seria perfeita.
A tabela a seguir lista recursos e funcionalidades de exibição de GPU e descreve os requisitos de alinhamento entre as duas GPUs.
Recurso | GPUs são necessárias para garantir suporte contínuo |
---|---|
HDR | Se o painel der suporte ao HDR, ambas as GPUs precisarão dar suporte ao HDR fp16 ou não dar suporte ao HDR. |
Cursor de hardware | Não. O sistema operacional se adapta a diferentes recursos de cursor sem interrupção visível para o usuário. |
MPO | Não. O sistema operacional se adapta a diferentes recursos de MPO sem interrupção visível para o usuário. |
PSR | Ambas as GPUs precisam dar suporte a esse recurso. |
EDID/DisplayID | Ambas as GPUs precisam expor o mesmo EDID/DisplayId. |
Limites de brilho | Ambas as GPUs precisam oferecer suporte à mesma interface de brilho e aos mesmos limites de brilho. |
Níveis de brilho | Ambas as GPUs precisam expor os mesmos níveis de brilho e intervalos. |
Resolução | Ambas as GPUs precisam dar suporte aos mesmos modos de origem e à resolução de destino. |
Taxas de atualização | Consulte Problema se a GPU1 não der suporte à taxa de atualização em que a GPU0 está executando o painel para obter detalhes. |
Taxa de Atualização Dinâmica | Não. O sistema operacional se adapta ao suporte de taxa de atualização virtual diferente. |
Taxa de atualização variável | Consulte Problema se a GPU1 não der suporte à taxa de atualização em que a GPU0 está executando o painel para obter detalhes. |
Problema se a GPU1 não dá suporte à taxa de atualização em que a GPU0 está operando o painel
Se GPU1 não oferecer suporte ao mesmo modo que GPU0, o modo reduzido provavelmente será armazenado no banco de dados de topologia de exibição. Em seguida, quando o sistema voltar para GPU0, o modo reduzido será definido. Por exemplo, se GPU0 der suporte a 120Hz, mas GPU1 só oferecer suporte a 60Hz, a seguinte sequência poderá acontecer:
- O sistema está configurado para que a GPU0 esteja controlando a exibição e o modo seja de 120Hz.
- O usuário alterna manualmente para GPU1.
- O banco de dados de topologia de exibição tem 120Hz armazenados para exibição, mas GPU1 não dá suporte a ele, portanto, o sistema operacional escolhe 60Hz.
- 60Hz é definido e armazenado no banco de dados de topologia de exibição.
- O usuário alterna manualmente de volta para GPU0.
- O banco de dados de topologia de exibição lê 60 Hz no banco de dados.
Para fornecer a melhor experiência, um OEM deve selecionar um iGPU e dGPU que dão suporte à taxa máxima de atualização do painel interno. Se isso não for possível e uma GPU não puder dar suporte à taxa de atualização máxima do painel, a GPU que dá suporte à taxa de atualização do painel deverá dar suporte ao recurso DRR (Taxa de Atualização Dinâmica) do Windows com intervalos que incluem:
- A taxa de atualização mais alta da outra GPU.
- A taxa de atualização mais alta do painel interno.
Por exemplo, se o painel puder dar suporte a 300Hz e iGPU só puder dar suporte a 60Hz, a dGPU terá que dar suporte a VRR com um intervalo de pelo menos 60Hz a 300Hz.
Para resumir, o requisito da ADS para a taxa de atualização é:
- IGPU e dGPU dão suporte à taxa máxima de atualização do painel interno.
- A GPU que dá suporte à taxa máxima de atualização do painel interno precisa suportar o DRR com um intervalo de taxa de atualização que vai desde a taxa máxima que a outra GPU pode suportar até a taxa máxima de atualização do painel interno.
HDR e Dolby Vision
O sistema operacional define na GPU1 o mesmo estado HDR/Dolby Vision no painel interno após a troca que estava no painel interno na GPU0 antes da troca. O usuário não deve notar nenhuma alteração.
Luz noturna
O Nightlight é implementado por meio de DDIs gama ou matriz de cores do WDDM. Em ambos os casos, o sistema operacional define os mesmos níveis de luz noturna através da GPU1 após a mudança, assim como fez com a GPU0 antes da mudança.
Perfil de cor
O sistema operacional aplica o mesmo perfil de cor ao painel após a mudança, que foi aplicado antes da mudança.
Exibindo a tela de verificação de bugs
Atualmente, o sistema operacional dá suporte à exibição da tela de verificação de bugs em dispositivos não POST. Quando ocorre uma verificação de bugs, o sistema operacional:
- Não alterna o mux.
- Usa o suporte atual do sistema operacional para exibir a tela de verificação de bugs.
Ao avaliar possíveis destinos para exibir a verificação de bugs, o sistema operacional ignora todos os destinos conectados a um mux que é alternado para um destino diferente.
Há um pequeno período de tempo em que o HPD longe da GPU0 foi processado, mas o HPD da GPU1 ainda não está totalmente processado. Se ocorrer uma verificação de erro durante esse período, o usuário não verá a verificação. Se ocorrer uma verificação de bugs no pequeno período em que o PSR ainda estiver habilitado, o driver que controla a exibição deverá garantir que o painel não esteja no modo PSR quando o sistema operacional chamar DxgkDdiSystemDisplayEnable.
Algoritmo de brilho adaptativo ao conteúdo
Em um mundo ideal, o algoritmo adaptável de conteúdo usado por ambas as GPUs deve produzir o mesmo efeito. No entanto, provavelmente o mesmo efeito não ocorrerá, e o usuário poderá perceber uma diferença quando o painel interno for trocado.
Dados de brilho
Para garantir que o usuário não observe uma alteração de brilho devido à opção, todos os atributos de brilho expostos por GPU0 e GPU1 precisam ser idênticos. Após a troca, esse requisito garante que qualquer nível de brilho antes da troca no GPU0 será suportado no GPU1.
Para fazer isso, os drivers para GPU0 e GPU1 precisam:
- Use a mesma interface de brilho, DXGK_BRIGHTNESS_INTERFACE_2 ou DXGK_BRIGHTNESS_INTERFACE_3, em que a versão 3 é altamente recomendada.
- Para a interface de brilho v3, os dois drivers devem oferecer brilho medido em nits ou brilho não calibrado.
- Para a interface de brilho v2, os dois drivers devem retornar exatamente os mesmos níveis possíveis de brilho do GetPossibleBrightness.
- Para a interface de brilho v3, os dois drivers precisam retornar exatamente as mesmas faixas; isto é, cada driver deve retornar estruturas idênticas DXGK_BRIGHTNESS_GET_NIT_RANGES_OUT do GetNitRanges.
- As tabelas internas que o driver usa para converter níveis de brilho fornecidos pelo sistema operacional em configurações específicas do painel devem ser as mesmas.
Na maioria dos laptops, o driver de GPU obtém alguns ou todos esses dados de nível de brilho da plataforma de maneira diferente do padrão. Esperamos que essa troca de dados de plataforma para GPU possa ter que ser expandida para atingir esses requisitos.
Embora a interface de brilho seja consultada no momento da inicialização do adaptador, o sistema operacional não chamará nenhum dos DDIs da interface de brilho até que o painel interno seja detectado como HPD. HPD ocorre depois que o mux é transferido para a GPU, permitindo que o driver acesse o EDID do painel interno nesse momento.
Sabemos que existem métodos específicos dos IHVs para que o driver defina o brilho de painéis que não suportam PWM. No entanto, esse método adiciona complicação para o TCon, pois talvez seja preciso dar suporte para obter o brilho de uma maneira diferente específica do IHV, dependendo de qual GPU está conectada por meio do mux.
Configuração de inicialização do mux
O firmware do sistema controla qual GPU está conectada ao painel interno na hora de início do sistema. O sistema operacional armazena qual GPU foi a última no controle do painel. Em seguida, durante a sequência de inicialização, o sistema operacional alterna o mux, se necessário, para que a GPU correta esteja controlando o painel.
Para preservar qualquer imagem de inicialização quando uma alternância de mux é necessária, a opção é executada somente quando:
- Ambas as GPUs são ativadas.
- O sistema operacional passou de ter gráficos de inicialização controlando a saída para o DWM/shell controlando a saída.
Assim, a alternância ocorre após a chamada de DxgkddiSettimingsfromvidpn na GPU que controla o painel interno, e o usuário verá a tela congelada durante o tempo em que o painel estiver em PSR durante a alternância.
Fornecendo informações do mux para o driver
Esse recurso foi intencionalmente projetado para que o sistema operacional chame o driver para fornecer as informações em vez de fornecer uma função de retorno que pode ser chamada pelo driver a qualquer momento. Esse método evita que o driver fique confuso se consultar o estado do sistema operacional durante uma sequência de comutação.
O sistema operacional chama o DDI DxgkDdiDisplayMuxUpdateState do driver para fornecer ao driver o estado atual do mux nos seguintes casos:
- Na inicialização do driver, o que permite que o driver evite sequências de sondagem desnecessárias quando o painel não estiver conectado.
- Ao retornar de Dxpara D0. Ao retornar de alguns estados de energia (por exemplo, hibernar), o firmware pode ter que redefinir o mux; portanto, o driver não sabe o estado.
Esses casos, juntamente com os DDIs normais envolvidos na sequência de troca, garantem que o driver possa determinar de que maneira um mux é alternado em qualquer momento em que a GPU está ativa.
Na primeira versão desse recurso, não há planos para alternar o mux quando o painel interno não estiver ativo, portanto, todas as opções passarão pela mesma sequência.
Hora de início do adaptador
Quando um driver é iniciado, ele precisa responder às solicitações de sondagem do sistema operacional. O driver pode tentar descobrir se o mux é alternado para eles tentando se comunicar, mas isso pode ser demorado ou não confiável. Como parte da sequência de inicialização da GPU, o sistema operacional chama o DDI DxgkDdiDisplayMuxUpdateState para cada destino conectado a um mux e indica se ele foi alternado para esse destino.
Quando um driver é iniciado, ele precisa responder às solicitações de sondagem do sistema operacional. O driver pode tentar descobrir se o mux está alternado para sua GPU comunicando-se com o sistema operacional, mas isso pode ser demorado ou não confiável.
Em vez disso, como parte da sequência de início da GPU, o sistema operacional chama DxgkDdiDisplayMuxUpdateState para cada alvo conectado a um mux e indica se o mux está comutado para esse alvo. O sistema operacional informa ao driver se o mux mudou para a GPU do driver antes de acionar os DDIs de sondagem.
O driver da ADS continua a relatar o painel interno para o sistema operacional da mesma maneira, com o sistema operacional chamando DxgkDdiQueryAdapterInfo (DXGKQAITYPE_INTEGRATED_DISPLAY_DESCRIPTOR2) para consultar os detalhes do painel interno. O driver precisa garantir que DXGK_CHILD_CAPABILITIES.HpdAwareness esteja definido como HpdAwarenessInterruptible para qualquer destino conectado a um mux.
Transição de D0
Sempre que uma GPU com um mux conectado é retornada ao estado ligado a partir de um estado de baixo consumo de energia, o sistema operacional chama DxgkDdiDisplayMuxUpdateState para informar ao driver se o mux está conectado ao destino ou alternado para a outra GPU.
Sequência de inicialização
A sequência de inicialização a seguir realça aspectos específicos do ADS. Nesta sequência, o sistema é inicializado com:
- O iGPU conectado ao mux.
- A última configuração do usuário antes da reinicialização foi que o mux estava conectado ao dGPU.
A sequência de inicialização é assíncrona por natureza, portanto, essa sequência é apenas para fins de exemplo.
- O sistema é habilitado e o iGPU está conectado ao painel por meio do mux.
- O iGPU exibe a tela de inicialização no painel.
- O Windows carrega e exibe a animação de inicialização na tampa interna.
- Devido a _DEP em iGPU e dGPU, o driver do mux do sistema operacional é iniciado antes de qualquer driver de GPU. O driver mux usa chamadas ACPI para garantir que o mux esteja configurado corretamente. O driver do mux verifica se a implementação do ACPI mux satisfaz os requisitos da ADS.
- Dxgkrnl chama DxgkDdiAddDevice para iGPU.
- Dxgkrnl chama DxgkDdiQueryInterface(DXGK_DISPLAYMUX_INTERFACE) para o iGPU. Mesmo que o sistema atual não seja compatível com ADS, o driver retornará sua interface se ele for compatível com ADS.
- Dxgkrnl chama DxgkDdiDisplayMuxGetDriverSupportLevel para obter o nível de suporte da ADS do driver.
- Dxgkrnl chama DxgkDdiDisplayMuxReportPresence(TRUE) para que o iGPU saiba que o sistema tem um ADS mux funcional nele.
- Dxgkrnl chama DxgkDdiStartDevice. O driver iGPU retorna o número de filhos, incluindo o destino VidPn para o painel interno.
- Dxgkrnl chama DxgkDdiDisplayMuxGetRuntimeStatus para verificar se o iGPU suporta ADS e se o driver obteve todas as informações necessárias do sistema.
- Dxgkrnl chama DxgkDdiQueryChildStatus para cada filho exposto pelo iGPU.
- Depois que Dxgkrnl encontra o filho do iGPU que está conectado ao mux, ele chamará DxgkDdiDisplayMuxUpdateState para informar o iGPU de que o mux está conectado a esse destino.
- Como o iGPU expôs um monitor interno conectado, Dxgkrnl define um modo no iGPU usando DxgkddiSettimingsfromvidpn.
- Dxgkrnl inicia o driver dGPU e repete as etapas de 5 a 12 para o dGPU.
- Dxgkrnl detecta que o iGPU, o dGPU e o mux estão configurados corretamente, portanto, ele cria um par mux e as propriedades da Interface do Dispositivo Pnp para o par mux.
- Dxgkrnl lê a última configuração do mux do registro. Como a última configuração era dGPU, Dxgkrnl agora inicia a sequência de comutação do mux descrita anteriormente para direcionar o mux para o dGPU.
Drivers de painel
Os drivers de painel de monitor são carregados com base na ID de hardware Pnp gerada a partir do EDID. Dado que o EDID permanece o mesmo, o driver de painel é carregado quando qualquer GPU está controlando o painel interno. Os dois drivers vão expor a mesma funcionalidade de brilho. Portanto, o carregamento não deve causar nenhum problema e o driver do painel não precisará saber qual GPU está no controle do mux.
Identificar os alvos que um mux controla
Quando o sistema operacional inicia o driver, ele chama o DxgkDdiQueryChildRelations do driver para consultar informações sobre os filhos relatados. O driver preenche a estrutura de DXGK_CHILD_DESCRIPTOR para cada filho. O membro AcpiUid é definido como o valor retornado pelo método _ADR sob esse dispositivo filho no namespace ACPI, o que permite que o sistema operacional localize o nome ACPI para esse dispositivo filho.
Para a ADS, definimos um método DMID de ACPI que precisa estar sob o namespace ACPI filho para o destino. Esse método DMID retorna o nome ACPI do dispositivo mux. Isso permite que o sistema operacional localize o nome da ACPI do mux para o destino.
Pnp interrompendo o adaptador que está escaneando para um destino
O sistema operacional não alterna o mux quando a GPU que está transmitindo para o painel interno é parada. Os cenários a seguir passam pelos diferentes casos quando uma GPU é interrompida.
GPU0 é o POST. Ele está conectado ao painel interno e está parado.
Nesse caso, o BDD (Driver de Exibição Básico) assume o modo ativo atualmente na GPU0 e continua atualizando a tela.
GPU0 é o POST, mas GPU1 está conectada ao painel interno. GPU0 está parada.
Devido ao design atual do sistema operacional, o BDD é iniciado na GPU0, o que faz com que um monitor fantasma seja detectado e apareça no CPL de exibição.
GPU1 não é o POST e está conectada ao painel interno. GPU1 está parada.
Devido ao design atual do sistema operacional, o BDD não é iniciado na GPU1 e, portanto, o usuário não poderá ver o painel.
GPU1 não é o POST. A GPU0 está conectada ao painel interno e a GPU1 é interrompida.
Nenhuma mudança ocorre e nada acontece. GPU0 continua a ser exibida no painel.
Os cenários 2 e 3 criam uma experiência ruim para o usuário. O recurso ADS altera o comportamento para corrigir esses dois casos.
GPUs plugin/externas não são suportadas
Não acreditamos que haja qualquer caso de uso para esse recurso com GPUs de plug-in.
O ADS é limitado apenas a painéis internos únicos
A primeira versão do ADS dá suporte apenas a painéis internos únicos. No entanto, o recurso é projetado para suportar o uso de telas externas e várias telas internas (quando compatível com o sistema operacional) no futuro com alterações mínimas no driver.
Alterações atuais da política do adaptador POST
O sistema operacional anteriormente tinha algumas políticas relacionadas ao adaptador POST. Por exemplo, o adaptador POST era o único adaptador que permitia expor destinos internos. Esses tipos de restrições são removidos do sistema operacional com a introdução do ADS.
Desabilitar efeitos visuais de chegada do monitor
Quando um monitor está conectado no Windows 11, o shell/DWM tem uma sequência de animação. Essa animação está desativada em cenários de mudança de exibição.
Desabilitar bonk Pnp
Quando um monitor é adicionado ou removido, o sistema Pnp reproduz um som 'bonk' para notificar o usuário. Esse "bonk" está desabilitado em cenários de alternância de exibição.
Notificações do aplicativo
Quando ocorre uma alternância de exibição, o sistema passa pelos caminhos regulares de código de remoção e chegada do HPD. Portanto, todas as notificações normais do aplicativo são acionadas normalmente; por exemplo, a notificação Pnp para HPD em saída e HPD em entrada, e as mensagens da janela WM_DISPLAYCHANGE.
API para alternância de comutador
O plano é ter uma API pública para que o sistema operacional e o painel de controle IHV possam disparar a opção.
Exibir APIs relacionadas e comportamento do Win+P
Considerando que o painel interno só está conectado a uma única GPU, as APIs de exibição funcionam conforme o esperado junto com a funcionalidade do Win+P.
Teste de HLK
Se um driver de GPU ou firmware ACPI relatar suporte completo ao ADS, ele precisará passar nos testes ADS HLK em um sistema habilitado para ADS.
Painel interno do HPDing da GPU quando o mux é desviado dessa GPU
O sistema operacional dispara uma verificação de bugs quando um painel interno é relatado como conectado de um driver quando esse mux está atualmente desligado desse driver.
Transição de AC/DC
Para a primeira versão do recurso ADS, o sistema operacional não armazenará uma configuração de mux de AC vs DC e não disparará uma alternância de mux em uma transição de AC <para> DC.
Transições de energia do sistema
A preocupação principal com as transições de energia é quando o firmware redefine o estado do mux (por exemplo, estado de hibernação) e, ao retomar a energia, o mux não é alternado para o painel no qual estava antes da transição de energia.
A abordagem inicial era reconfigurar o mux para o dGPU após ativar tanto o iGPU quanto o dGPU. O problema com essa abordagem é que, dependendo de diferentes eventos assíncronos, o resultado pode ser várias alterações de modo.
A abordagem atualizada para ajudar a simplificar a experiência do usuário é que o sistema alterne o mux de volta para o destino esperado enquanto o iGPU e o dGPU estão dormindo, evitando assim várias alterações de modo.
Sequência de transição de energia
O exemplo a seguir descreve uma transição de energia hibernada em um sistema de ADS.
- O sistema é configurado com mux conectado à dGPU.
- O sistema entra em hibernação.
- A iGPU e a dGPU são transferidas para a potência D3.
- O sistema é desligado.
- Poderes do usuário no sistema.
- O firmware configura o mux para o iGPU e a sequência de inicialização da exibição do iGPU no painel interno.
- Dxgkrnl lê a última configuração do mux (dGPU nesse caso) e a compara à posição atual do mux usando ACPI (iGPU, nesse caso). Dxgkrnl chama ACPI para alternar o mux para a dGPU.
- Dxgkrnl faz a transição da iGPU para D0 e, em seguida, chama a funçãoDxgkDdiDisplayMuxUpdateState da iGPU para informar ao driver que o mux não está conectado à iGPU.
- Dxgkrnl faz a transição da dGPU para D0 e, em seguida, chama a função DxgkDdiDisplayMuxUpdateState da dGPU para informar ao driver que o mux está conectado à iGPU.
- Dxgkrnl define um modo na dGPU.
Sistemas All In One (AIO)
Qualquer sistema AIO que deseje dar suporte para ADS deve ter o painel interno exposto como um tipo de destino interno nas duas GPUs.
Dispositivo ACPI do mux
O OEM é responsável por adicionar o dispositivo mux no namespace acPI e fornecer os métodos necessários para operar o mux.
O driver de GPU nunca deve chamar os métodos ACPI do mux porque o dispositivo mux pode estar localizado em qualquer lugar na árvore ACPI. A recomendação é localizar o mux no antecessor compartilhado mais próximo das duas GPUs.
Os dispositivos mux atuais só dão suporte a duas entradas e não esperamos que os muxes futuros ofereçam suporte a mais do que isso, portanto, o design pode assumir duas entradas e uma única saída para cada mux.
O dispositivo mux nunca pode ser interrompido enquanto o sistema está em execução. É um dispositivo de sistema oculto.
Métodos ACPI do dispositivo mux
Somente a pilha de driver de um dispositivo ACPI pode chamar métodos ACPI para avaliação no dispositivo. Portanto, para chamar métodos de dispositivo mux para alternar o mux, o sistema operacional precisa ter um driver carregado para o dispositivo mux. Por esse motivo, o sistema operacional agora fornece um driver de mux de exibição como o driver para todos os multiplexadores de alternância de exibição.
Um dispositivo mux é necessário para ter os seguintes métodos:
- _HID identifica o dispositivo mux por ID de hardware. Reservamos "MSFT0005" para o mux de exibição ACPI.
- DMQU (Consulta de mux de exibição) retorna o estado atual do mux.
- O DMCF (Display Mux Configure) configura o mux.
Método _HID (ID de hardware)
Argumentos:
Nenhum
Retornos:
Uma cadeia de caracteres ASCII que contém a ID de hardware, que é "MSFT0005".
Método DMQU (Consulta do mux de exibição)
Em uma versão futura, esperamos adicionar informações adicionais à consulta. Para habilitar consultas adicionais no futuro, Arg0 é usado para indicar o tipo de consulta. Se o método DMQU
não entender um tipo de consulta, ele deverá falhar no método como sem suporte.
Argumentos:
Arg0: um inteiro que especifica o tipo de consulta. A tabela a seguir lista os valores de tipo de consulta e seus significados.
Valor do tipo de consulta | Significado |
---|---|
1 | Consultar o estado atual de alternância |
2 | Consultar o nível de suporte da ADS no mux |
3 | Consultar o primeiro filho de GPU ao qual o mux está conectado |
4 | Consultar o segundo filho de GPU ao qual o mux está conectado |
Retornos:
Se o método entender o tipo de consulta especificado, ele deverá retornar os dados apropriados conforme descrito na tabela a seguir. Se o método não entender o tipo de consulta especificado, ele deverá retornar uma cadeia de caracteres vazia.
Valor do tipo de consulta | Retornar dados |
---|---|
1 | Cadeia de caracteres ASCII que contém o nome ACPI do dispositivo filho da GPU para o qual o mux está atualmente comutado. |
2 | Inteiro que representa o nível de suporte da ADS. Consulte a próxima tabela para obter detalhes. |
3 | Cadeia de caracteres ASCII que contém o nome ACPI do primeiro dispositivo filho da GPU ao qual o mux se conectou. |
4 | Cadeia de caracteres ASCII que contém o nome ACPI do segundo dispositivo filho da GPU ao qual o mux se conectou. |
A tabela a seguir lista os valores de nível de suporte do ADS e seus significados quando o tipo de consulta é 2.
Dados retornados | Significado |
---|---|
0 | Sem suporte |
1 | Suporte ao desenvolvimento. Os sistemas podem ser enviados com essa configuração sem passar em nenhum dos testes HLK, pois o ADS será desabilitado por padrão nos sistemas de clientes. |
2 | Suporte experimental. Os sistemas podem ser enviados com essa configuração sem passar em nenhum dos testes HLK, pois o ADS será desabilitado por padrão nos sistemas de clientes. |
3 | Suporte completo. A ADS será ativada por padrão neste sistema se for compatível com drivers gráficos totalmente suportados. O sistema precisa passar nos testes ADS HLK para liberação. |
Método DMCF (Configurar Mux de Exibição)
Argumentos:
Arg0: nome ASCII do dispositivo filho da GPU do ACPI para o qual o mux deve mudar.
Retornos:
Um inteiro igual a 0 significa sucesso; qualquer valor diferente de zero indica falha. O OEM pode definir o valor diferente de zero para um diagnóstico melhor.
Métodos ACPI do dispositivo GPU
Antes que um driver gráfico para uma GPU seja iniciado, o sistema precisa saber se o dispositivo mux ACPI está funcionando e qual é o seu estado atual. Para fazer isso, o driver do dispositivo ACPI mux já deve ser iniciado. O sistema usa o método ACPI _DEP
no namespace ACPI de cada GPU para garantir a relação entre dispositivos.
Se uma GPU já tiver um método _DEP
, ela deverá adicionar o nome ACPI do dispositivo mux à lista de dependência retornada. Se a GPU ainda não tiver um método _DEP
, ela deverá adicionar um.
Para que o firmware ACPI declare a dependência de uma GPU no mux apenas se o sistema operacional suportar ADS, será adicionada uma consulta ACPI _OSI
. O firmware ACPI pode usar essa consulta para verificar se há suporte a ADS. As versões do sistema operacional que suportam o ADS indicarão suporte retornando "true" para o comando ACPI _OSI(“DisplayMux”)
.
Métodos ACPI do dispositivo filho da GPU
Para cada destino conectado a um mux, o dispositivo ACPI correspondente expõe um método ACPI que retorna o nome ACPI do dispositivo mux ao qual está conectado. Para obter detalhes, consulte Identificar os destinos que um mux controla.
Método DMID (Identificador de Mux de Exibição)
Argumentos:
Nenhum
Retornos:
Cadeia de caracteres ASCII que contém o nome ACPI do dispositivo acPI mux ao qual essa saída está conectada
Exemplo
O exemplo a seguir demonstra como um sistema com duas GPUs (GPU0 e GPU1) e um mux é configurado e gerenciado dentro da estrutura ACPI.
O nome ACPI do dispositivo mux é 'SB. MUX1'.
Para GPU0:
- O nome ACPI do GPU0 é 'SB. PCI0. GFX0'.
- Ele expõe o destino 0x40f04 do VidPn, que relata um valor DXGK_CHILD_DESCRIPTOR.AcpiUid de 0x400.
- O nome do dispositivo filho ACPI correspondente ao destino conectado ao mux é 'SB. PCI0. GFX0. DD1F'.
- O método ACPI _ADR em 'SB. PCI0. GFX0. DD1F' retorna 0x400. Esse valor retornado é a maneira como o sistema operacional identifica que este dispositivo ACPI corresponde ao destino VidPn 0x40f04.
- O método ACPI DMID em 'SB. PCI0. GFX0. DD1F' retorna 'SB. MUX1'.
Para GPU1:
- O nome ACPI da GPU1 é 'SB. PCI0. PEG0. PEGP'.
- Ele expõe o destino VidPn 0x1103, que relata um valor DXGK_CHILD_DESCRIPTOR.AcpiUid de 0x100.
- O nome do dispositivo filho ACPI correspondente ao destino conectado ao mux é 'SB. PCI0. PEG0. PEGP. EDP1'.
- O método ACPI _ADR em 'SB.PCI0.PEG0.PEGP.EDP1' retorna 0x100. Esse valor retornado é como o sistema operacional sabe que esse dispositivo ACPI corresponde ao alvo VidPn 0x1103.
- O método ACPI DMID em 'SB. PCI0. PEG0. PEGP. EDP1' retorna 'SB. MUX1'.
O sistema operacional sabe que 0x40f04 de destino GPU0 e 0x1103 de destino GPU1 estão conectados ao mesmo mux com o nome ACPI 'SB. MUX1'.
Se a GPU1 estiver conectada ao painel no momento, o sistema operacional poderá alternar o mux para GPU0 chamando o método DMCF em 'SB. MUX1' passando 'SB. PCI0. GFX0. DD1F'
O código de linguagem de máquina ACPI a seguir é para as partes relevantes do exemplo. O pseudocódigo para lógica de plataforma é cercado 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")
}
}
}
}
Alterações de API
O recurso ADS adiciona a seguinte funcionalidade de API pública:
- Enumere os dispositivos mux no sistema.
- Consultar informações sobre o mux; por exemplo, a quais destinos ele está conectado e para qual destino ele está alternado atualmente.
- Acione uma alternância do mux.
- Como detectar quando o mux foi alternado.
Enumerar os dispositivos mux no sistema
Os aplicativos podem usar APIs gerais de plug-and-play para localizar interfaces de dispositivo que representam um mux de exibição funcional. Os componentes no modo de usuário podem usar Windows.Devices.Enumeration.DeviceInformation. C# ou C++ podem ser usados com essas APIs para enumerar 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);
Interface IDisplayMuxDevice
A interface IDisplayMuxDevice é adicionada para representar o dispositivo Mux.
O código a seguir demonstra como enumerar dispositivos de exibição mux, consultar seus estados, alternar o destino de exibição ativo e reagir a alterações de estado usando as APIs do Windows Runtime.
#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);
}
}
Alterações de DDI do WDDM para alternância automática de exibição
Esta seção descreve as adições e alterações feitas na DDI do WDDM para dar suporte ao ADS. Essas alterações estão disponíveis a partir do Windows 11, versão 24H2 atualização 2025.01D (WDDM 3.2).
Consultando a interface de suporte ADS do KMD
A estrutura de interface DXGK_DISPLAYMUX_INTERFACE_2 é adicionada. Ele contém as chamadas do sistema operacional para o driver necessárias para suportar a versão 2 da ADS. O sistema operacional consulta a interface de ADS compatível do driver na inicialização do driver, com InterfaceType definido como GUID_WDDM_INTERFACE_DISPLAYMUX_2.
(DXGK_DISPLAYMUX_INTERFACE contém as chamadas do sistema operacional para o driver necessárias para dar suporte à versão 1 do recurso ADS. Essa versão foi usada durante o pré-lançamento do ADS.)
Funções KMD para dar suporte a ADS
O KMD implementa as seguintes funções para dar suporte a ADS. Dxgkrnl obtém a interface funcional de ADS do KMD por meio de uma chamada para DxgkddiQueryInterface do KMD.
- DxgkDdiDisplayMuxGetDriverSupportLevel
- DxgkDdiDisplayMuxGetRuntimeStatus
- DxgkDdiDisplayMuxPreSwitchAway
- DxgkDdiDisplayMuxPreSwitchAwayGetPrivateData
- DxgkDdiDisplayMuxPreSwitchTo
- DxgkDdiDisplayMuxSwitchCanceled
- DxgkDdiDisplayMuxPostSwitchAway
- DxgkDdiDisplayMuxPostSwitchToPhase1
- DxgkDdiDisplayMuxPostSwitchToPhase2
- DxgkDdiDisplayMuxUpdateState
- DxgkDdiDisplayMuxReportPresence
- DxgkDdiDisplayMuxSetInternalPanelInfo
Driver que relata a capacidade da ADS
O driver reporta seu nível de suporte para ADS quando o sistema operacional chama o DDI DxgkDdiDisplayMuxGetDriverSupportLevel. Se o driver não implementar a interface DXGK_DISPLAYMUX_INTERFACE, o sistema operacional considerará o nível de suporte DXGK_DISPLAYMUX_SUPPORT_LEVEL_NONE.
O driver deve relatar o nível de suporte do ADS, independentemente do sistema em que está sendo executado. O nível de suporte indicado pelo driver deve ser baseado apenas no próprio driver. O driver não deve levar em conta nenhum dos seguintes critérios ao relatar o nível de suporte do ADS:
- O OEM do sistema.
- Qualquer outra GPU no sistema.
- A presença ou não do dispositivo ACPI mux.
- A presença ou não das entradas ACPI no nó ACPI da GPU.
Atualização para os destinos na inicialização do adaptador
Quando o adaptador inicia, ele relata todos os dispositivos filhos por meio do DDI DxgkDdiQueryChildRelations. O relatório inclui todos os destinos internos conectados a um mux. Um destino interno inclui o campo DXGK_CHILD_CAPABILITIES.Type.IntegratedDisplayChild.DescriptorLength.
Um problema ocorrerá se o mux for alternado para a outra GPU quando o adaptador for iniciado. Nessa situação, o driver não pode se comunicar com o painel interno para consultar o tamanho EDID/DisplayId. Portanto, um driver que expõe a interface GUID_WDDM_INTERFACE_DISPLAYMUX_2 deve definir DXGK_CHILD_CAPABILITIES.Type.IntegratedDisplayChild.DescriptorLength como zero quando o adaptador for iniciado, se o mux não estiver atualmente alternado para a GPU do driver. Caso contrário, o sistema operacional falhará na inicialização do adaptador.
O sistema operacional atualiza as informações internas sobre o tamanho do descritor interno na primeira operação de alternância do mux.
Atualização para alteração de conexão
Como mencionado anteriormente, há uma maneira específica da ADS para relatar o estado do painel interno durante uma sequência de alternância automática de exibição. Para indicar que um pacote de alteração de conexão faz parte de uma sequência de alternância de ADS, o indicador DisplayMuxConnectionChange é adicionado a DXGK_CONNECTION_MONITOR_CONNECT_FLAGS. Quando DisplayMuxConnectionChange está definido, indica que o status de conexão MonitorStatusConnected ou MonitorStatusDisconnectedestá relacionado a uma alternância automática de exibição.
DisplayMuxConnectionChange só deve ser usado durante uma alternância de ADS e não deve ser usado para nenhuma outra finalidade. Ele deve ser usado nas seguintes ocasiões de ADS:
Enquanto o driver está processando DxgkDdiDisplayMuxPreSwitchAway.
Se o painel interno estiver conectado, o driver deverá adicionar um pacote DXGK_CONNECTION_CHANGE à lista de alterações de conexão com o DXGK_CONNECTION_CHANGE.ConnectionStatus definido como MonitorStatusDisconnected e o DXGK_CONNECTION_CHANGE.MonitorConnect.MonitorConnectFlags.DisplayMuxConnectionChange definido como 1. Essas configurações indicam ao sistema operacional que o driver liberou o controle do painel interno.
Enquanto o driver está processando DxgkDdiDisplayMuxPostSwitchToPhase1.
- O driver deve primeiro determinar se o painel interno está conectado.
- Se o painel estiver conectado, o driver deverá adicionar um pacote DXGK_CONNECTION_CHANGE à sua lista de alterações de conexão, com DXGK_CONNECTION_CHANGE.ConnectionStatus definido como MonitorStatusConnected e DXGK_CONNECTION_CHANGE.MonitorConnect.MonitorConnectFlags.DisplayMuxConnectionChange definido como 1.
- Se o painel não estiver conectado, o driver deverá adicionar um pacote DXGK_CONNECTION_CHANGE à lista de alterações de conexão com DXGK_CONNECTION_CHANGE.ConnectionStatus definido como MonitorStatusDisconnected e DXGK_CONNECTION_CHANGE.MonitorConnect.MonitorConnectFlags.DisplayMuxConnectionChange definido como 1.
Enquanto o driver está processando DxgkDdiDisplayMuxSwitchCanceled.
- Todos os pacotes de alteração adicionados pelo driver em DxgkDdiDisplayMuxSwitchCanceled devem ter DXGK_CONNECTION_CHANGE.MonitorConnect.MonitorConnectFlags.DisplayMuxConnectionChange configurado como 1.
Caso uma solicitação de sondagem de destino seja recebida durante uma alternância, DisplayMuxConnectionChange só deve ser definido para pacotes de alteração de conexão que são adicionados em DxgkDdiDisplayMuxPreSwitchAway, DxgkDdiDisplayMuxPostSwitchToPhase1 ou DxgkDdiDisplayMuxSwitchCanceled.
Diretrizes atualizadas para DxgkDdiSystemDisplayEnable
Quando o DDI DxgkDdiSystemDisplayEnable do driver ADS (/windows-hardware/drivers/ddi/dispmprt/nc-dispmprt-dxgkddi_system_display_enable) é chamado, o driver deve garantir que o PSR esteja desativado ao final da chamada do DDI DxgkDdiSystemDisplayEnable.
Diretrizes para OEM
Há vários aspectos do recurso ADS que estão abaixo do nível que o sistema operacional controla na plataforma. É essencial que os OEMs garantam que ele funcione corretamente. A lista a seguir resume alguns dos principais pontos que os OEMs precisam considerar:
- O driver híbrido integrado e o híbrido discreto precisam dar suporte para ADS.
- O mux selecionado para a plataforma pode ser controlado via ACPI.
- Os métodos _HID, DMQU e DMCF no dispositivo mux, assim como os dispositivos ACPI filho da GPU, para os destinos internos, são implementados e possuem o método ACPI DMID.
- Os dispositivos ACPI das duas GPUs devem ter _DEP para marcar sua dependência em relação ao dispositivo ACPI mux.
- As interfaces de brilho/limites/intervalos expostas pelas duas GPUs correspondem exatamente.
- Conforme detalhado na seção Dados de brilho, a interface de brilho v3 é altamente recomendada em relação à interface de brilho V2.
- Se um driver de painel de monitor for usado, o código deverá ser independente de GPU; ou seja, a mesma lógica pode ser usada quando qualquer GPU está no controle do painel.
- Pelo menos para um mux interno, o ato de alternar o mux não deve gerar um evento HPD.
- Se o OEM quiser desabilitar o mux em um sistema, o método ACPI DMQU deverá retornar 0 quando chamado com Arg0 definido como 2.
- O mux deve ser capaz de alternar entre GPUs mesmo quando os drivers estão em baixa potência. Nesse caso, o PSR não será usado.
- Quando o mux alterna de uma GPU para outra, o brilho do painel deve ser mantido sem falhas de brilho. Há várias maneiras de fazer isso, incluindo as seguintes maneiras. O OEM é responsável por garantir que o sistema mantenha o brilho em todos os interruptores.
- Use o controle de brilho baseado em Nits do DisplayPort Aux.
- Use um Tcon com reconstrução PWM para evitar algum problema de brilho.
- O painel e o Tcon usados podem permanecer em atualização automática (PSR1 para eDP) quando a configuração de link de pré e pós-alternância é exposta pelo EDID e é compatível com tanto a iGPU quanto a dGPU. Isso inclui, mas não se limita a:
- Taxa de atualização
- Tamanho ativo
- Número de faixas de eDP usadas e largura de banda de faixa
- Configuração de DSC do eDP
- Versão do VSC SDP do eDP utilizada
- Versão do PSR e recursos usados para cenários sem alternância