[PATCH 3/3] ddraw/tests: Port test_mode_change to ddraw (v2)

Stefan Dösinger stefan at codeweavers.com
Mon Oct 27 17:34:08 CDT 2014


Version 2: Extend the test to cover surface and window sizes and
external mode changes like the d3d8 and d3d9 versions.

Since ddraw changes the window size on external mode changes there is no
need to prevent shrinking the resolution like.
---
 dlls/ddraw/tests/ddraw1.c | 153 ++++++++++++++++++++++++++++++++++++++++++++++
 dlls/ddraw/tests/ddraw2.c | 153 ++++++++++++++++++++++++++++++++++++++++++++++
 dlls/ddraw/tests/ddraw4.c | 153 ++++++++++++++++++++++++++++++++++++++++++++++
 dlls/ddraw/tests/ddraw7.c | 153 ++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 612 insertions(+)

diff --git a/dlls/ddraw/tests/ddraw1.c b/dlls/ddraw/tests/ddraw1.c
index 742d82c..35aa7af 100644
--- a/dlls/ddraw/tests/ddraw1.c
+++ b/dlls/ddraw/tests/ddraw1.c
@@ -5632,6 +5632,158 @@ static void test_surface_desc_lock(void)
     DestroyWindow(window);
 }
 
+struct mode_change_param
+{
+    DEVMODEW registry_mode;
+    DWORD width1, height1, width2, height2;
+};
+
+static HRESULT CALLBACK test_mode_change_cb(DDSURFACEDESC *surface_desc, void *context)
+{
+    struct mode_change_param *param = context;
+
+    if (U1(surface_desc->ddpfPixelFormat).dwRGBBitCount != param->registry_mode.dmBitsPerPel)
+        return DDENUMRET_OK;
+    if (surface_desc->dwWidth == param->registry_mode.dmPelsWidth
+            && surface_desc->dwHeight == param->registry_mode.dmPelsHeight)
+        return DDENUMRET_OK;
+
+    if (!param->width1)
+    {
+        param->width1 = surface_desc->dwWidth;
+        param->height1 = surface_desc->dwHeight;
+        return DDENUMRET_OK;
+    }
+    if (surface_desc->dwWidth == param->width1 && surface_desc->dwHeight == param->height1)
+        return DDENUMRET_OK;
+
+    param->width2 = surface_desc->dwWidth;
+    param->height2 = surface_desc->dwHeight;
+    return DDENUMRET_CANCEL;
+}
+
+static void test_mode_change(void)
+{
+    IDirectDraw *ddraw;
+    IDirectDrawSurface *surface;
+    DDSURFACEDESC surface_desc;
+    ULONG refcount;
+    HWND window;
+    HRESULT hr;
+    DEVMODEW devmode;
+    BOOL ret;
+    LONG change_ret;
+    struct mode_change_param param;
+    RECT ddraw_rect, user32_rect, r;
+
+    ddraw = create_ddraw();
+    ok(!!ddraw, "Failed to create a ddraw object.\n");
+
+    memset(&param, 0, sizeof(param));
+    param.registry_mode.dmSize = sizeof(param.registry_mode);
+    ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &param.registry_mode);
+    ok(ret, "Failed to get display mode.\n");
+    hr = IDirectDraw_EnumDisplayModes(ddraw, 0, NULL, &param, test_mode_change_cb);
+    ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#x.\n", hr);
+    refcount = IDirectDraw_Release(ddraw);
+    ok(!refcount, "Got unexpected refcount %u.\n", refcount);
+
+    if (!param.width2)
+    {
+        skip("Fewer than 3 different modes supported, skipping mode restore test.\n");
+        return;
+    }
+    SetRect(&user32_rect, 0, 0, param.width1, param.height1);
+    SetRect(&ddraw_rect, 0, 0, param.width2, param.height2);
+
+    memset(&devmode, 0, sizeof(devmode));
+    devmode.dmSize = sizeof(devmode);
+    devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
+    devmode.dmPelsWidth = param.width1;
+    devmode.dmPelsHeight = param.height1;
+    change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
+    ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", ret);
+
+    window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
+            0, 0, 640, 480, 0, 0, 0, 0);
+    ddraw = create_ddraw();
+    ok(!!ddraw, "Failed to create a ddraw object.\n");
+    hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
+    ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
+    hr = set_display_mode(ddraw, param.width2, param.height2);
+    ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
+
+    GetWindowRect(window, &r);
+    ok(EqualRect(&r, &ddraw_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
+            ddraw_rect.left, ddraw_rect.top, ddraw_rect.right, ddraw_rect.bottom,
+            r.left, r.top, r.right, r.bottom);
+
+    memset(&surface_desc, 0, sizeof(surface_desc));
+    surface_desc.dwSize = sizeof(surface_desc);
+    surface_desc.dwFlags = DDSD_CAPS;
+    surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
+    hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
+    ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
+
+    change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
+    ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", ret);
+    GetWindowRect(window, &r);
+    ok(EqualRect(&r, &user32_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
+            user32_rect.left, user32_rect.top, user32_rect.right, user32_rect.bottom,
+            r.left, r.top, r.right, r.bottom);
+
+    if (0) /* Crashes on the testbot. */
+    {
+        hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
+        ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
+        ok(surface_desc.dwWidth == param.width2 && surface_desc.dwHeight == param.height2,
+                "Got unexpected surface size %ux%u, expected %ux%u.\n",
+                surface_desc.dwWidth, surface_desc.dwHeight, param.width2, param.height2);
+    }
+    hr = IDirectDrawSurface_IsLost(surface);
+    todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
+    IDirectDrawSurface_Release(surface);
+
+    hr = IDirectDraw_RestoreDisplayMode(ddraw);
+    ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
+
+    ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
+    ok(ret, "Failed to get display mode.\n");
+    todo_wine ok(devmode.dmPelsWidth == param.registry_mode.dmPelsWidth, "Got unexpect width %u, expected %u.\n",
+            devmode.dmPelsWidth, param.registry_mode.dmPelsWidth);
+    todo_wine ok(devmode.dmPelsHeight == param.registry_mode.dmPelsHeight, "Got unexpect height %u, expected %u.\n",
+            devmode.dmPelsHeight, param.registry_mode.dmPelsHeight);
+
+    refcount = IDirectDraw_Release(ddraw);
+    ok(!refcount, "Got unexpected refcount %u.\n", refcount);
+
+    devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
+    devmode.dmPelsWidth = param.width1;
+    devmode.dmPelsHeight = param.height1;
+    change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
+    ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", ret);
+
+    ddraw = create_ddraw();
+    ok(!!ddraw, "Failed to create a ddraw object.\n");
+    hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
+    ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
+    hr = set_display_mode(ddraw, param.width2, param.height2);
+    ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
+    refcount = IDirectDraw_Release(ddraw);
+    ok(!refcount, "Got unexpected refcount %u.\n", refcount);
+
+    ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
+    ok(ret, "Failed to get display mode.\n");
+    todo_wine ok(devmode.dmPelsWidth == param.registry_mode.dmPelsWidth, "Got unexpect width %u, expected %u.\n",
+            devmode.dmPelsWidth, param.registry_mode.dmPelsWidth);
+    todo_wine ok(devmode.dmPelsHeight == param.registry_mode.dmPelsHeight, "Got unexpect height %u, expected %u.\n",
+            devmode.dmPelsHeight, param.registry_mode.dmPelsHeight);
+
+    DestroyWindow(window);
+    change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
+    ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", ret);
+}
+
 START_TEST(ddraw1)
 {
     IDirectDraw *ddraw;
@@ -5684,4 +5836,5 @@ START_TEST(ddraw1)
     test_palette_alpha();
     test_lost_device();
     test_surface_desc_lock();
+    test_mode_change();
 }
diff --git a/dlls/ddraw/tests/ddraw2.c b/dlls/ddraw/tests/ddraw2.c
index c5a8393..5bd9036 100644
--- a/dlls/ddraw/tests/ddraw2.c
+++ b/dlls/ddraw/tests/ddraw2.c
@@ -6708,6 +6708,158 @@ static void test_surface_desc_lock(void)
     DestroyWindow(window);
 }
 
