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)
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- dlls/dxgi/swapchain.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-)
diff --git a/dlls/dxgi/swapchain.c b/dlls/dxgi/swapchain.c index b060a30..86659d4 100644 --- a/dlls/dxgi/swapchain.c +++ b/dlls/dxgi/swapchain.c @@ -2286,9 +2286,24 @@ static HRESULT STDMETHODCALLTYPE d3d12_swapchain_ResizeBuffers(IDXGISwapChain3 * static HRESULT STDMETHODCALLTYPE d3d12_swapchain_ResizeTarget(IDXGISwapChain3 *iface, const DXGI_MODE_DESC *target_mode_desc) { - FIXME("iface %p, target_mode_desc %p stub!\n", iface, target_mode_desc); + struct DXGI_SWAP_CHAIN_DESC swap_chain_desc;
- return E_NOTIMPL; + TRACE("iface %p, target_mode_desc %p.\n", iface, target_mode_desc); + + if (!target_mode_desc) + { + WARN("Invalid pointer.\n"); + return DXGI_ERROR_INVALID_CALL; + } + + TRACE("Mode: %s.\n", debug_dxgi_mode(target_mode_desc)); + + if (target_mode_desc->Scaling) + FIXME("Ignoring scaling %#x.\n", target_mode_desc->Scaling); + + d3d12_swapchain_GetDesc(iface, &swap_chain_desc); + + return dxgi_resize_target((IDXGISwapChain1 *)iface, &swap_chain_desc, target_mode_desc); }
static HRESULT STDMETHODCALLTYPE d3d12_swapchain_GetContainingOutput(IDXGISwapChain3 *iface,
On Fri, 21 Jun 2019 at 11:35, Conor McCarthy cmccarthy@codeweavers.com wrote:
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);
}
This is the only user of wined3d_swapchain_resize_target(), so in principle it could now be removed from wined3d. Whether that's a good idea depends to some extent on what we're going to do with the other swapchain functions. For example, wined3d_swapchain_set_fullscreen() is also used by wined3d internally, and has some interactions with the wined3d device, so in some regards it's a more interesting case. I.e., we wouldn't want to use one approach for wined3d_swapchain_resize_target(), and then another for wined3d_swapchain_set_fullscreen(), and perhaps a third for e.g. gamma control.
June 21, 2019 7:48 PM, "Henri Verbeet" hverbeet@gmail.com wrote:
This is the only user of wined3d_swapchain_resize_target(), so in principle it could now be removed from wined3d. Whether that's a good idea depends to some extent on what we're going to do with the other swapchain functions. For example, wined3d_swapchain_set_fullscreen() is also used by wined3d internally, and has some interactions with the wined3d device, so in some regards it's a more interesting case. I.e., we wouldn't want to use one approach for wined3d_swapchain_resize_target(), and then another for wined3d_swapchain_set_fullscreen(), and perhaps a third for e.g. gamma control.
While doing d3d12_swapchain_SetFullscreenState() I found that using the new helpers with d3d11 was messy without further refactoring of d3d11. I'll see what can be done with it. Testing d3d12_swapchain_ResizeTarget() needs the d3d12 fullscreen functions implemented first, so maybe it should all be one large patch.
On Fri, 21 Jun 2019 at 15:57, cmccarthy@codeweavers.com wrote:
While doing d3d12_swapchain_SetFullscreenState() I found that using the new helpers with d3d11 was messy without further refactoring of d3d11. I'll see what can be done with it. Testing d3d12_swapchain_ResizeTarget() needs the d3d12 fullscreen functions implemented first, so maybe it should all be one large patch.
I haven't seen the final patch of course, but "one large patch" is rarely the correct answer.
June 21, 2019 9:30 PM, "Henri Verbeet" hverbeet@gmail.com wrote:
I haven't seen the final patch of course, but "one large patch" is rarely the correct answer.
To clarify, I mean split into many parts as usual, but the d3d11 refactorings may mean they should all be submitted together. I'm not sure how that will pan out though.
On Fri, Jun 21, 2019 at 1:27 PM cmccarthy@codeweavers.com wrote:
While doing d3d12_swapchain_SetFullscreenState() I found that using the new helpers with d3d11 was messy without further refactoring of d3d11. I'll see what can be done with it. Testing d3d12_swapchain_ResizeTarget() needs the d3d12 fullscreen functions implemented first, so maybe it should all be one large patch.
Also, d3d12_swapchain_ResizeTarget() can be tested without SetFullscreenState(). It just needs some skips, and the skips are a bit ugly. See the attachment for an example.