[PATCH 05/10] wined3d: Don't free D3D cube textures until the wined3d cube texture is destroyed.

Henri Verbeet hverbeet at codeweavers.com
Thu Sep 17 05:35:25 CDT 2009


---
 dlls/d3d8/cubetexture.c        |   27 ++++++++++++++++++++++-----
 dlls/d3d9/cubetexture.c        |   27 ++++++++++++++++++++++-----
 dlls/ddraw/ddraw.c             |    5 +++--
 dlls/wined3d/cubetexture.c     |   22 +++++++++-------------
 dlls/wined3d/device.c          |    8 ++++----
 dlls/wined3d/wined3d_private.h |    6 ++++--
 include/wine/wined3d.idl       |    5 ++---
 7 files changed, 66 insertions(+), 34 deletions(-)

diff --git a/dlls/d3d8/cubetexture.c b/dlls/d3d8/cubetexture.c
index 97454d0..d3ec98c 100644
--- a/dlls/d3d8/cubetexture.c
+++ b/dlls/d3d8/cubetexture.c
@@ -46,6 +46,14 @@ static ULONG WINAPI IDirect3DCubeTexture8Impl_AddRef(LPDIRECT3DCUBETEXTURE8 ifac
 
     TRACE("(%p) : AddRef from %d\n", This, ref - 1);
 
+    if (ref == 1)
+    {
+        IUnknown_AddRef(This->parentDevice);
+        wined3d_mutex_lock();
+        IWineD3DCubeTexture_AddRef(This->wineD3DCubeTexture);
+        wined3d_mutex_unlock();
+    }
+
     return ref;
 }
 
@@ -58,12 +66,10 @@ static ULONG WINAPI IDirect3DCubeTexture8Impl_Release(LPDIRECT3DCUBETEXTURE8 ifa
     if (ref == 0) {
         TRACE("Releasing child %p\n", This->wineD3DCubeTexture);
 
+        IUnknown_Release(This->parentDevice);
         wined3d_mutex_lock();
-        IWineD3DCubeTexture_Destroy(This->wineD3DCubeTexture);
+        IWineD3DCubeTexture_Release(This->wineD3DCubeTexture);
         wined3d_mutex_unlock();
-
-        IUnknown_Release(This->parentDevice);
-        HeapFree(GetProcessHeap(), 0, This);
     }
     return ref;
 }
@@ -313,6 +319,16 @@ static const IDirect3DCubeTexture8Vtbl Direct3DCubeTexture8_Vtbl =
     IDirect3DCubeTexture8Impl_AddDirtyRect
 };
 
