Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/ddraw/surface.c | 3 +++ dlls/ddraw/tests/ddraw1.c | 8 ++++++++ dlls/ddraw/tests/ddraw2.c | 8 ++++++++ dlls/ddraw/tests/ddraw4.c | 8 ++++++++ dlls/ddraw/tests/ddraw7.c | 8 ++++++++ 5 files changed, 35 insertions(+)
diff --git a/dlls/ddraw/surface.c b/dlls/ddraw/surface.c index 7b7f16e..3230410 100644 --- a/dlls/ddraw/surface.c +++ b/dlls/ddraw/surface.c @@ -3758,6 +3758,9 @@ static HRESULT WINAPI ddraw_surface7_Restore(IDirectDrawSurface7 *iface) struct wined3d_display_mode mode; HRESULT hr;
+ if (surface->ddraw->device_state == DDRAW_DEVICE_STATE_LOST) + return DDERR_WRONGMODE; + if (FAILED(hr = wined3d_swapchain_get_display_mode(swapchain, &mode, NULL))) { WARN("Failed to get display mode, hr %#x.\n", hr); diff --git a/dlls/ddraw/tests/ddraw1.c b/dlls/ddraw/tests/ddraw1.c index 652e52a..e543593 100644 --- a/dlls/ddraw/tests/ddraw1.c +++ b/dlls/ddraw/tests/ddraw1.c @@ -7358,6 +7358,14 @@ static void test_lost_device(void) ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr); hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT); ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr); + hr = IDirectDrawSurface_Restore(surface); + ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr); + hr = IDirectDrawSurface_IsLost(surface); + ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr); + hr = IDirectDrawSurface_IsLost(sysmem_surface); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); + hr = IDirectDrawSurface_Restore(sysmem_surface); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); hr = IDirectDrawSurface_IsLost(sysmem_surface); ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
diff --git a/dlls/ddraw/tests/ddraw2.c b/dlls/ddraw/tests/ddraw2.c index edaf868..e2a7f1e 100644 --- a/dlls/ddraw/tests/ddraw2.c +++ b/dlls/ddraw/tests/ddraw2.c @@ -8311,6 +8311,14 @@ static void test_lost_device(void) ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr); hr = IDirectDrawSurface_Flip(surface, NULL, DDFLIP_WAIT); ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr); + hr = IDirectDrawSurface_Restore(surface); + ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr); + hr = IDirectDrawSurface_IsLost(surface); + ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr); + hr = IDirectDrawSurface_IsLost(sysmem_surface); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); + hr = IDirectDrawSurface_Restore(sysmem_surface); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); hr = IDirectDrawSurface_IsLost(sysmem_surface); ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
diff --git a/dlls/ddraw/tests/ddraw4.c b/dlls/ddraw/tests/ddraw4.c index d1abde0..072d783 100644 --- a/dlls/ddraw/tests/ddraw4.c +++ b/dlls/ddraw/tests/ddraw4.c @@ -9708,6 +9708,14 @@ static void test_lost_device(void) ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr); hr = IDirectDrawSurface4_Flip(surface, NULL, DDFLIP_WAIT); ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr); + hr = IDirectDrawSurface4_Restore(surface); + ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr); + hr = IDirectDrawSurface4_IsLost(surface); + ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr); + hr = IDirectDrawSurface4_IsLost(sysmem_surface); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); + hr = IDirectDrawSurface4_Restore(sysmem_surface); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); hr = IDirectDrawSurface4_IsLost(sysmem_surface); ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
diff --git a/dlls/ddraw/tests/ddraw7.c b/dlls/ddraw/tests/ddraw7.c index 13eadfd..eb3a215 100644 --- a/dlls/ddraw/tests/ddraw7.c +++ b/dlls/ddraw/tests/ddraw7.c @@ -9466,6 +9466,14 @@ static void test_lost_device(void) ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr); hr = IDirectDrawSurface7_Flip(surface, NULL, DDFLIP_WAIT); ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr); + hr = IDirectDrawSurface7_Restore(surface); + ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr); + hr = IDirectDrawSurface7_IsLost(surface); + ok(hr == DDERR_SURFACELOST, "Got unexpected hr %#x.\n", hr); + hr = IDirectDrawSurface7_IsLost(sysmem_surface); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); + hr = IDirectDrawSurface7_Restore(sysmem_surface); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); hr = IDirectDrawSurface7_IsLost(sysmem_surface); ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com ---
I haven't been able to add a reliable test for this, mostly because WM_QUERYNEWPALETTE is rarely sent on Windows. In fact, for some reason even changing the display mode to 8bpp still didn't send it. But it was sent if the application was forced into "Run in 256 colors" (Windows XP) while having a 32bpp desktop display mode, which sounds like a compatibility shim hack to me.
dlls/ddraw/surface.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/dlls/ddraw/surface.c b/dlls/ddraw/surface.c index 3230410..0ffc274 100644 --- a/dlls/ddraw/surface.c +++ b/dlls/ddraw/surface.c @@ -3753,13 +3753,21 @@ static HRESULT WINAPI ddraw_surface7_Restore(IDirectDrawSurface7 *iface)
if (surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) { + HWND window = surface->ddraw->focuswindow ? surface->ddraw->focuswindow : surface->ddraw->dest_window; struct wined3d_swapchain *swapchain = surface->ddraw->wined3d_swapchain; struct wined3d_sub_resource_desc wined3d_desc; struct wined3d_display_mode mode; HRESULT hr;
if (surface->ddraw->device_state == DDRAW_DEVICE_STATE_LOST) - return DDERR_WRONGMODE; + { + /* Railroad Tycoon 2 tries to restore the surface from within + a WM_QUERYNEWPALETTE message and expects it to succeed. */ + if (GetForegroundWindow() != window) return DDERR_WRONGMODE; + + surface->ddraw->device_state = DDRAW_DEVICE_STATE_NOT_RESTORED; + } +
if (FAILED(hr = wined3d_swapchain_get_display_mode(swapchain, &mode, NULL))) {
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=76170
Your paranoid android.
=== debiant (build log) ===
The task timed out
=== debiant (32 bit WoW report) ===
ddraw: ddraw1: Timeout
=== debiant (build log) ===
The task timed out
On Mon, 27 Jul 2020 at 17:21, Gabriel Ivăncescu gabrielopcode@gmail.com wrote:
/* Railroad Tycoon 2 tries to restore the surface from within
a WM_QUERYNEWPALETTE message and expects it to succeed. */
I think the reason we care about that is that while the window has been restored at that point, WM_ACTIVATEAPP hasn't been sent yet; otherwise device_parent_activate() would take care of it. In other words, the comment could use some work.
if (GetForegroundWindow() != window) return DDERR_WRONGMODE;
surface->ddraw->device_state = DDRAW_DEVICE_STATE_NOT_RESTORED;
}
Stray newline.
Like patch 1/2, should this apply to non-primary surfaces as well?
On 27/07/2020 17:09, Henri Verbeet wrote:
On Mon, 27 Jul 2020 at 17:21, Gabriel Ivăncescu gabrielopcode@gmail.com wrote:
/* Railroad Tycoon 2 tries to restore the surface from within
a WM_QUERYNEWPALETTE message and expects it to succeed. */
I think the reason we care about that is that while the window has been restored at that point, WM_ACTIVATEAPP hasn't been sent yet; otherwise device_parent_activate() would take care of it. In other words, the comment could use some work.
Right, how about something like:
Railroad Tycoon 2 tries to restore the surface from within a WM_QUERYNEWPALETTE message and expects it to succeed. We haven't received the WM_ACTIVATEAPP message by that point, so the device state is still LOST, even though we are in the foreground.
Or do you have something else in mind?
if (GetForegroundWindow() != window) return DDERR_WRONGMODE;
surface->ddraw->device_state = DDRAW_DEVICE_STATE_NOT_RESTORED;
}
Stray newline.
Like patch 1/2, should this apply to non-primary surfaces as well?
Good question, I did add tests for sysmem, but apparently that one can't be lost in the first place. I'll look into it, thanks. :-)
On Mon, 27 Jul 2020 at 19:18, Gabriel Ivăncescu gabrielopcode@gmail.com wrote:
Right, how about something like:
Railroad Tycoon 2 tries to restore the surface from within a WM_QUERYNEWPALETTE message and expects it to succeed. We haven't received the WM_ACTIVATEAPP message by that point, so the device state is still LOST, even though we are in the foreground.
Something along those lines would be fine, yes.
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=76169
Your paranoid android.
=== debiant (build log) ===
The task timed out
On Mon, 27 Jul 2020 at 17:21, Gabriel Ivăncescu gabrielopcode@gmail.com wrote:
@@ -3758,6 +3758,9 @@ static HRESULT WINAPI ddraw_surface7_Restore(IDirectDrawSurface7 *iface) struct wined3d_display_mode mode; HRESULT hr;
if (surface->ddraw->device_state == DDRAW_DEVICE_STATE_LOST)
return DDERR_WRONGMODE;
Does this only apply to primary surfaces, or does it affect other surfaces as well?