Comment effectuer un rendu à l’aide d’un contexte d’appareil Direct2D

Dans cette rubrique, vous allez découvrir comment créer un contexte d’appareilDirect2D dans Windows 8. Ces informations s’appliquent à vous si vous développez des applications du Windows Store ou une application de bureau à l’aide de Direct2D. Cette rubrique décrit l’objectif des objets de contexte d’appareil Direct2D, la façon de créer cet objet et un guide pas à pas sur le rendu et l’affichage des primitives et des images Direct2D. Vous découvrirez également comment changer de cible de rendu et ajouter des effets à votre application.

Qu’est-ce qu’un appareil Direct2D ?

Vous avez besoin d’un appareil Direct2D et d’un appareil Direct3D pour créer un contexte d’appareil Direct2D. Un appareil Direct2D (expose un pointeur d’interface ID2D1Device ) représente un adaptateur d’affichage. Un appareil Direct3D (expose un pointeur d’interface ID3D11Device ) est associé à un appareil Direct2D. Chaque application doit avoir un appareil Direct2D, mais peut avoir plusieurs appareils.

Qu’est-ce qu’un contexte d’appareil Direct2D ?

Un contexte d’appareilDirect2D (expose un pointeur d’interface ID2D1DeviceContext) représente un ensemble de mémoires tampons d’état et de commande que vous utilisez pour afficher une cible. Vous pouvez appeler des méthodes sur le contexte de l’appareil pour définir l’état du pipeline et générer des commandes de rendu à l’aide des ressources appartenant à un appareil.

Rendu avec Direct2D sur Windows 8

Sur Windows 7 et versions antérieures, vous utilisez un ID2D1HwndRenderTarget ou une autre interface cible de rendu pour effectuer le rendu sur une fenêtre ou une surface. À compter de Windows 8, nous déconseillons le rendu à l’aide de méthodes qui s’appuient sur des interfaces telles que ID2D1HwndRenderTarget, car elles ne fonctionnent pas avec les applications du Windows Store. Vous pouvez utiliser un contexte d’appareil pour effectuer un rendu vers un Hwnd si vous souhaitez créer une application de bureau tout en tirant parti des fonctionnalités supplémentaires du contexte de l’appareil . Toutefois, le contexte de l’appareil est requis pour restituer du contenu dans une application du Windows Store avec Direct2D.

Pourquoi utiliser un contexte d’appareil pour le rendu ?

Comment créer un contexte d’appareil Direct2D pour le rendu

Le code ici vous montre comment créer un appareil Direct3D11, obtenir l’appareil DXGI associé, créer un appareil Direct2D, puis enfin créer le contexte d’appareil Direct2D pour le rendu.

Voici un diagramme des appels de méthode et des interfaces utilisées par ce code.

diagramme des appareils direct2d et direct3d et des contextes d’appareil.

Notes

Ce code suppose que vous disposez déjà d’un objet ID2D1Factory1 . Pour plus d’informations, consultez la page de référence 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
            )
        );

Passons en revue les étapes de l’exemple de code précédent.

  1. Obtenez un pointeur d’interface ID3D11Device dont vous aurez besoin pour créer le contexte de l’appareil.

    • Déclarez les indicateurs de création pour configurer l’appareil Direct3D pour la prise en charge de BGRA. Direct2D nécessite un ordre de couleur BGRA.

    • Déclarez un tableau d’entrées D3D_FEATURE_LEVEL représentant l’ensemble des niveaux de fonctionnalités pris en charge par votre application.

      Notes

      Direct3D recherche votre liste jusqu’à ce qu’il trouve le niveau de fonctionnalité pris en charge par le système hôte.

       

    • Utilisez la fonction D3D11CreateDevice pour créer un objet ID3D11Device . La fonction retourne également un objet ID3D11DeviceContext , mais cet objet n’est pas nécessaire pour cet exemple.

  2. Interrogez l’appareil Direct3D 11 pour son interface DXGI Device .

  3. Créez un objet ID2D1Device en appelant la méthode ID2D1Factory::CreateDevice et en transmettant l’objet IDXGIDevice .

  4. Créez un pointeur ID2D1DeviceContext à l’aide de la méthode ID2D1Device::CreateDeviceContext .

Sélection d’une cible

Le code ici vous montre comment obtenir la texture Direct3D 2 dimensions pour la mémoire tampon arrière de la fenêtre et créer une cible bitmap qui lie à cette texture à laquelle le contexte d’appareil Direct2D s’affiche.

        // 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());

Passons en revue les étapes de l’exemple de code précédent.

  1. Allouez une structure DXGI_SWAP_CHAIN_DESC1 et définissez les paramètres de la chaîne d’échange.

    Ces paramètres montrent un exemple de création d’une chaîne d’échange qu’une application du Windows Store peut utiliser.

  2. Obtenez l’adaptateur sur lequel l’appareil Direct3D et l’appareil DXGI s’exécutent et obtenez l’objet IDXGIFactory qui leur est associé. Vous devez utiliser cette fabrique DXGI pour vous assurer que la chaîne d’échange est créée sur la même carte.

  3. Appelez la méthode IDXGIFactory2::CreateSwapChainForCoreWindow pour créer la chaîne d’échange. Utilisez la classe Windows::UI::CoreWindow pour la fenêtre main d’une application du Windows Store.

    Veillez à définir la latence maximale des images sur 1 pour réduire la consommation d’énergie.

    Si vous souhaitez restituer du contenu Direct2D dans une application du Windows Store, consultez la méthode CreateSwapChainForComposition .

  4. Récupérez la mémoire tampon arrière à partir de la chaîne d’échange. La mémoire tampon arrière expose une interface ID3D11Texture2D allouée par la chaîne d’échange

  5. Déclarez un struct D2D1_BITMAP_PROPERTIES1 et définissez les valeurs de propriété. Définissez le format de pixel sur BGRA, car il s’agit du format utilisé par l’appareil Direct3D et l’appareil DXGI .

  6. Récupérez la mémoire tampon arrière en tant qu’IDXGISurface à passer à Direct2D. Direct2D n’accepte pas d’ID3D11Texture2D directement.

    Créez un objet ID2D1Bitmap à partir de la mémoire tampon arrière à l’aide de la méthode ID2D1DeviceContext::CreateBitmapFromDxgiSurface .

  7. À présent, la bitmap Direct2D est liée à la mémoire tampon arrière. Définissez la cible sur le contexte d’appareil Direct2D sur la bitmap.

Comment afficher et afficher le rendu

Maintenant que vous disposez d’une bitmap cible, vous pouvez y dessiner des primitives, des images, des effets d’image et du texte à l’aide du contexte de l’appareil Direct2D. Le code ici vous montre comment dessiner un rectangle.

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);
);

Passons en revue les étapes de l’exemple de code précédent.

  1. Appelez CreateSolidColorBrush pour créer un pinceau pour peindre le rectangle.
  2. Appelez la méthode BeginDraw avant d’émettre des commandes de dessin.
  3. Appelez la méthode DrawRectangle le rectangle à dessiner et le pinceau.
  4. Appelez la méthode EndDraw une fois que vous avez terminé d’émettre des commandes de dessin.
  5. Affichez le résultat en appelant la méthode IDXGISwapChain::P resent .

Vous pouvez maintenant utiliser le contexte de l’appareil Direct2D pour dessiner des primitives, des images, des effets d’image et du texte à l’écran.