Rendern mithilfe eines Direct2D-Gerätekontexts

In diesem Thema erfahren Sie, wie Sie den Direct2D-Gerätekontext in Windows 8 erstellen. Diese Informationen gelten für Sie, wenn Sie Windows Store-Apps oder eine Desktop-App mithilfe von Direct2D entwickeln. In diesem Thema werden der Zweck von Direct2D-Gerätekontextobjekten, das Erstellen dieses Objekts und eine schrittweise Anleitung zum Rendern und Anzeigen von Direct2D-Grundtypen und Bildern beschrieben. Außerdem erfahren Sie mehr über das Wechseln von Renderzielen und das Hinzufügen von Effekten zu Ihrer App.

Was ist ein Direct2D-Gerät?

Sie benötigen ein Direct2D-Gerät und ein Direct3D-Gerät, um einen Direct2D-Gerätekontext zu erstellen. Ein Direct2D-Gerät (macht einen ID2D1Device-Schnittstellenzeiger verfügbar) stellt einen Grafikkarte dar. Ein Direct3D-Gerät (macht einen ID3D11Device-Schnittstellenzeiger verfügbar) ist einem Direct2D-Gerät zugeordnet. Jede App muss über ein Direct2D-Gerät verfügen, kann jedoch über mehrere Geräte verfügen.

Was ist ein Direct2D-Gerätekontext?

Ein Direct2D-Gerätekontext (macht einen ID2D1DeviceContext-Schnittstellenzeiger verfügbar) stellt eine Gruppe von Zustands- und Befehlspuffern dar, die Sie zum Rendern in einem Ziel verwenden. Sie können Methoden im Gerätekontext aufrufen, um den Pipelinestatus festzulegen und Renderingbefehle mithilfe der Ressourcen zu generieren, die einem Gerät gehören.

Rendern mit Direct2D auf Windows 8

Unter Windows 7 und früher verwenden Sie ein ID2D1HwndRenderTarget oder eine andere Renderzielschnittstelle, um in einem Fenster oder einer Oberfläche zu rendern. Ab Windows 8 wird die Verwendung von Methoden, die auf Schnittstellen wie ID2D1HwndRenderTarget basieren, nicht empfohlen, da sie nicht mit Windows Store-Apps funktionieren. Sie können einen Gerätekontext verwenden, um in einem Hwnd zu rendern, wenn Sie eine Desktop-App erstellen möchten und dennoch die zusätzlichen Features des Gerätekontexts nutzen möchten. Der Gerätekontext ist jedoch erforderlich, um Inhalte in einer Windows Store-App mit Direct2D zu rendern.

Warum einen Gerätekontext zum Rendern verwenden?

Erstellen eines Direct2D-Gerätekontexts zum Rendern

Der Code hier zeigt, wie Sie ein Direct3D11-Gerät erstellen, das zugehörige DXGI-Gerät abrufen, ein Direct2D-Gerät erstellen und schließlich den Direct2D-Gerätekontext zum Rendern erstellen.

Hier sehen Sie ein Diagramm der Methodenaufrufe und der Schnittstellen, die dieser Code verwendet.

Diagramm der direct2d- und direct3d-Geräte und Gerätekontexte.

Hinweis

In diesem Code wird davon ausgegangen, dass Sie bereits über ein ID2D1Factory1-Objekt verfügen. Weitere Informationen finden Sie auf der Referenzseite 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
            )
        );

Im Folgenden werden die Schritte im vorherigen Codebeispiel beschrieben.

  1. Rufen Sie einen ID3D11Geräteschnittstellenzeiger ab, den Sie zum Erstellen des Gerätekontexts benötigen.

    • Deklarieren Sie die Erstellungsflags, um das Direct3D-Gerät für die BGRA-Unterstützung einzurichten. Direct2D erfordert die BGRA-Farbreihenfolge.

    • Deklarieren Sie ein Array von D3D_FEATURE_LEVEL Einträgen, die den Satz von Featureebenen darstellen, die Ihre App unterstützt.

      Hinweis

      Direct3D durchsucht Ihre Liste, bis die vom Hostsystem unterstützte Featureebene gefunden wird.

       

    • Verwenden Sie die D3D11CreateDevice-Funktion , um ein ID3D11Device-Objekt zu erstellen. Die Funktion gibt auch ein ID3D11DeviceContext-Objekt zurück, aber dieses Objekt wird für dieses Beispiel nicht benötigt.

  2. Fragen Sie das Direct3D 11-Gerät nach seiner DXGI-Geräteschnittstelle ab.

  3. Erstellen Sie ein ID2D1Device-Objekt , indem Sie die ID2D1Factory::CreateDevice-Methode aufrufen und das IDXGIDevice-Objekt übergeben.

  4. Erstellen Sie mithilfe der ID2D1DeviceContext-Methode einen ID2D1Device::CreateDeviceContext-Zeiger .

