[PATCH 3/4] ddraw/tests: Add tests for lost P8 primaries.

Stefan Dösinger stefan at codeweavers.com
Sun Jul 6 11:06:44 CDT 2014


The explicit request of DDSCAPS_VIDEOMEMORY is needed to work around two
bugs in Wine's ddraw that are not the concern of this test: If neither
SYSTEMMEMORY nor VIDEOMEMORY are requested we use SYSTEMMEMORY for P8
surfaces because check_device_format fails. The next patch addresses
this. The second problem is that we do not lose system memory surfaces
on SetCooperativeLevel even though we should. (We should at least lose
primaries. I haven't checked offscreen or texture surfaces.)

I don't feel strongly about having this test included. I'm happy with
just sending it as a documentation that SetCooperativeLevel does not
have to restore the palette. If the DDSCAPS_VIDEOMEMORY is considered
ugly, or the fix in the next patch wrong just ignore the patches. I do
not know any game that depends on the behavior tested here or the
behavior changed in the next patch.
---
 dlls/ddraw/tests/ddraw1.c | 141 +++++++++++++++++++++++++++++++++++++++++++
 dlls/ddraw/tests/ddraw2.c | 141 +++++++++++++++++++++++++++++++++++++++++++
 dlls/ddraw/tests/ddraw4.c | 141 +++++++++++++++++++++++++++++++++++++++++++
 dlls/ddraw/tests/ddraw7.c | 150 ++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 573 insertions(+)

diff --git a/dlls/ddraw/tests/ddraw1.c b/dlls/ddraw/tests/ddraw1.c
index ad60606..1bcd31f 100644
--- a/dlls/ddraw/tests/ddraw1.c
+++ b/dlls/ddraw/tests/ddraw1.c
@@ -5575,6 +5575,146 @@ static void test_lost_device(void)
     DestroyWindow(window);
 }
 
