From: Paul Gofman <pgofman@codeweavers.com> --- dlls/ddraw/tests/ddraw1.c | 184 ++++++++++++++++++++++++++++++++++++++ dlls/ddraw/tests/ddraw2.c | 184 ++++++++++++++++++++++++++++++++++++++ dlls/ddraw/tests/ddraw4.c | 184 ++++++++++++++++++++++++++++++++++++++ dlls/ddraw/tests/ddraw7.c | 184 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 736 insertions(+) diff --git a/dlls/ddraw/tests/ddraw1.c b/dlls/ddraw/tests/ddraw1.c index 2e2f7e62483..594baee6ff9 100644 --- a/dlls/ddraw/tests/ddraw1.c +++ b/dlls/ddraw/tests/ddraw1.c @@ -114,6 +114,14 @@ static void flush_events(void) } } +static void pump_messages(void) +{ + MSG msg; + + while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) + DispatchMessageA(&msg); +} + static HWND create_foreground_window(void) { for (UINT retries = 5; retries; retries--) @@ -16382,6 +16390,181 @@ out: DestroyWindow(window); } +static void check_surface_clipper(IDirectDrawSurface *surface, IDirectDrawClipper *clipper_hwnd, + IDirectDrawClipper *clipper_region, RECT *window_rect, DWORD style) +{ + unsigned int c; + DDBLTFX fx; + HRESULT hr; + + memset(&fx, 0, sizeof(fx)); + fx.dwSize = sizeof(fx); + fx.dwFillColor = 0xff00ff00; + + fill_surface(surface, 0xffff0000); + + /* Clipper with region works. */ + hr = IDirectDrawSurface_SetClipper(surface, clipper_region); + ok(hr == DD_OK, "got %#lx.\n", hr); + c = get_surface_color(surface, 101, 101); + ok(c == 0x00ff0000, "got %#x.\n", c); + hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx); + ok(hr == DD_OK, "got %#lx.\n", hr); + c = get_surface_color(surface, 0, 0); + ok(c == 0x00ff0000, "got %#x.\n", c); + c = get_surface_color(surface, 101, 101); + ok(c == 0x0000ff00, "got %#x.\n", c); + + /* Clipper with window has no effect. */ + hr = IDirectDrawSurface_SetClipper(surface, clipper_hwnd); + ok(hr == DD_OK, "got %#lx.\n", hr); + fill_surface(surface, 0xff0000ff); + c = get_surface_color(surface, window_rect->left + 1, window_rect->top + 1); + ok(c == 0x000000ff, "got %#x.\n", c); + + hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx); + ok(hr == DD_OK, "got %#lx.\n", hr); + + c = get_surface_color(surface, window_rect->left + 1, window_rect->top + 1); + todo_wine_if(!(style & WS_VISIBLE)) ok(c == 0x0000ff00, "got %#x.\n", c); + c = get_surface_color(surface, 0, 0); + todo_wine_if((style & (WS_CHILD | WS_VISIBLE)) != (WS_CHILD | WS_VISIBLE)) ok(c == 0x0000ff00, "got %#x.\n", c); + + hr = IDirectDrawSurface_SetClipper(surface, NULL); + ok(hr == DD_OK, "got %#lx.\n", hr); + fill_surface(surface, 0); +} + +static void test_clipper_in_exclusive_fullscreen(void) +{ + static const struct + { + DWORD style; + BOOL parent; + } + tests[] = + { + { WS_POPUP }, + { WS_POPUP, TRUE }, + { WS_CHILD, TRUE }, + { WS_OVERLAPPED }, + { WS_CHILD | WS_VISIBLE, TRUE }, + { WS_POPUP | WS_VISIBLE }, + }; + IDirectDrawSurface *primary, *offscreen; + IDirectDrawClipper *clipper, *clipper2; + DDSURFACEDESC surface_desc; + HWND window, clip_window; + IDirectDraw *ddraw; + RGNDATA *rgn_data; + DWORD ret, style; + RECT window_rect; + ULONG refcount; + unsigned int i; + HRESULT hr; + HRGN rgn; + + if (!(ddraw = create_ddraw())) + { + skip("Failed to create ddraw, skipping test.\n"); + return; + } + hr = IDirectDraw_CreateClipper(ddraw, 0, &clipper, NULL); + ok(hr == DD_OK, "got %#lx.\n", hr); + + hr = IDirectDraw_CreateClipper(ddraw, 0, &clipper2, NULL); + ok(hr == DD_OK, "got %#lx.\n", hr); + + window = CreateWindowA("static", "ddraw_fullscreen", WS_POPUP | WS_VISIBLE, 0, 0, 640, 480, NULL, NULL, NULL, NULL); + pump_messages(); + hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN); + ok(hr == DD_OK, "got %#lx.\n", hr); + pump_messages(); + + rgn = CreateRectRgn(100, 100, 200, 200); + ok(!!rgn, "Failed to create region.\n"); + ret = GetRegionData(rgn, 0, NULL); + rgn_data = malloc(ret); + ret = GetRegionData(rgn, ret, rgn_data); + ok(!!ret, "Failed to get region data.\n"); + DeleteObject(rgn); + hr = IDirectDrawClipper_SetClipList(clipper2, rgn_data, 0); + ok(hr == DD_OK, "got %#lx.\n", hr); + free(rgn_data); + + 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(hr == DD_OK, "got %#lx.\n", hr); + + surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + surface_desc.dwWidth = 640; + surface_desc.dwHeight = 480; + hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &offscreen, NULL); + ok(hr == DD_OK, "got %#lx.\n", hr); + + for (i = 0; i < ARRAY_SIZE(tests); ++i) + { + winetest_push_context("test %u", i); + style = tests[i].style; + clip_window = CreateWindowA("static", "ddraw_clip", style, 100, 100, 100, 100, + tests[i].parent ? window : NULL, NULL, NULL, NULL); + ok(!!clip_window, "got error %ld.\n", GetLastError()); + pump_messages(); + + GetWindowRect(clip_window, &window_rect); + hr = IDirectDrawClipper_SetHWnd(clipper, 0, clip_window); + ok(hr == DD_OK, "got %#lx.\n", hr); + + hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret); + ok(hr == DD_OK, "got %#lx.\n", hr); + rgn_data = malloc(ret); + hr = IDirectDrawClipper_GetClipList(clipper, NULL, rgn_data, &ret); + ok(hr == DD_OK, "got %#lx.\n", hr); + ok(rgn_data->rdh.dwSize == sizeof(rgn_data->rdh), "Got unexpected structure size %#lx.\n", rgn_data->rdh.dwSize); + ok(rgn_data->rdh.iType == RDH_RECTANGLES, "Got unexpected type %#lx.\n", rgn_data->rdh.iType); + if (style & WS_VISIBLE) + { + ok(rgn_data->rdh.nCount >= 1, "got %lu.\n", rgn_data->rdh.nCount); + if (!(style & WS_CHILD)) + ok(EqualRect(&rgn_data->rdh.rcBound, &window_rect), "got %s, expected %s.\n", + wine_dbgstr_rect(&rgn_data->rdh.rcBound), wine_dbgstr_rect(&window_rect)); + } + else + { + ok(!rgn_data->rdh.nCount, "got %lu.\n", rgn_data->rdh.nCount); + } + free(rgn_data); + + winetest_push_context("primary"); + check_surface_clipper(primary, clipper, clipper2, &window_rect, style); + winetest_pop_context(); + + winetest_push_context("offscreen"); + check_surface_clipper(offscreen, clipper, clipper2, &window_rect, style); + winetest_pop_context(); + + hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL); + ok(hr == DD_OK, "got %#lx.\n", hr); + DestroyWindow(clip_window); + pump_messages(); + winetest_pop_context(); + } + + IDirectDrawClipper_Release(clipper); + refcount = IDirectDrawSurface_Release(offscreen); + ok(!refcount, "Got unexpected refcount %lu.\n", refcount); + refcount = IDirectDrawSurface_Release(primary); + ok(!refcount, "Got unexpected refcount %lu.\n", refcount); + + IDirectDraw_Release(ddraw); + DestroyWindow(window); + pump_messages(); +} + START_TEST(ddraw1) { DDDEVICEIDENTIFIER identifier; @@ -16508,4 +16691,5 @@ START_TEST(ddraw1) test_sysmem_x_channel(); test_yuv_blit(); test_blit_to_self(); + test_clipper_in_exclusive_fullscreen(); } diff --git a/dlls/ddraw/tests/ddraw2.c b/dlls/ddraw/tests/ddraw2.c index ca030897abd..ebbc20aacac 100644 --- a/dlls/ddraw/tests/ddraw2.c +++ b/dlls/ddraw/tests/ddraw2.c @@ -115,6 +115,14 @@ static void flush_events(void) } } +static void pump_messages(void) +{ + MSG msg; + + while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) + DispatchMessageA(&msg); +} + static HWND create_foreground_window(void) { for (UINT retries = 5; retries; retries--) @@ -17453,6 +17461,181 @@ out: DestroyWindow(window); } +static void check_surface_clipper(IDirectDrawSurface *surface, IDirectDrawClipper *clipper_hwnd, + IDirectDrawClipper *clipper_region, RECT *window_rect, DWORD style) +{ + unsigned int c; + DDBLTFX fx; + HRESULT hr; + + memset(&fx, 0, sizeof(fx)); + fx.dwSize = sizeof(fx); + fx.dwFillColor = 0xff00ff00; + + fill_surface(surface, 0xffff0000); + + /* Clipper with region works. */ + hr = IDirectDrawSurface_SetClipper(surface, clipper_region); + ok(hr == DD_OK, "got %#lx.\n", hr); + c = get_surface_color(surface, 101, 101); + ok(c == 0x00ff0000, "got %#x.\n", c); + hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx); + ok(hr == DD_OK, "got %#lx.\n", hr); + c = get_surface_color(surface, 0, 0); + ok(c == 0x00ff0000, "got %#x.\n", c); + c = get_surface_color(surface, 101, 101); + ok(c == 0x0000ff00, "got %#x.\n", c); + + /* Clipper with window has no effect. */ + hr = IDirectDrawSurface_SetClipper(surface, clipper_hwnd); + ok(hr == DD_OK, "got %#lx.\n", hr); + fill_surface(surface, 0xff0000ff); + c = get_surface_color(surface, window_rect->left + 1, window_rect->top + 1); + ok(c == 0x000000ff, "got %#x.\n", c); + + hr = IDirectDrawSurface_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx); + ok(hr == DD_OK, "got %#lx.\n", hr); + + c = get_surface_color(surface, window_rect->left + 1, window_rect->top + 1); + todo_wine_if(!(style & WS_VISIBLE)) ok(c == 0x0000ff00, "got %#x.\n", c); + c = get_surface_color(surface, 0, 0); + todo_wine_if((style & (WS_CHILD | WS_VISIBLE)) != (WS_CHILD | WS_VISIBLE)) ok(c == 0x0000ff00, "got %#x.\n", c); + + hr = IDirectDrawSurface_SetClipper(surface, NULL); + ok(hr == DD_OK, "got %#lx.\n", hr); + fill_surface(surface, 0); +} + +static void test_clipper_in_exclusive_fullscreen(void) +{ + static const struct + { + DWORD style; + BOOL parent; + } + tests[] = + { + { WS_POPUP }, + { WS_POPUP, TRUE }, + { WS_CHILD, TRUE }, + { WS_OVERLAPPED }, + { WS_CHILD | WS_VISIBLE, TRUE }, + { WS_POPUP | WS_VISIBLE }, + }; + IDirectDrawSurface *primary, *offscreen; + IDirectDrawClipper *clipper, *clipper2; + DDSURFACEDESC surface_desc; + HWND window, clip_window; + IDirectDraw2 *ddraw; + RGNDATA *rgn_data; + DWORD ret, style; + RECT window_rect; + ULONG refcount; + unsigned int i; + HRESULT hr; + HRGN rgn; + + if (!(ddraw = create_ddraw())) + { + skip("Failed to create ddraw, skipping test.\n"); + return; + } + hr = IDirectDraw2_CreateClipper(ddraw, 0, &clipper, NULL); + ok(hr == DD_OK, "got %#lx.\n", hr); + + hr = IDirectDraw2_CreateClipper(ddraw, 0, &clipper2, NULL); + ok(hr == DD_OK, "got %#lx.\n", hr); + + window = CreateWindowA("static", "ddraw_fullscreen", WS_POPUP | WS_VISIBLE, 0, 0, 640, 480, NULL, NULL, NULL, NULL); + pump_messages(); + hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN); + ok(hr == DD_OK, "got %#lx.\n", hr); + pump_messages(); + + rgn = CreateRectRgn(100, 100, 200, 200); + ok(!!rgn, "Failed to create region.\n"); + ret = GetRegionData(rgn, 0, NULL); + rgn_data = malloc(ret); + ret = GetRegionData(rgn, ret, rgn_data); + ok(!!ret, "Failed to get region data.\n"); + DeleteObject(rgn); + hr = IDirectDrawClipper_SetClipList(clipper2, rgn_data, 0); + ok(hr == DD_OK, "got %#lx.\n", hr); + free(rgn_data); + + 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(hr == DD_OK, "got %#lx.\n", hr); + + surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + surface_desc.dwWidth = 640; + surface_desc.dwHeight = 480; + hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &offscreen, NULL); + ok(hr == DD_OK, "got %#lx.\n", hr); + + for (i = 0; i < ARRAY_SIZE(tests); ++i) + { + winetest_push_context("test %u", i); + style = tests[i].style; + clip_window = CreateWindowA("static", "ddraw_clip", style, 100, 100, 100, 100, + tests[i].parent ? window : NULL, NULL, NULL, NULL); + ok(!!clip_window, "got error %ld.\n", GetLastError()); + pump_messages(); + + GetWindowRect(clip_window, &window_rect); + hr = IDirectDrawClipper_SetHWnd(clipper, 0, clip_window); + ok(hr == DD_OK, "got %#lx.\n", hr); + + hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret); + ok(hr == DD_OK, "got %#lx.\n", hr); + rgn_data = malloc(ret); + hr = IDirectDrawClipper_GetClipList(clipper, NULL, rgn_data, &ret); + ok(hr == DD_OK, "got %#lx.\n", hr); + ok(rgn_data->rdh.dwSize == sizeof(rgn_data->rdh), "Got unexpected structure size %#lx.\n", rgn_data->rdh.dwSize); + ok(rgn_data->rdh.iType == RDH_RECTANGLES, "Got unexpected type %#lx.\n", rgn_data->rdh.iType); + if (style & WS_VISIBLE) + { + ok(rgn_data->rdh.nCount >= 1, "got %lu.\n", rgn_data->rdh.nCount); + if (!(style & WS_CHILD)) + ok(EqualRect(&rgn_data->rdh.rcBound, &window_rect), "got %s, expected %s.\n", + wine_dbgstr_rect(&rgn_data->rdh.rcBound), wine_dbgstr_rect(&window_rect)); + } + else + { + ok(!rgn_data->rdh.nCount, "got %lu.\n", rgn_data->rdh.nCount); + } + free(rgn_data); + + winetest_push_context("primary"); + check_surface_clipper(primary, clipper, clipper2, &window_rect, style); + winetest_pop_context(); + + winetest_push_context("offscreen"); + check_surface_clipper(offscreen, clipper, clipper2, &window_rect, style); + winetest_pop_context(); + + hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL); + ok(hr == DD_OK, "got %#lx.\n", hr); + DestroyWindow(clip_window); + pump_messages(); + winetest_pop_context(); + } + + IDirectDrawClipper_Release(clipper); + refcount = IDirectDrawSurface_Release(offscreen); + ok(!refcount, "Got unexpected refcount %lu.\n", refcount); + refcount = IDirectDrawSurface_Release(primary); + ok(!refcount, "Got unexpected refcount %lu.\n", refcount); + + IDirectDraw2_Release(ddraw); + DestroyWindow(window); + pump_messages(); +} + START_TEST(ddraw2) { DDDEVICEIDENTIFIER identifier; @@ -17585,4 +17768,5 @@ START_TEST(ddraw2) test_sysmem_x_channel(); test_yuv_blit(); test_blit_to_self(); + test_clipper_in_exclusive_fullscreen(); } diff --git a/dlls/ddraw/tests/ddraw4.c b/dlls/ddraw/tests/ddraw4.c index 285b36f54c6..e2fa4738cbc 100644 --- a/dlls/ddraw/tests/ddraw4.c +++ b/dlls/ddraw/tests/ddraw4.c @@ -121,6 +121,14 @@ static void flush_events(void) } } +static void pump_messages(void) +{ + MSG msg; + + while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) + DispatchMessageA(&msg); +} + static HWND create_foreground_window(void) { for (UINT retries = 5; retries; retries--) @@ -20552,6 +20560,181 @@ out: DestroyWindow(window); } +static void check_surface_clipper(IDirectDrawSurface4 *surface, IDirectDrawClipper *clipper_hwnd, + IDirectDrawClipper *clipper_region, RECT *window_rect, DWORD style) +{ + unsigned int c; + DDBLTFX fx; + HRESULT hr; + + memset(&fx, 0, sizeof(fx)); + fx.dwSize = sizeof(fx); + fx.dwFillColor = 0xff00ff00; + + fill_surface(surface, 0xffff0000); + + /* Clipper with region works. */ + hr = IDirectDrawSurface4_SetClipper(surface, clipper_region); + ok(hr == DD_OK, "got %#lx.\n", hr); + c = get_surface_color(surface, 101, 101); + ok(c == 0x00ff0000, "got %#x.\n", c); + hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx); + ok(hr == DD_OK, "got %#lx.\n", hr); + c = get_surface_color(surface, 0, 0); + ok(c == 0x00ff0000, "got %#x.\n", c); + c = get_surface_color(surface, 101, 101); + ok(c == 0x0000ff00, "got %#x.\n", c); + + /* Clipper with window has no effect. */ + hr = IDirectDrawSurface4_SetClipper(surface, clipper_hwnd); + ok(hr == DD_OK, "got %#lx.\n", hr); + fill_surface(surface, 0xff0000ff); + c = get_surface_color(surface, window_rect->left + 1, window_rect->top + 1); + ok(c == 0x000000ff, "got %#x.\n", c); + + hr = IDirectDrawSurface4_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx); + ok(hr == DD_OK, "got %#lx.\n", hr); + + c = get_surface_color(surface, window_rect->left + 1, window_rect->top + 1); + todo_wine_if(!(style & WS_VISIBLE)) ok(c == 0x0000ff00, "got %#x.\n", c); + c = get_surface_color(surface, 0, 0); + todo_wine_if((style & (WS_CHILD | WS_VISIBLE)) != (WS_CHILD | WS_VISIBLE)) ok(c == 0x0000ff00, "got %#x.\n", c); + + hr = IDirectDrawSurface4_SetClipper(surface, NULL); + ok(hr == DD_OK, "got %#lx.\n", hr); + fill_surface(surface, 0); +} + +static void test_clipper_in_exclusive_fullscreen(void) +{ + static const struct + { + DWORD style; + BOOL parent; + } + tests[] = + { + { WS_POPUP }, + { WS_POPUP, TRUE }, + { WS_CHILD, TRUE }, + { WS_OVERLAPPED }, + { WS_CHILD | WS_VISIBLE, TRUE }, + { WS_POPUP | WS_VISIBLE }, + }; + IDirectDrawSurface4 *primary, *offscreen; + IDirectDrawClipper *clipper, *clipper2; + DDSURFACEDESC2 surface_desc; + HWND window, clip_window; + IDirectDraw4 *ddraw; + RGNDATA *rgn_data; + DWORD ret, style; + RECT window_rect; + ULONG refcount; + unsigned int i; + HRESULT hr; + HRGN rgn; + + if (!(ddraw = create_ddraw())) + { + skip("Failed to create ddraw, skipping test.\n"); + return; + } + hr = IDirectDraw4_CreateClipper(ddraw, 0, &clipper, NULL); + ok(hr == DD_OK, "got %#lx.\n", hr); + + hr = IDirectDraw4_CreateClipper(ddraw, 0, &clipper2, NULL); + ok(hr == DD_OK, "got %#lx.\n", hr); + + window = CreateWindowA("static", "ddraw_fullscreen", WS_POPUP | WS_VISIBLE, 0, 0, 640, 480, NULL, NULL, NULL, NULL); + pump_messages(); + hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN); + ok(hr == DD_OK, "got %#lx.\n", hr); + pump_messages(); + + rgn = CreateRectRgn(100, 100, 200, 200); + ok(!!rgn, "Failed to create region.\n"); + ret = GetRegionData(rgn, 0, NULL); + rgn_data = malloc(ret); + ret = GetRegionData(rgn, ret, rgn_data); + ok(!!ret, "Failed to get region data.\n"); + DeleteObject(rgn); + hr = IDirectDrawClipper_SetClipList(clipper2, rgn_data, 0); + ok(hr == DD_OK, "got %#lx.\n", hr); + free(rgn_data); + + 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(hr == DD_OK, "got %#lx.\n", hr); + + surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + surface_desc.dwWidth = 640; + surface_desc.dwHeight = 480; + hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &offscreen, NULL); + ok(hr == DD_OK, "got %#lx.\n", hr); + + for (i = 0; i < ARRAY_SIZE(tests); ++i) + { + winetest_push_context("test %u", i); + style = tests[i].style; + clip_window = CreateWindowA("static", "ddraw_clip", style, 100, 100, 100, 100, + tests[i].parent ? window : NULL, NULL, NULL, NULL); + ok(!!clip_window, "got error %ld.\n", GetLastError()); + pump_messages(); + + GetWindowRect(clip_window, &window_rect); + hr = IDirectDrawClipper_SetHWnd(clipper, 0, clip_window); + ok(hr == DD_OK, "got %#lx.\n", hr); + + hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret); + ok(hr == DD_OK, "got %#lx.\n", hr); + rgn_data = malloc(ret); + hr = IDirectDrawClipper_GetClipList(clipper, NULL, rgn_data, &ret); + ok(hr == DD_OK, "got %#lx.\n", hr); + ok(rgn_data->rdh.dwSize == sizeof(rgn_data->rdh), "Got unexpected structure size %#lx.\n", rgn_data->rdh.dwSize); + ok(rgn_data->rdh.iType == RDH_RECTANGLES, "Got unexpected type %#lx.\n", rgn_data->rdh.iType); + if (style & WS_VISIBLE) + { + ok(rgn_data->rdh.nCount >= 1, "got %lu.\n", rgn_data->rdh.nCount); + if (!(style & WS_CHILD)) + ok(EqualRect(&rgn_data->rdh.rcBound, &window_rect), "got %s, expected %s.\n", + wine_dbgstr_rect(&rgn_data->rdh.rcBound), wine_dbgstr_rect(&window_rect)); + } + else + { + ok(!rgn_data->rdh.nCount, "got %lu.\n", rgn_data->rdh.nCount); + } + free(rgn_data); + + winetest_push_context("primary"); + check_surface_clipper(primary, clipper, clipper2, &window_rect, style); + winetest_pop_context(); + + winetest_push_context("offscreen"); + check_surface_clipper(offscreen, clipper, clipper2, &window_rect, style); + winetest_pop_context(); + + hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL); + ok(hr == DD_OK, "got %#lx.\n", hr); + DestroyWindow(clip_window); + pump_messages(); + winetest_pop_context(); + } + + IDirectDrawClipper_Release(clipper); + refcount = IDirectDrawSurface4_Release(offscreen); + ok(!refcount, "Got unexpected refcount %lu.\n", refcount); + refcount = IDirectDrawSurface4_Release(primary); + ok(!refcount, "Got unexpected refcount %lu.\n", refcount); + + IDirectDraw4_Release(ddraw); + DestroyWindow(window); + pump_messages(); +} + START_TEST(ddraw4) { DDDEVICEIDENTIFIER identifier; @@ -20701,4 +20884,5 @@ START_TEST(ddraw4) test_sysmem_x_channel(); test_yuv_blit(); test_blit_to_self(); + test_clipper_in_exclusive_fullscreen(); } diff --git a/dlls/ddraw/tests/ddraw7.c b/dlls/ddraw/tests/ddraw7.c index e8487283ead..eb35cfa6792 100644 --- a/dlls/ddraw/tests/ddraw7.c +++ b/dlls/ddraw/tests/ddraw7.c @@ -162,6 +162,14 @@ static void flush_events(void) } } +static void pump_messages(void) +{ + MSG msg; + + while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) + DispatchMessageA(&msg); +} + static HWND create_foreground_window(void) { for (UINT retries = 5; retries; retries--) @@ -20950,6 +20958,181 @@ out: DestroyWindow(window); } +static void check_surface_clipper(IDirectDrawSurface7 *surface, IDirectDrawClipper *clipper_hwnd, + IDirectDrawClipper *clipper_region, RECT *window_rect, DWORD style) +{ + unsigned int c; + DDBLTFX fx; + HRESULT hr; + + memset(&fx, 0, sizeof(fx)); + fx.dwSize = sizeof(fx); + fx.dwFillColor = 0xff00ff00; + + fill_surface(surface, 0xffff0000); + + /* Clipper with region works. */ + hr = IDirectDrawSurface7_SetClipper(surface, clipper_region); + ok(hr == DD_OK, "got %#lx.\n", hr); + c = get_surface_color(surface, 101, 101); + ok(c == 0x00ff0000, "got %#x.\n", c); + hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx); + ok(hr == DD_OK, "got %#lx.\n", hr); + c = get_surface_color(surface, 0, 0); + ok(c == 0x00ff0000, "got %#x.\n", c); + c = get_surface_color(surface, 101, 101); + ok(c == 0x0000ff00, "got %#x.\n", c); + + /* Clipper with window has no effect. */ + hr = IDirectDrawSurface7_SetClipper(surface, clipper_hwnd); + ok(hr == DD_OK, "got %#lx.\n", hr); + fill_surface(surface, 0xff0000ff); + c = get_surface_color(surface, window_rect->left + 1, window_rect->top + 1); + ok(c == 0x000000ff, "got %#x.\n", c); + + hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx); + ok(hr == DD_OK, "got %#lx.\n", hr); + + c = get_surface_color(surface, window_rect->left + 1, window_rect->top + 1); + todo_wine_if(!(style & WS_VISIBLE)) ok(c == 0x0000ff00, "got %#x.\n", c); + c = get_surface_color(surface, 0, 0); + todo_wine_if((style & (WS_CHILD | WS_VISIBLE)) != (WS_CHILD | WS_VISIBLE)) ok(c == 0x0000ff00, "got %#x.\n", c); + + hr = IDirectDrawSurface7_SetClipper(surface, NULL); + ok(hr == DD_OK, "got %#lx.\n", hr); + clear_surface(surface, 0); +} + +static void test_clipper_in_exclusive_fullscreen(void) +{ + static const struct + { + DWORD style; + BOOL parent; + } + tests[] = + { + { WS_POPUP }, + { WS_POPUP, TRUE }, + { WS_CHILD, TRUE }, + { WS_OVERLAPPED }, + { WS_CHILD | WS_VISIBLE, TRUE }, + { WS_POPUP | WS_VISIBLE }, + }; + IDirectDrawSurface7 *primary, *offscreen; + IDirectDrawClipper *clipper, *clipper2; + DDSURFACEDESC2 surface_desc; + HWND window, clip_window; + IDirectDraw7 *ddraw; + RGNDATA *rgn_data; + DWORD ret, style; + RECT window_rect; + ULONG refcount; + unsigned int i; + HRESULT hr; + HRGN rgn; + + if (!(ddraw = create_ddraw())) + { + skip("Failed to create ddraw, skipping test.\n"); + return; + } + hr = IDirectDraw7_CreateClipper(ddraw, 0, &clipper, NULL); + ok(hr == DD_OK, "got %#lx.\n", hr); + + hr = IDirectDraw7_CreateClipper(ddraw, 0, &clipper2, NULL); + ok(hr == DD_OK, "got %#lx.\n", hr); + + window = CreateWindowA("static", "ddraw_fullscreen", WS_POPUP | WS_VISIBLE, 0, 0, 640, 480, NULL, NULL, NULL, NULL); + pump_messages(); + hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN); + ok(hr == DD_OK, "got %#lx.\n", hr); + pump_messages(); + + rgn = CreateRectRgn(100, 100, 200, 200); + ok(!!rgn, "Failed to create region.\n"); + ret = GetRegionData(rgn, 0, NULL); + rgn_data = malloc(ret); + ret = GetRegionData(rgn, ret, rgn_data); + ok(!!ret, "Failed to get region data.\n"); + DeleteObject(rgn); + hr = IDirectDrawClipper_SetClipList(clipper2, rgn_data, 0); + ok(hr == DD_OK, "got %#lx.\n", hr); + free(rgn_data); + + 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(hr == DD_OK, "got %#lx.\n", hr); + + surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + surface_desc.dwWidth = 640; + surface_desc.dwHeight = 480; + hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &offscreen, NULL); + ok(hr == DD_OK, "got %#lx.\n", hr); + + for (i = 0; i < ARRAY_SIZE(tests); ++i) + { + winetest_push_context("test %u", i); + style = tests[i].style; + clip_window = CreateWindowA("static", "ddraw_clip", style, 100, 100, 100, 100, + tests[i].parent ? window : NULL, NULL, NULL, NULL); + ok(!!clip_window, "got error %ld.\n", GetLastError()); + pump_messages(); + + GetWindowRect(clip_window, &window_rect); + hr = IDirectDrawClipper_SetHWnd(clipper, 0, clip_window); + ok(hr == DD_OK, "got %#lx.\n", hr); + + hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &ret); + ok(hr == DD_OK, "got %#lx.\n", hr); + rgn_data = malloc(ret); + hr = IDirectDrawClipper_GetClipList(clipper, NULL, rgn_data, &ret); + ok(hr == DD_OK, "got %#lx.\n", hr); + ok(rgn_data->rdh.dwSize == sizeof(rgn_data->rdh), "Got unexpected structure size %#lx.\n", rgn_data->rdh.dwSize); + ok(rgn_data->rdh.iType == RDH_RECTANGLES, "Got unexpected type %#lx.\n", rgn_data->rdh.iType); + if (style & WS_VISIBLE) + { + ok(rgn_data->rdh.nCount >= 1, "got %lu.\n", rgn_data->rdh.nCount); + if (!(style & WS_CHILD)) + ok(EqualRect(&rgn_data->rdh.rcBound, &window_rect), "got %s, expected %s.\n", + wine_dbgstr_rect(&rgn_data->rdh.rcBound), wine_dbgstr_rect(&window_rect)); + } + else + { + ok(!rgn_data->rdh.nCount, "got %lu.\n", rgn_data->rdh.nCount); + } + free(rgn_data); + + winetest_push_context("primary"); + check_surface_clipper(primary, clipper, clipper2, &window_rect, style); + winetest_pop_context(); + + winetest_push_context("offscreen"); + check_surface_clipper(offscreen, clipper, clipper2, &window_rect, style); + winetest_pop_context(); + + hr = IDirectDrawClipper_SetHWnd(clipper, 0, NULL); + ok(hr == DD_OK, "got %#lx.\n", hr); + DestroyWindow(clip_window); + pump_messages(); + winetest_pop_context(); + } + + IDirectDrawClipper_Release(clipper); + refcount = IDirectDrawSurface7_Release(offscreen); + ok(!refcount, "Got unexpected refcount %lu.\n", refcount); + refcount = IDirectDrawSurface7_Release(primary); + ok(!refcount, "Got unexpected refcount %lu.\n", refcount); + + IDirectDraw7_Release(ddraw); + DestroyWindow(window); + pump_messages(); +} + START_TEST(ddraw7) { DDDEVICEIDENTIFIER2 identifier; @@ -21133,4 +21316,5 @@ START_TEST(ddraw7) test_sysmem_x_channel(); test_yuv_blit(); test_blit_to_self(); + test_clipper_in_exclusive_fullscreen(); } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10723