[PATCH 4/5] wined3d: Explicitly create the implicit swapchain.

Henri Verbeet hverbeet at codeweavers.com
Fri Apr 12 07:50:47 CDT 2019


Signed-off-by: Henri Verbeet <hverbeet at codeweavers.com>
---
 dlls/d3d11/device.c            |  28 -----------
 dlls/d3d8/d3d8_private.h       |   2 +-
 dlls/d3d8/device.c             |  59 +++++++++--------------
 dlls/d3d9/d3d9_private.h       |   2 +-
 dlls/d3d9/device.c             |  75 ++++++++++++------------------
 dlls/ddraw/ddraw.c             |  97 ++++++++++++++++----------------------
 dlls/dxgi/device.c             |  74 ++++++++++++++---------------
 dlls/dxgi/dxgi_private.h       |   1 +
 dlls/wined3d/device.c          | 103 ++++++++++++++++++++---------------------
 dlls/wined3d/swapchain.c       |  21 ++++++++-
 dlls/wined3d/wined3d.spec      |   2 -
 dlls/wined3d/wined3d_private.h |   3 ++
 include/wine/wined3d.h         |   5 +-
 include/wine/winedxgi.idl      |   5 --
 14 files changed, 201 insertions(+), 276 deletions(-)

diff --git a/dlls/d3d11/device.c b/dlls/d3d11/device.c
index 877775fdd3a..588395b4b6a 100644
--- a/dlls/d3d11/device.c
+++ b/dlls/d3d11/device.c
@@ -6106,33 +6106,6 @@ static HRESULT CDECL device_parent_create_swapchain_texture(struct wined3d_devic
     return S_OK;
 }
 
-static HRESULT CDECL device_parent_create_swapchain(struct wined3d_device_parent *device_parent,
-        struct wined3d_swapchain_desc *desc, struct wined3d_swapchain **swapchain)
-{
-    struct d3d_device *device = device_from_wined3d_device_parent(device_parent);
-    IWineDXGIDevice *wine_device;
-    HRESULT hr;
-
-    TRACE("device_parent %p, desc %p, swapchain %p.\n", device_parent, desc, swapchain);
-
-    if (FAILED(hr = d3d11_device_QueryInterface(&device->ID3D11Device2_iface,
-            &IID_IWineDXGIDevice, (void **)&wine_device)))
-    {
-        ERR("Device should implement IWineDXGIDevice.\n");
-        return E_FAIL;
-    }
-
-    hr = IWineDXGIDevice_create_swapchain(wine_device, desc, TRUE, swapchain);
-    IWineDXGIDevice_Release(wine_device);
-    if (FAILED(hr))
-    {
-        ERR("Failed to create DXGI swapchain, returning %#x\n", hr);
-        return hr;
-    }
-
-    return S_OK;
-}
-
 static const struct wined3d_device_parent_ops d3d_wined3d_device_parent_ops =
 {
     device_parent_wined3d_device_created,
@@ -6140,7 +6113,6 @@ static const struct wined3d_device_parent_ops d3d_wined3d_device_parent_ops =
     device_parent_activate,
     device_parent_texture_sub_resource_created,
     device_parent_create_swapchain_texture,
-    device_parent_create_swapchain,
 };
 
 static int d3d_sampler_state_compare(const void *key, const struct wine_rb_entry *entry)
diff --git a/dlls/d3d8/d3d8_private.h b/dlls/d3d8/d3d8_private.h
index 0f861658cf4..1669ff74315 100644
--- a/dlls/d3d8/d3d8_private.h
+++ b/dlls/d3d8/d3d8_private.h
@@ -131,7 +131,7 @@ struct d3d8_device
 
     /* The d3d8 API supports only one implicit swapchain (no D3DCREATE_ADAPTERGROUP_DEVICE,
      * no GetSwapchain, GetBackBuffer doesn't accept a swapchain number). */
