[PATCH v2 0/6] MR11231: dxgi: Create a windowed swapchain instead when the fullscreen mode scanline order or scaling is invalid.
-- v2: dxgi: Refuse to enter fullscreen when the fullscreen mode scanline order or scaling is invalid. dxgi: Create a windowed swapchain instead when the fullscreen mode scanline order or scaling is invalid. dxgi: Report the DXGI_SWAP_CHAIN_FULLSCREEN_DESC used for creating a D3D11 swapchain. dxgi/tests: Test creating a fullscreen swapchain with an invalid scanline order or scaling. https://gitlab.winehq.org/wine/wine/-/merge_requests/11231
From: Zhiyi Zhang <zzhang@codeweavers.com> Fix a prematurely skipped test like the following. The test has been checked on a Windows 11 23H2 physical machine. ``` dxgi.c:2156: Tests skipped: Fullscreen not supported. ``` --- dlls/dxgi/tests/dxgi.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dlls/dxgi/tests/dxgi.c b/dlls/dxgi/tests/dxgi.c index 0886adf76bd..37c4ac36e84 100644 --- a/dlls/dxgi/tests/dxgi.c +++ b/dlls/dxgi/tests/dxgi.c @@ -2143,6 +2143,11 @@ static void test_create_swapchain(void) check_window_fullscreen_state(creation_desc.OutputWindow, &initial_state.fullscreen_state); /* Fullscreen */ + /* Call flush_events() to make sure that the previously destroyed output windows are disappeared + * from the screen. Otherwise, creating a fullscreen swapchain returns DXGI_STATUS_OCCLUDED and + * gets a windowed swapchain instead. It's still possible that there is another window on the screen + * in the test environment so the following DXGI_STATUS_OCCLUDED return code is kept accepted */ + flush_events(); creation_desc.Windowed = FALSE; hr = IDXGIFactory_CreateSwapChain(factory, obj, &creation_desc, &swapchain); ok(hr == S_OK || hr == DXGI_STATUS_OCCLUDED, "Got unexpected hr %#lx.\n", hr); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11231
From: Zhiyi Zhang <zzhang@codeweavers.com> --- dlls/dxgi/tests/dxgi.c | 93 +++++++++++++++++++++++------------------- 1 file changed, 50 insertions(+), 43 deletions(-) diff --git a/dlls/dxgi/tests/dxgi.c b/dlls/dxgi/tests/dxgi.c index 37c4ac36e84..72d43bd462e 100644 --- a/dlls/dxgi/tests/dxgi.c +++ b/dlls/dxgi/tests/dxgi.c @@ -424,7 +424,7 @@ struct fullscreen_state RECT client_rect; HMONITOR monitor; RECT monitor_rect; - BOOL todo_style, todo_exstyle, todo_client_rect; + BOOL todo_style, todo_exstyle, todo_window_rect, todo_client_rect, todo_monitor_rect; }; struct swapchain_fullscreen_state @@ -468,6 +468,7 @@ static void check_fullscreen_state_(unsigned int line, const struct fullscreen_s ok_(__FILE__, line)((state->exstyle & ~WS_EX_TOPMOST) == (expected_state->exstyle & ~WS_EX_TOPMOST), "Got exstyle %#lx, expected %#lx.\n", state->exstyle & ~(DWORD)WS_EX_TOPMOST, expected_state->exstyle & ~(DWORD)WS_EX_TOPMOST); + todo_wine_if (expected_state->todo_window_rect) ok_(__FILE__, line)(EqualRect(&state->window_rect, &expected_state->window_rect), "Got window rect %s, expected %s.\n", wine_dbgstr_rect(&state->window_rect), wine_dbgstr_rect(&expected_state->window_rect)); @@ -478,6 +479,7 @@ static void check_fullscreen_state_(unsigned int line, const struct fullscreen_s ok_(__FILE__, line)(state->monitor == expected_state->monitor, "Got monitor %p, expected %p.\n", state->monitor, expected_state->monitor); + todo_wine_if (expected_state->todo_monitor_rect) ok_(__FILE__, line)(EqualRect(&state->monitor_rect, &expected_state->monitor_rect), "Got monitor rect %s, expected %s.\n", wine_dbgstr_rect(&state->monitor_rect), wine_dbgstr_rect(&expected_state->monitor_rect)); @@ -1739,21 +1741,21 @@ struct refresh_rates BOOL denominator_should_pass; }; -static void test_create_swapchain(void) +static void test_create_swapchain(IUnknown *device, BOOL is_d3d12) { struct swapchain_fullscreen_state initial_state, expected_state; unsigned int i, expected_width, expected_height; DXGI_SWAP_CHAIN_DESC creation_desc, result_desc; DXGI_SWAP_CHAIN_FULLSCREEN_DESC fullscreen_desc; DXGI_SWAP_CHAIN_DESC1 swapchain_desc; - IDXGIDevice *device, *bgra_device; ULONG refcount, expected_refcount; IUnknown *obj, *obj2, *parent; + IDXGIAdapter *adapter = NULL; IDXGISwapChain1 *swapchain1; RECT *expected_client_rect; IDXGISwapChain *swapchain; + IDXGIDevice *bgra_device; IDXGISurface1 *surface; - IDXGIAdapter *adapter; IDXGIFactory *factory; IDXGIOutput *target; BOOL fullscreen; @@ -1769,11 +1771,7 @@ static void test_create_swapchain(void) { 0, 0, TRUE, FALSE}, }; - if (!(device = create_device(0))) - { - skip("Failed to create device.\n"); - return; - } + get_factory(device, is_d3d12, &factory); creation_desc.BufferDesc.Width = 800; creation_desc.BufferDesc.Height = 600; @@ -1785,24 +1783,24 @@ static void test_create_swapchain(void) creation_desc.SampleDesc.Count = 1; creation_desc.SampleDesc.Quality = 0; creation_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; - creation_desc.BufferCount = 1; + creation_desc.BufferCount = is_d3d12 ? 2 : 1; creation_desc.OutputWindow = NULL; creation_desc.Windowed = TRUE; - creation_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; + creation_desc.SwapEffect = is_d3d12 ? DXGI_SWAP_EFFECT_FLIP_DISCARD : DXGI_SWAP_EFFECT_DISCARD; creation_desc.Flags = 0; - hr = IDXGIDevice_QueryInterface(device, &IID_IUnknown, (void **)&obj); - ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - - hr = IDXGIDevice_GetAdapter(device, &adapter); + hr = IUnknown_QueryInterface(device, &IID_IUnknown, (void **)&obj); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - hr = IDXGIAdapter_GetParent(adapter, &IID_IDXGIFactory, (void **)&factory); - ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + if (!is_d3d12) + { + hr = IDXGIDevice_GetAdapter((IDXGIDevice *)device, &adapter); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - expected_refcount = get_refcount(adapter); + expected_refcount = get_refcount(adapter); + } refcount = get_refcount(factory); - ok(refcount == 2, "Got unexpected refcount %lu.\n", refcount); + ok(refcount == (is_d3d12 ? 1 : 2), "Got unexpected refcount %lu.\n", refcount); refcount = get_refcount(device); ok(refcount == 2, "Got unexpected refcount %lu.\n", refcount); @@ -1823,12 +1821,15 @@ static void test_create_swapchain(void) hr = IDXGIFactory_CreateSwapChain(factory, obj, &creation_desc, &swapchain); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - refcount = get_refcount(adapter); - ok(refcount >= expected_refcount, "Got refcount %lu, expected >= %lu.\n", refcount, expected_refcount); + if (!is_d3d12) + { + refcount = get_refcount(adapter); + ok(refcount >= expected_refcount, "Got refcount %lu, expected >= %lu.\n", refcount, expected_refcount); + } refcount = get_refcount(factory); - todo_wine ok(refcount == 4, "Got unexpected refcount %lu.\n", refcount); + todo_wine ok(refcount == (is_d3d12 ? 5 : 4), "Got unexpected refcount %lu.\n", refcount); refcount = get_refcount(device); - ok(refcount == 3, "Got unexpected refcount %lu.\n", refcount); + todo_wine_if(is_d3d12) ok(refcount == (is_d3d12 ? 7 : 3), "Got unexpected refcount %lu.\n", refcount); hr = IDXGISwapChain_GetDesc(swapchain, NULL); ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr); @@ -1837,13 +1838,13 @@ static void test_create_swapchain(void) ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); ok(parent == (IUnknown *)factory, "Got unexpected parent interface pointer %p.\n", parent); refcount = IUnknown_Release(parent); - todo_wine ok(refcount == 4, "Got unexpected refcount %lu.\n", refcount); + todo_wine ok(refcount == (is_d3d12 ? 5 : 4), "Got unexpected refcount %lu.\n", refcount); hr = IDXGISwapChain_GetParent(swapchain, &IID_IDXGIFactory, (void **)&parent); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); ok(parent == (IUnknown *)factory, "Got unexpected parent interface pointer %p.\n", parent); refcount = IUnknown_Release(parent); - todo_wine ok(refcount == 4, "Got unexpected refcount %lu.\n", refcount); + todo_wine ok(refcount == (is_d3d12 ? 5 : 4), "Got unexpected refcount %lu.\n", refcount); hr = IDXGISwapChain_QueryInterface(swapchain, &IID_IDXGISwapChain1, (void **)&swapchain1); ok(hr == S_OK || broken(hr == E_NOINTERFACE) /* Not available on all Windows versions. */, @@ -1875,7 +1876,7 @@ static void test_create_swapchain(void) ok(!refcount, "Swapchain has %lu references left.\n", refcount); refcount = get_refcount(factory); - ok(refcount == 2, "Got unexpected refcount %lu.\n", refcount); + ok(refcount == (is_d3d12 ? 1 : 2), "Got unexpected refcount %lu.\n", refcount); for (i = 0; i < ARRAY_SIZE(refresh_list); ++i) { @@ -1891,11 +1892,11 @@ static void test_create_swapchain(void) ok(result_desc.Windowed == creation_desc.Windowed, "Test %u: Got unexpected windowed %#x.\n", i, result_desc.Windowed); - todo_wine_if (!refresh_list[i].numerator_should_pass) + todo_wine_if (!refresh_list[i].numerator_should_pass && !is_d3d12) ok(result_desc.BufferDesc.RefreshRate.Numerator == refresh_list[i].numerator, "Numerator %u is %u.\n", i, result_desc.BufferDesc.RefreshRate.Numerator); - todo_wine_if (!refresh_list[i].denominator_should_pass) + todo_wine_if (!refresh_list[i].denominator_should_pass && !is_d3d12) ok(result_desc.BufferDesc.RefreshRate.Denominator == refresh_list[i].denominator, "Denominator %u is %u.\n", i, result_desc.BufferDesc.RefreshRate.Denominator); @@ -1989,11 +1990,11 @@ static void test_create_swapchain(void) if (result_desc.Windowed != creation_desc.Windowed) trace("Test %u: Failed to change fullscreen state.\n", i); - todo_wine_if (!refresh_list[i].numerator_should_pass) + todo_wine_if (!refresh_list[i].numerator_should_pass && !is_d3d12) ok(result_desc.BufferDesc.RefreshRate.Numerator == refresh_list[i].numerator, "Numerator %u is %u.\n", i, result_desc.BufferDesc.RefreshRate.Numerator); - todo_wine_if (!refresh_list[i].denominator_should_pass) + todo_wine_if (!refresh_list[i].denominator_should_pass && !is_d3d12) ok(result_desc.BufferDesc.RefreshRate.Denominator == refresh_list[i].denominator, "Denominator %u is %u.\n", i, result_desc.BufferDesc.RefreshRate.Denominator); @@ -2013,9 +2014,10 @@ static void test_create_swapchain(void) i, containing_output); IDXGIOutput_Release(containing_output); - ok(output_belongs_to_adapter(target, adapter), - "Test %u: Output %p doesn't belong to adapter %p.\n", - i, target, adapter); + if (adapter) + ok(output_belongs_to_adapter(target, adapter), + "Test %u: Output %p doesn't belong to adapter %p.\n", + i, target, adapter); IDXGIOutput_Release(target); hr = IDXGISwapChain_GetFullscreenState(swapchain, NULL, NULL); @@ -2052,18 +2054,18 @@ static void test_create_swapchain(void) creation_desc.Windowed = TRUE; creation_desc.Flags = 0; hr = IDXGIFactory_CreateSwapChain(factory, obj, &creation_desc, &swapchain); - ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr); + ok(hr == (is_d3d12 ? DXGI_ERROR_INVALID_CALL : E_INVALIDARG), "Got unexpected hr %#lx.\n", hr); creation_desc.Windowed = FALSE; hr = IDXGIFactory_CreateSwapChain(factory, obj, &creation_desc, &swapchain); - ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr); + ok(hr == (is_d3d12 ? DXGI_ERROR_INVALID_CALL : E_INVALIDARG), "Got unexpected hr %#lx.\n", hr); creation_desc.BufferCount = 2; creation_desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; hr = IDXGIFactory_CreateSwapChain(factory, obj, &creation_desc, &swapchain); ok(hr == E_INVALIDARG || hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#lx.\n", hr); - creation_desc.BufferCount = 1; - creation_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; + creation_desc.BufferCount = is_d3d12 ? 2 : 1; + creation_desc.SwapEffect = is_d3d12 ? DXGI_SWAP_EFFECT_FLIP_DISCARD : DXGI_SWAP_EFFECT_DISCARD;; check_window_fullscreen_state(creation_desc.OutputWindow, &initial_state.fullscreen_state); @@ -2214,6 +2216,12 @@ static void test_create_swapchain(void) result_desc.BufferDesc.Width, expected_width); todo_wine ok(result_desc.BufferDesc.Height == expected_height, "Got height %u, expected %u.\n", result_desc.BufferDesc.Height, expected_height); + if (is_d3d12) + { + expected_state.fullscreen_state.todo_window_rect = TRUE; + expected_state.fullscreen_state.todo_client_rect = TRUE; + expected_state.fullscreen_state.todo_monitor_rect = TRUE; + } check_swapchain_fullscreen_state(swapchain, &expected_state); hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); @@ -2224,12 +2232,10 @@ static void test_create_swapchain(void) done: IUnknown_Release(obj); - refcount = IDXGIDevice_Release(device); - ok(!refcount, "Device has %lu references left.\n", refcount); - refcount = IDXGIAdapter_Release(adapter); - ok(!refcount, "Adapter has %lu references left.\n", refcount); + if (adapter) + IDXGIAdapter_Release(adapter); refcount = IDXGIFactory_Release(factory); - ok(!refcount, "Factory has %lu references left.\n", refcount); + ok(refcount == !is_d3d12, "Got unexpected refcount %lu.\n", refcount); check_window_fullscreen_state(creation_desc.OutputWindow, &initial_state.fullscreen_state); DestroyWindow(creation_desc.OutputWindow); } @@ -8628,12 +8634,12 @@ START_TEST(dxgi) run_queued_tests(); /* These tests use full-screen swapchains, so shouldn't run in parallel. */ - test_create_swapchain(); test_inexact_modes(); test_gamma_control(); test_multi_adapter(); test_swapchain_parameters(); test_swapchain_window_styles(); + run_on_d3d10(test_create_swapchain); run_on_d3d10(test_set_fullscreen); run_on_d3d10(test_resize_target); run_on_d3d10(test_resize_fullscreen); @@ -8668,6 +8674,7 @@ START_TEST(dxgi) ID3D12Debug_Release(debug); } + run_on_d3d12(test_create_swapchain); run_on_d3d12(test_set_fullscreen); run_on_d3d12(test_resize_target); run_on_d3d12(test_resize_fullscreen); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11231
From: Zhiyi Zhang <zzhang@codeweavers.com> --- dlls/dxgi/tests/dxgi.c | 173 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 173 insertions(+) diff --git a/dlls/dxgi/tests/dxgi.c b/dlls/dxgi/tests/dxgi.c index 72d43bd462e..de49e55ee95 100644 --- a/dlls/dxgi/tests/dxgi.c +++ b/dlls/dxgi/tests/dxgi.c @@ -2230,6 +2230,179 @@ static void test_create_swapchain(IUnknown *device, BOOL is_d3d12) IDXGIOutput_Release(expected_state.target); + /* Try to create a fullscreen swapchain with an invalid scanline order. Expect swapchain + * creation successful but entering fullscreen mode fails */ + creation_desc.BufferDesc.Width = 1024; + creation_desc.BufferDesc.Height = 768; + creation_desc.BufferDesc.RefreshRate.Numerator = 60; + creation_desc.BufferDesc.RefreshRate.Denominator = 1; + creation_desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + creation_desc.BufferDesc.ScanlineOrdering = 0xdeadbeef; + creation_desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; + creation_desc.Windowed = FALSE; + creation_desc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; + hr = IDXGIFactory_CreateSwapChain(factory, obj, &creation_desc, &swapchain); + ok(hr == DXGI_STATUS_OCCLUDED || hr == S_OK /* <= Win10 22H2 */, "Got unexpected hr %#lx.\n", hr); + hr = IDXGISwapChain_QueryInterface(swapchain, &IID_IDXGISwapChain1, (void **)&swapchain1); + ok(hr == S_OK || broken(hr == E_NOINTERFACE) /* Not available on all Windows versions. */, + "Got unexpected hr %#lx.\n", hr); + if (SUCCEEDED(hr)) + { + hr = IDXGISwapChain1_GetFullscreenDesc(swapchain1, &fullscreen_desc); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + todo_wine_if(!is_d3d12) + ok(fullscreen_desc.ScanlineOrdering == creation_desc.BufferDesc.ScanlineOrdering, + "Got unexpected scanline ordering %d.\n", fullscreen_desc.ScanlineOrdering); + ok(fullscreen_desc.Scaling == creation_desc.BufferDesc.Scaling, + "Got unexpected scanline ordering %d.\n", fullscreen_desc.ScanlineOrdering); + todo_wine + ok(fullscreen_desc.Windowed != creation_desc.Windowed, + "Got unexpected windowed %#x.\n", fullscreen_desc.Windowed); + IDXGISwapChain1_Release(swapchain1); + } + hr = IDXGISwapChain_GetDesc(swapchain, &result_desc); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + todo_wine + ok(result_desc.Windowed, "Got unexpected fullscreen state.\n"); + hr = IDXGISwapChain_GetFullscreenState(swapchain, &fullscreen, NULL); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + todo_wine + ok(!fullscreen, "Got unexpected fullscreen state.\n"); + hr = IDXGISwapChain_SetFullscreenState(swapchain, TRUE, NULL); + todo_wine + ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#lx.\n", hr); + if (hr == S_OK) + { + hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + } + IDXGISwapChain_Release(swapchain); + + /* Try to create a fullscreen swapchain with an invalid scanline order, zero width and height. + * Expect swapchain creation successful but entering fullscreen mode fails */ + creation_desc.BufferDesc.Width = 0; + creation_desc.BufferDesc.Height = 0; + hr = IDXGIFactory_CreateSwapChain(factory, obj, &creation_desc, &swapchain); + ok(hr == DXGI_STATUS_OCCLUDED || hr == S_OK /* <= Win10 22H2 */, "Got unexpected hr %#lx.\n", hr); + hr = IDXGISwapChain_QueryInterface(swapchain, &IID_IDXGISwapChain1, (void **)&swapchain1); + ok(hr == S_OK || broken(hr == E_NOINTERFACE) /* Not available on all Windows versions. */, + "Got unexpected hr %#lx.\n", hr); + if (SUCCEEDED(hr)) + { + hr = IDXGISwapChain1_GetFullscreenDesc(swapchain1, &fullscreen_desc); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + todo_wine_if(!is_d3d12) + ok(fullscreen_desc.ScanlineOrdering == creation_desc.BufferDesc.ScanlineOrdering, + "Got unexpected scanline ordering %d.\n", fullscreen_desc.ScanlineOrdering); + ok(fullscreen_desc.Scaling == creation_desc.BufferDesc.Scaling, + "Got unexpected scanline ordering %d.\n", fullscreen_desc.ScanlineOrdering); + todo_wine + ok(fullscreen_desc.Windowed != creation_desc.Windowed, + "Got unexpected windowed %#x.\n", fullscreen_desc.Windowed); + IDXGISwapChain1_Release(swapchain1); + } + hr = IDXGISwapChain_GetDesc(swapchain, &result_desc); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + todo_wine + ok(result_desc.Windowed, "Got unexpected fullscreen state.\n"); + hr = IDXGISwapChain_GetFullscreenState(swapchain, &fullscreen, NULL); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + todo_wine + ok(!fullscreen, "Got unexpected fullscreen state.\n"); + hr = IDXGISwapChain_SetFullscreenState(swapchain, TRUE, NULL); + todo_wine + ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#lx.\n", hr); + if (hr == S_OK) + { + hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + } + IDXGISwapChain_Release(swapchain); + + /* Try to create a fullscreen swapchain with an invalid scaling. Expect swapchain creation + * successful but entering fullscreen mode fails */ + creation_desc.BufferDesc.Width = 1024; + creation_desc.BufferDesc.Height = 768; + creation_desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; + creation_desc.BufferDesc.Scaling = 0xdeadbeef; + hr = IDXGIFactory_CreateSwapChain(factory, obj, &creation_desc, &swapchain); + ok(hr == DXGI_STATUS_OCCLUDED || hr == S_OK /* <= Win10 22H2 */, "Got unexpected hr %#lx.\n", hr); + hr = IDXGISwapChain_QueryInterface(swapchain, &IID_IDXGISwapChain1, (void **)&swapchain1); + ok(hr == S_OK || broken(hr == E_NOINTERFACE) /* Not available on all Windows versions. */, + "Got unexpected hr %#lx.\n", hr); + if (SUCCEEDED(hr)) + { + hr = IDXGISwapChain1_GetFullscreenDesc(swapchain1, &fullscreen_desc); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + ok(fullscreen_desc.ScanlineOrdering == creation_desc.BufferDesc.ScanlineOrdering, + "Got unexpected scanline ordering %d.\n", fullscreen_desc.ScanlineOrdering); + todo_wine_if(!is_d3d12) + ok(fullscreen_desc.Scaling == creation_desc.BufferDesc.Scaling, + "Got unexpected scanline ordering %d.\n", fullscreen_desc.ScanlineOrdering); + todo_wine + ok(fullscreen_desc.Windowed != creation_desc.Windowed, + "Got unexpected windowed %#x.\n", fullscreen_desc.Windowed); + IDXGISwapChain1_Release(swapchain1); + } + hr = IDXGISwapChain_GetDesc(swapchain, &result_desc); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + todo_wine + ok(result_desc.Windowed, "Got unexpected fullscreen state.\n"); + hr = IDXGISwapChain_GetFullscreenState(swapchain, &fullscreen, NULL); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + todo_wine + ok(!fullscreen, "Got unexpected fullscreen state.\n"); + hr = IDXGISwapChain_SetFullscreenState(swapchain, TRUE, NULL); + todo_wine + ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#lx.\n", hr); + if (hr == S_OK) + { + hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + } + IDXGISwapChain_Release(swapchain); + + /* Try to create a fullscreen swapchain with an invalid scaling, zero width and height. Expect + * swapchain creation successful but entering fullscreen mode fails */ + creation_desc.BufferDesc.Width = 0; + creation_desc.BufferDesc.Height = 0; + hr = IDXGIFactory_CreateSwapChain(factory, obj, &creation_desc, &swapchain); + ok(hr == DXGI_STATUS_OCCLUDED || hr == S_OK /* <= Win10 22H2 */, "Got unexpected hr %#lx.\n", hr); + hr = IDXGISwapChain_QueryInterface(swapchain, &IID_IDXGISwapChain1, (void **)&swapchain1); + ok(hr == S_OK || broken(hr == E_NOINTERFACE) /* Not available on all Windows versions. */, + "Got unexpected hr %#lx.\n", hr); + if (SUCCEEDED(hr)) + { + hr = IDXGISwapChain1_GetFullscreenDesc(swapchain1, &fullscreen_desc); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + ok(fullscreen_desc.ScanlineOrdering == creation_desc.BufferDesc.ScanlineOrdering, + "Got unexpected scanline ordering %d.\n", fullscreen_desc.ScanlineOrdering); + todo_wine_if(!is_d3d12) + ok(fullscreen_desc.Scaling == creation_desc.BufferDesc.Scaling, + "Got unexpected scanline ordering %d.\n", fullscreen_desc.ScanlineOrdering); + todo_wine + ok(fullscreen_desc.Windowed != creation_desc.Windowed, + "Got unexpected windowed %#x.\n", fullscreen_desc.Windowed); + IDXGISwapChain1_Release(swapchain1); + } + hr = IDXGISwapChain_GetDesc(swapchain, &result_desc); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + todo_wine + ok(result_desc.Windowed, "Got unexpected fullscreen state.\n"); + hr = IDXGISwapChain_GetFullscreenState(swapchain, &fullscreen, NULL); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + todo_wine + ok(!fullscreen, "Got unexpected fullscreen state.\n"); + hr = IDXGISwapChain_SetFullscreenState(swapchain, TRUE, NULL); + todo_wine + ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#lx.\n", hr); + if (hr == S_OK) + { + hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + } + IDXGISwapChain_Release(swapchain); + done: IUnknown_Release(obj); if (adapter) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11231
From: Zhiyi Zhang <zzhang@codeweavers.com> So that we can get the original values of ScanlineOrdering and Scaling even when they are invalid. This is similar to how d3d12_swapchain_GetFullscreenDesc() works. --- dlls/dxgi/device.c | 2 +- dlls/dxgi/dxgi_private.h | 3 ++- dlls/dxgi/factory.c | 8 ++++++++ dlls/dxgi/swapchain.c | 18 +++--------------- dlls/dxgi/tests/dxgi.c | 4 ---- 5 files changed, 14 insertions(+), 21 deletions(-) diff --git a/dlls/dxgi/device.c b/dlls/dxgi/device.c index 46d252f2b67..eedcc81d845 100644 --- a/dlls/dxgi/device.c +++ b/dlls/dxgi/device.c @@ -462,7 +462,7 @@ static HRESULT STDMETHODCALLTYPE dxgi_swapchain_factory_create_swapchain(IWineDX return E_OUTOFMEMORY; } - if (FAILED(hr = d3d11_swapchain_init(object, device, &wined3d_desc))) + if (FAILED(hr = d3d11_swapchain_init(object, device, &wined3d_desc, fullscreen_desc))) { WARN("Failed to initialise swapchain, hr %#lx.\n", hr); free(object); diff --git a/dlls/dxgi/dxgi_private.h b/dlls/dxgi/dxgi_private.h index 483aac4d566..c74a80f5c22 100644 --- a/dlls/dxgi/dxgi_private.h +++ b/dlls/dxgi/dxgi_private.h @@ -180,13 +180,14 @@ struct d3d11_swapchain IWineDXGIDevice *device; IWineDXGIFactory *factory; + DXGI_SWAP_CHAIN_FULLSCREEN_DESC fullscreen_desc; IDXGIOutput *target; LONG present_count; LONG in_set_fullscreen_state; }; HRESULT d3d11_swapchain_init(struct d3d11_swapchain *swapchain, struct dxgi_device *device, - struct wined3d_swapchain_desc *desc); + struct wined3d_swapchain_desc *desc, const DXGI_SWAP_CHAIN_FULLSCREEN_DESC *fullscreen_desc); HRESULT d3d12_swapchain_create(IWineDXGIFactory *factory, ID3D12CommandQueue *queue, HWND window, const DXGI_SWAP_CHAIN_DESC1 *swapchain_desc, const DXGI_SWAP_CHAIN_FULLSCREEN_DESC *fullscreen_desc, diff --git a/dlls/dxgi/factory.c b/dlls/dxgi/factory.c index ebdb42a3806..43594d14d4e 100644 --- a/dlls/dxgi/factory.c +++ b/dlls/dxgi/factory.c @@ -272,6 +272,7 @@ static HRESULT STDMETHODCALLTYPE dxgi_factory_CreateSwapChainForHwnd(IWineDXGIFa const DXGI_SWAP_CHAIN_FULLSCREEN_DESC *fullscreen_desc, IDXGIOutput *output, IDXGISwapChain1 **swapchain) { + DXGI_SWAP_CHAIN_FULLSCREEN_DESC windowed_fullscreen_desc; IWineDXGISwapChainFactory *swapchain_factory; ID3D12CommandQueue *command_queue; HRESULT hr; @@ -291,6 +292,13 @@ static HRESULT STDMETHODCALLTYPE dxgi_factory_CreateSwapChainForHwnd(IWineDXGIFa return DXGI_ERROR_UNSUPPORTED; } + if (!fullscreen_desc) + { + memset(&windowed_fullscreen_desc, 0, sizeof(windowed_fullscreen_desc)); + windowed_fullscreen_desc.Windowed = TRUE; + fullscreen_desc = &windowed_fullscreen_desc; + } + if (!dxgi_validate_swapchain_desc(desc)) return DXGI_ERROR_INVALID_CALL; diff --git a/dlls/dxgi/swapchain.c b/dlls/dxgi/swapchain.c index 5c49c7f2482..206fcd3683b 100644 --- a/dlls/dxgi/swapchain.c +++ b/dlls/dxgi/swapchain.c @@ -662,12 +662,7 @@ static HRESULT STDMETHODCALLTYPE d3d11_swapchain_GetFullscreenDesc(IDXGISwapChai wined3d_swapchain_get_desc(swapchain->wined3d_swapchain, &wined3d_desc); wined3d_mutex_unlock(); - FIXME("Ignoring ScanlineOrdering and Scaling.\n"); - - desc->RefreshRate.Numerator = wined3d_desc.refresh_rate; - desc->RefreshRate.Denominator = 1; - desc->ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; - desc->Scaling = DXGI_MODE_SCALING_UNSPECIFIED; + *desc = swapchain->fullscreen_desc; desc->Windowed = wined3d_desc.windowed; return S_OK; @@ -989,7 +984,7 @@ static HRESULT d3d11_swapchain_create_d3d11_textures(struct d3d11_swapchain *swa } HRESULT d3d11_swapchain_init(struct d3d11_swapchain *swapchain, struct dxgi_device *device, - struct wined3d_swapchain_desc *desc) + struct wined3d_swapchain_desc *desc, const DXGI_SWAP_CHAIN_FULLSCREEN_DESC *fullscreen_desc) { struct wined3d_swapchain_state *state; BOOL fullscreen; @@ -1008,6 +1003,7 @@ HRESULT d3d11_swapchain_init(struct d3d11_swapchain *swapchain, struct dxgi_devi swapchain->IDXGISwapChain4_iface.lpVtbl = &d3d11_swapchain_vtbl; swapchain->state_parent.ops = &d3d11_swapchain_state_parent_ops; + swapchain->fullscreen_desc = *fullscreen_desc; swapchain->refcount = 1; wined3d_mutex_lock(); wined3d_private_store_init(&swapchain->private_store); @@ -3389,7 +3385,6 @@ HRESULT d3d12_swapchain_create(IWineDXGIFactory *factory, ID3D12CommandQueue *qu const DXGI_SWAP_CHAIN_DESC1 *swapchain_desc, const DXGI_SWAP_CHAIN_FULLSCREEN_DESC *fullscreen_desc, IDXGISwapChain1 **swapchain) { - DXGI_SWAP_CHAIN_FULLSCREEN_DESC default_fullscreen_desc; struct D3D12_COMMAND_QUEUE_DESC queue_desc; struct d3d12_swapchain *object; ID3D12Device *device; @@ -3402,13 +3397,6 @@ HRESULT d3d12_swapchain_create(IWineDXGIFactory *factory, ID3D12CommandQueue *qu if (queue_desc.Type != D3D12_COMMAND_LIST_TYPE_DIRECT) return DXGI_ERROR_INVALID_CALL; - if (!fullscreen_desc) - { - memset(&default_fullscreen_desc, 0, sizeof(default_fullscreen_desc)); - default_fullscreen_desc.Windowed = TRUE; - fullscreen_desc = &default_fullscreen_desc; - } - if (!(object = calloc(1, sizeof(*object)))) return E_OUTOFMEMORY; diff --git a/dlls/dxgi/tests/dxgi.c b/dlls/dxgi/tests/dxgi.c index de49e55ee95..96dcf7a38cd 100644 --- a/dlls/dxgi/tests/dxgi.c +++ b/dlls/dxgi/tests/dxgi.c @@ -2250,7 +2250,6 @@ static void test_create_swapchain(IUnknown *device, BOOL is_d3d12) { hr = IDXGISwapChain1_GetFullscreenDesc(swapchain1, &fullscreen_desc); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - todo_wine_if(!is_d3d12) ok(fullscreen_desc.ScanlineOrdering == creation_desc.BufferDesc.ScanlineOrdering, "Got unexpected scanline ordering %d.\n", fullscreen_desc.ScanlineOrdering); ok(fullscreen_desc.Scaling == creation_desc.BufferDesc.Scaling, @@ -2291,7 +2290,6 @@ static void test_create_swapchain(IUnknown *device, BOOL is_d3d12) { hr = IDXGISwapChain1_GetFullscreenDesc(swapchain1, &fullscreen_desc); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - todo_wine_if(!is_d3d12) ok(fullscreen_desc.ScanlineOrdering == creation_desc.BufferDesc.ScanlineOrdering, "Got unexpected scanline ordering %d.\n", fullscreen_desc.ScanlineOrdering); ok(fullscreen_desc.Scaling == creation_desc.BufferDesc.Scaling, @@ -2336,7 +2334,6 @@ static void test_create_swapchain(IUnknown *device, BOOL is_d3d12) ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); ok(fullscreen_desc.ScanlineOrdering == creation_desc.BufferDesc.ScanlineOrdering, "Got unexpected scanline ordering %d.\n", fullscreen_desc.ScanlineOrdering); - todo_wine_if(!is_d3d12) ok(fullscreen_desc.Scaling == creation_desc.BufferDesc.Scaling, "Got unexpected scanline ordering %d.\n", fullscreen_desc.ScanlineOrdering); todo_wine @@ -2377,7 +2374,6 @@ static void test_create_swapchain(IUnknown *device, BOOL is_d3d12) ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); ok(fullscreen_desc.ScanlineOrdering == creation_desc.BufferDesc.ScanlineOrdering, "Got unexpected scanline ordering %d.\n", fullscreen_desc.ScanlineOrdering); - todo_wine_if(!is_d3d12) ok(fullscreen_desc.Scaling == creation_desc.BufferDesc.Scaling, "Got unexpected scanline ordering %d.\n", fullscreen_desc.ScanlineOrdering); todo_wine -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11231
From: Zhiyi Zhang <zzhang@codeweavers.com> Titan Quest Anniversary Edition (SteamID: 475150) tries to create a fullscreen swapchain with an invalid scanline order and scaling and gets a windowed swapchain instead on Windows. Wine creates a fullscreen swapchain in this case and thus causes some unexpected window management bugs such as the taskbar showing up on top of the game window. On Windows 11, DXGI_STATUS_OCCLUDED is returned when creating a fullscreen swapchain in such cases and S_OK is returned on Windows 10 <= 22H2. Choose S_OK here because I worry that some applications might not handle DXGI_STATUS_OCCLUDED gracefully. --- dlls/dxgi/dxgi_private.h | 2 +- dlls/dxgi/factory.c | 11 ++++++++++- dlls/dxgi/swapchain.c | 32 +++++++++++++++++++++++++------- dlls/dxgi/tests/dxgi.c | 12 ------------ 4 files changed, 36 insertions(+), 21 deletions(-) diff --git a/dlls/dxgi/dxgi_private.h b/dlls/dxgi/dxgi_private.h index c74a80f5c22..8eba24de24d 100644 --- a/dlls/dxgi/dxgi_private.h +++ b/dlls/dxgi/dxgi_private.h @@ -193,7 +193,7 @@ HRESULT d3d12_swapchain_create(IWineDXGIFactory *factory, ID3D12CommandQueue *qu const DXGI_SWAP_CHAIN_DESC1 *swapchain_desc, const DXGI_SWAP_CHAIN_FULLSCREEN_DESC *fullscreen_desc, IDXGISwapChain1 **swapchain); -BOOL dxgi_validate_swapchain_desc(const DXGI_SWAP_CHAIN_DESC1 *desc); +HRESULT dxgi_validate_swapchain_desc(const DXGI_SWAP_CHAIN_DESC1 *desc, const DXGI_SWAP_CHAIN_FULLSCREEN_DESC *fullscreen_desc); /* IDXGISurface/IDXGIResource */ struct dxgi_resource diff --git a/dlls/dxgi/factory.c b/dlls/dxgi/factory.c index 43594d14d4e..e3fa6d41160 100644 --- a/dlls/dxgi/factory.c +++ b/dlls/dxgi/factory.c @@ -299,8 +299,17 @@ static HRESULT STDMETHODCALLTYPE dxgi_factory_CreateSwapChainForHwnd(IWineDXGIFa fullscreen_desc = &windowed_fullscreen_desc; } - if (!dxgi_validate_swapchain_desc(desc)) + if (FAILED(hr = dxgi_validate_swapchain_desc(desc, fullscreen_desc))) + { return DXGI_ERROR_INVALID_CALL; + } + else if (hr == DXGI_STATUS_OCCLUDED) + { + /* Create a windowed swapchain instead */ + windowed_fullscreen_desc = *fullscreen_desc; + windowed_fullscreen_desc.Windowed = TRUE; + fullscreen_desc = &windowed_fullscreen_desc; + } if (output) FIXME("Ignoring output %p.\n", output); diff --git a/dlls/dxgi/swapchain.c b/dlls/dxgi/swapchain.c index 206fcd3683b..c33a2daf359 100644 --- a/dlls/dxgi/swapchain.c +++ b/dlls/dxgi/swapchain.c @@ -60,7 +60,8 @@ static BOOL dxgi_validate_flip_swap_effect_format(DXGI_FORMAT format) } } -BOOL dxgi_validate_swapchain_desc(const DXGI_SWAP_CHAIN_DESC1 *desc) +HRESULT dxgi_validate_swapchain_desc(const DXGI_SWAP_CHAIN_DESC1 *desc, + const DXGI_SWAP_CHAIN_FULLSCREEN_DESC *fullscreen_desc) { unsigned int min_buffer_count; @@ -76,28 +77,45 @@ BOOL dxgi_validate_swapchain_desc(const DXGI_SWAP_CHAIN_DESC1 *desc) min_buffer_count = 2; if (desc->Format && !dxgi_validate_flip_swap_effect_format(desc->Format)) - return FALSE; + return DXGI_ERROR_INVALID_CALL; if (desc->SampleDesc.Count != 1 || desc->SampleDesc.Quality) { WARN("Invalid sample desc %u, %u for swap effect %#x.\n", desc->SampleDesc.Count, desc->SampleDesc.Quality, desc->SwapEffect); - return FALSE; + return DXGI_ERROR_INVALID_CALL; } break; default: WARN("Invalid swap effect %u used.\n", desc->SwapEffect); - return FALSE; + return DXGI_ERROR_INVALID_CALL; } if (desc->BufferCount < min_buffer_count || desc->BufferCount > DXGI_MAX_SWAP_CHAIN_BUFFERS) { WARN("BufferCount is %u.\n", desc->BufferCount); - return FALSE; + return DXGI_ERROR_INVALID_CALL; } - return TRUE; + if (fullscreen_desc && !fullscreen_desc->Windowed) + { + if (!(fullscreen_desc->ScanlineOrdering >= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED + && fullscreen_desc->ScanlineOrdering <= DXGI_MODE_SCANLINE_ORDER_LOWER_FIELD_FIRST)) + { + WARN("Invalid scaline order %#x.\n", fullscreen_desc->ScanlineOrdering); + return DXGI_STATUS_OCCLUDED; + } + + if (!(fullscreen_desc->Scaling >= DXGI_MODE_SCALING_UNSPECIFIED + && fullscreen_desc->Scaling <= DXGI_MODE_SCALING_STRETCHED)) + { + WARN("Invalid scaling %#x.\n", fullscreen_desc->Scaling); + return DXGI_STATUS_OCCLUDED; + } + } + + return S_OK; } HRESULT dxgi_get_output_from_window(IWineDXGIFactory *factory, HWND window, IDXGIOutput **dxgi_output) @@ -2586,7 +2604,7 @@ static HRESULT d3d12_swapchain_resize_buffers(struct d3d12_swapchain *swapchain, if (format) new_desc.Format = format; - if (!dxgi_validate_swapchain_desc(&new_desc)) + if (FAILED(dxgi_validate_swapchain_desc(&new_desc, NULL))) return DXGI_ERROR_INVALID_CALL; if (desc->Width == new_desc.Width && desc->Height == new_desc.Height diff --git a/dlls/dxgi/tests/dxgi.c b/dlls/dxgi/tests/dxgi.c index 96dcf7a38cd..7fa3d7ab18a 100644 --- a/dlls/dxgi/tests/dxgi.c +++ b/dlls/dxgi/tests/dxgi.c @@ -2254,18 +2254,15 @@ static void test_create_swapchain(IUnknown *device, BOOL is_d3d12) "Got unexpected scanline ordering %d.\n", fullscreen_desc.ScanlineOrdering); ok(fullscreen_desc.Scaling == creation_desc.BufferDesc.Scaling, "Got unexpected scanline ordering %d.\n", fullscreen_desc.ScanlineOrdering); - todo_wine ok(fullscreen_desc.Windowed != creation_desc.Windowed, "Got unexpected windowed %#x.\n", fullscreen_desc.Windowed); IDXGISwapChain1_Release(swapchain1); } hr = IDXGISwapChain_GetDesc(swapchain, &result_desc); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - todo_wine ok(result_desc.Windowed, "Got unexpected fullscreen state.\n"); hr = IDXGISwapChain_GetFullscreenState(swapchain, &fullscreen, NULL); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - todo_wine ok(!fullscreen, "Got unexpected fullscreen state.\n"); hr = IDXGISwapChain_SetFullscreenState(swapchain, TRUE, NULL); todo_wine @@ -2294,18 +2291,15 @@ static void test_create_swapchain(IUnknown *device, BOOL is_d3d12) "Got unexpected scanline ordering %d.\n", fullscreen_desc.ScanlineOrdering); ok(fullscreen_desc.Scaling == creation_desc.BufferDesc.Scaling, "Got unexpected scanline ordering %d.\n", fullscreen_desc.ScanlineOrdering); - todo_wine ok(fullscreen_desc.Windowed != creation_desc.Windowed, "Got unexpected windowed %#x.\n", fullscreen_desc.Windowed); IDXGISwapChain1_Release(swapchain1); } hr = IDXGISwapChain_GetDesc(swapchain, &result_desc); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - todo_wine ok(result_desc.Windowed, "Got unexpected fullscreen state.\n"); hr = IDXGISwapChain_GetFullscreenState(swapchain, &fullscreen, NULL); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - todo_wine ok(!fullscreen, "Got unexpected fullscreen state.\n"); hr = IDXGISwapChain_SetFullscreenState(swapchain, TRUE, NULL); todo_wine @@ -2336,18 +2330,15 @@ static void test_create_swapchain(IUnknown *device, BOOL is_d3d12) "Got unexpected scanline ordering %d.\n", fullscreen_desc.ScanlineOrdering); ok(fullscreen_desc.Scaling == creation_desc.BufferDesc.Scaling, "Got unexpected scanline ordering %d.\n", fullscreen_desc.ScanlineOrdering); - todo_wine ok(fullscreen_desc.Windowed != creation_desc.Windowed, "Got unexpected windowed %#x.\n", fullscreen_desc.Windowed); IDXGISwapChain1_Release(swapchain1); } hr = IDXGISwapChain_GetDesc(swapchain, &result_desc); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - todo_wine ok(result_desc.Windowed, "Got unexpected fullscreen state.\n"); hr = IDXGISwapChain_GetFullscreenState(swapchain, &fullscreen, NULL); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - todo_wine ok(!fullscreen, "Got unexpected fullscreen state.\n"); hr = IDXGISwapChain_SetFullscreenState(swapchain, TRUE, NULL); todo_wine @@ -2376,18 +2367,15 @@ static void test_create_swapchain(IUnknown *device, BOOL is_d3d12) "Got unexpected scanline ordering %d.\n", fullscreen_desc.ScanlineOrdering); ok(fullscreen_desc.Scaling == creation_desc.BufferDesc.Scaling, "Got unexpected scanline ordering %d.\n", fullscreen_desc.ScanlineOrdering); - todo_wine ok(fullscreen_desc.Windowed != creation_desc.Windowed, "Got unexpected windowed %#x.\n", fullscreen_desc.Windowed); IDXGISwapChain1_Release(swapchain1); } hr = IDXGISwapChain_GetDesc(swapchain, &result_desc); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - todo_wine ok(result_desc.Windowed, "Got unexpected fullscreen state.\n"); hr = IDXGISwapChain_GetFullscreenState(swapchain, &fullscreen, NULL); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - todo_wine ok(!fullscreen, "Got unexpected fullscreen state.\n"); hr = IDXGISwapChain_SetFullscreenState(swapchain, TRUE, NULL); todo_wine -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11231
From: Zhiyi Zhang <zzhang@codeweavers.com> --- dlls/dxgi/swapchain.c | 77 +++++++++++++++++++++++++++++------------- dlls/dxgi/tests/dxgi.c | 24 ------------- 2 files changed, 53 insertions(+), 48 deletions(-) diff --git a/dlls/dxgi/swapchain.c b/dlls/dxgi/swapchain.c index c33a2daf359..1719cc1a488 100644 --- a/dlls/dxgi/swapchain.c +++ b/dlls/dxgi/swapchain.c @@ -65,37 +65,40 @@ HRESULT dxgi_validate_swapchain_desc(const DXGI_SWAP_CHAIN_DESC1 *desc, { unsigned int min_buffer_count; - switch (desc->SwapEffect) + if (desc) { - case DXGI_SWAP_EFFECT_DISCARD: - case DXGI_SWAP_EFFECT_SEQUENTIAL: - min_buffer_count = 1; - break; + switch (desc->SwapEffect) + { + case DXGI_SWAP_EFFECT_DISCARD: + case DXGI_SWAP_EFFECT_SEQUENTIAL: + min_buffer_count = 1; + break; - case DXGI_SWAP_EFFECT_FLIP_DISCARD: - case DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL: - min_buffer_count = 2; + case DXGI_SWAP_EFFECT_FLIP_DISCARD: + case DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL: + min_buffer_count = 2; - if (desc->Format && !dxgi_validate_flip_swap_effect_format(desc->Format)) - return DXGI_ERROR_INVALID_CALL; + if (desc->Format && !dxgi_validate_flip_swap_effect_format(desc->Format)) + return DXGI_ERROR_INVALID_CALL; - if (desc->SampleDesc.Count != 1 || desc->SampleDesc.Quality) - { - WARN("Invalid sample desc %u, %u for swap effect %#x.\n", - desc->SampleDesc.Count, desc->SampleDesc.Quality, desc->SwapEffect); + if (desc->SampleDesc.Count != 1 || desc->SampleDesc.Quality) + { + WARN("Invalid sample desc %u, %u for swap effect %#x.\n", + desc->SampleDesc.Count, desc->SampleDesc.Quality, desc->SwapEffect); + return DXGI_ERROR_INVALID_CALL; + } + break; + + default: + WARN("Invalid swap effect %u used.\n", desc->SwapEffect); return DXGI_ERROR_INVALID_CALL; - } - break; + } - default: - WARN("Invalid swap effect %u used.\n", desc->SwapEffect); + if (desc->BufferCount < min_buffer_count || desc->BufferCount > DXGI_MAX_SWAP_CHAIN_BUFFERS) + { + WARN("BufferCount is %u.\n", desc->BufferCount); return DXGI_ERROR_INVALID_CALL; - } - - if (desc->BufferCount < min_buffer_count || desc->BufferCount > DXGI_MAX_SWAP_CHAIN_BUFFERS) - { - WARN("BufferCount is %u.\n", desc->BufferCount); - return DXGI_ERROR_INVALID_CALL; + } } if (fullscreen_desc && !fullscreen_desc->Windowed) @@ -400,6 +403,19 @@ static HRESULT STDMETHODCALLTYPE DECLSPEC_HOTPATCH d3d11_swapchain_SetFullscreen return DXGI_ERROR_INVALID_CALL; } + if (fullscreen) + { + IDXGISwapChain4_GetFullscreenState(iface, &old_fs, NULL); + if (!old_fs) + { + DXGI_SWAP_CHAIN_FULLSCREEN_DESC test_fullscreen_desc = swapchain->fullscreen_desc; + + test_fullscreen_desc.Windowed = FALSE; + if (dxgi_validate_swapchain_desc(NULL, &test_fullscreen_desc) == DXGI_STATUS_OCCLUDED) + return DXGI_ERROR_INVALID_CALL; + } + } + if (target) { IDXGIOutput_AddRef(target); @@ -2420,6 +2436,19 @@ static HRESULT STDMETHODCALLTYPE DECLSPEC_HOTPATCH d3d12_swapchain_SetFullscreen return DXGI_ERROR_INVALID_CALL; } + if (fullscreen) + { + IDXGISwapChain4_GetFullscreenState(iface, &old_fs, NULL); + if (!old_fs) + { + DXGI_SWAP_CHAIN_FULLSCREEN_DESC test_fullscreen_desc = *fullscreen_desc; + + test_fullscreen_desc.Windowed = FALSE; + if (dxgi_validate_swapchain_desc(NULL, &test_fullscreen_desc) == DXGI_STATUS_OCCLUDED) + return DXGI_ERROR_INVALID_CALL; + } + } + if (target) { IDXGIOutput_AddRef(target); diff --git a/dlls/dxgi/tests/dxgi.c b/dlls/dxgi/tests/dxgi.c index 7fa3d7ab18a..f5443f60372 100644 --- a/dlls/dxgi/tests/dxgi.c +++ b/dlls/dxgi/tests/dxgi.c @@ -2265,13 +2265,7 @@ static void test_create_swapchain(IUnknown *device, BOOL is_d3d12) ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); ok(!fullscreen, "Got unexpected fullscreen state.\n"); hr = IDXGISwapChain_SetFullscreenState(swapchain, TRUE, NULL); - todo_wine ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#lx.\n", hr); - if (hr == S_OK) - { - hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL); - ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - } IDXGISwapChain_Release(swapchain); /* Try to create a fullscreen swapchain with an invalid scanline order, zero width and height. @@ -2302,13 +2296,7 @@ static void test_create_swapchain(IUnknown *device, BOOL is_d3d12) ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); ok(!fullscreen, "Got unexpected fullscreen state.\n"); hr = IDXGISwapChain_SetFullscreenState(swapchain, TRUE, NULL); - todo_wine ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#lx.\n", hr); - if (hr == S_OK) - { - hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL); - ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - } IDXGISwapChain_Release(swapchain); /* Try to create a fullscreen swapchain with an invalid scaling. Expect swapchain creation @@ -2341,13 +2329,7 @@ static void test_create_swapchain(IUnknown *device, BOOL is_d3d12) ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); ok(!fullscreen, "Got unexpected fullscreen state.\n"); hr = IDXGISwapChain_SetFullscreenState(swapchain, TRUE, NULL); - todo_wine ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#lx.\n", hr); - if (hr == S_OK) - { - hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL); - ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - } IDXGISwapChain_Release(swapchain); /* Try to create a fullscreen swapchain with an invalid scaling, zero width and height. Expect @@ -2378,13 +2360,7 @@ static void test_create_swapchain(IUnknown *device, BOOL is_d3d12) ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); ok(!fullscreen, "Got unexpected fullscreen state.\n"); hr = IDXGISwapChain_SetFullscreenState(swapchain, TRUE, NULL); - todo_wine ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#lx.\n", hr); - if (hr == S_OK) - { - hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL); - ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - } IDXGISwapChain_Release(swapchain); done: -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11231
v2: Validate the scanline order and scaling on the DXGI side. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/11231#note_144307
participants (2)
-
Zhiyi Zhang -
Zhiyi Zhang (@zhiyi)