[PATCH 05/10] d3d9/tests: Port test_wndproc to d3d9ex.
Stefan Dösinger
stefan at codeweavers.com
Thu Sep 25 07:24:21 CDT 2014
---
dlls/d3d9/tests/d3d9ex.c | 353 ++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 348 insertions(+), 5 deletions(-)
diff --git a/dlls/d3d9/tests/d3d9ex.c b/dlls/d3d9/tests/d3d9ex.c
index 0309013..8db6e8b 100644
--- a/dlls/d3d9/tests/d3d9ex.c
+++ b/dlls/d3d9/tests/d3d9ex.c
@@ -420,7 +420,6 @@ static void test_get_adapter_displaymode_ex(void)
D3DDISPLAYMODE mode;
D3DDISPLAYMODEEX mode_ex;
D3DDISPLAYROTATION rotation;
- HANDLE hdll;
DEVMODEA startmode;
LONG retval;
@@ -447,10 +446,6 @@ static void test_get_adapter_displaymode_ex(void)
hr);
ok(d3d9 != NULL && d3d9 != (void *) 0xdeadbeef,
"QueryInterface returned interface %p, expected != NULL && != 0xdeadbeef\n", d3d9);
- /* change displayorientation*/
- hdll = GetModuleHandleA("user32.dll");
- pEnumDisplaySettingsExA = (void*)GetProcAddress(hdll, "EnumDisplaySettingsExA");
- pChangeDisplaySettingsExA = (void*)GetProcAddress(hdll, "ChangeDisplaySettingsExA");
if (!pEnumDisplaySettingsExA || !pChangeDisplaySettingsExA) goto out;
@@ -1331,8 +1326,351 @@ done:
DestroyWindow(window);
}
+/* try to make sure pending X events have been processed before continuing */
+static void flush_events(void)
+{
+ MSG msg;
+ int diff = 200;
+ int min_timeout = 100;
+ DWORD time = GetTickCount() + diff;
+
+ while (diff > 0)
+ {
+ if (MsgWaitForMultipleObjects( 0, NULL, FALSE, min_timeout, QS_ALLINPUT ) == WAIT_TIMEOUT) break;
+ while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
+ diff = time - GetTickCount();
+ }
+}
+
+static HWND filter_messages;
+
+enum message_window
+{
+ DEVICE_WINDOW,
+ FOCUS_WINDOW,
+};
+
+struct message
+{
+ UINT message;
+ enum message_window window;
+ BOOL check_wparam;
+ WPARAM expect_wparam;
+};
+
+static const struct message *expect_messages;
+static HWND device_window, focus_window;
+
+struct wndproc_thread_param
+{
+ HWND dummy_window;
+ HANDLE window_created;
+ HANDLE test_finished;
+ BOOL running_in_foreground;
+};
+
+static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
+{
+ if (filter_messages && filter_messages == hwnd)
+ {
+ if (message != WM_DISPLAYCHANGE && message != WM_IME_NOTIFY)
+ todo_wine ok( 0, "Received unexpected message %#x for window %p.\n", message, hwnd);
+ }
+
+ if (expect_messages)
+ {
+ HWND w;
+
+ switch (expect_messages->window)
+ {
+ case DEVICE_WINDOW:
+ w = device_window;
+ break;
+
+ case FOCUS_WINDOW:
+ w = focus_window;
+ break;
+
+ default:
+ w = NULL;
+ break;
+ };
+
+
+ if (hwnd == w && expect_messages->message == message)
+ {
+ if (expect_messages->check_wparam)
+ ok(wparam == expect_messages->expect_wparam,
+ "Got unexpected wparam %lx for message %x.\n", wparam, message);
+
+ ++expect_messages;
+ }
+ }
+
+ return DefWindowProcA(hwnd, message, wparam, lparam);
+}
+
+static DWORD WINAPI wndproc_thread(void *param)
+{
+ struct wndproc_thread_param *p = param;
+ DWORD res;
+ BOOL ret;
+
+ p->dummy_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
+ WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, 200, 200, 0, 0, 0, 0);
+ p->running_in_foreground = SetForegroundWindow(p->dummy_window);
+
+ ret = SetEvent(p->window_created);
+ ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
+
+ for (;;)
+ {
+ MSG msg;
+
+ while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
+ res = WaitForSingleObject(p->test_finished, 100);
+ if (res == WAIT_OBJECT_0) break;
+ if (res != WAIT_TIMEOUT)
+ {
+ ok(0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
+ break;
+ }
+ }
+
+ DestroyWindow(p->dummy_window);
+
+ return 0;
+}
+
+static void test_wndproc(void)
+{
+ struct wndproc_thread_param thread_params;
+ IDirect3DDevice9Ex *device;
+ WNDCLASSA wc = {0};
+ IDirect3D9Ex *d3d9;
+ HANDLE thread;
+ LONG_PTR proc;
+ ULONG ref;
+ DWORD res, tid;
+ HWND tmp;
+ D3DPRESENT_PARAMETERS present_parameters = {0};
+ DEVMODEA devmode, orig_mode;
+ BOOL ret;
+ D3DDISPLAYMODEEX mode;
+ HRESULT hr;
+
+ static const struct message create_messages[] =
+ {
+ {WM_WINDOWPOSCHANGING, FOCUS_WINDOW, FALSE, 0},
+ {WM_ACTIVATE, FOCUS_WINDOW, TRUE, WA_ACTIVE},
+ {WM_SETFOCUS, FOCUS_WINDOW, FALSE, 0},
+ {0, 0, FALSE, 0},
+ };
+ static const struct message focus_loss_messages[] =
+ {
+ {WM_ACTIVATE, FOCUS_WINDOW, TRUE, WA_INACTIVE},
+ {WM_DISPLAYCHANGE, DEVICE_WINDOW, FALSE, 0},
+ /* WM_DISPLAYCHANGE is sent to the focus window too, but the order is
+ * not deterministic. */
+ {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0},
+ /* Windows sends WM_ACTIVATE to the device window, indicating that
+ * SW_SHOWMINIMIZED is used instead of SW_MINIMIZE. Yet afterwards
+ * the foreground and focus window are NULL. On Wine SW_SHOWMINIMIZED
+ * leaves the device window active, breaking re-activation in the
+ * lost device test.
+ * {WM_ACTIVATE, DEVICE_WINDOW, TRUE, 0x200000 | WA_ACTIVE}, */
+ {WM_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0},
+ {WM_SIZE, DEVICE_WINDOW, TRUE, SIZE_MINIMIZED},
+ {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE},
+ /* WM_ACTIVATEAPP is sent to the device window too, but the order is
+ * not deterministic. It may be sent after the focus window handling
+ * or before. */
+ {0, 0, FALSE, 0},
+ };
+
+ memset(&orig_mode, 0, sizeof(orig_mode));
+ orig_mode.dmSize = sizeof(orig_mode);
+ ret = pEnumDisplaySettingsExA(NULL, ENUM_CURRENT_SETTINGS, &orig_mode, 0);
+ ok(ret, "Failed to get display mode.\n");
+
+ if (FAILED(pDirect3DCreate9Ex(D3D_SDK_VERSION, &d3d9)))
+ return;
+
+ wc.lpfnWndProc = test_proc;
+ wc.lpszClassName = "d3d9_test_wndproc_wc";
+ ok(RegisterClassA(&wc), "Failed to register window class.\n");
+
+ thread_params.window_created = CreateEventA(NULL, FALSE, FALSE, NULL);
+ ok(!!thread_params.window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
+ thread_params.test_finished = CreateEventA(NULL, FALSE, FALSE, NULL);
+ ok(!!thread_params.test_finished, "CreateEvent failed, last error %#x.\n", GetLastError());
+
+ focus_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
+ WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, orig_mode.dmPelsWidth, orig_mode.dmPelsHeight, 0, 0, 0, 0);
+ device_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
+ WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, orig_mode.dmPelsWidth, orig_mode.dmPelsHeight, 0, 0, 0, 0);
+ thread = CreateThread(NULL, 0, wndproc_thread, &thread_params, 0, &tid);
+ ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
+
+ res = WaitForSingleObject(thread_params.window_created, INFINITE);
+ ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
+
+ proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
+ ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
+ (LONG_PTR)test_proc, proc);
+ proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
+ ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
+ (LONG_PTR)test_proc, proc);
+
+ trace("device_window %p, focus_window %p, dummy_window %p.\n",
+ device_window, focus_window, thread_params.dummy_window);
+
+ tmp = GetFocus();
+ ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
+ if (thread_params.running_in_foreground)
+ {
+ tmp = GetForegroundWindow();
+ ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
+ thread_params.dummy_window, tmp);
+ }
+ else
+ skip("Not running in foreground, skip foreground window test\n");
+
+ flush_events();
+
+ expect_messages = create_messages;
+
+ present_parameters.Windowed = FALSE;
+ present_parameters.hDeviceWindow = device_window;
+ present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
+ present_parameters.BackBufferWidth = 640;
+ present_parameters.BackBufferHeight = 480;
+ present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
+ mode.Size = sizeof(mode);
+ mode.Width = 640;
+ mode.Height = 480;
+ mode.RefreshRate = 0;
+ mode.Format = D3DFMT_A8R8G8B8;
+ mode.ScanLineOrdering = 0;
+ if (FAILED(IDirect3D9Ex_CreateDeviceEx(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
+ D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &mode, &device)))
+ {
+ skip("Failed to create a D3D device, skipping tests.\n");
+ goto done;
+ }
+
+ ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it.\n",
+ expect_messages->message, expect_messages->window);
+ expect_messages = NULL;
+
+ if (0) /* Disabled until we can make this work in a reliable way on Wine. */
+ {
+ tmp = GetFocus();
+ ok(tmp == focus_window, "Expected focus %p, got %p.\n", focus_window, tmp);
+ tmp = GetForegroundWindow();
+ ok(tmp == focus_window, "Expected foreground window %p, got %p.\n", focus_window, tmp);
+ }
+ SetForegroundWindow(focus_window);
+ flush_events();
+
+ proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
+ ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
+ (LONG_PTR)test_proc, proc);
+
+ proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
+ ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
+ (LONG_PTR)test_proc, proc);
+
+ filter_messages = NULL;
+ expect_messages = focus_loss_messages;
+ SetForegroundWindow(GetDesktopWindow());
+ ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it.\n",
+ expect_messages->message, expect_messages->window);
+ expect_messages = NULL;
+ tmp = GetFocus();
+ ok(tmp != device_window, "The device window is active.\n");
+ ok(tmp != focus_window, "The focus window is active.\n");
+
+ memset(&devmode, 0, sizeof(devmode));
+ devmode.dmSize = sizeof(devmode);
+ ret = pEnumDisplaySettingsExA(NULL, ENUM_CURRENT_SETTINGS, &devmode, 0);
+ ok(ret, "Failed to get display mode.\n");
+ ok(devmode.dmPelsWidth == orig_mode.dmPelsWidth, "Got unexpect width %u.\n", devmode.dmPelsWidth);
+ ok(devmode.dmPelsHeight == orig_mode.dmPelsHeight, "Got unexpect height %u.\n", devmode.dmPelsHeight);
+
+ proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
+ ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
+ (LONG_PTR)test_proc, proc);
+
+ proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
+ ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
+ (LONG_PTR)test_proc, proc);
+
+ /* For some reason I have to minimize and restore the focus window,
+ * otherwise native d3d9 fails device::reset. */
+ ShowWindow(focus_window, SW_MINIMIZE);
+ ShowWindow(focus_window, SW_RESTORE);
+ SetForegroundWindow(focus_window);
+ flush_events();
+
+ filter_messages = focus_window;
+ hr = reset_device(device, device_window, FALSE);
+ ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
+
+ ref = IDirect3DDevice9_Release(device);
+ ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
+
+ proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
+ ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
+ (LONG_PTR)test_proc, proc);
+
+ device = create_device(focus_window, focus_window, FALSE);
+ if (!device)
+ {
+ skip("Failed to create a D3D device, skipping tests.\n");
+ goto done;
+ }
+
+ ref = IDirect3DDevice9_Release(device);
+ ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
+
+ device = create_device(device_window, focus_window, FALSE);
+ if (!device)
+ {
+ skip("Failed to create a D3D device, skipping tests.\n");
+ goto done;
+ }
+
+ proc = SetWindowLongPtrA(focus_window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
+ ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
+ (LONG_PTR)test_proc, proc);
+
+ ref = IDirect3DDevice9_Release(device);
+ ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
+
+ proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
+ ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
+ (LONG_PTR)DefWindowProcA, proc);
+
+done:
+ filter_messages = NULL;
+ IDirect3D9_Release(d3d9);
+
+ SetEvent(thread_params.test_finished);
+ WaitForSingleObject(thread, INFINITE);
+ CloseHandle(thread_params.test_finished);
+ CloseHandle(thread_params.window_created);
+ CloseHandle(thread);
+
+ DestroyWindow(device_window);
+ DestroyWindow(focus_window);
+ UnregisterClassA("d3d9_test_wndproc_wc", GetModuleHandleA(NULL));
+}
+
START_TEST(d3d9ex)
{
+ HANDLE user32_handle;
+
d3d9_handle = LoadLibraryA("d3d9.dll");
if (!d3d9_handle)
{
@@ -1346,6 +1684,10 @@ START_TEST(d3d9ex)
return;
}
+ user32_handle = GetModuleHandleA("user32.dll");
+ pEnumDisplaySettingsExA = (void*)GetProcAddress(user32_handle, "EnumDisplaySettingsExA");
+ pChangeDisplaySettingsExA = (void*)GetProcAddress(user32_handle, "ChangeDisplaySettingsExA");
+
test_qi_base_to_ex();
test_qi_ex_to_base();
test_swapchain_get_displaymode_ex();
@@ -1357,4 +1699,5 @@ START_TEST(d3d9ex)
test_vidmem_accounting();
test_user_memory_getdc();
test_lost_device();
+ test_wndproc();
}
--
1.8.5.5
More information about the wine-patches
mailing list