[PATCH v3 2/2] dxgi: Update swapchain containing output after Alt+Enter was used to exit fullscreen.

Zhiyi Zhang zzhang at codeweavers.com
Fri Oct 9 04:56:53 CDT 2020


Signed-off-by: Zhiyi Zhang <zzhang at codeweavers.com>
---
v2: Supersede 194122. Put a struct wined3d_swapchain_state_parent in d3d/dxgi swapchains.
    struct wined3d_swapchain_state_parent is passed to wined3d_swapchain_create as a parameter
    and not in struct wined3d_swapchain_desc because puttting it in there will make some
    swapchain description struct conversion ugly. For example, wined3d_swapchain_desc_from_dxgi()
    needs to take in account of whether it's a d3d11 or d3d12 swapchain and then set corresponding
    wined3d_swapchain_state_parent unless we set the field outside of wined3d_swapchain_desc_from_dxgi(),
    which doesn't seem nice also.
v3: Supersede 194317. Fix a test failures.

 dlls/d3d8/d3d8_private.h       |  1 +
 dlls/d3d8/swapchain.c          | 16 ++++++++--
 dlls/d3d9/d3d9_private.h       |  1 +
 dlls/d3d9/swapchain.c          | 16 ++++++++--
 dlls/ddraw/ddraw.c             | 16 ++++++++--
 dlls/ddraw/ddraw_private.h     |  1 +
 dlls/dxgi/dxgi_private.h       |  1 +
 dlls/dxgi/swapchain.c          | 57 ++++++++++++++++++++++++++++++++--
 dlls/dxgi/tests/dxgi.c         | 13 ++++----
 dlls/wined3d/adapter_gl.c      |  9 +++---
 dlls/wined3d/adapter_vk.c      | 10 +++---
 dlls/wined3d/directx.c         | 10 +++---
 dlls/wined3d/swapchain.c       | 52 ++++++++++++++++++++-----------
 dlls/wined3d/wined3d.spec      |  4 +--
 dlls/wined3d/wined3d_private.h | 16 +++++++---
 include/wine/wined3d.h         | 20 ++++++++++--
 16 files changed, 187 insertions(+), 56 deletions(-)

diff --git a/dlls/d3d8/d3d8_private.h b/dlls/d3d8/d3d8_private.h
index e98746a13bd..bb25be16de0 100644
--- a/dlls/d3d8/d3d8_private.h
+++ b/dlls/d3d8/d3d8_private.h
@@ -185,6 +185,7 @@ struct d3d8_swapchain
     IDirect3DSwapChain8 IDirect3DSwapChain8_iface;
     LONG refcount;
     struct wined3d_swapchain *wined3d_swapchain;
+    struct wined3d_swapchain_state_parent state_parent;
     IDirect3DDevice8 *parent_device;
     unsigned int swap_interval;
 };
diff --git a/dlls/d3d8/swapchain.c b/dlls/d3d8/swapchain.c
index f08a19ca238..78db4fcaf24 100644
--- a/dlls/d3d8/swapchain.c
+++ b/dlls/d3d8/swapchain.c
@@ -156,6 +156,17 @@ static const struct wined3d_parent_ops d3d8_swapchain_wined3d_parent_ops =
     d3d8_swapchain_wined3d_object_released,
 };
 