+struct mode_change_param
+{
+    DEVMODEW registry_mode;
+    DWORD width1, height1, width2, height2;
+};
+
+static HRESULT CALLBACK test_mode_change_cb(DDSURFACEDESC *surface_desc, void *context)
+{
+    struct mode_change_param *param = context;
+
+    if (U1(surface_desc->ddpfPixelFormat).dwRGBBitCount != param->registry_mode.dmBitsPerPel)
+        return DDENUMRET_OK;
+    if (surface_desc->dwWidth == param->registry_mode.dmPelsWidth
+            && surface_desc->dwHeight == param->registry_mode.dmPelsHeight)
+        return DDENUMRET_OK;
+
+    if (!param->width1)
+    {
+        param->width1 = surface_desc->dwWidth;
+        param->height1 = surface_desc->dwHeight;
+        return DDENUMRET_OK;
+    }
+    if (surface_desc->dwWidth == param->width1 && surface_desc->dwHeight == param->height1)
+        return DDENUMRET_OK;
+
+    param->width2 = surface_desc->dwWidth;
+    param->height2 = surface_desc->dwHeight;
+    return DDENUMRET_CANCEL;
+}
+
+static void test_mode_change(void)
+{
+    IDirectDraw2 *ddraw;
+    IDirectDrawSurface *surface;
+    DDSURFACEDESC surface_desc;
+    ULONG refcount;
+    HWND window;
+    HRESULT hr;
+    DEVMODEW devmode;
+    BOOL ret;
+    LONG change_ret;
+    struct mode_change_param param;
+    RECT ddraw_rect, user32_rect, r;
+
+    ddraw = create_ddraw();
+    ok(!!ddraw, "Failed to create a ddraw object.\n");
+
+    memset(&param, 0, sizeof(param));
+    param.registry_mode.dmSize = sizeof(param.registry_mode);
+    ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &param.registry_mode);
+    ok(ret, "Failed to get display mode.\n");
+    hr = IDirectDraw2_EnumDisplayModes(ddraw, 0, NULL, &param, test_mode_change_cb);
+    ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#x.\n", hr);
+    refcount = IDirectDraw2_Release(ddraw);
+    ok(!refcount, "Got unexpected refcount %u.\n", refcount);
+
+    if (!param.width2)
+    {
+        skip("Fewer than 3 different modes supported, skipping mode restore test.\n");
+        return;
+    }
+    SetRect(&user32_rect, 0, 0, param.width1, param.height1);
+    SetRect(&ddraw_rect, 0, 0, param.width2, param.height2);
+
+    memset(&devmode, 0, sizeof(devmode));
+    devmode.dmSize = sizeof(devmode);
+    devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
+    devmode.dmPelsWidth = param.width1;
+    devmode.dmPelsHeight = param.height1;
+    change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
+    ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", ret);
+
+    window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
+            0, 0, 640, 480, 0, 0, 0, 0);
+    ddraw = create_ddraw();
+    ok(!!ddraw, "Failed to create a ddraw object.\n");
+    hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
+    ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
+    hr = set_display_mode(ddraw, param.width2, param.height2);
+    ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
+
+    GetWindowRect(window, &r);
+    ok(EqualRect(&r, &ddraw_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
+            ddraw_rect.left, ddraw_rect.top, ddraw_rect.right, ddraw_rect.bottom,
+            r.left, r.top, r.right, r.bottom);
+
+    memset(&surface_desc, 0, sizeof(surface_desc));
+    surface_desc.dwSize = sizeof(surface_desc);
+    surface_desc.dwFlags = DDSD_CAPS;
+    surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
+    hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
+    ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
+
+    change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
+    ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", ret);
+    GetWindowRect(window, &r);
+    ok(EqualRect(&r, &user32_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
+            user32_rect.left, user32_rect.top, user32_rect.right, user32_rect.bottom,
+            r.left, r.top, r.right, r.bottom);
+
+    if (0) /* Crashes on the testbot. */
+    {
+        hr = IDirectDrawSurface_GetSurfaceDesc(surface, &surface_desc);
+        ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
+        ok(surface_desc.dwWidth == param.width2 && surface_desc.dwHeight == param.height2,
+                "Got unexpected surface size %ux%u, expected %ux%u.\n",
+                surface_desc.dwWidth, surface_desc.dwHeight, param.width2, param.height2);
+    }
+    hr = IDirectDrawSurface_IsLost(surface);
+    todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
+    IDirectDrawSurface_Release(surface);
+
+    hr = IDirectDraw2_RestoreDisplayMode(ddraw);
+    ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
+
+    ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
+    ok(ret, "Failed to get display mode.\n");
+    todo_wine ok(devmode.dmPelsWidth == param.registry_mode.dmPelsWidth, "Got unexpect width %u, expected %u.\n",
+            devmode.dmPelsWidth, param.registry_mode.dmPelsWidth);
+    todo_wine ok(devmode.dmPelsHeight == param.registry_mode.dmPelsHeight, "Got unexpect height %u, expected %u.\n",
+            devmode.dmPelsHeight, param.registry_mode.dmPelsHeight);
+
+    refcount = IDirectDraw2_Release(ddraw);
+    ok(!refcount, "Got unexpected refcount %u.\n", refcount);
+
+    devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
+    devmode.dmPelsWidth = param.width1;
+    devmode.dmPelsHeight = param.height1;
+    change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
+    ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", ret);
+
+    ddraw = create_ddraw();
+    ok(!!ddraw, "Failed to create a ddraw object.\n");
+    hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
+    ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
+    hr = set_display_mode(ddraw, param.width2, param.height2);
+    ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
+    refcount = IDirectDraw2_Release(ddraw);
+    ok(!refcount, "Got unexpected refcount %u.\n", refcount);
+
+    ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
+    ok(ret, "Failed to get display mode.\n");
+    todo_wine ok(devmode.dmPelsWidth == param.registry_mode.dmPelsWidth, "Got unexpect width %u, expected %u.\n",
+            devmode.dmPelsWidth, param.registry_mode.dmPelsWidth);
+    todo_wine ok(devmode.dmPelsHeight == param.registry_mode.dmPelsHeight, "Got unexpect height %u, expected %u.\n",
+            devmode.dmPelsHeight, param.registry_mode.dmPelsHeight);
+
+    DestroyWindow(window);
+    change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
+    ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", ret);
+}
+
 START_TEST(ddraw2)
 {
     IDirectDraw2 *ddraw;
@@ -6766,4 +6918,5 @@ START_TEST(ddraw2)
     test_palette_alpha();
     test_lost_device();
     test_surface_desc_lock();
+    test_mode_change();
 }
diff --git a/dlls/ddraw/tests/ddraw4.c b/dlls/ddraw/tests/ddraw4.c
index 009ac6f..c282e0a 100644
--- a/dlls/ddraw/tests/ddraw4.c
+++ b/dlls/ddraw/tests/ddraw4.c
@@ -7783,6 +7783,158 @@ static void test_surface_desc_lock(void)
     DestroyWindow(window);
 }
 
