D3D11 screen desktop copy to ID3D11Texture2D

匿名 (未验证) 提交于 2019-12-03 03:04:01

问题:

I am writing a DLL plugin that will read the desktop frame buffer (whole screen) and render it directly into a Texture2D pointer that is passed in. The goal is to keep everything in video memory (and avoid the cost of copying back to system memory and back to video memory).

I am able to pass the Texture2D (showing up as a ID3D11Texture2D), but I am having issues grabbing the desktop frame buffer with D3D11. D3D9 offered GetFrontBufferData() but it seems D3D11 solution is to use GetBuffer().

My issue is about getting the IDXGISwapChain. Because I want to read the desktop frame buffer and simply read the content via GetBuffer() and display it on the ID3D11Texture2D. I am getting a ID3D11Device I do not understand how to get its IDXGISwapChain.

I have code as follows to get the frame buffer and put it on the Texture:

ID3D11Texture2D* src = (ID3D11Texture2D*)g_TexturePointer; ID3D11Texture2D* dst = NULL; HRESULT hr = swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&dst); g_devCon->CopyResource(dst, src); 

Here I actually created my own swapchain using D3D11CreateDeviceAndSwapChain() but I wonder if it is necessary as I already have a ID3D11Device.

The CopyResource() also seems to fail.

回答1:

Not necessarily all desktop content would be rendered with D3D11. DXGI is the underlying system for all graphics on Windows, so you will definitely need to use it in some way to get a capture of the desktop. However, D3D11 is built on DXGI (for example, ID3D11Texture2D supports the IDXGIResource interface). The code sample below shows how you can capture the output of an entire monitor into a D3D11 staging texture:

// IDXGIOutput* poutput = ...; // from DXGIAdapter::EnumOutputs.  // Get description of desktop. DXGI_OUTPUT_DESC outdesc; poutput->GetDesc(&outdesc);  // Create destination texture, sized same as desktop. D3D11_TEXTURE2D_DESC texDesc; memset(&texDesc, 0, sizeof(texDesc)); texDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; texDesc.BindFlags = 0; texDesc.Width  = outdesc.DesktopCoordinates.right - outdesc.DesktopCoordinates.left; texDesc.Height = outdesc.DesktopCoordinates.bottom - outdesc.DesktopCoordinates.top; texDesc.MipLevels = 1; texDesc.SampleDesc = { 1, 0 }; texDesc.Usage = D3D11_USAGE_STAGING; texDesc.ArraySize = 1; ID3D11Texture2D* destinationTexture = 0; pDevice->CreateTexture2D(&texDesc, 0, &destinationTexture); // check HRESULT.  // Get IDXGIResource from texture. IDXGIResource* destinationResource=0; destinationTexture->QueryInterface(IID_PPV_ARGS(&destinationResource)); // check HRESULT.  // Get data. IDXGIOutput1* poutput1; poutput->QueryInterface(IID_PPV_ARGS(&poutput1)); // check HRESULT. poutput1->TakeOwnership(pDevice, TRUE); poutput1->GetDisplaySurfaceData1(destinationResource); // check HRESULT. poutput1->ReleaseOwnership();  // Now use destinationTexture, it contains the contents of the desktop. 

Unfortunately, it has the nasty side effect of turning the output black during the IDXGIOutput::TakeOwnership call. However, without this call, the GetDiplaySurfaceData1 will fail. Depending on your situation, this may be acceptable.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!