Partilhar via


Como renderizar usando um contexto de dispositivo Direct2D

Neste tópico, irá aprender a criar contexto de dispositivo Direct2D no Windows 8. Estas informações aplicam-se se estiver a desenvolver aplicações da Loja Windows ou uma aplicação de ambiente de trabalho utilizando Direct2D. Este tópico descreve a finalidade dos objetos de contexto de dispositivo Direct2D, como criar esse objeto e um guia passo a passo sobre como renderizar e exibir primitivos e imagens Direct2D. Você também aprenderá sobre como alternar destinos de renderização e adicionar efeitos ao seu aplicativo.

O que é um dispositivo Direct2D?

Você precisa de um dispositivo Direct2D e um dispositivo Direct3D para criar um contexto de dispositivo Direct2D. Um dispositivo Direct2D (expõe um ponteiro de interface ID2D1Device) representa um adaptador de vídeo. Um dispositivo Direct3D (expõe um ponteiro de interface ID3D11Device ) está associado a um dispositivo Direct2D. Cada aplicativo deve ter um dispositivo Direct2D , mas pode ter mais de um dispositivo .

O que é um contexto de dispositivo Direct2D?

Um contexto de dispositivo Direct2D (expõe um ponteiro de interface ID2D1DeviceContext ) representa um conjunto de buffers de estado e de comando que você usa para renderizar num alvo. Você pode chamar métodos no contexto do dispositivo para definir o estado do pipeline e gerar comandos de renderização usando os recursos de propriedade de um dispositivo.

Renderização com Direct2D no Windows 8

No Windows 7 e versões anteriores, você usa um ID2D1HwndRenderTarget ou outra interface de destino de renderização para renderizar em uma janela ou superfície. A partir do Windows 8, não recomendamos a renderização usando métodos que dependem de interfaces como ID2D1HwndRenderTarget porque eles não funcionarão com aplicativos da Windows Store. Você pode usar um contexto de dispositivo para renderizar para um Hwnd se quiser criar um aplicativo de área de trabalho e ainda aproveitar os recursos adicionais do contexto do dispositivo. No entanto, o contexto de dispositivo é necessário para renderizar conteúdo em aplicações da Windows Store com o Direct2D.

Por que usar um contexto de dispositivo para renderizar?

  • Você pode renderizar para aplicativos da Windows Store.
  • Você pode alterar o destino de renderização a qualquer momento antes, durante e depois da renderização. O contexto do dispositivo gráfico garante que as chamadas para métodos de desenho sejam executadas em ordem e são aplicadas quando o utilizador alterna o destino de renderização.
  • Você pode usar mais de um tipo de janela com um contexto de dispositivo. Você pode usar um contexto de dispositivo e uma swap chain DXGI para renderizar diretamente para um Windows::UI::Core::CoreWindow ou para um Windows::UI::XAML::SwapChainBackgroundPanel .
  • Pode utilizar o contexto de dispositivo Direct2D para criar efeitos Direct2D e para renderizar a saída de um efeito de imagem ou de um gráfico de efeitos para um alvo de renderização.
  • Você pode ter vários contextos de dispositivo , o que pode ser útil para melhorar o desempenho em um aplicativo encadeado. Consulte de aplicativos Direct2D multithreaded para obter mais informações.
  • O contexto do dispositivo interopera estreitamente com o Direct3D, dando-lhe mais acesso às opções do Direct3D.

Como criar um contexto de dispositivo Direct2D para renderização

O código aqui mostra como criar um dispositivo Direct3D11, obter o dispositivo DXGI associado, criar um dispositivo Direct2D e, finalmente, criar o contexto do dispositivo Direct2D para renderização.

Aqui está um diagrama das chamadas de método e as interfaces que esse código usa.

diagrama de dispositivos Direct2D e Direct3D e contextos de dispositivos.

Observação

