Conceitos básicos

Observação

Para aplicativos em Windows 10, recomendamos 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 fornece uma visão geral dos conceitos básicos do Microsoft DirectComposition. Ele contém as seções a seguir:

Composição

O DirectComposition define uma composição como uma coleção de bitmaps que são combinados e manipulados aplicando várias transformações, efeitos e animações para produzir um resultado visual em uma interface do usuário do aplicativo. O DirectComposition funciona apenas com conteúdo de bitmap; ele não dá suporte a vetores ou texto. O DirectComposition não fornece conteúdo de bitmap. Em vez disso, ele fornece interfaces nas quais os usuários podem desenhar com D2D, DXGI ou carregar seu próprio conteúdo de textura.

Um aplicativo DirectComposition cria dois conjuntos de objetos para compor uma cena: bitmaps compostos juntos e visuais que definem as relações espaciais entre os bitmaps. Para obter mais informações sobre os objetos bitmap com suporte do DirectComposition, consulte Objetos Bitmap.

Visuais

Visuais (ou objetos visuais) são os elementos fundamentais do DirectComposition. Eles são os blocos de construção básicos que você usa para criar composições e animações na interface do usuário do aplicativo.

Em termos de programação, um visual é um objeto que tem um conjunto de propriedades e expõe uma interface que você usa para definir o valor das propriedades. A propriedade Content de um visual associa um bitmap específico ao visual, enquanto outras propriedades controlam como o DirectComposition posiciona e manipula o visual conforme ele é renderizado na tela.

Para obter mais informações, consulte Propriedades de um visual.

Árvore visual

O DirectComposition cria uma composição de uma coleção hierárquica de objetos visuais chamada árvore visual. O visual na raiz de uma árvore é chamado de visual raiz e pode ter um ou mais visuais filho associados a ela. Um visual filho pode ter um ou mais visuais filho próprios. Qualquer visual que tenha visuais filho associados é chamado de visual pai e todos os visuais filho que compartilham o mesmo pai são chamados de visuais irmãos. Um visual específico, juntamente com todos os seus visuais filho e descendentes, é chamado de subárvore visual.

A localização de um visual na árvore ajuda a determinar sua posição de tela e a ordem z em relação aos outros visuais na composição. O visual raiz é posicionado em relação ao canto superior esquerdo da área do cliente da janela de destino em que a composição é renderizada. Todos os visuais filho são posicionados em relação ao canto superior esquerdo do visual pai (ou ao visual especificado pela propriedade TransformParent) e sempre aparecem na frente de seus pais na ordem z.

A ilustração a seguir mostra uma composição de visuais e a estrutura da árvore visual usada para produzir a composição. O Visual 1 é o visual raiz e também é o pai dos visuais filho 2 e 3, que são visuais irmãos. O Visual 3 tem dois visuais filho próprios, Visuais 4 e 5. Juntos, os Visuais 3 a 5 compõem uma subárvore visual.

uma composição de visuais e a árvore visual correspondente

Um visual pai mantém uma lista ordenada de seus visuais filho. Quando os visuais irmãos são posicionados de modo que se sobreponham uns aos outros, o DirectComposition define a ordem z dos irmãos com base na ordem em que aparecem na lista de filhos do visual pai. Um irmão que aparece mais tarde na lista é colocado na frente de todos os irmãos que aparecem anteriormente na lista. A ilustração a seguir mostra a ordem z de visuais filho sobrepostos.

a ordem z de visuais filho sobrepostos

Propriedades de um objeto visual

Um objeto visual expõe um conjunto de propriedades que permitem definir o conteúdo de bitmap para o visual e controlar como o DirectComposition posiciona e manipula o conteúdo visual. As seções a seguir descrevem cada propriedade em detalhes.

Propriedade de conteúdo

A propriedade Content de um visual especifica o conteúdo de bitmap associado ao visual. Esse é o bitmap que o DirectComposition usa quando você inclui o visual em uma composição.

Você define a propriedade Content de um visual chamando o método IDCompositionVisual::SetContent .

Para obter mais informações sobre os tipos de conteúdo de bitmap com suporte do DirectComposition, consulte Objetos Bitmap.

Propriedade Clip

A propriedade Clip de um visual especifica uma área retangular chamada região de recorte (ou retângulo de clipe). Quando um visual é renderizado, somente a parte do visual que cai dentro da região de recorte é exibida, enquanto qualquer conteúdo que se estende fora da região de recorte é recortado (ou seja, não exibido). O DirectComposition dá suporte a regiões de recorte que têm cantos arredondados ou quadrados.

