Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- dlls/dxgi/dxgi_private.h | 2 ++ dlls/dxgi/output.c | 61 +++++++++++++++++++++++++++++++++++++++ dlls/dxgi/swapchain.c | 62 +++++++++++++++++++++++++++++++++++++--- 3 files changed, 121 insertions(+), 4 deletions(-)
diff --git a/dlls/dxgi/dxgi_private.h b/dlls/dxgi/dxgi_private.h index 553eace..9cb43b8 100644 --- a/dlls/dxgi/dxgi_private.h +++ b/dlls/dxgi/dxgi_private.h @@ -148,6 +148,8 @@ struct dxgi_output };
HRESULT dxgi_output_create(struct dxgi_adapter *adapter, struct dxgi_output **output) DECLSPEC_HIDDEN; +HRESULT dxgi_output_set_display_mode(IDXGIOutput *iface, DXGI_MODE_DESC *target_mode_desc) DECLSPEC_HIDDEN; +HRESULT dxgi_output_get_display_mode(IDXGIOutput *iface, DXGI_MODE_DESC *mode_desc) DECLSPEC_HIDDEN;
/* IDXGIAdapter */ struct dxgi_adapter diff --git a/dlls/dxgi/output.c b/dlls/dxgi/output.c index 123dee8..0b4d1b6 100644 --- a/dlls/dxgi/output.c +++ b/dlls/dxgi/output.c @@ -539,3 +539,64 @@ HRESULT dxgi_output_create(struct dxgi_adapter *adapter, struct dxgi_output **ou dxgi_output_init(*output, adapter); return S_OK; } + +HRESULT dxgi_output_set_display_mode(IDXGIOutput *iface, DXGI_MODE_DESC *target_mode_desc) +{ + struct wined3d_display_mode wined3d_mode; + struct dxgi_output *target; + struct dxgi_adapter *adapter; + struct wined3d *wined3d; + HRESULT hr; + + target = impl_from_IDXGIOutput4((IDXGIOutput4 *)iface); + adapter = target->adapter; + wined3d = adapter->factory->wined3d; + + wined3d_display_mode_from_dxgi(&wined3d_mode, target_mode_desc); + + if (FAILED(hr = dxgi_output_find_closest_matching_mode(target, &wined3d_mode, NULL))) + WARN("Failed to find closest matching mode, hr %#x.\n", hr); + else /* Copy the actual mode back to the caller */ + dxgi_mode_from_wined3d(target_mode_desc, &wined3d_mode); + + wined3d_mutex_lock(); + hr = wined3d_set_adapter_display_mode(wined3d, adapter->ordinal, &wined3d_mode); + wined3d_mutex_unlock(); + + if (FAILED(hr)) + { + WARN("Failed to set display mode, hr %#x.\n", hr); + return DXGI_ERROR_INVALID_CALL; + } + + return S_OK; +} + +HRESULT dxgi_output_get_display_mode(IDXGIOutput *iface, DXGI_MODE_DESC *mode_desc) +{ + struct wined3d_display_mode wined3d_mode; + struct dxgi_output *target; + struct dxgi_adapter *adapter; + struct wined3d *wined3d; + HRESULT hr; + + target = impl_from_IDXGIOutput4((IDXGIOutput4 *)iface); + adapter = target->adapter; + wined3d = adapter->factory->wined3d; + + wined3d_mutex_lock(); + hr = wined3d_get_adapter_display_mode(wined3d, adapter->ordinal, &wined3d_mode, NULL); + wined3d_mutex_unlock(); + + if (FAILED(hr)) + { + ERR("Failed to get display mode, hr %#x.\n", hr); + return hr; + } + + dxgi_mode_from_wined3d(mode_desc, &wined3d_mode); + + TRACE("Returning %s.\n", debug_dxgi_mode(mode_desc)); + + return S_OK; +} diff --git a/dlls/dxgi/swapchain.c b/dlls/dxgi/swapchain.c index 4f01d9c..b060a30 100644 --- a/dlls/dxgi/swapchain.c +++ b/dlls/dxgi/swapchain.c @@ -501,11 +501,65 @@ static HRESULT STDMETHODCALLTYPE d3d11_swapchain_ResizeBuffers(IDXGISwapChain1 * return hr; }
+static HRESULT dxgi_resize_target(IDXGISwapChain1 *iface, + const DXGI_SWAP_CHAIN_DESC *desc, const DXGI_MODE_DESC *mode) +{ + RECT original_window_rect, window_rect; + HWND window = desc->OutputWindow; + HRESULT hr; + + TRACE("iface %p, desc %p, mode %p.\n", iface, desc, mode); + + if (desc->Windowed) + { + SetRect(&window_rect, 0, 0, mode->Width, mode->Height); + AdjustWindowRectEx(&window_rect, + GetWindowLongW(window, GWL_STYLE), FALSE, + GetWindowLongW(window, GWL_EXSTYLE)); + SetRect(&window_rect, 0, 0, + window_rect.right - window_rect.left, window_rect.bottom - window_rect.top); + GetWindowRect(window, &original_window_rect); + OffsetRect(&window_rect, original_window_rect.left, original_window_rect.top); + } + else + { + DXGI_MODE_DESC actual_mode; + IDXGIOutput *target; + + if (FAILED(hr = IDXGISwapChain1_GetContainingOutput(iface, &target))) + { + WARN("Failed to get output, hr %#x.\n", hr); + return hr; + } + + if (desc->Flags & DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH) + { + actual_mode = *mode; + hr = dxgi_output_set_display_mode(target, &actual_mode); + } + else + { + hr = dxgi_output_get_display_mode(target, &actual_mode); + } + + IDXGIOutput_Release(target); + + if(FAILED(hr)) + return hr; + + SetRect(&window_rect, 0, 0, actual_mode.Width, actual_mode.Height); + } + + MoveWindow(window, window_rect.left, window_rect.top, + window_rect.right - window_rect.left, window_rect.bottom - window_rect.top, TRUE); + + return S_OK; +} + static HRESULT STDMETHODCALLTYPE d3d11_swapchain_ResizeTarget(IDXGISwapChain1 *iface, const DXGI_MODE_DESC *target_mode_desc) { - struct d3d11_swapchain *swapchain = d3d11_swapchain_from_IDXGISwapChain1(iface); - struct wined3d_display_mode mode; + struct DXGI_SWAP_CHAIN_DESC swap_chain_desc;
TRACE("iface %p, target_mode_desc %p.\n", iface, target_mode_desc);
@@ -520,9 +574,9 @@ static HRESULT STDMETHODCALLTYPE d3d11_swapchain_ResizeTarget(IDXGISwapChain1 *i if (target_mode_desc->Scaling) FIXME("Ignoring scaling %#x.\n", target_mode_desc->Scaling);
- wined3d_display_mode_from_dxgi(&mode, target_mode_desc); + d3d11_swapchain_GetDesc(iface, &swap_chain_desc);
- return wined3d_swapchain_resize_target(swapchain->wined3d_swapchain, &mode); + return dxgi_resize_target(iface, &swap_chain_desc, target_mode_desc); }
static HRESULT STDMETHODCALLTYPE d3d11_swapchain_GetContainingOutput(IDXGISwapChain1 *iface, IDXGIOutput **output)