I am receiving IDirect3DSurfaces from a FrameReader and wish to render them to a SwapChain in a WinUI3 desktop app.

I have followed DirectX and XAML interop to implement the SwapChain, including this fix.

My research suggests I need to create a Bitmap from the surface returned from the frame and use Direct2D to render that bitmap on the SwapChain back-buffer. Here is the code with the two approaches I have tried, selected via preprocessor for the moment.

    winrt::Windows::Graphics::DirectX::Direct3D11::IDirect3DSurface surface = 
        frameRef.VideoMediaFrame().Direct3DSurface();
    winrt::com_ptr<::Windows::Graphics::DirectX::Direct3D11::IDirect3DDxgiInterfaceAccess> dxgiInterfaceAccess{
        surface.as<::Windows::Graphics::DirectX::Direct3D11::IDirect3DDxgiInterfaceAccess>()
    };

    winrt::com_ptr<::IDXGISurface> nativeSurface;
    winrt::check_hresult(
        dxgiInterfaceAccess->GetInterface(__uuidof(nativeSurface), nativeSurface.put_void())
    );

#if 0
    winrt::com_ptr<::ID2D1Bitmap> frameBitmap;
    winrt::check_hresult(
        d2dDeviceContext->CreateSharedBitmap(
            __uuidof(nativeSurface), 
            nativeSurface.get(), 
            nullptr, 
            frameBitmap.put())
    );
#else       
    winrt::com_ptr<::ID2D1Bitmap1> frameBitmap;
    winrt::check_hresult(
        d2dDeviceContext->CreateBitmapFromDxgiSurface(
            nativeSurface.get(),
            nullptr,
            frameBitmap.put()
        )
    );
#endif

    // Both approaches fail before getting here!

    winrt::com_ptr<::IDXGISurface> dxgiBackBuffer;
    swapChain->GetBuffer(0, __uuidof(dxgiBackBuffer), dxgiBackBuffer.put_void());

    winrt::com_ptr<::ID2D1Bitmap1> targetBitmap;
    winrt::check_hresult(
        d2dDeviceContext->CreateBitmapFromDxgiSurface(
            dxgiBackBuffer.get(),
            nullptr,
            targetBitmap.put()
        )
    );

    d2dDeviceContext->SetTarget(targetBitmap.get());
    d2dDeviceContext->BeginDraw();
    d2dDeviceContext->DrawBitmap(frameBitmap.get());
    d2dDeviceContext->EndDraw();

Both most often fail with "pixel format not supported". As per the guide, the d3dDevice is created with D3D11_CREATE_DEVICE_BGRA_SUPPORT. I have tried creating the frame reader with MediaEncodingSubtypes::Bgra8() as well as testing many other formats with no luck.

As a final note, the second approach sometimes fails with "0x88990003 : The requested operation is not supported." for certain MediaEncodingSubtypes, for example Argb32.

0

There are 0 best solutions below