+static void test_palette_lost(void)
+{
+    IDirectDrawSurface *primary, *texture;
+    DDSURFACEDESC surface_desc;
+    IDirectDraw *ddraw;
+    IDirectDrawPalette *palette, *palette2, *palette3;
+    ULONG refcount;
+    HWND window;
+    HRESULT hr;
+    PALETTEENTRY palette_entries[256];
+    DWORD needed_caps = DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE;
+    DDCAPS hal_caps;
+
+    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");
+
+    memset(&hal_caps, 0, sizeof(hal_caps));
+    hal_caps.dwSize = sizeof(hal_caps);
+    hr = IDirectDraw_GetCaps(ddraw, &hal_caps, NULL);
+    ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
+    if ((hal_caps.ddsCaps.dwCaps & needed_caps) != needed_caps)
+    {
+        skip("Video memory surfaces or textures not supported, skipping test.\n");
+        goto done;
+    }
+
+    if (FAILED(IDirectDraw_SetDisplayMode(ddraw, 640, 480, 8)))
+    {
+        win_skip("Failed to set 8 bpp display mode, skipping test.\n");
+        goto done;
+    }
+    hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
+    ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
+
+    memset(palette_entries, 0, sizeof(palette_entries));
+    hr = IDirectDraw_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
+            palette_entries, &palette, NULL);
+    ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
+    hr = IDirectDraw_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
+            palette_entries, &palette2, NULL);
+    ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
+    memset(&surface_desc, 0, sizeof(surface_desc));
+    surface_desc.dwSize = sizeof(surface_desc);
+    surface_desc.dwFlags = DDSD_CAPS;
+    surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_VIDEOMEMORY;
+    hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &primary, NULL);
+    ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
+    hr = IDirectDrawSurface_SetPalette(primary, palette);
+    ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
+
+    hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
+    ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
+
+    hr = IDirectDrawSurface_IsLost(primary);
+    ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
+    hr = IDirectDrawSurface_GetPalette(primary, &palette3);
+    ok(hr == DDERR_SURFACELOST || broken(SUCCEEDED(hr)) /* Win8 */, "Got unexpected hr %#x.\n", hr);
+    if (SUCCEEDED(hr))
+        IDirectDrawPalette_Release(palette3);
+    hr = IDirectDrawSurface_GetPalette(primary, NULL);
+    ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
+    hr = IDirectDrawSurface_SetPalette(primary, palette2);
+    ok(hr == DDERR_SURFACELOST || broken(SUCCEEDED(hr)) /* Win8 */, "Got unexpected hr %#x.\n", hr);
+
+    hr = IDirectDrawSurface_Restore(primary);
+    ok(SUCCEEDED(hr), "Failed to restore surface, hr %#x.\n", hr);
+    hr = IDirectDrawSurface_IsLost(primary);
+    ok(SUCCEEDED(hr), "Failed to restore surface, hr %#x.\n", hr);
+    hr = IDirectDrawSurface_GetPalette(primary, &palette3);
+    ok(SUCCEEDED(hr), "Failed to get palette, hr %#x.\n", hr);
+    ok(palette3 == palette || broken(palette3 == palette2), "Got unexpected palette %p.\n", palette3);
+    IDirectDrawPalette_Release(palette3);
+
+    /* Even though the palette is assigned to the surface it is not used when
+     * writing data to the surface. Instead, Windows seems to use the system
+     * palette to transform P8 data into RGB colors. Other things are drawn
+     * onto the screen as well, like highlights from the start menu. Do not
+     * test the actual color values until we find an application that depends
+     * on this behavior. Tested on Windows XP and Windows 7. */
+
+    /* The Windows 8 testbot keeps extra references to the primary and
+     * backbuffer while in 8 bpp mode. */
+    hr = IDirectDraw_RestoreDisplayMode(ddraw);
+    ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
+    refcount = IDirectDrawSurface_Release(primary);
+    ok(!refcount, "Got unexpected refcount %u.\n", refcount);
+
+    /* Test priorities of error values. */
+    hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
+    ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
+    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, &primary, NULL);
+    ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
+    memset(&surface_desc, 0, sizeof(surface_desc));
+    surface_desc.dwSize = sizeof(surface_desc);
+    surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
+    surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
+    surface_desc.dwWidth = 4;
+    surface_desc.dwHeight = 4;
+    surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
+    surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
+    U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
+    U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
+    U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
+    U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
+    hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &texture, NULL);
+    ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
+
+    hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
+    ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
+    hr = IDirectDrawSurface_IsLost(primary);
+    ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
+    hr = IDirectDrawSurface_SetPalette(primary, palette);
+    ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr); /* For some reason this works even on Win8. */
+
+    hr = IDirectDrawSurface_IsLost(texture);
+    ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
+    hr = IDirectDrawSurface_SetPalette(texture, palette);
+    ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
+
+    refcount = IDirectDrawSurface_Release(texture);
+    ok(!refcount, "Got unexpected refcount %u.\n", refcount);
+    refcount = IDirectDrawSurface_Release(primary);
+    ok(!refcount, "Got unexpected refcount %u.\n", refcount);
+    refcount = IDirectDrawPalette_Release(palette);
+    ok(!refcount, "Got unexpected refcount %u.\n", refcount);
+    refcount = IDirectDrawPalette_Release(palette2);
+    ok(!refcount, "Got unexpected refcount %u.\n", refcount);
+
+done:
+    refcount = IDirectDraw_Release(ddraw);
+    ok(!refcount, "Got unexpected refcount %u.\n", refcount);
+    DestroyWindow(window);
+}
+
 START_TEST(ddraw1)
 {
     IDirectDraw *ddraw;
@@ -5626,4 +5766,5 @@ START_TEST(ddraw1)
     test_palette_gdi();
     test_palette_alpha();
     test_lost_device();
+    test_palette_lost();
 }
diff --git a/dlls/ddraw/tests/ddraw2.c b/dlls/ddraw/tests/ddraw2.c
index 7e0e925..cedf83e 100644
--- a/dlls/ddraw/tests/ddraw2.c
+++ b/dlls/ddraw/tests/ddraw2.c
@@ -6651,6 +6651,146 @@ static void test_lost_device(void)
     DestroyWindow(window);
 }
 
