[PATCH 3/3] dxgi: Support Alt+Enter for d3d12 swapchains.

Zhiyi Zhang zzhang at codeweavers.com
Tue Oct 6 08:30:59 CDT 2020


Signed-off-by: Zhiyi Zhang <zzhang at codeweavers.com>
---
 dlls/dxgi/swapchain.c  | 51 ++++++++++++++++++++++++++++++++++++++----
 dlls/dxgi/tests/dxgi.c | 16 ++++++-------
 2 files changed, 54 insertions(+), 13 deletions(-)

diff --git a/dlls/dxgi/swapchain.c b/dlls/dxgi/swapchain.c
index aa889bbe236..e74717056cb 100644
--- a/dlls/dxgi/swapchain.c
+++ b/dlls/dxgi/swapchain.c
@@ -1919,6 +1919,7 @@ static void d3d12_swapchain_destroy(struct d3d12_swapchain *swapchain)
 
     close_library(vulkan_module);
 
+    wined3d_swapchain_state_unregister(swapchain->state);
     wined3d_swapchain_state_destroy(swapchain->state);
 }
 
@@ -2289,18 +2290,37 @@ static HRESULT STDMETHODCALLTYPE d3d12_swapchain_GetFullscreenState(IDXGISwapCha
         BOOL *fullscreen, IDXGIOutput **target)
 {
     struct d3d12_swapchain *swapchain = d3d12_swapchain_from_IDXGISwapChain4(iface);
+    BOOL windowed;
+    HRESULT hr;
 
     TRACE("iface %p, fullscreen %p, target %p.\n", iface, fullscreen, target);
 
-    if (fullscreen)
+    if (fullscreen || target)
     {
         wined3d_mutex_lock();
-        *fullscreen = !wined3d_swapchain_state_is_windowed(swapchain->state);
+        windowed = wined3d_swapchain_state_is_windowed(swapchain->state);
         wined3d_mutex_unlock();
     }
 
-    if (target && (*target = swapchain->target))
-        IDXGIOutput_AddRef(*target);
+    if (fullscreen)
+        *fullscreen = !windowed;
+
+    if (target)
+    {
+        if (!windowed)
+        {
+            if (!swapchain->target && FAILED(hr = IDXGISwapChain4_GetContainingOutput(iface,
+                    &swapchain->target)))
+                return hr;
+
+            *target = swapchain->target;
+            IDXGIOutput_AddRef(*target);
+        }
+        else
+        {
+            *target = NULL;
+        }
+    }
 
     return S_OK;
 }
@@ -2936,6 +2956,24 @@ static BOOL init_vk_funcs(struct dxgi_vk_funcs *dxgi, VkInstance vk_instance, Vk
     return TRUE;
 }
 
+static void STDMETHODCALLTYPE d3d12_swapchain_windowed_state_changed(void *parent, BOOL windowed)
+{
+    struct d3d12_swapchain *swapchain = parent;
+
+    TRACE("parent %p, windowed %d.\n", parent, windowed);
+
+    if (windowed && swapchain->target)
+    {
+        IDXGIOutput_Release(swapchain->target);
+        swapchain->target = NULL;
+    }
+}
+
+static const struct wined3d_swapchain_state_parent_ops d3d12_swapchain_state_parent_ops =
+{
+    d3d12_swapchain_windowed_state_changed,
+};
+
 static HRESULT d3d12_swapchain_init(struct d3d12_swapchain *swapchain, IWineDXGIFactory *factory,
         ID3D12Device *device, ID3D12CommandQueue *queue, HWND window,
         const DXGI_SWAP_CHAIN_DESC1 *swapchain_desc, const DXGI_SWAP_CHAIN_FULLSCREEN_DESC *fullscreen_desc)
@@ -2944,6 +2982,7 @@ 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_factory *dxgi_factory;
     VkFenceCreateInfo fence_desc;
     uint32_t queue_family_index;
     VkSurfaceKHR vk_surface;
@@ -3025,6 +3064,10 @@ static HRESULT d3d12_swapchain_init(struct d3d12_swapchain *swapchain, IWineDXGI
         return hr;
     }
 