Você define a propriedade Clip de um visual chamando o método IDCompositionVisual::SetClip .

Para obter mais informações, consulte Recorte.

Propriedade BorderMode

A propriedade BorderMode especifica como compor as bordas de bitmaps e clipes associados a esse visual ou com visuais na subárvore com raiz neste visual.

O modo de borda afeta como as bordas de um bitmap são compostas quando o bitmap é transformado de modo que as bordas não são alinhadas ao eixo com coordenadas de inteiro. Também afeta como o conteúdo é recortado nos cantos de um clipe que tem cantos arredondados e na borda de um clipe que é transformado de modo que as bordas não sejam alinhadas ao eixo com coordenadas de inteiro.

Para obter mais informações, consulte IDCompositionVisual::SetBorderMode.

Propriedade BitmapInterpolationMode

A propriedade BitmapInterpolationMode informa ao DirectComposition como compor um bitmap quando ele é transformado de modo que não haja correspondência um-para-um entre pixels no bitmap e pixels na tela.

Você define a propriedade BitmapInterpolationMode de um visual chamando o método IDCompositionVisual::SetBitmapInterpolationMode .

Propriedade CompositeMode

A propriedade CompositeMode informa ao DirectComposition como mesclar o conteúdo de bitmap de um visual com o destino de renderização. Para obter uma descrição dos modos compostos com suporte, consulte DCOMPOSITION_COMPOSITE_MODE.

Você define a propriedade CompositeMode de um visual chamando o método IDCompositionVisual::SetCompositeMode .

Propriedades OffsetX e OffsetY

As propriedades OffsetX e OffsetY informam a DirectComposition onde posicionar um visual horizontal e verticalmente. Eles definem a posição fixa bidimensional da qual todas as transformações e efeitos do visual são calculados.

Para um visual raiz, as propriedades OffsetX e OffsetY definem a coordenada x e a coordenada y de um ponto relativo ao canto superior esquerdo da janela que hospeda o visual. Para um visual filho, as coordenadas são relativas ao canto superior esquerdo do pai ou, se a propriedade TransformParent for especificada, o canto superior esquerdo do visual especificado. Quando um visual é renderizado, ele é posicionado de modo que o canto superior esquerdo do visual coincide com as coordenadas especificadas.

Defina as propriedades OffsetX e OffsetY de um visual chamando os métodos IDCompositionVisual::SetOffsetX e SetOffsetY .

Propriedade Effect

A propriedade Effect permite que você especifique um efeito ou um grupo de efeitos que modificará como um visual e sua subárvore são compostos. Por exemplo, você pode especificar efeitos que controlam a opacidade de um visual, combinar o visual com outro bitmap de várias maneiras e aplicar transformações de perspectiva ao visual.

Você define a propriedade Effect de um visual chamando o método IDCompositionVisual::SetEffect .

Para obter mais informações, veja Efeitos.

Propriedade Transform

A propriedade Transform especifica uma transformação bidimensional (2D) ou um grupo de transformações 2D para o DirectComposition executar no visual. Uma transformação (ou transformação) é uma operação que modifica o sistema de coordenadas de um visual em relação ao seu pai ou em relação ao visual especificado pela propriedade TransformParent. Você pode usar transformações para alterar a posição, o tamanho ou a natureza de um visual movendo-o para outro local (tradução), tornando-o maior ou menor (dimensionamento), girando-o (rotação), distorcendo sua forma (distorção) e assim por diante.

Defina a propriedade Transform de um visual chamando o método IDCompositionVisual::SetTransform .

Para obter mais informações, consulte Transformações.

Propriedade TransformParent

O sistema de coordenadas de um visual é modificado pelas propriedades OffsetX, OffsetY e Transform. Normalmente, essas propriedades definem o sistema de coordenadas de um visual em relação ao pai imediato. Para usar algum visual diferente do pai como base para o sistema de coordenadas de um visual filho, use a propriedade TransformParent para especificar um visual diferente como o "pai" para fins de transformação.

Defina a propriedade TransformParent de um visual chamando o método IDCompositionVisual::SetTransformParent .

Objeto de dispositivo

Para usar o DirectComposition, você deve criar e manipular uma variedade de objetos COM (Component Object Model). O primeiro objeto que você precisa criar é o objeto de dispositivo DirectComposition porque ele serve como a fábrica para criar todos os outros objetos usados em uma composição.

