Arquitetura e componentes
Observação
Para aplicativos no Windows 10, é recomendável usar APIs Windows.UI.Composition em vez de DirectComposition. Para obter mais informações, consulte Modernizar seu aplicativo da área de trabalho usando a camada Visual.
Este tópico descreve os componentes que compõem o Microsoft DirectComposition. Ele consiste nas seções a seguir.
Componentes de software
O DirectComposition consiste nos seguintes componentes de software main.
- Uma biblioteca de aplicativos no modo de usuário (dcomp.dll) que implementa a API pública baseada em COM (Component Object Model).
- Um mecanismo de composição do modo de usuário (dwmcore.dll) hospedado no processo do DWM (Gerenciador de Janelas da Área de Trabalho) (dwm.exe) e executa a composição da área de trabalho real.
- Um banco de dados de objeto no modo kernel (parte do win32k.sys) que realiza marshaling de comandos do aplicativo para o mecanismo de composição.
Uma única instância do mecanismo de composição manipula as árvores de composição directComposition para todos os aplicativos e a árvore de composição dwm, que representa toda a área de trabalho. O banco de dados de objeto do modo kernel e o mecanismo de composição do modo de usuário são instanciados uma vez por sessão, portanto, um computador do Terminal Server com vários usuários tem várias instâncias desses dois componentes.
O diagrama a seguir mostra os componentes main DirectComposition e como eles se relacionam entre si.
Biblioteca de aplicativos
A biblioteca de aplicativos DirectComposition é uma API pública baseada em COM com um único ponto de entrada simples que é exportado de dcomp.dll e retorna um ponteiro de interface para um objeto de dispositivo. O objeto de dispositivo, por sua vez, tem métodos para criar todos os outros objetos, cada um deles representado por um ponteiro de interface. Todas as interfaces DirectComposition herdam e implementam totalmente a interface IUnknown . Todos os métodos que aceitam interfaces DirectComposition marcar se a interface é implementada dentro de dcomp.dll ou se ela é implementada por outro componente. Como DirectComposition não é extensível, métodos que tomam interfaces como parâmetros retornam E_INVALIDARG se as interfaces não forem implementadas no dcomp.dll. A API não requer privilégios especiais; ele pode ser chamado por processos em execução no nível mais baixo de acesso. No entanto, como a API não opera na sessão 0, ela não é adequada para serviços. Nesses aspectos, a API DirectComposition é semelhante a outras APIs do Microsoft DirectX, principalmente Direct2D, Microsoft Direct3D e Microsoft DirectWrite.
Como o mecanismo de composição foi projetado exclusivamente para execução assíncrona, as propriedades de objeto na API directComposition são somente gravação. Todas as propriedades têm métodos setter, mas não métodos getter. Ler propriedades não é apenas uso intensivo de recursos, mas também pode ser impreciso porque qualquer valor retornado pelo mecanismo de composição pode se tornar imediatamente inválido. Isso poderá acontecer se, por exemplo, uma animação independente estiver associada à propriedade que está sendo lida.
A API é thread-safe. Um aplicativo pode chamar qualquer método de qualquer thread a qualquer momento. No entanto, como muitos métodos de API devem ser chamados em uma sequência específica, sem qualquer sincronização, um aplicativo pode experimentar um comportamento imprevisível dependendo de como os threads se intercalam. Por exemplo, se dois threads alterarem a mesma propriedade do mesmo objeto para valores diferentes ao mesmo tempo, o aplicativo não poderá prever qual dos dois valores será o valor final da propriedade. Da mesma forma, se dois threads chamarem Commit no mesmo dispositivo, nenhum thread obterá um comportamento realmente transacional porque uma chamada para Commit em um thread enviará o lote de todos os comandos emitidos por ambos os threads, não apenas aquele que chamou Commit.
O sistema mantém todo o estado interno por objeto de dispositivo. Se um aplicativo criar dois ou mais objetos de dispositivo DirectComposition, o aplicativo poderá manter lotes independentes e outro estado entre os dois.
Todos os objetos DirectComposition têm afinidade de objeto de dispositivo; objetos criados por um objeto de dispositivo específico só podem ser usados com esse objeto de dispositivo e só podem ser associados a outros objetos criados pelo mesmo objeto de dispositivo. Em outras palavras, cada objeto de dispositivo é uma ilha de funcionalidade separada e não contígua. A única exceção é a classe visual , que permite a construção de árvores visuais em que um visual pode pertencer a um objeto de dispositivo diferente do pai. Isso permite cenários em que um aplicativo e um controle podem gerenciar uma única árvore de composição sem também precisar compartilhar um único objeto de dispositivo DirectComposition.
Mecanismo de composição
O mecanismo de composição do DirectComposition é executado em um processo dedicado, separado de qualquer processo de aplicativo. Um único processo de composição, dwm.exe, dá suporte a todos os aplicativos em uma sessão. Cada aplicativo pode criar duas árvores visuais para cada janela que possui. Todas as árvores são realmente implementadas como subárvores de uma árvore visual maior que também abrange as estruturas de composição do DWM. O DWM constrói uma árvore visual grande para cada área de trabalho em uma sessão. Aqui estão as principais vantagens dessa arquitetura:
- O mecanismo de composição tem acesso a todos os bitmaps do aplicativo e árvores visuais, o que permite a interoperabilidade e a composição da janela entre processos.
- O mecanismo de composição é executado em um processo de sistema confiável separado de qualquer processo de aplicativo, permitindo que aplicativos com direitos de acesso baixo componham conteúdo protegido com segurança.
- O mecanismo de composição pode detectar quando uma janela específica está totalmente ocluída e evitar o perda de recursos de GPU (unidade de processamento gráfico) e CPU compondo para a janela.
- O mecanismo de composição pode compor diretamente para o buffer de fundo da tela, evitando a necessidade de uma cópia extra necessária para mecanismos de composição por processo.
- Todos os aplicativos compartilham um único dispositivo Direct3D para composição, o que oferece uma economia de memória considerável
A árvore visual é uma estrutura retida. A API DirectComposition expõe métodos para editar a estrutura em lotes de alterações que são processadas atomicamente. O objeto raiz na API DirectComposition é o objeto de dispositivo, que serve como a fábrica para todos os outros objetos DirectComposition e contém um método chamado Commit. O mecanismo de composição não reflete nenhuma alteração feita pelo aplicativo na árvore visual até que o aplicativo chame Commit, momento em que todas as alterações desde a última Confirmação são processadas como uma única transação.
O requisito para chamar Commit é semelhante ao conceito de um "quadro", exceto que, como o mecanismo de composição é executado de forma assíncrona, ele pode apresentar vários quadros diferentes entre chamadas para Commit. No DirectComposition, um quadro é uma iteração única do mecanismo de composição e o intervalo gasto por um aplicativo entre duas chamadas para Commit é chamado de lote.
O DirectComposition agrupa todas as chamadas de aplicativo para a API do DirectComposition. O banco de dados de objeto kernel, que é implementado no driver de sessão win32k.sys, armazena todas as informações de estado associadas às chamadas à API.
O mecanismo de composição produz um quadro para cada espaço em branco vertical na tela. O quadro é iniciado em um espaço em branco vertical e tem como destino o espaço em branco vertical subsequente. Quando o quadro é iniciado, o mecanismo de composição pega todos os lotes pendentes e inclui seus comandos nesse quadro. Os lotes são colocados em uma fila pendente quando o aplicativo chama Commit e a fila pendente é liberada atomicamente no início do quadro. Portanto, há um único ponto no tempo que marca o início de um quadro. Todos os lotes enviados antes desse ponto são incluídos no quadro, enquanto todos os lotes enviados depois devem aguardar até que o próximo quadro seja processado. O loop de composição completo é o seguinte:
- Estime a hora do próximo espaço em branco vertical.
- Recuperar todos os lotes pendentes.
- Processe os lotes recuperados.
- Atualize todas as animações usando o tempo estimado na etapa 1.
- Determine as regiões da tela que precisam ser redigidos.
- Redigir as regiões de sujo.
- Apresente o quadro invertendo os buffers traseiro e frontal para cada tela.
- Se nada tiver sido composto e apresentado nas etapas 6 e 7, aguarde até que um lote seja confirmado.
- Aguarde o próximo espaço em branco vertical.
Se houver vários monitores anexados a um único adaptador de vídeo, o mecanismo de composição usará o espaço em branco vertical do monitor primário para conduzir o loop de composição e definir os tempos de amostragem de animação. Cada monitor é representado por uma cadeia de inversão de tela inteira separada; o mecanismo de composição repete as etapas 6 e 7 para cada monitor, de maneira round robin, usando um único dispositivo Direct3D. Se também houver vários adaptadores de vídeo, o mecanismo de composição usará um dispositivo Direct3D separado para cada adaptador de vídeo nas etapas 6 e 7.
Os quadros de composição são agendados para sempre iniciar em um espaço em branco vertical, como mostra a ilustração a seguir.
Se o mecanismo de composição não tiver trabalho a fazer porque a árvore de composição não foi alterada, o thread de composição será suspenso enquanto aguarda um novo lote. Quando um novo lote é enviado, o thread de composição é ativado, mas volta imediatamente para suspensão até o próximo espaço em branco vertical. Esse comportamento garante horários previsíveis de início e término de quadros para aplicativos e para o mecanismo de composição.
O mecanismo de composição publica os tempos de apresentação de quadro e a taxa de quadros atual. A publicação dessas informações permite que os aplicativos estimem o tempo de apresentação para seus próprios lotes, o que, por sua vez, permite que as animações sejam sincronizadas. Em particular, um aplicativo pode usar uma combinação de estatísticas de quadro do mecanismo de composição e um modelo histórico de quanto tempo seu thread de interface do usuário leva para produzir um lote, para determinar o tempo de amostragem para suas próprias animações.
Por exemplo, no início do lote do aplicativo mostrado na ilustração anterior, o aplicativo pode consultar o mecanismo de composição para determinar a hora exata da apresentação do próximo quadro. Em seguida, o aplicativo pode usar a hora atual, juntamente com informações sobre lotes anteriores que ele produziu, para determinar se o aplicativo pode concluir o lote atual antes do próximo espaço em branco vertical. Portanto, o aplicativo usa o tempo de apresentação do quadro como o tempo de amostragem para suas próprias animações. Se o aplicativo determinar que é improvável concluir seu trabalho no espaço em branco vertical atual, o aplicativo poderá usar o tempo de quadro subsequente como o tempo de amostragem, usando as informações de taxa de quadros retornadas pelo mecanismo de composição para calcular esse tempo.
Tópicos relacionados