+static void test_palette_lost(void)
+{
+    IDirectDrawSurface *primary, *texture;
+    DDSURFACEDESC surface_desc;
+    IDirectDraw2 *ddraw;
+    IDirectDrawPalette *palette, *palette2, *palette3;
+    ULONG refcount;
+    HWND window;
+    HRESULT hr;
+    PALETTEENTRY palette_entries[256];
+    DWORD needed_caps = DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE;
+    DDCAPS hal_caps;
+
+    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");
+
+    memset(&hal_caps, 0, sizeof(hal_caps));
+    hal_caps.dwSize = sizeof(hal_caps);
+    hr = IDirectDraw2_GetCaps(ddraw, &hal_caps, NULL);
+    ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
+    if ((hal_caps.ddsCaps.dwCaps & needed_caps) != needed_caps)
+    {
+        skip("Video memory surfaces or textures not supported, skipping test.\n");
+        goto done;
+    }
+
+    if (FAILED(IDirectDraw2_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
+    {
+        win_skip("Failed to set 8 bpp display mode, skipping test.\n");
+        goto done;
+    }
+    hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
+    ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
+
+    memset(palette_entries, 0, sizeof(palette_entries));
+    hr = IDirectDraw2_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
+            palette_entries, &palette, NULL);
+    ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
+    hr = IDirectDraw2_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
+            palette_entries, &palette2, NULL);
+    ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
+    memset(&surface_desc, 0, sizeof(surface_desc));
+    surface_desc.dwSize = sizeof(surface_desc);
+    surface_desc.dwFlags = DDSD_CAPS;
+    surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_VIDEOMEMORY;
+    hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &primary, NULL);
+    ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
+    hr = IDirectDrawSurface_SetPalette(primary, palette);
+    ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
+
+    hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
+    ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
+
+    hr = IDirectDrawSurface_IsLost(primary);
+    ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
+    hr = IDirectDrawSurface_GetPalette(primary, &palette3);
+    ok(hr == DDERR_SURFACELOST || broken(SUCCEEDED(hr)) /* Win8 */, "Got unexpected hr %#x.\n", hr);
+    if (SUCCEEDED(hr))
+        IDirectDrawPalette_Release(palette3);
+    hr = IDirectDrawSurface_GetPalette(primary, NULL);
+    ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
+    hr = IDirectDrawSurface_SetPalette(primary, palette2);
+    ok(hr == DDERR_SURFACELOST || broken(SUCCEEDED(hr)) /* Win8 */, "Got unexpected hr %#x.\n", hr);
+
+    hr = IDirectDrawSurface_Restore(primary);
+    ok(SUCCEEDED(hr), "Failed to restore surface, hr %#x.\n", hr);
+    hr = IDirectDrawSurface_IsLost(primary);
+    ok(SUCCEEDED(hr), "Failed to restore surface, hr %#x.\n", hr);
+    hr = IDirectDrawSurface_GetPalette(primary, &palette3);
+    ok(SUCCEEDED(hr), "Failed to get palette, hr %#x.\n", hr);
+    ok(palette3 == palette || broken(palette3 == palette2), "Got unexpected palette %p.\n", palette3);
+    IDirectDrawPalette_Release(palette3);
+
+    /* Even though the palette is assigned to the surface it is not used when
+     * writing data to the surface. Instead, Windows seems to use the system
+     * palette to transform P8 data into RGB colors. Other things are drawn
+     * onto the screen as well, like highlights from the start menu. Do not
+     * test the actual color values until we find an application that depends
+     * on this behavior. Tested on Windows XP and Windows 7. */
+
+    /* The Windows 8 testbot keeps extra references to the primary and
+     * backbuffer while in 8 bpp mode. */
+    hr = IDirectDraw2_RestoreDisplayMode(ddraw);
+    ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
+    refcount = IDirectDrawSurface_Release(primary);
+    ok(!refcount, "Got unexpected refcount %u.\n", refcount);
+
+    /* Test priorities of error values. */
+    hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
+    ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
+    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, &primary, NULL);
+    ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
+    memset(&surface_desc, 0, sizeof(surface_desc));
+    surface_desc.dwSize = sizeof(surface_desc);
+    surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
+    surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
+    surface_desc.dwWidth = 4;
+    surface_desc.dwHeight = 4;
+    surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat);
+    surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
+    U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
+    U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
+    U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
+    U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
+    hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &texture, NULL);
+    ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
+
+    hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
+    ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
+    hr = IDirectDrawSurface_IsLost(primary);
+    ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
+    hr = IDirectDrawSurface_SetPalette(primary, palette);
+    ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr); /* For some reason this works even on Win8. */
+
+    hr = IDirectDrawSurface_IsLost(texture);
+    ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
+    hr = IDirectDrawSurface_SetPalette(texture, palette);
+    ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
+
+    refcount = IDirectDrawSurface_Release(texture);
+    ok(!refcount, "Got unexpected refcount %u.\n", refcount);
+    refcount = IDirectDrawSurface_Release(primary);
+    ok(!refcount, "Got unexpected refcount %u.\n", refcount);
+    refcount = IDirectDrawPalette_Release(palette);
+    ok(!refcount, "Got unexpected refcount %u.\n", refcount);
+    refcount = IDirectDrawPalette_Release(palette2);
+    ok(!refcount, "Got unexpected refcount %u.\n", refcount);
+
+done:
+    refcount = IDirectDraw2_Release(ddraw);
+    ok(!refcount, "Got unexpected refcount %u.\n", refcount);
+    DestroyWindow(window);
+}
+
 START_TEST(ddraw2)
 {
     IDirectDraw2 *ddraw;
@@ -6708,4 +6848,5 @@ START_TEST(ddraw2)
     test_palette_gdi();
     test_palette_alpha();
     test_lost_device();
+    test_palette_lost();
 }