+static void CDECL d3d8_swapchain_windowed_state_changed(struct wined3d_swapchain_state_parent *parent,
+        BOOL windowed)
+{
+    TRACE("parent %p, windowed %d.\n", parent, windowed);
+}
+
+static const struct wined3d_swapchain_state_parent_ops d3d8_swapchain_state_parent_ops =
+{
+    d3d8_swapchain_windowed_state_changed,
+};
+
 static HRESULT swapchain_init(struct d3d8_swapchain *swapchain, struct d3d8_device *device,
         struct wined3d_swapchain_desc *desc, unsigned int swap_interval)
 {
@@ -163,10 +174,11 @@ static HRESULT swapchain_init(struct d3d8_swapchain *swapchain, struct d3d8_devi
 
     swapchain->refcount = 1;
     swapchain->IDirect3DSwapChain8_iface.lpVtbl = &d3d8_swapchain_vtbl;
+    swapchain->state_parent.ops = &d3d8_swapchain_state_parent_ops;
     swapchain->swap_interval = swap_interval;
 
-    if (FAILED(hr = wined3d_swapchain_create(device->wined3d_device, desc, swapchain,
-            &d3d8_swapchain_wined3d_parent_ops, &swapchain->wined3d_swapchain)))
+    if (FAILED(hr = wined3d_swapchain_create(device->wined3d_device, desc, &swapchain->state_parent,
+            swapchain, &d3d8_swapchain_wined3d_parent_ops, &swapchain->wined3d_swapchain)))
     {
         WARN("Failed to create wined3d swapchain, hr %#x.\n", hr);
         return hr;
diff --git a/dlls/d3d9/d3d9_private.h b/dlls/d3d9/d3d9_private.h
index e78ce75a2f0..03ab10ad01b 100644
--- a/dlls/d3d9/d3d9_private.h
+++ b/dlls/d3d9/d3d9_private.h
@@ -162,6 +162,7 @@ struct d3d9_swapchain
     IDirect3DSwapChain9Ex IDirect3DSwapChain9Ex_iface;
     LONG refcount;
     struct wined3d_swapchain *wined3d_swapchain;
+    struct wined3d_swapchain_state_parent state_parent;
     IDirect3DDevice9Ex *parent_device;
     unsigned int swap_interval;
 };
diff --git a/dlls/d3d9/swapchain.c b/dlls/d3d9/swapchain.c
index 8d6cff982d3..0955b672c79 100644
--- a/dlls/d3d9/swapchain.c
+++ b/dlls/d3d9/swapchain.c
@@ -356,6 +356,17 @@ static const struct wined3d_parent_ops d3d9_swapchain_wined3d_parent_ops =
     d3d9_swapchain_wined3d_object_released,
 };
 
+static void CDECL d3d9_swapchain_windowed_state_changed(struct wined3d_swapchain_state_parent *parent,
+        BOOL windowed)
+{
+    TRACE("parent %p, windowed %d.\n", parent, windowed);
+}
+
+static const struct wined3d_swapchain_state_parent_ops d3d9_swapchain_state_parent_ops =
+{
+    d3d9_swapchain_windowed_state_changed,
+};
+
 static HRESULT swapchain_init(struct d3d9_swapchain *swapchain, struct d3d9_device *device,
         struct wined3d_swapchain_desc *desc, unsigned int swap_interval)
 {
@@ -363,10 +374,11 @@ static HRESULT swapchain_init(struct d3d9_swapchain *swapchain, struct d3d9_devi
 
     swapchain->refcount = 1;
     swapchain->IDirect3DSwapChain9Ex_iface.lpVtbl = &d3d9_swapchain_vtbl;
+    swapchain->state_parent.ops = &d3d9_swapchain_state_parent_ops;
     swapchain->swap_interval = swap_interval;
 
-    if (FAILED(hr = wined3d_swapchain_create(device->wined3d_device, desc, swapchain,
-            &d3d9_swapchain_wined3d_parent_ops, &swapchain->wined3d_swapchain)))
+    if (FAILED(hr = wined3d_swapchain_create(device->wined3d_device, desc, &swapchain->state_parent,
+            swapchain, &d3d9_swapchain_wined3d_parent_ops, &swapchain->wined3d_swapchain)))
     {
         WARN("Failed to create wined3d swapchain, hr %#x.\n", hr);
         return hr;
diff --git a/dlls/ddraw/ddraw.c b/dlls/ddraw/ddraw.c
index c3c335d978e..11a16f8d535 100644
--- a/dlls/ddraw/ddraw.c
+++ b/dlls/ddraw/ddraw.c
@@ -80,6 +80,17 @@ const struct wined3d_parent_ops ddraw_null_wined3d_parent_ops =
     ddraw_null_wined3d_object_destroyed,
 };
 
+static void CDECL ddraw_swapchain_windowed_state_changed(struct wined3d_swapchain_state_parent *parent,
+        BOOL windowed)
+{
+    TRACE("parent %p, windowed %d.\n", parent, windowed);
+}
+
+static const struct wined3d_swapchain_state_parent_ops ddraw_swapchain_state_parent_ops =
+{
+    ddraw_swapchain_windowed_state_changed,
+};
+
 static inline struct ddraw *impl_from_IDirectDraw(IDirectDraw *iface)
 {
     return CONTAINING_RECORD(iface, struct ddraw, IDirectDraw_iface);
@@ -577,7 +588,7 @@ static HRESULT ddraw_attach_d3d_device(struct ddraw *ddraw, HWND window,
 
     if (ddraw->flags & DDRAW_NO3D)
         return wined3d_swapchain_create(ddraw->wined3d_device, &swapchain_desc,
-                NULL, &ddraw_null_wined3d_parent_ops, wined3d_swapchain);
+                &ddraw->state_parent, NULL, &ddraw_null_wined3d_parent_ops, wined3d_swapchain);
 
     if (!window || window == GetDesktopWindow())
     {
@@ -605,7 +616,7 @@ static HRESULT ddraw_attach_d3d_device(struct ddraw *ddraw, HWND window,
      * recursive loop until ram or emulated video memory is full. */
     ddraw->flags |= DDRAW_D3D_INITIALIZED;
     if (FAILED(hr = wined3d_swapchain_create(ddraw->wined3d_device, &swapchain_desc,
-            NULL, &ddraw_null_wined3d_parent_ops, wined3d_swapchain)))
+            &ddraw->state_parent, NULL, &ddraw_null_wined3d_parent_ops, wined3d_swapchain)))
     {
         ddraw->flags &= ~DDRAW_D3D_INITIALIZED;
         DestroyWindow(window);
@@ -5105,6 +5116,7 @@ HRESULT ddraw_init(struct ddraw *ddraw, DWORD flags, enum wined3d_device_type de
     ddraw->IDirect3D3_iface.lpVtbl = &d3d3_vtbl;
     ddraw->IDirect3D7_iface.lpVtbl = &d3d7_vtbl;
     ddraw->device_parent.ops = &ddraw_wined3d_device_parent_ops;
+    ddraw->state_parent.ops = &ddraw_swapchain_state_parent_ops;
     ddraw->numIfaces = 1;
     ddraw->ref7 = 1;
 
diff --git a/dlls/ddraw/ddraw_private.h b/dlls/ddraw/ddraw_private.h
index 776f61e1024..6bbd62949ac 100644
--- a/dlls/ddraw/ddraw_private.h
+++ b/dlls/ddraw/ddraw_private.h
@@ -105,6 +105,7 @@ struct ddraw
     struct wined3d_texture *wined3d_frontbuffer;
     struct wined3d_texture *gdi_surface;
     struct wined3d_swapchain *wined3d_swapchain;
+    struct wined3d_swapchain_state_parent state_parent;
     HWND swapchain_window;
 
     /* DirectDraw things, which are not handled by WineD3D */
diff --git a/dlls/dxgi/dxgi_private.h b/dlls/dxgi/dxgi_private.h
index e43ee59461c..acba3544e39 100644
--- a/dlls/dxgi/dxgi_private.h
+++ b/dlls/dxgi/dxgi_private.h
@@ -177,6 +177,7 @@ struct d3d11_swapchain
     LONG refcount;
     struct wined3d_private_store private_store;
     struct wined3d_swapchain *wined3d_swapchain;
+    struct wined3d_swapchain_state_parent state_parent;
     IWineDXGIDevice *device;
     IDXGIFactory *factory;
 
diff --git a/dlls/dxgi/swapchain.c b/dlls/dxgi/swapchain.c
index 36beb84aa28..0f335a71cb7 100644
--- a/dlls/dxgi/swapchain.c
+++ b/dlls/dxgi/swapchain.c
@@ -811,6 +811,30 @@ static const struct wined3d_parent_ops d3d11_swapchain_wined3d_parent_ops =
     d3d11_swapchain_wined3d_object_released,
 };
 
+static inline struct d3d11_swapchain *d3d11_swapchain_from_wined3d_swapchain_state_parent(struct wined3d_swapchain_state_parent *parent)
+{
+    return CONTAINING_RECORD(parent, struct d3d11_swapchain, state_parent);
+}
+
+static void CDECL d3d11_swapchain_windowed_state_changed(struct wined3d_swapchain_state_parent *parent,
+        BOOL windowed)
+{
+    struct d3d11_swapchain *swapchain = d3d11_swapchain_from_wined3d_swapchain_state_parent(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 d3d11_swapchain_state_parent_ops =
+{
+    d3d11_swapchain_windowed_state_changed,
+};
+
 HRESULT d3d11_swapchain_init(struct d3d11_swapchain *swapchain, struct dxgi_device *device,
         struct wined3d_swapchain_desc *desc)
 {
@@ -840,6 +864,7 @@ HRESULT d3d11_swapchain_init(struct d3d11_swapchain *swapchain, struct dxgi_devi
     }
 
     swapchain->IDXGISwapChain1_iface.lpVtbl = &d3d11_swapchain_vtbl;
+    swapchain->state_parent.ops = &d3d11_swapchain_state_parent_ops;
     swapchain->refcount = 1;
     wined3d_mutex_lock();
     wined3d_private_store_init(&swapchain->private_store);
@@ -849,8 +874,8 @@ HRESULT d3d11_swapchain_init(struct d3d11_swapchain *swapchain, struct dxgi_devi
 
     fullscreen = !desc->windowed;
     desc->windowed = TRUE;
-    if (FAILED(hr = wined3d_swapchain_create(device->wined3d_device, desc, swapchain,
-            &d3d11_swapchain_wined3d_parent_ops, &swapchain->wined3d_swapchain)))
+    if (FAILED(hr = wined3d_swapchain_create(device->wined3d_device, desc, &swapchain->state_parent,
+            swapchain, &d3d11_swapchain_wined3d_parent_ops, &swapchain->wined3d_swapchain)))
     {
         WARN("Failed to create wined3d swapchain, hr %#x.\n", hr);
         goto cleanup;
@@ -1037,6 +1062,7 @@ struct d3d12_swapchain
     struct wined3d_private_store private_store;
 
     struct wined3d_swapchain_state *state;
+    struct wined3d_swapchain_state_parent state_parent;
 
     VkSwapchainKHR vk_swapchain;
     VkSurfaceKHR vk_surface;
@@ -2938,6 +2964,30 @@ static BOOL init_vk_funcs(struct dxgi_vk_funcs *dxgi, VkInstance vk_instance, Vk
     return TRUE;
 }
 
+static inline struct d3d12_swapchain *d3d12_swapchain_from_wined3d_swapchain_state_parent(struct wined3d_swapchain_state_parent *parent)
+{
+    return CONTAINING_RECORD(parent, struct d3d12_swapchain, state_parent);
+}
+
+static void CDECL d3d12_swapchain_windowed_state_changed(struct wined3d_swapchain_state_parent *parent,
+        BOOL windowed)
+{
+    struct d3d12_swapchain *swapchain = d3d12_swapchain_from_wined3d_swapchain_state_parent(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)
@@ -2967,6 +3017,7 @@ static HRESULT d3d12_swapchain_init(struct d3d12_swapchain *swapchain, IWineDXGI
     }
 
     swapchain->IDXGISwapChain4_iface.lpVtbl = &d3d12_swapchain_vtbl;
+    swapchain->state_parent.ops = &d3d12_swapchain_state_parent_ops;
     swapchain->refcount = 1;
 
     swapchain->window = window;
@@ -3024,7 +3075,7 @@ static HRESULT d3d12_swapchain_init(struct d3d12_swapchain *swapchain, IWineDXGI
 
     dxgi_factory = unsafe_impl_from_IDXGIFactory((IDXGIFactory *)factory);
     if (FAILED(hr = wined3d_swapchain_state_create(&wined3d_desc, window, dxgi_factory->wined3d,
-            &swapchain->state)))
+            &swapchain->state_parent, &swapchain->state)))
     {
         IDXGIOutput_Release(output);
         return hr;
diff --git a/dlls/dxgi/tests/dxgi.c b/dlls/dxgi/tests/dxgi.c
index 2838a025e57..bf798508a6d 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 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 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, 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}
     };
 
diff --git a/dlls/wined3d/adapter_gl.c b/dlls/wined3d/adapter_gl.c
index 5bf9d179e4d..140948beb6d 100644
--- a/dlls/wined3d/adapter_gl.c
+++ b/dlls/wined3d/adapter_gl.c
@@ -4590,19 +4590,20 @@ static void adapter_gl_copy_bo_address(struct wined3d_context *context,
     wined3d_context_gl_copy_bo_address(wined3d_context_gl(context), dst, src, size);
 }
 
-static HRESULT adapter_gl_create_swapchain(struct wined3d_device *device, struct wined3d_swapchain_desc *desc,
+static HRESULT adapter_gl_create_swapchain(struct wined3d_device *device,
+        struct wined3d_swapchain_desc *desc, struct wined3d_swapchain_state_parent *state_parent,
         void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_swapchain **swapchain)
 {
     struct wined3d_swapchain_gl *swapchain_gl;
     HRESULT hr;
 
-    TRACE("device %p, desc %p, parent %p, parent_ops %p, swapchain %p.\n",
-            device, desc, parent, parent_ops, swapchain);
+    TRACE("device %p, desc %p, state_parent %p, parent %p, parent_ops %p, swapchain %p.\n",
+            device, desc, state_parent, parent, parent_ops, swapchain);
 
     if (!(swapchain_gl = heap_alloc_zero(sizeof(*swapchain_gl))))
         return E_OUTOFMEMORY;
 
-    if (FAILED(hr = wined3d_swapchain_gl_init(swapchain_gl, device, desc, parent, parent_ops)))
+    if (FAILED(hr = wined3d_swapchain_gl_init(swapchain_gl, device, desc, state_parent, parent, parent_ops)))
     {
         WARN("Failed to initialise swapchain, hr %#x.\n", hr);
         heap_free(swapchain_gl);
diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c
index 5c219d45d3e..64850944040 100644
--- a/dlls/wined3d/adapter_vk.c
+++ b/dlls/wined3d/adapter_vk.c
@@ -1103,19 +1103,21 @@ static void adapter_vk_copy_bo_address(struct wined3d_context *context,
     adapter_vk_unmap_bo_address(context, src, 0, NULL);
 }
 
-static HRESULT adapter_vk_create_swapchain(struct wined3d_device *device, struct wined3d_swapchain_desc *desc,
+static HRESULT adapter_vk_create_swapchain(struct wined3d_device *device,
+        struct wined3d_swapchain_desc *desc, struct wined3d_swapchain_state_parent *state_parent,
         void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_swapchain **swapchain)
 {
     struct wined3d_swapchain_vk *swapchain_vk;
     HRESULT hr;
 
-    TRACE("device %p, desc %p, parent %p, parent_ops %p, swapchain %p.\n",
-            device, desc, parent, parent_ops, swapchain);
+    TRACE("device %p, desc %p, state_parent %p, parent %p, parent_ops %p, swapchain %p.\n",
+            device, desc, state_parent, parent, parent_ops, swapchain);
 
     if (!(swapchain_vk = heap_alloc_zero(sizeof(*swapchain_vk))))
         return E_OUTOFMEMORY;
 
-    if (FAILED(hr = wined3d_swapchain_vk_init(swapchain_vk, device, desc, parent, parent_ops)))
+    if (FAILED(hr = wined3d_swapchain_vk_init(swapchain_vk, device, desc, state_parent, parent,
+            parent_ops)))
     {
         WARN("Failed to initialise swapchain, hr %#x.\n", hr);
         heap_free(swapchain_vk);
diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c
index 0fa05a06be6..108a190bf61 100644
--- a/dlls/wined3d/directx.c
+++ b/dlls/wined3d/directx.c
@@ -2665,19 +2665,21 @@ static void adapter_no3d_copy_bo_address(struct wined3d_context *context,
     memcpy(dst->addr, src->addr, size);
 }
 
-static HRESULT adapter_no3d_create_swapchain(struct wined3d_device *device, struct wined3d_swapchain_desc *desc,
+static HRESULT adapter_no3d_create_swapchain(struct wined3d_device *device,
+        struct wined3d_swapchain_desc *desc, struct wined3d_swapchain_state_parent *state_parent,
         void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_swapchain **swapchain)
 {
     struct wined3d_swapchain *swapchain_no3d;
     HRESULT hr;
 
-    TRACE("device %p, desc %p, parent %p, parent_ops %p, swapchain %p.\n",
-            device, desc, parent, parent_ops, swapchain);
+    TRACE("device %p, desc %p, state_parent %p, parent %p, parent_ops %p, swapchain %p.\n",
+            device, desc, state_parent, parent, parent_ops, swapchain);
 
     if (!(swapchain_no3d = heap_alloc_zero(sizeof(*swapchain_no3d))))
         return E_OUTOFMEMORY;
 
-    if (FAILED(hr = wined3d_swapchain_no3d_init(swapchain_no3d, device, desc, parent, parent_ops)))
+    if (FAILED(hr = wined3d_swapchain_no3d_init(swapchain_no3d, device, desc, state_parent, parent,
+            parent_ops)))
     {
         WARN("Failed to initialise swapchain, hr %#x.\n", hr);
         heap_free(swapchain_no3d);
diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c
index b35fb5af65a..f8214379971 100644
--- a/dlls/wined3d/swapchain.c
+++ b/dlls/wined3d/swapchain.c
@@ -1288,7 +1288,8 @@ static enum wined3d_format_id adapter_format_from_backbuffer_format(const struct
 }
 
 static HRESULT wined3d_swapchain_state_init(struct wined3d_swapchain_state *state,
-        const struct wined3d_swapchain_desc *desc, HWND window, struct wined3d *wined3d)
+        const struct wined3d_swapchain_desc *desc, HWND window, struct wined3d *wined3d,
+        struct wined3d_swapchain_state_parent *parent)
 {
     HRESULT hr;
 
@@ -1319,6 +1320,7 @@ static HRESULT wined3d_swapchain_state_init(struct wined3d_swapchain_state *stat
 
     GetWindowRect(window, &state->original_window_rect);
     state->device_window = window;
+    state->parent = parent;
 
     if (desc->flags & WINED3D_SWAPCHAIN_REGISTER_STATE)
         wined3d_swapchain_state_register(state, wined3d);
@@ -1327,7 +1329,8 @@ static HRESULT wined3d_swapchain_state_init(struct wined3d_swapchain_state *stat
 }
 
 static HRESULT wined3d_swapchain_init(struct wined3d_swapchain *swapchain, struct wined3d_device *device,
-        struct wined3d_swapchain_desc *desc, void *parent, const struct wined3d_parent_ops *parent_ops,
+        struct wined3d_swapchain_desc *desc, struct wined3d_swapchain_state_parent *state_parent,
+        void *parent, const struct wined3d_parent_ops *parent_ops,
         const struct wined3d_swapchain_ops *swapchain_ops)
 {
     struct wined3d_resource_desc texture_desc;
@@ -1353,7 +1356,7 @@ static HRESULT wined3d_swapchain_init(struct wined3d_swapchain *swapchain, struc
         FIXME("Unimplemented swap effect %#x.\n", desc->swap_effect);
 
     window = desc->device_window ? desc->device_window : device->create_parms.focus_window;
-    if (FAILED(hr = wined3d_swapchain_state_init(&swapchain->state, desc, window, device->wined3d)))
+    if (FAILED(hr = wined3d_swapchain_state_init(&swapchain->state, desc, window, device->wined3d, state_parent)))
     {
         ERR("Failed to initialise swapchain state, hr %#x.\n", hr);
         goto err;
@@ -1568,23 +1571,27 @@ err:
 }
 
 HRESULT wined3d_swapchain_no3d_init(struct wined3d_swapchain *swapchain_no3d, struct wined3d_device *device,
-        struct wined3d_swapchain_desc *desc, void *parent, const struct wined3d_parent_ops *parent_ops)
+        struct wined3d_swapchain_desc *desc, struct wined3d_swapchain_state_parent *state_parent,
+        void *parent, const struct wined3d_parent_ops *parent_ops)
 {
-    TRACE("swapchain_no3d %p, device %p, desc %p, parent %p, parent_ops %p.\n",
-            swapchain_no3d, device, desc, parent, parent_ops);
+    TRACE("swapchain_no3d %p, device %p, desc %p, state_parent %p, parent %p, parent_ops %p.\n",
+            swapchain_no3d, device, desc, state_parent, parent, parent_ops);
 
-    return wined3d_swapchain_init(swapchain_no3d, device, desc, parent, parent_ops, &swapchain_no3d_ops);
+    return wined3d_swapchain_init(swapchain_no3d, device, desc, state_parent, parent, parent_ops,
+            &swapchain_no3d_ops);
 }
 
 HRESULT wined3d_swapchain_gl_init(struct wined3d_swapchain_gl *swapchain_gl, struct wined3d_device *device,
-        struct wined3d_swapchain_desc *desc, void *parent, const struct wined3d_parent_ops *parent_ops)
+        struct wined3d_swapchain_desc *desc, struct wined3d_swapchain_state_parent *state_parent,
+        void *parent, const struct wined3d_parent_ops *parent_ops)
 {
     HRESULT hr;
 
-    TRACE("swapchain_gl %p, device %p, desc %p, parent %p, parent_ops %p.\n",
-            swapchain_gl, device, desc, parent, parent_ops);
+    TRACE("swapchain_gl %p, device %p, desc %p, state_parent %p, parent %p, parent_ops %p.\n",
+            swapchain_gl, device, desc, state_parent, parent, parent_ops);
 
-    if (FAILED(hr = wined3d_swapchain_init(&swapchain_gl->s, device, desc, parent, parent_ops, &swapchain_gl_ops)))
+    if (FAILED(hr = wined3d_swapchain_init(&swapchain_gl->s, device, desc, state_parent, parent,
+            parent_ops, &swapchain_gl_ops)))
     {
         /* Cleanup any context that may have been created for the swapchain. */
         wined3d_cs_destroy_object(device->cs, wined3d_swapchain_gl_destroy_object, swapchain_gl);
@@ -1595,14 +1602,16 @@ HRESULT wined3d_swapchain_gl_init(struct wined3d_swapchain_gl *swapchain_gl, str
 }
 
 HRESULT wined3d_swapchain_vk_init(struct wined3d_swapchain_vk *swapchain_vk, struct wined3d_device *device,
-        struct wined3d_swapchain_desc *desc, void *parent, const struct wined3d_parent_ops *parent_ops)
+        struct wined3d_swapchain_desc *desc, struct wined3d_swapchain_state_parent *state_parent,
+        void *parent, const struct wined3d_parent_ops *parent_ops)
 {
     HRESULT hr;
 
     TRACE("swapchain_vk %p, device %p, desc %p, parent %p, parent_ops %p.\n",
             swapchain_vk, device, desc, parent, parent_ops);
 
-    if (FAILED(hr = wined3d_swapchain_init(&swapchain_vk->s, device, desc, parent, parent_ops, &swapchain_vk_ops)))
+    if (FAILED(hr = wined3d_swapchain_init(&swapchain_vk->s, device, desc, state_parent, parent,
+            parent_ops, &swapchain_vk_ops)))
         return hr;
 
     if (swapchain_vk->s.win_handle == GetDesktopWindow())
@@ -1620,14 +1629,16 @@ HRESULT wined3d_swapchain_vk_init(struct wined3d_swapchain_vk *swapchain_vk, str
     return hr;
 }
 
-HRESULT CDECL wined3d_swapchain_create(struct wined3d_device *device, struct wined3d_swapchain_desc *desc,
-        void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_swapchain **swapchain)
+HRESULT CDECL wined3d_swapchain_create(struct wined3d_device *device,
+        struct wined3d_swapchain_desc *desc, struct wined3d_swapchain_state_parent *state_parent,
+        void *parent, const struct wined3d_parent_ops *parent_ops,
+        struct wined3d_swapchain **swapchain)
 {
     struct wined3d_swapchain *object;
     HRESULT hr;
 
     if (FAILED(hr = device->adapter->adapter_ops->adapter_create_swapchain(device,
-            desc, parent, parent_ops, &object)))
+            desc, state_parent, parent, parent_ops, &object)))
         return hr;
 
     if (desc->flags & WINED3D_SWAPCHAIN_IMPLICIT)
@@ -2175,6 +2186,7 @@ HRESULT CDECL wined3d_swapchain_state_set_fullscreen(struct wined3d_swapchain_st
 {
     struct wined3d_display_mode actual_mode;
     struct wined3d_output_desc output_desc;
+    BOOL windowed = state->desc.windowed;
     HRESULT hr;
 
     TRACE("state %p, swapchain_desc %p, mode %p.\n", state, swapchain_desc, mode);
@@ -2263,6 +2275,9 @@ HRESULT CDECL wined3d_swapchain_state_set_fullscreen(struct wined3d_swapchain_st
     state->desc.output = swapchain_desc->output;
     state->desc.windowed = swapchain_desc->windowed;
 
+    if (windowed != state->desc.windowed)
+        state->parent->ops->windowed_state_changed(state->parent, state->desc.windowed);
+
     return WINED3D_OK;
 }
 
@@ -2280,7 +2295,8 @@ void CDECL wined3d_swapchain_state_destroy(struct wined3d_swapchain_state *state
 }
 
 HRESULT CDECL wined3d_swapchain_state_create(const struct wined3d_swapchain_desc *desc,
-        HWND window, struct wined3d *wined3d, struct wined3d_swapchain_state **state)
+        HWND window, struct wined3d *wined3d, struct wined3d_swapchain_state_parent *state_parent,
+        struct wined3d_swapchain_state **state)
 {
     struct wined3d_swapchain_state *s;
     HRESULT hr;
@@ -2290,7 +2306,7 @@ HRESULT CDECL wined3d_swapchain_state_create(const struct wined3d_swapchain_desc
     if (!(s = heap_alloc_zero(sizeof(*s))))
         return E_OUTOFMEMORY;
 
-    if (FAILED(hr = wined3d_swapchain_state_init(s, desc, window, wined3d)))
+    if (FAILED(hr = wined3d_swapchain_state_init(s, desc, window, wined3d, state_parent)))
     {
         heap_free(s);
         return hr;
diff --git a/dlls/wined3d/wined3d.spec b/dlls/wined3d/wined3d.spec
index 77b22b3c907..e4ff1161bce 100644
--- a/dlls/wined3d/wined3d.spec
+++ b/dlls/wined3d/wined3d.spec
@@ -271,7 +271,7 @@
 @ cdecl wined3d_stateblock_set_vs_consts_f(ptr long long ptr)
 @ cdecl wined3d_stateblock_set_vs_consts_i(ptr long long ptr)
 
-@ cdecl wined3d_swapchain_create(ptr ptr ptr ptr ptr)
+@ cdecl wined3d_swapchain_create(ptr ptr ptr ptr ptr ptr)
 @ cdecl wined3d_swapchain_decref(ptr)
 @ cdecl wined3d_swapchain_get_back_buffer(ptr long)
 @ cdecl wined3d_swapchain_get_device(ptr)
@@ -289,7 +289,7 @@
 @ cdecl wined3d_swapchain_set_palette(ptr ptr)
 @ cdecl wined3d_swapchain_set_window(ptr ptr)
 
-@ cdecl wined3d_swapchain_state_create(ptr ptr ptr ptr)
+@ cdecl wined3d_swapchain_state_create(ptr ptr ptr ptr ptr)
 @ cdecl wined3d_swapchain_state_destroy(ptr)
 @ cdecl wined3d_swapchain_state_is_windowed(ptr)
 @ cdecl wined3d_swapchain_state_resize_target(ptr ptr)
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index bbb0a60d7bb..4c2204cd86e 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -3245,8 +3245,10 @@ struct wined3d_adapter_ops
             unsigned int range_count, const struct wined3d_range *ranges);
     void (*adapter_copy_bo_address)(struct wined3d_context *context,
             const struct wined3d_bo_address *dst, const struct wined3d_bo_address *src, size_t size);
-    HRESULT (*adapter_create_swapchain)(struct wined3d_device *device, struct wined3d_swapchain_desc *desc,
-            void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_swapchain **swapchain);
+    HRESULT (*adapter_create_swapchain)(struct wined3d_device *device,
+            struct wined3d_swapchain_desc *desc,
+            struct wined3d_swapchain_state_parent *state_parent, void *parent,
+            const struct wined3d_parent_ops *parent_ops, struct wined3d_swapchain **swapchain);
     void (*adapter_destroy_swapchain)(struct wined3d_swapchain *swapchain);
     HRESULT (*adapter_create_buffer)(struct wined3d_device *device, const struct wined3d_buffer_desc *desc,
             const struct wined3d_sub_resource_data *data, void *parent, const struct wined3d_parent_ops *parent_ops,
@@ -5070,6 +5072,7 @@ void wined3d_unordered_access_view_vk_update(struct wined3d_unordered_access_vie
 struct wined3d_swapchain_state
 {
     struct wined3d_swapchain_desc desc;
+    struct wined3d_swapchain_state_parent *parent;
 
     struct wined3d_display_mode original_mode, d3d_mode;
     RECT original_window_rect;
@@ -5128,7 +5131,8 @@ void swapchain_set_max_frame_latency(struct wined3d_swapchain *swapchain,
 
 HRESULT wined3d_swapchain_no3d_init(struct wined3d_swapchain *swapchain_no3d,
         struct wined3d_device *device, struct wined3d_swapchain_desc *desc,
-        void *parent, const struct wined3d_parent_ops *parent_ops) DECLSPEC_HIDDEN;
+        struct wined3d_swapchain_state_parent *state_parent, void *parent,
+        const struct wined3d_parent_ops *parent_ops) DECLSPEC_HIDDEN;
 
 struct wined3d_swapchain_gl
 {
@@ -5153,7 +5157,8 @@ HDC wined3d_swapchain_gl_get_backup_dc(struct wined3d_swapchain_gl *swapchain_gl
 struct wined3d_context_gl *wined3d_swapchain_gl_get_context(struct wined3d_swapchain_gl *swapchain_gl) DECLSPEC_HIDDEN;
 HRESULT wined3d_swapchain_gl_init(struct wined3d_swapchain_gl *swapchain_gl,
         struct wined3d_device *device, struct wined3d_swapchain_desc *desc,
-        void *parent, const struct wined3d_parent_ops *parent_ops) DECLSPEC_HIDDEN;
+        struct wined3d_swapchain_state_parent *state_parent, void *parent,
+        const struct wined3d_parent_ops *parent_ops) DECLSPEC_HIDDEN;
 
 struct wined3d_swapchain_vk
 {
@@ -5179,7 +5184,8 @@ static inline struct wined3d_swapchain_vk *wined3d_swapchain_vk(struct wined3d_s
 void wined3d_swapchain_vk_cleanup(struct wined3d_swapchain_vk *swapchain_vk) DECLSPEC_HIDDEN;
 HRESULT wined3d_swapchain_vk_init(struct wined3d_swapchain_vk *swapchain_vk,
         struct wined3d_device *device, struct wined3d_swapchain_desc *desc,
-        void *parent, const struct wined3d_parent_ops *parent_ops) DECLSPEC_HIDDEN;
+        struct wined3d_swapchain_state_parent *state_parent, void *parent,
+        const struct wined3d_parent_ops *parent_ops) DECLSPEC_HIDDEN;
 
 /*****************************************************************************
  * Utility function prototypes
diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h
index 61ab0e90953..62ea3960118 100644
--- a/include/wine/wined3d.h
+++ b/include/wine/wined3d.h
@@ -2248,6 +2248,17 @@ struct wined3d_device_parent_ops
             const struct wined3d_resource_desc *desc, DWORD texture_flags, struct wined3d_texture **texture);
 };
 
+struct wined3d_swapchain_state_parent
+{
+    const struct wined3d_swapchain_state_parent_ops *ops;
+};
+
+struct wined3d_swapchain_state_parent_ops
+{
+    void (__cdecl *windowed_state_changed)(struct wined3d_swapchain_state_parent *state_parent,
+            BOOL windowed);
+};
+
 struct wined3d_private_store
 {
     struct list content;
@@ -2774,8 +2785,10 @@ HRESULT __cdecl wined3d_stateblock_set_vs_consts_f(struct wined3d_stateblock *st
 HRESULT __cdecl wined3d_stateblock_set_vs_consts_i(struct wined3d_stateblock *stateblock,
         unsigned int start_idx, unsigned int count, const struct wined3d_ivec4 *constants);
 
-HRESULT __cdecl wined3d_swapchain_create(struct wined3d_device *device, struct wined3d_swapchain_desc *desc,
-        void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_swapchain **swapchain);
+HRESULT __cdecl wined3d_swapchain_create(struct wined3d_device *device,
+        struct wined3d_swapchain_desc *desc, struct wined3d_swapchain_state_parent *state_parent,
+        void *parent, const struct wined3d_parent_ops *parent_ops,
+        struct wined3d_swapchain **swapchain);
 ULONG __cdecl wined3d_swapchain_decref(struct wined3d_swapchain *swapchain);
 struct wined3d_texture * __cdecl wined3d_swapchain_get_back_buffer(const struct wined3d_swapchain *swapchain,
         UINT backbuffer_idx);
@@ -2804,7 +2817,8 @@ void __cdecl wined3d_swapchain_set_palette(struct wined3d_swapchain *swapchain,
 void __cdecl wined3d_swapchain_set_window(struct wined3d_swapchain *swapchain, HWND window);
 
 HRESULT __cdecl wined3d_swapchain_state_create(const struct wined3d_swapchain_desc *desc,
-        HWND window, struct wined3d *wined3d, struct wined3d_swapchain_state **state);
+        HWND window, struct wined3d *wined3d, struct wined3d_swapchain_state_parent *state_parent,
+        struct wined3d_swapchain_state **state);
 void __cdecl wined3d_swapchain_state_destroy(struct wined3d_swapchain_state *state);
 BOOL __cdecl wined3d_swapchain_state_is_windowed(const struct wined3d_swapchain_state *state);
 HRESULT __cdecl wined3d_swapchain_state_resize_target(struct wined3d_swapchain_state *state,
-- 
2.25.1



More information about the wine-devel mailing list