+struct mode_change_param
+{
+    DEVMODEW registry_mode;
+    DWORD width1, height1, width2, height2;
+};
+
+static HRESULT CALLBACK test_mode_change_cb(DDSURFACEDESC2 *surface_desc, void *context)
+{
+    struct mode_change_param *param = context;
+
+    if (U1(surface_desc->ddpfPixelFormat).dwRGBBitCount != param->registry_mode.dmBitsPerPel)
+        return DDENUMRET_OK;
+    if (surface_desc->dwWidth == param->registry_mode.dmPelsWidth
+            && surface_desc->dwHeight == param->registry_mode.dmPelsHeight)
+        return DDENUMRET_OK;
+
+    if (!param->width1)
+    {
+        param->width1 = surface_desc->dwWidth;
+        param->height1 = surface_desc->dwHeight;
+        return DDENUMRET_OK;
+    }
+    if (surface_desc->dwWidth == param->width1 && surface_desc->dwHeight == param->height1)
+        return DDENUMRET_OK;
+
+    param->width2 = surface_desc->dwWidth;
+    param->height2 = surface_desc->dwHeight;
+    return DDENUMRET_CANCEL;
+}
+
+static void test_mode_change(void)
+{
+    IDirectDraw4 *ddraw;
+    IDirectDrawSurface4 *surface;
+    DDSURFACEDESC2 surface_desc;
+    ULONG refcount;
+    HWND window;
+    HRESULT hr;
+    DEVMODEW devmode;
+    BOOL ret;
+    LONG change_ret;
+    struct mode_change_param param;
+    RECT ddraw_rect, user32_rect, r;
+
+    ddraw = create_ddraw();
+    ok(!!ddraw, "Failed to create a ddraw object.\n");
+
+    memset(&param, 0, sizeof(param));
+    param.registry_mode.dmSize = sizeof(param.registry_mode);
+    ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &param.registry_mode);
+    ok(ret, "Failed to get display mode.\n");
+    hr = IDirectDraw4_EnumDisplayModes(ddraw, 0, NULL, &param, test_mode_change_cb);
+    ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#x.\n", hr);
+    refcount = IDirectDraw4_Release(ddraw);
+    ok(!refcount, "Got unexpected refcount %u.\n", refcount);
+
+    if (!param.width2)
+    {
+        skip("Fewer than 3 different modes supported, skipping mode restore test.\n");
+        return;
+    }
+    SetRect(&user32_rect, 0, 0, param.width1, param.height1);
+    SetRect(&ddraw_rect, 0, 0, param.width2, param.height2);
+
+    memset(&devmode, 0, sizeof(devmode));
+    devmode.dmSize = sizeof(devmode);
+    devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
+    devmode.dmPelsWidth = param.width1;
+    devmode.dmPelsHeight = param.height1;
+    change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
+    ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", ret);
+
+    window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
+            0, 0, 640, 480, 0, 0, 0, 0);
+    ddraw = create_ddraw();
+    ok(!!ddraw, "Failed to create a ddraw object.\n");
+    hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
+    ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
+    hr = set_display_mode(ddraw, param.width2, param.height2);
+    ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
+
+    GetWindowRect(window, &r);
+    ok(EqualRect(&r, &ddraw_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
+            ddraw_rect.left, ddraw_rect.top, ddraw_rect.right, ddraw_rect.bottom,
+            r.left, r.top, r.right, r.bottom);
+
+    memset(&surface_desc, 0, sizeof(surface_desc));
+    surface_desc.dwSize = sizeof(surface_desc);
+    surface_desc.dwFlags = DDSD_CAPS;
+    surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
+    hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
+    ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
+
+    change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
+    ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", ret);
+    GetWindowRect(window, &r);
+    ok(EqualRect(&r, &user32_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
+            user32_rect.left, user32_rect.top, user32_rect.right, user32_rect.bottom,
+            r.left, r.top, r.right, r.bottom);
+
+    if (0) /* Crashes on the testbot. */
+    {
+        hr = IDirectDrawSurface4_GetSurfaceDesc(surface, &surface_desc);
+        ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
+        ok(surface_desc.dwWidth == param.width2 && surface_desc.dwHeight == param.height2,
+                "Got unexpected surface size %ux%u, expected %ux%u.\n",
+                surface_desc.dwWidth, surface_desc.dwHeight, param.width2, param.height2);
+    }
+    hr = IDirectDrawSurface4_IsLost(surface);
+    todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
+    IDirectDrawSurface4_Release(surface);
+
+    hr = IDirectDraw4_RestoreDisplayMode(ddraw);
+    ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
+
+    ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
+    ok(ret, "Failed to get display mode.\n");
+    todo_wine ok(devmode.dmPelsWidth == param.registry_mode.dmPelsWidth, "Got unexpect width %u, expected %u.\n",
+            devmode.dmPelsWidth, param.registry_mode.dmPelsWidth);
+    todo_wine ok(devmode.dmPelsHeight == param.registry_mode.dmPelsHeight, "Got unexpect height %u, expected %u.\n",
+            devmode.dmPelsHeight, param.registry_mode.dmPelsHeight);
+
+    refcount = IDirectDraw4_Release(ddraw);
+    ok(!refcount, "Got unexpected refcount %u.\n", refcount);
+
+    devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
+    devmode.dmPelsWidth = param.width1;
+    devmode.dmPelsHeight = param.height1;
+    change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
+    ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", ret);
+
+    ddraw = create_ddraw();
+    ok(!!ddraw, "Failed to create a ddraw object.\n");
+    hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
+    ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
+    hr = set_display_mode(ddraw, param.width2, param.height2);
+    ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
+    refcount = IDirectDraw4_Release(ddraw);
+    ok(!refcount, "Got unexpected refcount %u.\n", refcount);
+
+    ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
+    ok(ret, "Failed to get display mode.\n");
+    todo_wine ok(devmode.dmPelsWidth == param.registry_mode.dmPelsWidth, "Got unexpect width %u, expected %u.\n",
+            devmode.dmPelsWidth, param.registry_mode.dmPelsWidth);
+    todo_wine ok(devmode.dmPelsHeight == param.registry_mode.dmPelsHeight, "Got unexpect height %u, expected %u.\n",
+            devmode.dmPelsHeight, param.registry_mode.dmPelsHeight);
+
+    DestroyWindow(window);
+    change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
+    ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", ret);
+}
+
 START_TEST(ddraw4)
 {
     IDirectDraw4 *ddraw;
@@ -7848,4 +8000,5 @@ START_TEST(ddraw4)
     test_vb_writeonly();
     test_lost_device();
     test_surface_desc_lock();
+    test_mode_change();
 }
diff --git a/dlls/ddraw/tests/ddraw7.c b/dlls/ddraw/tests/ddraw7.c
index ec50fb8..a63cc15 100644
--- a/dlls/ddraw/tests/ddraw7.c
+++ b/dlls/ddraw/tests/ddraw7.c
@@ -7626,6 +7626,158 @@ static void test_surface_desc_lock(void)
     DestroyWindow(window);
 }
 
