Always reset the thread desktop before calling DuplicateOutput()

Otherwise capture will fail if the thread desktop is different than the current input desktop (ex: UAC secure desktop is active)
This commit is contained in:
Cameron Gutman 2024-01-17 17:15:21 -06:00
commit f64712f277
2 changed files with 31 additions and 4 deletions

View file

@ -376,11 +376,15 @@ namespace platf::dxgi {
// Check if we can use the Desktop Duplication API on this output // Check if we can use the Desktop Duplication API on this output
for (int x = 0; x < 2; ++x) { for (int x = 0; x < 2; ++x) {
dup_t dup; dup_t dup;
// Ensure we can duplicate the current display
syncThreadDesktop();
status = output1->DuplicateOutput((IUnknown *) device.get(), &dup); status = output1->DuplicateOutput((IUnknown *) device.get(), &dup);
if (SUCCEEDED(status)) { if (SUCCEEDED(status)) {
return true; return true;
} }
Sleep(200); std::this_thread::sleep_for(200ms);
} }
BOOST_LOG(error) << "DuplicateOutput() test failed [0x"sv << util::hex(status).to_string_view() << ']'; BOOST_LOG(error) << "DuplicateOutput() test failed [0x"sv << util::hex(status).to_string_view() << ']';
@ -405,9 +409,6 @@ namespace platf::dxgi {
FreeLibrary(user32); FreeLibrary(user32);
}); });
// Ensure we can duplicate the current display
syncThreadDesktop();
// Get rectangle of full desktop for absolute mouse coordinates // Get rectangle of full desktop for absolute mouse coordinates
env_width = GetSystemMetrics(SM_CXVIRTUALSCREEN); env_width = GetSystemMetrics(SM_CXVIRTUALSCREEN);
env_height = GetSystemMetrics(SM_CYVIRTUALSCREEN); env_height = GetSystemMetrics(SM_CYVIRTUALSCREEN);
@ -679,6 +680,9 @@ namespace platf::dxgi {
// We try this twice, in case we still get an error on reinitialization // We try this twice, in case we still get an error on reinitialization
for (int x = 0; x < 2; ++x) { for (int x = 0; x < 2; ++x) {
// Ensure we can duplicate the current display
syncThreadDesktop();
status = output5->DuplicateOutput1((IUnknown *) device.get(), 0, supported_formats.size(), supported_formats.data(), &dup.dup); status = output5->DuplicateOutput1((IUnknown *) device.get(), 0, supported_formats.size(), supported_formats.data(), &dup.dup);
if (SUCCEEDED(status)) { if (SUCCEEDED(status)) {
break; break;
@ -705,6 +709,9 @@ namespace platf::dxgi {
} }
for (int x = 0; x < 2; ++x) { for (int x = 0; x < 2; ++x) {
// Ensure we can duplicate the current display
syncThreadDesktop();
status = output1->DuplicateOutput((IUnknown *) device.get(), &dup.dup); status = output1->DuplicateOutput((IUnknown *) device.get(), &dup.dup);
if (SUCCEEDED(status)) { if (SUCCEEDED(status)) {
break; break;

View file

@ -52,6 +52,23 @@ set_gpu_preference(int preference) {
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
void
syncThreadDesktop() {
auto hDesk = OpenInputDesktop(DF_ALLOWOTHERACCOUNTHOOK, FALSE, GENERIC_ALL);
if (!hDesk) {
auto err = GetLastError();
std::cout << "Failed to Open Input Desktop [0x"sv << util::hex(err).to_string_view() << ']' << std::endl;
return;
}
if (!SetThreadDesktop(hDesk)) {
auto err = GetLastError();
std::cout << "Failed to sync desktop to thread [0x"sv << util::hex(err).to_string_view() << ']' << std::endl;
}
CloseDesktop(hDesk);
}
HRESULT HRESULT
test_dxgi_duplication(dxgi::adapter_t &adapter, dxgi::output_t &output) { test_dxgi_duplication(dxgi::adapter_t &adapter, dxgi::output_t &output) {
D3D_FEATURE_LEVEL featureLevels[] { D3D_FEATURE_LEVEL featureLevels[] {
@ -87,6 +104,9 @@ test_dxgi_duplication(dxgi::adapter_t &adapter, dxgi::output_t &output) {
return status; return status;
} }
// Ensure we can duplicate the current display
syncThreadDesktop();
// Return the result of DuplicateOutput() to Sunshine // Return the result of DuplicateOutput() to Sunshine
dxgi::dup_t dup; dxgi::dup_t dup;
return output1->DuplicateOutput((IUnknown *) device.get(), &dup); return output1->DuplicateOutput((IUnknown *) device.get(), &dup);