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

Henri Verbeet hverbeet at codeweavers.com
Thu Sep 17 16:03:25 CDT 2009


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

diff --git a/dlls/d3d8/texture.c b/dlls/d3d8/texture.c
index 25c9f55..e377fff 100644
--- a/dlls/d3d8/texture.c
+++ b/dlls/d3d8/texture.c
@@ -47,6 +47,14 @@ static ULONG WINAPI IDirect3DTexture8Impl_AddRef(LPDIRECT3DTEXTURE8 iface) {
 
     TRACE("(%p) : AddRef from %d\n", This, ref - 1);
 
+    if (ref == 1)
+    {
+        IDirect3DDevice8_AddRef(This->parentDevice);
+        wined3d_mutex_lock();
+        IWineD3DTexture_AddRef(This->wineD3DTexture);
+        wined3d_mutex_unlock();
+    }
+
     return ref;
 }
 
@@ -57,12 +65,10 @@ static ULONG WINAPI IDirect3DTexture8Impl_Release(LPDIRECT3DTEXTURE8 iface) {
     TRACE("(%p) : ReleaseRef to %d\n", This, ref);
 
     if (ref == 0) {
+        IDirect3DDevice8_Release(This->parentDevice);
         wined3d_mutex_lock();
-        IWineD3DTexture_Destroy(This->wineD3DTexture);
+        IWineD3DTexture_Release(This->wineD3DTexture);
         wined3d_mutex_unlock();
-
-        IUnknown_Release(This->parentDevice);
-        HeapFree(GetProcessHeap(), 0, This);
     }
     return ref;
 }
@@ -312,6 +318,16 @@ static const IDirect3DTexture8Vtbl Direct3DTexture8_Vtbl =
     IDirect3DTexture8Impl_AddDirtyRect
 };
 