+static void STDMETHODCALLTYPE d3d8_cubetexture_wined3d_object_destroyed(void *parent)
+{
+    HeapFree(GetProcessHeap(), 0, parent);
+}
+
+static const struct wined3d_parent_ops d3d8_cubetexture_wined3d_parent_ops =
+{
+    d3d8_cubetexture_wined3d_object_destroyed,
+};
+
 HRESULT cubetexture_init(IDirect3DCubeTexture8Impl *texture, IDirect3DDevice8Impl *device,
         UINT edge_length, UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool)
 {
@@ -323,7 +339,8 @@ HRESULT cubetexture_init(IDirect3DCubeTexture8Impl *texture, IDirect3DDevice8Imp
 
     wined3d_mutex_lock();
     hr = IWineD3DDevice_CreateCubeTexture(device->WineD3DDevice, edge_length, levels, usage & WINED3DUSAGE_MASK,
-            wined3dformat_from_d3dformat(format), pool, &texture->wineD3DCubeTexture, (IUnknown *)texture);
+            wined3dformat_from_d3dformat(format), pool, &texture->wineD3DCubeTexture,
+            (IUnknown *)texture, &d3d8_cubetexture_wined3d_parent_ops);
     wined3d_mutex_unlock();
     if (FAILED(hr))
     {
diff --git a/dlls/d3d9/cubetexture.c b/dlls/d3d9/cubetexture.c
index 4727051..4bab9df 100644
--- a/dlls/d3d9/cubetexture.c
+++ b/dlls/d3d9/cubetexture.c
@@ -49,6 +49,14 @@ static ULONG WINAPI IDirect3DCubeTexture9Impl_AddRef(LPDIRECT3DCUBETEXTURE9 ifac
 
     TRACE("(%p) : AddRef from %d\n", This, ref - 1);
 
+    if (ref == 1)
+    {
+        IDirect3DDevice9Ex_AddRef(This->parentDevice);
+        wined3d_mutex_lock();
+        IWineD3DCubeTexture_AddRef(This->wineD3DCubeTexture);
+        wined3d_mutex_unlock();
+    }
+
     return ref;
 }
 
@@ -61,12 +69,10 @@ static ULONG WINAPI IDirect3DCubeTexture9Impl_Release(LPDIRECT3DCUBETEXTURE9 ifa
     if (ref == 0) {
         TRACE("Releasing child %p\n", This->wineD3DCubeTexture);
 
-        wined3d_mutex_lock();
-        IWineD3DCubeTexture_Destroy(This->wineD3DCubeTexture);
         IDirect3DDevice9Ex_Release(This->parentDevice);
+        wined3d_mutex_lock();
+        IWineD3DCubeTexture_Release(This->wineD3DCubeTexture);
         wined3d_mutex_unlock();
-
-        HeapFree(GetProcessHeap(), 0, This);
     }
     return ref;
 }
@@ -352,6 +358,16 @@ static const IDirect3DCubeTexture9Vtbl Direct3DCubeTexture9_Vtbl =
     IDirect3DCubeTexture9Impl_AddDirtyRect
 };
 
+static void STDMETHODCALLTYPE cubetexture_wined3d_object_destroyed(void *parent)
+{
+    HeapFree(GetProcessHeap(), 0, parent);
+}
+
+static const struct wined3d_parent_ops d3d9_cubetexture_wined3d_parent_ops =
+{
+    cubetexture_wined3d_object_destroyed,
+};
+
 HRESULT cubetexture_init(IDirect3DCubeTexture9Impl *texture, IDirect3DDevice9Impl *device,
         UINT edge_length, UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool)
 {
@@ -362,7 +378,8 @@ HRESULT cubetexture_init(IDirect3DCubeTexture9Impl *texture, IDirect3DDevice9Imp
 
     wined3d_mutex_lock();
     hr = IWineD3DDevice_CreateCubeTexture(device->WineD3DDevice, edge_length, levels, usage,
-            wined3dformat_from_d3dformat(format), pool, &texture->wineD3DCubeTexture, (IUnknown *)texture);
+            wined3dformat_from_d3dformat(format), pool, &texture->wineD3DCubeTexture,
+            (IUnknown *)texture, &d3d9_cubetexture_wined3d_parent_ops);
     wined3d_mutex_unlock();
     if (FAILED(hr))
     {
diff --git a/dlls/ddraw/ddraw.c b/dlls/ddraw/ddraw.c
index 98c30b4..5434b9a 100644
--- a/dlls/ddraw/ddraw.c
+++ b/dlls/ddraw/ddraw.c
@@ -2620,8 +2620,9 @@ IDirectDrawImpl_CreateSurface(IDirectDraw7 *iface,
          */
         if(desc2.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
         {
-            hr = IWineD3DDevice_CreateCubeTexture(This->wineD3DDevice, DDSD->dwWidth /* Edgelength */, levels,
-                    0 /* usage */, Format, Pool, (IWineD3DCubeTexture **)&object->wineD3DTexture, (IUnknown *)object);
+            hr = IWineD3DDevice_CreateCubeTexture(This->wineD3DDevice, DDSD->dwWidth /* Edgelength */,
+                    levels, 0 /* usage */, Format, Pool, (IWineD3DCubeTexture **)&object->wineD3DTexture,
+                    (IUnknown *)object, &ddraw_null_wined3d_parent_ops);
         }
         else
         {
diff --git a/dlls/wined3d/cubetexture.c b/dlls/wined3d/cubetexture.c
index 744bb7f..45a94d3 100644
--- a/dlls/wined3d/cubetexture.c
+++ b/dlls/wined3d/cubetexture.c
@@ -174,8 +174,11 @@ static ULONG WINAPI IWineD3DCubeTextureImpl_Release(IWineD3DCubeTexture *iface)
     ULONG ref;
     TRACE("(%p) : Releasing from %d\n", This, This->resource.ref);
     ref = InterlockedDecrement(&This->resource.ref);
-    if (ref == 0) {
-        IWineD3DCubeTexture_Destroy(iface);
+    if (!ref)
+    {
+        cubetexture_cleanup(This);
+        This->parent_ops->wined3d_object_destroyed(This->resource.parent);
+        HeapFree(GetProcessHeap(), 0, This);
     }
     return ref;
 }
@@ -318,15 +321,6 @@ static BOOL WINAPI IWineD3DCubeTextureImpl_IsCondNP2(IWineD3DCubeTexture *iface)
 /* *******************************************
    IWineD3DCubeTexture IWineD3DCubeTexture parts follow
    ******************************************* */
-static void WINAPI IWineD3DCubeTextureImpl_Destroy(IWineD3DCubeTexture *iface)
-{
-    IWineD3DCubeTextureImpl *This = (IWineD3DCubeTextureImpl *)iface;
-
-    cubetexture_cleanup(This);
-    /* finally delete the object */
-    HeapFree(GetProcessHeap(), 0, This);
-}
-
 static HRESULT WINAPI IWineD3DCubeTextureImpl_GetLevelDesc(IWineD3DCubeTexture *iface, UINT Level, WINED3DSURFACE_DESC* pDesc) {
     IWineD3DCubeTextureImpl *This = (IWineD3DCubeTextureImpl *)iface;
 
@@ -435,7 +429,6 @@ static const IWineD3DCubeTextureVtbl IWineD3DCubeTexture_Vtbl =
     IWineD3DCubeTextureImpl_GetTextureDimensions,
     IWineD3DCubeTextureImpl_IsCondNP2,
     /* IWineD3DCubeTexture */
-    IWineD3DCubeTextureImpl_Destroy,
     IWineD3DCubeTextureImpl_GetLevelDesc,
     IWineD3DCubeTextureImpl_GetCubeMapSurface,
     IWineD3DCubeTextureImpl_LockRect,
@@ -444,7 +437,8 @@ static const IWineD3DCubeTextureVtbl IWineD3DCubeTexture_Vtbl =
 };
 
 HRESULT cubetexture_init(IWineD3DCubeTextureImpl *texture, UINT edge_length, UINT levels,
-        IWineD3DDeviceImpl *device, DWORD usage, WINED3DFORMAT format, WINED3DPOOL pool, IUnknown *parent)
+        IWineD3DDeviceImpl *device, DWORD usage, WINED3DFORMAT format, 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, gl_info);
@@ -500,6 +494,8 @@ HRESULT cubetexture_init(IWineD3DCubeTextureImpl *texture, UINT edge_length, UIN
         return hr;
     }
 
+    texture->parent_ops = parent_ops;
+
     /* Find the nearest pow2 match. */
     pow2_edge_length = 1;
     while (pow2_edge_length < edge_length) pow2_edge_length <<= 1;
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index c5b8d97..ee19bbb 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -1066,9 +1066,9 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface, UIN
     return WINED3D_OK;
 }
 
-static HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface,
-        UINT EdgeLength, UINT Levels, DWORD Usage, WINED3DFORMAT Format,
-        WINED3DPOOL Pool, IWineD3DCubeTexture **ppCubeTexture, IUnknown *parent)
+static HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength, UINT Levels,
+        DWORD Usage, WINED3DFORMAT Format, WINED3DPOOL Pool, IWineD3DCubeTexture **ppCubeTexture,
+        IUnknown *parent, const struct wined3d_parent_ops *parent_ops)
 {
     IWineD3DDeviceImpl      *This = (IWineD3DDeviceImpl *)iface;
     IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
@@ -1082,7 +1082,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface
         return WINED3DERR_OUTOFVIDEOMEMORY;
     }
 
-    hr = cubetexture_init(object, EdgeLength, Levels, This, Usage, Format, Pool, parent);
+    hr = cubetexture_init(object, EdgeLength, Levels, This, Usage, Format, Pool, parent, parent_ops);
     if (FAILED(hr))
     {
         WARN("Failed to initialize cubetexture, returning %#x\n", hr);
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 23fc13c..baf8d36 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1839,11 +1839,13 @@ typedef struct IWineD3DCubeTextureImpl
     IWineD3DBaseTextureClass  baseTexture;
 
     /* IWineD3DCubeTexture */
+    const struct wined3d_parent_ops *parent_ops;
     IWineD3DSurface          *surfaces[6][MAX_MIP_LEVELS];
 } IWineD3DCubeTextureImpl;
 
-HRESULT cubetexture_init(IWineD3DCubeTextureImpl *texture, UINT edge_length, UINT levels, IWineD3DDeviceImpl *device,
-        DWORD usage, WINED3DFORMAT format, WINED3DPOOL pool, IUnknown *parent) DECLSPEC_HIDDEN;
+HRESULT cubetexture_init(IWineD3DCubeTextureImpl *texture, UINT edge_length, UINT levels,
+        IWineD3DDeviceImpl *device, DWORD usage, WINED3DFORMAT format, WINED3DPOOL pool,
+        IUnknown *parent, const struct wined3d_parent_ops *parent_ops) DECLSPEC_HIDDEN;
 
 typedef struct _WINED3DVOLUMET_DESC
 {
diff --git a/include/wine/wined3d.idl b/include/wine/wined3d.idl
index d22b2b6..9d17000 100644
--- a/include/wine/wined3d.idl
+++ b/include/wine/wined3d.idl
@@ -2652,8 +2652,6 @@ interface IWineD3DTexture : IWineD3DBaseTexture
 ]
 interface IWineD3DCubeTexture : IWineD3DBaseTexture
 {
-    void Destroy(
-    );
     HRESULT GetLevelDesc(
         [in] UINT level,
         [out] WINED3DSURFACE_DESC *desc
@@ -2975,7 +2973,8 @@ interface IWineD3DDevice : IWineD3DBase
         [in] WINED3DFORMAT format,
         [in] WINED3DPOOL pool,
         [out] IWineD3DCubeTexture **texture,
-        [in] IUnknown *parent
+        [in] IUnknown *parent,
+        [in] const struct wined3d_parent_ops *parent_ops
     );
     HRESULT CreateQuery(
         [in] WINED3DQUERYTYPE type,
-- 
1.6.0.6




More information about the wine-patches mailing list