diff --git a/dlls/ddraw/tests/ddraw4.c b/dlls/ddraw/tests/ddraw4.c
index b96330c..79a9a40 100644
--- a/dlls/ddraw/tests/ddraw4.c
+++ b/dlls/ddraw/tests/ddraw4.c
@@ -7726,6 +7726,146 @@ static void test_lost_device(void)
     DestroyWindow(window);
 }
 
+static void test_palette_lost(void)
+{
+    IDirectDrawSurface4 *primary, *texture;
+    DDSURFACEDESC2 surface_desc;
+    IDirectDraw4 *ddraw;
+    IDirectDrawPalette *palette, *palette2, *palette3;
+    ULONG refcount;
+    HWND window;
+    HRESULT hr;
+    PALETTEENTRY palette_entries[256];
+    DWORD needed_caps = DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE;
+    DDCAPS hal_caps;
+
+    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");
+
+    memset(&hal_caps, 0, sizeof(hal_caps));
+    hal_caps.dwSize = sizeof(hal_caps);
+    hr = IDirectDraw4_GetCaps(ddraw, &hal_caps, NULL);
+    ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
+    if ((hal_caps.ddsCaps.dwCaps & needed_caps) != needed_caps)
+    {
+        skip("Video memory surfaces or textures not supported, skipping test.\n");
+        goto done;
+    }
+
+    if (FAILED(IDirectDraw4_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
+    {
+        win_skip("Failed to set 8 bpp display mode, skipping test.\n");
+        goto done;
+    }
+    hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
+    ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
+
+    memset(palette_entries, 0, sizeof(palette_entries));
+    hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
+            palette_entries, &palette, NULL);
+    ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
+    hr = IDirectDraw4_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
+            palette_entries, &palette2, NULL);
+    ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
+    memset(&surface_desc, 0, sizeof(surface_desc));
+    surface_desc.dwSize = sizeof(surface_desc);
+    surface_desc.dwFlags = DDSD_CAPS;
+    surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_VIDEOMEMORY;
+    hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &primary, NULL);
+    ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
+    hr = IDirectDrawSurface4_SetPalette(primary, palette);
+    ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
+
+    hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
+    ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
+
+    hr = IDirectDrawSurface4_IsLost(primary);
+    ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
+    hr = IDirectDrawSurface4_GetPalette(primary, &palette3);
+    ok(hr == DDERR_SURFACELOST || broken(SUCCEEDED(hr)) /* Win8 */, "Got unexpected hr %#x.\n", hr);
+    if (SUCCEEDED(hr))
+        IDirectDrawPalette_Release(palette3);
+    hr = IDirectDrawSurface4_GetPalette(primary, NULL);
+    ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
+    hr = IDirectDrawSurface4_SetPalette(primary, palette2);
+    ok(hr == DDERR_SURFACELOST || broken(SUCCEEDED(hr)) /* Win8 */, "Got unexpected hr %#x.\n", hr);
+
+    hr = IDirectDrawSurface4_Restore(primary);
+    ok(SUCCEEDED(hr), "Failed to restore surface, hr %#x.\n", hr);
+    hr = IDirectDrawSurface4_IsLost(primary);
+    ok(SUCCEEDED(hr), "Failed to restore surface, hr %#x.\n", hr);
+    hr = IDirectDrawSurface4_GetPalette(primary, &palette3);
+    ok(SUCCEEDED(hr), "Failed to get palette, hr %#x.\n", hr);
+    ok(palette3 == palette || broken(palette3 == palette2), "Got unexpected palette %p.\n", palette3);
+    IDirectDrawPalette_Release(palette3);
+
+    /* Even though the palette is assigned to the surface it is not used when
+     * writing data to the surface. Instead, Windows seems to use the system
+     * palette to transform P8 data into RGB colors. Other things are drawn
+     * onto the screen as well, like highlights from the start menu. Do not
+     * test the actual color values until we find an application that depends
+     * on this behavior. Tested on Windows XP and Windows 7. */
+
+    /* The Windows 8 testbot keeps extra references to the primary and
+     * backbuffer while in 8 bpp mode. */
+    hr = IDirectDraw4_RestoreDisplayMode(ddraw);
+    ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
+    refcount = IDirectDrawSurface4_Release(primary);
+    ok(!refcount, "Got unexpected refcount %u.\n", refcount);
+
+    /* Test priorities of error values. */
+    hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
+    ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
+    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, &primary, NULL);
+    ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
+    memset(&surface_desc, 0, sizeof(surface_desc));
+    surface_desc.dwSize = sizeof(surface_desc);
+    surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
+    surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
+    surface_desc.dwWidth = 4;
+    surface_desc.dwHeight = 4;
+    U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
+    U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
+    U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
+    U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
+    U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
+    U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
+    hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &texture, NULL);
+    ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
+
+    hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
+    ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
+    hr = IDirectDrawSurface4_IsLost(primary);
+    ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
+    hr = IDirectDrawSurface4_SetPalette(primary, palette);
+    ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr); /* For some reason this works even on Win8. */
+
+    hr = IDirectDrawSurface4_IsLost(texture);
+    ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
+    hr = IDirectDrawSurface4_SetPalette(texture, palette);
+    ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
+
+    refcount = IDirectDrawSurface4_Release(texture);
+    ok(!refcount, "Got unexpected refcount %u.\n", refcount);
+    refcount = IDirectDrawSurface4_Release(primary);
+    ok(!refcount, "Got unexpected refcount %u.\n", refcount);
+    refcount = IDirectDrawPalette_Release(palette);
+    ok(!refcount, "Got unexpected refcount %u.\n", refcount);
+    refcount = IDirectDrawPalette_Release(palette2);
+    ok(!refcount, "Got unexpected refcount %u.\n", refcount);
+
+done:
+    refcount = IDirectDraw4_Release(ddraw);
+    ok(!refcount, "Got unexpected refcount %u.\n", refcount);
+    DestroyWindow(window);
+}
+
 START_TEST(ddraw4)
 {
     IDirectDraw4 *ddraw;
@@ -7790,4 +7930,5 @@ START_TEST(ddraw4)
     test_palette_alpha();
     test_vb_writeonly();
     test_lost_device();
+    test_palette_lost();
 }
