diff --git a/dlls/ddraw/tests/ddraw1.c b/dlls/ddraw/tests/ddraw1.c index 67e7c3afc9f..0f845295bf0 100644 --- a/dlls/ddraw/tests/ddraw1.c +++ b/dlls/ddraw/tests/ddraw1.c @@ -3410,6 +3410,101 @@ done: DestroyWindow(window); } +static void test_surface_discard(void) +{ + IDirectDraw *ddraw; + HRESULT hr; + HWND window; + DDSURFACEDESC ddsd; + IDirectDrawSurface *surface, *primary; + void *addr; + static const struct + { + DWORD caps; + BOOL discard; + } + tests[] = + { + {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, TRUE}, + {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, FALSE}, + {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, TRUE}, + {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, FALSE}, + }; + unsigned int i; + + window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW, + 0, 0, 640, 480, 0, 0, 0, 0); + if (!(ddraw = create_ddraw())) + { + skip("Failed to create ddraw object, skipping test.\n"); + DestroyWindow(window); + return; + } + hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL); + ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr); + + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; + hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &primary, NULL); + + for (i = 0; i < sizeof(tests) / sizeof(*tests); i++) + { + BOOL discarded; + + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.ddsCaps.dwCaps = tests[i].caps; + ddsd.dwWidth = 64; + ddsd.dwHeight = 64; + hr = IDirectDraw_CreateSurface(ddraw, &ddsd, &surface, NULL); + if (FAILED(hr)) + { + skip("Failed to create surface, skipping.\n"); + continue; + } + + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + addr = ddsd.lpSurface; + hr = IDirectDrawSurface_Unlock(surface, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS | DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + discarded = ddsd.lpSurface != addr; + hr = IDirectDrawSurface_Unlock(surface, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + hr = IDirectDrawSurface_Blt(primary, NULL, surface, NULL, DDBLT_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr); + + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS | DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + discarded |= ddsd.lpSurface != addr; + hr = IDirectDrawSurface_Unlock(surface, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + IDirectDrawSurface_Release(surface); + + /* Windows 7 reliably changes the address of surfaces that are discardable (Nvidia Kepler, + * AMD r500, evergreen). Windows XP, at least on AMD r200, never changes the pointer. */ + ok(!discarded || tests[i].discard, "Expected surface not to be discarded, case %u\n", i); + } + + IDirectDrawSurface_Release(primary); + IDirectDraw_Release(ddraw); + DestroyWindow(window); +} + START_TEST(ddraw1) { test_coop_level_create_device_window(); @@ -3436,4 +3531,5 @@ START_TEST(ddraw1) test_unsupported_formats(); test_rt_caps(); test_surface_lock(); + test_surface_discard(); } diff --git a/dlls/ddraw/tests/ddraw2.c b/dlls/ddraw/tests/ddraw2.c index c1df167244a..f4702f1a8d0 100644 --- a/dlls/ddraw/tests/ddraw2.c +++ b/dlls/ddraw/tests/ddraw2.c @@ -4069,6 +4069,101 @@ done: DestroyWindow(window); } +static void test_surface_discard(void) +{ + IDirectDraw2 *ddraw; + HRESULT hr; + HWND window; + DDSURFACEDESC ddsd; + IDirectDrawSurface *surface, *primary; + void *addr; + static const struct + { + DWORD caps; + BOOL discard; + } + tests[] = + { + {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, TRUE}, + {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, FALSE}, + {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, TRUE}, + {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, FALSE}, + }; + unsigned int i; + + window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW, + 0, 0, 640, 480, 0, 0, 0, 0); + if (!(ddraw = create_ddraw())) + { + skip("Failed to create ddraw object, skipping test.\n"); + DestroyWindow(window); + return; + } + hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL); + ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr); + + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; + hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &primary, NULL); + + for (i = 0; i < sizeof(tests) / sizeof(*tests); i++) + { + BOOL discarded; + + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.ddsCaps.dwCaps = tests[i].caps; + ddsd.dwWidth = 64; + ddsd.dwHeight = 64; + hr = IDirectDraw2_CreateSurface(ddraw, &ddsd, &surface, NULL); + if (FAILED(hr)) + { + skip("Failed to create surface, skipping.\n"); + continue; + } + + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + addr = ddsd.lpSurface; + hr = IDirectDrawSurface_Unlock(surface, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS | DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr) , "Failed to lock surface, hr %#x.\n", hr); + discarded = ddsd.lpSurface != addr; + hr = IDirectDrawSurface_Unlock(surface, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + hr = IDirectDrawSurface_Blt(primary, NULL, surface, NULL, DDBLT_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr); + + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + hr = IDirectDrawSurface_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS | DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + discarded |= ddsd.lpSurface != addr; + hr = IDirectDrawSurface_Unlock(surface, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + IDirectDrawSurface_Release(surface); + + /* Windows 7 reliably changes the address of surfaces that are discardable (Nvidia Kepler, + * AMD r500, evergreen). Windows XP, at least on AMD r200, never changes the pointer. */ + ok(!discarded || tests[i].discard, "Expected surface not to be discarded, case %u\n", i); + } + + IDirectDrawSurface_Release(primary); + IDirectDraw2_Release(ddraw); + DestroyWindow(window); +} + START_TEST(ddraw2) { test_coop_level_create_device_window(); @@ -4099,4 +4194,5 @@ START_TEST(ddraw2) test_unsupported_formats(); test_rt_caps(); test_surface_lock(); + test_surface_discard(); } diff --git a/dlls/ddraw/tests/ddraw4.c b/dlls/ddraw/tests/ddraw4.c index 457eea0f4ff..61a54bb407c 100644 --- a/dlls/ddraw/tests/ddraw4.c +++ b/dlls/ddraw/tests/ddraw4.c @@ -4694,6 +4694,105 @@ done: DestroyWindow(window); } +static void test_surface_discard(void) +{ + IDirect3DDevice3 *device; + IDirect3D3 *d3d; + IDirectDraw4 *ddraw; + HRESULT hr; + HWND window; + DDSURFACEDESC2 ddsd; + IDirectDrawSurface4 *surface, *target; + void *addr; + static const struct + { + DWORD caps, caps2; + BOOL discard; + } + tests[] = + { + {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0, TRUE}, + {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0, FALSE}, + {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0, TRUE}, + {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0, FALSE}, + {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, FALSE}, + {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_HINTDYNAMIC, FALSE}, + {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, FALSE}, + {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE | DDSCAPS2_HINTDYNAMIC, FALSE}, + }; + unsigned int i; + + window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW, + 0, 0, 640, 480, 0, 0, 0, 0); + + if (!(device = create_device(window, DDSCL_NORMAL))) + { + skip("Failed to create a ddraw object, skipping test.\n"); + DestroyWindow(window); + return; + } + hr = IDirect3DDevice3_GetDirect3D(device, &d3d); + ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr); + hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw); + ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr); + hr = IDirect3DDevice3_GetRenderTarget(device, &target); + ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr); + + for (i = 0; i < sizeof(tests) / sizeof(*tests); i++) + { + BOOL discarded; + + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.ddsCaps.dwCaps = tests[i].caps; + ddsd.ddsCaps.dwCaps2 = tests[i].caps2; + ddsd.dwWidth = 64; + ddsd.dwHeight = 64; + hr = IDirectDraw4_CreateSurface(ddraw, &ddsd, &surface, NULL); + ok(SUCCEEDED(hr), "Failed to create offscreen surface, hr %#x, case %u.\n", hr, i); + + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + hr = IDirectDrawSurface4_Lock(surface, NULL, &ddsd, 0, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + addr = ddsd.lpSurface; + hr = IDirectDrawSurface4_Unlock(surface, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + hr = IDirectDrawSurface4_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + discarded = ddsd.lpSurface != addr; + hr = IDirectDrawSurface4_Unlock(surface, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + hr = IDirectDrawSurface4_Blt(target, NULL, surface, NULL, DDBLT_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr); + + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + hr = IDirectDrawSurface4_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + discarded |= ddsd.lpSurface != addr; + hr = IDirectDrawSurface4_Unlock(surface, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + IDirectDrawSurface4_Release(surface); + + /* Windows 7 reliably changes the address of surfaces that are discardable (Nvidia Kepler, + * AMD r500, evergreen). Windows XP, at least on AMD r200, does not. */ + ok(!discarded || tests[i].discard, "Expected surface not to be discarded, case %u\n", i); + } + + IDirectDrawSurface4_Release(target); + IDirectDraw4_Release(ddraw); + IDirect3D3_Release(d3d); + IDirect3DDevice3_Release(device); + DestroyWindow(window); +} + START_TEST(ddraw4) { test_process_vertices(); @@ -4729,4 +4828,5 @@ START_TEST(ddraw4) test_unsupported_formats(); test_rt_caps(); test_surface_lock(); + test_surface_discard(); } diff --git a/dlls/ddraw/tests/ddraw7.c b/dlls/ddraw/tests/ddraw7.c index 6cf6b7fbd57..44a68c45c0d 100644 --- a/dlls/ddraw/tests/ddraw7.c +++ b/dlls/ddraw/tests/ddraw7.c @@ -4580,6 +4580,105 @@ done: DestroyWindow(window); } +static void test_surface_discard(void) +{ + IDirect3DDevice7 *device; + IDirect3D7 *d3d; + IDirectDraw7 *ddraw; + HRESULT hr; + HWND window; + DDSURFACEDESC2 ddsd; + IDirectDrawSurface7 *surface, *target; + void *addr; + static const struct + { + DWORD caps, caps2; + BOOL discard; + } + tests[] = + { + {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY, 0, TRUE}, + {DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY, 0, FALSE}, + {DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY, 0, TRUE}, + {DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY, 0, FALSE}, + {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE, FALSE}, + {DDSCAPS_TEXTURE, DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_HINTDYNAMIC, FALSE}, + {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE, FALSE}, + {DDSCAPS_TEXTURE, DDSCAPS2_D3DTEXTUREMANAGE | DDSCAPS2_HINTDYNAMIC, FALSE}, + }; + unsigned int i; + + window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW, + 0, 0, 640, 480, 0, 0, 0, 0); + + if (!(device = create_device(window, DDSCL_NORMAL))) + { + skip("Failed to create a ddraw object, skipping test.\n"); + DestroyWindow(window); + return; + } + hr = IDirect3DDevice7_GetDirect3D(device, &d3d); + ok(SUCCEEDED(hr), "Failed to get d3d interface, hr %#x.\n", hr); + hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw); + ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr); + hr = IDirect3DDevice7_GetRenderTarget(device, &target); + ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr); + + for (i = 0; i < sizeof(tests) / sizeof(*tests); i++) + { + BOOL discarded; + + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.ddsCaps.dwCaps = tests[i].caps; + ddsd.ddsCaps.dwCaps2 = tests[i].caps2; + ddsd.dwWidth = 64; + ddsd.dwHeight = 64; + hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL); + ok(SUCCEEDED(hr), "Failed to create offscreen surface, hr %#x, case %u.\n", hr, i); + + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd, 0, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + addr = ddsd.lpSurface; + hr = IDirectDrawSurface7_Unlock(surface, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + discarded = ddsd.lpSurface != addr; + hr = IDirectDrawSurface7_Unlock(surface, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + hr = IDirectDrawSurface7_Blt(target, NULL, surface, NULL, DDBLT_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr); + + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd, DDLOCK_DISCARDCONTENTS, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + discarded |= ddsd.lpSurface != addr; + hr = IDirectDrawSurface7_Unlock(surface, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + IDirectDrawSurface7_Release(surface); + + /* Windows 7 reliably changes the address of surfaces that are discardable (Nvidia Kepler, + * AMD r500, evergreen). Windows XP, at least on AMD r200, does not. */ + ok(!discarded || tests[i].discard, "Expected surface not to be discarded, case %u\n", i); + } + + IDirectDrawSurface7_Release(target); + IDirectDraw7_Release(ddraw); + IDirect3D7_Release(d3d); + IDirect3DDevice7_Release(device); + DestroyWindow(window); +} + START_TEST(ddraw7) { HMODULE module = GetModuleHandleA("ddraw.dll"); @@ -4623,4 +4722,5 @@ START_TEST(ddraw7) test_unsupported_formats(); test_rt_caps(); test_surface_lock(); + test_surface_discard(); }