From: Rémi Bernon rbernon@codeweavers.com
Using a new wined3d WINED3D_NO_CLIP_CHILDREN flag which will remove the style, as native, to allow win32u offscreen rendering to blit over child windows but still invalidate them after WM_PAINT, as necessary for some game such as Command & Conquer 2 to refresh their display properly.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=58844 --- dlls/ddraw/ddraw_private.h | 3 ++- dlls/ddraw/tests/ddraw1.c | 4 ++-- dlls/ddraw/tests/ddraw2.c | 4 ++-- dlls/ddraw/tests/ddraw4.c | 4 ++-- dlls/ddraw/tests/ddraw7.c | 4 ++-- dlls/wined3d/device.c | 19 +++++++++++++++++++ dlls/wined3d/swapchain.c | 9 ++++++--- include/wine/wined3d.h | 1 + 8 files changed, 36 insertions(+), 12 deletions(-)
diff --git a/dlls/ddraw/ddraw_private.h b/dlls/ddraw/ddraw_private.h index bd1df8e1b82..b8e830296dc 100644 --- a/dlls/ddraw/ddraw_private.h +++ b/dlls/ddraw/ddraw_private.h @@ -62,7 +62,8 @@ struct FvfToDecl
#define DDRAW_WINED3D_FLAGS (WINED3D_LEGACY_DEPTH_BIAS | WINED3D_RESTORE_MODE_ON_ACTIVATE \ | WINED3D_FOCUS_MESSAGES | WINED3D_PIXEL_CENTER_INTEGER | WINED3D_LEGACY_UNBOUND_RESOURCE_COLOR \ - | WINED3D_NO_PRIMITIVE_RESTART | WINED3D_LEGACY_CUBEMAP_FILTERING | WINED3D_NO_DRAW_INDIRECT) + | WINED3D_NO_PRIMITIVE_RESTART | WINED3D_LEGACY_CUBEMAP_FILTERING | WINED3D_NO_DRAW_INDIRECT \ + | WINED3D_NO_CLIP_CHILDREN)
#define DDRAW_WINED3D_SWAPCHAIN_FLAGS (WINED3D_SWAPCHAIN_ALLOW_MODE_SWITCH \ | WINED3D_SWAPCHAIN_IMPLICIT | WINED3D_SWAPCHAIN_REGISTER_TOPMOST_TIMER) diff --git a/dlls/ddraw/tests/ddraw1.c b/dlls/ddraw/tests/ddraw1.c index 53397088829..60496a0921b 100644 --- a/dlls/ddraw/tests/ddraw1.c +++ b/dlls/ddraw/tests/ddraw1.c @@ -16364,7 +16364,7 @@ static void test_window_clipping(void) ok(ret == 1, "Got unexpected ret %d\n", ret); data = get_region_data(region); /* expect children *not* to be clipped out */ - todo_wine ok(data->rdh.nCount == 1, "Got nCount %lu\n", data->rdh.nCount); + ok(data->rdh.nCount == 1, "Got nCount %lu\n", data->rdh.nCount); free(data); DeleteObject(region);
@@ -16397,7 +16397,7 @@ static void test_window_clipping(void) ok(ret == 1, "Got unexpected ret %d\n", ret); data = get_region_data(region); /* expect children *not* to be clipped out */ - todo_wine ok(data->rdh.nCount == 1, "Got nCount %lu\n", data->rdh.nCount); + ok(data->rdh.nCount == 1, "Got nCount %lu\n", data->rdh.nCount); free(data); DeleteObject(region);
diff --git a/dlls/ddraw/tests/ddraw2.c b/dlls/ddraw/tests/ddraw2.c index d4678344585..c6b3f9aa9da 100644 --- a/dlls/ddraw/tests/ddraw2.c +++ b/dlls/ddraw/tests/ddraw2.c @@ -17435,7 +17435,7 @@ static void test_window_clipping(void) ok(ret == 1, "Got unexpected ret %d\n", ret); data = get_region_data(region); /* expect children *not* to be clipped out */ - todo_wine ok(data->rdh.nCount == 1, "Got nCount %lu\n", data->rdh.nCount); + ok(data->rdh.nCount == 1, "Got nCount %lu\n", data->rdh.nCount); free(data); DeleteObject(region);
@@ -17468,7 +17468,7 @@ static void test_window_clipping(void) ok(ret == 1, "Got unexpected ret %d\n", ret); data = get_region_data(region); /* expect children *not* to be clipped out */ - todo_wine ok(data->rdh.nCount == 1, "Got nCount %lu\n", data->rdh.nCount); + ok(data->rdh.nCount == 1, "Got nCount %lu\n", data->rdh.nCount); free(data); DeleteObject(region);
diff --git a/dlls/ddraw/tests/ddraw4.c b/dlls/ddraw/tests/ddraw4.c index 7a955155099..4f49d50359a 100644 --- a/dlls/ddraw/tests/ddraw4.c +++ b/dlls/ddraw/tests/ddraw4.c @@ -20516,7 +20516,7 @@ static void test_window_clipping(void) ok(ret == 1, "Got unexpected ret %d\n", ret); data = get_region_data(region); /* expect children *not* to be clipped out */ - todo_wine ok(data->rdh.nCount == 1, "Got nCount %lu\n", data->rdh.nCount); + ok(data->rdh.nCount == 1, "Got nCount %lu\n", data->rdh.nCount); free(data); DeleteObject(region);
@@ -20549,7 +20549,7 @@ static void test_window_clipping(void) ok(ret == 1, "Got unexpected ret %d\n", ret); data = get_region_data(region); /* expect children *not* to be clipped out */ - todo_wine ok(data->rdh.nCount == 1, "Got nCount %lu\n", data->rdh.nCount); + ok(data->rdh.nCount == 1, "Got nCount %lu\n", data->rdh.nCount); free(data); DeleteObject(region);
diff --git a/dlls/ddraw/tests/ddraw7.c b/dlls/ddraw/tests/ddraw7.c index 50963559fb3..c0360cf8966 100644 --- a/dlls/ddraw/tests/ddraw7.c +++ b/dlls/ddraw/tests/ddraw7.c @@ -20916,7 +20916,7 @@ static void test_window_clipping(void) ok(ret == 1, "Got unexpected ret %d\n", ret); data = get_region_data(region); /* expect children *not* to be clipped out */ - todo_wine ok(data->rdh.nCount == 1, "Got nCount %lu\n", data->rdh.nCount); + ok(data->rdh.nCount == 1, "Got nCount %lu\n", data->rdh.nCount); free(data); DeleteObject(region);
@@ -20949,7 +20949,7 @@ static void test_window_clipping(void) ok(ret == 1, "Got unexpected ret %d\n", ret); data = get_region_data(region); /* expect children *not* to be clipped out */ - todo_wine ok(data->rdh.nCount == 1, "Got nCount %lu\n", data->rdh.nCount); + ok(data->rdh.nCount == 1, "Got nCount %lu\n", data->rdh.nCount); free(data); DeleteObject(region);
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 443bf10ab76..2736a4be4f6 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -5633,6 +5633,25 @@ LRESULT device_process_message(struct wined3d_device *device, HWND window, BOOL DefWindowProcA(window, message, wparam, lparam); } } + else if (message == WM_PAINT && device->wined3d->flags & WINED3D_NO_CLIP_CHILDREN) + { + struct wined3d_swapchain *swapchain; + LRESULT res; + + if (unicode) + res = CallWindowProcW(proc, window, message, wparam, lparam); + else + res = CallWindowProcA(proc, window, message, wparam, lparam); + + if ((swapchain = wined3d_device_get_swapchain(device, 0)) + && swapchain->state.style & WS_CLIPCHILDREN) + { + RedrawWindow(window, NULL, 0, RDW_INVALIDATE | RDW_NOFRAME); + RedrawWindow(window, NULL, 0, RDW_VALIDATE | RDW_NOFRAME | RDW_NOCHILDREN); + } + + return res; + }
if (unicode) return CallWindowProcW(proc, window, message, wparam, lparam); diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c index a1000ec2393..fbba1f348ba 100644 --- a/dlls/wined3d/swapchain.c +++ b/dlls/wined3d/swapchain.c @@ -2148,11 +2148,13 @@ HRESULT CDECL wined3d_swapchain_state_resize_target(struct wined3d_swapchain_sta return WINED3D_OK; }
-static LONG fullscreen_style(LONG style) +static LONG fullscreen_style(LONG style, UINT flags) { /* Make sure the window is managed, otherwise we won't get keyboard input. */ style |= WS_POPUP | WS_SYSMENU; style &= ~(WS_CAPTION | WS_THICKFRAME); + if (flags & WINED3D_NO_CLIP_CHILDREN) + style &= ~WS_CLIPCHILDREN;
return style; } @@ -2282,7 +2284,7 @@ HRESULT wined3d_swapchain_state_setup_fullscreen(struct wined3d_swapchain_state state->style = GetWindowLongW(window, GWL_STYLE); state->exstyle = GetWindowLongW(window, GWL_EXSTYLE);
- s->style = fullscreen_style(state->style); + s->style = fullscreen_style(state->style, state->wined3d->flags); s->exstyle = fullscreen_exstyle(state->exstyle); s->set_style = true; s->register_topmost_timer = !!(state->desc.flags & WINED3D_SWAPCHAIN_REGISTER_TOPMOST_TIMER); @@ -2340,7 +2342,8 @@ void wined3d_swapchain_state_restore_from_fullscreen(struct wined3d_swapchain_st * fullscreen phase. Some applications change it before calling Reset() * when switching between windowed and fullscreen modes (HL2), some * depend on the original style (Eve Online). */ - s->set_style = style == fullscreen_style(state->style) && exstyle == fullscreen_exstyle(state->exstyle); + s->set_style = style == fullscreen_style(state->style, state->wined3d->flags) + && exstyle == fullscreen_exstyle(state->exstyle); s->register_topmost_timer = !!(state->desc.flags & WINED3D_SWAPCHAIN_REGISTER_TOPMOST_TIMER); s->set_topmost_timer = false;
diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h index 2c57b55cb1a..9aa16f78f0d 100644 --- a/include/wine/wined3d.h +++ b/include/wine/wined3d.h @@ -1345,6 +1345,7 @@ enum wined3d_memory_segment_group #define WINED3D_LEGACY_CUBEMAP_FILTERING 0x00001000 #define WINED3D_NORMALIZED_DEPTH_BIAS 0x00002000 #define WINED3D_NO_DRAW_INDIRECT 0x00004000 +#define WINED3D_NO_CLIP_CHILDREN 0x00008000
#define WINED3D_RESZ_CODE 0x7fa05000