检索要通过网络

时间:2016-07-02 23:18:45

标签: c++ windows winapi directx dxgi

我正在修改桌面复制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

想象的唯一解决方案

2 个答案:

答案 0 :(得分:2)

私人数据不是您正在寻找的。它们仅用于将自定义值附加到d3d对象。

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

然后,您需要使用ID3D11DeviceContext使用CopyResource将纹理复制到暂存状态。然后,您可以使用上下文MapUnmap 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.");
    }