[PATCH 1/3] dxgi/tests: Add test for swapchain window messages.

Józef Kucia jkucia at codeweavers.com
Wed Sep 19 09:55:29 CDT 2018


Signed-off-by: Józef Kucia <jkucia at 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);
-- 
2.16.4




More information about the wine-devel mailing list