-
-
Notifications
You must be signed in to change notification settings - Fork 58
Open
Labels
enhancementNew feature or requestNew feature or request
Description
I wanna capture screen output by indices from virtual-display-cli after adding monitor, but the index in virtual display cli is not match the order of EnumDisplayMonitors()
.
Without this feature I have to use EnumDisplayMonitors()
to enum all display monitors to choose indices, any other resolvetion?
#include "screen.h"
#include <windows.h>
#include <d3d11.h>
#include <dxgi1_2.h>
#include <wrl/client.h>
using Microsoft::WRL::ComPtr;
// capture screen output by index
int capture(
ComPtr<ID3D11Texture2D> &outTexture,
D3D11_TEXTURE2D_DESC *outDesc,
UINT screenIndex) // I want it from virtual-display-cli output
{
ComPtr<ID3D11Device> device = nullptr;
ComPtr<ID3D11DeviceContext> context = nullptr;
D3D_FEATURE_LEVEL featureLevel;
HRESULT hr = D3D11CreateDevice(
nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, 0, nullptr, 0,
D3D11_SDK_VERSION, &device, &featureLevel, &context);
if (FAILED(hr))
{
return -1;
}
ComPtr<IDXGIDevice> dxgiDevice;
device.As(&dxgiDevice);
ComPtr<IDXGIAdapter> dxgiAdapter;
dxgiDevice->GetAdapter(&dxgiAdapter);
ComPtr<IDXGIOutput> dxgiOutput;
// the first param is match the order of EnumDisplayMonitors(), which means screenIndex from cli can't be passed
hr = dxgiAdapter->EnumOutputs(screenIndex, &dxgiOutput);
if (FAILED(hr))
{
return -10;
}
ComPtr<IDXGIOutput1> dxgiOutput1;
dxgiOutput.As(&dxgiOutput1);
ComPtr<IDXGIOutputDuplication> deskDupl;
hr = dxgiOutput1->DuplicateOutput(device.Get(), &deskDupl);
if (FAILED(hr))
{
return -2;
}
DXGI_OUTDUPL_FRAME_INFO frameInfo;
ComPtr<IDXGIResource> desktopResource;
hr = deskDupl->AcquireNextFrame(1000, &frameInfo, &desktopResource);
if (FAILED(hr))
{
return -3;
}
ComPtr<ID3D11Texture2D> acquiredDesktopImage;
desktopResource.As(&acquiredDesktopImage);
D3D11_TEXTURE2D_DESC desc = {};
acquiredDesktopImage->GetDesc(&desc);
if (outDesc)
*outDesc = desc;
D3D11_TEXTURE2D_DESC descStaging = desc;
descStaging.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
descStaging.Usage = D3D11_USAGE_STAGING;
descStaging.BindFlags = 0;
descStaging.MiscFlags = 0;
ComPtr<ID3D11Texture2D> stagingTex;
hr = device->CreateTexture2D(&descStaging, nullptr, &stagingTex);
if (FAILED(hr))
{
deskDupl->ReleaseFrame();
return -4;
}
context->CopyResource(stagingTex.Get(), acquiredDesktopImage.Get());
deskDupl->ReleaseFrame();
outTexture = stagingTex;
return 0;
}
//get screens(with resolutions info) by indices from cli
std::vector<Screen> getScreens(const std::vector<int> &indices)
{
std::vector<Screen> screens;
int monitorCount = 0;
std::vector<std::pair<uint16_t, uint16_t>> resolutions;
// the order is not match the indices from cli
EnumDisplayMonitors(
nullptr, nullptr,
[](HMONITOR hMon, HDC hdcMon, LPRECT lprcMon, LPARAM pData) -> BOOL
{
auto res = reinterpret_cast<std::vector<std::pair<uint16_t, uint16_t>> *>(pData);
MONITORINFOEX mi;
mi.cbSize = sizeof(mi);
if (GetMonitorInfo(hMon, &mi))
{
// output: "Monitor name: \\.\DISPLAY1", there is no monitor name in cli output, I can't use it to find the target monitor
printf("Monitor name: %s\n", mi.szDevice);
DEVMODE dm;
dm.dmSize = sizeof(dm);
if (EnumDisplaySettings(mi.szDevice, ENUM_CURRENT_SETTINGS, &dm))
{
res->emplace_back(static_cast<uint16_t>(dm.dmPelsWidth), static_cast<uint16_t>(dm.dmPelsHeight));
}
}
return TRUE;
},
reinterpret_cast<LPARAM>(&resolutions));
for (int idx : indices)
{
if (idx >= 0 && idx < static_cast<int>(resolutions.size()))
{
screens.push_back({idx,
resolutions[idx].first,
resolutions[idx].second});
}
}
return screens;
}
Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or request