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

wined3d: Don't free D3D surfaces until the wined3d surface is destroyed.

This prevents for example a d3d9 depth stencil from being destroyed when it has no external references but is still in use by the device/stateblock. A nice side effect is that it simplifies handling of "implicit" surfaces like the frontbuffer and backbuffers, as well as the forwarding of reference counts for surfaces that are part of a texture.
parent 6b6d8ccc
......@@ -1379,6 +1379,8 @@ static HRESULT STDMETHODCALLTYPE device_parent_CreateSurface(IWineD3DDeviceParen
}
*surface = texture->wined3d_surface;
IWineD3DSurface_AddRef(*surface);
ID3D10Texture2D_Release((ID3D10Texture2D *)texture);
return S_OK;
}
......@@ -1418,6 +1420,8 @@ static HRESULT STDMETHODCALLTYPE device_parent_CreateRenderTarget(IWineD3DDevice
}
*surface = texture->wined3d_surface;
IWineD3DSurface_AddRef(*surface);
ID3D10Texture2D_Release((ID3D10Texture2D *)texture);
return S_OK;
}
......@@ -1457,6 +1461,8 @@ static HRESULT STDMETHODCALLTYPE device_parent_CreateDepthStencilSurface(IWineD3
}
*surface = texture->wined3d_surface;
IWineD3DSurface_AddRef(*surface);
ID3D10Texture2D_Release((ID3D10Texture2D *)texture);
return S_OK;
}
......
......@@ -61,9 +61,19 @@ static ULONG STDMETHODCALLTYPE d3d10_texture2d_AddRef(ID3D10Texture2D *iface)
TRACE("%p increasing refcount to %u\n", This, refcount);
if (refcount == 1 && This->wined3d_surface) IWineD3DSurface_AddRef(This->wined3d_surface);
return refcount;
}
static void STDMETHODCALLTYPE d3d10_texture2d_wined3d_object_released(void *parent)
{
struct d3d10_texture2d *This = parent;
if (This->dxgi_surface) IDXGISurface_Release(This->dxgi_surface);
HeapFree(GetProcessHeap(), 0, This);
}
static ULONG STDMETHODCALLTYPE d3d10_texture2d_Release(ID3D10Texture2D *iface)
{
struct d3d10_texture2d *This = (struct d3d10_texture2d *)iface;
......@@ -73,9 +83,8 @@ static ULONG STDMETHODCALLTYPE d3d10_texture2d_Release(ID3D10Texture2D *iface)
if (!refcount)
{
if (This->dxgi_surface) IDXGISurface_Release(This->dxgi_surface);
if (This->wined3d_surface) IWineD3DSurface_Release(This->wined3d_surface);
HeapFree(GetProcessHeap(), 0, This);
else d3d10_texture2d_wined3d_object_released(This);
}
return refcount;
......@@ -182,6 +191,11 @@ static const struct ID3D10Texture2DVtbl d3d10_texture2d_vtbl =
d3d10_texture2d_GetDesc,
};
static const struct wined3d_parent_ops d3d10_texture2d_wined3d_parent_ops =
{
d3d10_texture2d_wined3d_object_released,
};
HRESULT d3d10_texture2d_init(struct d3d10_texture2d *texture, struct d3d10_device *device,
const D3D10_TEXTURE2D_DESC *desc)
{
......@@ -217,7 +231,8 @@ HRESULT d3d10_texture2d_init(struct d3d10_texture2d *texture, struct d3d10_devic
wined3dformat_from_dxgi_format(desc->Format), FALSE, FALSE, 0,
&texture->wined3d_surface, desc->Usage, WINED3DPOOL_DEFAULT,
desc->SampleDesc.Count > 1 ? desc->SampleDesc.Count : WINED3DMULTISAMPLE_NONE,
desc->SampleDesc.Quality, SURFACE_OPENGL, (IUnknown *)texture);
desc->SampleDesc.Quality, SURFACE_OPENGL, (IUnknown *)texture,
&d3d10_texture2d_wined3d_parent_ops);
if (FAILED(hr))
{
ERR("CreateSurface failed, returning %#x\n", hr);
......
......@@ -59,7 +59,7 @@ static ULONG WINAPI IDirect3DCubeTexture8Impl_Release(LPDIRECT3DCUBETEXTURE8 ifa
TRACE("Releasing child %p\n", This->wineD3DCubeTexture);
wined3d_mutex_lock();
IWineD3DCubeTexture_Destroy(This->wineD3DCubeTexture, D3D8CB_DestroySurface);
IWineD3DCubeTexture_Destroy(This->wineD3DCubeTexture);
wined3d_mutex_unlock();
IUnknown_Release(This->parentDevice);
......
......@@ -284,9 +284,6 @@ struct IDirect3DSurface8Impl
/* If set forward refcounting to this object */
IUnknown *forwardReference;
/* Flags an implicit surface */
BOOL isImplicit;
};
HRESULT surface_init(IDirect3DSurface8Impl *surface, IDirect3DDevice8Impl *device,
......@@ -650,9 +647,6 @@ size_t parse_token(const DWORD* pToken);
/* Callbacks */
extern ULONG WINAPI D3D8CB_DestroySwapChain (IWineD3DSwapChain *pSwapChain);
extern ULONG WINAPI D3D8CB_DestroyDepthStencilSurface (IWineD3DSurface *pSurface);
extern ULONG WINAPI D3D8CB_DestroyRenderTarget (IWineD3DSurface *pSurface);
extern ULONG WINAPI D3D8CB_DestroySurface(IWineD3DSurface *pSurface);
extern ULONG WINAPI D3D8CB_DestroyVolume(IWineD3DVolume *pVolume);
#endif /* __WINE_D3DX8_PRIVATE_H */
......@@ -309,7 +309,7 @@ static ULONG WINAPI IDirect3DDevice8Impl_Release(LPDIRECT3DDEVICE8 iface) {
}
HeapFree(GetProcessHeap(), 0, This->decls);
IWineD3DDevice_Uninit3D(This->WineD3DDevice, D3D8CB_DestroyDepthStencilSurface, D3D8CB_DestroySwapChain);
IWineD3DDevice_Uninit3D(This->WineD3DDevice, D3D8CB_DestroySwapChain);
IWineD3DDevice_Release(This->WineD3DDevice);
HeapFree(GetProcessHeap(), 0, This->handle_table.entries);
HeapFree(GetProcessHeap(), 0, This);
......@@ -2602,17 +2602,6 @@ const IDirect3DDevice8Vtbl Direct3DDevice8_Vtbl =
IDirect3DDevice8Impl_DeletePatch
};
ULONG WINAPI D3D8CB_DestroySurface(IWineD3DSurface *pSurface) {
IDirect3DSurface8Impl* surfaceParent;
TRACE("(%p) call back\n", pSurface);
IWineD3DSurface_GetParent(pSurface, (IUnknown **) &surfaceParent);
/* GetParent's AddRef was forwarded to an object in destruction.
* Releasing it here again would cause an endless recursion. */
surfaceParent->forwardReference = NULL;
return IDirect3DSurface8_Release((IDirect3DSurface8*) surfaceParent);
}
/* IWineD3DDeviceParent IUnknown methods */
static inline struct IDirect3DDevice8Impl *device_from_device_parent(IWineD3DDeviceParent *iface)
......@@ -2672,9 +2661,13 @@ static HRESULT STDMETHODCALLTYPE device_parent_CreateSurface(IWineD3DDeviceParen
}
*surface = d3d_surface->wineD3DSurface;
IWineD3DSurface_AddRef(*surface);
d3d_surface->container = superior;
IUnknown_Release(d3d_surface->parentDevice);
d3d_surface->parentDevice = NULL;
IDirect3DSurface8_Release((IDirect3DSurface8 *)d3d_surface);
d3d_surface->forwardReference = superior;
return hr;
......@@ -2701,8 +2694,9 @@ static HRESULT STDMETHODCALLTYPE device_parent_CreateRenderTarget(IWineD3DDevice
}
*surface = d3d_surface->wineD3DSurface;
IWineD3DSurface_AddRef(*surface);
d3d_surface->container = (IUnknown *)This;
d3d_surface->isImplicit = TRUE;
/* Implicit surfaces are created with an refcount of 0 */
IUnknown_Release((IUnknown *)d3d_surface);
......@@ -2730,8 +2724,9 @@ static HRESULT STDMETHODCALLTYPE device_parent_CreateDepthStencilSurface(IWineD3
}
*surface = d3d_surface->wineD3DSurface;
IWineD3DSurface_AddRef(*surface);
d3d_surface->container = (IUnknown *)This;
d3d_surface->isImplicit = TRUE;
/* Implicit surfaces are created with an refcount of 0 */
IUnknown_Release((IUnknown *)d3d_surface);
......
......@@ -312,16 +312,6 @@ static HMONITOR WINAPI IDirect3D8Impl_GetAdapterMonitor(LPDIRECT3D8 iface, UINT
return ret;
}
ULONG WINAPI D3D8CB_DestroyRenderTarget(IWineD3DSurface *pSurface) {
IDirect3DSurface8Impl* surfaceParent;
TRACE("(%p) call back\n", pSurface);
IWineD3DSurface_GetParent(pSurface, (IUnknown **) &surfaceParent);
surfaceParent->isImplicit = FALSE;
/* Surface had refcount of 0 GetParent addrefed to 1, so 1 Release is enough */
return IDirect3DSurface8_Release((IDirect3DSurface8*) surfaceParent);
}
ULONG WINAPI D3D8CB_DestroySwapChain(IWineD3DSwapChain *pSwapChain) {
IUnknown* swapChainParent;
TRACE("(%p) call back\n", pSwapChain);
......@@ -331,16 +321,6 @@ ULONG WINAPI D3D8CB_DestroySwapChain(IWineD3DSwapChain *pSwapChain) {
return IUnknown_Release(swapChainParent);
}
ULONG WINAPI D3D8CB_DestroyDepthStencilSurface(IWineD3DSurface *pSurface) {
IDirect3DSurface8Impl* surfaceParent;
TRACE("(%p) call back\n", pSurface);
IWineD3DSurface_GetParent(pSurface, (IUnknown **) &surfaceParent);
surfaceParent->isImplicit = FALSE;
/* Surface had refcount of 0 GetParent addrefed to 1, so 1 Release is enough */
return IDirect3DSurface8_Release((IDirect3DSurface8*) surfaceParent);
}
static HRESULT WINAPI IDirect3D8Impl_CreateDevice(LPDIRECT3D8 iface, UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow,
DWORD BehaviourFlags, D3DPRESENT_PARAMETERS* pPresentationParameters,
IDirect3DDevice8** ppReturnedDeviceInterface) {
......
......@@ -52,7 +52,13 @@ static ULONG WINAPI IDirect3DSurface8Impl_AddRef(LPDIRECT3DSURFACE8 iface) {
} else {
/* No container, handle our own refcounting */
ULONG ref = InterlockedIncrement(&This->ref);
if(ref == 1 && This->parentDevice) IUnknown_AddRef(This->parentDevice);
if (ref == 1)
{
if (This->parentDevice) IUnknown_AddRef(This->parentDevice);
wined3d_mutex_lock();
IUnknown_AddRef(This->wineD3DSurface);
wined3d_mutex_unlock();
}
TRACE("(%p) : AddRef from %d\n", This, ref - 1);
return ref;
}
......@@ -75,13 +81,9 @@ static ULONG WINAPI IDirect3DSurface8Impl_Release(LPDIRECT3DSURFACE8 iface) {
if (ref == 0) {
if (This->parentDevice) IUnknown_Release(This->parentDevice);
/* Implicit surfaces are destroyed with the device, not if refcount reaches 0. */
if (!This->isImplicit) {
wined3d_mutex_lock();
IWineD3DSurface_Release(This->wineD3DSurface);
wined3d_mutex_unlock();
HeapFree(GetProcessHeap(), 0, This);
}
wined3d_mutex_lock();
IWineD3DSurface_Release(This->wineD3DSurface);
wined3d_mutex_unlock();
}
return ref;
......@@ -247,6 +249,16 @@ static const IDirect3DSurface8Vtbl Direct3DSurface8_Vtbl =
IDirect3DSurface8Impl_UnlockRect
};
static void STDMETHODCALLTYPE surface_wined3d_object_destroyed(void *parent)
{
HeapFree(GetProcessHeap(), 0, parent);
}
static const struct wined3d_parent_ops d3d8_surface_wined3d_parent_ops =
{
surface_wined3d_object_destroyed,
};
HRESULT surface_init(IDirect3DSurface8Impl *surface, IDirect3DDevice8Impl *device,
UINT width, UINT height, D3DFORMAT format, BOOL lockable, BOOL discard, UINT level,
DWORD usage, D3DPOOL pool, D3DMULTISAMPLE_TYPE multisample_type, DWORD multisample_quality)
......@@ -266,7 +278,8 @@ HRESULT surface_init(IDirect3DSurface8Impl *surface, IDirect3DDevice8Impl *devic
wined3d_mutex_lock();
hr = IWineD3DDevice_CreateSurface(device->WineD3DDevice, width, height, wined3dformat_from_d3dformat(format),
lockable, discard, level, &surface->wineD3DSurface, usage & WINED3DUSAGE_MASK, (WINED3DPOOL)pool,
multisample_type, multisample_quality, SURFACE_OPENGL, (IUnknown *)surface);
multisample_type, multisample_quality, SURFACE_OPENGL, (IUnknown *)surface,
&d3d8_surface_wined3d_parent_ops);
wined3d_mutex_unlock();
if (FAILED(hr))
{
......
......@@ -57,7 +57,7 @@ static ULONG WINAPI IDirect3DSwapChain8Impl_Release(LPDIRECT3DSWAPCHAIN8 iface)
if (ref == 0) {
wined3d_mutex_lock();
IWineD3DSwapChain_Destroy(This->wineD3DSwapChain, D3D8CB_DestroyRenderTarget);
IWineD3DSwapChain_Destroy(This->wineD3DSwapChain);
wined3d_mutex_unlock();
if (This->parentDevice) IUnknown_Release(This->parentDevice);
......
......@@ -58,7 +58,7 @@ static ULONG WINAPI IDirect3DTexture8Impl_Release(LPDIRECT3DTEXTURE8 iface) {
if (ref == 0) {
wined3d_mutex_lock();
IWineD3DTexture_Destroy(This->wineD3DTexture, D3D8CB_DestroySurface);
IWineD3DTexture_Destroy(This->wineD3DTexture);
wined3d_mutex_unlock();
IUnknown_Release(This->parentDevice);
......
......@@ -62,7 +62,7 @@ static ULONG WINAPI IDirect3DCubeTexture9Impl_Release(LPDIRECT3DCUBETEXTURE9 ifa
TRACE("Releasing child %p\n", This->wineD3DCubeTexture);
wined3d_mutex_lock();
IWineD3DCubeTexture_Destroy(This->wineD3DCubeTexture, D3D9CB_DestroySurface);
IWineD3DCubeTexture_Destroy(This->wineD3DCubeTexture);
IDirect3DDevice9Ex_Release(This->parentDevice);
wined3d_mutex_unlock();
......
......@@ -301,9 +301,6 @@ typedef struct IDirect3DSurface9Impl
/* If set forward refcounting to this object */
IUnknown *forwardReference;
/* Flags an implicit surface */
BOOL isImplicit;
BOOL getdc_supported;
} IDirect3DSurface9Impl;
......@@ -539,9 +536,6 @@ typedef struct IDirect3DQuery9Impl {
/* Callbacks */
extern ULONG WINAPI D3D9CB_DestroySwapChain (IWineD3DSwapChain *pSwapChain);
extern ULONG WINAPI D3D9CB_DestroyDepthStencilSurface (IWineD3DSurface *pSurface);
extern ULONG WINAPI D3D9CB_DestroyRenderTarget (IWineD3DSurface *pSurface);
extern ULONG WINAPI D3D9CB_DestroySurface(IWineD3DSurface *pSurface);
extern ULONG WINAPI D3D9CB_DestroyVolume(IWineD3DVolume *pVolume);
#endif /* __WINE_D3D9_PRIVATE_H */
......@@ -257,7 +257,7 @@ static ULONG WINAPI IDirect3DDevice9Impl_Release(LPDIRECT3DDEVICE9EX iface) {
}
HeapFree(GetProcessHeap(), 0, This->convertedDecls);
IWineD3DDevice_Uninit3D(This->WineD3DDevice, D3D9CB_DestroyDepthStencilSurface, D3D9CB_DestroySwapChain);
IWineD3DDevice_Uninit3D(This->WineD3DDevice, D3D9CB_DestroySwapChain);
IWineD3DDevice_Release(This->WineD3DDevice);
wined3d_mutex_unlock();
......@@ -1997,17 +1997,6 @@ const IDirect3DDevice9ExVtbl Direct3DDevice9_Vtbl =
IDirect3DDevice9ExImpl_GetDisplayModeEx
};
ULONG WINAPI D3D9CB_DestroySurface(IWineD3DSurface *pSurface) {
IDirect3DSurface9Impl* surfaceParent;
TRACE("(%p) call back\n", pSurface);
IWineD3DSurface_GetParent(pSurface, (IUnknown **) &surfaceParent);
/* GetParent's AddRef was forwarded to an object in destruction.
* Releasing it here again would cause an endless recursion. */
surfaceParent->forwardReference = NULL;
return IDirect3DSurface9_Release((IDirect3DSurface9*) surfaceParent);
}
/* IWineD3DDeviceParent IUnknown methods */
static inline struct IDirect3DDevice9Impl *device_from_device_parent(IWineD3DDeviceParent *iface)
......@@ -2067,9 +2056,13 @@ static HRESULT STDMETHODCALLTYPE device_parent_CreateSurface(IWineD3DDeviceParen
}
*surface = d3d_surface->wineD3DSurface;
IWineD3DSurface_AddRef(*surface);
d3d_surface->container = superior;
IDirect3DDevice9Ex_Release(d3d_surface->parentDevice);
d3d_surface->parentDevice = NULL;
IDirect3DSurface9_Release((IDirect3DSurface9 *)d3d_surface);
d3d_surface->forwardReference = superior;
return hr;
......@@ -2097,8 +2090,9 @@ static HRESULT STDMETHODCALLTYPE device_parent_CreateRenderTarget(IWineD3DDevice
}
*surface = d3d_surface->wineD3DSurface;
IWineD3DSurface_AddRef(*surface);
d3d_surface->container = superior;
d3d_surface->isImplicit = TRUE;
/* Implicit surfaces are created with an refcount of 0 */
IDirect3DSurface9_Release((IDirect3DSurface9 *)d3d_surface);
......@@ -2127,8 +2121,8 @@ static HRESULT STDMETHODCALLTYPE device_parent_CreateDepthStencilSurface(IWineD3
}
*surface = d3d_surface->wineD3DSurface;
IWineD3DSurface_AddRef(*surface);
d3d_surface->container = (IUnknown *)This;
d3d_surface->isImplicit = TRUE;
/* Implicit surfaces are created with an refcount of 0 */
IDirect3DSurface9_Release((IDirect3DSurface9 *)d3d_surface);
......
......@@ -383,16 +383,6 @@ static HMONITOR WINAPI IDirect3D9Impl_GetAdapterMonitor(LPDIRECT3D9EX iface, UIN
return ret;
}
ULONG WINAPI D3D9CB_DestroyRenderTarget(IWineD3DSurface *pSurface) {
IDirect3DSurface9Impl* surfaceParent;
TRACE("(%p) call back\n", pSurface);
IWineD3DSurface_GetParent(pSurface, (IUnknown **) &surfaceParent);
surfaceParent->isImplicit = FALSE;
/* Surface had refcount of 0 GetParent addrefed to 1, so 1 Release is enough */
return IDirect3DSurface9_Release((IDirect3DSurface9*) surfaceParent);
}
ULONG WINAPI D3D9CB_DestroySwapChain(IWineD3DSwapChain *pSwapChain) {
IDirect3DSwapChain9Impl* swapChainParent;
TRACE("(%p) call back\n", pSwapChain);
......@@ -403,16 +393,6 @@ ULONG WINAPI D3D9CB_DestroySwapChain(IWineD3DSwapChain *pSwapChain) {
return IDirect3DSwapChain9_Release((IDirect3DSwapChain9*) swapChainParent);
}
ULONG WINAPI D3D9CB_DestroyDepthStencilSurface(IWineD3DSurface *pSurface) {
IDirect3DSurface9Impl* surfaceParent;
TRACE("(%p) call back\n", pSurface);
IWineD3DSurface_GetParent(pSurface, (IUnknown **) &surfaceParent);
surfaceParent->isImplicit = FALSE;
/* Surface had refcount of 0 GetParent addrefed to 1, so 1 Release is enough */
return IDirect3DSurface9_Release((IDirect3DSurface9*) surfaceParent);
}
static HRESULT WINAPI IDirect3D9Impl_CreateDevice(LPDIRECT3D9EX iface, UINT Adapter, D3DDEVTYPE DeviceType,
HWND hFocusWindow, DWORD BehaviourFlags,
D3DPRESENT_PARAMETERS* pPresentationParameters,
......
......@@ -53,7 +53,13 @@ static ULONG WINAPI IDirect3DSurface9Impl_AddRef(LPDIRECT3DSURFACE9 iface) {
} else {
/* No container, handle our own refcounting */
ULONG ref = InterlockedIncrement(&This->ref);
if(ref == 1 && This->parentDevice) IDirect3DDevice9Ex_AddRef(This->parentDevice);
if (ref == 1)
{
if (This->parentDevice) IDirect3DDevice9Ex_AddRef(This->parentDevice);
wined3d_mutex_lock();
IWineD3DSurface_AddRef(This->wineD3DSurface);
wined3d_mutex_unlock();
}
TRACE("(%p) : AddRef from %d\n", This, ref - 1);
return ref;
......@@ -77,13 +83,9 @@ static ULONG WINAPI IDirect3DSurface9Impl_Release(LPDIRECT3DSURFACE9 iface) {
if (ref == 0) {
if (This->parentDevice) IDirect3DDevice9Ex_Release(This->parentDevice);
if (!This->isImplicit) {
wined3d_mutex_lock();
IWineD3DSurface_Release(This->wineD3DSurface);
wined3d_mutex_unlock();
HeapFree(GetProcessHeap(), 0, This);
}
wined3d_mutex_lock();
IWineD3DSurface_Release(This->wineD3DSurface);
wined3d_mutex_unlock();
}
return ref;
......@@ -322,6 +324,16 @@ static const IDirect3DSurface9Vtbl Direct3DSurface9_Vtbl =
IDirect3DSurface9Impl_ReleaseDC
};
static void STDMETHODCALLTYPE surface_wined3d_object_destroyed(void *parent)
{
HeapFree(GetProcessHeap(), 0, parent);
}
static const struct wined3d_parent_ops d3d9_surface_wined3d_parent_ops =
{
surface_wined3d_object_destroyed,
};
HRESULT surface_init(IDirect3DSurface9Impl *surface, IDirect3DDevice9Impl *device,
UINT width, UINT height, D3DFORMAT format, BOOL lockable, BOOL discard, UINT level,
DWORD usage, D3DPOOL pool, D3DMULTISAMPLE_TYPE multisample_type, DWORD multisample_quality)
......@@ -357,7 +369,8 @@ HRESULT surface_init(IDirect3DSurface9Impl *surface, IDirect3DDevice9Impl *devic
wined3d_mutex_lock();
hr = IWineD3DDevice_CreateSurface(device->WineD3DDevice, width, height, wined3dformat_from_d3dformat(format),
lockable, discard, level, &surface->wineD3DSurface, usage & WINED3DUSAGE_MASK, (WINED3DPOOL)pool,
multisample_type, multisample_quality, SURFACE_OPENGL, (IUnknown *)surface);
multisample_type, multisample_quality, SURFACE_OPENGL, (IUnknown *)surface,
&d3d9_surface_wined3d_parent_ops);
wined3d_mutex_unlock();
if (FAILED(hr))
{
......
......@@ -63,7 +63,7 @@ static ULONG WINAPI IDirect3DSwapChain9Impl_Release(LPDIRECT3DSWAPCHAIN9 iface)
if (This->parentDevice) IDirect3DDevice9Ex_Release(This->parentDevice);
if (!This->isImplicit) {
wined3d_mutex_lock();
IWineD3DSwapChain_Destroy(This->wineD3DSwapChain, D3D9CB_DestroyRenderTarget);
IWineD3DSwapChain_Destroy(This->wineD3DSwapChain);
wined3d_mutex_unlock();
HeapFree(GetProcessHeap(), 0, This);
......
......@@ -60,7 +60,7 @@ static ULONG WINAPI IDirect3DTexture9Impl_Release(LPDIRECT3DTEXTURE9 iface) {
if (ref == 0) {
wined3d_mutex_lock();
IWineD3DTexture_Destroy(This->wineD3DTexture, D3D9CB_DestroySurface);
IWineD3DTexture_Destroy(This->wineD3DTexture);
wined3d_mutex_unlock();
IDirect3DDevice9Ex_Release(This->parentDevice);
......
......@@ -62,6 +62,13 @@ static const DDDEVICEIDENTIFIER2 deviceidentifier =
0
};
static void STDMETHODCALLTYPE ddraw_null_wined3d_object_destroyed(void *parent) {}
static const struct wined3d_parent_ops ddraw_null_wined3d_parent_ops =
{
ddraw_null_wined3d_object_destroyed,
};
/*****************************************************************************
* IUnknown Methods
*****************************************************************************/
......@@ -1655,11 +1662,9 @@ IDirectDrawImpl_RecreateSurfacesCallback(IDirectDrawSurface7 *surf,
IDirectDrawSurfaceImpl *surfImpl = (IDirectDrawSurfaceImpl *)surf;
IDirectDrawImpl *This = surfImpl->ddraw;
IUnknown *Parent;
IParentImpl *parImpl = NULL;
IWineD3DSurface *wineD3DSurface;
IWineD3DSwapChain *swapchain;
HRESULT hr;
void *tmp;
IWineD3DClipper *clipper = NULL;
WINED3DSURFACE_DESC Desc;
......@@ -1683,18 +1688,6 @@ IDirectDrawImpl_RecreateSurfacesCallback(IDirectDrawSurface7 *surf,
swapchain = surfImpl->wineD3DSwapChain;
surfImpl->wineD3DSwapChain = NULL;
wineD3DSurface = surfImpl->WineD3DSurface;
IWineD3DSurface_GetParent(wineD3DSurface, &Parent);
IUnknown_Release(Parent); /* For the getParent */
/* Is the parent an IParent interface? */
if(IUnknown_QueryInterface(Parent, &IID_IParent, &tmp) == S_OK)
{
/* It is a IParent interface! */
IUnknown_Release(Parent); /* For the QueryInterface */
parImpl = (IParentImpl *)Parent;
/* Release the reference the parent interface is holding */
IWineD3DSurface_Release(wineD3DSurface);
}
/* get the clipper */
IWineD3DSurface_GetClipper(wineD3DSurface, &clipper);
......@@ -1711,34 +1704,19 @@ IDirectDrawImpl_RecreateSurfacesCallback(IDirectDrawSurface7 *surf,
Width = Desc.width;
Height = Desc.height;
if(swapchain) {
/* If there's a swapchain, it owns the IParent interface. Create a new one for the
* new surface
*/
parImpl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*parImpl));
parImpl->lpVtbl = &IParent_Vtbl;
parImpl->ref = 1;
Parent = (IUnknown *) parImpl;
}
IWineD3DSurface_GetParent(wineD3DSurface, &Parent);
/* Create the new surface */
hr = IWineD3DDevice_CreateSurface(This->wineD3DDevice, Width, Height, Format,
TRUE /* Lockable */, FALSE /* Discard */, surfImpl->mipmap_level, &surfImpl->WineD3DSurface,
Usage, Pool, MultiSampleType, MultiSampleQuality, This->ImplType, Parent);
TRUE /* Lockable */, FALSE /* Discard */, surfImpl->mipmap_level, &surfImpl->WineD3DSurface, Usage, Pool,
MultiSampleType, MultiSampleQuality, This->ImplType, Parent, &ddraw_null_wined3d_parent_ops);
IUnknown_Release(Parent);
if(hr != D3D_OK)
return hr;
IWineD3DSurface_SetClipper(surfImpl->WineD3DSurface, clipper);
/* Update the IParent if it exists */
if(parImpl)
{
parImpl->child = (IUnknown *) surfImpl->WineD3DSurface;
/* Add a reference for the IParent */
IWineD3DSurface_AddRef(surfImpl->WineD3DSurface);
}
/* TODO: Copy the surface content, except for render targets */
/* If there's a swapchain, it owns the wined3d surfaces. So Destroy
......@@ -1787,7 +1765,7 @@ IDirectDrawImpl_RecreateAllSurfaces(IDirectDrawImpl *This)
/* Should happen almost never */
FIXME("(%p) Switching to non-opengl surfaces with d3d started. Is this a bug?\n", This);
/* Shutdown d3d */
IWineD3DDevice_Uninit3D(This->wineD3DDevice, D3D7CB_DestroyDepthStencilSurface, D3D7CB_DestroySwapChain);
IWineD3DDevice_Uninit3D(This->wineD3DDevice, D3D7CB_DestroySwapChain);
}
/* Contrary: D3D starting is handled by the caller, because it knows the render target */
......@@ -1806,15 +1784,6 @@ ULONG WINAPI D3D7CB_DestroySwapChain(IWineD3DSwapChain *pSwapChain) {
return IUnknown_Release(swapChainParent);
}
ULONG WINAPI D3D7CB_DestroyDepthStencilSurface(IWineD3DSurface *pSurface) {
IUnknown* surfaceParent;
TRACE("(%p) call back\n", pSurface);
IWineD3DSurface_GetParent(pSurface, &surfaceParent);
IUnknown_Release(surfaceParent);
return IUnknown_Release(surfaceParent);
}
/*****************************************************************************
* IDirectDrawImpl_CreateNewSurface
*
......@@ -1841,8 +1810,6 @@ IDirectDrawImpl_CreateNewSurface(IDirectDrawImpl *This,
DWORD Usage = 0;
WINED3DSURFTYPE ImplType = This->ImplType;
WINED3DSURFACE_DESC Desc;
IUnknown *Parent;
IParentImpl *parImpl = NULL;
WINED3DPOOL Pool = WINED3DPOOL_DEFAULT;
if (TRACE_ON(ddraw))
......@@ -1990,34 +1957,11 @@ IDirectDrawImpl_CreateNewSurface(IDirectDrawImpl *This,
/* A trace message for debugging */
TRACE("(%p) Created IDirectDrawSurface implementation structure at %p\n", This, *ppSurf);
if(pDDSD->ddsCaps.dwCaps & ( DDSCAPS_PRIMARYSURFACE | DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE) )
{
/* Render targets and textures need a IParent interface,
* because WineD3D will destroy them when the swapchain
* is released
*/
parImpl = HeapAlloc(GetProcessHeap(), 0, sizeof(IParentImpl));
if(!parImpl)
{
ERR("Out of memory when allocating memory for a IParent implementation\n");
return DDERR_OUTOFMEMORY;
}
parImpl->ref = 1;
parImpl->lpVtbl = &IParent_Vtbl;
Parent = (IUnknown *)parImpl;
TRACE("Using IParent interface %p as parent\n", parImpl);
}
else
{
/* Use the surface as parent */
Parent = (IUnknown *)*ppSurf;
TRACE("Using Surface interface %p as parent\n", *ppSurf);
}
/* Now create the WineD3D Surface */
hr = IWineD3DDevice_CreateSurface(This->wineD3DDevice, pDDSD->dwWidth, pDDSD->dwHeight, Format,
TRUE /* Lockable */, FALSE /* Discard */, level, &(*ppSurf)->WineD3DSurface,
Usage, Pool, WINED3DMULTISAMPLE_NONE, 0 /* MultiSampleQuality */, ImplType, Parent);
Usage, Pool, WINED3DMULTISAMPLE_NONE, 0 /* MultiSampleQuality */, ImplType,
(IUnknown *)*ppSurf, &ddraw_null_wined3d_parent_ops);
if(hr != D3D_OK)
{
......@@ -2025,16 +1969,6 @@ IDirectDrawImpl_CreateNewSurface(IDirectDrawImpl *This,
return hr;
}
/* Set the child of the parent implementation if it exists */
if(parImpl)
{
parImpl->child = (IUnknown *) (*ppSurf)->WineD3DSurface;
/* The IParent releases the WineD3DSurface, and
* the ddraw surface does that too. Hold a reference
*/
IWineD3DSurface_AddRef((*ppSurf)->WineD3DSurface);
}
/* Increase the surface counter, and attach the surface */
InterlockedIncrement(&This->surfaces);
list_add_head(&This->surface_list, &(*ppSurf)->surface_list_entry);
......@@ -3032,9 +2966,7 @@ IDirectDrawImpl_AttachD3DDevice(IDirectDrawImpl *This,
{
ERR("Error allocating an array for the converted vertex decls\n");
This->declArraySize = 0;
hr = IWineD3DDevice_Uninit3D(This->wineD3DDevice,
D3D7CB_DestroyDepthStencilSurface,
D3D7CB_DestroySwapChain);
hr = IWineD3DDevice_Uninit3D(This->wineD3DDevice, D3D7CB_DestroySwapChain);
return E_OUTOFMEMORY;
}
......@@ -3436,6 +3368,7 @@ static HRESULT STDMETHODCALLTYPE device_parent_CreateSurface(IWineD3DDeviceParen
/* Return the surface */
*surface = surf->WineD3DSurface;
IWineD3DSurface_AddRef(*surface);
TRACE("Returning wineD3DSurface %p, it belongs to surface %p\n", *surface, surf);
......@@ -3472,6 +3405,7 @@ static HRESULT STDMETHODCALLTYPE device_parent_CreateRenderTarget(IWineD3DDevice
/* TODO: Return failure if the dimensions do not match, but this shouldn't happen */
*surface = target->WineD3DSurface;
IWineD3DSurface_AddRef(*surface);
target->isRenderTarget = TRUE;
TRACE("Returning wineD3DSurface %p, it belongs to surface %p\n", *surface, d3d_surface);
......@@ -3484,7 +3418,7 @@ static HRESULT STDMETHODCALLTYPE device_parent_CreateDepthStencilSurface(IWineD3
DWORD multisample_quality, BOOL discard, IWineD3DSurface **surface)
{
struct IDirectDrawImpl *This = ddraw_from_device_parent(iface);
/* Create a Depth Stencil surface to make WineD3D happy */
IDirectDrawSurfaceImpl *ddraw_surface;
DDSURFACEDESC2 ddsd;
HRESULT hr;
......@@ -3512,8 +3446,7 @@ static HRESULT STDMETHODCALLTYPE device_parent_CreateDepthStencilSurface(IWineD3
}
This->depthstencil = TRUE;
hr = IDirectDraw7_CreateSurface((IDirectDraw7 *)This,
&ddsd, (IDirectDrawSurface7 **)&This->DepthStencilBuffer, NULL);
hr = IDirectDraw7_CreateSurface((IDirectDraw7 *)This, &ddsd, (IDirectDrawSurface7 **)&ddraw_surface, NULL);
This->depthstencil = FALSE;
if(FAILED(hr))
{
......@@ -3521,7 +3454,9 @@ static HRESULT STDMETHODCALLTYPE device_parent_CreateDepthStencilSurface(IWineD3
return hr;
}
*surface = This->DepthStencilBuffer->WineD3DSurface;
*surface = ddraw_surface->WineD3DSurface;
IWineD3DSurface_AddRef(*surface);
IDirectDrawSurface7_Release((IDirectDrawSurface7 *)ddraw_surface);
return D3D_OK;
}
......
......@@ -79,8 +79,6 @@ typedef struct IParentImpl IParentImpl;
/* Callbacks for implicit object destruction */
extern ULONG WINAPI D3D7CB_DestroySwapChain(IWineD3DSwapChain *pSwapChain);
extern ULONG WINAPI D3D7CB_DestroyDepthStencilSurface(IWineD3DSurface *pSurface);
/* Global critical section */
extern CRITICAL_SECTION ddraw_cs;
......@@ -115,7 +113,6 @@ struct IDirectDrawImpl
/* WineD3D linkage */
IWineD3D *wineD3D;
IWineD3DDevice *wineD3DDevice;
IDirectDrawSurfaceImpl *DepthStencilBuffer;
BOOL d3d_initialized;
/* Misc ddraw fields */
......
......@@ -748,7 +748,6 @@ DestroyCallback(IDirectDrawSurface7 *surf,
void *context)
{
IDirectDrawSurfaceImpl *Impl = (IDirectDrawSurfaceImpl *)surf;
IDirectDrawImpl *ddraw = context;
ULONG ref;
ref = IDirectDrawSurface7_Release(surf); /* For the EnumSurfaces */
......@@ -760,9 +759,6 @@ DestroyCallback(IDirectDrawSurface7 *surf,
*/
if( (!Impl->is_complex_root) || (Impl->first_attached != Impl) )
return DDENUMRET_OK;
/* Skip our depth stencil surface, it will be released with the render target */
if( Impl == ddraw->DepthStencilBuffer)
return DDENUMRET_OK;
/* Destroy the surface */
while(ref) ref = IDirectDrawSurface7_Release(surf);
......
......@@ -159,6 +159,13 @@ IDirectDrawSurfaceImpl_AddRef(IDirectDrawSurface7 *iface)
IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
ULONG refCount = InterlockedIncrement(&This->ref);
if (refCount == 1 && This->WineD3DSurface)
{
EnterCriticalSection(&ddraw_cs);
IWineD3DSurface_AddRef(This->WineD3DSurface);
LeaveCriticalSection(&ddraw_cs);
}
TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1);
return refCount;
}
......@@ -320,7 +327,7 @@ IDirectDrawSurfaceImpl_Release(IDirectDrawSurface7 *iface)
HeapFree(GetProcessHeap(), 0, ddraw->decls);
ddraw->numConvertedDecls = 0;
if(IWineD3DDevice_Uninit3D(ddraw->wineD3DDevice, D3D7CB_DestroyDepthStencilSurface, D3D7CB_DestroySwapChain) != D3D_OK)
if (FAILED(IWineD3DDevice_Uninit3D(ddraw->wineD3DDevice, D3D7CB_DestroySwapChain)))
{
/* Not good */
ERR("(%p) Failed to uninit 3D\n", This);
......
......@@ -56,18 +56,6 @@ static ULONG STDMETHODCALLTYPE dxgi_swapchain_AddRef(IDXGISwapChain *iface)
return refcount;
}
static ULONG STDMETHODCALLTYPE destroy_surface(IWineD3DSurface *surface)
{
IDXGISurface *dxgi_surface;
TRACE("surface %p\n", surface);
IWineD3DSurface_GetParent(surface, (IUnknown **)&dxgi_surface);
IDXGISurface_Release(dxgi_surface);
return IDXGISurface_Release(dxgi_surface);
}
static ULONG STDMETHODCALLTYPE destroy_swapchain(IWineD3DSwapChain *swapchain)
{
TRACE("swapchain %p\n", swapchain);
......@@ -96,7 +84,7 @@ static ULONG STDMETHODCALLTYPE dxgi_swapchain_Release(IDXGISwapChain *iface)
}
else
{
hr = IWineD3DDevice_Uninit3D(wined3d_device, destroy_surface, destroy_swapchain);
hr = IWineD3DDevice_Uninit3D(wined3d_device, destroy_swapchain);
IWineD3DDevice_Release(wined3d_device);
if (FAILED(hr))
{
......
......@@ -110,7 +110,7 @@ static void cubetexture_internal_preload(IWineD3DBaseTexture *iface, enum WINED3
*dirty = FALSE;
}
static void cubetexture_cleanup(IWineD3DCubeTextureImpl *This, D3DCB_DESTROYSURFACEFN surface_destroy_cb)
static void cubetexture_cleanup(IWineD3DCubeTextureImpl *This)
{
unsigned int i, j;
......@@ -130,7 +130,7 @@ static void cubetexture_cleanup(IWineD3DCubeTextureImpl *This, D3DCB_DESTROYSURF
surface_set_texture_name(surface, 0, FALSE);
surface_set_texture_target(surface, 0);
IWineD3DSurface_SetContainer(surface, NULL);
surface_destroy_cb(surface);
IWineD3DSurface_Release(surface);
}
}
}
......@@ -237,7 +237,7 @@ HRESULT cubetexture_init(IWineD3DCubeTextureImpl *texture, UINT edge_length, UIN
{
FIXME("(%p) Failed to create surface, hr %#x.\n", texture, hr);
texture->surfaces[j][i] = NULL;
cubetexture_cleanup(texture, D3DCB_DefaultDestroySurface);
cubetexture_cleanup(texture);
return hr;
}
......@@ -289,7 +289,7 @@ static ULONG WINAPI IWineD3DCubeTextureImpl_Release(IWineD3DCubeTexture *iface)
TRACE("(%p) : Releasing from %d\n", This, This->resource.ref);
ref = InterlockedDecrement(&This->resource.ref);
if (ref == 0) {
IWineD3DCubeTexture_Destroy(iface, D3DCB_DefaultDestroySurface);
IWineD3DCubeTexture_Destroy(iface);
}
return ref;
}
......@@ -432,10 +432,11 @@ static BOOL WINAPI IWineD3DCubeTextureImpl_IsCondNP2(IWineD3DCubeTexture *iface)
/* *******************************************
IWineD3DCubeTexture IWineD3DCubeTexture parts follow
******************************************* */
static void WINAPI IWineD3DCubeTextureImpl_Destroy(IWineD3DCubeTexture *iface, D3DCB_DESTROYSURFACEFN D3DCB_DestroySurface) {
static void WINAPI IWineD3DCubeTextureImpl_Destroy(IWineD3DCubeTexture *iface)
{
IWineD3DCubeTextureImpl *This = (IWineD3DCubeTextureImpl *)iface;
cubetexture_cleanup(This, D3DCB_DestroySurface);
cubetexture_cleanup(This);
/* finally delete the object */
HeapFree(GetProcessHeap(), 0, This);
}
......
......@@ -901,7 +901,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface,
static HRESULT WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, UINT Width, UINT Height,
WINED3DFORMAT Format, BOOL Lockable, BOOL Discard, UINT Level, IWineD3DSurface **ppSurface,
DWORD Usage, WINED3DPOOL Pool, WINED3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality,
WINED3DSURFTYPE Impl, IUnknown *parent)
WINED3DSURFTYPE Impl, IUnknown *parent, const struct wined3d_parent_ops *parent_ops)
{
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
IWineD3DSurfaceImpl *object;
......@@ -924,7 +924,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, UI
}
hr = surface_init(object, Impl, This->surface_alignment, Width, Height, Level, Lockable,
Discard, MultiSample, MultisampleQuality, This, Usage, Format, Pool, parent);
Discard, MultiSample, MultisampleQuality, This, Usage, Format, Pool, parent, parent_ops);
if (FAILED(hr))
{
WARN("Failed to initialize surface, returning %#x.\n", hr);
......@@ -1343,7 +1343,6 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateSwapChain(IWineD3DDevice *iface,
HDC hDc;
IWineD3DSwapChainImpl *object; /** NOTE: impl ref allowed since this is a create function **/
HRESULT hr;
IUnknown *bufferParent;
BOOL displaymode_set = FALSE;
WINED3DDISPLAYMODE Mode;
const struct GlPixelFormatDesc *format_desc;
......@@ -1604,26 +1603,14 @@ error:
if (object->backBuffer) {
UINT i;
for(i = 0; i < object->presentParms.BackBufferCount; i++) {
if(object->backBuffer[i]) {
IWineD3DSurface_GetParent(object->backBuffer[i], &bufferParent);
IUnknown_Release(bufferParent); /* once for the get parent */
if (IUnknown_Release(bufferParent) > 0) {
FIXME("(%p) Something's still holding the back buffer\n",This);
}
}
if (object->backBuffer[i]) IWineD3DSurface_Release(object->backBuffer[i]);
}
HeapFree(GetProcessHeap(), 0, object->backBuffer);
object->backBuffer = NULL;
}
if(object->context && object->context[0])
DestroyContext(This, object->context[0]);
if(object->frontBuffer) {
IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
IUnknown_Release(bufferParent); /* once for the get parent */
if (IUnknown_Release(bufferParent) > 0) {
FIXME("(%p) Something's still holding the front buffer\n",This);
}
}
if (object->frontBuffer) IWineD3DSurface_Release(object->frontBuffer);
HeapFree(GetProcessHeap(), 0, object);
return hr;
}
......@@ -1983,7 +1970,8 @@ static void IWineD3DDeviceImpl_LoadLogo(IWineD3DDeviceImpl *This, const char *fi
}
hr = IWineD3DDevice_CreateSurface((IWineD3DDevice *) This, bm.bmWidth, bm.bmHeight, WINED3DFMT_R5G6B5, TRUE,
FALSE, 0, &This->logo_surface, 0, WINED3DPOOL_DEFAULT, WINED3DMULTISAMPLE_NONE, 0, SURFACE_OPENGL, NULL);
FALSE, 0, &This->logo_surface, 0, WINED3DPOOL_DEFAULT, WINED3DMULTISAMPLE_NONE, 0, SURFACE_OPENGL,
NULL, &wined3d_null_parent_ops);
if(FAILED(hr)) {
ERR("Wine logo requested, but failed to create surface\n");
goto out;
......@@ -2287,7 +2275,9 @@ static HRESULT WINAPI device_unload_resource(IWineD3DResource *resource, void *c
return WINED3D_OK;
}
static HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface, D3DCB_DESTROYSURFACEFN D3DCB_DestroyDepthStencilSurface, D3DCB_DESTROYSWAPCHAINFN D3DCB_DestroySwapChain) {
static HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface,
D3DCB_DESTROYSWAPCHAINFN D3DCB_DestroySwapChain)
{
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
int sampler;
UINT i;
......@@ -2399,7 +2389,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface, D3DCB_D
This->render_targets[0] = NULL;
if (This->auto_depth_stencil_buffer) {
if(D3DCB_DestroyDepthStencilSurface(This->auto_depth_stencil_buffer) > 0) {
if (IWineD3DSurface_Release(This->auto_depth_stencil_buffer) > 0)
{
FIXME("(%p) Something's still holding the auto depth stencil buffer\n", This);
}
This->auto_depth_stencil_buffer = NULL;
......
......@@ -6,6 +6,7 @@
* Copyright 2004 Christian Costa
* Copyright 2005 Oliver Stieber
* Copyright 2007-2008 Stefan Dösinger for CodeWeavers
* Copyright 2009 Henri Verbeet for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
......@@ -4316,16 +4317,6 @@ static HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent
return WINED3D_OK;
}
ULONG WINAPI D3DCB_DefaultDestroySurface(IWineD3DSurface *pSurface) {
IUnknown* surfaceParent;
TRACE("(%p) call back\n", pSurface);
/* Now, release the parent, which will take care of cleaning up the surface for us */
IWineD3DSurface_GetParent(pSurface, &surfaceParent);
IUnknown_Release(surfaceParent);
return IUnknown_Release(surfaceParent);
}
ULONG WINAPI D3DCB_DefaultDestroyVolume(IWineD3DVolume *pVolume) {
IUnknown* volumeParent;
TRACE("(%p) call back\n", pVolume);
......@@ -4830,3 +4821,10 @@ const IWineD3DVtbl IWineD3D_Vtbl =
IWineD3DImpl_GetDeviceCaps,
IWineD3DImpl_CreateDevice
};
static void STDMETHODCALLTYPE wined3d_null_wined3d_object_destroyed(void *parent) {}
const struct wined3d_parent_ops wined3d_null_parent_ops =
{
wined3d_null_wined3d_object_destroyed,
};
......@@ -10,6 +10,7 @@
* Copyright 2006-2008 Stefan Dösinger for CodeWeavers
* Copyright 2007-2008 Henri Verbeet
* Copyright 2006-2008 Roderick Colenbrander
* Copyright 2009 Henri Verbeet for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
......@@ -122,7 +123,7 @@ UINT surface_calculate_size(const struct GlPixelFormatDesc *format_desc, UINT al
HRESULT surface_init(IWineD3DSurfaceImpl *surface, WINED3DSURFTYPE surface_type, UINT alignment,
UINT width, UINT height, UINT level, BOOL lockable, BOOL discard, WINED3DMULTISAMPLE_TYPE multisample_type,
UINT multisample_quality, IWineD3DDeviceImpl *device, DWORD usage, WINED3DFORMAT format,
WINED3DPOOL pool, IUnknown *parent)
WINED3DPOOL pool, IUnknown *parent, const struct wined3d_parent_ops *parent_ops)
{
const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
const struct GlPixelFormatDesc *format_desc = getFormatDescEntry(format, &GLINFO_LOCATION);
......@@ -166,6 +167,8 @@ HRESULT surface_init(IWineD3DSurfaceImpl *surface, WINED3DSURFTYPE surface_type,
return hr;
}
surface->parent_ops = parent_ops;
/* "Standalone" surface. */
IWineD3DSurface_SetContainer((IWineD3DSurface *)surface, NULL);
......@@ -727,6 +730,7 @@ static ULONG WINAPI IWineD3DSurfaceImpl_Release(IWineD3DSurface *iface)
if (!ref)
{
surface_cleanup(This);
This->parent_ops->wined3d_object_destroyed(This->resource.parent);
TRACE("(%p) Released.\n", This);
HeapFree(GetProcessHeap(), 0, This);
......
......@@ -10,6 +10,7 @@
* Copyright 2006-2008 Stefan Dösinger for CodeWeavers
* Copyright 2007 Henri Verbeet
* Copyright 2006-2007 Roderick Colenbrander
* Copyright 2009 Henri Verbeet for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
......@@ -799,7 +800,8 @@ static IWineD3DSurfaceImpl *surface_convert_format(IWineD3DSurfaceImpl *source,
IWineD3DDevice_CreateSurface((IWineD3DDevice *)source->resource.wineD3DDevice, source->currentDesc.Width,
source->currentDesc.Height, to_fmt, TRUE /* lockable */, TRUE /* discard */, 0 /* level */, &ret,
0 /* usage */, WINED3DPOOL_SCRATCH, WINED3DMULTISAMPLE_NONE /* TODO: Multisampled conversion */,
0 /* MultiSampleQuality */, IWineD3DSurface_GetImplType((IWineD3DSurface *) source), NULL /* parent */);
0 /* MultiSampleQuality */, IWineD3DSurface_GetImplType((IWineD3DSurface *) source),
NULL /* parent */, &wined3d_null_parent_ops);
if(!ret) {
ERR("Failed to create a destination surface for conversion\n");
return NULL;
......
......@@ -36,7 +36,8 @@ WINE_DECLARE_DEBUG_CHANNEL(fps);
#define GLINFO_LOCATION This->wineD3DDevice->adapter->gl_info
/*IWineD3DSwapChain parts follow: */
static void WINAPI IWineD3DSwapChainImpl_Destroy(IWineD3DSwapChain *iface, D3DCB_DESTROYSURFACEFN D3DCB_DestroyRenderTarget) {
static void WINAPI IWineD3DSwapChainImpl_Destroy(IWineD3DSwapChain *iface)
{
IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
WINED3DDISPLAYMODE mode;
unsigned int i;
......@@ -50,9 +51,9 @@ static void WINAPI IWineD3DSwapChainImpl_Destroy(IWineD3DSwapChain *iface, D3DCB
if (This->frontBuffer)
{
IWineD3DSurface_SetContainer(This->frontBuffer, 0);
if (D3DCB_DestroyRenderTarget(This->frontBuffer))
if (IWineD3DSurface_Release(This->frontBuffer))
{
FIXME("(%p) Something's still holding the front buffer (%p).\n",
WARN("(%p) Something's still holding the front buffer (%p).\n",
This, This->frontBuffer);
}
This->frontBuffer = NULL;
......@@ -65,8 +66,8 @@ static void WINAPI IWineD3DSwapChainImpl_Destroy(IWineD3DSwapChain *iface, D3DCB
while (i--)
{
IWineD3DSurface_SetContainer(This->backBuffer[i], 0);
if (D3DCB_DestroyRenderTarget(This->backBuffer[i]))
FIXME("(%p) Something's still holding back buffer %u (%p).\n",
if (IWineD3DSurface_Release(This->backBuffer[i]))
WARN("(%p) Something's still holding back buffer %u (%p).\n",
This, i, This->backBuffer[i]);
}
HeapFree(GetProcessHeap(), 0, This->backBuffer);
......
......@@ -59,7 +59,7 @@ ULONG WINAPI IWineD3DBaseSwapChainImpl_Release(IWineD3DSwapChain *iface) {
refCount = InterlockedDecrement(&This->ref);
TRACE("(%p) : ReleaseRef to %d\n", This, refCount);
if (refCount == 0) {
IWineD3DSwapChain_Destroy(iface, D3DCB_DefaultDestroySurface);
IWineD3DSwapChain_Destroy(iface);
}
return refCount;
}
......
......@@ -27,7 +27,8 @@
WINE_DEFAULT_DEBUG_CHANNEL(d3d);
WINE_DECLARE_DEBUG_CHANNEL(fps);
static void WINAPI IWineGDISwapChainImpl_Destroy(IWineD3DSwapChain *iface, D3DCB_DESTROYSURFACEFN D3DCB_DestroyRenderback) {
static void WINAPI IWineGDISwapChainImpl_Destroy(IWineD3DSwapChain *iface)
{
IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
WINED3DDISPLAYMODE mode;
......@@ -38,8 +39,9 @@ static void WINAPI IWineGDISwapChainImpl_Destroy(IWineD3DSwapChain *iface, D3DCB
/* release the ref to the front and back buffer parents */
if(This->frontBuffer) {
IWineD3DSurface_SetContainer(This->frontBuffer, 0);
if(D3DCB_DestroyRenderback(This->frontBuffer) > 0) {
FIXME("(%p) Something's still holding the front buffer\n",This);
if (IWineD3DSurface_Release(This->frontBuffer) > 0)
{
WARN("(%p) Something's still holding the front buffer\n",This);
}
}
......@@ -47,8 +49,9 @@ static void WINAPI IWineGDISwapChainImpl_Destroy(IWineD3DSwapChain *iface, D3DCB
UINT i;
for(i = 0; i < This->presentParms.BackBufferCount; i++) {
IWineD3DSurface_SetContainer(This->backBuffer[i], 0);
if(D3DCB_DestroyRenderback(This->backBuffer[i]) > 0) {
FIXME("(%p) Something's still holding the back buffer\n",This);
if (IWineD3DSurface_Release(This->backBuffer[i]) > 0)
{
WARN("(%p) Something's still holding the back buffer\n",This);
}
}
HeapFree(GetProcessHeap(), 0, This->backBuffer);
......
......@@ -100,7 +100,7 @@ static void texture_internal_preload(IWineD3DBaseTexture *iface, enum WINED3DSRG
*dirty = FALSE;
}
static void texture_cleanup(IWineD3DTextureImpl *This, D3DCB_DESTROYSURFACEFN surface_destroy_cb)
static void texture_cleanup(IWineD3DTextureImpl *This)
{
unsigned int i;
......@@ -116,7 +116,7 @@ static void texture_cleanup(IWineD3DTextureImpl *This, D3DCB_DESTROYSURFACEFN su
surface_set_texture_name(This->surfaces[i], 0, FALSE);
surface_set_texture_target(This->surfaces[i], 0);
IWineD3DSurface_SetContainer(This->surfaces[i], 0);
surface_destroy_cb(This->surfaces[i]);
IWineD3DSurface_Release(This->surfaces[i]);
}
}
......@@ -266,7 +266,7 @@ HRESULT texture_init(IWineD3DTextureImpl *texture, UINT width, UINT height, UINT
{
FIXME("Failed to create surface %p, hr %#x\n", texture, hr);
texture->surfaces[i] = NULL;
texture_cleanup(texture, D3DCB_DefaultDestroySurface);
texture_cleanup(texture);
return hr;
}
......@@ -319,7 +319,7 @@ static ULONG WINAPI IWineD3DTextureImpl_Release(IWineD3DTexture *iface) {
TRACE("(%p) : Releasing from %d\n", This, This->resource.ref);
ref = InterlockedDecrement(&This->resource.ref);
if (ref == 0) {
IWineD3DTexture_Destroy(iface, D3DCB_DefaultDestroySurface);
IWineD3DTexture_Destroy(iface);
}
return ref;
}
......@@ -480,10 +480,11 @@ static BOOL WINAPI IWineD3DTextureImpl_IsCondNP2(IWineD3DTexture *iface) {
/* *******************************************
IWineD3DTexture IWineD3DTexture parts follow
******************************************* */
static void WINAPI IWineD3DTextureImpl_Destroy(IWineD3DTexture *iface, D3DCB_DESTROYSURFACEFN D3DCB_DestroySurface) {
static void WINAPI IWineD3DTextureImpl_Destroy(IWineD3DTexture *iface)
{
IWineD3DTextureImpl *This = (IWineD3DTextureImpl *)iface;
texture_cleanup(This, D3DCB_DestroySurface);
texture_cleanup(This);
/* free the object */
HeapFree(GetProcessHeap(), 0, This);
}
......
......@@ -1337,8 +1337,6 @@ HRESULT create_primary_opengl_context(IWineD3DDevice *iface, IWineD3DSwapChain *
#define WINE_D3D9_CAPABLE(gl_info) WINE_D3D8_CAPABLE(gl_info) && (gl_info->supported[ARB_FRAGMENT_PROGRAM] && gl_info->supported[ARB_VERTEX_SHADER])
/* Default callbacks for implicit object destruction */
extern ULONG WINAPI D3DCB_DefaultDestroySurface(IWineD3DSurface *pSurface) DECLSPEC_HIDDEN;
extern ULONG WINAPI D3DCB_DefaultDestroyVolume(IWineD3DVolume *pSurface) DECLSPEC_HIDDEN;
/*****************************************************************************
......@@ -1467,6 +1465,7 @@ struct ffp_frag_desc
};
extern const struct wine_rb_functions wined3d_ffp_frag_program_rb_functions DECLSPEC_HIDDEN;
extern const struct wined3d_parent_ops wined3d_null_parent_ops DECLSPEC_HIDDEN;
void gen_ffp_frag_op(IWineD3DStateBlockImpl *stateblock, struct ffp_frag_settings *settings,
BOOL ignore_textype) DECLSPEC_HIDDEN;
......@@ -1958,6 +1957,7 @@ struct IWineD3DSurfaceImpl
IWineD3DResourceClass resource;
/* IWineD3DSurface fields */
const struct wined3d_parent_ops *parent_ops;
IWineD3DBase *container;
WINED3DSURFACET_DESC currentDesc;
IWineD3DPaletteImpl *palette; /* D3D7 style palette handling */
......@@ -2023,7 +2023,7 @@ void surface_gdi_cleanup(IWineD3DSurfaceImpl *This) DECLSPEC_HIDDEN;
HRESULT surface_init(IWineD3DSurfaceImpl *surface, WINED3DSURFTYPE surface_type, UINT alignment,
UINT width, UINT height, UINT level, BOOL lockable, BOOL discard, WINED3DMULTISAMPLE_TYPE multisample_type,
UINT multisample_quality, IWineD3DDeviceImpl *device, DWORD usage, WINED3DFORMAT format,
WINED3DPOOL pool, IUnknown *parent) DECLSPEC_HIDDEN;
WINED3DPOOL pool, IUnknown *parent, const struct wined3d_parent_ops *parent_ops) DECLSPEC_HIDDEN;
/* Predeclare the shared Surface functions */
HRESULT WINAPI IWineD3DBaseSurfaceImpl_QueryInterface(IWineD3DSurface *iface,
......
......@@ -2143,6 +2143,11 @@ struct wined3d_shader_signature
char *string_data;
};
struct wined3d_parent_ops
{
void (*wined3d_object_destroyed)(void *parent);
};
interface IWineD3DResource;
interface IWineD3DSurface;
interface IWineD3DVolume;
......@@ -2210,7 +2215,6 @@ interface IWineD3DDeviceParent : IUnknown
[out] IWineD3DSwapChain **swapchain
);
}
typedef ULONG (*D3DCB_DESTROYSURFACEFN)(IWineD3DSurface *pSurface);
typedef ULONG (*D3DCB_DESTROYVOLUMEFN)(IWineD3DVolume *pVolume);
typedef ULONG (*D3DCB_DESTROYSWAPCHAINFN)(IWineD3DSwapChain *pSwapChain);
typedef HRESULT (*D3DCB_ENUMRESOURCES)(IWineD3DResource *resource, void *pData);
......@@ -2619,7 +2623,6 @@ interface IWineD3DBaseTexture : IWineD3DResource
interface IWineD3DTexture : IWineD3DBaseTexture
{
void Destroy(
[in] D3DCB_DESTROYSURFACEFN destroy_surface_callback
);
HRESULT GetLevelDesc(
[in] UINT level,
......@@ -2651,7 +2654,6 @@ interface IWineD3DTexture : IWineD3DBaseTexture
interface IWineD3DCubeTexture : IWineD3DBaseTexture
{
void Destroy(
[in] D3DCB_DESTROYSURFACEFN destroy_surface_callback
);
HRESULT GetLevelDesc(
[in] UINT level,
......@@ -2773,7 +2775,6 @@ interface IWineD3DQuery : IWineD3DBase
interface IWineD3DSwapChain : IWineD3DBase
{
void Destroy(
[in] D3DCB_DESTROYSURFACEFN destroy_surface_callback
);
HRESULT GetDevice(
[out] IWineD3DDevice **device
......@@ -2930,7 +2931,8 @@ interface IWineD3DDevice : IWineD3DBase
[in] WINED3DMULTISAMPLE_TYPE multisample_type,
[in] DWORD multisample_quality,
[in] WINED3DSURFTYPE surface_type,
[in] IUnknown *parent
[in] IUnknown *parent,
[in] const struct wined3d_parent_ops *parent_ops
);
HRESULT CreateRendertargetView(
[in] IWineD3DResource *resource,
......@@ -3024,7 +3026,6 @@ interface IWineD3DDevice : IWineD3DBase
[in] WINED3DPRESENT_PARAMETERS *present_parameters
);
HRESULT Uninit3D(
[in] D3DCB_DESTROYSURFACEFN destroy_surface_callback,
[in] D3DCB_DESTROYSWAPCHAINFN destroy_swapchain_callback
);
HRESULT UninitGDI(
......
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