Ričardas Barkauskas : ddraw: Add iface count for IDirectSurfaceImpl.

Alexandre Julliard julliard at winehq.org
Tue Jun 21 12:25:41 CDT 2011


Module: wine
Branch: master
Commit: 4b8fd522f66d2554563f906663653f3ce6c1553c
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=4b8fd522f66d2554563f906663653f3ce6c1553c

Author: Ričardas Barkauskas <rbarkauskas at codeweavers.com>
Date:   Sun Jun 19 13:18:22 2011 +0300

ddraw: Add iface count for IDirectSurfaceImpl.

---

 dlls/ddraw/ddraw_private.h |    2 +-
 dlls/ddraw/surface.c       |   83 ++++++++++++++++++++++++++++---------------
 2 files changed, 55 insertions(+), 30 deletions(-)

diff --git a/dlls/ddraw/ddraw_private.h b/dlls/ddraw/ddraw_private.h
index 9cfbd0e..7b00deb 100644
--- a/dlls/ddraw/ddraw_private.h
+++ b/dlls/ddraw/ddraw_private.h
@@ -161,7 +161,7 @@ struct IDirectDrawSurfaceImpl
     const IDirect3DTexture2Vtbl *IDirect3DTexture2_vtbl;
     const IDirect3DTextureVtbl *IDirect3DTexture_vtbl;
 
-    LONG                     ref;
+    LONG                     ref, iface_count;
     IUnknown                *ifaceToRelease;
 
     int                     version;
diff --git a/dlls/ddraw/surface.c b/dlls/ddraw/surface.c
index 4370ff7..ca9f333 100644
--- a/dlls/ddraw/surface.c
+++ b/dlls/ddraw/surface.c
@@ -215,6 +215,22 @@ static HRESULT WINAPI d3d_texture1_QueryInterface(IDirect3DTexture *iface, REFII
     return ddraw_surface7_QueryInterface(&This->IDirectDrawSurface7_iface, riid, object);
 }
 
+static void ddraw_surface_add_iface(IDirectDrawSurfaceImpl *This)
+{
+    ULONG iface_count = InterlockedIncrement(&This->iface_count);
+    TRACE("%p increasing iface count to %u.\n", This, iface_count);
+
+    if (iface_count == 1)
+    {
+        EnterCriticalSection(&ddraw_cs);
+        if (This->wined3d_surface)
+            wined3d_surface_incref(This->wined3d_surface);
+        if (This->wined3d_texture)
+            wined3d_texture_incref(This->wined3d_texture);
+        LeaveCriticalSection(&ddraw_cs);
+    }
+}
+
 /*****************************************************************************
  * IDirectDrawSurface7::AddRef
  *
@@ -227,21 +243,16 @@ static HRESULT WINAPI d3d_texture1_QueryInterface(IDirect3DTexture *iface, REFII
 static ULONG WINAPI ddraw_surface7_AddRef(IDirectDrawSurface7 *iface)
 {
     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
-    ULONG refCount = InterlockedIncrement(&This->ref);
+    ULONG refcount = InterlockedIncrement(&This->ref);
 
-    TRACE("%p increasing refcount to %u.\n", This, refCount);
+    TRACE("iface %p increasing refcount to %u.\n", iface, refcount);
 
-    if (refCount == 1)
+    if (refcount == 1)
     {
-        EnterCriticalSection(&ddraw_cs);
-        if (This->wined3d_surface)
-            wined3d_surface_incref(This->wined3d_surface);
-        if (This->wined3d_texture)
-            wined3d_texture_incref(This->wined3d_texture);
-        LeaveCriticalSection(&ddraw_cs);
+        ddraw_surface_add_iface(This);
     }
 
-    return refCount;
+    return refcount;
 }
 
 static ULONG WINAPI ddraw_surface4_AddRef(IDirectDrawSurface4 *iface)
@@ -317,8 +328,8 @@ void ddraw_surface_destroy(IDirectDrawSurfaceImpl *This)
 {
     TRACE("surface %p.\n", This);
 
-    /* Check the refcount and give a warning */
-    if(This->ref > 1)
+    /* Check the iface count and give a warning */
+    if(This->iface_count > 1)
     {
         /* This can happen when a complex surface is destroyed,
          * because the 2nd surface was addref()ed when the app
@@ -423,6 +434,31 @@ static void ddraw_surface_cleanup(IDirectDrawSurfaceImpl *surface)
         IUnknown_Release(ifaceToRelease);
 }
 
+static void ddraw_surface_release_iface(IDirectDrawSurfaceImpl *This)
+{
+    ULONG iface_count = InterlockedDecrement(&This->iface_count);
+    TRACE("%p decreasing iface count to %u.\n", This, iface_count);
+
+    if (iface_count == 0)
+    {
+        /* Complex attached surfaces are destroyed implicitly when the root is released */
+        EnterCriticalSection(&ddraw_cs);
+        if(!This->is_complex_root)
+        {
+            WARN("(%p) Attempt to destroy a surface that is not a complex root\n", This);
+            LeaveCriticalSection(&ddraw_cs);
+            return;
+        }
+        if (This->wined3d_texture) /* If it's a texture, destroy the wined3d texture. */
+            wined3d_texture_decref(This->wined3d_texture);
+        else
+            ddraw_surface_cleanup(This);
+        LeaveCriticalSection(&ddraw_cs);
+    }
+
+    return;
+}
+
 /*****************************************************************************
  * IDirectDrawSurface7::Release
  *
@@ -455,28 +491,16 @@ static void ddraw_surface_cleanup(IDirectDrawSurfaceImpl *surface)
 static ULONG WINAPI ddraw_surface7_Release(IDirectDrawSurface7 *iface)
 {
     IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
-    ULONG ref = InterlockedDecrement(&This->ref);
+    ULONG refcount = InterlockedDecrement(&This->ref);
 
-    TRACE("%p decreasing refcount to %u.\n", This, ref);
+    TRACE("iface %p decreasing refcount to %u.\n", iface, refcount);
 
-    if (ref == 0)
+    if (refcount == 0)
     {
-        /* Complex attached surfaces are destroyed implicitly when the root is released */
-        EnterCriticalSection(&ddraw_cs);
-        if(!This->is_complex_root)
-        {
-            WARN("(%p) Attempt to destroy a surface that is not a complex root\n", This);
-            LeaveCriticalSection(&ddraw_cs);
-            return ref;
-        }
-        if (This->wined3d_texture) /* If it's a texture, destroy the wined3d texture. */
-            wined3d_texture_decref(This->wined3d_texture);
-        else
-            ddraw_surface_cleanup(This);
-        LeaveCriticalSection(&ddraw_cs);
+        ddraw_surface_release_iface(This);
     }
 
-    return ref;
+    return refcount;
 }
 
 static ULONG WINAPI ddraw_surface4_Release(IDirectDrawSurface4 *iface)
@@ -5005,6 +5029,7 @@ HRESULT ddraw_surface_init(IDirectDrawSurfaceImpl *surface, IDirectDrawImpl *ddr
     surface->IDirect3DTexture2_vtbl = &d3d_texture2_vtbl;
     surface->IDirect3DTexture_vtbl = &d3d_texture1_vtbl;
     surface->ref = 1;
+    surface->iface_count = 1;
     surface->version = version;
     surface->ddraw = ddraw;
 




More information about the wine-cvs mailing list