+    dxgi_factory = unsafe_impl_from_IDXGIFactory((IDXGIFactory *)factory);
+    wined3d_swapchain_state_register(swapchain->state, dxgi_factory->wined3d, swapchain,
+            &d3d12_swapchain_state_parent_ops);
+
     if (!fullscreen_desc->Windowed)
     {
         hr = wined3d_swapchain_state_set_fullscreen(swapchain->state, &wined3d_desc, NULL);
diff --git a/dlls/dxgi/tests/dxgi.c b/dlls/dxgi/tests/dxgi.c
index 5830426f756..c6ece51f2a8 100644
--- a/dlls/dxgi/tests/dxgi.c
+++ b/dlls/dxgi/tests/dxgi.c
@@ -2431,7 +2431,7 @@ static void test_get_containing_output(IUnknown *device, BOOL is_d3d12)
         flush_events();
         hr = IDXGISwapChain_GetFullscreenState(swapchain, &fullscreen, NULL);
         ok(hr == S_OK, "GetFullscreenState failed, hr %#x.\n", hr);
-        todo_wine_if(is_d3d12) ok(!fullscreen, "Expect swapchain not full screen.\n");
+        ok(!fullscreen, "Expect swapchain not full screen.\n");
 
         /* Move the swapchain output window to the second output */
         hr = IDXGIOutput_GetDesc(output2, &output_desc2);
@@ -2453,7 +2453,7 @@ static void test_get_containing_output(IUnknown *device, BOOL is_d3d12)
         ok(hr == S_OK, "GetDesc failed, hr %#x.\n", hr);
         hr = IDXGIOutput_GetDesc(output2, &output_desc2);
         ok(hr == S_OK, "GetDesc failed, hr %#x.\n", hr);
-        todo_wine_if(is_d3d12) ok(!lstrcmpW(output_desc.DeviceName, output_desc2.DeviceName),
+        ok(!lstrcmpW(output_desc.DeviceName, output_desc2.DeviceName),
                 "Expect device name %s, got %s.\n", wine_dbgstr_w(output_desc2.DeviceName),
                 wine_dbgstr_w(output_desc.DeviceName));
         IDXGIOutput_Release(output);
@@ -2465,7 +2465,7 @@ static void test_get_containing_output(IUnknown *device, BOOL is_d3d12)
         ok(hr == S_OK, "GetDesc failed, hr %#x.\n", hr);
         hr = IDXGIOutput_GetDesc(output2, &output_desc2);
         ok(hr == S_OK, "GetDesc failed, hr %#x.\n", hr);
-        todo_wine_if(is_d3d12) ok(!lstrcmpW(output_desc.DeviceName, output_desc2.DeviceName),
+        ok(!lstrcmpW(output_desc.DeviceName, output_desc2.DeviceName),
                 "Expect device name %s, got %s.\n", wine_dbgstr_w(output_desc2.DeviceName),
                 wine_dbgstr_w(output_desc.DeviceName));
 
@@ -6148,7 +6148,6 @@ static void test_window_association(IUnknown *device, BOOL is_d3d12)
         UINT flag;
         BOOL expect_fullscreen;
         BOOL broken_d3d10;
-        BOOL todo_on_d3d12;
     }
     tests[] =
     {
@@ -6162,15 +6161,15 @@ static void test_window_association(IUnknown *device, BOOL is_d3d12)
          * - Posting them hangs the posting thread. Another thread that keeps
          *   sending input is needed to avoid the hang. The hang is not
          *   because of flush_events(). */
-        {0, TRUE, FALSE, TRUE},
+        {0, TRUE},
         {0, FALSE},
         {DXGI_MWA_NO_WINDOW_CHANGES, FALSE},
         {DXGI_MWA_NO_WINDOW_CHANGES, FALSE},
-        {DXGI_MWA_NO_ALT_ENTER, FALSE, TRUE},
+        {DXGI_MWA_NO_ALT_ENTER},
         {DXGI_MWA_NO_ALT_ENTER, FALSE},
-        {DXGI_MWA_NO_PRINT_SCREEN, TRUE, FALSE, TRUE},
+        {DXGI_MWA_NO_PRINT_SCREEN, TRUE},
         {DXGI_MWA_NO_PRINT_SCREEN, FALSE},
-        {0, TRUE, FALSE, TRUE},
+        {0, TRUE},
         {0, FALSE}
     };
 
@@ -6272,7 +6271,6 @@ static void test_window_association(IUnknown *device, BOOL is_d3d12)
             output = NULL;
             hr = IDXGISwapChain_GetFullscreenState(swapchain, &fullscreen, &output);
             ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
-            todo_wine_if(is_d3d12 && tests[i].todo_on_d3d12)
             ok(fullscreen == tests[i].expect_fullscreen
                     || broken(tests[i].broken_d3d10 && fullscreen),
                     "Test %u: Got unexpected fullscreen %#x.\n", i, fullscreen);
-- 
2.25.1



More information about the wine-devel mailing list