Você cria um objeto de dispositivo chamando a função DCompositionCreateDevice , que retorna um ponteiro de interface IDCompositionDevice . Essa interface expõe um conjunto de métodos que você usa para criar objetos visuais, recortar objetos, objetos de animação, transformar objetos, objetos de efeito e assim por diante.

O objeto de dispositivo serve a uma outra finalidade além de ser uma fábrica para criar outros objetos. Ele expõe um método chamado Commit que passa uma árvore visual para DirectComposition para processamento. Para obter mais informações, consulte Composição transacional.

Lembre-se de que, embora você possa criar várias instâncias do objeto de dispositivo em seu aplicativo, todos os objetos usados em uma composição específica devem ser criados pelo mesmo objeto de dispositivo, com uma exceção: você pode combinar objetos visuais de diferentes objetos de dispositivo na mesma árvore visual. Quando você faz isso, o DirectComposition trata a árvore visual como normalmente faria, exceto que as alterações em um objeto visual específico na árvore só entrarão em vigor quando o método Commit for chamado no objeto de dispositivo que criou o objeto visual.

A capacidade de usar visuais de diferentes dispositivos na mesma árvore visual permite que vários threads criem e manipulem uma única árvore visual, mantendo dois dispositivos independentes que podem ser usados para confirmar alterações de forma assíncrona. Para obter mais informações, consulte Árvores visuais entre dispositivos.

Janela de destino de composição

Uma árvore visual deve ser associada a uma janela antes que qualquer um dos visuais da árvore possa ser exibido na tela. A janela, chamada de janela de destino de composição, pode ser uma janela de nível superior ou uma janela filho. Além disso, a janela de destino de composição pode ser uma janela em camadas; ou seja, ele pode ter o estilo de janela WS_EX_LAYERED .

O DirectComposition permite que um aplicativo associe no máximo duas árvores visuais a cada janela. As árvores visuais incluem uma composta na parte superior da própria janela, mas atrás de todas as janelas filho da janela e outra composta em cima da janela e na parte superior das janelas filho. Em outras palavras, cada janela tem quatro camadas conceituais e todas as camadas são recortadas na região visível da janela de destino. A ilustração a seguir mostra as quatro camadas conceituais de uma janela.

as camadas conceituais de uma janela

Composição transacional

O DirectComposition usa um modelo transacional em que você cria um conjunto em lote de alterações em um visual e, em seguida, "confirma" o conjunto como DirectComposition para processar tudo de uma só vez. Você pode modificar o mesmo objeto visual DirectComposition e confirmar as alterações várias vezes. Quando o DWM (Gerenciador de Janelas da Área de Trabalho) pega lotes, ele pega todos os lotes pendentes e os aplica ao próximo quadro na ordem em que foram confirmados.

Todas as alterações em um único commit têm a garantia de serem aplicadas a um único quadro. Como o DWM coleta lotes uma vez por quadro, você pode modificar qualquer objeto específico apenas uma vez por quadro. Confirmações subsequentes que modificam objetos diferentes também podem ser aplicadas ao quadro atual, mas o DirectComposition não garante que as alterações ocorrerão no mesmo quadro.

Os métodos IDCompositionSurface::BeginDraw e IDCompositionSurface::EndDraw permitem sincronizar atualizações de renderização com atualizações visuais. Por exemplo, você pode chamar IDCompositionSurface::BeginDraw, atualizar as propriedades OffsetX e Clip de um visual, chamar IDCompositionDevice::Commit, desenhar conteúdo com o Microsoft DirectX e, em seguida, chamar IDCompositionSurface::EndDraw. Nesse caso, o Microsoft DirectComposition garante que o conteúdo do bitmap e as propriedades visuais sejam atualizados ao mesmo tempo.

Separação em lotes

