[PATCH v4 4/6] dxgi: Implement d3d12_swapchain_GetFullscreenState() and d3d12_swapchain_SetFullscreenState().
Conor McCarthy
cmccarthy at codeweavers.com
Wed Jun 26 10:30:43 CDT 2019
Signed-off-by: Conor McCarthy <cmccarthy at codeweavers.com>
---
dlls/dxgi/swapchain.c | 144 ++++++++++++++++++++++++++++++++++++++++--
1 file changed, 140 insertions(+), 4 deletions(-)
diff --git a/dlls/dxgi/swapchain.c b/dlls/dxgi/swapchain.c
index b7a3cc0..457d187 100644
--- a/dlls/dxgi/swapchain.c
+++ b/dlls/dxgi/swapchain.c
@@ -1085,8 +1085,12 @@ struct d3d12_swapchain
IWineDXGIFactory *factory;
HWND window;
+ IDXGIOutput *target;
DXGI_SWAP_CHAIN_DESC1 desc;
DXGI_SWAP_CHAIN_FULLSCREEN_DESC fullscreen_desc;
+ struct wined3d_window_state window_state;
+ DXGI_MODE_DESC original_mode;
+ RECT orig_window_rect;
};
static DXGI_FORMAT dxgi_format_from_vk_format(VkFormat vk_format)
@@ -2178,17 +2182,122 @@ 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;
+ HWND window = swapchain->window;
+ DXGI_MODE_DESC actual_mode;
+ HRESULT hr = S_OK;
- 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 default target output for swapchain, hr %#x.\n", hr);
+ return hr;
+ }
+
+ wined3d_mutex_lock();
+
+ if (swapchain_desc->Flags & DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH)
+ {
+ if (fullscreen)
+ {
+ actual_mode.Width = swapchain_desc->Width;
+ actual_mode.Height = swapchain_desc->Height;
+ actual_mode.RefreshRate = fullscreen_desc->RefreshRate;
+ actual_mode.Format = swapchain_desc->Format;
+ actual_mode.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
+ }
+ else
+ {
+ actual_mode = swapchain->original_mode;
+ }
+
+ if (FAILED(hr = dxgi_output_set_display_mode(target, &actual_mode)))
+ goto release;
+ }
+ else
+ {
+ if (FAILED(hr = dxgi_output_get_display_mode(target, &actual_mode)))
+ {
+ ERR("Failed to get display mode, hr %#x.\n", hr);
+ hr = DXGI_ERROR_INVALID_CALL;
+ goto release;
+ }
+ }
+
+ if (fullscreen)
+ {
+ if (fullscreen_desc->Windowed)
+ {
+ if (FAILED(hr = wined3d_window_setup_fullscreen(&swapchain->window_state,
+ window, actual_mode.Width, actual_mode.Height)))
+ goto release;
+ }
+ else
+ {
+ /* Fullscreen -> fullscreen mode change */
+ MoveWindow(window, 0, 0, actual_mode.Width, actual_mode.Height, TRUE);
+ ShowWindow(window, SW_SHOW);
+ }
+ }
+ else if (!fullscreen_desc->Windowed)
+ {
+ /* Fullscreen -> windowed switch */
+ wined3d_window_restore_from_fullscreen(&swapchain->window_state, window, &swapchain->orig_window_rect);
+ }
+
+ wined3d_mutex_unlock();
+ fullscreen_desc->Windowed = !fullscreen;
+
+ if (!fullscreen)
+ {
+ IDXGIOutput_Release(target);
+ target = NULL;
+ }
+
+ if (swapchain->target)
+ IDXGIOutput_Release(swapchain->target);
+ swapchain->target = target;
+
+ return S_OK;
+
+release:
+ wined3d_mutex_unlock();
+ IDXGIOutput_Release(target);
+
+ return DXGI_ERROR_NOT_CURRENTLY_AVAILABLE;
}
static HRESULT STDMETHODCALLTYPE d3d12_swapchain_GetFullscreenState(IDXGISwapChain3 *iface,
BOOL *fullscreen, IDXGIOutput **target)
{
- FIXME("iface %p, fullscreen %p, target %p stub!\n", iface, fullscreen, target);
+ struct d3d12_swapchain *swapchain = d3d12_swapchain_from_IDXGISwapChain3(iface);
- return E_NOTIMPL;
+ TRACE("iface %p, fullscreen %p, target %p.\n", iface, fullscreen, target);
+
+ if (fullscreen)
+ *fullscreen = !swapchain->fullscreen_desc.Windowed;
+
+ if (target)
+ {
+ *target = swapchain->target;
+ if (*target)
+ IDXGIOutput_AddRef(*target);
+ }
+
+ return S_OK;
}
static HRESULT STDMETHODCALLTYPE d3d12_swapchain_GetDesc(IDXGISwapChain3 *iface, DXGI_SWAP_CHAIN_DESC *desc)
@@ -2306,6 +2415,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)))
@@ -2752,6 +2867,7 @@ static HRESULT d3d12_swapchain_init(struct d3d12_swapchain *swapchain, IWineDXGI
swapchain->refcount = 1;
swapchain->window = window;
+ GetWindowRect(window, &swapchain->orig_window_rect);
swapchain->desc = *swapchain_desc;
swapchain->fullscreen_desc = *fullscreen_desc;
@@ -2865,6 +2981,7 @@ HRESULT d3d12_swapchain_create(IWineDXGIFactory *factory, ID3D12CommandQueue *qu
DXGI_SWAP_CHAIN_FULLSCREEN_DESC default_fullscreen_desc;
struct d3d12_swapchain *object;
ID3D12Device *device;
+ IDXGIOutput *output;
HRESULT hr;
if (swapchain_desc->Format == DXGI_FORMAT_UNKNOWN)
@@ -2895,11 +3012,30 @@ HRESULT d3d12_swapchain_create(IWineDXGIFactory *factory, ID3D12CommandQueue *qu
return hr;
}
+ if (FAILED(hr = d3d12_swapchain_GetContainingOutput(&object->IDXGISwapChain3_iface, &output)))
+ {
+ ERR("Failed to get containing output, hr %#x.\n", hr);
+ goto cleanup;
+ }
+
+ hr = dxgi_output_get_display_mode(output, &object->original_mode);
+ IDXGIOutput_Release(output);
+ if (FAILED(hr))
+ {
+ ERR("Failed to get current display mode, hr %#x.\n", hr);
+ goto cleanup;
+ }
+
TRACE("Created swapchain %p.\n", object);
*swapchain = (IDXGISwapChain1 *)&object->IDXGISwapChain3_iface;
return S_OK;
+
+cleanup:
+ d3d12_swapchain_destroy(object);
+ heap_free(object);
+ return hr;
}
#else
--
2.21.0
More information about the wine-devel
mailing list