检索要通过网络发送的ID3D11Texture2D数据

Retrieving ID3D11Texture2D data to be sent over network

本文关键字:ID3D11Texture2D 数据 网络 检索      更新时间:2023-10-16

我正在修改微软提供的桌面复制api示例,以捕获屏幕并通过网络向我的应用程序发送更新。我知道如何发送数据;我的问题是从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。我需要通过网络(尽可能高效地)传输这些数据。

这个答案似乎是正确的,但是我是Windows编程的新手,所以我需要一些额外的帮助。

这是我能想到的唯一解决方案使用IDXGIObject::GetPrivateData

私有数据根本不是你想要的。它们只是在这里为d3d对象附加自定义值。

一旦有了需要从中读回映像的ID3D11Texture2D对象,就需要从ID3D11Device在暂存内存池中创建第二个对象(获取原始描述、更改池并删除绑定)。

然后,您需要使用ID3D11DeviceContext将纹理复制到使用CopyResource的登台纹理。然后您可以使用上下文MapUnmap api来读取图像。

我有一个很好的链接。查找方法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.");
    }