Signed-off-by: Zhiyi Zhang zzhang@codeweavers.com --- dlls/dxgi/tests/dxgi.c | 160 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 141 insertions(+), 19 deletions(-)
diff --git a/dlls/dxgi/tests/dxgi.c b/dlls/dxgi/tests/dxgi.c index e2b5df7b27..cc49c7b2ae 100644 --- a/dlls/dxgi/tests/dxgi.c +++ b/dlls/dxgi/tests/dxgi.c @@ -4940,15 +4940,17 @@ static void test_multi_adapter(void) { unsigned int output_count = 0, expected_output_count = 0; unsigned int adapter_index, output_index, device_index; + DXGI_OUTPUT_DESC old_output_desc, output_desc; DISPLAY_DEVICEW display_device; - DXGI_OUTPUT_DESC output_desc; MONITORINFO monitor_info; + DEVMODEW old_mode, mode; IDXGIFactory *factory; IDXGIAdapter *adapter; IDXGIOutput *output; HMONITOR monitor; BOOL found; HRESULT hr; + LONG ret;
if (FAILED(hr = CreateDXGIFactory(&IID_IDXGIFactory, (void **)&factory))) { @@ -4973,7 +4975,8 @@ static void test_multi_adapter(void) for (output_index = 0; SUCCEEDED(IDXGIAdapter_EnumOutputs(adapter, output_index, &output)); ++output_index) { hr = IDXGIOutput_GetDesc(output, &output_desc); - ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); + ok(hr == S_OK, "Adapter %u output %u: Got unexpected hr %#x.\n", adapter_index, + output_index, hr);
found = FALSE; display_device.cb = sizeof(display_device); @@ -4985,39 +4988,158 @@ static void test_multi_adapter(void) break; } } - ok(found, "Failed to find device %s for adapter %u, output %u.\n", - wine_dbgstr_w(output_desc.DeviceName), adapter_index, output_index); + ok(found, "Adapter %u output %u: Failed to find device %s.\n", + adapter_index, output_index, wine_dbgstr_w(output_desc.DeviceName));
ok(display_device.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP, - "Got unexpected state flags %#x for adapter %u, output %u.\n", - display_device.StateFlags, adapter_index, output_index); + "Adapter %u output %u: Got unexpected state flags %#x.\n", adapter_index, + output_index, display_device.StateFlags); if (!adapter_index && !output_index) ok(display_device.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE, - "Got unexpected state flags %#x for adapter %u, output %u.\n", - display_device.StateFlags, adapter_index, output_index); + "Adapter %u output %u: Got unexpected state flags %#x.\n", adapter_index, + output_index, display_device.StateFlags); else ok(!(display_device.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE), - "Got unexpected state flags %#x for adapter %u, output %u.\n", - display_device.StateFlags, adapter_index, output_index); + "Adapter %u output %u: Got unexpected state flags %#x.\n", adapter_index, + output_index, display_device.StateFlags);
/* Should have the same monitor handle. */ monitor = get_monitor(display_device.DeviceName); - ok(!!monitor, "Failed to find monitor %s.\n", wine_dbgstr_w(display_device.DeviceName)); - ok(monitor == output_desc.Monitor, "Got unexpected monitor %p, expected %p.\n", - monitor, output_desc.Monitor); + ok(!!monitor, "Adapter %u output %u: Failed to find monitor %s.\n", adapter_index, + output_index, wine_dbgstr_w(display_device.DeviceName)); + ok(monitor == output_desc.Monitor, + "Adapter %u output %u: Got unexpected monitor %p, expected %p.\n", + adapter_index, output_index, monitor, output_desc.Monitor);
/* Should have the same monitor rectangle. */ monitor_info.cbSize = sizeof(monitor_info); ok(GetMonitorInfoA(monitor, &monitor_info), - "Failed to get monitor info for adapter %u, output %u, error %#x.\n", - adapter_index, output_index, GetLastError()); + "Adapter %u output %u: Failed to get monitor info, error %#x.\n", adapter_index, + output_index, GetLastError()); ok(EqualRect(&monitor_info.rcMonitor, &output_desc.DesktopCoordinates), - "Got unexpected output rect %s, expected %s for adapter %u, output %u.\n", - wine_dbgstr_rect(&monitor_info.rcMonitor), wine_dbgstr_rect(&output_desc.DesktopCoordinates), - adapter_index, output_index); + "Adapter %u output %u: Got unexpected output rect %s, expected %s.\n", + adapter_index, output_index, wine_dbgstr_rect(&monitor_info.rcMonitor), + wine_dbgstr_rect(&output_desc.DesktopCoordinates)); + + ++output_count; + + /* Test output description after it got detached */ + if (display_device.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) + { + IDXGIOutput_Release(output); + continue; + } + + old_output_desc = output_desc; + + /* Save current display settings */ + memset(&old_mode, 0, sizeof(old_mode)); + old_mode.dmSize = sizeof(old_mode); + ret = EnumDisplaySettingsW(display_device.DeviceName, ENUM_CURRENT_SETTINGS, &old_mode); + /* Win10 TestBots may return FALSE but it's actually successful */ + ok(ret || broken(!ret), + "Adapter %u output %u: EnumDisplaySettingsW failed for %s, error %#x.\n", + adapter_index, output_index, wine_dbgstr_w(display_device.DeviceName), + GetLastError()); + + /* Detach */ + memset(&mode, 0, sizeof(mode)); + mode.dmSize = sizeof(mode); + mode.dmFields = DM_POSITION | DM_PELSWIDTH | DM_PELSHEIGHT; + mode.dmPosition = old_mode.dmPosition; + ret = ChangeDisplaySettingsExW(display_device.DeviceName, &mode, NULL, + CDS_UPDATEREGISTRY | CDS_NORESET, NULL); + ok(ret == DISP_CHANGE_SUCCESSFUL, + "Adapter %u output %u: ChangeDisplaySettingsExW %s returned unexpected %d.\n", + adapter_index, output_index, wine_dbgstr_w(display_device.DeviceName), ret); + ret = ChangeDisplaySettingsExW(display_device.DeviceName, NULL, NULL, 0, NULL); + ok(ret == DISP_CHANGE_SUCCESSFUL, + "Adapter %u output %u: ChangeDisplaySettingsExW %s returned unexpected %d.\n", + adapter_index, output_index, wine_dbgstr_w(display_device.DeviceName), ret); + + /* Check if it is really detached */ + memset(&mode, 0, sizeof(mode)); + mode.dmSize = sizeof(mode); + ret = EnumDisplaySettingsW(display_device.DeviceName, ENUM_CURRENT_SETTINGS, &mode); + /* Win10 TestBots may return FALSE but it's actually successful */ + ok(ret || broken(!ret) , + "Adapter %u output %u: EnumDisplaySettingsW failed for %s, error %#x.\n", + adapter_index, output_index, wine_dbgstr_w(display_device.DeviceName), + GetLastError()); + if (mode.dmPelsWidth && mode.dmPelsHeight) + { + skip("Adapter %u output %u: Failed to detach device %s.\n", adapter_index, + output_index, wine_dbgstr_w(display_device.DeviceName)); + IDXGIOutput_Release(output); + continue; + } + + /* Only the AttachedToDesktop field is updated after an output is detached. + * IDXGIAdapter_EnumOutputs() has to be called again to get other fields updated. + * But resolution changes are reflected right away. This weird behaviour is currently + * unimplemented in Wine */ + memset(&output_desc, 0, sizeof(output_desc)); + hr = IDXGIOutput_GetDesc(output, &output_desc); + ok(hr == S_OK, "Adapter %u output %u: Got unexpected hr %#x.\n", adapter_index, + output_index, hr); + ok(!lstrcmpiW(output_desc.DeviceName, old_output_desc.DeviceName), + "Adapter %u output %u: Expect device name %s, got %s.\n", adapter_index, + output_index, wine_dbgstr_w(old_output_desc.DeviceName), + wine_dbgstr_w(output_desc.DeviceName)); + todo_wine + ok(EqualRect(&output_desc.DesktopCoordinates, &old_output_desc.DesktopCoordinates), + "Adapter %u output %u: Expect desktop coordinates %s, got %s.\n", + adapter_index, output_index, + wine_dbgstr_rect(&old_output_desc.DesktopCoordinates), + wine_dbgstr_rect(&output_desc.DesktopCoordinates)); + ok(!output_desc.AttachedToDesktop, + "Adapter %u output %u: Expect output not attached to desktop.\n", adapter_index, + output_index); + ok(output_desc.Rotation == old_output_desc.Rotation, + "Adapter %u output %u: Expect rotation %#x, got %#x.\n", adapter_index, + output_index, old_output_desc.Rotation, output_desc.Rotation); + todo_wine + ok(output_desc.Monitor == old_output_desc.Monitor, + "Adapter %u output %u: Expect monitor %p, got %p.\n", adapter_index, + output_index, old_output_desc.Monitor, output_desc.Monitor); + IDXGIOutput_Release(output); + + /* Call IDXGIAdapter_EnumOutputs() again to get up-to-date output description */ + hr = IDXGIAdapter_EnumOutputs(adapter, output_index, &output); + ok(hr == S_OK, "Adapter %u output %u: Got unexpected hr %#x.\n", adapter_index, + output_index, hr); + memset(&output_desc, 0, sizeof(output_desc)); + hr = IDXGIOutput_GetDesc(output, &output_desc); + ok(hr == S_OK, "Adapter %u output %u: Got unexpected hr %#x.\n", adapter_index, + output_index, hr); + ok(!lstrcmpiW(output_desc.DeviceName, display_device.DeviceName), + "Adapter %u output %u: Expect device name %s, got %s.\n", adapter_index, + output_index, wine_dbgstr_w(display_device.DeviceName), + wine_dbgstr_w(output_desc.DeviceName)); + ok(IsRectEmpty(&output_desc.DesktopCoordinates), + "Adapter %u output %u: Expect desktop rect empty, got %s.\n", adapter_index, + output_index, wine_dbgstr_rect(&output_desc.DesktopCoordinates)); + ok(!output_desc.AttachedToDesktop, + "Adapter %u output %u: Expect output not attached to desktop.\n", adapter_index, + output_index); + ok(output_desc.Rotation == DXGI_MODE_ROTATION_IDENTITY, + "Adapter %u output %u: Expect rotation %#x, got %#x.\n", adapter_index, + output_index, DXGI_MODE_ROTATION_IDENTITY, output_desc.Rotation); + ok(!output_desc.Monitor, "Adapter %u output %u: Expect monitor NULL.\n", adapter_index, + output_index); + + /* Restore settings */ + ret = ChangeDisplaySettingsExW(display_device.DeviceName, &old_mode, NULL, + CDS_UPDATEREGISTRY | CDS_NORESET, NULL); + ok(ret == DISP_CHANGE_SUCCESSFUL, + "Adapter %u output %u: ChangeDisplaySettingsExW %s returned unexpected %d.\n", + adapter_index, output_index, wine_dbgstr_w(display_device.DeviceName), ret); + ret = ChangeDisplaySettingsExW(display_device.DeviceName, NULL, NULL, 0, NULL); + ok(ret == DISP_CHANGE_SUCCESSFUL, + "Adapter %u output %u: ChangeDisplaySettingsExW %s returned unexpected %d.\n", + adapter_index, output_index, wine_dbgstr_w(display_device.DeviceName), ret);
IDXGIOutput_Release(output); - ++output_count; }
IDXGIAdapter_Release(adapter);