Auswählen eines Ziels

Der Code hier zeigt, wie Sie die zweidimensionale Direct3D-Textur für den Fensterrückpuffer abrufen und ein Bitmapziel erstellen, das mit dieser Textur verknüpft ist, mit der der Direct2D-Gerätekontext gerendert wird.

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

Im Folgenden werden die Schritte im vorherigen Codebeispiel beschrieben.

  1. Ordnen Sie eine DXGI_SWAP_CHAIN_DESC1-Struktur zu, und definieren Sie die Einstellungen für die Swapchain.

    Diese Einstellungen zeigen ein Beispiel für das Erstellen einer Swapchain, die eine Windows Store-App verwenden kann.

  2. Rufen Sie den Adapter ab, auf dem das Direct3D-Gerät und das DXGI-Gerät ausgeführt werden, und rufen Sie das ihnen zugeordnete IDXGIFactory-Objekt ab. Sie müssen diese DXGI-Factory verwenden, um sicherzustellen, dass die Swapchain auf demselben Adapter erstellt wird.

  3. Rufen Sie die IDXGIFactory2::CreateSwapChainForCoreWindow-Methode auf, um die Swap chain zu erstellen. Verwenden Sie die Windows::UI::CoreWindow-Klasse für das Standard Fenster einer Windows Store-App.

    Stellen Sie sicher, dass Sie die maximale Framelatenz auf 1 festlegen, um den Energieverbrauch zu minimieren.

    Wenn Sie Direct2D-Inhalte in einer Windows Store-App rendern möchten, lesen Sie die CreateSwapChainForComposition-Methode .

  4. Rufen Sie den Backpuffer aus der Swapchain ab. Der Backpuffer macht eine ID3D11Texture2D-Schnittstelle verfügbar, die von der Swap chain zugewiesen wird.

  5. Deklarieren Sie eine D2D1_BITMAP_PROPERTIES1 Struktur, und legen Sie die Eigenschaftswerte fest. Legen Sie das Pixelformat auf BGRA fest, da dies das Format ist, das das Direct3D-Gerät und das DXGI-Gerät verwenden.

  6. Rufen Sie den Backpuffer als IDXGISurface ab, um an Direct2D zu übergeben. Direct2D akzeptiert keinen ID3D11Texture2D direkt.

    Erstellen Sie ein ID2D1Bitmap-Objekt aus dem Backpuffer mithilfe der ID2D1DeviceContext::CreateBitmapFromDxgiSurface-Methode .

  7. Nun ist die Direct2D-Bitmap mit dem Backpuffer verknüpft. Legen Sie das Ziel im Direct2D-Gerätekontext auf die Bitmap fest.

Rendern und Anzeigen

Nachdem Sie nun über eine Ziel-Bitmap verfügen, können Sie Primitive, Bilder, Bildeffekte und Text mithilfe des Direct2D-Gerätekontexts zeichnen. Der Code hier zeigt Ihnen, wie Sie ein Rechteck zeichnen.

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

Im Folgenden werden die Schritte im vorherigen Codebeispiel beschrieben.

  1. Rufen Sie CreateSolidColorBrush auf, um einen Pinsel zum Zeichnen des Rechtecks zu erstellen.
  2. Rufen Sie die BeginDraw-Methode auf, bevor Sie Zeichnungsbefehle ausgeben.
  3. Rufen Sie die DrawRectangle-Methode das zu zeichnende Rechteck und den Pinsel auf.
  4. Rufen Sie die EndDraw-Methode auf, nachdem Sie die Zeichenbefehle ausgegeben haben.
  5. Zeigen Sie das Ergebnis an, indem Sie die IDXGISwapChain::P resent-Methode aufrufen.

Jetzt können Sie den Direct2D-Gerätekontext verwenden, um Primitiven, Bilder, Bildeffekte und Text auf den Bildschirm zu zeichnen.