Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Importante
Algumas informações referem-se 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 a funcionalidade de comutação automática de vídeo (ADS) que fornece suporte para o painel interno de um laptop ser alternado de forma fluida entre uma GPU integrada (iGPU) e uma GPU discreta (dGPU). O ADS é um recurso WDDM opcional, suportado 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 deverá ser comutado.
Visão geral
Alguns laptops lançados têm um dispositivo multiplexador (mux) que permite que o painel interno seja alternado entre a GPU integrada (iGPU) e a GPU discreta (dGPU). O driver gráfico atualmente aciona e executa o switch nesses laptops sem qualquer conhecimento do sistema operacional, o que leva a algumas experiências de usuário indesejadas.
ADS permite que o SO controle o uso de um dispositivo multiplexador no sistema para alternar entre a iGPU e a dGPU quando envia sinais para o painel interno. Assim, o sistema operacional pode fornecer uma melhor experiência ao usuário.
A versão inicial do ADS suporta apenas a comutação do painel interno entre a iGPU e a dGPU. No futuro, esse recurso pode ser expandido para suportar muxing de conectores externos em laptops também.
Design de alto nível
Em geral, o sistema tem que garantir que o conteúdo do painel interno seja exibido sem cintilações/falhas enquanto o interruptor está em andamento. O SO não restringe esta funcionalidade a nenhum protocolo de visualização específico. Este artigo se concentra em como implementar o ADS com o eDP, mas há mais padrões do setor que podem ser usados (por exemplo, MIPI ou DSI). Um design de plataforma é livre para usar outro protocolo de conexão de ecrã se ele puder alcançar a mesma experiência sem quaisquer outras alterações ao sistema operativo.
As subseções desta seção identificam os aspetos de design do recurso e detalham a abordagem de alto nível para cada aspeto.
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 desta abordagem são:
- Ele 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 de drivers 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 está disponível.
Expondo o dispositivo mux
Como esta solução é para muxing entre iGPU interna e dGPU, faz sentido expor o mux via ACPI.
Funcionalidade do controlador multiplexador
O driver mux deve atender aos seguintes requisitos funcionais de alto nível:
- Ele deve fornecer o status do mux, cujo alvo está atualmente controlando o painel interno, e quaisquer limites de capacidade.
- Ele deve fornecer uma maneira de acionar um switch e relatar o status do switch.
Para obter mais informações sobre o dispositivo mux ACPI e seus métodos, consulte ACPI.
A fim de executar um switch contínuo, o dispositivo mux requer as seguintes condições em todos os momentos durante o switch GPU:
- Alimentação do painel. A qualquer momento, o mux precisa que a energia do painel seja fornecida por qualquer uma das GPUs. Não há problema em ter ambas as GPUs fornecendo energia ao painel ao mesmo tempo.
- Sinais de controlo de brilho de ambas as GPUs habilitados durante a alternância.
- Nível de brilho (largura de pulso modulada) de ambas as GPUs ao fazer a alternância.
O mux alterna as seguintes informações entre as duas GPUs e o painel:
- Sinal de controlo com capacidade de ajuste de brilho
- Nível de brilho (modulado por largura de pulso)
- Linha DisplayPort (DP) Aux
- Linha de deteção de conector quente (HPD)
- Linha de dados DP
O mux deve ter a capacidade de alternar quando o painel não está ativo. Pelo menos para a comutação do painel interno, o mux não deve disparar nenhum sinal HPD para a GPU ao mudar.
O driver da GPU nunca deve chamar os métodos mux ACPI.
Interruptor automático de ecrã DDI
Vários DDIs são adicionados para satisfazer os requisitos mux. Existem cinco pontos diferentes em que o sistema operativo chama os DDIs de um controlador durante uma comutação mux, utilizando as seguintes funções. As várias chamadas dependem do estágio do switch e se o driver está controlando a GPU que atualmente tem controle da tela.
| DDI | Descrição |
|---|---|
| DxgkDdiDisplayMuxPreSwitchAway | Ligue para o condutor atualmente conectado ao ecrã. Esta chamada informa o condutor de que o sistema está a planear mudar a tela para outra GPU (de GPU0 para GPU1). |
| DxgkDdiDisplayMuxPreSwitchAwayGetPrivateData | Ligue para coletar quaisquer dados do switch privado do driver atualmente conectado ao painel (da GPU0). |
| DxgkDdiDisplayMuxPreSwitchTo | Ligue para o driver atualmente não conectado ao monitor. Esta chamada informa o driver que o sistema operacional está planejando mudar a exibição para esta GPU (para GPU1). |
| DxgkDdiDisplayMuxSwitchCanceled | Ligue para o motorista para indicar que a sequência de comutação foi cancelada antes de ser concluída. |
| DxgkDdiDisplayMuxPostSwitchAway | O comutador mux está completo e o controlador da GPU0 não está mais conectado ao ecrã. |
| DxgkDdiDisplayMuxPostSwitchToPhase1 | O switch mux está completo e o driver da GPU1 agora está conectado ao display. Este driver agora deve executar tarefas da fase 1. |
| DxgkDdiDisplayMuxPostSwitchToPhase2 | O interruptor mux está completo e o driver da GPU1 agora está conectado ao display. Este 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 controlador sobre o estado atual do mux. |
Há ações explícitas que o motorista precisa concluir em cada etapa. Essas ações são descritas mais adiante neste artigo.
Para obter uma lista completa de atualizações DDI relacionadas ao ADS, consulte as alterações de DDI WDDM para comutação automática de ecrã .
Compartilhamento de dados entre GPU0 e GPU1
Pode haver casos em que uma melhor experiência do usuário pode ser criada quando:
- GPU0 e GPU1 são do mesmo IHV.
- GPU0 pode passar informações para GPU1 sobre a configuração de exibição que é opaca para o sistema operacional.
Um conjunto de dados é descrito por um GUID que o driver da GPU1 pode identificar rapidamente caso compreenda o conjunto de dados. Em um nível superior, o sistema operativo chama o GPU0 para obter o GUID do blob e dados antes da comutação e passa-os para o GPU1 antes de ser requisitado pelo HPD no ecrã.
O driver da GPU1 é responsável por:
- Verificar se ele entende o GUID do blob.
- Validação de cada elemento de dados no blob para evitar quaisquer efeitos nocivos de dados malformados no blob.
Interoperabilidade do driver
Se um driver WDDM suporta ADS, ele precisa suportar ADS, não importa em qual sistema OEM ele está sendo executado ou qual é a outra GPU no sistema.
A sequência de interruptores
Embora possa ser tecnicamente possível mudar de uma GPU quando o driver dessa GPU é interrompido, esse cenário não é suportado no momento. Portanto, a comutação só é realizada quando ambas as GPUs têm drivers carregados que suportam o DDI de comutação.
A sequência a seguir é uma visão de alto nível de toda a sequência de switch quando o painel está ativo, onde GPU0 e GPU1 representam a iGPU e dGPU, respectivamente. GPU0 está atualmente conectado ao painel interno através do mux e queremos mudar para GPU1 para saír 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 SO desativa a execução de qualquer topologia de visualização devido a HPDs de qualquer GPU no sistema.
- O sistema operacional chama o driver GPU1 DxgkDdiDisplayMuxPreSwitchTo, passando o nível de brilho atual. O condutor deve fazer o seguinte apenas se a tampa estiver aberta:
- Ligue a energia do painel.
- Defina o sinal de brilho ativado.
- Ajuste o nível de brilho que foi transmitido pelo SO.
- O SO desativa a chamada DxgkDdiQueryConnectionChange na GPU0 para garantir que o HPD da tampa não possa ser processado até depois do comutador mux.
- O sistema operacional chama o driver GPU0 DxgkDdiDisplayMuxPreSwitchAway DDI. O condutor deve:
- Se a tampa estiver ativa, ative o PSR1 (auto-atualização do painel 1) no painel e certifique-se de que não está desativado até que o SO solicite a desativação mais tarde na sequência.
- Adicione um pacote à sua lista de alterações de conexão com o ConnectionStatus do DXGK_CONNECTION_CHANGE definido como MonitorStatusDisconnected e MonitorConnect.MonitorConnectFlags.DisplayMuxConnectionChange definido como 1.
- GPU0 não consegue adicionar nenhum pacote de alteração de conexão para o alvo da tampa na sua fila. O bug do sistema operacional verifica se ele faz isso.
- Devolver o tamanho de qualquer blob de dados ADS privado (GUID e dados) para o SO. Se o driver GPU0 falhar nessa chamada, ele precisará garantir que todos os pacotes de status de conexão ADS colocados na fila sejam removidos antes de retornar.
- Se o driver da GPU0 retornou um tamanho de dados privados diferente de zero, o sistema operacional aloca esse tamanho e o passa para o retorno de chamada de retorno de chamada
DxgkDdiDisplayMuxPreSwitchAwayGetPrivateData da GPU0 para obter os dados do switch privado. - O sistema operacional chama o método ACPI do mux para alternar de GPU0 para GPU1.
- O sistema operacional permite que o
DxgkDdiQueryConnectionChange da GPU0 seja chamado novamente. - O SO chama o DxgkDdiQueryConnectionChanges da GPU0 para processar o pacote de conexão MonitorStatusDisconnected com DisplayMuxConnectionChange definido como 1.
- O sistema operacional chama DxgkddiSettimingsfromvidpn da GPU0 para desativar o caminho da tela que está sendo trocada. O driver da GPU0 deve:
- Desligue a energia do painel.
- Desative o sinal de brilho.
- Pare de enviar o nível de brilho para o mux.
- O SO processa a saída do ecrã. Ele não aciona uma alteração de topologia para evitar alterações de topologia desnecessárias.
- O sistema operacional chama o DxgkDdiDisplayMuxPostSwitchToPhase1 da GPU1 callback, passando qualquer blob privado ADS obtido da GPU0. O condutor deve:
- Determine se a tampa está aberta ou fechada.
- Adicione o pacote à sua lista de alterações de conexão com DXGK_CONNECTION_CHANGE's:
- MonitorConnect.MonitorConnectFlags.DisplayMuxConnectionChange bit está definido.
- ConnectionStatus será definido como MonitorStatusConnected se a tampa estiver aberta, ou MonitorStatusDisconnected se a tampa estiver fechada.
- Se a tampa estiver fechada, desligue a alimentação e o sinal de ativação do brilho para o painel.
- Se o sistema operacional ainda não chamou DxgkDdiQueryAdapterInfo com DXGKQAITYPE_INTEGRATED_DISPLAY_DESCRIPTOR2 para o destino interno da GPU1, ele faz isso. Como resultado dessa chamada, o sistema operacional chama DxgkDdiQueryDeviceDescriptor também.
- O sistema operacional chama o da GPU1 DxgkDdiQueryConnectionChange para processar o evento em sua lista de alteração de conexão. Essa chamada resulta em DxgkDdiQueryDeviceDescriptor sendo chamado para o novo monitor que está sendo HPD'ed.
- O SO permite alterações na topologia de visualização devido a HPDs.
- O sistema operativo processará de forma assíncrona os pacotes de ligação da GPU0 e da GPU1 com DisplayMuxConnectionChange definido como 1.
- Se a GPU1 estiver na fila MonitorStatusConnected:
- O sistema operacional chama as funções DWM da GPU1 para enumerar modos.
- DxgkddiSettimingsfromvidpn é chamado na GPU1 para ativar o caminho de exibição.
- O DWM renderiza e apresenta o quadro para o caminho de exibição na GPU1.
- O SO aguarda que o primeiro quadro seja tornado visível.
- O Sistema Operativo chama o DxgkDdiDisplayMuxPostSwitchToPhase2 callback da GPU1, onde o driver deve desligar o PSR1 do visor se MonitorStatusConnected tiver sido enfileirado pela GPU1; caso contrário, não deverá fazer nada.
- O sistema operacional chama GPU0's DxgkDdiDisplayMuxPreSwitchAway. Embora não haja ações esperadas do condutor, esta chamada é útil para qualquer limpeza do driver ou gestão relacionada com a mudança.
- O SO recolhe os atributos do estado atual do painel interno. Se o estado do painel for diferente do que foi salvo anteriormente, o sistema operacional acionará a telemetria.
Esta sequência de comutação é a mesma para iGPU->dGPU e dGPU->iGPU. Em algumas situações, poderá ser necessário mudar o mux quando o painel está inativo. Nesse caso, essa sequência não é necessária e o sistema operacional pode apenas 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 Vsync, relatar flips como concluídos e assim por diante, mesmo que o usuário não veja esses acontecimentos.
Processo de recuperação
Caso aconteça uma falha durante qualquer estágio da sequência de switch, efetuar-se-á a seguinte limpeza:
- O sistema operacional chama o da GPU0 DxgkDdiDisplayMuxSwitchCanceled se o da GPU0 DxgkDdiDisplayMuxPreSwitchAway foi chamado com sucesso, mas seuDxgkDdiDisplayMuxPostSwitchAway não foi chamado.
- O sistema operacional chama o da GPU1 DxgkDdiDisplayMuxSwitchCanceled se o da GPU1 DxgkDdiDisplayMuxPreSwitchTo foi chamado com sucesso, mas seu DxgkDdiDisplayMuxPostSwitchToPhase2 não foi chamado.
- O SO reativa as alterações de topologia de exibição se elas estiverem desativadas.
- O SO reativa a função DxgkDdiQueryConnectionChange na GPU0, se a chamada
tiver sido desativada. - O SO verifica a conexão da tampa com a GPU à qual está ligada.
- O sistema operativo aciona uma redefinição da configuração predefinida de exibição (SDC). O driver que tem o painel conectado a ele através do mux (retornado de DxgkDdiDisplayMuxSwitchCanceled) precisa garantir que o PSR esteja desativado.
Eventos incomuns que podem acontecer durante a mudança
O usuário conecta ou desconecta um monitor externo
Como parte da sequência de switch, desativamos o processamento de eventos HPD pelo SO. Desta forma, qualquer HPD é enfileirado e processado juntamente com a chegada da tampa numa operação atómica.
Outra aplicação contacta a SDC durante a mudança.
Enquanto a comutação está em curso, as chamadas para o SDC são bloqueadas e serão executadas depois que a comutação for processada.
Driver fica desativado durante a mudança
Quando um driver é parado, as chamadas na sequência de switch falham e a sequência de recuperação é ativada. A seção PnPStop também detalha como garante que a tela esteja sempre visível.
Cenários de fecho da tampa
De um modo geral, o condutor pode utilizar qualquer uma das seguintes abordagens para detetar eventos de abertura/fecho da tampa:
- Rastrear o estado da tampa de DxgkDdiNotifyAcpiEvent(DxgkPowerStateEvent, PO_CB_LID_SWITCH_STATE)
- Rastreie o estado da tampa a partir do callback PoRegisterPowerSettingCallback(GUID_LIDSWITCH_STATE_CHANGE).
- Uma forma diferente, dependente da plataforma.
No entanto, para WDDM em geral, os drivers têm que usar a abordagem DxgkDdiNotifyAcpiEvent porque permite que Dxgkrnl estado e estado do driver estejam em sincronia. Dado que tanto a iGPU quanto a dGPU podem ser GPU1 numa sequência de comutação, faz sentido para todos os drivers ADS monitorizar o estado da tampa, mesmo quando a tampa é afastada dele.
Uma vez que o sistema operacional processa o evento DisplayMuxConnectionChange da GPU0, considera que a GPU0 já não possui o estado da tampa, e, portanto, já não pode relatar mais pacotes de estado de conexão para esse alvo até que a tampa seja revertida. Se GPU0 fizer isso, o sistema operacional irá verificar bugs. Uma vez que o sistema operativo processa o DisplayMuxConnectionChange da GPU1, considera a GPU1 como proprietário do estado da tampa. Qualquer evento de abertura ou fechamento da tampa pode ser ignorado entre esses dois eventos, uma vez que se espera que a GPU1 conheça o estado da tampa e relate corretamente o pacote DisplayMuxConnectionChange.
Quando o SO considera que o driver é o proprietário do painel
A tabela a seguir descreve os estágios de sequência nos quais o sistema operacional considera uma GPU proprietária do painel. GPU proprietária pode relatar alterações de conectividade usando a sequência de comutação. Os números de passo são da sequência de interruptores descrita anteriormente.
| Palco de | Etapa para | Qual GPU controla o painel |
|---|---|---|
| Antes da mudança | 5º Passo | GPU0 |
| Passo 6 | Passo 12 | Sem GPU |
| Passo 13 | Após a mudança | GPU1 |
O bug do sistema operativo verifica se deteta um pacote de alteração de conexão na fila do driver para um alvo multiplexado quando a GPU não controla o painel.
Controlo da auto-atualização do painel (PSR)
O recurso ADS usa PSR para evitar falhas durante a transição. Especificamente, o PSR1 (modo de atualização em tela cheia) é usado para que GPU0 e GPU1 não precisem negociar qual modo PSR usar.
Mesmo dentro do PSR1, há recursos opcionais que o painel precisa suportar:
| Capacidade do lavatório | Detalhes | Pia exposta via |
|---|---|---|
| DPCD & versão eDP | Ative o eDP v1.3 ou superior. | DPCD |
| Capacidade e versão do PSR | O lavatório deve suportar a versão 1. | DPCD 00070h bit 7:0 |
| Dar suporte ao VSC SDP para transmitir o estado PSR | Apenas 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 sumidouro deve informar corretamente o estado relacionado ao PSR | O receptor deve expor o estado; por exemplo, erro de CRC do link, erro de armazenamento de RFB, estado de autorrefrigeração do dispositivo de receção, contagem máxima de frames de ressincronização, última latência de sincronização real no receptor e último SDP PSR recebido. | DPCD 2008h, 2009h, 200Ah deve refletir o estado correto da pia. |
Quando a GPU1 realiza treinamento de link como parte de uma chamada de DxgkddiSettimingsfromvidpn do
Garantir que o painel permaneça no PSR durante a mudança
Quando GPU1 define um modo no painel, não há garantia de que os atributos de link definidos pela GPU1 enquanto o painel está em PSR corresponderão ao modo de entrada PSR. Por exemplo, a taxa de atualização ou o tamanho ativo podem mudar. Hoje, o DP ou outros padrões do setor não têm um método para o painel informar que pode permanecer em PSR enquanto os atributos do link são alterados. A longo prazo, queremos trabalhar para que essa capacidade seja adicionada à especificação do PD. Até que isso aconteça, para um sistema com suporte a ADS, o OEM tem que escolher uma combinação TCon/painel/Mux que possa permanecer no PSR enquanto os atributos da ligação (por exemplo, taxa de atualização, tamanho ativo) mudam entre quaisquer duas combinações expostas no EDID. Essa abordagem garante que o PSR possa ser mantido ativo durante a troca.
Para que o teste ADS HLK verifique se o PSR é mantido durante o processo de switch, gostaríamos de uma forma de o sistema operativo saber se o PSR não estava ativo após o modo de teste da GPU1. Um desafio é que não está definido como um painel reagirá se não puder suportar PSR em todo o treinamento de link.
Como parte de DxgkDdiDisplayMuxPostSwitchToPhase2 , o driver retorna um valor booleano em pWasPanelInPSR para informar ao sistema operacional se detetou 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 precisam relatar o EDID/DisplayId para a tela interna. Esse requisito garante que o banco de dados CCD que armazena modos de exibição e topologias escolha essas mesmas configurações, independentemente da GPU que está controlando a exibição interna.
O EDID que os drivers relatam para o OS deve ser o EDID que é consultado a partir do painel usando o comando "aux" sem qualquer modificação.
Atualmente, o sistema operativo chamará DxgkDdiQueryAdapterInfo(DXGKQAITYPE_INTEGRATED_DISPLAY_DESCRIPTOR2) ao iniciar um controlador que reporte um painel interno. Se o mux se desviar desse destino integrado, o driver não poderá comunicar-se com o painel para coletar as informações necessárias. A solução é que, quando um driver é iniciado e o mux é trocado de seu destino interno, o sistema operacional atrasa a chamada DxgkDdiQueryAdapterInfo(DXGKQAITYPE_INTEGRATED_DISPLAY_DESCRIPTOR2) até que o mux seja trocado pela primeira vez para o destino interno.
Como o sistema operacional decide se o recurso ADS está habilitado em um sistema e o switch é permitido
O sistema operacional executa a seguinte lista de verificações para determinar se o ADS está disponível em um sistema. Todas as verificações devem ser verdadeiras para que o ADS seja suportado.
- Há uma GPU marcada como híbrida integrada (DXGK_DRIVERCAPS. HybridIntegrated) que:
- O seu driver implementa a interface DXGK_DISPLAYMUX_INTERFACE.
- Verifica o nível de suporte do ADS retornado do DxgkDdiDisplayMuxGetDriverSupportLevel.
- Verifica o status do ADS em tempo de execução DxgkDdiDisplayMuxGetRuntimeStatus.
- Driver tem que suportar os seguintes DDIs:
- DxgkddiSettimingsfromvidpn
- DxgkDdiSetVidPnSourceAddressWithMultiPlaneOverlay3
- DxgkDdiDisplayDetectControl
- DxgkDdiQueryConnectionChange
- DxgkDdiNotifyAcpiEvent
- Expõe um alvo para 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 GPU tem um método ACPI '_DEP' que, como dependência, retorna o nome ACPI mux correto.
- Há uma GPU marcada como híbrida discreta (DXGK_DRIVERCAPS. HybridDiscrete) que:
- O seu driver implementa a interface DXGK_DISPLAYMUX_INTERFACE.
- Verifica o nível de suporte do ADS retornado do DxgkDdiDisplayMuxGetDriverSupportLevel.
- Driver tem que suportar os seguintes DDIs:
- DxgkddiSettimingsfromvidpn
- DxgkDdiSetVidPnSourceAddressWithMultiPlaneOverlay3
- DxgkDdiDisplayDetectControl
- DxgkDdiQueryConnectionChange
- DxgkDdiNotifyAcpiEvent
- Expõe um alvo para 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 GPU tem um método ACPI '_DEP' que, como dependência, retorna o nome ACPI mux correto.
- O nome mux ACPI retornado do 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 mux ACPI DMQU retornou o nome ACPI do destino do painel interno de uma das GPUs.
- Atualmente, o ADS suporta apenas sistemas com um único painel interno.
- Ou:
- GPU0, GPU1 e Mux ACPI relatam suporte total a ADS.
- GPU0, GPU1 e Mux ACPI reportam suporte ADS experimental ou completo e a chave do Registro EnableMDMExperimentalFeature está ativada.
As condições 1 e 2 implicam que ambos os adaptadores têm de ser iniciados para que o mux seja comutado.
Gerindo a qualidade do lançamento de funcionalidades do ADS
Para que o ADS forneça uma boa experiência ao usuário, todos os seguintes componentes precisam trabalhar juntos perfeitamente:
- A função de multiplexador de exibição do sistema operativo.
- Os métodos ACPI da plataforma para comutação de mux.
- A funcionalidade de comutação de mux de ecrã nos drivers iGPU e dGPU.
Para ajudar os IHV/OEMs a terem código de qualidade não final nas suas versões, podem expor qualquer um dos seguintes níveis de suporte a ADS:
- Sem suporte: o driver não suporta nenhuma funcionalidade ADS.
- Suporte ao desenvolvimento: o driver suporta 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 suporta ADS, mas ainda não está com a 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 motorista suporta ADS na qualidade do navio. O SO considera que o driver suporta ADS.
Exibir atributos que devem permanecer iguais após uma mudança de exibição
Um interruptor de ecrã não deve alterar nenhum dos seguintes atributos de exibição:
- Resolução do ambiente de trabalho
- Caminho VidPn (incluindo modo de origem VidPn, modo de destino, redimensionamento e assim por diante)
- DPI
- Ajuste de luz noturna
- Gama
- Topologia de exibição
- HDR ligado/desligado
- Nível de branco SDR
- Perfil de cor
- Tipo de destino OPM do monitor
- Brilho do ecrã
Correspondência de capacidades da GPU para uma experiência de transição sem interrupções
Para dar ao usuário uma experiência de comutação perfeita, a tela deve ser configurada da mesma forma após o switch como era antes do switch. Há certos recursos de GPU que ambas as GPUs precisam do mesmo suporte para alcançar esse comportamento. Por exemplo, se uma GPU suporta HDR e a outra não, então uma mudança enquanto o HDR está ativado numa GPU não seria contínua.
A tabela a seguir lista a funcionalidade e os recursos de exibição da GPU e descreve os requisitos de alinhamento entre as duas GPUs.
| Funcionalidade | GPUs são necessárias para ter suporte sem interrupções |
|---|---|
| HDR | Se o painel suporta HDR, então ambas as GPUs têm de suportar fp16 HDR ou não devem suportar HDR. |
| Cursor Hw | Não. O sistema operacional se adapta a diferentes recursos do cursor sem interrupção visível para o usuário. |
| MPO | Não. O sistema operacional se adapta a diferentes recursos MPO sem interrupção visível para o usuário. |
| PSR | Ambas as GPUs precisam suportar esse recurso. |
| EDID/DisplayID | Ambas as GPUs têm de expor o mesmo EDID/DisplayId. |
| Limites de brilho | Ambas as GPUs têm de suportar a mesma interface de brilho e limites de brilho. |
| Níveis de brilho | Ambas as GPUs precisam expor os mesmos níveis e intervalos de brilho. |
| Resolução | Ambas as GPUs precisam suportar os mesmos modos de origem e resolução de destino. |
| Taxas de atualização | Consulte o Problema se a GPU1 não suportar a taxa de atualização que a GPU0 está a usar no painel. Veja para obter detalhes. |
| Taxa de atualização dinâmica | Não. O SO adapta-se à compatibilidade com diferentes taxas de atualização virtual. |
| Taxa de atualização variável | Consulte o Problema se a GPU1 não suportar a taxa de atualização que a GPU0 está a usar no painel. Veja para obter detalhes. |
Problema se a GPU1 não suportar a taxa de atualização em que a GPU0 está executando o painel
Se a GPU1 não suportar o mesmo modo que a 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 suporta 120Hz, mas GPU1 suporta apenas 60Hz, então a seguinte sequência pode acontecer:
- O sistema está configurado para que a GPU0 esteja a controlar o ecrã 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 a tela, mas a GPU1 não o suporta, então 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ê 60Hz do banco de dados.
Para fornecer a melhor experiência, um OEM deve selecionar uma iGPU e dGPU que suportam a taxa de atualização máxima do painel interno. Se isso não for possível e uma GPU não puder suportar a taxa de atualização máxima do painel, a GPU que suporta a taxa de atualização do painel deve suportar o recurso DRR (Taxa de Atualização Dinâmica) do Windows com intervalos que incluem:
- A maior taxa de atualização da outra GPU.
- A maior taxa de atualização do painel interno.
Por exemplo, se o painel pode suportar 300Hz e iGPU só pode suportar 60Hz, então a dGPU tem que suportar VRR com um intervalo de pelo menos 60Hz a 300Hz.
Para resumir, o requisito do ADS para a taxa de atualização é um dos seguintes:
- iGPU e dGPU suportam a taxa de atualização máxima do painel interno.
- A GPU que suporta a taxa de atualização máxima do painel interno tem de suportar DRR com um intervalo que vai desde a taxa de atualização mais alta que a outra GPU pode suportar até à taxa de atualização máxima do painel interno.
HDR e Dolby Vision
O sistema operativo define o mesmo estado HDR/visão Dolby no painel interno da GPU1 após a mudança, tal como foi definido no painel interno da GPU0 antes da mudança. O usuário não deve notar nenhuma alteração.
Luz noturna
A luz noturna é implementada via DDIs de gama de cores ou matriz de cores WDDM. Em ambos os casos, o SO define os mesmos níveis de luz noturna através da GPU1 após o switch como fazia com a GPU0 antes do switch.
Perfil de cor
O sistema operativo aplica o mesmo perfil de cor ao painel após a troca como foi aplicado antes da mudança.
Exibindo a tela de verificação de bugs
Atualmente, o sistema operacional suporta a exibição da tela de verificação de bugs em dispositivos não-POST. Quando ocorre uma verificação de bug no SO:
- Não muda o mux.
- Usa o suporte atual do sistema operacional para exibir a tela de verificação de bugs.
Ao avaliar alvos potenciais para exibir a verificação de bugs, o sistema operacional ignora todos os alvos conectados a um mux que é alternado para um destino diferente.
Há um pequeno intervalo de tempo em que o HPD da GPU0 foi processado, mas o HPD da GPU1 ainda não foi totalmente processado. Se ocorrer uma verificação de bug durante esse período, o usuário não verá a verificação de bug. Se ocorrer uma verificação de bug no pequeno período de tempo em que o PSR ainda está ativado, o driver que controla a exibição deve 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 adaptativo de conteúdo usado por ambas as GPUs deve produzir o mesmo efeito. No entanto, o mesmo efeito provavelmente não ocorrerá e o utilizador pode notar uma diferença quando o painel interno for trocado.
Dados de brilho
Para garantir que o usuário não perceba uma mudança de brilho devido ao switch, todos os atributos de brilho expostos pela GPU0 e GPU1 precisam ser idênticos. Este requisito garante que qualquer nível de brilho na GPU0 antes da mudança será suportado na GPU1 após a mudança.
Para fazer isso, os drivers para GPU0 e GPU1 devem:
- Use a mesma interface de brilho, DXGK_BRIGHTNESS_INTERFACE_2 ou DXGK_BRIGHTNESS_INTERFACE_3, onde a versão 3 é altamente recomendada.
- Para a interface de brilho v3, ambos os drivers têm que suportar brilho em candelas ou brilho não calibrado.
- Para a interface de brilho v2, ambos os drivers têm que retornar exatamente os mesmos níveis possíveis de brilho de GetPossibleBrightness.
- Para a interface de brilho v3, ambos os drivers têm que retornar exatamente os mesmos intervalos; ou seja, cada driver deve retornar estruturas idênticas DXGK_BRIGHTNESS_GET_NIT_RANGES_OUT de GetNitRanges.
- As tabelas internas que o driver usa para converter os níveis de brilho fornecidos pelo SO para configurações específicas do painel devem ser as mesmas.
Na maioria dos laptops, o driver da GPU obtém alguns ou todos esses dados de nível de brilho da plataforma de forma não 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 início do adaptador, o sistema operacional não chamará nenhuma das IIDs da interface de brilho até que o painel interno detecte a conexão (HPD). HPD ocorre depois que o mux é comutado para a GPU para que o driver tenha acesso ao EDID do painel interno naquele momento.
Entendemos que existem maneiras específicas de IHV para o driver definir o brilho do painel para painéis que não suportam PWM. No entanto, esse método adiciona complicação para o TCon, pois ele pode ter que suportar a obtenção do brilho de uma maneira diferente específica do IHV, dependendo de qual GPU está conectada através 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 um switch mux é necessário, o switch é executado somente quando:
- Ambas as GPUs estão ligadas.
- O sistema operacional passou de gráficos de inicialização controlando a saída para DWM / shell controlando a saída.
Assim, o switch ocorre após a chamada DxgkddiSettimingsfromvidpn na GPU que controla o painel interno, e o usuário experienciará uma tela congelada enquanto o painel estiver em PSR durante o switch.
Fornecendo informações de multiplexagem ao motorista
Este recurso é intencionalmente concebido para que o sistema operativo ligue para o driver para fornecer as informações, em vez de fornecer um callback que o driver possa invocar a qualquer momento. Esse método evita que o driver fique confuso se ele consultar o estado do sistema operativo durante uma sequência de comutação.
O sistema operacional chama o do driver DxgkDdiDisplayMuxUpdateState DDI para fornecer ao driver o estado mux atual nos seguintes casos:
- No início do driver, o que permite ao utilizador evitar sequências de sondagem desnecessárias quando o painel não está ligado.
- No regresso a D0 de Dx. Ao retornar de alguns estados de energia (por exemplo, hibernar), o firmware pode ter que redefinir o mux; portanto, o motorista não conhece o estado.
Esses casos, juntamente com as DDIs normais envolvidas na sequência de comutação, garantem que o driver possa determinar de que forma um mux é comutado sempre que a GPU está ativa.
Na primeira versão deste recurso, não há planos para mudar o mux quando o painel interno não estiver ativo, então todos os switches 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 motorista pode tentar descobrir se o mux está direcionado para si ao tentar comunicar-se, mas isso pode ser demorado ou não confiável. Como parte da sequência de início da GPU, o sistema operacional chama o DxgkDdiDisplayMuxUpdateState DDI 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 é mudado 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 operativo chama DxgkDdiDisplayMuxUpdateState para cada alvo conectado a um mux e indica se o mux está comutado para esse alvo. O sistema operativo informa ao driver se o mux está comutado para a GPU do driver antes de chamar qualquer chamada de sondagem DDI.
O driver ADS continua a relatar o painel interno ao sistema operativo da mesma maneira, com o sistema operativo chamando DxgkDdiQueryAdapterInfo(DXGKQAITYPE_INTEGRATED_DISPLAY_DESCRIPTOR2) para consultar os detalhes do painel interno. O condutor precisa garantir que DXGK_CHILD_CAPABILITIES.HpdAwareness está definido como HpdAwarenessInterruptible para qualquer destino conectado a um mux.
Transição 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 seu destino ou trocado para a outra GPU.
Sequência de arranque
A sequência de inicialização a seguir destaca aspetos específicos do ADS. Nesta sequência, o sistema é inicializado com:
- A iGPU conectada ao mux.
- A última configuração do usuário antes da reinicialização foi que o mux estava conectado à dGPU.
A sequência de inicialização é assíncrona por natureza, portanto, essa sequência é apenas a finalidade de exemplo.
- O sistema liga e a iGPU é conectada ao painel através do mux.
- A iGPU exibe a tela de inicialização no painel.
- O Windows carrega e exibe a animação de inicialização na tampa interna.
- Devido ao _DEP na iGPU e na dGPU, o driver 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 de multiplexagem verifica se a implementação de multiplexagem ACPI cumpre os requisitos do ADS.
- Dxgkrnl chama DxgkDdiAddDevice para a iGPU.
- Dxgkrnl chama DxgkDdiQueryInterface(DXGK_DISPLAYMUX_INTERFACE) para a iGPU. Mesmo que o sistema atual não suporte ADS, o driver retorna a sua interface se ele suportar ADS.
- Dxgkrnl chama DxgkDdiDisplayMuxGetDriverSupportLevel para obter o nível de suporte ADS do driver.
- Dxgkrnl chama DxgkDdiDisplayMuxReportPresence(TRUE) para informar o iGPU de que o sistema tem um mux ADS em funcionamento.
- 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 a iGPU suporta ADS e se o driver obteve todas as informações necessárias do sistema.
- Dxgkrnl chama DxgkDdiQueryChildStatus para cada sub-elemento que a iGPU apresenta.
- Assim que Dxgkrnl encontra a componente relatada pela iGPU que está conectada ao mux, ele chama DxgkDdiDisplayMuxUpdateState para informar à iGPU que o mux está conectado a esse alvo.
- Como a iGPU expôs um monitor interno conectado, Dxgkrnl define um modo na iGPU usando DxgkddiSettimingsfromvidpn.
- Dxgkrnl inicia o driver dGPU e, em seguida, repete as etapas 5-12 para a dGPU.
- Dxgkrnl deteta que a iGPU, dGPU e mux estão configuradas corretamente, portanto, cria um par mux e as propriedades PnP Device Interface para o par mux.
- Dxgkrnl lê a última configuração mux do registro. Como a última configuração foi dGPU, Dxgkrnl agora inicia a sequência de comutação do mux descrita anteriormente para alternar o mux para o dGPU.
Drivers de painel
Os drivers do painel de monitoramento são carregados com base no ID de hardware PnP gerado a partir do EDID. Dado que o EDID permanece o mesmo, o driver do painel é carregado quando uma das GPUs está a controlar o painel interno. Ambos os drivers irão oferecer a mesma funcionalidade de ajuste de brilho. Assim, 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 do driver DxgkDdiQueryChildRelations para consultar informações sobre os filhos relatados. O motorista preenche a estrutura DXGK_CHILD_DESCRIPTOR para cada criança. O membro AcpiUid é definido como sendo o valor retornado pelo método _ADR sob esse elemento no espaço de nomes ACPI, permitindo ao sistema operativo encontrar o nome ACPI para esse elemento.
Para o ADS, definimos um método DMID ACPI que precisa estar dentro do espaço de nomes ACPI 'child' para o alvo. Esse método DMID retorna o nome ACPI do dispositivo mux. Ele permite que o sistema operacional encontre o nome mux ACPI para o alvo.
PnP parando o adaptador que está fazendo a varredura para um destino
O SO não alternará o mux quando a GPU que está transmitindo para o painel interno for desligada. Os cenários a seguir passam pelos diferentes casos em que uma GPU é interrompida.
GPU0 é o post. Está ligado ao painel interno e está parado.
Neste caso, o Basic Display Driver (BDD) assume o modo atualmente ativo na GPU0 e continua atualizando a tela.
GPU0 é o post, mas GPU1 está conectado ao painel interno. GPU0 é parado.
Devido ao design atual do sistema operacional, o BDD é iniciado na GPU0, o que faz com que um monitor fantasma seja relatado e apareça na CPL da tela.
GPU1 não é o post e está conectado ao painel interno. GPU1 é parado.
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. GPU0 é conectado ao painel interno e GPU1 é parado.
Nenhuma mudança ocorre e nada acontece. GPU0 continua a ser exibido 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.
Plugin/GPUs externas não são suportadas
Não acreditamos que haja qualquer caso de uso para esse recurso com GPUs de plugin.
O ADS está limitado apenas a painéis internos únicos
A primeira versão do ADS suporta apenas painéis internos únicos. No entanto, o recurso foi concebido para permitir o suporte à ligação de monitores externos e múltiplos internos, caso sejam compatíveis com o sistema operativo, no futuro, com mínimas alterações nos controladores.
Alterações atuais na política do adaptador POST
O sistema operacional anteriormente tinha algumas políticas em relação ao adaptador POST. Por exemplo, o adaptador POST era o único adaptador que podia expor destinos internos. Esses tipos de restrições são removidos do sistema operacional com a introdução do ADS.
Desativar os efeitos visuais de chegada do monitor
Quando um monitor está conectado no Windows 11, o shell/DWM tem uma sequência de animação. Esta animação está desativada em cenários de alternância de exibição.
Desativar PnP bonk
Quando um monitor é adicionado ou removido, o sistema PnP reproduz um som 'bonk' para notificar o utilizador. Este 'bonk' está desativado em cenários de mudança de visualização.
Notificações de aplicação
Quando ocorre uma mudança de ecrã, o sistema passa pelos processos regulares de remoção e chegada do HPD. Por isso, todas as notificações normais de aplicação são acionadas normalmente; por exemplo, a notificação PnP para a saída HPD e a entrada HPD e as mensagens da janela WM_DISPLAYCHANGE.
API para acionar o interruptor
O plano é ter uma API pública para que o SO e o painel de controle IHV possam acionar o switch.
Exibir APIs relacionadas e comportamento Win+P
Dado que o painel interno só está conectado a uma única GPU, as APIs de exibição funcionam conforme o esperado, juntamente com a funcionalidade Win+P.
Teste HLK
Se um driver de GPU ou firmware ACPI indicar suporte completo a ADS, ele deve ser aprovado nos testes ADS HLK em um sistema com ADS habilitado.
Painel interno HPDing da GPU quando o mux é desligado dessa GPU
O sistema operacional aciona uma verificação de bug quando um painel interno é relatado como conectado de um driver quando esse mux está atualmente desligado desse driver.
Transição AC/DC
Para a primeira versão do recurso ADS, o sistema operacional não armazenará uma configuração AC vs DC mux e não acionará um interruptor mux em uma transição AC <-> DC.
Transições de energia do sistema
A principal preocupação com as transições de energia é quando o firmware redefine o estado mux (por exemplo, hibernar), e ao retomar da alimentação o mux não é mudado para o painel que era antes da transição de energia.
A abordagem inicial era, depois de ligar tanto a iGPU quanto a dGPU, mudar novamente o mux para a 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 utilizador é que o sistema alterne o mux de volta para o alvo esperado enquanto a iGPU e a dGPU estão em suspensão, evitando assim múltiplas alterações de modo.
Sequência de transição de potência
O exemplo a seguir descreve uma transição de energia de hibernação em um sistema ADS.
- O sistema é configurado com mux conectado à dGPU.
- O sistema entra em hibernação.
- Tanto a iGPU como a dGPU são transferidas para o estado de energia D3.
- O sistema desliga.
- Poderes do utilizador no sistema.
- O firmware configura o mux para o iGPU e a sequência de inicialização do display no painel interno.
- Dxgkrnl lê a última configuração mux (dGPU neste caso) e a compara com a posição mux atual usando ACPI (iGPU neste caso). Dxgkrnl chama a ACPI para alternar o mux para a dGPU.
- Dxgkrnl faz a transição da iGPU para D0 e, em seguida, chama oda iGPU DxgkDdiDisplayMuxUpdateState para informar o driver que o mux não está ligado a ele.
- Dxgkrnl faz a transição da dGPU para D0 e, em seguida, chama o da dGPU DxgkDdiDisplayMuxUpdateState para informar ao driver que o mux está conectado a ele.
- Dxgkrnl define um modo na dGPU.
Sistemas All In One (AIO)
Qualquer sistema AIO que queira suportar ADS deve ter o painel interno exposto como um tipo de destino interno em ambas as placas gráficas.
Dispositivo Mux ACPI
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 da 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 sob o antepassado comum mais próximo de ambas as GPUs.
Os dispositivos mux atuais suportam apenas duas entradas e não esperamos que os futuros muxes suportem mais do que isso, então 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 drivers para um dispositivo ACPI pode invocar para avaliar os métodos ACPI 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 esta razão, o sistema operativo agora fornece um driver mux de display como controlador para todos os muxes de comutação de display.
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 (Display Mux Query) retorna o estado atual do mux.
- DMCF (Display Mux Configure) configura o mux.
Método _HID (ID de hardware)
Argumentos:
Nenhum
Devoluções:
Uma cadeia de caracteres ASCII contendo o ID de hardware, que é 'MSFT0005'.
Método DMQU (Display Mux Query)
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 o método como sem suporte.
Argumentos:
Arg0: Um inteiro especificando o tipo de consulta. A tabela a seguir lista os valores do tipo de consulta e seus significados.
| Valor do tipo de consulta | Significado |
|---|---|
| 1 | Consultar estado atual do comutador |
| 2 | Consultar o nível de suporte do mux ADS |
| 3 | Consulte o primeiro subprocesso da GPU ao qual o mux está conectado |
| 4 | Consultar a segunda GPU filha à qual o mux está conectado |
Devoluções:
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 deve retornar uma cadeia de caracteres vazia.
| Valor do tipo de consulta | Dados de retorno |
|---|---|
| 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 | Número inteiro que representa o nível de suporte de ADS. Consulte a tabela seguinte 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 devolvidos | Significado |
|---|---|
| 0 | Sem suporte |
| 1 | Apoio ao desenvolvimento. Os sistemas podem ser fornecidos com essa configuração sem passar em nenhum dos testes HLK, pois o ADS será desativado por padrão nos sistemas do cliente. |
| 2 | Apoio experimental. Os sistemas podem ser fornecidos com essa configuração sem passar em nenhum dos testes HLK, pois o ADS será desativado por padrão nos sistemas do cliente. |
| 3 | Apoio total. O ADS será ativado por padrão neste sistema se estiver emparelhado com drivers gráficos totalmente suportados. O sistema precisa passar nos testes ADS HLK para ser enviado. |
Método DMCF (Display Mux Configure)
Argumentos:
Arg0: Nome ASCII do dispositivo filho da GPU ACPI para onde o mux deve alternar.
Devoluções:
Um inteiro 0 significa sucesso; qualquer valor diferente de zero indica falha. O OEM pode definir o valor diferente de zero para melhores diagnósticos.
Métodos ACPI do dispositivo GPU
Antes de um driver gráfico para uma GPU ser iniciado, o sistema precisa saber se o dispositivo mux ACPI está funcionando e qual é o seu estado atual. Para tal, o driver do dispositivo mux ACPI deve já estar iniciado. O sistema utiliza o método ACPI _DEP no namespace ACPI de cada GPU para assegurar a ligação do dispositivo.
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, deve adicionar um.
Para que o firmware ACPI só declare a dependência de uma GPU no mux se o SO suportar ADS, é adicionada uma consulta ACPI _OSI. O firmware ACPI pode usar esta consulta para verificar se há suporte a ADS. As versões do SO que suportam ADS indicarão suporte retornando "true" ao comando ACPI _OSI(“DisplayMux”).
Métodos ACPI do dispositivo filho GPU
Para cada destino conectado a um mux, o dispositivo ACPI dessa criança expõe um método ACPI que retorna o nome ACPI do dispositivo mux ao qual ele está conectado. Para obter detalhes, consulte Identificar os destinos que um mux controla.
Método DMID (Display Mux Identifier)
Argumentos:
Nenhum
Devoluções:
Cadeia de caracteres ASCII que contém o nome ACPI do dispositivo mux ACPI 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 da GPU0 é 'SB. PCI0. GFX0».
- Ele expõe o alvo VidPn 0x40f04, que relata um DXGK_CHILD_DESCRIPTOR.AcpiUid valor de 0x400.
- O nome do dispositivo filho ACPI correspondente ao destino conectado ao mux é 'SB. PCI0. GFX0. DD1F».
- O método ACPI _ADR na rubrica «SB. PCI0. GFX0. DD1F' retorna 0x400. É através deste valor de retorno que o sistema operativo consegue identificar que este dispositivo ACPI corresponde ao alvo 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 na rubrica «SB. PCI0. PEG0. PEGP. EDP1' retorna 0x100. Este valor de retorno é a forma como o sistema operativo identifica que este dispositivo ACPI corresponde ao destino VidPn 0x1103.
- O método ACPI DMID em «SB. PCI0. PEG0. PEGP. EDP1' devolve '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 atualmente conectada ao painel, o sistema operacional pode alternar o mux para GPU0 chamando o método DMCF em 'SB.MUX1' passando 'SB.PCI0.GFX0.DD1F'
O seguinte código de linguagem de máquina ACPI é 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 na 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 que alvos está ligado e para qual alvo está atualmente comutado.
- Acione um interruptor mux.
- Como detetar quando o mux foi trocado.
Enumerar os dispositivos mux no sistema
Os aplicativos podem usar APIs plug and play gerais para encontrar interfaces de dispositivo que representam um mux de exibição funcional. Os componentes de 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
O interface IDisplayMuxDevice é adicionado para representar o dispositivo mux.
O código a seguir demonstra como enumerar dispositivos mux de exibição, consultar seus estados, alternar o destino de exibição ativo e reagir a alterações de estado usando as APIs do Tempo de Execução do 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);
}
}
Alterações de DDI WDDM para a comutação automática de ecrã
Esta seção descreve as adições e alterações feitas no DDI WDDM para oferecer 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. Contém as chamadas do sistema operativo para o driver necessárias para suportar a versão 2 do ADS. O sistema operativo consulta a interface ADS suportada do driver ao arrancar o driver, com InterfaceType definido como GUID_WDDM_INTERFACE_DISPLAYMUX_2.
(DXGK_DISPLAYMUX_INTERFACE contém as chamadas de SO para driver necessárias para suportar a Versão 1 do recurso ADS. Esta versão foi usada durante o pré-lançamento do ADS.)
Funções KMD para suportar ADS
O KMD implementa as seguintes funções para suportar o ADS. Dxgkrnl obtém a interface funcional ADS do KMD através de uma chamada para DxgkddiQueryInterface do KMD .
Relatório de capacidades de ADS de motorista
O driver relata seu nível de suporte a ADS quando o sistema operacional chama seu DxgkDdiDisplayMuxGetDriverSupportLevel DDI. Se o driver não implementar a interface DXGK_DISPLAYMUX_INTERFACE, o sistema operacional considerará o nível de suporte como DXGK_DISPLAYMUX_SUUPORT_LEVEL_NONE.
O driver deve informar seu nível de suporte ADS, independentemente do sistema em que está sendo executado. O nível de suporte comunicado pelo condutor deve basear-se apenas no condutor. O driver não deve levar em conta nenhum dos seguintes critérios ao relatar seu nível de suporte ADS:
- O sistema OEM.
- Qualquer outra GPU no sistema.
- A presença ou não do dispositivo mux ACPI.
- A presença ou não das entradas ACPI no nó ACPI da GPU.
Atualização para objetivos de relatórios no tempo de inicialização do adaptador
Quando o adaptador é iniciado, ele reporta todos os seus dispositivos subordinados por meio do DxgkDdiQueryChildRelations DDI. O relatório inclui quaisquer alvos internos conectados a um mux. Um alvo interno inclui o campo DXGK_CHILD_CAPABILITIES.Type.IntegratedDisplayChild.DescriptorLength.
Um problema surge se o mux é comutado para a outra GPU quando o adaptador é iniciado. Nesta situação, o driver não pode comunicar-se com o painel interno para consultar o tamanho do EDID/DisplayId. Assim, um driver que expõe a interface GUID_WDDM_INTERFACE_DISPLAYMUX_2 deve definir DXGK_CHILD_CAPABILITIES. Type.IntegratedDisplayChild.DescriptorLength a zero no início do adaptador se o mux não estiver atualmente alternado para a GPU do driver. Caso contrário, o SO falhará em iniciar o adaptador.
O sistema operativo atualiza as suas informações internas sobre o tamanho do descritor interno na primeira operação do switch mux.
Atualização para alteração de conexão
Como mencionado anteriormente, há uma maneira específica do ADS para comunicar o estado do painel interno durante uma sequência de mudança automática de exibição. Para indicar que um pacote de alteração de conexão faz parte de uma sequência de comutadores ADS, o sinalizador DisplayMuxConnectionChange é adicionado a DXGK_CONNECTION_MONITOR_CONNECT_FLAGS. Quando DisplayMuxConnectionChange é definido, indica que o status de conexão MonitorStatusConnected ou MonitorStatusDisconnected está relacionado a um comutador de ecrã automático.
DisplayMuxConnectionChange só deve ser usado durante uma troca ADS e não deve ser usado para qualquer outra finalidade. Deve ser usado nas seguintes ocasiões de ADS:
Enquanto o driver está processando DxgkDdiDisplayMuxPreSwitchAway.
Se o painel interno estiver conectado, o driver deve adicionar um pacote de DXGK_CONNECTION_CHANGE à sua 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. 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 deve adicionar um pacote de DXGK_CONNECTION_CHANGE à sua lista de alteração 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 de DXGK_CONNECTION_CHANGE à sua lista de alterações de conexão com o DXGK_CONNECTION_CHANGE.ConnectionStatus configurado como MonitorStatusDisconnected e o DXGK_CONNECTION_CHANGE.MonitorConnect.MonitorConnectFlags.DisplayMuxConnectionChange configurado como 1.
Enquanto o driver está a processar DxgkDdiDisplayMuxSwitchCanceled.
- Todos os pacotes de alteração adicionados pelo driver em DxgkDdiDisplayMuxSwitchCanceled precisam ter DXGK_CONNECTION_CHANGE.MonitorConnect.MonitorConnectFlags.DisplayMuxConnectionChange configurado para 1.
*No caso de uma solicitação de sondagem de destino chegar durante um switch, DisplayMuxConnectionChange só deve ser definida para pacotes de alteração de conexão que são adicionados a partir de DxgkDdiDisplayMuxPreSwitchAway, DxgkDdiDisplayMuxPostSwitchToPhase1ou DxgkDdiDisplayMuxSwitchCanceled.
Orientação atualizada para DxgkDdiSystemDisplayEnable
Quando um driver ADS DxgkDdiSystemDisplayEnableDDI (/windows-hardware/drivers/ddi/dispmprt/nc-dispmprt-dxgkddi_system_display_enable) é chamado, o driver deve garantir que o PSR esteja desativado no final da chamada DxgkDdiSystemDisplayEnable DDI.
Orientação OEM
Existem vários aspetos 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:
- Tanto o driver híbrido integrado quanto o híbrido discreto têm que suportar ADS.
- O mux selecionado para a plataforma pode ser controlado via ACPI.
- Os métodos _HID, DMQU e DMCF sob o dispositivo mux e os dispositivos ACPI filho GPU para os alvos internos são implementados e têm o método DMID ACPI.
- Os dispositivos ACPI de ambas as GPUs devem ter _DEP para marcar a sua dependência do dispositivo ACPI multiplexador.
- A interface de brilho, os limites e os intervalos revelados pelas duas GPUs correspondem exatamente.
- Conforme detalhado na seção de dados de brilho , a interface de brilho V3 é altamente recomendada em relação à interface de brilho V2.
- Se for usado um driver de painel de monitor, o código deve ser independente da 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 trocar o mux não deve gerar um evento HPD.
- Se o OEM quisesse desativar o mux em um sistema, o método ACPI DMQU deveria 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 baixo consumo de energia. Neste caso, o PSR não será usado.
- Quando o mux muda 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 entre os interruptores.
- Utilize o controlo de brilho baseado em DisplayPort Aux Nits.
- Utilize um Tcon com reconstrução PWM para evitar quaisquer falhas de brilho.
- O painel e o Tcon usados podem permanecer em auto-refresco (PSR1 para eDP) quando a configuração de link antes da comutação e após a comutação é exposta pelo EDID e suportada tanto pela iGPU quanto pela dGPU. Isso inclui, mas não está limitado a:
- Taxa de atualização
- Tamanho ativo
- Número de faixas eDP utilizadas e largura de banda da faixa
- Configuração do eDP DSC
- eDP VSC SDP versão usada
- Versão PSR e recursos usados para cenários sem switch