Dela via


Så här renderar du med hjälp av en Direct2D-enhetskontext

I det här avsnittet får du lära dig mer om att skapa Direct2Denhetskontext i Windows 8. Den här informationen gäller för dig om du utvecklar Windows Store-appar eller en skrivbordsapp med hjälp av Direct2D. Det här avsnittet beskriver syftet med Direct2D-enhetskontextobjekt, hur du skapar objektet och en stegvis guide om rendering och visning av Direct2D-primitiver och bilder. Du får också lära dig mer om att byta renderingsmål och lägga till effekter i din app.

Vad är en Direct2D-enhet?

Du behöver en Direct2D-enhet och en Direct3D-enhet för att skapa en Direct2D-enhetskontext. En Direct2D-enhet (exponerar en ID2D1Enhet gränssnittspekare) representerar ett bildskärmskort. En Direct3D-enhet (exponerar en ID3D11Enhet gränssnittspekare) är associerad med en Direct2D-enhet. Varje app måste ha en Direct2D-enhet, men kan ha fler än en enhet.

Vad är en Direct2D-enhetskontext?

En Direct2Denhetskontext (exponerar en ID2D1DeviceContext gränssnittspekare) representerar en uppsättning tillstånds- och kommandobuffertar som du använder för att återge till ett mål. Du kan anropa metoder i enhetskontexten för att ange pipelinetillstånd och generera återgivningskommandon med hjälp av de resurser som ägs av en enhet.

Rendering med Direct2D på Windows 8

I Windows 7 och tidigare använder du ett ID2D1HwndRenderTarget- eller ett annat återgivningsmålgränssnitt för att rendera till ett fönster eller en yta. Från och med Windows 8 rekommenderar vi inte rendering med hjälp av metoder som förlitar sig på gränssnitt som ID2D1HwndRenderTarget eftersom de inte fungerar med Windows Store-appar. Du kan använda en enhetskontext för att rendera till en Hwnd om du vill skapa en skrivbordsapp och fortfarande dra nytta av enhetskontextens ytterligare funktioner. Den enhetskontexten krävs dock för att återge innehåll i Windows Store-appar med Direct2D.

Varför ska du använda en enhetskontext för att återge?

Så här skapar du en Direct2D-enhetskontext för återgivning

Koden här visar hur du skapar en Direct3D11-enhet, hämtar den associerade DXGI-enheten, skapar en Direct2D-enhetoch slutligen skapar Direct2D-enhetskontext för återgivning.

Här är ett diagram över metodanropen och de gränssnitt som den här koden använder.

diagram över direct2d- och direct3d-enheter och enhetskontexter.

Notera

Den här koden förutsätter att du redan har ett ID2D1Factory1--objekt. Mer information finns på referenssidan 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
            )
        );

Nu ska vi gå igenom stegen i föregående kodexempel.

  1. Hämta en ID3D11Enhetsgränssnittspekare som du behöver för att skapa enhetskontexten.

    • Deklarera skapandeflaggor för att konfigurera Direct3D enhet för BGRA-stöd. Direct2D- kräver BGRA-färgordning.

    • Deklarera en matris med D3D_FEATURE_LEVEL element som representerar den uppsättning funktionsnivåer som appen stöder.

      Anteckning

      Direct3D- söker i listan tills den hittar den funktionsnivå som stöds av värdsystemet.

       

    • Använd funktionen D3D11CreateDevice för att skapa ett ID3D11Enhet-objekt. Funktionen returnerar också ett ID3D11EnhetKontext objekt, men det objektet behövs inte för det här exemplet.

  2. Fråga Direct3D 11-enheten för dess DXGI-enhetsgränssnitt.

  3. Skapa ett ID2D1Device-objekt genom att anropa metoden ID2D1Factory::CreateDevice och överföra IDXGIDevice-objektet.

  4. Skapa en ID2D1DeviceContext pekare med hjälp av metoden ID2D1Device::CreateDeviceContext.

Välja ett mål

Koden här visar hur du hämtar 2-dimensionell Direct3D-textur för fönstrets buffert och skapar ett bitmappsmål som länkar till den här strukturen som Direct2D-enhetskontexten renderas till.

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

Vi går igenom stegen i föregående kodexempel.

  1. Allokera en DXGI_SWAP_CHAIN_DESC1 struktur och definiera inställningarna för växlingskedja.

    De här inställningarna visar ett exempel på hur du skapar en växlingskedja som en Windows Store-app kan använda.

  2. Hämta adaptern som Direct3D-enheten och DXGI-enheten körs på och hämta det IDXGIFactory- objekt som är associerat med dem. Du måste använda den här DXGI-fabriken för att säkerställa att växlingskedja har skapats på samma adapter.

  3. Anropa metoden IDXGIFactory2::CreateSwapChainForCoreWindow för att skapa växlingskedjan. Använd klassen Windows::UI::CoreWindow för huvudfönstret i en Windows Store-app.

    Se till att ange den maximala bildrutefördröjningen till 1 för att minimera energiförbrukningen.

    Om du vill återge Direct2D-innehåll i en Windows Store-app kan du läsa metoden CreateSwapChainForComposition.

  4. Hämta bufferten från växlingskedjan. Serverbufferten exponerar ett ID3D11Texture2D- gränssnitt som allokerats av

  5. Deklarera en D2D1_BITMAP_PROPERTIES1 struct och ange egenskapsvärdena. Ange pixelformatet till BGRA eftersom det här är formatet som Direct3D-enhet och DXGI-enhet använda.

  6. Hämta bufferten som en IDXGISurface- för att skicka till Direct2D. Direct2D accepterar inte en ID3D11Texture2D direkt.

    Skapa ett ID2D1Bitmap- objekt från den bakre bufferten med hjälp av metoden ID2D1DeviceContext::CreateBitmapFromDxgiSurface.

  7. Nu är Direct2D-bitmappen länkad till serverbufferten. Ange målet för enhetskontexten Direct2D till bitmappen .

Så här renderar och visar du

Nu när du har en målbitmapp kan du rita primitiver, bilder, bildeffekter och text till den med hjälp av Direct2D-enhetskontext. Koden här visar hur du ritar en rektangel.

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

Vi går igenom stegen i föregående kodexempel.

  1. Anropa CreateSolidColorBrush för att skapa en borste för att måla på rektangeln.
  2. Anropa metoden BeginDraw innan du utfärdar några ritkommandon.
  3. Anropa metoden DrawRectangle för rektangeln som ska ritas och penseln.
  4. Anropa metoden EndDraw när du har utfärdat ritkommandon.
  5. Visa resultatet genom att anropa metoden IDXGISwapChain::Present.

Nu kan du använda Direct2D-enhetskontext rita primitiver, bilder, bildeffekter och text på skärmen.