When I want to use DXGI Duplication API to take screenshots, the deviceContext->map()
always failed. It returns E_INVALIDAGR (one or more arguments are invalid). However, I don't think there are any arguments invalid. I don't know how to solve this problem. Here's my code. (all the initialization are successes, including device
, deviceContext
, dxgiOutputDuplication
).
/*
this function take a screenshot and save the bmp image of the screenshot to the data pointer.
@param BYTE* data: (out) The pointer to a BYTE array where the bmp image will be saved to.
@return ULARGE_INTEGER: the size of bmp image.
*/
ULARGE_INTEGER GetFrame(BYTE* data) {
IDXGIResource* desktopResource = nullptr;
DXGI_OUTDUPL_FRAME_INFO FrameInfo{};
ID3D11Texture2D* acquiredDesktopImage = nullptr;
//Get new frame
HRESULT hr = 0;
do {
hr = dxgiOutputDuplication->AcquireNextFrame(1000, &FrameInfo, &desktopResource);
} while (hr != S_OK);
hr = desktopResource->QueryInterface(__uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&acquiredDesktopImage));
if (hr != S_OK) {
printf("failed to query interface\n");
}
D3D11_MAPPED_SUBRESOURCE* resource = new D3D11_MAPPED_SUBRESOURCE();
ID3D11Texture2D* copiedImage = nullptr;
D3D11_TEXTURE2D_DESC desc{};
acquiredDesktopImage->GetDesc(&desc);
desc.Usage = D3D11_USAGE_DEFAULT;
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
hr = device->CreateTexture2D(&desc, NULL, &copiedImage);
if (hr != S_OK) {
printf("failed to create texture\n");
}
deviceContext->CopyResource(copiedImage, acquiredDesktopImage);
hr = deviceContext->Map(copiedImage, 0, D3D11_MAP_READ, NULL, resource);
// always failed in the upper line.
if (hr != S_OK) {
printf("failed to map\n");
}
ULARGE_INTEGER length = encodeData(dxgiOutDuplDesc.ModeDesc.Width, dxgiOutDuplDesc.ModeDesc.Height, resource->RowPitch, resource->pData, data);
// This function is to encode the data from rgb matrix to bmp format.
// Here is the description of this function.
/*
encode RGB matrix to bmp format and save it into data
@param int width: (in) matrix width
@param int height: (in) matrix height
@param UINT stride: (in) the size of a line of matrix
@param void* pixels: (in) data source pointer
@param BYTE* data: (out) data result pointer
@return ULARGE_INTEGER: data result length
*/
desktopResource->Release();
acquiredDesktopImage->Release();
delete resource;
return length;
}
here is the initialization function.
BOOL initDevice() {
IDXGIDevice* dxgiDevice = nullptr;
IDXGIAdapter* dxgiAdapter = nullptr;
IDXGIOutput* dxgiOutput = nullptr;
IDXGIOutput1* dxgiOutput1 = nullptr;
D3D_FEATURE_LEVEL feature_levels[] = {
D3D_FEATURE_LEVEL_11_0
};
CHECK_RESULT(D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, D3D11_CREATE_DEVICE_DEBUG, feature_levels, ARRAYSIZE(feature_levels), D3D11_SDK_VERSION, &device, NULL, &deviceContext));
printf("successful init create d3d11 device\n");
// Get DXGI device
CHECK_RESULT(device->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&dxgiDevice)));
// Get DXGI adapter
CHECK_RESULT(dxgiDevice->GetParent(__uuidof(IDXGIAdapter), reinterpret_cast<void**>(&dxgiAdapter)));
// Get output
CHECK_RESULT(dxgiAdapter->EnumOutputs(0, &dxgiOutput));
CHECK_RESULT(dxgiOutput->GetDesc(&dxgiOutputDesc));
// QI for Output 1
CHECK_RESULT(dxgiOutput->QueryInterface(__uuidof(dxgiOutput1), reinterpret_cast<void**>(&dxgiOutput1)));
// Create desktop duplication
CHECK_RESULT(dxgiOutput1->DuplicateOutput(device, &dxgiOutputDuplication));
dxgiOutputDuplication->GetDesc(&dxgiOutDuplDesc);
dxgiDevice->Release();
dxgiDevice = nullptr;
dxgiAdapter->Release();
dxgiAdapter = nullptr;
dxgiOutput->Release();
dxgiOutput = nullptr;
dxgiOutput1->Release();
dxgiOutput1 = nullptr;
return true;
}
This is the macro that I used.
#define CHECK_RESULT(func) if ((func) != S_OK) return false
I tried to change almost all of the parameters of desc(D3D11_TEXTURE2D_DESC)
, but none of them can succeed. Also, I have searched about this question, and the code on their articles are as the same as mine, so I am really confused about what happened. Could anyone help me with that? I'll appreciate very much for your helping.