C++ D3D11屏幕桌面复制到ID3D11Texture2D

C++ D3D11屏幕桌面复制到ID3D11Texture2D,c++,directx,direct3d,C++,Directx,Direct3d,我正在编写一个DLL插件,它将读取桌面帧缓冲区(整个屏幕),并将其直接渲染为传入的Texture2D指针。目标是将所有内容都保存在视频内存中(并避免复制回系统内存和视频内存的成本) 我能够通过Texture2D(显示为ID3D11Texture2D),但在使用D3D11获取桌面帧缓冲区时遇到问题。D3D9提供了GetFrontBufferData(),但D3D11的解决方案似乎是使用GetBuffer() 我的问题是获取IDXGISwapChain。因为我想读取桌面帧缓冲区,只需通过GetBuf

我正在编写一个DLL插件,它将读取桌面帧缓冲区(整个屏幕),并将其直接渲染为传入的Texture2D指针。目标是将所有内容都保存在视频内存中(并避免复制回系统内存和视频内存的成本)

我能够通过Texture2D(显示为ID3D11Texture2D),但在使用D3D11获取桌面帧缓冲区时遇到问题。D3D9提供了GetFrontBufferData(),但D3D11的解决方案似乎是使用GetBuffer()

我的问题是获取IDXGISwapChain。因为我想读取桌面帧缓冲区,只需通过GetBuffer()读取内容并将其显示在ID3D11Texture2D上。我正在使用ID3D11设备,我不知道如何获取其IDXGISwapChain

我有如下代码来获取帧缓冲区并将其放在纹理上:

ID3D11Texture2D* src = (ID3D11Texture2D*)g_TexturePointer;
ID3D11Texture2D* dst = NULL;
HRESULT hr = swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&dst);
g_devCon->CopyResource(dst, src);
在这里,我实际上使用D3D11CreateDeviceAndSwapChain()创建了自己的swapchain,但我想知道这是否必要,因为我已经有了ID3D11设备


CopyResource()似乎也失败了。

不一定所有桌面内容都会使用D3D11呈现。DXGI是Windows上所有图形的底层系统,因此您肯定需要以某种方式使用它来捕获桌面。但是,D3D11构建在DXGI上(例如,ID3D11Texture2D支持IDXGIResource接口)。下面的代码示例显示了如何将整个监视器的输出捕获到D3D11分段纹理中:

// 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.

不幸的是,在调用
IDXGIOutput::TakeOwnership
时,它会产生令人讨厌的副作用,将输出变成黑色。但是,如果没有此调用,
GetDiplaySurfaceData1
将失败。根据您的情况,这可能是可以接受的。

当您说“桌面”时,我假设您指的是应用程序的窗口,而不是整个windows桌面?不,我想抓住整个windows桌面。对不起,不精确。