Commit dd2c7d0d authored by Henri Verbeet's avatar Henri Verbeet Committed by Alexandre Julliard

wined3d: Don't free D3D swapchains until the wined3d swapchain is destroyed.

This will allow us the get rid of the swapchain refcounting hacks in d3d9 in particular. This is similar to the way we handle resources that are still in use by a stateblock, but aren't referenced anywhere by the application.
parent d19c3588
......@@ -54,6 +54,15 @@ static ULONG WINAPI IDirect3DSwapChain8Impl_AddRef(IDirect3DSwapChain8 *iface)
TRACE("%p increasing refcount to %u.\n", iface, ref);
if (ref == 1)
{
if (This->parentDevice)
IDirect3DDevice8_AddRef(This->parentDevice);
wined3d_mutex_lock();
IWineD3DSwapChain_AddRef(This->wineD3DSwapChain);
wined3d_mutex_unlock();
}
return ref;
}
......@@ -64,13 +73,16 @@ static ULONG WINAPI IDirect3DSwapChain8Impl_Release(IDirect3DSwapChain8 *iface)
TRACE("%p decreasing refcount to %u.\n", iface, ref);
if (ref == 0) {
if (!ref)
{
IDirect3DDevice8 *parentDevice = This->parentDevice;
wined3d_mutex_lock();
IWineD3DSwapChain_Destroy(This->wineD3DSwapChain);
wined3d_mutex_unlock();
if (This->parentDevice) IUnknown_Release(This->parentDevice);
HeapFree(GetProcessHeap(), 0, This);
if (parentDevice)
IDirect3DDevice8_Release(parentDevice);
}
return ref;
}
......@@ -125,6 +137,16 @@ static const IDirect3DSwapChain8Vtbl Direct3DSwapChain8_Vtbl =
IDirect3DSwapChain8Impl_GetBackBuffer
};
static void STDMETHODCALLTYPE d3d8_swapchain_wined3d_object_released(void *parent)
{
HeapFree(GetProcessHeap(), 0, parent);
}
static const struct wined3d_parent_ops d3d8_swapchain_wined3d_parent_ops =
{
d3d8_swapchain_wined3d_object_released,
};
HRESULT swapchain_init(IDirect3DSwapChain8Impl *swapchain, IDirect3DDevice8Impl *device,
D3DPRESENT_PARAMETERS *present_parameters)
{
......@@ -152,7 +174,8 @@ HRESULT swapchain_init(IDirect3DSwapChain8Impl *swapchain, IDirect3DDevice8Impl
wined3d_mutex_lock();
hr = IWineD3DDevice_CreateSwapChain(device->WineD3DDevice, &wined3d_parameters,
SURFACE_OPENGL, swapchain, &swapchain->wineD3DSwapChain);
SURFACE_OPENGL, swapchain, &d3d8_swapchain_wined3d_parent_ops,
&swapchain->wineD3DSwapChain);
wined3d_mutex_unlock();
present_parameters->BackBufferWidth = wined3d_parameters.BackBufferWidth;
......
......@@ -50,7 +50,18 @@ static ULONG WINAPI IDirect3DSwapChain9Impl_AddRef(LPDIRECT3DSWAPCHAIN9 iface) {
TRACE("%p increasing refcount to %u.\n", iface, ref);
if(ref == 1 && This->parentDevice) IDirect3DDevice9Ex_AddRef(This->parentDevice);
if (ref == 1)
{
if (This->parentDevice)
IDirect3DDevice9Ex_AddRef(This->parentDevice);
if (!This->isImplicit)
{
wined3d_mutex_lock();
IWineD3DSwapChain_AddRef(This->wineD3DSwapChain);
wined3d_mutex_unlock();
}
}
return ref;
}
......@@ -68,8 +79,6 @@ static ULONG WINAPI IDirect3DSwapChain9Impl_Release(LPDIRECT3DSWAPCHAIN9 iface)
wined3d_mutex_lock();
IWineD3DSwapChain_Destroy(This->wineD3DSwapChain);
wined3d_mutex_unlock();
HeapFree(GetProcessHeap(), 0, This);
}
/* Release the device last, as it may cause the device to be destroyed. */
......@@ -217,6 +226,16 @@ static const IDirect3DSwapChain9Vtbl Direct3DSwapChain9_Vtbl =
IDirect3DSwapChain9Impl_GetPresentParameters
};
static void STDMETHODCALLTYPE d3d9_swapchain_wined3d_object_released(void *parent)
{
HeapFree(GetProcessHeap(), 0, parent);
}
static const struct wined3d_parent_ops d3d9_swapchain_wined3d_parent_ops =
{
d3d9_swapchain_wined3d_object_released,
};
HRESULT swapchain_init(IDirect3DSwapChain9Impl *swapchain, IDirect3DDevice9Impl *device,
D3DPRESENT_PARAMETERS *present_parameters)
{
......@@ -244,7 +263,8 @@ HRESULT swapchain_init(IDirect3DSwapChain9Impl *swapchain, IDirect3DDevice9Impl
wined3d_mutex_lock();
hr = IWineD3DDevice_CreateSwapChain(device->WineD3DDevice, &wined3d_parameters,
SURFACE_OPENGL, swapchain, &swapchain->wineD3DSwapChain);
SURFACE_OPENGL, swapchain, &d3d9_swapchain_wined3d_parent_ops,
&swapchain->wineD3DSwapChain);
wined3d_mutex_unlock();
present_parameters->BackBufferWidth = wined3d_parameters.BackBufferWidth;
......
......@@ -5905,7 +5905,7 @@ static HRESULT STDMETHODCALLTYPE device_parent_CreateSwapChain(IWineD3DDevicePar
TRACE("iface %p, present_parameters %p, swapchain %p\n", iface, present_parameters, swapchain);
hr = IWineD3DDevice_CreateSwapChain(This->wineD3DDevice, present_parameters,
This->ImplType, NULL, swapchain);
This->ImplType, NULL, &ddraw_null_wined3d_parent_ops, swapchain);
if (FAILED(hr))
{
FIXME("(%p) CreateSwapChain failed, returning %#x\n", iface, hr);
......
......@@ -53,6 +53,9 @@ static ULONG STDMETHODCALLTYPE dxgi_swapchain_AddRef(IDXGISwapChain *iface)
TRACE("%p increasing refcount to %u\n", This, refcount);
if (refcount == 1)
IWineD3DSwapChain_AddRef(This->wined3d_swapchain);
return refcount;
}
......@@ -91,8 +94,6 @@ static ULONG STDMETHODCALLTYPE dxgi_swapchain_Release(IDXGISwapChain *iface)
ERR("Uninit3D failed, hr %#x\n", hr);
}
}
HeapFree(GetProcessHeap(), 0, This);
}
return refcount;
......@@ -269,6 +270,16 @@ static const struct IDXGISwapChainVtbl dxgi_swapchain_vtbl =
dxgi_swapchain_GetLastPresentCount,
};
static void STDMETHODCALLTYPE dxgi_swapchain_wined3d_object_released(void *parent)
{
HeapFree(GetProcessHeap(), 0, parent);
}
static const struct wined3d_parent_ops dxgi_swapchain_wined3d_parent_ops =
{
dxgi_swapchain_wined3d_object_released,
};
HRESULT dxgi_swapchain_init(struct dxgi_swapchain *swapchain, struct dxgi_device *device,
WINED3DPRESENT_PARAMETERS *present_parameters)
{
......@@ -278,7 +289,8 @@ HRESULT dxgi_swapchain_init(struct dxgi_swapchain *swapchain, struct dxgi_device
swapchain->refcount = 1;
hr = IWineD3DDevice_CreateSwapChain(device->wined3d_device, present_parameters,
SURFACE_OPENGL, swapchain, &swapchain->wined3d_swapchain);
SURFACE_OPENGL, swapchain, &dxgi_swapchain_wined3d_parent_ops,
&swapchain->wined3d_swapchain);
if (FAILED(hr))
{
WARN("Failed to create wined3d swapchain, hr %#x.\n", hr);
......
......@@ -1278,7 +1278,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface,
/* Do not call while under the GL lock. */
static HRESULT WINAPI IWineD3DDeviceImpl_CreateSwapChain(IWineD3DDevice *iface,
WINED3DPRESENT_PARAMETERS *present_parameters, WINED3DSURFTYPE surface_type,
void *parent, IWineD3DSwapChain **swapchain)
void *parent, const struct wined3d_parent_ops *parent_ops, IWineD3DSwapChain **swapchain)
{
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
IWineD3DSwapChainImpl *object;
......@@ -1294,7 +1294,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateSwapChain(IWineD3DDevice *iface,
return E_OUTOFMEMORY;
}
hr = swapchain_init(object, surface_type, This, present_parameters, parent);
hr = swapchain_init(object, surface_type, This, present_parameters, parent, parent_ops);
if (FAILED(hr))
{
WARN("Failed to initialize swapchain, hr %#x.\n", hr);
......
......@@ -80,6 +80,7 @@ static void WINAPI IWineD3DBaseSwapChainImpl_Destroy(IWineD3DSwapChain *iface)
IWineD3DDevice_SetDisplayMode((IWineD3DDevice *)swapchain->device, 0, &mode);
}
swapchain->parent_ops->wined3d_object_destroyed(swapchain->parent);
HeapFree(GetProcessHeap(), 0, swapchain->context);
HeapFree(GetProcessHeap(), 0, swapchain);
}
......@@ -860,7 +861,8 @@ static const IWineD3DSwapChainVtbl IWineGDISwapChain_Vtbl =
/* Do not call while under the GL lock. */
HRESULT swapchain_init(IWineD3DSwapChainImpl *swapchain, WINED3DSURFTYPE surface_type,
IWineD3DDeviceImpl *device, WINED3DPRESENT_PARAMETERS *present_parameters, void *parent)
IWineD3DDeviceImpl *device, WINED3DPRESENT_PARAMETERS *present_parameters,
void *parent, const struct wined3d_parent_ops *parent_ops)
{
const struct wined3d_adapter *adapter = device->adapter;
const struct wined3d_format *format;
......@@ -903,6 +905,7 @@ HRESULT swapchain_init(IWineD3DSwapChainImpl *swapchain, WINED3DSURFTYPE surface
swapchain->device = device;
swapchain->parent = parent;
swapchain->parent_ops = parent_ops;
swapchain->ref = 1;
swapchain->win_handle = window;
swapchain->device_window = window;
......
......@@ -2530,6 +2530,7 @@ struct IWineD3DSwapChainImpl
LONG ref; /* Note: Ref counting not required */
void *parent;
const struct wined3d_parent_ops *parent_ops;
IWineD3DDeviceImpl *device;
/* IWineD3DSwapChain fields */
......@@ -2556,7 +2557,8 @@ void x11_copy_to_screen(IWineD3DSwapChainImpl *This, const RECT *rc) DECLSPEC_HI
struct wined3d_context *swapchain_get_context(struct IWineD3DSwapChainImpl *swapchain) DECLSPEC_HIDDEN;
HRESULT swapchain_init(IWineD3DSwapChainImpl *swapchain, WINED3DSURFTYPE surface_type,
IWineD3DDeviceImpl *device, WINED3DPRESENT_PARAMETERS *present_parameters, void *parent) DECLSPEC_HIDDEN;
IWineD3DDeviceImpl *device, WINED3DPRESENT_PARAMETERS *present_parameters,
void *parent, const struct wined3d_parent_ops *parent_ops) DECLSPEC_HIDDEN;
#define DEFAULT_REFRESH_RATE 0
......
......@@ -2481,6 +2481,7 @@ interface IWineD3DDevice : IUnknown
[in] WINED3DPRESENT_PARAMETERS *present_parameters,
[in] WINED3DSURFTYPE surface_type,
[in] void *parent,
[in] const struct wined3d_parent_ops *parent_ops,
[out] IWineD3DSwapChain **swapchain
);
HRESULT CreateVertexDeclaration(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment