Signed-off-by: Józef Kucia jkucia@codeweavers.com ---
With some tweaks wined3d passes the test.
--- dlls/dxgi/tests/dxgi.c | 276 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 273 insertions(+), 3 deletions(-)
diff --git a/dlls/dxgi/tests/dxgi.c b/dlls/dxgi/tests/dxgi.c index 9ab247254922..8c41eab41cfe 100644 --- a/dlls/dxgi/tests/dxgi.c +++ b/dlls/dxgi/tests/dxgi.c @@ -2152,9 +2152,9 @@ static void test_set_fullscreen(void) ok(SUCCEEDED(hr), "CreateSwapChain failed, hr %#x.\n", hr); check_swapchain_fullscreen_state(swapchain, &initial_state); hr = IDXGISwapChain_SetFullscreenState(swapchain, TRUE, NULL); - ok(SUCCEEDED(hr) || hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE || - broken(hr == DXGI_ERROR_UNSUPPORTED), /* Win 7 testbot */ - "SetFullscreenState failed, hr %#x.\n", hr); + ok(SUCCEEDED(hr) || hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE + || broken(hr == DXGI_ERROR_UNSUPPORTED), /* Win 7 testbot */ + "SetFullscreenState failed, hr %#x.\n", hr); if (FAILED(hr)) { skip("Could not change fullscreen state.\n"); @@ -4211,6 +4211,275 @@ static void test_object_wrapping(void) ok(!refcount, "Factory has %u references left.\n", refcount); }
+/* try to make sure pending X events have been processed before continuing */ +static void flush_events(void) +{ + int diff = 200; + DWORD time; + MSG msg; + + time = GetTickCount() + diff; + while (diff > 0) + { + if (MsgWaitForMultipleObjects(0, NULL, FALSE, 100, QS_ALLINPUT) == WAIT_TIMEOUT) + break; + while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) + DispatchMessageA(&msg); + diff = time - GetTickCount(); + } +} + +struct message +{ + unsigned int message; + BOOL check_wparam; + WPARAM expect_wparam; +}; + +static BOOL expect_no_messages; +static const struct message *expect_messages; +static const struct message *expect_messages_broken; + +static BOOL check_message(const struct message *expected, + HWND hwnd, unsigned int message, WPARAM wparam, LPARAM lparam) +{ + if (expected->message != message) + return FALSE; + + if (expected->check_wparam) + { + ok(wparam == expected->expect_wparam, + "Got unexpected wparam %lx for message %x, expected %lx.\n", + wparam, message, expected->expect_wparam); + } + + return TRUE; +} + +static LRESULT CALLBACK test_wndproc(HWND hwnd, unsigned int message, WPARAM wparam, LPARAM lparam) +{ + ok(!expect_no_messages, "Got unexpected message %#x, hwnd %p, wparam %#lx, lparam %#lx.\n", + message, hwnd, wparam, lparam); + + if (expect_messages) + { + if (check_message(expect_messages, hwnd, message, wparam, lparam)) + ++expect_messages; + } + + if (expect_messages_broken) + { + if (check_message(expect_messages_broken, hwnd, message, wparam, lparam)) + ++expect_messages_broken; + } + + return DefWindowProcA(hwnd, message, wparam, lparam); +} + +static void test_swapchain_window_messages(void) +{ + DXGI_SWAP_CHAIN_DESC swapchain_desc; + IDXGISwapChain *swapchain; + DXGI_MODE_DESC mode_desc; + IDXGIFactory *factory; + IDXGIAdapter *adapter; + IDXGIDevice *device; + ULONG refcount; + WNDCLASSA wc; + HWND window; + HRESULT hr; + + static const struct message enter_fullscreen_messages[] = + { + {WM_STYLECHANGING, TRUE, GWL_STYLE}, + {WM_STYLECHANGED, TRUE, GWL_STYLE}, + {WM_STYLECHANGING, TRUE, GWL_EXSTYLE}, + {WM_STYLECHANGED, TRUE, GWL_EXSTYLE}, + {WM_WINDOWPOSCHANGING, FALSE, 0}, + {WM_GETMINMAXINFO, FALSE, 0}, + {WM_NCCALCSIZE, FALSE, 0}, + {WM_WINDOWPOSCHANGED, FALSE, 0}, + {WM_MOVE, FALSE, 0}, + {WM_SIZE, FALSE, 0}, + {0, FALSE, 0}, + }; + static const struct message enter_fullscreen_messages_vista[] = + { + {WM_STYLECHANGING, TRUE, GWL_STYLE}, + {WM_STYLECHANGED, TRUE, GWL_STYLE}, + {WM_WINDOWPOSCHANGING, FALSE, 0}, + {WM_NCCALCSIZE, FALSE, 0}, + {WM_WINDOWPOSCHANGED, FALSE, 0}, + {WM_MOVE, FALSE, 0}, + {WM_SIZE, FALSE, 0}, + {WM_STYLECHANGING, TRUE, GWL_EXSTYLE}, + {WM_STYLECHANGED, TRUE, GWL_EXSTYLE}, + {WM_WINDOWPOSCHANGING, FALSE, 0}, + {WM_GETMINMAXINFO, FALSE, 0}, + {WM_NCCALCSIZE, FALSE, 0}, + {WM_WINDOWPOSCHANGED, FALSE, 0}, + {WM_SIZE, FALSE, 0}, + {0, FALSE, 0}, + }; + static const struct message leave_fullscreen_messages[] = + { + {WM_STYLECHANGING, TRUE, GWL_STYLE}, + {WM_STYLECHANGED, TRUE, GWL_STYLE}, + {WM_STYLECHANGING, TRUE, GWL_EXSTYLE}, + {WM_STYLECHANGED, TRUE, GWL_EXSTYLE}, + {WM_WINDOWPOSCHANGING, FALSE, 0}, + {WM_GETMINMAXINFO, FALSE, 0}, + {WM_NCCALCSIZE, FALSE, 0}, + {WM_WINDOWPOSCHANGED, FALSE, 0}, + {WM_MOVE, FALSE, 0}, + {WM_SIZE, FALSE, 0}, + {0, FALSE, 0}, + }; + static const struct message resize_target_messages[] = + { + {WM_WINDOWPOSCHANGING, FALSE, 0}, + {WM_GETMINMAXINFO, FALSE, 0}, + {WM_NCCALCSIZE, FALSE, 0}, + {WM_WINDOWPOSCHANGED, FALSE, 0}, + {WM_SIZE, FALSE, 0}, + {0, FALSE, 0}, + }; + + if (!(device = create_device(0))) + { + skip("Failed to create device.\n"); + return; + } + + memset(&wc, 0, sizeof(wc)); + wc.lpfnWndProc = test_wndproc; + wc.lpszClassName = "dxgi_test_wndproc_wc"; + ok(RegisterClassA(&wc), "Failed to register window class.\n"); + window = CreateWindowA("dxgi_test_wndproc_wc", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0); + ok(!!window, "Failed to create window.\n"); + + hr = IDXGIDevice_GetAdapter(device, &adapter); + ok(hr == S_OK, "Failed to get adapter, hr %#x.\n", hr); + hr = IDXGIAdapter_GetParent(adapter, &IID_IDXGIFactory, (void **)&factory); + ok(hr == S_OK, "Failed to get parent, hr %#x.\n", hr); + IDXGIAdapter_Release(adapter); + + swapchain_desc.BufferDesc.Width = 800; + swapchain_desc.BufferDesc.Height = 600; + swapchain_desc.BufferDesc.RefreshRate.Numerator = 60; + swapchain_desc.BufferDesc.RefreshRate.Denominator = 60; + swapchain_desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + swapchain_desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; + swapchain_desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; + swapchain_desc.SampleDesc.Count = 1; + swapchain_desc.SampleDesc.Quality = 0; + swapchain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapchain_desc.BufferCount = 1; + swapchain_desc.OutputWindow = window; + swapchain_desc.Windowed = TRUE; + swapchain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; + swapchain_desc.Flags = 0; + + /* create swapchain */ + flush_events(); + expect_no_messages = TRUE; + hr = IDXGIFactory_CreateSwapChain(factory, (IUnknown *)device, &swapchain_desc, &swapchain); + ok(hr == S_OK, "Failed to create swapchain, hr %#x.\n", hr); + flush_events(); + expect_no_messages = FALSE; + + /* resize target */ + expect_messages = resize_target_messages; + memset(&mode_desc, 0, sizeof(mode_desc)); + mode_desc.Width = 800; + mode_desc.Width = 600; + hr = IDXGISwapChain_ResizeTarget(swapchain, &mode_desc); + ok(hr == S_OK, "Failed to resize target, hr %#x.\n", hr); + flush_events(); + ok(!expect_messages->message, "Expected message %#x.\n", expect_messages->message); + + expect_messages = resize_target_messages; + memset(&mode_desc, 0, sizeof(mode_desc)); + mode_desc.Width = 400; + mode_desc.Width = 200; + hr = IDXGISwapChain_ResizeTarget(swapchain, &mode_desc); + ok(hr == S_OK, "Failed to resize target, hr %#x.\n", hr); + flush_events(); + ok(!expect_messages->message, "Expected message %#x.\n", expect_messages->message); + + /* enter fullscreen */ + expect_messages = enter_fullscreen_messages; + expect_messages_broken = enter_fullscreen_messages_vista; + hr = IDXGISwapChain_SetFullscreenState(swapchain, TRUE, NULL); + ok(hr == S_OK || hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE + || broken(hr == DXGI_ERROR_UNSUPPORTED), /* Win 7 testbot */ + "Failed to enter fullscreen, hr %#x.\n", hr); + if (FAILED(hr)) + { + skip("Could not change fullscreen state.\n"); + goto done; + } + flush_events(); + todo_wine + ok(!expect_messages->message || broken(!expect_messages_broken->message), + "Expected message %#x or %#x.\n", + expect_messages->message, expect_messages_broken->message); + expect_messages_broken = NULL; + + /* leave fullscreen */ + expect_messages = leave_fullscreen_messages; + hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL); + ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); + flush_events(); + todo_wine + ok(!expect_messages->message, "Expected message %#x.\n", expect_messages->message); + expect_messages = NULL; + + refcount = IDXGISwapChain_Release(swapchain); + ok(!refcount, "IDXGISwapChain has %u references left.\n", refcount); + + /* create fullscreen swapchain */ + DestroyWindow(window); + window = CreateWindowA("dxgi_test_wndproc_wc", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0); + ok(!!window, "Failed to create window.\n"); + swapchain_desc.OutputWindow = window; + swapchain_desc.Windowed = FALSE; + swapchain_desc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; + flush_events(); + + expect_messages = enter_fullscreen_messages; + expect_messages_broken = enter_fullscreen_messages_vista; + hr = IDXGIFactory_CreateSwapChain(factory, (IUnknown *)device, &swapchain_desc, &swapchain); + ok(hr == S_OK, "Failed to create swapchain, hr %#x.\n", hr); + flush_events(); + todo_wine + ok(!expect_messages->message || broken(!expect_messages_broken->message), + "Expected message %#x or %#x.\n", + expect_messages->message, expect_messages_broken->message); + expect_messages_broken = NULL; + + /* leave fullscreen */ + expect_messages = leave_fullscreen_messages; + hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL); + ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); + flush_events(); + todo_wine + ok(!expect_messages->message, "Expected message %#x.\n", expect_messages->message); + expect_messages = NULL; + +done: + refcount = IDXGISwapChain_Release(swapchain); + ok(!refcount, "IDXGISwapChain has %u references left.\n", refcount); + DestroyWindow(window); + + refcount = IDXGIDevice_Release(device); + ok(!refcount, "Device has %u references left.\n", refcount); + refcount = IDXGIFactory_Release(factory); + ok(!refcount, "Factory has %u references left.\n", refcount); + + UnregisterClassA("dxgi_test_wndproc_wc", GetModuleHandleA(NULL)); +} + static void run_on_d3d10(void (*test_func)(IUnknown *device, BOOL is_d3d12)) { IDXGIDevice *device; @@ -4304,6 +4573,7 @@ START_TEST(dxgi) test_resize_target(); test_inexact_modes(); test_swapchain_parameters(); + test_swapchain_window_messages(); run_on_d3d10(test_swapchain_resize); run_on_d3d10(test_swapchain_backbuffer_index); run_on_d3d10(test_swapchain_formats);