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.
This commit is contained in:
Henri Verbeet 2011-04-07 18:46:01 +02:00 committed by Alexandre Julliard
parent d19c3588bc
commit dd2c7d0d8c
8 changed files with 77 additions and 16 deletions

View File

@ -54,6 +54,15 @@ static ULONG WINAPI IDirect3DSwapChain8Impl_AddRef(IDirect3DSwapChain8 *iface)
TRACE("%p increasing refcount to %u.\n", iface, ref); 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; return ref;
} }
@ -64,13 +73,16 @@ static ULONG WINAPI IDirect3DSwapChain8Impl_Release(IDirect3DSwapChain8 *iface)
TRACE("%p decreasing refcount to %u.\n", iface, ref); TRACE("%p decreasing refcount to %u.\n", iface, ref);
if (ref == 0) { if (!ref)
{
IDirect3DDevice8 *parentDevice = This->parentDevice;
wined3d_mutex_lock(); wined3d_mutex_lock();
IWineD3DSwapChain_Destroy(This->wineD3DSwapChain); IWineD3DSwapChain_Destroy(This->wineD3DSwapChain);
wined3d_mutex_unlock(); wined3d_mutex_unlock();
if (This->parentDevice) IUnknown_Release(This->parentDevice); if (parentDevice)
HeapFree(GetProcessHeap(), 0, This); IDirect3DDevice8_Release(parentDevice);
} }
return ref; return ref;
} }
@ -125,6 +137,16 @@ static const IDirect3DSwapChain8Vtbl Direct3DSwapChain8_Vtbl =
IDirect3DSwapChain8Impl_GetBackBuffer 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, HRESULT swapchain_init(IDirect3DSwapChain8Impl *swapchain, IDirect3DDevice8Impl *device,
D3DPRESENT_PARAMETERS *present_parameters) D3DPRESENT_PARAMETERS *present_parameters)
{ {
@ -152,7 +174,8 @@ HRESULT swapchain_init(IDirect3DSwapChain8Impl *swapchain, IDirect3DDevice8Impl
wined3d_mutex_lock(); wined3d_mutex_lock();
hr = IWineD3DDevice_CreateSwapChain(device->WineD3DDevice, &wined3d_parameters, 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(); wined3d_mutex_unlock();
present_parameters->BackBufferWidth = wined3d_parameters.BackBufferWidth; present_parameters->BackBufferWidth = wined3d_parameters.BackBufferWidth;

View File

@ -50,7 +50,18 @@ static ULONG WINAPI IDirect3DSwapChain9Impl_AddRef(LPDIRECT3DSWAPCHAIN9 iface) {
TRACE("%p increasing refcount to %u.\n", iface, ref); 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; return ref;
} }
@ -68,8 +79,6 @@ static ULONG WINAPI IDirect3DSwapChain9Impl_Release(LPDIRECT3DSWAPCHAIN9 iface)
wined3d_mutex_lock(); wined3d_mutex_lock();
IWineD3DSwapChain_Destroy(This->wineD3DSwapChain); IWineD3DSwapChain_Destroy(This->wineD3DSwapChain);
wined3d_mutex_unlock(); wined3d_mutex_unlock();
HeapFree(GetProcessHeap(), 0, This);
} }
/* Release the device last, as it may cause the device to be destroyed. */ /* Release the device last, as it may cause the device to be destroyed. */
@ -217,6 +226,16 @@ static const IDirect3DSwapChain9Vtbl Direct3DSwapChain9_Vtbl =
IDirect3DSwapChain9Impl_GetPresentParameters 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, HRESULT swapchain_init(IDirect3DSwapChain9Impl *swapchain, IDirect3DDevice9Impl *device,
D3DPRESENT_PARAMETERS *present_parameters) D3DPRESENT_PARAMETERS *present_parameters)
{ {
@ -244,7 +263,8 @@ HRESULT swapchain_init(IDirect3DSwapChain9Impl *swapchain, IDirect3DDevice9Impl
wined3d_mutex_lock(); wined3d_mutex_lock();
hr = IWineD3DDevice_CreateSwapChain(device->WineD3DDevice, &wined3d_parameters, 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(); wined3d_mutex_unlock();
present_parameters->BackBufferWidth = wined3d_parameters.BackBufferWidth; present_parameters->BackBufferWidth = wined3d_parameters.BackBufferWidth;

View File

@ -5905,7 +5905,7 @@ static HRESULT STDMETHODCALLTYPE device_parent_CreateSwapChain(IWineD3DDevicePar
TRACE("iface %p, present_parameters %p, swapchain %p\n", iface, present_parameters, swapchain); TRACE("iface %p, present_parameters %p, swapchain %p\n", iface, present_parameters, swapchain);
hr = IWineD3DDevice_CreateSwapChain(This->wineD3DDevice, present_parameters, hr = IWineD3DDevice_CreateSwapChain(This->wineD3DDevice, present_parameters,
This->ImplType, NULL, swapchain); This->ImplType, NULL, &ddraw_null_wined3d_parent_ops, swapchain);
if (FAILED(hr)) if (FAILED(hr))
{ {
FIXME("(%p) CreateSwapChain failed, returning %#x\n", iface, hr); FIXME("(%p) CreateSwapChain failed, returning %#x\n", iface, hr);

View File

@ -53,6 +53,9 @@ static ULONG STDMETHODCALLTYPE dxgi_swapchain_AddRef(IDXGISwapChain *iface)
TRACE("%p increasing refcount to %u\n", This, refcount); TRACE("%p increasing refcount to %u\n", This, refcount);
if (refcount == 1)
IWineD3DSwapChain_AddRef(This->wined3d_swapchain);
return refcount; return refcount;
} }
@ -91,8 +94,6 @@ static ULONG STDMETHODCALLTYPE dxgi_swapchain_Release(IDXGISwapChain *iface)
ERR("Uninit3D failed, hr %#x\n", hr); ERR("Uninit3D failed, hr %#x\n", hr);
} }
} }
HeapFree(GetProcessHeap(), 0, This);
} }
return refcount; return refcount;
@ -269,6 +270,16 @@ static const struct IDXGISwapChainVtbl dxgi_swapchain_vtbl =
dxgi_swapchain_GetLastPresentCount, 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, HRESULT dxgi_swapchain_init(struct dxgi_swapchain *swapchain, struct dxgi_device *device,
WINED3DPRESENT_PARAMETERS *present_parameters) WINED3DPRESENT_PARAMETERS *present_parameters)
{ {
@ -278,7 +289,8 @@ HRESULT dxgi_swapchain_init(struct dxgi_swapchain *swapchain, struct dxgi_device
swapchain->refcount = 1; swapchain->refcount = 1;
hr = IWineD3DDevice_CreateSwapChain(device->wined3d_device, present_parameters, 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)) if (FAILED(hr))
{ {
WARN("Failed to create wined3d swapchain, hr %#x.\n", hr); WARN("Failed to create wined3d swapchain, hr %#x.\n", hr);

View File

@ -1278,7 +1278,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface,
/* Do not call while under the GL lock. */ /* Do not call while under the GL lock. */
static HRESULT WINAPI IWineD3DDeviceImpl_CreateSwapChain(IWineD3DDevice *iface, static HRESULT WINAPI IWineD3DDeviceImpl_CreateSwapChain(IWineD3DDevice *iface,
WINED3DPRESENT_PARAMETERS *present_parameters, WINED3DSURFTYPE surface_type, 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; IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
IWineD3DSwapChainImpl *object; IWineD3DSwapChainImpl *object;
@ -1294,7 +1294,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateSwapChain(IWineD3DDevice *iface,
return E_OUTOFMEMORY; 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)) if (FAILED(hr))
{ {
WARN("Failed to initialize swapchain, hr %#x.\n", hr); WARN("Failed to initialize swapchain, hr %#x.\n", hr);

View File

@ -80,6 +80,7 @@ static void WINAPI IWineD3DBaseSwapChainImpl_Destroy(IWineD3DSwapChain *iface)
IWineD3DDevice_SetDisplayMode((IWineD3DDevice *)swapchain->device, 0, &mode); IWineD3DDevice_SetDisplayMode((IWineD3DDevice *)swapchain->device, 0, &mode);
} }
swapchain->parent_ops->wined3d_object_destroyed(swapchain->parent);
HeapFree(GetProcessHeap(), 0, swapchain->context); HeapFree(GetProcessHeap(), 0, swapchain->context);
HeapFree(GetProcessHeap(), 0, swapchain); HeapFree(GetProcessHeap(), 0, swapchain);
} }
@ -860,7 +861,8 @@ static const IWineD3DSwapChainVtbl IWineGDISwapChain_Vtbl =
/* Do not call while under the GL lock. */ /* Do not call while under the GL lock. */
HRESULT swapchain_init(IWineD3DSwapChainImpl *swapchain, WINED3DSURFTYPE surface_type, 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_adapter *adapter = device->adapter;
const struct wined3d_format *format; const struct wined3d_format *format;
@ -903,6 +905,7 @@ HRESULT swapchain_init(IWineD3DSwapChainImpl *swapchain, WINED3DSURFTYPE surface
swapchain->device = device; swapchain->device = device;
swapchain->parent = parent; swapchain->parent = parent;
swapchain->parent_ops = parent_ops;
swapchain->ref = 1; swapchain->ref = 1;
swapchain->win_handle = window; swapchain->win_handle = window;
swapchain->device_window = window; swapchain->device_window = window;

View File

@ -2530,6 +2530,7 @@ struct IWineD3DSwapChainImpl
LONG ref; /* Note: Ref counting not required */ LONG ref; /* Note: Ref counting not required */
void *parent; void *parent;
const struct wined3d_parent_ops *parent_ops;
IWineD3DDeviceImpl *device; IWineD3DDeviceImpl *device;
/* IWineD3DSwapChain fields */ /* 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; struct wined3d_context *swapchain_get_context(struct IWineD3DSwapChainImpl *swapchain) DECLSPEC_HIDDEN;
HRESULT swapchain_init(IWineD3DSwapChainImpl *swapchain, WINED3DSURFTYPE surface_type, 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 #define DEFAULT_REFRESH_RATE 0

View File

@ -2481,6 +2481,7 @@ interface IWineD3DDevice : IUnknown
[in] WINED3DPRESENT_PARAMETERS *present_parameters, [in] WINED3DPRESENT_PARAMETERS *present_parameters,
[in] WINED3DSURFTYPE surface_type, [in] WINED3DSURFTYPE surface_type,
[in] void *parent, [in] void *parent,
[in] const struct wined3d_parent_ops *parent_ops,
[out] IWineD3DSwapChain **swapchain [out] IWineD3DSwapChain **swapchain
); );
HRESULT CreateVertexDeclaration( HRESULT CreateVertexDeclaration(