Este código pressupõe que você já tenha um objetoID2D1Factory1, para obter mais informações, consulte a página de referência ID2D1Factory .

 

    // This flag adds support for surfaces with a different color channel ordering than the API default.
    // You need it for compatibility with Direct2D.
    UINT creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
    
    // This array defines the set of DirectX hardware feature levels this app  supports.
    // The ordering is important and you should  preserve it.
    // Don't forget to declare your app's minimum required feature level in its
    // description.  All apps are assumed to support 9.1 unless otherwise stated.
    D3D_FEATURE_LEVEL featureLevels[] = 
    {
        D3D_FEATURE_LEVEL_11_1,
        D3D_FEATURE_LEVEL_11_0,
        D3D_FEATURE_LEVEL_10_1,
        D3D_FEATURE_LEVEL_10_0,
        D3D_FEATURE_LEVEL_9_3,
        D3D_FEATURE_LEVEL_9_2,
        D3D_FEATURE_LEVEL_9_1
    };

    // Create the DX11 API device object, and get a corresponding context.
    ComPtr<ID3D11Device> device;
    ComPtr<ID3D11DeviceContext> context;

    DX::ThrowIfFailed(
        D3D11CreateDevice(
            nullptr,                    // specify null to use the default adapter
            D3D_DRIVER_TYPE_HARDWARE,
            0,                          
            creationFlags,              // optionally set debug and Direct2D compatibility flags
            featureLevels,              // list of feature levels this app can support
            ARRAYSIZE(featureLevels),   // number of possible feature levels
            D3D11_SDK_VERSION,          
            &device,                    // returns the Direct3D device created
            &m_featureLevel,            // returns feature level of device created
            &context                    // returns the device immediate context
            )
        );

    ComPtr<IDXGIDevice> dxgiDevice;
    // Obtain the underlying DXGI device of the Direct3D11 device.
    DX::ThrowIfFailed(
        device.As(&dxgiDevice)
        );

    // Obtain the Direct2D device for 2-D rendering.
    DX::ThrowIfFailed(
        m_d2dFactory->CreateDevice(dxgiDevice.Get(), &m_d2dDevice)
        );

    // Get Direct2D device's corresponding device context object.
    DX::ThrowIfFailed(
        m_d2dDevice->CreateDeviceContext(
            D2D1_DEVICE_CONTEXT_OPTIONS_NONE,
            &m_d2dContext
            )
        );

Vamos percorrer as etapas no exemplo de código anterior.

  1. Obtenha um ponteiro para a interface ID3D11Device, que será necessário para criar o contexto do dispositivo.

    • Declare os sinalizadores de criação para configurar o dispositivo Direct3D para suporte a BGRA. Direct2D requer a ordem de cores BGRA.

    • Declare uma matriz de entradas de D3D_FEATURE_LEVEL que representam o conjunto de níveis de recursos suportados pelo seu aplicativo.

      Observação

      Direct3D pesquisa sua lista até encontrar o nível de recurso suportado pelo sistema host.

       

    • Use a função D3D11CreateDevice para criar um ID3D11Device objeto, a função também retornará um ID3D11DeviceContext objeto, mas esse objeto não é necessário para este exemplo.

  2. Consulte o dispositivo Direct3D 11 para obter a sua interface de dispositivo DXGI .

  3. Crie um ID2D1Device objeto chamando o ID2D1Factory::CreateDevice método e passando o IDXGIDevice objeto.

  4. Crie um ponteiro ID2D1DeviceContext usando o método ID2D1Device::CreateDeviceContext.

Seleção de um alvo

O código aqui mostra como obter ode textura Direct3D2 dimensões para o buffer de volta da janela e criar um destino de bitmap que vincula a essa textura à qual o contexto do dispositivo Direct2D renderiza.

        // Allocate a descriptor.
        DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0};
        swapChainDesc.Width = 0;                           // use automatic sizing
        swapChainDesc.Height = 0;
        swapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; // this is the most common swapchain format
        swapChainDesc.Stereo = false; 
        swapChainDesc.SampleDesc.Count = 1;                // don't use multi-sampling
        swapChainDesc.SampleDesc.Quality = 0;
        swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
        swapChainDesc.BufferCount = 2;                     // use double buffering to enable flip
        swapChainDesc.Scaling = DXGI_SCALING_NONE;
        swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; // all apps must use this SwapEffect
        swapChainDesc.Flags = 0;

        // Identify the physical adapter (GPU or card) this device is runs on.
        ComPtr<IDXGIAdapter> dxgiAdapter;
        DX::ThrowIfFailed(
            dxgiDevice->GetAdapter(&dxgiAdapter)
            );

        // Get the factory object that created the DXGI device.
        ComPtr<IDXGIFactory2> dxgiFactory;
        DX::ThrowIfFailed(
            dxgiAdapter->GetParent(IID_PPV_ARGS(&dxgiFactory))
            );

        // Get the final swap chain for this window from the DXGI factory.
        DX::ThrowIfFailed(
            dxgiFactory->CreateSwapChainForCoreWindow(
                device.Get(),
                reinterpret_cast<IUnknown*>(m_window),
                &swapChainDesc,
                nullptr,    // allow on all displays
                &m_swapChain
                )
            );

        // Ensure that DXGI doesn't queue more than one frame at a time.
        DX::ThrowIfFailed(
            dxgiDevice->SetMaximumFrameLatency(1)
            );

    // Get the backbuffer for this window which is be the final 3D render target.
    ComPtr<ID3D11Texture2D> backBuffer;
    DX::ThrowIfFailed(
        m_swapChain->GetBuffer(0, IID_PPV_ARGS(&backBuffer))
        );

    // Now we set up the Direct2D render target bitmap linked to the swapchain. 
    // Whenever we render to this bitmap, it is directly rendered to the 
    // swap chain associated with the window.
    D2D1_BITMAP_PROPERTIES1 bitmapProperties = 
        BitmapProperties1(
            D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW,
            PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE),
            m_dpi,
            m_dpi
            );

    // Direct2D needs the dxgi version of the backbuffer surface pointer.
    ComPtr<IDXGISurface> dxgiBackBuffer;
    DX::ThrowIfFailed(
        m_swapChain->GetBuffer(0, IID_PPV_ARGS(&dxgiBackBuffer))
        );

    // Get a D2D surface from the DXGI back buffer to use as the D2D render target.
    DX::ThrowIfFailed(
        m_d2dContext->CreateBitmapFromDxgiSurface(
            dxgiBackBuffer.Get(),
            &bitmapProperties,
            &m_d2dTargetBitmap
            )
        );

    // Now we can set the Direct2D render target.
    m_d2dContext->SetTarget(m_d2dTargetBitmap.Get());

