1

I use dxgi to capture window, since the windows maybe resized, so I use IDXGISwapChain1 and recreate framepool, but now I can't get the surface since GetRestrictToOutput always return null.

  void OnFrameArrived(winrt::Windows::Graphics::Capture::Direct3D11CaptureFramePool const &sender,winrt::Windows::Foundation::IInspectable const &)
    {
        const winrt::Windows::Graphics::Capture::Direct3D11CaptureFrame frame = sender.TryGetNextFrame();
        auto swapChainResizedToFrame = TryResizeSwapChain(frame);
    
        winrt::com_ptr<ID3D11Texture2D> backBuffer;
        winrt::check_hresult(m_swapChain->GetBuffer(0, winrt::guid_of<ID3D11Texture2D>(), backBuffer.put_void()));
        winrt::com_ptr<ID3D11Texture2D> frameSurface = GetDXGIInterfaceFromObject<ID3D11Texture2D>(frame.Surface());
        m_d3dContext->CopyResource(backBuffer.get(), frameSurface.get());
        DXGI_PRESENT_PARAMETERS presentParameters{};
        m_swapChain->Present1(1, 0, &presentParameters);
    
        //winrt::com_ptr<IDXGIOutput> dxgiOutput = nullptr;
        IDXGIOutput* dxgiOutput = nullptr;
        BOOL full;
        m_swapChain->GetRestrictToOutput(&dxgiOutput);
        if(dxgiOutput!=nullptr){
            std::cerr <<"33333333333333"<<std::endl;
...
        }
 m_framePool.Recreate(m_device, m_pixelFormat, 2, m_lastSize);

If I use getbuffer to get the image data, if the window size is changed, then the image is black, the code is as below:

winrt::com_ptr<ID3D11Texture2D> renderBuffer;
 winrt::check_hresult(m_swapChain->GetBuffer(0, winrt::guid_of<ID3D11Texture2D>(), renderBuffer.put_void()));
 if(renderBuffer != nullptr){
        D3D11_TEXTURE2D_DESC desc;
        renderBuffer->GetDesc(&desc);
        desc.Usage = D3D11_USAGE_STAGING;
        desc.BindFlags = 0;
        desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
        desc.MiscFlags = 0;
        desc.MipLevels = 1;
        desc.ArraySize = 1;
        desc.SampleDesc.Count = 1;
        winrt::com_ptr<ID3D11Texture2D> textureCopy;
        auto d3dDevice = GetDXGIInterfaceFromObject<ID3D11Device>(m_device);
        winrt::check_hresult(d3dDevice->CreateTexture2D(&desc, nullptr, textureCopy.put()));
        m_d3dContext->CopyResource(textureCopy.get(), renderBuffer.get());

        winrt::com_ptr<IDXGISurface> dxgi_surface = nullptr;
        HRESULT hr = textureCopy->QueryInterface(__uuidof(IDXGISurface), (void **)(&dxgi_surface));
        DXGI_MAPPED_RECT mapped_rect;
        hr = dxgi_surface->Map(&mapped_rect, DXGI_MAP_READ);

        unsigned int imgSize = desc.Width * desc.Height * 4;
        uint8_t* buffer = new uint8_t[imgSize];
        int dst_rowpitch = desc.Width * 4;
        for (unsigned int h = 0; h < desc.Height; h++) {
            memcpy_s(buffer + h * dst_rowpitch, dst_rowpitch, (BYTE*)mapped_rect.pBits + h * mapped_rect.Pitch, min(mapped_rect.Pitch, dst_rowpitch));
        }
        dxgi_surface->Unmap();
TONY
  • 101
  • 7
  • It should be IDXGISwapChain::GetBuffer method https://learn.microsoft.com/en-us/windows/win32/api/dxgi/nf-dxgi-idxgiswapchain-getbuffer – Simon Mourier Feb 07 '21 at 10:41
  • If the window's size is changed, then the image I got from getbuffer is black. I use the following code to get the image data – TONY Feb 08 '21 at 07:22
  • You can get IDXGISurface directly from GetBuffer. When the window size changes you must call IDXGISwapChain::ResizeBuffers – Simon Mourier Feb 08 '21 at 07:30
  • I have called DXGISwapChain::ResizeBuffers in TryResizeSwapChain. In addition, the IDXGISurface I got from GetBuffer is always null. winrt::com_ptr renderBuffer; winrt::check_hresult(m_swapChain->GetBuffer(0, winrt::guid_of(), renderBuffer.put_void())); – TONY Feb 08 '21 at 08:01
  • Difficult to say. Since you're using winrt, it's possible there are restrictions. Post a small reproducing project. – Simon Mourier Feb 08 '21 at 08:06

0 Answers0