-    struct d3d8_swapchain   *implicit_swapchain;
+    struct wined3d_swapchain *implicit_swapchain;
 };
 
 HRESULT device_init(struct d3d8_device *device, struct d3d8 *parent, struct wined3d *wined3d, UINT adapter,
diff --git a/dlls/d3d8/device.c b/dlls/d3d8/device.c
index 3dce0f60462..974764cdf51 100644
--- a/dlls/d3d8/device.c
+++ b/dlls/d3d8/device.c
@@ -594,7 +594,7 @@ static ULONG WINAPI d3d8_device_Release(IDirect3DDevice8 *iface)
         if (device->index_buffer)
             wined3d_buffer_decref(device->index_buffer);
 
-        wined3d_device_uninit_3d(device->wined3d_device);
+        wined3d_swapchain_decref(device->implicit_swapchain);
         wined3d_device_release_focus_window(device->wined3d_device);
         wined3d_device_decref(device->wined3d_device);
         heap_free(device->handle_table.entries);
@@ -877,6 +877,7 @@ static HRESULT WINAPI d3d8_device_Reset(IDirect3DDevice8 *iface,
 {
     struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
     struct wined3d_swapchain_desc swapchain_desc;
+    struct d3d8_swapchain *implicit_swapchain;
     HRESULT hr;
 
     TRACE("iface %p, present_parameters %p.\n", iface, present_parameters);
@@ -888,6 +889,7 @@ static HRESULT WINAPI d3d8_device_Reset(IDirect3DDevice8 *iface,
     }
     if (!wined3d_swapchain_desc_from_present_parameters(&swapchain_desc, present_parameters))
         return D3DERR_INVALIDCALL;
+    swapchain_desc.flags |= WINED3D_SWAPCHAIN_IMPLICIT;
 
     wined3d_mutex_lock();
 
@@ -909,7 +911,8 @@ static HRESULT WINAPI d3d8_device_Reset(IDirect3DDevice8 *iface,
     {
         device->recording = FALSE;
         present_parameters->BackBufferCount = swapchain_desc.backbuffer_count;
-        device->implicit_swapchain->swap_interval
+        implicit_swapchain = wined3d_swapchain_get_parent(device->implicit_swapchain);
+        implicit_swapchain->swap_interval
                 = wined3dswapinterval_from_d3d(present_parameters->FullScreen_PresentationInterval);
         wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_POINTSIZE_MIN, 0);
         wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_ZENABLE,
@@ -929,6 +932,7 @@ static HRESULT WINAPI d3d8_device_Present(IDirect3DDevice8 *iface, const RECT *s
         const RECT *dst_rect, HWND dst_window_override, const RGNDATA *dirty_region)
 {
     struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
+    struct d3d8_swapchain *implicit_swapchain;
 
     TRACE("iface %p, src_rect %s, dst_rect %s, dst_window_override %p, dirty_region %p.\n",
             iface, wine_dbgstr_rect(src_rect), wine_dbgstr_rect(dst_rect), dst_window_override, dirty_region);
@@ -938,7 +942,8 @@ static HRESULT WINAPI d3d8_device_Present(IDirect3DDevice8 *iface, const RECT *s
      * shows a framerate on Windows in applications that only call the device
      * method, like e.g. the dx8 sdk samples. The conclusion is that native
      * calls the swapchain's public method from the device. */
-    return IDirect3DSwapChain8_Present(&device->implicit_swapchain->IDirect3DSwapChain8_iface,
+    implicit_swapchain = wined3d_swapchain_get_parent(device->implicit_swapchain);
+    return IDirect3DSwapChain8_Present(&implicit_swapchain->IDirect3DSwapChain8_iface,
             src_rect, dst_rect, dst_window_override, dirty_region);
 }
 
@@ -946,7 +951,6 @@ static HRESULT WINAPI d3d8_device_GetBackBuffer(IDirect3DDevice8 *iface,
         UINT backbuffer_idx, D3DBACKBUFFER_TYPE backbuffer_type, IDirect3DSurface8 **backbuffer)
 {
     struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
-    struct wined3d_swapchain *wined3d_swapchain;
     struct wined3d_texture *wined3d_texture;
     struct d3d8_surface *surface_impl;
 
@@ -958,8 +962,7 @@ static HRESULT WINAPI d3d8_device_GetBackBuffer(IDirect3DDevice8 *iface,
     /* No need to check for backbuffer == NULL, Windows crashes in that case. */
     wined3d_mutex_lock();
 
-    wined3d_swapchain = device->implicit_swapchain->wined3d_swapchain;
-    if (!(wined3d_texture = wined3d_swapchain_get_back_buffer(wined3d_swapchain, backbuffer_idx)))
+    if (!(wined3d_texture = wined3d_swapchain_get_back_buffer(device->implicit_swapchain, backbuffer_idx)))
     {
         wined3d_mutex_unlock();
         *backbuffer = NULL;
@@ -1387,7 +1390,7 @@ static HRESULT WINAPI d3d8_device_GetFrontBuffer(IDirect3DDevice8 *iface, IDirec
     }
 
     wined3d_mutex_lock();
-    hr = wined3d_swapchain_get_front_buffer_data(device->implicit_swapchain->wined3d_swapchain,
+    hr = wined3d_swapchain_get_front_buffer_data(device->implicit_swapchain,
             dst_impl->wined3d_texture, dst_impl->sub_resource_idx);
     wined3d_mutex_unlock();
 
@@ -3532,29 +3535,6 @@ static HRESULT CDECL device_parent_create_swapchain_texture(struct wined3d_devic
     return hr;
 }
 
-static HRESULT CDECL device_parent_create_swapchain(struct wined3d_device_parent *device_parent,
-        struct wined3d_swapchain_desc *desc, struct wined3d_swapchain **swapchain)
-{
-    struct d3d8_device *device = device_from_device_parent(device_parent);
-    struct d3d8_swapchain *d3d_swapchain;
-    HRESULT hr;
-
-    TRACE("device_parent %p, desc %p, swapchain %p.\n", device_parent, desc, swapchain);
-
-    if (FAILED(hr = d3d8_swapchain_create(device, desc, WINED3D_SWAP_INTERVAL_DEFAULT, &d3d_swapchain)))
-    {
-        WARN("Failed to create swapchain, hr %#x.\n", hr);
-        *swapchain = NULL;
-        return hr;
-    }
-
-    *swapchain = d3d_swapchain->wined3d_swapchain;
-    wined3d_swapchain_incref(*swapchain);
-    IDirect3DSwapChain8_Release(&d3d_swapchain->IDirect3DSwapChain8_iface);
-
-    return hr;
-}
-
 static const struct wined3d_device_parent_ops d3d8_wined3d_device_parent_ops =
 {
     device_parent_wined3d_device_created,
@@ -3562,7 +3542,6 @@ static const struct wined3d_device_parent_ops d3d8_wined3d_device_parent_ops =
     device_parent_activate,
     device_parent_texture_sub_resource_created,
     device_parent_create_swapchain_texture,
-    device_parent_create_swapchain,
 };
 
 static void setup_fpu(void)
@@ -3587,6 +3566,7 @@ HRESULT device_init(struct d3d8_device *device, struct d3d8 *parent, struct wine
 {
     struct wined3d_swapchain_desc swapchain_desc;
     struct wined3d_swapchain *wined3d_swapchain;
+    struct d3d8_swapchain *d3d_swapchain;
     HRESULT hr;
 
     static const enum wined3d_feature_level feature_levels[] =
@@ -3654,10 +3634,12 @@ HRESULT device_init(struct d3d8_device *device, struct d3d8 *parent, struct wine
         heap_free(device->handle_table.entries);
         return D3DERR_INVALIDCALL;
     }
+    swapchain_desc.flags |= WINED3D_SWAPCHAIN_IMPLICIT;
 
-    if (FAILED(hr = wined3d_device_init_3d(device->wined3d_device, &swapchain_desc)))
+    if (FAILED(hr = d3d8_swapchain_create(device, &swapchain_desc,
+            wined3dswapinterval_from_d3d(parameters->FullScreen_PresentationInterval), &d3d_swapchain)))
     {
-        WARN("Failed to initialize 3D, hr %#x.\n", hr);
+        WARN("Failed to create implicit swapchain, hr %#x.\n", hr);
         wined3d_device_release_focus_window(device->wined3d_device);
         wined3d_device_decref(device->wined3d_device);
         wined3d_mutex_unlock();
@@ -3665,6 +3647,10 @@ HRESULT device_init(struct d3d8_device *device, struct d3d8 *parent, struct wine
         return hr;
     }
 
+    wined3d_swapchain = d3d_swapchain->wined3d_swapchain;
+    wined3d_swapchain_incref(wined3d_swapchain);
+    IDirect3DSwapChain8_Release(&d3d_swapchain->IDirect3DSwapChain8_iface);
+
     wined3d_device_set_render_state(device->wined3d_device,
             WINED3D_RS_ZENABLE, !!swapchain_desc.enable_auto_depth_stencil);
     wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_POINTSIZE_MIN, 0);
@@ -3681,10 +3667,7 @@ HRESULT device_init(struct d3d8_device *device, struct d3d8 *parent, struct wine
         goto err;
     }
 
-    wined3d_swapchain = wined3d_device_get_swapchain(device->wined3d_device, 0);
-    device->implicit_swapchain = wined3d_swapchain_get_parent(wined3d_swapchain);
-    device->implicit_swapchain->swap_interval
-            = wined3dswapinterval_from_d3d(parameters->FullScreen_PresentationInterval);
+    device->implicit_swapchain = wined3d_swapchain;
 
     device->d3d_parent = &parent->IDirect3D8_iface;
     IDirect3D8_AddRef(device->d3d_parent);
@@ -3693,7 +3676,7 @@ HRESULT device_init(struct d3d8_device *device, struct d3d8 *parent, struct wine
 
 err:
     wined3d_mutex_lock();
-    wined3d_device_uninit_3d(device->wined3d_device);
+    wined3d_swapchain_decref(wined3d_swapchain);
     wined3d_device_release_focus_window(device->wined3d_device);
     wined3d_device_decref(device->wined3d_device);
     wined3d_mutex_unlock();
diff --git a/dlls/d3d9/d3d9_private.h b/dlls/d3d9/d3d9_private.h
index b07d72a0662..8ee521b14b0 100644
--- a/dlls/d3d9/d3d9_private.h
+++ b/dlls/d3d9/d3d9_private.h
@@ -116,7 +116,7 @@ struct d3d9_device
     unsigned int max_user_clip_planes;
 
     UINT implicit_swapchain_count;
-    struct d3d9_swapchain **implicit_swapchains;
+    struct wined3d_swapchain **implicit_swapchains;
 };
 
 HRESULT device_init(struct d3d9_device *device, struct d3d9 *parent, struct wined3d *wined3d,
diff --git a/dlls/d3d9/device.c b/dlls/d3d9/device.c
index f7f9358913d..999969119e3 100644
--- a/dlls/d3d9/device.c
+++ b/dlls/d3d9/device.c
@@ -599,9 +599,12 @@ static ULONG WINAPI DECLSPEC_HOTPATCH d3d9_device_Release(IDirect3DDevice9Ex *if
         if (device->index_buffer)
             wined3d_buffer_decref(device->index_buffer);
 
+        for (i = 0; i < device->implicit_swapchain_count; ++i)
+        {
+            wined3d_swapchain_decref(device->implicit_swapchains[i]);
+        }
         heap_free(device->implicit_swapchains);
 
-        wined3d_device_uninit_3d(device->wined3d_device);
         wined3d_device_release_focus_window(device->wined3d_device);
         wined3d_device_decref(device->wined3d_device);
         wined3d_mutex_unlock();
@@ -838,6 +841,7 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_GetSwapChain(IDirect3DDevice
         UINT swapchain_idx, IDirect3DSwapChain9 **swapchain)
 {
     struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    struct d3d9_swapchain *d3d9_swapchain;
     HRESULT hr;
 
     TRACE("iface %p, swapchain_idx %u, swapchain %p.\n", iface, swapchain_idx, swapchain);
@@ -845,7 +849,8 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_GetSwapChain(IDirect3DDevice
     wined3d_mutex_lock();
     if (swapchain_idx < device->implicit_swapchain_count)
     {
-        *swapchain = (IDirect3DSwapChain9 *)&device->implicit_swapchains[swapchain_idx]->IDirect3DSwapChain9Ex_iface;
+        d3d9_swapchain = wined3d_swapchain_get_parent(device->implicit_swapchains[swapchain_idx]);
+        *swapchain = (IDirect3DSwapChain9 *)&d3d9_swapchain->IDirect3DSwapChain9Ex_iface;
         IDirect3DSwapChain9Ex_AddRef(*swapchain);
         hr = D3D_OK;
     }
@@ -924,15 +929,13 @@ static HRESULT CDECL reset_enum_callback(struct wined3d_resource *resource)
 static HRESULT d3d9_device_get_swapchains(struct d3d9_device *device)
 {
     UINT i, new_swapchain_count = wined3d_device_get_swapchain_count(device->wined3d_device);
-    struct wined3d_swapchain *wined3d_swapchain;
 
     if (!(device->implicit_swapchains = heap_alloc(new_swapchain_count * sizeof(*device->implicit_swapchains))))
         return E_OUTOFMEMORY;
 
     for (i = 0; i < new_swapchain_count; ++i)
     {
-        wined3d_swapchain = wined3d_device_get_swapchain(device->wined3d_device, i);
-        device->implicit_swapchains[i] = wined3d_swapchain_get_parent(wined3d_swapchain);
+        device->implicit_swapchains[i] = wined3d_device_get_swapchain(device->wined3d_device, i);
     }
     device->implicit_swapchain_count = new_swapchain_count;
 
@@ -946,6 +949,7 @@ static HRESULT d3d9_device_reset(struct d3d9_device *device,
     struct wined3d_swapchain_desc swapchain_desc;
     struct wined3d_display_mode wined3d_mode;
     struct wined3d_rendertarget_view *rtv;
+    struct d3d9_swapchain *d3d9_swapchain;
     unsigned int i;
     HRESULT hr;
 
@@ -966,6 +970,7 @@ static HRESULT d3d9_device_reset(struct d3d9_device *device,
 
     if (!wined3d_swapchain_desc_from_present_parameters(&swapchain_desc, present_parameters, extended))
         return D3DERR_INVALIDCALL;
+    swapchain_desc.flags |= WINED3D_SWAPCHAIN_IMPLICIT;
 
     wined3d_mutex_lock();
 
@@ -1002,9 +1007,10 @@ static HRESULT d3d9_device_reset(struct d3d9_device *device,
         }
         else
         {
-            device->implicit_swapchains[0]->swap_interval
+            d3d9_swapchain = wined3d_swapchain_get_parent(device->implicit_swapchains[0]);
+            d3d9_swapchain->swap_interval
                     = wined3dswapinterval_from_d3d(present_parameters->PresentationInterval);
-            wined3d_swapchain_get_desc(device->implicit_swapchains[0]->wined3d_swapchain, &swapchain_desc);
+            wined3d_swapchain_get_desc(d3d9_swapchain->wined3d_swapchain, &swapchain_desc);
             present_parameters->BackBufferWidth = swapchain_desc.backbuffer_width;
             present_parameters->BackBufferHeight = swapchain_desc.backbuffer_height;
             present_parameters->BackBufferFormat = d3dformat_from_wined3dformat(swapchain_desc.backbuffer_format);
@@ -1058,7 +1064,7 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_Present(IDirect3DDevice9Ex *
     wined3d_mutex_lock();
     for (i = 0; i < device->implicit_swapchain_count; ++i)
     {
-        swapchain = device->implicit_swapchains[i];
+        swapchain = wined3d_swapchain_get_parent(device->implicit_swapchains[i]);
         if (FAILED(hr = wined3d_swapchain_present(swapchain->wined3d_swapchain,
                 src_rect, dst_rect, dst_window_override, swapchain->swap_interval, 0)))
         {
@@ -1075,6 +1081,7 @@ static HRESULT WINAPI d3d9_device_GetBackBuffer(IDirect3DDevice9Ex *iface, UINT
         UINT backbuffer_idx, D3DBACKBUFFER_TYPE backbuffer_type, IDirect3DSurface9 **backbuffer)
 {
     struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
+    struct d3d9_swapchain *d3d9_swapchain;
     HRESULT hr;
 
     TRACE("iface %p, swapchain %u, backbuffer_idx %u, backbuffer_type %#x, backbuffer %p.\n",
@@ -1093,7 +1100,8 @@ static HRESULT WINAPI d3d9_device_GetBackBuffer(IDirect3DDevice9Ex *iface, UINT
         return D3DERR_INVALIDCALL;
     }
 
-    hr = IDirect3DSwapChain9Ex_GetBackBuffer(&device->implicit_swapchains[swapchain]->IDirect3DSwapChain9Ex_iface,
+    d3d9_swapchain = wined3d_swapchain_get_parent(device->implicit_swapchains[swapchain]);
+    hr = IDirect3DSwapChain9Ex_GetBackBuffer(&d3d9_swapchain->IDirect3DSwapChain9Ex_iface,
             backbuffer_idx, backbuffer_type, backbuffer);
     wined3d_mutex_unlock();
 
@@ -1645,7 +1653,7 @@ static HRESULT WINAPI d3d9_device_GetFrontBufferData(IDirect3DDevice9Ex *iface,
 
     wined3d_mutex_lock();
     if (swapchain < device->implicit_swapchain_count)
-        hr = wined3d_swapchain_get_front_buffer_data(device->implicit_swapchains[swapchain]->wined3d_swapchain,
+        hr = wined3d_swapchain_get_front_buffer_data(device->implicit_swapchains[swapchain],
                 dst_impl->wined3d_texture, dst_impl->sub_resource_idx);
     wined3d_mutex_unlock();
 
@@ -3953,7 +3961,7 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_PresentEx(IDirect3DDevice9Ex
     wined3d_mutex_lock();
     for (i = 0; i < device->implicit_swapchain_count; ++i)
     {
-        swapchain = device->implicit_swapchains[i];
+        swapchain = wined3d_swapchain_get_parent(device->implicit_swapchains[i]);
         if (FAILED(hr = wined3d_swapchain_present(swapchain->wined3d_swapchain,
                 src_rect, dst_rect, dst_window_override, swapchain->swap_interval, flags)))
         {
@@ -4033,7 +4041,7 @@ static HRESULT WINAPI d3d9_device_CheckDeviceState(IDirect3DDevice9Ex *iface, HW
     TRACE("iface %p, dst_window %p.\n", iface, dst_window);
 
     wined3d_mutex_lock();
-    wined3d_swapchain_get_desc(device->implicit_swapchains[0]->wined3d_swapchain, &swapchain_desc);
+    wined3d_swapchain_get_desc(device->implicit_swapchains[0], &swapchain_desc);
     wined3d_mutex_unlock();
 
     if (swapchain_desc.windowed)
@@ -4397,29 +4405,6 @@ static HRESULT CDECL device_parent_create_swapchain_texture(struct wined3d_devic
     return hr;
 }
 
-static HRESULT CDECL device_parent_create_swapchain(struct wined3d_device_parent *device_parent,
-        struct wined3d_swapchain_desc *desc, struct wined3d_swapchain **swapchain)
-{
-    struct d3d9_device *device = device_from_device_parent(device_parent);
-    struct d3d9_swapchain *d3d_swapchain;
-    HRESULT hr;
-
-    TRACE("device_parent %p, desc %p, swapchain %p\n", device_parent, desc, swapchain);
-
-    if (FAILED(hr = d3d9_swapchain_create(device, desc, WINED3D_SWAP_INTERVAL_DEFAULT, &d3d_swapchain)))
-    {
-        WARN("Failed to create swapchain, hr %#x.\n", hr);
-        *swapchain = NULL;
-        return hr;
-    }
-
-    *swapchain = d3d_swapchain->wined3d_swapchain;
-    wined3d_swapchain_incref(*swapchain);
-    IDirect3DSwapChain9Ex_Release(&d3d_swapchain->IDirect3DSwapChain9Ex_iface);
-
-    return hr;
-}
-
 static const struct wined3d_device_parent_ops d3d9_wined3d_device_parent_ops =
 {
     device_parent_wined3d_device_created,
@@ -4427,7 +4412,6 @@ static const struct wined3d_device_parent_ops d3d9_wined3d_device_parent_ops =
     device_parent_activate,
     device_parent_texture_sub_resource_created,
     device_parent_create_swapchain_texture,
-    device_parent_create_swapchain,
 };
 
 static void setup_fpu(void)
@@ -4452,6 +4436,7 @@ HRESULT device_init(struct d3d9_device *device, struct d3d9 *parent, struct wine
         D3DPRESENT_PARAMETERS *parameters, D3DDISPLAYMODEEX *mode)
 {
     struct wined3d_swapchain_desc *swapchain_desc;
+    struct d3d9_swapchain *d3d_swapchain;
     struct wined3d_caps caps;
     unsigned i, count = 1;
     HRESULT hr;
@@ -4537,11 +4522,13 @@ HRESULT device_init(struct d3d9_device *device, struct d3d9 *parent, struct wine
             wined3d_mutex_unlock();
             return D3DERR_INVALIDCALL;
         }
+        swapchain_desc[i].flags |= WINED3D_SWAPCHAIN_IMPLICIT;
     }
 
-    if (FAILED(hr = wined3d_device_init_3d(device->wined3d_device, swapchain_desc)))
+    if (FAILED(hr = d3d9_swapchain_create(device, swapchain_desc,
+            wined3dswapinterval_from_d3d(parameters->PresentationInterval), &d3d_swapchain)))
     {
-        WARN("Failed to initialize 3D, hr %#x.\n", hr);
+        WARN("Failed to create swapchain, hr %#x.\n", hr);
         wined3d_device_release_focus_window(device->wined3d_device);
         heap_free(swapchain_desc);
         wined3d_device_decref(device->wined3d_device);
@@ -4549,22 +4536,20 @@ HRESULT device_init(struct d3d9_device *device, struct d3d9 *parent, struct wine
         return hr;
     }
 
+    wined3d_swapchain_incref(d3d_swapchain->wined3d_swapchain);
+    IDirect3DSwapChain9Ex_Release(&d3d_swapchain->IDirect3DSwapChain9Ex_iface);
+
     wined3d_device_set_render_state(device->wined3d_device,
             WINED3D_RS_ZENABLE, !!swapchain_desc->enable_auto_depth_stencil);
 
     if (FAILED(hr = d3d9_device_get_swapchains(device)))
     {
-        wined3d_device_uninit_3d(device->wined3d_device);
+        wined3d_swapchain_decref(d3d_swapchain->wined3d_swapchain);
         wined3d_device_release_focus_window(device->wined3d_device);
         wined3d_device_decref(device->wined3d_device);
         wined3d_mutex_unlock();
         return E_OUTOFMEMORY;
     }
-    for (i = 0; i < device->implicit_swapchain_count; ++i)
-    {
-        device->implicit_swapchains[i]->swap_interval
-                = wined3dswapinterval_from_d3d(parameters[i].PresentationInterval);
-    }
 
     for (i = 0; i < count; ++i)
     {
@@ -4583,7 +4568,7 @@ HRESULT device_init(struct d3d9_device *device, struct d3d9 *parent, struct wine
         ERR("Failed to allocate FVF vertex declaration map memory.\n");
         wined3d_mutex_lock();
         heap_free(device->implicit_swapchains);
-        wined3d_device_uninit_3d(device->wined3d_device);
+        wined3d_swapchain_decref(d3d_swapchain->wined3d_swapchain);
         wined3d_device_release_focus_window(device->wined3d_device);
         wined3d_device_decref(device->wined3d_device);
         wined3d_mutex_unlock();
diff --git a/dlls/ddraw/ddraw.c b/dlls/ddraw/ddraw.c
index b2097726076..b005f10826d 100644
--- a/dlls/ddraw/ddraw.c
+++ b/dlls/ddraw/ddraw.c
@@ -366,12 +366,10 @@ static ULONG WINAPI d3d1_AddRef(IDirect3D *iface)
 static void ddraw_destroy_swapchain(struct ddraw *ddraw)
 {
     unsigned int i;
-    HRESULT hr;
 
     TRACE("Destroying the swapchain.\n");
 
     wined3d_swapchain_decref(ddraw->wined3d_swapchain);
-    ddraw->wined3d_swapchain = NULL;
 
     for (i = 0; i < ddraw->numConvertedDecls; ++i)
     {
@@ -380,8 +378,8 @@ static void ddraw_destroy_swapchain(struct ddraw *ddraw)
     heap_free(ddraw->decls);
     ddraw->numConvertedDecls = 0;
 
-    if (FAILED(hr = wined3d_device_uninit_3d(ddraw->wined3d_device)))
-        ERR("Failed to uninit 3D, hr %#x.\n", hr);
+    wined3d_swapchain_decref(ddraw->wined3d_swapchain);
+    ddraw->wined3d_swapchain = NULL;
 
     /* Free the d3d window if one was created. */
     if (ddraw->d3d_window && ddraw->d3d_window != ddraw->dest_window)
@@ -551,16 +549,35 @@ static HRESULT ddraw_set_focus_window(struct ddraw *ddraw, HWND window)
     return DD_OK;
 }
 
-static HRESULT ddraw_attach_d3d_device(struct ddraw *ddraw,
-        struct wined3d_swapchain_desc *swapchain_desc)
+static HRESULT ddraw_attach_d3d_device(struct ddraw *ddraw, HWND window,
+        BOOL windowed, struct wined3d_swapchain **wined3d_swapchain)
 {
-    HWND window = swapchain_desc->device_window;
+    struct wined3d_swapchain_desc swapchain_desc;
+    struct wined3d_display_mode mode;
     HRESULT hr;
 
     TRACE("ddraw %p.\n", ddraw);
 
+    if (FAILED(hr = wined3d_get_adapter_display_mode(ddraw->wined3d, WINED3DADAPTER_DEFAULT, &mode, NULL)))
+    {
+        ERR("Failed to get display mode.\n");
+        return hr;
+    }
+
+    memset(&swapchain_desc, 0, sizeof(swapchain_desc));
+    swapchain_desc.backbuffer_width = mode.width;
+    swapchain_desc.backbuffer_height = mode.height;
+    swapchain_desc.backbuffer_format = mode.format_id;
+    swapchain_desc.backbuffer_bind_flags = 0;
+    swapchain_desc.backbuffer_count = 1;
+    swapchain_desc.swap_effect = WINED3D_SWAP_EFFECT_DISCARD;
+    swapchain_desc.device_window = window;
+    swapchain_desc.windowed = windowed;
+    swapchain_desc.flags = WINED3D_SWAPCHAIN_ALLOW_MODE_SWITCH | WINED3D_SWAPCHAIN_IMPLICIT;
+
     if (ddraw->flags & DDRAW_NO3D)
-        return wined3d_device_init_3d(ddraw->wined3d_device, swapchain_desc);
+        return wined3d_swapchain_create(ddraw->wined3d_device, &swapchain_desc,
+                NULL, &ddraw_null_wined3d_parent_ops, wined3d_swapchain);
 
     if (!window || window == GetDesktopWindow())
     {
@@ -576,7 +593,7 @@ static HRESULT ddraw_attach_d3d_device(struct ddraw *ddraw,
         ShowWindow(window, SW_HIDE);   /* Just to be sure */
         WARN("No window for the Direct3DDevice, created hidden window %p.\n", window);
 
-        swapchain_desc->device_window = window;
+        swapchain_desc.device_window = window;
     }
     else
     {
@@ -587,9 +604,12 @@ static HRESULT ddraw_attach_d3d_device(struct ddraw *ddraw,
     /* Set this NOW, otherwise creating the depth stencil surface will cause a
      * recursive loop until ram or emulated video memory is full. */
     ddraw->flags |= DDRAW_D3D_INITIALIZED;
-    if (FAILED(hr = wined3d_device_init_3d(ddraw->wined3d_device, swapchain_desc)))
+    if (FAILED(hr = wined3d_swapchain_create(ddraw->wined3d_device, &swapchain_desc,
+            NULL, &ddraw_null_wined3d_parent_ops, wined3d_swapchain)))
     {
         ddraw->flags &= ~DDRAW_D3D_INITIALIZED;
+        DestroyWindow(window);
+        ddraw->d3d_window = NULL;
         return hr;
     }
 
@@ -598,7 +618,9 @@ static HRESULT ddraw_attach_d3d_device(struct ddraw *ddraw,
     {
         ERR("Error allocating an array for the converted vertex decls.\n");
         ddraw->declArraySize = 0;
-        hr = wined3d_device_uninit_3d(ddraw->wined3d_device);
+        wined3d_swapchain_decref(*wined3d_swapchain);
+        DestroyWindow(window);
+        ddraw->d3d_window = NULL;
         return E_OUTOFMEMORY;
     }
 
@@ -609,40 +631,21 @@ static HRESULT ddraw_attach_d3d_device(struct ddraw *ddraw,
 
 static HRESULT ddraw_create_swapchain(struct ddraw *ddraw, HWND window, BOOL windowed)
 {
-    struct wined3d_swapchain_desc swapchain_desc;
-    struct wined3d_display_mode mode;
-    HRESULT hr = WINED3D_OK;
+    HRESULT hr;
 
-    if (FAILED(hr = wined3d_get_adapter_display_mode(ddraw->wined3d, WINED3DADAPTER_DEFAULT, &mode, NULL)))
+    if (ddraw->wined3d_swapchain)
     {
-        ERR("Failed to get display mode.\n");
-        return hr;
+        ERR("Swapchain already created.\n");
+        return E_FAIL;
     }
 
-    memset(&swapchain_desc, 0, sizeof(swapchain_desc));
-    swapchain_desc.backbuffer_width = mode.width;
-    swapchain_desc.backbuffer_height = mode.height;
-    swapchain_desc.backbuffer_format = mode.format_id;
-    swapchain_desc.backbuffer_bind_flags = 0;
-    swapchain_desc.backbuffer_count = 1;
-    swapchain_desc.swap_effect = WINED3D_SWAP_EFFECT_DISCARD;
-    swapchain_desc.device_window = window;
-    swapchain_desc.windowed = windowed;
-    swapchain_desc.flags = WINED3D_SWAPCHAIN_ALLOW_MODE_SWITCH;
-
-    if (FAILED(hr = ddraw_attach_d3d_device(ddraw, &swapchain_desc)))
+    if (FAILED(hr = ddraw_attach_d3d_device(ddraw, window, windowed, &ddraw->wined3d_swapchain)))
     {
         ERR("Failed to create swapchain, hr %#x.\n", hr);
         return hr;
     }
-
-    if (!(ddraw->wined3d_swapchain = wined3d_device_get_swapchain(ddraw->wined3d_device, 0)))
-    {
-        ERR("Failed to get swapchain.\n");
-        return DDERR_INVALIDPARAMS;
-    }
-
     wined3d_swapchain_incref(ddraw->wined3d_swapchain);
+
     ddraw_set_swapchain_window(ddraw, window);
 
     if (ddraw->primary && ddraw->primary->palette)
@@ -4967,27 +4970,6 @@ static HRESULT CDECL device_parent_create_swapchain_texture(struct wined3d_devic
     return hr;
 }
 
-static HRESULT CDECL device_parent_create_swapchain(struct wined3d_device_parent *device_parent,
-        struct wined3d_swapchain_desc *desc, struct wined3d_swapchain **swapchain)
-{
-    struct ddraw *ddraw = ddraw_from_device_parent(device_parent);
-    HRESULT hr;
-
-    TRACE("device_parent %p, desc %p, swapchain %p.\n", device_parent, desc, swapchain);
-
-    if (ddraw->wined3d_swapchain)
-    {
-        ERR("Swapchain already created.\n");
-        return E_FAIL;
-    }
-
-    if (FAILED(hr = wined3d_swapchain_create(ddraw->wined3d_device, desc, NULL,
-            &ddraw_null_wined3d_parent_ops, swapchain)))
-        WARN("Failed to create swapchain, hr %#x.\n", hr);
-
-    return hr;
-}
-
 static const struct wined3d_device_parent_ops ddraw_wined3d_device_parent_ops =
 {
     device_parent_wined3d_device_created,
@@ -4995,7 +4977,6 @@ static const struct wined3d_device_parent_ops ddraw_wined3d_device_parent_ops =
     device_parent_activate,
     device_parent_texture_sub_resource_created,
     device_parent_create_swapchain_texture,
-    device_parent_create_swapchain,
 };
 
 HRESULT ddraw_init(struct ddraw *ddraw, DWORD flags, enum wined3d_device_type device_type)
diff --git a/dlls/dxgi/device.c b/dlls/dxgi/device.c
index c7d663f953b..d6dd0418c47 100644
--- a/dlls/dxgi/device.c
+++ b/dlls/dxgi/device.c
@@ -90,7 +90,7 @@ static ULONG STDMETHODCALLTYPE dxgi_device_Release(IWineDXGIDevice *iface)
         if (device->child_layer)
             IUnknown_Release(device->child_layer);
         wined3d_mutex_lock();
-        wined3d_device_uninit_3d(device->wined3d_device);
+        wined3d_swapchain_decref(device->implicit_swapchain);
         wined3d_device_decref(device->wined3d_device);
         wined3d_mutex_unlock();
         IWineDXGIAdapter_Release(device->adapter);
@@ -352,35 +352,6 @@ static HRESULT STDMETHODCALLTYPE dxgi_device_create_surface(IWineDXGIDevice *ifa
     return S_OK;
 }
 
-static HRESULT STDMETHODCALLTYPE dxgi_device_create_swapchain(IWineDXGIDevice *iface,
-        struct wined3d_swapchain_desc *desc, BOOL implicit, struct wined3d_swapchain **wined3d_swapchain)
-{
-    struct dxgi_device *device = impl_from_IWineDXGIDevice(iface);
-    struct d3d11_swapchain *object;
-    HRESULT hr;
-
-    TRACE("iface %p, desc %p, wined3d_swapchain %p.\n",
-            iface, desc, wined3d_swapchain);
-
-    if (!(object = heap_alloc_zero(sizeof(*object))))
-    {
-        ERR("Failed to allocate DXGI swapchain object memory\n");
-        return E_OUTOFMEMORY;
-    }
-
-    if (FAILED(hr = d3d11_swapchain_init(object, device, desc, implicit)))
-    {
-        WARN("Failed to initialize swapchain, hr %#x.\n", hr);
-        heap_free(object);
-        return hr;
-    }
-
-    TRACE("Created IDXGISwapChain %p.\n", object);
-    *wined3d_swapchain = object->wined3d_swapchain;
-
-    return S_OK;
-}
-
 static const struct IWineDXGIDeviceVtbl dxgi_device_vtbl =
 {
     /* IUnknown methods */
@@ -407,7 +378,6 @@ static const struct IWineDXGIDeviceVtbl dxgi_device_vtbl =
     dxgi_device_EnqueueSetEvent,
     /* IWineDXGIDevice methods */
     dxgi_device_create_surface,
-    dxgi_device_create_swapchain,
 };
 
 static inline struct dxgi_device *impl_from_IWineDXGISwapChainFactory(IWineDXGISwapChainFactory *iface)
@@ -448,8 +418,8 @@ static HRESULT STDMETHODCALLTYPE dxgi_swapchain_factory_create_swapchain(IWineDX
         const DXGI_SWAP_CHAIN_FULLSCREEN_DESC *fullscreen_desc, IDXGIOutput *output, IDXGISwapChain1 **swapchain)
 {
     struct dxgi_device *device = impl_from_IWineDXGISwapChainFactory(iface);
-    struct wined3d_swapchain *wined3d_swapchain;
     struct wined3d_swapchain_desc wined3d_desc;
+    struct d3d11_swapchain *object;
     HRESULT hr;
 
     TRACE("iface %p, factory %p, window %p, desc %p, fullscreen_desc %p, output %p, swapchain %p.\n",
@@ -498,16 +468,22 @@ static HRESULT STDMETHODCALLTYPE dxgi_swapchain_factory_create_swapchain(IWineDX
     wined3d_desc.refresh_rate = fullscreen_desc ? dxgi_rational_to_uint(&fullscreen_desc->RefreshRate) : 0;
     wined3d_desc.auto_restore_display_mode = TRUE;
 
-    if (FAILED(hr = dxgi_device_create_swapchain(&device->IWineDXGIDevice_iface,
-            &wined3d_desc, FALSE, &wined3d_swapchain)))
+    if (!(object = heap_alloc_zero(sizeof(*object))))
+    {
+        ERR("Failed to allocate swapchain memory.\n");
+        return E_OUTOFMEMORY;
+    }
+
+    if (FAILED(hr = d3d11_swapchain_init(object, device, &wined3d_desc, FALSE)))
     {
-        WARN("Failed to create swapchain, hr %#x.\n", hr);
+        WARN("Failed to initialise swapchain, hr %#x.\n", hr);
+        heap_free(object);
         return hr;
     }
 
-    wined3d_mutex_lock();
-    *swapchain = wined3d_swapchain_get_parent(wined3d_swapchain);
-    wined3d_mutex_unlock();
+    TRACE("Created swapchain %p.\n", object);
+
+    *swapchain = &object->IDXGISwapChain1_iface;
 
     return S_OK;
 }
@@ -527,6 +503,7 @@ HRESULT dxgi_device_init(struct dxgi_device *device, struct dxgi_device_layer *l
     struct wined3d_device_parent *wined3d_device_parent;
     struct wined3d_swapchain_desc swapchain_desc;
     IWineDXGIDeviceParent *dxgi_device_parent;
+    struct d3d11_swapchain *swapchain;
     struct dxgi_adapter *dxgi_adapter;
     struct dxgi_factory *dxgi_factory;
     void *layer_base;
@@ -589,15 +566,32 @@ HRESULT dxgi_device_init(struct dxgi_device *device, struct dxgi_device_layer *l
     swapchain_desc.swap_effect = WINED3D_SWAP_EFFECT_DISCARD;
     swapchain_desc.device_window = dxgi_factory_get_device_window(dxgi_factory);
     swapchain_desc.windowed = TRUE;
-    if (FAILED(hr = wined3d_device_init_3d(device->wined3d_device, &swapchain_desc)))
+    swapchain_desc.flags = WINED3D_SWAPCHAIN_IMPLICIT;
+
+    if (!(swapchain = heap_alloc_zero(sizeof(*swapchain))))
     {
-        ERR("Failed to initialize 3D, hr %#x.\n", hr);
+        ERR("Failed to allocate swapchain memory.\n");
+        wined3d_device_decref(device->wined3d_device);
+        IUnknown_Release(device->child_layer);
+        wined3d_private_store_cleanup(&device->private_store);
+        wined3d_mutex_unlock();
+        return E_OUTOFMEMORY;
+    }
+
+    if (FAILED(hr = d3d11_swapchain_init(swapchain, device, &swapchain_desc, TRUE)))
+    {
+        WARN("Failed to initialize swapchain, hr %#x.\n", hr);
+        heap_free(swapchain);
         wined3d_device_decref(device->wined3d_device);
         IUnknown_Release(device->child_layer);
         wined3d_private_store_cleanup(&device->private_store);
         wined3d_mutex_unlock();
         return hr;
     }
+    device->implicit_swapchain = swapchain->wined3d_swapchain;
+
+    TRACE("Created swapchain %p.\n", swapchain);
+
     wined3d_mutex_unlock();
 
     device->adapter = &dxgi_adapter->IWineDXGIAdapter_iface;
diff --git a/dlls/dxgi/dxgi_private.h b/dlls/dxgi/dxgi_private.h
index 1461e3c3af7..5c5775ca377 100644
--- a/dlls/dxgi/dxgi_private.h
+++ b/dlls/dxgi/dxgi_private.h
@@ -130,6 +130,7 @@ struct dxgi_device
     LONG refcount;
     struct wined3d_private_store private_store;
     struct wined3d_device *wined3d_device;
+    struct wined3d_swapchain *implicit_swapchain;
     IWineDXGIAdapter *adapter;
 };
 
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index a0c44b5d41c..361ac6b1e36 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -486,6 +486,9 @@ ULONG CDECL wined3d_device_decref(struct wined3d_device *device)
     {
         UINT i;
 
+        if (device->swapchain_count)
+            wined3d_device_uninit_3d(device);
+
         wined3d_stateblock_state_cleanup(&device->stateblock_state);
 
         wined3d_cs_destroy(device->cs);
@@ -1067,30 +1070,19 @@ static HRESULT wined3d_device_create_primary_opengl_context(struct wined3d_devic
     return WINED3D_OK;
 }
 
-HRESULT CDECL wined3d_device_init_3d(struct wined3d_device *device,
-        struct wined3d_swapchain_desc *swapchain_desc)
+HRESULT wined3d_device_set_implicit_swapchain(struct wined3d_device *device, struct wined3d_swapchain *swapchain)
 {
     static const struct wined3d_color black = {0.0f, 0.0f, 0.0f, 0.0f};
-    struct wined3d_swapchain *swapchain = NULL;
+    const struct wined3d_swapchain_desc *swapchain_desc;
     DWORD clear_flags = 0;
     HRESULT hr;
 
-    TRACE("device %p, swapchain_desc %p.\n", device, swapchain_desc);
+    TRACE("device %p, swapchain %p.\n", device, swapchain);
 
     if (device->d3d_initialized)
         return WINED3DERR_INVALIDCALL;
 
-    memset(device->fb.render_targets, 0, sizeof(device->fb.render_targets));
-
-    /* Setup the implicit swapchain. This also initializes a context. */
-    TRACE("Creating implicit swapchain.\n");
-    if (FAILED(hr = device->device_parent->ops->create_swapchain(device->device_parent,
-            swapchain_desc, &swapchain)))
-    {
-        WARN("Failed to create implicit swapchain.\n");
-        goto err_out;
-    }
-
+    swapchain_desc = &swapchain->desc;
     if (swapchain_desc->backbuffer_count && swapchain_desc->backbuffer_bind_flags & WINED3D_BIND_RENDER_TARGET)
     {
         struct wined3d_resource *back_buffer = &swapchain->back_buffers[0]->resource;
@@ -1106,18 +1098,20 @@ HRESULT CDECL wined3d_device_init_3d(struct wined3d_device *device,
                 NULL, &wined3d_null_parent_ops, &device->back_buffer_view)))
         {
             ERR("Failed to create rendertarget view, hr %#x.\n", hr);
-            goto err_out;
+            return hr;
         }
     }
 
     device->swapchain_count = 1;
     if (!(device->swapchains = heap_calloc(device->swapchain_count, sizeof(*device->swapchains))))
     {
-        ERR("Out of memory!\n");
+        ERR("Failed to allocate swapchain array.\n");
+        hr = E_OUTOFMEMORY;
         goto err_out;
     }
     device->swapchains[0] = swapchain;
 
+    memset(device->fb.render_targets, 0, sizeof(device->fb.render_targets));
     if (device->wined3d->flags & WINED3D_NO3D)
     {
         if (!(device->blitter = wined3d_cpu_blitter_create()))
@@ -1125,6 +1119,7 @@ HRESULT CDECL wined3d_device_init_3d(struct wined3d_device *device,
             ERR("Failed to create CPU blitter.\n");
             heap_free(device->swapchains);
             device->swapchain_count = 0;
+            hr = E_FAIL;
             goto err_out;
         }
     }
@@ -1156,11 +1151,13 @@ HRESULT CDECL wined3d_device_init_3d(struct wined3d_device *device,
 
 err_out:
     heap_free(device->swapchains);
+    device->swapchains = NULL;
     device->swapchain_count = 0;
     if (device->back_buffer_view)
+    {
         wined3d_rendertarget_view_decref(device->back_buffer_view);
-    if (swapchain)
-        wined3d_swapchain_decref(swapchain);
+        device->back_buffer_view = NULL;
+    }
 
     return hr;
 }
@@ -1172,24 +1169,42 @@ static void device_free_sampler(struct wine_rb_entry *entry, void *context)
     wined3d_sampler_decref(sampler);
 }
 
-HRESULT CDECL wined3d_device_uninit_3d(struct wined3d_device *device)
+void wined3d_device_uninit_3d(struct wined3d_device *device)
 {
     BOOL no3d = device->wined3d->flags & WINED3D_NO3D;
+    struct wined3d_rendertarget_view *view;
+    struct wined3d_texture *texture;
     unsigned int i;
 
     TRACE("device %p.\n", device);
 
     if (!device->d3d_initialized && !no3d)
-        return WINED3DERR_INVALIDCALL;
+    {
+        ERR("Called while 3D support was not initialised.\n");
+        return;
+    }
 
     wined3d_cs_finish(device->cs, WINED3D_CS_QUEUE_DEFAULT);
 
-    if (device->logo_texture)
-        wined3d_texture_decref(device->logo_texture);
-    if (device->cursor_texture)
-        wined3d_texture_decref(device->cursor_texture);
+    device->swapchain_count = 0;
+
+    if ((texture = device->logo_texture))
+    {
+        device->logo_texture = NULL;
+        wined3d_texture_decref(texture);
+    }
+
+    if ((texture = device->cursor_texture))
+    {
+        device->cursor_texture = NULL;
+        wined3d_texture_decref(texture);
+    }
 
     state_unbind_resources(&device->state);
+    for (i = 0; i < device->adapter->d3d_info.limits.max_rt_count; ++i)
+    {
+        wined3d_device_set_rendertarget_view(device, i, NULL, FALSE);
+    }
 
     wine_rb_clear(&device->samplers, device_free_sampler, NULL);
 
@@ -1198,49 +1213,31 @@ HRESULT CDECL wined3d_device_uninit_3d(struct wined3d_device *device)
     else
         wined3d_device_delete_opengl_contexts(device);
 
-    if (device->fb.depth_stencil)
+    if ((view = device->fb.depth_stencil))
     {
-        struct wined3d_rendertarget_view *view = device->fb.depth_stencil;
-
         TRACE("Releasing depth/stencil view %p.\n", view);
 
         device->fb.depth_stencil = NULL;
         wined3d_rendertarget_view_decref(view);
     }
 
-    if (device->auto_depth_stencil_view)
+    if ((view = device->auto_depth_stencil_view))
     {
-        struct wined3d_rendertarget_view *view = device->auto_depth_stencil_view;
-
         device->auto_depth_stencil_view = NULL;
         if (wined3d_rendertarget_view_decref(view))
             ERR("Something's still holding the auto depth/stencil view (%p).\n", view);
     }
 
-    for (i = 0; i < device->adapter->d3d_info.limits.max_rt_count; ++i)
-    {
-        wined3d_device_set_rendertarget_view(device, i, NULL, FALSE);
-    }
-    if (device->back_buffer_view)
+    if ((view = device->back_buffer_view))
     {
-        wined3d_rendertarget_view_decref(device->back_buffer_view);
         device->back_buffer_view = NULL;
-    }
-
-    for (i = 0; i < device->swapchain_count; ++i)
-    {
-        TRACE("Releasing the implicit swapchain %u.\n", i);
-        if (wined3d_swapchain_decref(device->swapchains[i]))
-            FIXME("Something's still holding the implicit swapchain.\n");
+        wined3d_rendertarget_view_decref(view);
     }
 
     heap_free(device->swapchains);
     device->swapchains = NULL;
-    device->swapchain_count = 0;
 
     device->d3d_initialized = FALSE;
-
-    return WINED3D_OK;
 }
 
 /* Enables thread safety in the wined3d device and its resources. Called by DirectDraw
@@ -4825,6 +4822,7 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device,
 {
     const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info;
     struct wined3d_resource *resource, *cursor;
+    struct wined3d_rendertarget_view *view;
     struct wined3d_swapchain *swapchain;
     struct wined3d_view_desc view_desc;
     BOOL backbuffer_resized;
@@ -4959,10 +4957,10 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device,
         }
     }
 
-    if (device->auto_depth_stencil_view)
+    if ((view = device->auto_depth_stencil_view))
     {
-        wined3d_rendertarget_view_decref(device->auto_depth_stencil_view);
         device->auto_depth_stencil_view = NULL;
+        wined3d_rendertarget_view_decref(view);
     }
     if (swapchain->desc.enable_auto_depth_stencil)
     {
@@ -5008,10 +5006,10 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device,
         wined3d_device_set_depth_stencil_view(device, device->auto_depth_stencil_view);
     }
 
-    if (device->back_buffer_view)
+    if ((view = device->back_buffer_view))
     {
-        wined3d_rendertarget_view_decref(device->back_buffer_view);
         device->back_buffer_view = NULL;
+        wined3d_rendertarget_view_decref(view);
     }
     if (swapchain->desc.backbuffer_count && swapchain->desc.backbuffer_bind_flags & WINED3D_BIND_RENDER_TARGET)
     {
@@ -5057,9 +5055,8 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device,
         if (wined3d_settings.logo)
             device_load_logo(device, wined3d_settings.logo);
     }
-    else if (device->back_buffer_view)
+    else if ((view = device->back_buffer_view))
     {
-        struct wined3d_rendertarget_view *view = device->back_buffer_view;
         struct wined3d_state *state = &device->state;
 
         wined3d_device_set_rendertarget_view(device, 0, view, FALSE);
diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c
index c5060f93fc3..c1429de91b1 100644
--- a/dlls/wined3d/swapchain.c
+++ b/dlls/wined3d/swapchain.c
@@ -114,9 +114,14 @@ ULONG CDECL wined3d_swapchain_decref(struct wined3d_swapchain *swapchain)
 
     if (!refcount)
     {
+        struct wined3d_device *device;
+
         wined3d_mutex_lock();
 
-        wined3d_cs_finish(swapchain->device->cs, WINED3D_CS_QUEUE_DEFAULT);
+        device = swapchain->device;
+        if (device->swapchain_count && device->swapchains[0] == swapchain)
+            wined3d_device_uninit_3d(device);
+        wined3d_cs_finish(device->cs, WINED3D_CS_QUEUE_DEFAULT);
 
         swapchain_cleanup(swapchain);
         swapchain->parent_ops->wined3d_object_destroyed(swapchain->parent);
@@ -1053,6 +1058,20 @@ HRESULT CDECL wined3d_swapchain_create(struct wined3d_device *device, struct win
         return hr;
     }
 
+    if (desc->flags & WINED3D_SWAPCHAIN_IMPLICIT)
+    {
+        wined3d_mutex_lock();
+        if (FAILED(hr = wined3d_device_set_implicit_swapchain(device, object)))
+        {
+            wined3d_cs_finish(device->cs, WINED3D_CS_QUEUE_DEFAULT);
+            swapchain_cleanup(object);
+            wined3d_mutex_unlock();
+            heap_free(swapchain);
+            return hr;
+        }
+        wined3d_mutex_unlock();
+    }
+
     TRACE("Created swapchain %p.\n", object);
     *swapchain = object;
 
diff --git a/dlls/wined3d/wined3d.spec b/dlls/wined3d/wined3d.spec
index 704e19db46b..040b9fc4ac1 100644
--- a/dlls/wined3d/wined3d.spec
+++ b/dlls/wined3d/wined3d.spec
@@ -120,7 +120,6 @@
 @ cdecl wined3d_device_get_vs_sampler(ptr long)
 @ cdecl wined3d_device_get_wined3d(ptr)
 @ cdecl wined3d_device_incref(ptr)
-@ cdecl wined3d_device_init_3d(ptr ptr)
 @ cdecl wined3d_device_multiply_transform(ptr long ptr)
 @ cdecl wined3d_device_process_vertices(ptr long long long ptr ptr long long)
 @ cdecl wined3d_device_release_focus_window(ptr)
@@ -188,7 +187,6 @@
 @ cdecl wined3d_device_set_vs_sampler(ptr long ptr)
 @ cdecl wined3d_device_setup_fullscreen_window(ptr ptr long long)
 @ cdecl wined3d_device_show_cursor(ptr long)
-@ cdecl wined3d_device_uninit_3d(ptr)
 @ cdecl wined3d_device_update_sub_resource(ptr ptr long ptr ptr long long long)
 @ cdecl wined3d_device_update_texture(ptr ptr ptr)
 @ cdecl wined3d_device_validate_device(ptr ptr)
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index bfc911ef473..9f63f3d8d62 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -3177,6 +3177,9 @@ LRESULT device_process_message(struct wined3d_device *device, HWND window, BOOL
 void device_resource_add(struct wined3d_device *device, struct wined3d_resource *resource) DECLSPEC_HIDDEN;
 void device_resource_released(struct wined3d_device *device, struct wined3d_resource *resource) DECLSPEC_HIDDEN;
 void device_invalidate_state(const struct wined3d_device *device, DWORD state) DECLSPEC_HIDDEN;
+HRESULT wined3d_device_set_implicit_swapchain(struct wined3d_device *device,
+        struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN;
+void wined3d_device_uninit_3d(struct wined3d_device *device) DECLSPEC_HIDDEN;
 
 struct wined3d_device_gl
 {
diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h
index 8a29ef63999..958ade166c0 100644
--- a/include/wine/wined3d.h
+++ b/include/wine/wined3d.h
@@ -902,6 +902,7 @@ enum wined3d_shader_type
 #define WINED3D_SWAPCHAIN_USE_CLOSEST_MATCHING_MODE             0x00002000u
 #define WINED3D_SWAPCHAIN_RESTORE_WINDOW_RECT                   0x00004000u
 #define WINED3D_SWAPCHAIN_GDI_COMPATIBLE                        0x00008000u
+#define WINED3D_SWAPCHAIN_IMPLICIT                              0x00010000u
 
 #define WINED3DDP_MAXTEXCOORD                                   8
 
@@ -2145,8 +2146,6 @@ struct wined3d_device_parent_ops
             void **parent, const struct wined3d_parent_ops **parent_ops);
     HRESULT (__cdecl *create_swapchain_texture)(struct wined3d_device_parent *device_parent, void *parent,
             const struct wined3d_resource_desc *desc, DWORD texture_flags, struct wined3d_texture **texture);
-    HRESULT (__cdecl *create_swapchain)(struct wined3d_device_parent *device_parent,
-            struct wined3d_swapchain_desc *desc, struct wined3d_swapchain **swapchain);
 };
 
 struct wined3d_private_store
@@ -2363,7 +2362,6 @@ struct wined3d_shader_resource_view * __cdecl wined3d_device_get_vs_resource_vie
 struct wined3d_sampler * __cdecl wined3d_device_get_vs_sampler(const struct wined3d_device *device, UINT idx);
 struct wined3d * __cdecl wined3d_device_get_wined3d(const struct wined3d_device *device);
 ULONG __cdecl wined3d_device_incref(struct wined3d_device *device);
-HRESULT __cdecl wined3d_device_init_3d(struct wined3d_device *device, struct wined3d_swapchain_desc *swapchain_desc);
 void __cdecl wined3d_device_multiply_transform(struct wined3d_device *device,
         enum wined3d_transform_state state, const struct wined3d_matrix *matrix);
 HRESULT __cdecl wined3d_device_process_vertices(struct wined3d_device *device,
@@ -2480,7 +2478,6 @@ void __cdecl wined3d_device_set_vs_resource_view(struct wined3d_device *device,
 void __cdecl wined3d_device_set_vs_sampler(struct wined3d_device *device, UINT idx, struct wined3d_sampler *sampler);
 void __cdecl wined3d_device_setup_fullscreen_window(struct wined3d_device *device, HWND window, UINT w, UINT h);
 BOOL __cdecl wined3d_device_show_cursor(struct wined3d_device *device, BOOL show);
-HRESULT __cdecl wined3d_device_uninit_3d(struct wined3d_device *device);
 void __cdecl wined3d_device_update_sub_resource(struct wined3d_device *device, struct wined3d_resource *resource,
         unsigned int sub_resource_idx, const struct wined3d_box *box, const void *data, unsigned int row_pitch,
         unsigned int depth_pitch, unsigned int flags);
diff --git a/include/wine/winedxgi.idl b/include/wine/winedxgi.idl
index 84440901a9e..610b7c0485c 100644
--- a/include/wine/winedxgi.idl
+++ b/include/wine/winedxgi.idl
@@ -51,11 +51,6 @@ interface IWineDXGIDevice : IDXGIDevice2
         [in] IUnknown *outer,
         [out] void **surface
     );
-    HRESULT create_swapchain(
-        [in] struct wined3d_swapchain_desc *desc,
-        [in] BOOL implicit,
-        [out] struct wined3d_swapchain **wined3d_swapchain
-    );
 }
 
 [
-- 
2.11.0




More information about the wine-devel mailing list