+struct mode_change_param
+{
+    DEVMODEW registry_mode;
+    DWORD width1, height1, width2, height2;
+};
+
+static HRESULT CALLBACK test_mode_change_cb(DDSURFACEDESC2 *surface_desc, void *context)
+{
+    struct mode_change_param *param = context;
+
+    if (U1(surface_desc->ddpfPixelFormat).dwRGBBitCount != param->registry_mode.dmBitsPerPel)
+        return DDENUMRET_OK;
+    if (surface_desc->dwWidth == param->registry_mode.dmPelsWidth
+            && surface_desc->dwHeight == param->registry_mode.dmPelsHeight)
+        return DDENUMRET_OK;
+
+    if (!param->width1)
+    {
+        param->width1 = surface_desc->dwWidth;
+        param->height1 = surface_desc->dwHeight;
+        return DDENUMRET_OK;
+    }
+    if (surface_desc->dwWidth == param->width1 && surface_desc->dwHeight == param->height1)
+        return DDENUMRET_OK;
+
+    param->width2 = surface_desc->dwWidth;
+    param->height2 = surface_desc->dwHeight;
+    return DDENUMRET_CANCEL;
+}
+
+static void test_mode_change(void)
+{
+    IDirectDraw7 *ddraw;
+    IDirectDrawSurface7 *surface;
+    DDSURFACEDESC2 surface_desc;
+    ULONG refcount;
+    HWND window;
+    HRESULT hr;
+    DEVMODEW devmode;
+    BOOL ret;
+    LONG change_ret;
+    struct mode_change_param param;
+    RECT ddraw_rect, user32_rect, r;
+
+    ddraw = create_ddraw();
+    ok(!!ddraw, "Failed to create a ddraw object.\n");
+
+    memset(&param, 0, sizeof(param));
+    param.registry_mode.dmSize = sizeof(param.registry_mode);
+    ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &param.registry_mode);
+    ok(ret, "Failed to get display mode.\n");
+    hr = IDirectDraw7_EnumDisplayModes(ddraw, 0, NULL, &param, test_mode_change_cb);
+    ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#x.\n", hr);
+    refcount = IDirectDraw7_Release(ddraw);
+    ok(!refcount, "Got unexpected refcount %u.\n", refcount);
+
+    if (!param.width2)
+    {
+        skip("Fewer than 3 different modes supported, skipping mode restore test.\n");
+        return;
+    }
+    SetRect(&user32_rect, 0, 0, param.width1, param.height1);
+    SetRect(&ddraw_rect, 0, 0, param.width2, param.height2);
+
+    memset(&devmode, 0, sizeof(devmode));
+    devmode.dmSize = sizeof(devmode);
+    devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
+    devmode.dmPelsWidth = param.width1;
+    devmode.dmPelsHeight = param.height1;
+    change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
+    ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", ret);
+
+    window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
+            0, 0, 640, 480, 0, 0, 0, 0);
+    ddraw = create_ddraw();
+    ok(!!ddraw, "Failed to create a ddraw object.\n");
+    hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
+    ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
+    hr = set_display_mode(ddraw, param.width2, param.height2);
+    ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
+
+    GetWindowRect(window, &r);
+    ok(EqualRect(&r, &ddraw_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
+            ddraw_rect.left, ddraw_rect.top, ddraw_rect.right, ddraw_rect.bottom,
+            r.left, r.top, r.right, r.bottom);
+
+    memset(&surface_desc, 0, sizeof(surface_desc));
+    surface_desc.dwSize = sizeof(surface_desc);
+    surface_desc.dwFlags = DDSD_CAPS;
+    surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
+    hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
+    ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
+
+    change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
+    ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", ret);
+    GetWindowRect(window, &r);
+    ok(EqualRect(&r, &user32_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
+            user32_rect.left, user32_rect.top, user32_rect.right, user32_rect.bottom,
+            r.left, r.top, r.right, r.bottom);
+
+    if (0) /* Crashes on the testbot. */
+    {
+        hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &surface_desc);
+        ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
+        ok(surface_desc.dwWidth == param.width2 && surface_desc.dwHeight == param.height2,
+                "Got unexpected surface size %ux%u, expected %ux%u.\n",
+                surface_desc.dwWidth, surface_desc.dwHeight, param.width2, param.height2);
+    }
+    hr = IDirectDrawSurface7_IsLost(surface);
+    todo_wine ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
+    IDirectDrawSurface7_Release(surface);
+
+    hr = IDirectDraw7_RestoreDisplayMode(ddraw);
+    ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
+
+    ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
+    ok(ret, "Failed to get display mode.\n");
+    todo_wine ok(devmode.dmPelsWidth == param.registry_mode.dmPelsWidth, "Got unexpect width %u, expected %u.\n",
+            devmode.dmPelsWidth, param.registry_mode.dmPelsWidth);
+    todo_wine ok(devmode.dmPelsHeight == param.registry_mode.dmPelsHeight, "Got unexpect height %u, expected %u.\n",
+            devmode.dmPelsHeight, param.registry_mode.dmPelsHeight);
+
+    refcount = IDirectDraw7_Release(ddraw);
+    ok(!refcount, "Got unexpected refcount %u.\n", refcount);
+
+    devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
+    devmode.dmPelsWidth = param.width1;
+    devmode.dmPelsHeight = param.height1;
+    change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
+    ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", ret);
+
+    ddraw = create_ddraw();
+    ok(!!ddraw, "Failed to create a ddraw object.\n");
+    hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
+    ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
+    hr = set_display_mode(ddraw, param.width2, param.height2);
+    ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
+    todo_wine refcount = IDirectDraw7_Release(ddraw);
+    ok(!refcount, "Got unexpected refcount %u.\n", refcount);
+
+    ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
+    ok(ret, "Failed to get display mode.\n");
+    todo_wine ok(devmode.dmPelsWidth == param.registry_mode.dmPelsWidth, "Got unexpect width %u, expected %u.\n",
+            devmode.dmPelsWidth, param.registry_mode.dmPelsWidth);
+    todo_wine ok(devmode.dmPelsHeight == param.registry_mode.dmPelsHeight, "Got unexpect height %u, expected %u.\n",
+            devmode.dmPelsHeight, param.registry_mode.dmPelsHeight);
+
+    DestroyWindow(window);
+    change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
+    ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", ret);
+}
+
 START_TEST(ddraw7)
 {
     HMODULE module = GetModuleHandleA("ddraw.dll");
@@ -7699,4 +7851,5 @@ START_TEST(ddraw7)
     test_lost_device();
     test_resource_priority();
     test_surface_desc_lock();
+    test_mode_change();
 }
-- 
2.0.4




More information about the wine-patches mailing list