我正在修改桌面复制api示例kindly provided by Microsoft以捕获屏幕并通过网络将更新发送到我的应用程序。我知道如何实际发送数据;我的问题是从ID3D11Texture2D对象获取数据。
ID3D11Texture2D* m_AcquiredDesktopImage;
IDXGIResource* desktopResource = nullptr;
DXGI_OUTDUPL_FRAME_INFO FrameInfo;
// Get new frame
HRESULT hr = m_DeskDupl->AcquireNextFrame(500, &FrameInfo, &desktopResource);
// QI for IDXGIResource
hr = desktopResource->QueryInterface(__uuidof(ID3D11Texture2D), reinterpret_cast<void **>(&m_AcquiredDesktopImage));
此时,我认为屏幕更新位于m_AcquiredDesktopImage
。我需要通过线路传输这些数据(尽可能高效)。
This answer似乎走在正确的轨道上,但我是Windows编程的新手,所以我需要一些额外的帮助。
这是我能用 IDXGIObject::GetPrivateData
答案 0 :(得分:2)
私人数据不是您正在寻找的。它们仅用于将自定义值附加到d3d对象。
一旦你有ID3D11Texture2D
对象需要从中回读图像,你需要在ID3D11Device
的暂存内存池中创建第二个(获取原始描述,更改池) ,并删除绑定。)
然后,您需要使用ID3D11DeviceContext
使用CopyResource
将纹理复制到暂存状态。然后,您可以使用上下文Map
和Unmap
api来阅读图片。
答案 1 :(得分:2)
我有一个很好的链接可以做到这一点..寻找方法SaveTextureToBmp
[...]
// map the texture
ComPtr<ID3D11Texture2D> mappedTexture;
D3D11_MAPPED_SUBRESOURCE mapInfo;
mapInfo.RowPitch;
hr = d3dContext->Map(
Texture,
0, // Subresource
D3D11_MAP_READ,
0, // MapFlags
&mapInfo);
if (FAILED(hr)) {
// If we failed to map the texture, copy it to a staging resource
if (hr == E_INVALIDARG) {
D3D11_TEXTURE2D_DESC desc2;
desc2.Width = desc.Width;
desc2.Height = desc.Height;
desc2.MipLevels = desc.MipLevels;
desc2.ArraySize = desc.ArraySize;
desc2.Format = desc.Format;
desc2.SampleDesc = desc.SampleDesc;
desc2.Usage = D3D11_USAGE_STAGING;
desc2.BindFlags = 0;
desc2.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
desc2.MiscFlags = 0;
ComPtr<ID3D11Texture2D> stagingTexture;
hr = d3dDevice->CreateTexture2D(&desc2, nullptr, &stagingTexture);
if (FAILED(hr)) {
throw MyException::Make(hr, L"Failed to create staging texture");
}
// copy the texture to a staging resource
d3dContext->CopyResource(stagingTexture.Get(), Texture);
// now, map the staging resource
hr = d3dContext->Map(
stagingTexture.Get(),
0,
D3D11_MAP_READ,
0,
&mapInfo);
if (FAILED(hr)) {
throw MyException::Make(hr, L"Failed to map staging texture");
}
mappedTexture = std::move(stagingTexture);
} else {
throw MyException::Make(hr, L"Failed to map texture.");
}
} else {
mappedTexture = Texture;
}
auto unmapResource = Finally([&] {
d3dContext->Unmap(mappedTexture.Get(), 0);
});
[...]
hr = frameEncode->WritePixels(
desc.Height,
mapInfo.RowPitch,
desc.Height * mapInfo.RowPitch,
reinterpret_cast<BYTE*>(mapInfo.pData));
if (FAILED(hr)) {
throw MyException::Make(hr, L"frameEncode->WritePixels(...) failed.");
}