Você pode confirmar várias alterações no mesmo visual ou várias alterações em visuais diferentes, dentro do mesmo quadro. Ao fazer várias alterações no mesmo visual dentro do mesmo quadro, lembre-se dos seguintes pontos:

  • Se você fizer várias alterações na mesma propriedade de um visual, somente a última alteração será aplicada. Por exemplo, se você definir a opacidade como 0, então como 0,5 e, por fim, como 1,0, apenas uma opacidade de 1,0 será aplicada ao visual.

  • Se você alterar várias propriedades do mesmo visual, o DirectComposition aplicará as alterações primeiro ao visual e, em seguida, a todos os visuais filho. As propriedades são aplicadas na seguinte ordem, independentemente da ordem em que você as especifica:

    1. Deslocamento
    2. Transformação
    3. Recortar
    4. Efeito

    A ilustração a seguir mostra o resultado da aplicação de todas as quatro propriedades a um visual.

    resultado da aplicação de todas as quatro propriedades a um visual

    Lembre-se de que todas as alterações são aplicadas ao visual de uma só vez dentro do contexto do mesmo quadro. Isso significa que, da perspectiva do usuário, as alterações no visual ocorrem instantaneamente.

  • Para a propriedade Transform, você pode usar IDCompositionDevice::CreateTransformGroup para criar um grupo de transformações a serem aplicadas a um visual de uma só vez. O DirectComposition aplica as transformações na ordem especificada.

  • Para a propriedade Effect, você pode usar IDCompositionEffectGroup para aplicar um grupo de efeitos. DirectComposition aplica os efeitos na ordem especificada. Além disso, as transformações de perspectiva 3D resultam no nivelamento da árvore visual depois que todas as transformações 3D no visual atual foram aplicadas. Isso ajuda a garantir que o visual resultante fique o mais próximo possível de 3D.

Sincronização

Seu aplicativo pode chamar DirectComposition de vários threads ao mesmo tempo. A ordem de execução é garantida para chamadas sequenciais, mas não para chamadas simultâneas. Por exemplo, se o thread A modificar um visual e o thread B confirmar o lote ao mesmo tempo, não será definido se essa alteração visual está incluída no lote confirmado ou se inicia um novo lote. Por outro lado, se o aplicativo usar outros mecanismos de sincronização para garantir que um método seja chamado antes do outro, o DirectComposition respeitará a ordem de chamada e as processará como se ambas as chamadas fossem emitidas nessa ordem de um único thread.

Árvores visuais entre dispositivos

Objetos DirectComposition não são associados a thread; você pode usar vários threads para modificar o mesmo conjunto de objetos. No entanto, esteja ciente dos problemas a seguir ao compartilhar o mesmo objeto de dispositivo.

  • Ambos os threads precisam ser capazes de chamar IDCompositionDevice::Commit. Se apenas um dos threads chamar IDCompositionDevice::Commit, o outro thread não poderá confirmar nenhuma de suas alterações no DirectComposition.
  • O comportamento transacional poderá ser perdido se um thread chamar IDCompositionDevice::Commit enquanto o outro thread ainda estiver fazendo alterações que se destinam a fazer parte da mesma transação.

Se você precisar confirmar várias transações simultâneas no DirectComposition, deverá usar vários objetos de dispositivo, possivelmente de vários threads. Nesse cenário, a mesma árvore visual é compartilhada por ambos os objetos de dispositivo e cada objeto de dispositivo confirma suas próprias transações.

A ilustração a seguir mostra uma árvore visual compartilhada por dois objetos de dispositivo. Os visuais 1, 2, 4 e 5 pertencem a um dispositivo ou outro, mas o visual 3 é compartilhado por ambos os dispositivos e, portanto, pode ser usado para conectar duas subárvores em uma única árvore visual maior. Compartilhar a árvore visual permite que os dois dispositivos sejam manipulados de dois threads diferentes de forma assíncrona.

uma árvore visual compartilhada por dois dispositivos

Para ilustrar a utilidade de compartilhar uma árvore visual entre dois dispositivos, considere uma arquitetura que permite entrada por toque de baixa latência. A arquitetura pode usar dois threads, um que manipula a maioria das tarefas de interface do usuário e um segundo thread dedicado ao processamento de eventos de entrada por toque. O thread de toque atualiza a transformação de um visual específico com base no gesto de entrada do usuário. Ao atualizar a transformação, o thread de toque pode fazer com que toda a subárvore sob esse visual siga o dedo do usuário, escale verticalmente ou para baixo à medida que o usuário executa um gesto de vários toques e assim por diante. O thread de interface do usuário mantém a propriedade da maior parte da árvore de composição, com o thread de toque possuindo apenas os poucos visuais marcados para resposta de toque assíncrona. A ilustração a seguir mostra uma versão simplificada dessa árvore de composição:

uma árvore visual compartilhada entre um thread de interface do usuário e um thread de toque

Normalmente, o thread da interface do usuário modifica apenas os visuais que possui exclusivamente e o thread de toque modifica apenas o visual compartilhado. A única exceção ocorre ao criar ou destruir uma subárvore habilitada para toque.

IDCompositionSurface::BeginDraw

IDCompositionSurface::EndDraw

IDCompositonDevice::Commit

Conceitos do DirectComposition