Compartilhar via


Como renderizar usando um contexto de dispositivo Direct2D

Neste tópico, você aprenderá a criar Direct2Dcontexto de dispositivo em Windows 8. Essas informações se aplicam a você se você estiver desenvolvendo aplicativos da Windows Store ou um aplicativo da área de trabalho usando Direct2D. Este tópico descreve a finalidade de Direct2D objetos de contexto do dispositivo, como criar esse objeto e um guia passo a passo sobre renderização e exibição de Direct2D primitivos e imagens. Você também aprenderá a 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 Direct2D contexto de dispositivo. Um dispositivo Direct2D (expõe um ponteiro de interface ID2D1Device) representa um adaptador de exibição. 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 Direct2Ddispositivo (expõe um ponteiro de interface ID2D1DeviceContext) representa um conjunto de buffers de estado e comando que você usa para renderizar em um destino. Você pode chamar métodos no contexto do dispositivo para definir o estado do pipeline e gerar comandos de renderização usando os recursos pertencentes a 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 em um Hwnd se quiser criar um aplicativo da área de trabalho e ainda aproveitar os recursos adicionais do contexto do dispositivo . No entanto, o contexto do dispositivo é necessário para renderizar conteúdo em aplicativos da Windows Store com Direct2D.

Por que usar um contexto de dispositivo para renderizar?

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, por fim, criar o contexto do dispositivo Direct2D para renderização.

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

diagrama de dispositivos direct2d e direct3d e contextos de dispositivo.

Observação

Esse código pressupõe que você já tenha um objeto ID2D1Factory1 . 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 de interface ID3D11Device de que você precisará para criar o contexto do dispositivo.

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

    • Declare uma matriz de entradas D3D_FEATURE_LEVEL que representam o conjunto de níveis de recursos aos quais seu aplicativo dará suporte.

      Observação

      O Direct3D pesquisa sua lista até encontrar o nível de recurso compatível com o sistema host.

       

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

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

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

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

Selecionando um destino

O código aqui mostra como obter a textura Direct3D bidimensional para o buffer de fundo da janela e criar um destino de bitmap que se 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 de DXGI_SWAP_CHAIN_DESC1 e defina as configurações para a cadeia de troca.

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

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

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

    Defina a latência máxima do quadro como 1 para minimizar o consumo de energia.

    Se você quiser renderizar Direct2D conteúdo em um aplicativo da Windows Store, consulte o método CreateSwapChainForComposition.

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

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

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

    Crie um objeto ID2D1Bitmap do buffer de fundo usando o método ID2D1DeviceContext::CreateBitmapFromDxgiSurface .

  7. Agora, o bitmap Direct2D está vinculado ao buffer de fundo. Defina o destino no contexto do dispositivo Direct2D como o bitmap.

Como renderizar e exibir

Agora que você tem um bitmap de destino, pode desenhar primitivos, imagens, efeitos de imagem e texto para ele 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 CreateSolidColorBrush para criar um pincel para pintar o retângulo.
  2. Chame o método BeginDraw antes de emitir comandos de desenho.
  3. Chame o método DrawRectangle de retângulo a ser desenhado e o pincel.
  4. Chame o método EndDraw depois de concluir a emissão de comandos de desenho.
  5. Exiba o resultado chamando o método IDXGISwapChain::P resent .

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