Vamos percorrer as etapas no exemplo de código anterior.

  1. Aloque uma estrutura DXGI_SWAP_CHAIN_DESC1 e defina as configurações para a cadeia de permuta .

    Essas configurações mostram um exemplo de como criar uma cadeia de permuta que um aplicativo da Windows Store pode usar.

  2. Obtenha o adaptador no qual o dispositivo Direct3D e o dispositivo DXGI estão a ser executados e obtenha o objeto IDXGIFactory associado a eles. Você deve usar esta fábrica DXGI para garantir que a cadeia de troca seja criada no mesmo adaptador.

  3. Chame o IDXGIFactory2::CreateSwapChainForCoreWindow método para criar a cadeia de permuta. Use a classeWindows::UI::CoreWindow para a janela principal de um aplicativo da Windows Store.

    Certifique-se de definir a latência máxima do quadro como 1 para minimizar o consumo de energia.

    Se tu quiseres renderizar conteúdo Direct2D numa aplicação da Windows Store, consulta o método CreateSwapChainForComposition.

  4. Obtenha o buffer traseiro da cadeia de permuta . O buffer traseiro expõe uma interface ID3D11Texture2D alocada pela cadeia de permuta

  5. Declare um D2D1_BITMAP_PROPERTIES1 struct e defina os valores de propriedade. Defina o formato de pixel como BGRA porque este é o formato que o dispositivo Direct3D e o dispositivo DXGI usar.

  6. Obtenha o buffer traseiro como um IDXGISurface para passar para o Direct2D. O Direct2D não aceita um ID3D11Texture2D diretamente.

    Crie um objeto ID2D1Bitmap usando o método ID2D1DeviceContext::CreateBitmapFromDxgiSurface a partir do buffer traseiro.

  7. Agora, ode bitmap Direct2Destá vinculado ao buffer traseiro. Defina o alvo no contexto do dispositivo Direct2Dpara definir o bitmap como .

Como renderizar e exibir

Agora que tem um bitmap de destino, pode desenhar primitivos, imagens, efeitos de imagem e texto nela usando o contexto do dispositivo Direct2D . O código aqui mostra como desenhar um retângulo.

ComPtr<ID2D1SolidColorBrush> pBlackBrush;
DX::ThrowIfFailed(
   m_d2dContext->CreateSolidColorBrush(
        D2D1::ColorF(D2D1::ColorF::Black),
        &pBlackBrush
        )
);

m_d2dContext->BeginDraw();

m_d2dContext->DrawRectangle(
    D2D1::RectF(
        rc.left + 100.0f,
        rc.top + 100.0f,
        rc.right - 100.0f,
        rc.bottom - 100.0f),
        pBlackBrush);

DX::ThrowIfFailed(
    m_d2dContext->EndDraw()
);

DX::ThrowIfFailed(
    m_swapChain->Present1(1, 0, &parameters);
);

Vamos percorrer as etapas no exemplo de código anterior.

  1. Chame o CreateSolidColorBrush para criar um pincel para pintar o retângulo.
  2. Chame o método BeginDraw antes de emitir qualquer comando de desenho.
  3. Chame o método DrawRectangle com o retângulo a ser desenhado e o pincel.
  4. Chame o método EndDraw depois de terminar de emitir comandos de desenho.
  5. Exiba o resultado chamando o método IDXGISwapChain::Present.

Agora você pode usar o contexto do dispositivo Direct2D desenhar primitivos, imagens, efeitos de imagem e texto na tela.