From: Stefan Dösinger Subject: [PATCH 1/5] d3d9: Refuse to reset a lost device. Message-Id: <1417169803-30971-1-git-send-email-stefan@codeweavers.com> Date: Fri, 28 Nov 2014 11:16:39 +0100 This fixes tabbing out of Crashday. This game uses Reset instead of TestCooperativeLevel to find out if focus has been restored. I did not place the failing reset call in the first focus loss cycle because this changes some follow-up return values from D3DERR_DEVICELOST to D3DERR_INVALIDCALL on native. In d3d9ex the (successful) reset call changes some results from S_PRESENT_MODE_CHANGED to S_PRESENT_OCCLUDED. --- dlls/d3d9/device.c | 7 +++++++ dlls/d3d9/tests/d3d9ex.c | 17 +++++++++++++++++ dlls/d3d9/tests/device.c | 11 +++++++++++ 3 files changed, 35 insertions(+) diff --git a/dlls/d3d9/device.c b/dlls/d3d9/device.c index 67a5629..89f6122 100644 --- a/dlls/d3d9/device.c +++ b/dlls/d3d9/device.c @@ -635,6 +635,13 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_Reset(IDirect3DDevice9Ex *if TRACE("iface %p, present_parameters %p.\n", iface, present_parameters); + if (!device->d3d_parent->extended && InterlockedCompareExchange(&device->device_state, + D3D9_DEVICE_STATE_LOST, D3D9_DEVICE_STATE_LOST) == D3D9_DEVICE_STATE_LOST) + { + WARN("App not active, returning D3DERR_DEVICELOST.\n"); + return D3DERR_DEVICELOST; + } + wined3d_mutex_lock(); if (device->vertex_buffer) diff --git a/dlls/d3d9/tests/d3d9ex.c b/dlls/d3d9/tests/d3d9ex.c index 226e338..0ac9db7 100644 --- a/dlls/d3d9/tests/d3d9ex.c +++ b/dlls/d3d9/tests/d3d9ex.c @@ -1374,6 +1374,23 @@ static void test_lost_device(void) hr = IDirect3DDevice9Ex_CheckDeviceState(device, NULL); ok(hr == S_PRESENT_OCCLUDED, "Got unexpected hr %#x.\n", hr); + ret = SetForegroundWindow(GetDesktopWindow()); + ok(ret, "Failed to set foreground window.\n"); + hr = IDirect3DDevice9Ex_Present(device, NULL, NULL, NULL, NULL); + ok(hr == S_PRESENT_OCCLUDED, "Got unexpected hr %#x.\n", hr); + hr = reset_device(device, &desc); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + hr = IDirect3DDevice9Ex_TestCooperativeLevel(device); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + hr = IDirect3DDevice9Ex_Present(device, NULL, NULL, NULL, NULL); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + hr = IDirect3DDevice9Ex_PresentEx(device, NULL, NULL, NULL, NULL, 0); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + hr = IDirect3DDevice9Ex_CheckDeviceState(device, window); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + hr = IDirect3DDevice9Ex_CheckDeviceState(device, NULL); + ok(hr == S_PRESENT_OCCLUDED, "Got unexpected hr %#x.\n", hr); + refcount = IDirect3DDevice9Ex_Release(device); ok(!refcount, "Device has %u references left.\n", refcount); done: diff --git a/dlls/d3d9/tests/device.c b/dlls/d3d9/tests/device.c index cd6a9bd..a5cab96 100644 --- a/dlls/d3d9/tests/device.c +++ b/dlls/d3d9/tests/device.c @@ -9751,6 +9751,17 @@ static void test_lost_device(void) hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL); ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + ret = SetForegroundWindow(GetDesktopWindow()); + ok(ret, "Failed to set foreground window.\n"); + hr = reset_device(device, &device_desc); + ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr); + ret = ShowWindow(window, SW_RESTORE); + ok(ret, "Failed to restore window.\n"); + ret = SetForegroundWindow(window); + ok(ret, "Failed to set foreground window.\n"); + hr = reset_device(device, &device_desc); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + refcount = IDirect3DDevice9_Release(device); ok(!refcount, "Device has %u references left.\n", refcount); done: -- 2.0.4