+static void STDMETHODCALLTYPE d3d8_texture_wined3d_object_destroyed(void *parent)
+{
+    HeapFree(GetProcessHeap(), 0, parent);
+}
+
+static const struct wined3d_parent_ops d3d8_texture_wined3d_parent_ops =
+{
+    d3d8_texture_wined3d_object_destroyed,
+};
+
 HRESULT texture_init(IDirect3DTexture8Impl *texture, IDirect3DDevice8Impl *device,
         UINT width, UINT height, UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool)
 {
@@ -321,8 +337,9 @@ HRESULT texture_init(IDirect3DTexture8Impl *texture, IDirect3DDevice8Impl *devic
     texture->ref = 1;
 
     wined3d_mutex_lock();
-    hr = IWineD3DDevice_CreateTexture(device->WineD3DDevice, width, height, levels, usage & WINED3DUSAGE_MASK,
-            wined3dformat_from_d3dformat(format), pool, &texture->wineD3DTexture, (IUnknown *)texture);
+    hr = IWineD3DDevice_CreateTexture(device->WineD3DDevice, width, height, levels,
+            usage & WINED3DUSAGE_MASK, wined3dformat_from_d3dformat(format), pool,
+            &texture->wineD3DTexture, (IUnknown *)texture, &d3d8_texture_wined3d_parent_ops);
     wined3d_mutex_unlock();
     if (FAILED(hr))
     {
diff --git a/dlls/d3d9/texture.c b/dlls/d3d9/texture.c
index c3a3232..9818c26 100644
--- a/dlls/d3d9/texture.c
+++ b/dlls/d3d9/texture.c
@@ -49,6 +49,14 @@ static ULONG WINAPI IDirect3DTexture9Impl_AddRef(LPDIRECT3DTEXTURE9 iface) {
 
     TRACE("(%p) : AddRef from %d\n", This, ref - 1);
 
+    if (ref == 1)
+    {
+        IDirect3DDevice9Ex_AddRef(This->parentDevice);
+        wined3d_mutex_lock();
+        IWineD3DTexture_AddRef(This->wineD3DTexture);
+        wined3d_mutex_unlock();
+    }
+
     return ref;
 }
 
@@ -59,12 +67,10 @@ static ULONG WINAPI IDirect3DTexture9Impl_Release(LPDIRECT3DTEXTURE9 iface) {
     TRACE("(%p) : ReleaseRef to %d\n", This, ref);
 
     if (ref == 0) {
+        IDirect3DDevice9Ex_Release(This->parentDevice);
         wined3d_mutex_lock();
-        IWineD3DTexture_Destroy(This->wineD3DTexture);
+        IWineD3DTexture_Release(This->wineD3DTexture);
         wined3d_mutex_unlock();
-
-        IDirect3DDevice9Ex_Release(This->parentDevice);
-        HeapFree(GetProcessHeap(), 0, This);
     }
     return ref;
 }
@@ -350,6 +356,16 @@ static const IDirect3DTexture9Vtbl Direct3DTexture9_Vtbl =
     IDirect3DTexture9Impl_AddDirtyRect
 };
 
+static void STDMETHODCALLTYPE d3d9_texture_wined3d_object_destroyed(void *parent)
+{
+    HeapFree(GetProcessHeap(), 0, parent);
+}
+
+static const struct wined3d_parent_ops d3d9_texture_wined3d_parent_ops =
+{
+    d3d9_texture_wined3d_object_destroyed,
+};
+
 HRESULT texture_init(IDirect3DTexture9Impl *texture, IDirect3DDevice9Impl *device,
         UINT width, UINT height, UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool)
 {
@@ -359,8 +375,9 @@ HRESULT texture_init(IDirect3DTexture9Impl *texture, IDirect3DDevice9Impl *devic
     texture->ref = 1;
 
     wined3d_mutex_lock();
-    hr = IWineD3DDevice_CreateTexture(device->WineD3DDevice, width, height, levels, usage & WINED3DUSAGE_MASK,
-            wined3dformat_from_d3dformat(format), pool, &texture->wineD3DTexture, (IUnknown *)texture);
+    hr = IWineD3DDevice_CreateTexture(device->WineD3DDevice, width, height, levels,
+            usage & WINED3DUSAGE_MASK, wined3dformat_from_d3dformat(format), pool,
+            &texture->wineD3DTexture, (IUnknown *)texture, &d3d9_texture_wined3d_parent_ops);
     wined3d_mutex_unlock();
     if (FAILED(hr))
     {
diff --git a/dlls/ddraw/ddraw.c b/dlls/ddraw/ddraw.c
index 5434b9a..bcbd3c2 100644
--- a/dlls/ddraw/ddraw.c
+++ b/dlls/ddraw/ddraw.c
@@ -2627,7 +2627,8 @@ IDirectDrawImpl_CreateSurface(IDirectDraw7 *iface,
         else
         {
             hr = IWineD3DDevice_CreateTexture(This->wineD3DDevice, DDSD->dwWidth, DDSD->dwHeight, levels,
-                    0 /* usage */, Format, Pool, (IWineD3DTexture **)&object->wineD3DTexture, (IUnknown *)object);
+                    0 /* usage */, Format, Pool, (IWineD3DTexture **)&object->wineD3DTexture,
+                    (IUnknown *)object, &ddraw_null_wined3d_parent_ops);
         }
         This->tex_root = NULL;
     }
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index ee19bbb..ff9d454 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -964,8 +964,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateRendertargetView(IWineD3DDevice *
 }
 
 static HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface,
-        UINT Width, UINT Height, UINT Levels, DWORD Usage, WINED3DFORMAT Format,
-        WINED3DPOOL Pool, IWineD3DTexture **ppTexture, IUnknown *parent)
+        UINT Width, UINT Height, UINT Levels, DWORD Usage, WINED3DFORMAT Format, WINED3DPOOL Pool,
+        IWineD3DTexture **ppTexture, IUnknown *parent, const struct wined3d_parent_ops *parent_ops)
 {
     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
     IWineD3DTextureImpl *object;
@@ -983,7 +983,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface,
         return WINED3DERR_OUTOFVIDEOMEMORY;
     }
 
-    hr = texture_init(object, Width, Height, Levels, This, Usage, Format, Pool, parent);
+    hr = texture_init(object, Width, Height, Levels, This, Usage, Format, Pool, parent, parent_ops);
     if (FAILED(hr))
     {
         WARN("Failed to initialize texture, returning %#x\n", hr);
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c
index 6fd1cf5..b75109e 100644
--- a/dlls/wined3d/texture.c
+++ b/dlls/wined3d/texture.c
@@ -161,8 +161,11 @@ static ULONG WINAPI IWineD3DTextureImpl_Release(IWineD3DTexture *iface) {
     ULONG ref;
     TRACE("(%p) : Releasing from %d\n", This, This->resource.ref);
     ref = InterlockedDecrement(&This->resource.ref);
-    if (ref == 0) {
-        IWineD3DTexture_Destroy(iface);
+    if (!ref)
+    {
+        texture_cleanup(This);
+        This->parent_ops->wined3d_object_destroyed(This->resource.parent);
+        HeapFree(GetProcessHeap(), 0, This);
     }
     return ref;
 }
@@ -323,15 +326,6 @@ static BOOL WINAPI IWineD3DTextureImpl_IsCondNP2(IWineD3DTexture *iface) {
 /* *******************************************
    IWineD3DTexture IWineD3DTexture parts follow
    ******************************************* */
-static void WINAPI IWineD3DTextureImpl_Destroy(IWineD3DTexture *iface)
-{
-    IWineD3DTextureImpl *This = (IWineD3DTextureImpl *)iface;
-
-    texture_cleanup(This);
-    /* free the object */
-    HeapFree(GetProcessHeap(), 0, This);
-}
-
 static HRESULT WINAPI IWineD3DTextureImpl_GetLevelDesc(IWineD3DTexture *iface, UINT Level, WINED3DSURFACE_DESC* pDesc) {
     IWineD3DTextureImpl *This = (IWineD3DTextureImpl *)iface;
 
@@ -432,7 +426,6 @@ static const IWineD3DTextureVtbl IWineD3DTexture_Vtbl =
     IWineD3DTextureImpl_GetTextureDimensions,
     IWineD3DTextureImpl_IsCondNP2,
     /* IWineD3DTexture */
-    IWineD3DTextureImpl_Destroy,
     IWineD3DTextureImpl_GetLevelDesc,
     IWineD3DTextureImpl_GetSurfaceLevel,
     IWineD3DTextureImpl_LockRect,
@@ -441,7 +434,8 @@ static const IWineD3DTextureVtbl IWineD3DTexture_Vtbl =
 };
 
 HRESULT texture_init(IWineD3DTextureImpl *texture, UINT width, UINT height, 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);
@@ -515,6 +509,8 @@ HRESULT texture_init(IWineD3DTextureImpl *texture, UINT width, UINT height, UINT
         return hr;
     }
 
+    texture->parent_ops = parent_ops;
+
     /* Precalculated scaling for 'faked' non power of two texture coords.
      * Second also don't use ARB_TEXTURE_RECTANGLE in case the surface format is P8 and EXT_PALETTED_TEXTURE
      * is used in combination with texture uploads (RTL_READTEX). The reason is that EXT_PALETTED_TEXTURE
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index baf8d36..819cc17 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1819,14 +1819,16 @@ typedef struct IWineD3DTextureImpl
     IWineD3DBaseTextureClass  baseTexture;
 
     /* IWineD3DTexture */
+    const struct wined3d_parent_ops *parent_ops;
     IWineD3DSurface          *surfaces[MAX_MIP_LEVELS];
     UINT                      target;
     BOOL                      cond_np2;
 
 } IWineD3DTextureImpl;
 
-HRESULT texture_init(IWineD3DTextureImpl *texture, UINT width, UINT height, UINT levels, IWineD3DDeviceImpl *device,
-        DWORD usage, WINED3DFORMAT format, WINED3DPOOL pool, IUnknown *parent) DECLSPEC_HIDDEN;
+HRESULT texture_init(IWineD3DTextureImpl *texture, UINT width, UINT height, UINT levels,
+        IWineD3DDeviceImpl *device, DWORD usage, WINED3DFORMAT format, WINED3DPOOL pool,
+        IUnknown *parent, const struct wined3d_parent_ops *parent_ops) DECLSPEC_HIDDEN;
 
 /*****************************************************************************
  * IWineD3DCubeTexture implementation structure (extends IWineD3DBaseTextureImpl)
diff --git a/include/wine/wined3d.idl b/include/wine/wined3d.idl
index 9d17000..6e7ff64 100644
--- a/include/wine/wined3d.idl
+++ b/include/wine/wined3d.idl
@@ -2621,8 +2621,6 @@ interface IWineD3DBaseTexture : IWineD3DResource
 ]
 interface IWineD3DTexture : IWineD3DBaseTexture
 {
-    void Destroy(
-    );
     HRESULT GetLevelDesc(
         [in] UINT level,
         [out] WINED3DSURFACE_DESC *desc
@@ -2941,7 +2939,8 @@ interface IWineD3DDevice : IWineD3DBase
         [in] WINED3DFORMAT format,
         [in] WINED3DPOOL pool,
         [out] IWineD3DTexture **texture,
-        [in] IUnknown *parent
+        [in] IUnknown *parent,
+        [in] const struct wined3d_parent_ops *parent_ops
     );
     HRESULT CreateVolumeTexture(
         [in] UINT width,
-- 
1.6.0.6




More information about the wine-patches mailing list