[PATCH v2 4/6] dxgi: Implement d3d12_swapchain_GetFullscreenState() and d3d12_swapchain_SetFullscreenState().

Conor McCarthy cmccarthy at codeweavers.com
Mon Jun 24 09:22:19 CDT 2019


Signed-off-by: Conor McCarthy <cmccarthy at codeweavers.com>
---
 dlls/dxgi/swapchain.c | 150 ++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 146 insertions(+), 4 deletions(-)

diff --git a/dlls/dxgi/swapchain.c b/dlls/dxgi/swapchain.c
index 86659d4..c623b95 100644
--- a/dlls/dxgi/swapchain.c
+++ b/dlls/dxgi/swapchain.c
@@ -1084,8 +1084,12 @@ struct d3d12_swapchain
     IWineDXGIFactory *factory;
 
     HWND window;
+    IDXGIOutput *target;
     DXGI_SWAP_CHAIN_DESC1 desc;
     DXGI_SWAP_CHAIN_FULLSCREEN_DESC fullscreen_desc;
+    struct wined3d_fullscreen_state fullscreen_state;
+    DXGI_MODE_DESC original_mode;
+    RECT orig_window_rect;
 };
 
 static DXGI_FORMAT dxgi_format_from_vk_format(VkFormat vk_format)
@@ -2177,17 +2181,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_fullscreen_setup_window(&swapchain->fullscreen_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_fullscreen_restore_window(&swapchain->fullscreen_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)
@@ -2316,6 +2425,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)))
@@ -2756,6 +2871,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;
 
@@ -2862,6 +2978,26 @@ static HRESULT d3d12_swapchain_init(struct d3d12_swapchain *swapchain, IWineDXGI
     return S_OK;
 }
 
+static HRESULT d3d12_swapchain_fullscreen_init(struct d3d12_swapchain *swapchain)
+{
+    IDXGISwapChain3 *iface = &swapchain->IDXGISwapChain3_iface;
+    IDXGIOutput *output;
+    HRESULT hr;
+
+    if (FAILED(hr = d3d12_swapchain_GetContainingOutput(iface, &output)))
+    {
+        ERR("Failed to get containing output, hr %#x.\n", hr);
+        return hr;
+    }
+
+    if (FAILED(hr = dxgi_output_get_display_mode(output, &swapchain->original_mode)))
+        ERR("Failed to get current display mode, hr %#x.\n", hr);
+
+    IDXGIOutput_Release(output);
+
+    return hr;
+}
+
 HRESULT d3d12_swapchain_create(IWineDXGIFactory *factory, ID3D12CommandQueue *queue, HWND window,
         const DXGI_SWAP_CHAIN_DESC1 *swapchain_desc, const DXGI_SWAP_CHAIN_FULLSCREEN_DESC *fullscreen_desc,
         IDXGISwapChain1 **swapchain)
@@ -2899,6 +3035,12 @@ HRESULT d3d12_swapchain_create(IWineDXGIFactory *factory, ID3D12CommandQueue *qu
         return hr;
     }
 
+    if(FAILED(hr = d3d12_swapchain_fullscreen_init(object)))
+    {
+        heap_free(object);
+        return hr;
+    }
+
     TRACE("Created swapchain %p.\n", object);
 
     *swapchain = (IDXGISwapChain1 *)&object->IDXGISwapChain3_iface;
-- 
2.21.0




More information about the wine-devel mailing list