From: Conor McCarthy [email protected]
Signed-off-by: Henri Verbeet [email protected] --- This supersedes patch 167239.
dlls/dxgi/swapchain.c | 146 ++++++++++++++++++++++++++++++++++------- dlls/dxgi/tests/dxgi.c | 34 +++++----- dlls/wined3d/device.c | 3 +- dlls/wined3d/swapchain.c | 137 +++++++++++++++++++++----------------- dlls/wined3d/wined3d.spec | 4 +- dlls/wined3d/wined3d_main.c | 3 +- dlls/wined3d/wined3d_private.h | 5 +- include/wine/wined3d.h | 7 +- 8 files changed, 230 insertions(+), 109 deletions(-)
diff --git a/dlls/dxgi/swapchain.c b/dlls/dxgi/swapchain.c index 0871200ff7c..c76ad1d1359 100644 --- a/dlls/dxgi/swapchain.c +++ b/dlls/dxgi/swapchain.c @@ -152,6 +152,24 @@ static HRESULT dxgi_get_output_from_window(IDXGIAdapter *adapter, HWND window, I return DXGI_ERROR_NOT_FOUND; }
+static HRESULT dxgi_swapchain_set_fullscreen_state(struct wined3d_swapchain_state *state, + const struct wined3d_swapchain_desc *swapchain_desc, IDXGIOutput *output) +{ + struct dxgi_output *dxgi_output; + struct dxgi_adapter *adapter; + HRESULT hr; + + dxgi_output = unsafe_impl_from_IDXGIOutput(output); + adapter = dxgi_output->adapter; + + wined3d_mutex_lock(); + hr = wined3d_swapchain_state_set_fullscreen(state, swapchain_desc, + adapter->factory->wined3d, adapter->ordinal, NULL); + wined3d_mutex_unlock(); + + return hr; +} + static HRESULT dxgi_swapchain_resize_target(IDXGISwapChain1 *swapchain, struct wined3d_swapchain_state *state, const DXGI_MODE_DESC *target_mode_desc) { @@ -391,6 +409,7 @@ static HRESULT STDMETHODCALLTYPE DECLSPEC_HOTPATCH d3d11_swapchain_SetFullscreen { struct d3d11_swapchain *swapchain = d3d11_swapchain_from_IDXGISwapChain1(iface); struct wined3d_swapchain_desc swapchain_desc; + struct wined3d_swapchain_state *state; HRESULT hr;
TRACE("iface %p, fullscreen %#x, target %p.\n", iface, fullscreen, target); @@ -401,31 +420,35 @@ static HRESULT STDMETHODCALLTYPE DECLSPEC_HOTPATCH d3d11_swapchain_SetFullscreen return DXGI_ERROR_INVALID_CALL; }
- if (fullscreen) + if (target) { - if (target) - { - IDXGIOutput_AddRef(target); - } - else if (FAILED(hr = IDXGISwapChain1_GetContainingOutput(iface, &target))) - { - WARN("Failed to get default target output for swapchain, hr %#x.\n", hr); - return hr; - } + IDXGIOutput_AddRef(target); + } + else if (FAILED(hr = IDXGISwapChain1_GetContainingOutput(iface, &target))) + { + WARN("Failed to get target output for swapchain, hr %#x.\n", hr); + return hr; }
wined3d_mutex_lock(); + state = wined3d_swapchain_get_state(swapchain->wined3d_swapchain); wined3d_swapchain_get_desc(swapchain->wined3d_swapchain, &swapchain_desc); swapchain_desc.windowed = !fullscreen; - hr = wined3d_swapchain_set_fullscreen(swapchain->wined3d_swapchain, &swapchain_desc, NULL); + hr = dxgi_swapchain_set_fullscreen_state(state, &swapchain_desc, target); wined3d_mutex_unlock(); if (FAILED(hr)) { - if (target) - IDXGIOutput_Release(target); + IDXGIOutput_Release(target); + return DXGI_ERROR_NOT_CURRENTLY_AVAILABLE; }
+ if (!fullscreen) + { + IDXGIOutput_Release(target); + target = NULL; + } + if (swapchain->target) IDXGIOutput_Release(swapchain->target); swapchain->target = target; @@ -866,22 +889,27 @@ HRESULT d3d11_swapchain_init(struct d3d11_swapchain *swapchain, struct dxgi_devi swapchain->target = NULL; if (fullscreen) { + struct wined3d_swapchain_state *state; + desc->windowed = FALSE; - if (FAILED(hr = wined3d_swapchain_set_fullscreen(swapchain->wined3d_swapchain, - desc, NULL))) + state = wined3d_swapchain_get_state(swapchain->wined3d_swapchain); + + if (FAILED(hr = IDXGISwapChain1_GetContainingOutput(&swapchain->IDXGISwapChain1_iface, + &swapchain->target))) { - WARN("Failed to set fullscreen state, hr %#x.\n", hr); + WARN("Failed to get target output for fullscreen swapchain, hr %#x.\n", hr); wined3d_swapchain_decref(swapchain->wined3d_swapchain); goto cleanup; }
- if (FAILED(hr = IDXGISwapChain1_GetContainingOutput(&swapchain->IDXGISwapChain1_iface, - &swapchain->target))) + if (FAILED(hr = dxgi_swapchain_set_fullscreen_state(state, desc, swapchain->target))) { - WARN("Failed to get target output for fullscreen swapchain, hr %#x.\n", hr); + WARN("Failed to set fullscreen state, hr %#x.\n", hr); + IDXGIOutput_Release(swapchain->target); wined3d_swapchain_decref(swapchain->wined3d_swapchain); goto cleanup; } + } wined3d_mutex_unlock();
@@ -1067,6 +1095,7 @@ struct d3d12_swapchain IWineDXGIFactory *factory;
HWND window; + IDXGIOutput *target; DXGI_SWAP_CHAIN_DESC1 desc; DXGI_SWAP_CHAIN_FULLSCREEN_DESC fullscreen_desc; }; @@ -1865,6 +1894,12 @@ static void d3d12_swapchain_destroy(struct d3d12_swapchain *swapchain) if (swapchain->vk_instance) vk_funcs->p_vkDestroySurfaceKHR(swapchain->vk_instance, swapchain->vk_surface, NULL);
+ if (swapchain->target) + { + WARN("Destroying fullscreen swapchain.\n"); + IDXGIOutput_Release(swapchain->target); + } + if (swapchain->device) ID3D12Device_Release(swapchain->device);
@@ -2165,9 +2200,57 @@ static HRESULT STDMETHODCALLTYPE d3d12_swapchain_GetBuffer(IDXGISwapChain3 *ifac static HRESULT STDMETHODCALLTYPE DECLSPEC_HOTPATCH d3d12_swapchain_SetFullscreenState(IDXGISwapChain3 *iface, BOOL fullscreen, IDXGIOutput *target) { - FIXME("iface %p, fullscreen %#x, target %p stub!\n", iface, fullscreen, target); + struct d3d12_swapchain *swapchain = d3d12_swapchain_from_IDXGISwapChain3(iface); + DXGI_SWAP_CHAIN_FULLSCREEN_DESC *fullscreen_desc = &swapchain->fullscreen_desc; + const DXGI_SWAP_CHAIN_DESC1 *swapchain_desc = &swapchain->desc; + struct wined3d_swapchain_desc wined3d_desc; + HWND window = swapchain->window; + HRESULT hr;
- return E_NOTIMPL; + TRACE("iface %p, fullscreen %#x, target %p.\n", iface, fullscreen, target); + + if (!fullscreen && target) + { + WARN("Invalid call.\n"); + return DXGI_ERROR_INVALID_CALL; + } + + if (target) + { + IDXGIOutput_AddRef(target); + } + else if (FAILED(hr = IDXGISwapChain3_GetContainingOutput(iface, &target))) + { + WARN("Failed to get target output for swapchain, hr %#x.\n", hr); + return hr; + } + + if (FAILED(hr = wined3d_swapchain_desc_from_dxgi(&wined3d_desc, window, swapchain_desc, fullscreen_desc))) + goto fail; + wined3d_mutex_lock(); + wined3d_desc.windowed = !fullscreen; + hr = dxgi_swapchain_set_fullscreen_state(swapchain->state, &wined3d_desc, target); + wined3d_mutex_unlock(); + if (FAILED(hr)) + goto fail; + + fullscreen_desc->Windowed = wined3d_desc.windowed; + if (!fullscreen) + { + IDXGIOutput_Release(target); + target = NULL; + } + + if (swapchain->target) + IDXGIOutput_Release(swapchain->target); + swapchain->target = target; + + return S_OK; + +fail: + IDXGIOutput_Release(target); + + return DXGI_ERROR_NOT_CURRENTLY_AVAILABLE; }
static HRESULT STDMETHODCALLTYPE d3d12_swapchain_GetFullscreenState(IDXGISwapChain3 *iface, @@ -2180,8 +2263,8 @@ static HRESULT STDMETHODCALLTYPE d3d12_swapchain_GetFullscreenState(IDXGISwapCha if (fullscreen) *fullscreen = !swapchain->fullscreen_desc.Windowed;
- if (target) - *target = NULL; + if (target && (*target = swapchain->target)) + IDXGIOutput_AddRef(*target);
return S_OK; } @@ -2299,6 +2382,12 @@ static HRESULT STDMETHODCALLTYPE d3d12_swapchain_GetContainingOutput(IDXGISwapCh
TRACE("iface %p, output %p.\n", iface, output);
+ if (swapchain->target) + { + IDXGIOutput_AddRef(*output = swapchain->target); + return S_OK; + } + device_parent = vkd3d_get_device_parent(swapchain->device);
if (SUCCEEDED(hr = IUnknown_QueryInterface(device_parent, &IID_IDXGIAdapter, (void **)&adapter))) @@ -2726,10 +2815,13 @@ static HRESULT d3d12_swapchain_init(struct d3d12_swapchain *swapchain, IWineDXGI struct wined3d_swapchain_desc wined3d_desc; VkWin32SurfaceCreateInfoKHR surface_desc; VkPhysicalDevice vk_physical_device; + struct dxgi_adapter *dxgi_adapter; VkFenceCreateInfo fence_desc; uint32_t queue_family_index; VkSurfaceKHR vk_surface; + IUnknown *device_parent; VkInstance vk_instance; + IDXGIAdapter *adapter; VkBool32 supported; VkDevice vk_device; VkFence vk_fence; @@ -2768,9 +2860,15 @@ static HRESULT d3d12_swapchain_init(struct d3d12_swapchain *swapchain, IWineDXGI return DXGI_ERROR_UNSUPPORTED; }
+ device_parent = vkd3d_get_device_parent(device); + if (FAILED(hr = IUnknown_QueryInterface(device_parent, &IID_IDXGIAdapter, (void **)&adapter))) + return hr; + dxgi_adapter = unsafe_impl_from_IDXGIAdapter(adapter); + IDXGIAdapter_Release(adapter); if (FAILED(hr = wined3d_swapchain_desc_from_dxgi(&wined3d_desc, window, swapchain_desc, fullscreen_desc))) return hr; - if (FAILED(hr = wined3d_swapchain_state_create(&wined3d_desc, window, &swapchain->state))) + if (FAILED(hr = wined3d_swapchain_state_create(&wined3d_desc, window, + dxgi_adapter->factory->wined3d, dxgi_adapter->ordinal, &swapchain->state))) return hr;
if (swapchain_desc->BufferUsage && swapchain_desc->BufferUsage != DXGI_USAGE_RENDER_TARGET_OUTPUT) diff --git a/dlls/dxgi/tests/dxgi.c b/dlls/dxgi/tests/dxgi.c index 5f5bb1e33d7..2d4a5d460b0 100644 --- a/dlls/dxgi/tests/dxgi.c +++ b/dlls/dxgi/tests/dxgi.c @@ -4155,7 +4155,7 @@ static void test_swapchain_present(IUnknown *device, BOOL is_d3d12) skip("Test %u: Could not change fullscreen state.\n", i); continue; } - todo_wine_if(is_d3d12) ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr); + ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr); hr = IDXGISwapChain_ResizeBuffers(swapchain, 0, 0, 0, DXGI_FORMAT_UNKNOWN, 0); todo_wine_if(!is_d3d12) ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr); hr = IDXGISwapChain_Present(swapchain, 0, flags[i]); @@ -4164,8 +4164,8 @@ static void test_swapchain_present(IUnknown *device, BOOL is_d3d12) fullscreen = FALSE; hr = IDXGISwapChain_GetFullscreenState(swapchain, &fullscreen, &output); ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr); - todo_wine_if(is_d3d12) ok(fullscreen, "Test %u: Got unexpected fullscreen status.\n", i); - todo_wine_if(is_d3d12) ok(!!output, "Test %u: Got unexpected output.\n", i); + ok(fullscreen, "Test %u: Got unexpected fullscreen status.\n", i); + ok(!!output, "Test %u: Got unexpected output.\n", i);
if (output) IDXGIOutput_ReleaseOwnership(output); @@ -4173,7 +4173,7 @@ static void test_swapchain_present(IUnknown *device, BOOL is_d3d12) fullscreen = FALSE; hr = IDXGISwapChain_GetFullscreenState(swapchain, &fullscreen, NULL); ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr); - todo_wine_if(is_d3d12) ok(fullscreen, "Test %u: Got unexpected fullscreen status.\n", i); + ok(fullscreen, "Test %u: Got unexpected fullscreen status.\n", i); /* Calling IDXGISwapChain_Present() will exit fullscreen. */ hr = IDXGISwapChain_Present(swapchain, 0, flags[i]); ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr); @@ -4185,7 +4185,7 @@ static void test_swapchain_present(IUnknown *device, BOOL is_d3d12) /* Still fullscreen on vista and 2008. */ todo_wine ok(!fullscreen || broken(fullscreen), "Test %u: Got unexpected fullscreen status.\n", i); else - todo_wine_if(is_d3d12) ok(fullscreen, "Test %u: Got unexpected fullscreen status.\n", i); + ok(fullscreen, "Test %u: Got unexpected fullscreen status.\n", i); if (output) IDXGIOutput_Release(output);
@@ -4198,11 +4198,11 @@ static void test_swapchain_present(IUnknown *device, BOOL is_d3d12) * compositing. D3d12 fullscreen mode acts just like borderless * fullscreen window mode. */ hr = IDXGISwapChain_SetFullscreenState(swapchain, TRUE, NULL); - todo_wine_if(is_d3d12) ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr); + ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr); fullscreen = FALSE; hr = IDXGISwapChain_GetFullscreenState(swapchain, &fullscreen, NULL); ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr); - todo_wine_if(is_d3d12) ok(fullscreen, "Test %u: Got unexpected fullscreen status.\n", i); + ok(fullscreen, "Test %u: Got unexpected fullscreen status.\n", i); hr = IDXGISwapChain_ResizeBuffers(swapchain, 0, 0, 0, DXGI_FORMAT_UNKNOWN, 0); todo_wine_if(!is_d3d12) ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr); hr = IDXGISwapChain_Present(swapchain, 0, flags[i]); @@ -4218,7 +4218,7 @@ static void test_swapchain_present(IUnknown *device, BOOL is_d3d12) fullscreen = FALSE; hr = IDXGISwapChain_GetFullscreenState(swapchain, &fullscreen, NULL); ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr); - todo_wine_if(is_d3d12) ok(fullscreen, "Test %u: Got unexpected fullscreen status.\n", i); + ok(fullscreen, "Test %u: Got unexpected fullscreen status.\n", i); /* A visible, but with bottom z-order window still causes the * swapchain to exit fullscreen mode. */ SetWindowPos(occluding_window, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); @@ -4232,7 +4232,7 @@ static void test_swapchain_present(IUnknown *device, BOOL is_d3d12) fullscreen = TRUE; hr = IDXGISwapChain_GetFullscreenState(swapchain, &fullscreen, NULL); ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr); - todo_wine ok(is_d3d12 ? fullscreen : !fullscreen, + todo_wine_if(!is_d3d12) ok(is_d3d12 ? fullscreen : !fullscreen, "Test %u: Got unexpected fullscreen status.\n", i);
hr = IDXGISwapChain_ResizeBuffers(swapchain, 0, 0, 0, DXGI_FORMAT_UNKNOWN, 0); @@ -4245,10 +4245,10 @@ static void test_swapchain_present(IUnknown *device, BOOL is_d3d12) hr = IDXGISwapChain_GetFullscreenState(swapchain, &fullscreen, NULL); ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr); if (flags[i] == DXGI_PRESENT_TEST) - todo_wine ok(is_d3d12 ? fullscreen : !fullscreen, + todo_wine_if(!is_d3d12) ok(is_d3d12 ? fullscreen : !fullscreen, "Test %u: Got unexpected fullscreen status.\n", i); else - todo_wine_if(!is_d3d12) ok(!fullscreen, "Test %u: Got unexpected fullscreen status.\n", i); + todo_wine ok(!fullscreen, "Test %u: Got unexpected fullscreen status.\n", i);
/* Even though d3d12 doesn't exit fullscreen, a * IDXGISwapChain_ResizeBuffers() is still needed for subsequent @@ -4267,7 +4267,7 @@ static void test_swapchain_present(IUnknown *device, BOOL is_d3d12) * IDXGISwapChain_GetFullscreenState() before IDXGISwapChain_Present(). */ ShowWindow(occluding_window, SW_HIDE); hr = IDXGISwapChain_SetFullscreenState(swapchain, TRUE, NULL); - todo_wine_if(is_d3d12) ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr); + ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr); ShowWindow(occluding_window, SW_SHOW);
hr = IDXGISwapChain_ResizeBuffers(swapchain, 0, 0, 0, DXGI_FORMAT_UNKNOWN, 0); @@ -4303,7 +4303,7 @@ static void test_swapchain_present(IUnknown *device, BOOL is_d3d12) fullscreen = TRUE; hr = IDXGISwapChain_GetFullscreenState(swapchain, &fullscreen, NULL); ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr); - todo_wine_if(!is_d3d12) ok(!fullscreen, "Test %u: Got unexpected fullscreen status.\n", i); + todo_wine ok(!fullscreen, "Test %u: Got unexpected fullscreen status.\n", i);
DestroyWindow(occluding_window); hr = IDXGISwapChain_ResizeBuffers(swapchain, 0, 0, 0, DXGI_FORMAT_UNKNOWN, 0); @@ -4312,7 +4312,7 @@ static void test_swapchain_present(IUnknown *device, BOOL is_d3d12) ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL); - todo_wine_if(is_d3d12) ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr); + ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr); hr = IDXGISwapChain_ResizeBuffers(swapchain, 0, 0, 0, DXGI_FORMAT_UNKNOWN, 0); ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr); } @@ -5558,11 +5558,11 @@ static void test_output_ownership(IUnknown *device, BOOL is_d3d12) skip("Failed to change fullscreen state.\n"); goto done; } - todo_wine_if(is_d3d12) ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); + ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); fullscreen = FALSE; hr = IDXGISwapChain_GetFullscreenState(swapchain, &fullscreen, NULL); - todo_wine_if(is_d3d12) ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); - todo_wine_if(is_d3d12) ok(fullscreen, "Got unexpected fullscreen state.\n"); + ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); + ok(fullscreen, "Got unexpected fullscreen state.\n"); if (is_d3d12) wait_vidpn_exclusive_ownership(&check_ownership_desc, STATUS_SUCCESS, FALSE); else diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index db1b313fcbf..2c05209ea26 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -5428,7 +5428,8 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device, return hr; } } - if (FAILED(hr = wined3d_swapchain_set_fullscreen(swapchain, swapchain_desc, mode))) + if (FAILED(hr = wined3d_swapchain_state_set_fullscreen(&swapchain->state, + swapchain_desc, device->wined3d, device->adapter->ordinal, mode))) return hr;
/* Switch from fullscreen to windowed. */ diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c index 333c3153f68..37b0a78e386 100644 --- a/dlls/wined3d/swapchain.c +++ b/dlls/wined3d/swapchain.c @@ -80,13 +80,13 @@ static void swapchain_cleanup(struct wined3d_swapchain *swapchain) if (swapchain->state.desc.auto_restore_display_mode) { if (FAILED(hr = wined3d_set_adapter_display_mode(swapchain->device->wined3d, - swapchain->device->adapter->ordinal, &swapchain->original_mode))) + swapchain->device->adapter->ordinal, &swapchain->state.original_mode))) ERR("Failed to restore display mode, hr %#x.\n", hr);
if (swapchain->state.desc.flags & WINED3D_SWAPCHAIN_RESTORE_WINDOW_RECT) { wined3d_swapchain_state_restore_from_fullscreen(&swapchain->state, - swapchain->state.device_window, &swapchain->original_window_rect); + swapchain->state.device_window, &swapchain->state.original_window_rect); wined3d_device_release_focus_window(swapchain->device); } } @@ -736,16 +736,53 @@ void swapchain_set_max_frame_latency(struct wined3d_swapchain *swapchain, const swapchain->max_frame_latency = device->max_frame_latency >= 2 ? device->max_frame_latency - 1 : 1; }
-static enum wined3d_format_id adapter_format_from_backbuffer_format(struct wined3d_swapchain *swapchain, +static enum wined3d_format_id adapter_format_from_backbuffer_format(const struct wined3d_adapter *adapter, enum wined3d_format_id format_id) { - const struct wined3d_adapter *adapter = swapchain->device->adapter; const struct wined3d_format *backbuffer_format;
backbuffer_format = wined3d_get_format(adapter, format_id, WINED3D_BIND_RENDER_TARGET); return pixelformat_for_depth(backbuffer_format->byte_count * CHAR_BIT); }
+static HRESULT wined3d_swapchain_state_init(struct wined3d_swapchain_state *state, + const struct wined3d_swapchain_desc *desc, HWND window, + struct wined3d *wined3d, unsigned int adapter_idx) +{ + HRESULT hr; + + state->desc = *desc; + + if (FAILED(hr = wined3d_get_adapter_display_mode(wined3d, adapter_idx, &state->original_mode, NULL))) + { + ERR("Failed to get current display mode, hr %#x.\n", hr); + return hr; + } + + if (!desc->windowed) + { + if (desc->flags & WINED3D_SWAPCHAIN_ALLOW_MODE_SWITCH) + { + struct wined3d_adapter *adapter = wined3d->adapters[adapter_idx]; + + state->d3d_mode.width = desc->backbuffer_width; + state->d3d_mode.height = desc->backbuffer_height; + state->d3d_mode.format_id = adapter_format_from_backbuffer_format(adapter, desc->backbuffer_format); + state->d3d_mode.refresh_rate = desc->refresh_rate; + state->d3d_mode.scanline_ordering = WINED3D_SCANLINE_ORDERING_UNKNOWN; + } + else + { + state->d3d_mode = state->original_mode; + } + } + + GetWindowRect(window, &state->original_window_rect); + state->device_window = window; + + return hr; +} + static HRESULT swapchain_init(struct wined3d_swapchain *swapchain, struct wined3d_device *device, struct wined3d_swapchain_desc *desc, void *parent, const struct wined3d_parent_ops *parent_ops) { @@ -775,24 +812,17 @@ static HRESULT swapchain_init(struct wined3d_swapchain *swapchain, struct wined3 swapchain->swapchain_ops = &swapchain_gl_ops;
window = desc->device_window ? desc->device_window : device->create_parms.focus_window; + if (FAILED(hr = wined3d_swapchain_state_init(&swapchain->state, desc, window, device->wined3d, adapter->ordinal))) + return hr;
swapchain->device = device; swapchain->parent = parent; swapchain->parent_ops = parent_ops; swapchain->ref = 1; swapchain->win_handle = window; - swapchain->state.device_window = window; swapchain->swap_interval = WINED3D_SWAP_INTERVAL_DEFAULT; swapchain_set_max_frame_latency(swapchain, device);
- if (FAILED(hr = wined3d_get_adapter_display_mode(device->wined3d, - adapter->ordinal, &swapchain->original_mode, NULL))) - { - ERR("Failed to get current display mode, hr %#x.\n", hr); - goto err; - } - GetWindowRect(window, &swapchain->original_window_rect); - GetClientRect(window, &client_rect); if (desc->windowed) { @@ -811,8 +841,8 @@ static HRESULT swapchain_init(struct wined3d_swapchain *swapchain, struct wined3
if (desc->backbuffer_format == WINED3DFMT_UNKNOWN) { - desc->backbuffer_format = swapchain->original_mode.format_id; - TRACE("Updating format to %s.\n", debug_d3dformat(swapchain->original_mode.format_id)); + desc->backbuffer_format = swapchain->state.original_mode.format_id; + TRACE("Updating format to %s.\n", debug_d3dformat(swapchain->state.original_mode.format_id)); } } else @@ -863,30 +893,16 @@ static HRESULT swapchain_init(struct wined3d_swapchain *swapchain, struct wined3 /* MSDN says we're only allowed a single fullscreen swapchain per device, * so we should really check to see if there is a fullscreen swapchain * already. Does a single head count as full screen? */ - if (!desc->windowed) + if (!desc->windowed && desc->flags & WINED3D_SWAPCHAIN_ALLOW_MODE_SWITCH) { - if (desc->flags & WINED3D_SWAPCHAIN_ALLOW_MODE_SWITCH) - { - /* Change the display settings */ - swapchain->d3d_mode.width = desc->backbuffer_width; - swapchain->d3d_mode.height = desc->backbuffer_height; - swapchain->d3d_mode.format_id = adapter_format_from_backbuffer_format(swapchain, - desc->backbuffer_format); - swapchain->d3d_mode.refresh_rate = desc->refresh_rate; - swapchain->d3d_mode.scanline_ordering = WINED3D_SCANLINE_ORDERING_UNKNOWN; - - if (FAILED(hr = wined3d_set_adapter_display_mode(device->wined3d, - adapter->ordinal, &swapchain->d3d_mode))) - { - WARN("Failed to set display mode, hr %#x.\n", hr); - goto err; - } - displaymode_set = TRUE; - } - else + /* Change the display settings */ + if (FAILED(hr = wined3d_set_adapter_display_mode(device->wined3d, + adapter->ordinal, &swapchain->state.d3d_mode))) { - swapchain->d3d_mode = swapchain->original_mode; + WARN("Failed to set display mode, hr %#x.\n", hr); + goto err; } + displaymode_set = TRUE; }
if (swapchain->state.desc.backbuffer_count > 0) @@ -963,7 +979,7 @@ err: if (displaymode_set) { if (FAILED(wined3d_set_adapter_display_mode(device->wined3d, - adapter->ordinal, &swapchain->original_mode))) + adapter->ordinal, &swapchain->state.original_mode))) ERR("Failed to restore display mode.\n"); ClipCursor(NULL); } @@ -1184,7 +1200,7 @@ void wined3d_swapchain_activate(struct wined3d_swapchain *swapchain, BOOL activa if (device->wined3d->flags & WINED3D_RESTORE_MODE_ON_ACTIVATE) { if (FAILED(wined3d_set_adapter_display_mode(device->wined3d, - device->adapter->ordinal, &swapchain->d3d_mode))) + device->adapter->ordinal, &swapchain->state.d3d_mode))) ERR("Failed to set display mode.\n"); }
@@ -1272,7 +1288,7 @@ HRESULT CDECL wined3d_swapchain_resize_buffers(struct wined3d_swapchain *swapcha { if (!desc->windowed) return WINED3DERR_INVALIDCALL; - format_id = swapchain->original_mode.format_id; + format_id = swapchain->state.original_mode.format_id; }
if (format_id != desc->backbuffer_format) @@ -1500,15 +1516,15 @@ void wined3d_swapchain_state_restore_from_fullscreen(struct wined3d_swapchain_st state->exstyle = 0; }
-HRESULT CDECL wined3d_swapchain_set_fullscreen(struct wined3d_swapchain *swapchain, - const struct wined3d_swapchain_desc *swapchain_desc, const struct wined3d_display_mode *mode) +HRESULT CDECL wined3d_swapchain_state_set_fullscreen(struct wined3d_swapchain_state *state, + const struct wined3d_swapchain_desc *swapchain_desc, struct wined3d *wined3d, + unsigned int adapter_idx, const struct wined3d_display_mode *mode) { - struct wined3d_swapchain_state *state = &swapchain->state; - struct wined3d_device *device = swapchain->device; struct wined3d_display_mode actual_mode; HRESULT hr;
- TRACE("swapchain %p, desc %p, mode %p.\n", swapchain, swapchain_desc, mode); + TRACE("state %p, swapchain_desc %p, wined3d %p, adapter_idx %u, mode %p.\n", + state, swapchain_desc, wined3d, adapter_idx, mode);
if (state->desc.flags & WINED3D_SWAPCHAIN_ALLOW_MODE_SWITCH) { @@ -1520,21 +1536,22 @@ HRESULT CDECL wined3d_swapchain_set_fullscreen(struct wined3d_swapchain *swapcha { if (!swapchain_desc->windowed) { + const struct wined3d_adapter *adapter = wined3d->adapters[adapter_idx]; + actual_mode.width = swapchain_desc->backbuffer_width; actual_mode.height = swapchain_desc->backbuffer_height; actual_mode.refresh_rate = swapchain_desc->refresh_rate; - actual_mode.format_id = adapter_format_from_backbuffer_format(swapchain, + actual_mode.format_id = adapter_format_from_backbuffer_format(adapter, swapchain_desc->backbuffer_format); actual_mode.scanline_ordering = WINED3D_SCANLINE_ORDERING_UNKNOWN; } else { - actual_mode = swapchain->original_mode; + actual_mode = state->original_mode; } }
- if (FAILED(hr = wined3d_swapchain_state_set_display_mode(state, - device->wined3d, device->adapter->ordinal, &actual_mode))) + if (FAILED(hr = wined3d_swapchain_state_set_display_mode(state, wined3d, adapter_idx, &actual_mode))) return hr; } else @@ -1542,8 +1559,7 @@ HRESULT CDECL wined3d_swapchain_set_fullscreen(struct wined3d_swapchain *swapcha if (mode) WARN("WINED3D_SWAPCHAIN_ALLOW_MODE_SWITCH is not set, ignoring mode.\n");
- if (FAILED(hr = wined3d_get_adapter_display_mode(device->wined3d, device->adapter->ordinal, - &actual_mode, NULL))) + if (FAILED(hr = wined3d_get_adapter_display_mode(wined3d, adapter_idx, &actual_mode, NULL))) { ERR("Failed to get display mode, hr %#x.\n", hr); return WINED3DERR_INVALIDCALL; @@ -1558,13 +1574,12 @@ HRESULT CDECL wined3d_swapchain_set_fullscreen(struct wined3d_swapchain *swapcha if (state->desc.windowed) { /* Switch from windowed to fullscreen */ - if (FAILED(hr = wined3d_swapchain_state_setup_fullscreen(state, - state->device_window, width, height))) + if (FAILED(hr = wined3d_swapchain_state_setup_fullscreen(state, state->device_window, width, height))) return hr; } else { - HWND window = swapchain->state.device_window; + HWND window = state->device_window; BOOL filter;
/* Fullscreen -> fullscreen mode change */ @@ -1573,14 +1588,14 @@ HRESULT CDECL wined3d_swapchain_set_fullscreen(struct wined3d_swapchain *swapcha ShowWindow(window, SW_SHOW); wined3d_filter_messages(window, filter); } - swapchain->d3d_mode = actual_mode; + state->d3d_mode = actual_mode; } else if (!state->desc.windowed) { /* Fullscreen -> windowed switch */ RECT *window_rect = NULL; if (state->desc.flags & WINED3D_SWAPCHAIN_RESTORE_WINDOW_RECT) - window_rect = &swapchain->original_window_rect; + window_rect = &state->original_window_rect; wined3d_swapchain_state_restore_from_fullscreen(state, state->device_window, window_rect); }
@@ -1595,19 +1610,23 @@ void CDECL wined3d_swapchain_state_destroy(struct wined3d_swapchain_state *state }
HRESULT CDECL wined3d_swapchain_state_create(const struct wined3d_swapchain_desc *desc, - HWND window, struct wined3d_swapchain_state **state) + HWND window, struct wined3d *wined3d, unsigned int adapter_idx, struct wined3d_swapchain_state **state) { struct wined3d_swapchain_state *s; + HRESULT hr; + + TRACE("desc %p, window %p, wined3d %p, adapter_idx %u, state %p.\n", + desc, window, wined3d, adapter_idx, state);
TRACE("desc %p, window %p, state %p.\n", desc, window, state);
if (!(s = heap_alloc_zero(sizeof(*s)))) return E_OUTOFMEMORY;
- s->desc = *desc; - s->device_window = window; + if (FAILED(hr = wined3d_swapchain_state_init(s, desc, window, wined3d, adapter_idx))) + return hr;
*state = s;
- return WINED3D_OK; + return hr; } diff --git a/dlls/wined3d/wined3d.spec b/dlls/wined3d/wined3d.spec index 01e466e0147..edd4a70d979 100644 --- a/dlls/wined3d/wined3d.spec +++ b/dlls/wined3d/wined3d.spec @@ -273,14 +273,14 @@ @ cdecl wined3d_swapchain_incref(ptr) @ cdecl wined3d_swapchain_present(ptr ptr ptr ptr long long) @ cdecl wined3d_swapchain_resize_buffers(ptr long long long long long long) -@ cdecl wined3d_swapchain_set_fullscreen(ptr ptr ptr) @ cdecl wined3d_swapchain_set_gamma_ramp(ptr long ptr) @ cdecl wined3d_swapchain_set_palette(ptr ptr) @ cdecl wined3d_swapchain_set_window(ptr ptr)
-@ cdecl wined3d_swapchain_state_create(ptr ptr ptr) +@ cdecl wined3d_swapchain_state_create(ptr ptr ptr long ptr) @ cdecl wined3d_swapchain_state_destroy(ptr) @ cdecl wined3d_swapchain_state_resize_target(ptr ptr long ptr) +@ cdecl wined3d_swapchain_state_set_fullscreen(ptr ptr ptr long ptr)
@ cdecl wined3d_texture_add_dirty_region(ptr long ptr) @ cdecl wined3d_texture_blt(ptr long ptr ptr long ptr long ptr long) diff --git a/dlls/wined3d/wined3d_main.c b/dlls/wined3d/wined3d_main.c index 360d6d51962..132c9782def 100644 --- a/dlls/wined3d/wined3d_main.c +++ b/dlls/wined3d/wined3d_main.c @@ -565,7 +565,8 @@ static LRESULT CALLBACK wined3d_hook_proc(int code, WPARAM wparam, LPARAM lparam
wined3d_swapchain_get_desc(swapchain, &swapchain_desc); swapchain_desc.windowed = !swapchain_desc.windowed; - wined3d_swapchain_set_fullscreen(swapchain, &swapchain_desc, NULL); + wined3d_swapchain_state_set_fullscreen(&swapchain->state, &swapchain_desc, + swapchain->device->wined3d, swapchain->device->adapter->ordinal, NULL);
wined3d_wndproc_mutex_unlock();
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 5ddf066878a..03a3afb85a8 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -4178,6 +4178,9 @@ struct wined3d_swapchain_state { struct wined3d_swapchain_desc desc;
+ struct wined3d_display_mode original_mode, d3d_mode; + RECT original_window_rect; + /* Window styles to restore when switching fullscreen mode. */ LONG style; LONG exstyle; @@ -4206,8 +4209,6 @@ struct wined3d_swapchain
struct wined3d_texture **back_buffers; struct wined3d_texture *front_buffer; - struct wined3d_display_mode original_mode, d3d_mode; - RECT original_window_rect; struct wined3d_gamma_ramp orig_gamma; BOOL render_to_fbo, reapply_mode; const struct wined3d_format *ds_format; diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h index bae2cf86184..3e46c23c145 100644 --- a/include/wine/wined3d.h +++ b/include/wine/wined3d.h @@ -2684,18 +2684,19 @@ HRESULT __cdecl wined3d_swapchain_present(struct wined3d_swapchain *swapchain, c HRESULT __cdecl wined3d_swapchain_resize_buffers(struct wined3d_swapchain *swapchain, unsigned int buffer_count, unsigned int width, unsigned int height, enum wined3d_format_id format_id, enum wined3d_multisample_type multisample_type, unsigned int multisample_quality); -HRESULT __cdecl wined3d_swapchain_set_fullscreen(struct wined3d_swapchain *swapchain, - const struct wined3d_swapchain_desc *desc, const struct wined3d_display_mode *mode); HRESULT __cdecl wined3d_swapchain_set_gamma_ramp(const struct wined3d_swapchain *swapchain, DWORD flags, const struct wined3d_gamma_ramp *ramp); void __cdecl wined3d_swapchain_set_palette(struct wined3d_swapchain *swapchain, struct wined3d_palette *palette); void __cdecl wined3d_swapchain_set_window(struct wined3d_swapchain *swapchain, HWND window);
HRESULT __cdecl wined3d_swapchain_state_create(const struct wined3d_swapchain_desc *desc, - HWND window, struct wined3d_swapchain_state **state); + HWND window, struct wined3d *wined3d, unsigned int adapter_idx, struct wined3d_swapchain_state **state); void __cdecl wined3d_swapchain_state_destroy(struct wined3d_swapchain_state *state); HRESULT __cdecl wined3d_swapchain_state_resize_target(struct wined3d_swapchain_state *state, struct wined3d *wined3d, unsigned int adapter_idx, const struct wined3d_display_mode *mode); +HRESULT __cdecl wined3d_swapchain_state_set_fullscreen(struct wined3d_swapchain_state *state, + const struct wined3d_swapchain_desc *desc, struct wined3d *wined3d, + unsigned int adapter_idx, const struct wined3d_display_mode *mode);
HRESULT __cdecl wined3d_texture_add_dirty_region(struct wined3d_texture *texture, UINT layer, const struct wined3d_box *dirty_region);
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=54972
Your paranoid android.
=== wvistau64_zh_CN (32 bit report) ===
dxgi: dxgi.c:5456: Test failed: Test 0: Got unexpected fullscreen 0. dxgi.c:5456: Test failed: Test 1: Got unexpected fullscreen 0x1. dxgi.c:5456: Test failed: Test 2: Got unexpected fullscreen 0x1. dxgi.c:5456: Test failed: Test 3: Got unexpected fullscreen 0x1. dxgi.c:5456: Test failed: Test 5: Got unexpected fullscreen 0x1. dxgi.c:5456: Test failed: Test 6: Got unexpected fullscreen 0. dxgi.c:5456: Test failed: Test 7: Got unexpected fullscreen 0x1. dxgi.c:5456: Test failed: Test 8: Got unexpected fullscreen 0. dxgi.c:5456: Test failed: Test 9: Got unexpected fullscreen 0x1.
=== debian10 (build log) ===
error: patch failed: dlls/wined3d/swapchain.c:85 error: patch failed: dlls/wined3d/wined3d_private.h:4183 error: patch failed: dlls/wined3d/device.c:5404 error: patch failed: dlls/wined3d/swapchain.c:86 error: patch failed: dlls/wined3d/wined3d_private.h:4181 error: patch failed: dlls/wined3d/swapchain.c:80 error: patch failed: dlls/wined3d/wined3d_private.h:4178 Task: Patch failed to apply
=== debian10 (build log) ===
error: patch failed: dlls/wined3d/swapchain.c:85 error: patch failed: dlls/wined3d/wined3d_private.h:4183 error: patch failed: dlls/wined3d/device.c:5404 error: patch failed: dlls/wined3d/swapchain.c:86 error: patch failed: dlls/wined3d/wined3d_private.h:4181 error: patch failed: dlls/wined3d/swapchain.c:80 error: patch failed: dlls/wined3d/wined3d_private.h:4178 Task: Patch failed to apply