diff --git a/dlls/ddraw/tests/ddraw7.c b/dlls/ddraw/tests/ddraw7.c
index 393cea3..23e7ced 100644
--- a/dlls/ddraw/tests/ddraw7.c
+++ b/dlls/ddraw/tests/ddraw7.c
@@ -7448,6 +7448,155 @@ static void test_lost_device(void)
     DestroyWindow(window);
 }
 
+static void test_palette_lost(void)
+{
+    IDirectDrawSurface7 *primary, *texture, *mipmap;
+    DDSURFACEDESC2 surface_desc;
+    IDirectDraw7 *ddraw;
+    IDirectDrawPalette *palette, *palette2, *palette3;
+    ULONG refcount;
+    HWND window;
+    HRESULT hr;
+    PALETTEENTRY palette_entries[256];
+    DDSCAPS2 caps = {DDSCAPS_COMPLEX, 0, 0, 0};
+    DWORD needed_caps = DDSCAPS_VIDEOMEMORY | DDSCAPS_TEXTURE;
+    DDCAPS hal_caps;
+
+    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");
+
+    memset(&hal_caps, 0, sizeof(hal_caps));
+    hal_caps.dwSize = sizeof(hal_caps);
+    hr = IDirectDraw7_GetCaps(ddraw, &hal_caps, NULL);
+    ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
+    if ((hal_caps.ddsCaps.dwCaps & needed_caps) != needed_caps)
+    {
+        skip("Video memory surfaces or textures not supported, skipping test.\n");
+        goto done;
+    }
+
+    if (FAILED(IDirectDraw7_SetDisplayMode(ddraw, 640, 480, 8, 0, 0)))
+    {
+        win_skip("Failed to set 8 bpp display mode, skipping test.\n");
+        goto done;
+    }
+    hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
+    ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
+
+    memset(palette_entries, 0, sizeof(palette_entries));
+    hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
+            palette_entries, &palette, NULL);
+    ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
+    hr = IDirectDraw7_CreatePalette(ddraw, DDPCAPS_8BIT | DDPCAPS_ALLOW256,
+            palette_entries, &palette2, NULL);
+    ok(SUCCEEDED(hr), "Failed to create palette, hr %#x.\n", hr);
+    memset(&surface_desc, 0, sizeof(surface_desc));
+    surface_desc.dwSize = sizeof(surface_desc);
+    surface_desc.dwFlags = DDSD_CAPS;
+    surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_VIDEOMEMORY;
+    hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &primary, NULL);
+    ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
+    hr = IDirectDrawSurface7_SetPalette(primary, palette);
+    ok(SUCCEEDED(hr), "Failed to set palette, hr %#x.\n", hr);
+
+    hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
+    ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
+
+    hr = IDirectDrawSurface7_IsLost(primary);
+    ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
+    hr = IDirectDrawSurface7_GetPalette(primary, &palette3);
+    ok(hr == DDERR_SURFACELOST || broken(SUCCEEDED(hr)) /* Win8 */, "Got unexpected hr %#x.\n", hr);
+    if (SUCCEEDED(hr))
+        IDirectDrawPalette_Release(palette3);
+    hr = IDirectDrawSurface7_GetPalette(primary, NULL);
+    ok(hr == DDERR_INVALIDPARAMS, "Got unexpected hr %#x.\n", hr);
+    hr = IDirectDrawSurface7_SetPalette(primary, palette2);
+    ok(hr == DDERR_SURFACELOST || broken(SUCCEEDED(hr)) /* Win8 */, "Got unexpected hr %#x.\n", hr);
+
+    hr = IDirectDrawSurface7_Restore(primary);
+    ok(SUCCEEDED(hr), "Failed to restore surface, hr %#x.\n", hr);
+    hr = IDirectDrawSurface7_IsLost(primary);
+    ok(SUCCEEDED(hr), "Failed to restore surface, hr %#x.\n", hr);
+    hr = IDirectDrawSurface7_GetPalette(primary, &palette3);
+    ok(SUCCEEDED(hr), "Failed to get palette, hr %#x.\n", hr);
+    ok(palette3 == palette || broken(palette3 == palette2), "Got unexpected palette %p.\n", palette3);
+    IDirectDrawPalette_Release(palette3);
+
+    /* Even though the palette is assigned to the surface it is not used when
+     * writing data to the surface. Instead, Windows seems to use the system
+     * palette to transform P8 data into RGB colors. Other things are drawn
+     * onto the screen as well, like highlights from the start menu. Do not
+     * test the actual color values until we find an application that depends
+     * on this behavior. Tested on Windows XP and Windows 7. */
+
+    /* The Windows 8 testbot keeps extra references to the primary and
+     * backbuffer while in 8 bpp mode. */
+    hr = IDirectDraw7_RestoreDisplayMode(ddraw);
+    ok(SUCCEEDED(hr), "Failed to restore display mode, hr %#x.\n", hr);
+    refcount = IDirectDrawSurface7_Release(primary);
+    ok(!refcount, "Got unexpected refcount %u.\n", refcount);
+
+    /* Test priorities of error values. */
+    hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
+    ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
+    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, &primary, NULL);
+    ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
+    memset(&surface_desc, 0, sizeof(surface_desc));
+    surface_desc.dwSize = sizeof(surface_desc);
+    surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_MIPMAPCOUNT | DDSD_PIXELFORMAT;
+    surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
+    surface_desc.dwWidth = 4;
+    surface_desc.dwHeight = 4;
+    U2(surface_desc).dwMipMapCount = 2;
+    U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
+    U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
+    U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
+    U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
+    U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
+    U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
+    hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &texture, NULL);
+    ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
+    hr = IDirectDrawSurface7_GetAttachedSurface(texture, &caps, &mipmap);
+    ok(SUCCEEDED(hr), "Failed to get attached surface, hr %#x.\n", hr);
+
+    hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
+    ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
+    hr = IDirectDrawSurface7_IsLost(primary);
+    ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
+    hr = IDirectDrawSurface7_SetPalette(primary, palette);
+    ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr); /* For some reason this works even on Win8. */
+
+    hr = IDirectDrawSurface7_IsLost(texture);
+    ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
+    hr = IDirectDrawSurface7_IsLost(mipmap);
+    ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
+    hr = IDirectDrawSurface7_SetPalette(texture, palette);
+    ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr);
+    hr = IDirectDrawSurface7_SetPalette(mipmap, palette);
+    ok(hr == DDERR_NOTONMIPMAPSUBLEVEL, "Got unexpected hr %#x.\n", hr);
+
+    IDirectDrawSurface7_Release(mipmap);
+    refcount = IDirectDrawSurface7_Release(texture);
+    ok(!refcount, "Got unexpected refcount %u.\n", refcount);
+    refcount = IDirectDrawSurface7_Release(primary);
+    ok(!refcount, "Got unexpected refcount %u.\n", refcount);
+    refcount = IDirectDrawPalette_Release(palette);
+    ok(!refcount, "Got unexpected refcount %u.\n", refcount);
+    refcount = IDirectDrawPalette_Release(palette2);
+    ok(!refcount, "Got unexpected refcount %u.\n", refcount);
+
+done:
+    refcount = IDirectDraw7_Release(ddraw);
+    ok(!refcount, "Got unexpected refcount %u.\n", refcount);
+    DestroyWindow(window);
+}
+
 START_TEST(ddraw7)
 {
     HMODULE module = GetModuleHandleA("ddraw.dll");
@@ -7519,4 +7668,5 @@ START_TEST(ddraw7)
     test_palette_alpha();
     test_vb_writeonly();
     test_lost_device();
+    test_palette_lost();
 }
-- 
1.8.5.5




More information about the wine-patches mailing list