From: Stefan Dösinger stefan@codeweavers.com
I am still deliberately not testing after which message the swapchain state changes from the old state to the new until we find a game that depends on this.
ddraw, d3d8 and d3d9 do not catch recursive SetDisplayMode or Reset() calls. They will recurse for about 16 times and then return library specific weird return values like 0xd0000510 (NTSTATUS, but nonexistent facility) or 0x88760868 (non-existent HRESULT facility). I suspect it aborts when the kernel-side message processing stack is exhausted. As such, an application depending on nested calls in those libraries would have to deliberately do it, but limit the amount of nesting to a non-zero amount. --- dlls/dxgi/tests/dxgi.c | 44 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+)
diff --git a/dlls/dxgi/tests/dxgi.c b/dlls/dxgi/tests/dxgi.c index 097f85b2ac8..d9b1472df16 100644 --- a/dlls/dxgi/tests/dxgi.c +++ b/dlls/dxgi/tests/dxgi.c @@ -5847,14 +5847,54 @@ static BOOL check_message(const struct message *expected,
static LRESULT CALLBACK test_wndproc(HWND hwnd, unsigned int message, WPARAM wparam, LPARAM lparam) { + IDXGISwapChain *swapchain = (IDXGISwapChain *)GetWindowLongPtrA(hwnd, GWLP_USERDATA); + static BOOL reentry; + IDXGIOutput *target; + HRESULT hr, hr2; + BOOL fs; + flaky ok(!expect_no_messages, "Got unexpected message %#x, hwnd %p, wparam %#Ix, lparam %#Ix.\n", message, hwnd, wparam, lparam);
+ ok(!reentry, "Re-entered wndproc in nested SetFullscreenState call\n"); + if (expect_messages) { if (check_message(expect_messages, hwnd, message, wparam, lparam)) + { ++expect_messages; + + if (swapchain) + { + reentry = TRUE; + + hr = IDXGISwapChain_GetFullscreenState(swapchain, &fs, NULL); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + /* Priority of error values. */ + hr = IDXGISwapChain_GetContainingOutput(swapchain, &target); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, target); + ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#lx.\n", DXGI_ERROR_INVALID_CALL); + IDXGIOutput_Release(target); + + hr = IDXGISwapChain_SetFullscreenState(swapchain, TRUE, NULL); + hr2 = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL); + + if (fs) + { + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + ok(hr2 == DXGI_STATUS_MODE_CHANGE_IN_PROGRESS, "Got unexpected hr %#lx.\n", hr); + } + else + { + ok(hr == DXGI_STATUS_MODE_CHANGE_IN_PROGRESS, "Got unexpected hr %#lx.\n", hr); + ok(hr2 == S_OK, "Got unexpected hr %#lx.\n", hr); + } + reentry = FALSE; + } + } }
if (expect_messages_broken) @@ -5986,12 +6026,14 @@ static void test_swapchain_window_messages(IUnknown *device, BOOL is_d3d12) ok(!expect_messages->message, "Expected message %#x.\n", expect_messages->message);
/* enter fullscreen */ + SetWindowLongPtrA(window, GWLP_USERDATA, (LONG_PTR)swapchain); expect_messages = enter_fullscreen_messages; expect_messages_broken = enter_fullscreen_messages_vista; hr = IDXGISwapChain_SetFullscreenState(swapchain, TRUE, NULL); ok(hr == S_OK || hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE || broken(hr == DXGI_ERROR_UNSUPPORTED), /* Win 7 testbot */ "Got unexpected hr %#lx.\n", hr); + SetWindowLongPtrA(window, GWLP_USERDATA, (LONG_PTR)NULL); if (FAILED(hr)) { skip("Could not change fullscreen state.\n"); @@ -6036,9 +6078,11 @@ static void test_swapchain_window_messages(IUnknown *device, BOOL is_d3d12) expect_messages_broken = NULL;
/* leave fullscreen */ + SetWindowLongPtrA(window, GWLP_USERDATA, (LONG_PTR)swapchain); expect_messages = leave_fullscreen_messages; hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + SetWindowLongPtrA(window, GWLP_USERDATA, (LONG_PTR)NULL); flush_events(); ok(!expect_messages->message, "Expected message %#x.\n", expect_messages->message); expect_messages = NULL;