diff --git a/dlls/ddraw/ddraw_private.h b/dlls/ddraw/ddraw_private.h index 7b00debdded..5d747152ed5 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, iface_count; + LONG ref, ref2, iface_count; IUnknown *ifaceToRelease; int version; diff --git a/dlls/ddraw/main.c b/dlls/ddraw/main.c index 7a693ee574b..863c5b0143a 100644 --- a/dlls/ddraw/main.c +++ b/dlls/ddraw/main.c @@ -752,10 +752,12 @@ DestroyCallback(IDirectDrawSurface7 *surf, void *context) { IDirectDrawSurfaceImpl *Impl = impl_from_IDirectDrawSurface7(surf); - ULONG ref; + ULONG ref, ref2; ref = IDirectDrawSurface7_Release(surf); /* For the EnumSurfaces */ - WARN("Surface %p has an reference count of %d\n", Impl, ref); + IDirectDrawSurface2_AddRef(&Impl->IDirectDrawSurface2_iface); + ref2 = IDirectDrawSurface2_Release(&Impl->IDirectDrawSurface2_iface); + WARN("Surface %p has an reference counts of %d 2: %d\n", Impl, ref, ref2); /* Skip surfaces which are attached somewhere or which are * part of a complex compound. They will get released when destroying @@ -765,7 +767,8 @@ DestroyCallback(IDirectDrawSurface7 *surf, return DDENUMRET_OK; /* Destroy the surface */ - while(ref) ref = IDirectDrawSurface7_Release(surf); + while (ref) ref = IDirectDrawSurface7_Release(surf); + while (ref2) ref2 = IDirectDrawSurface2_Release(&Impl->IDirectDrawSurface2_iface); return DDENUMRET_OK; } diff --git a/dlls/ddraw/surface.c b/dlls/ddraw/surface.c index fdb199ea80e..62047036e33 100644 --- a/dlls/ddraw/surface.c +++ b/dlls/ddraw/surface.c @@ -97,7 +97,7 @@ static HRESULT WINAPI ddraw_surface7_QueryInterface(IDirectDrawSurface7 *iface, } else if (IsEqualGUID(riid, &IID_IDirectDrawSurface2)) { - IUnknown_AddRef(iface); + IDirectDrawSurface2_AddRef(&This->IDirectDrawSurface2_iface); *obj = &This->IDirectDrawSurface2_iface; TRACE("(%p) returning IDirectDrawSurface2 interface at %p\n", This, *obj); return S_OK; @@ -274,9 +274,16 @@ static ULONG WINAPI ddraw_surface3_AddRef(IDirectDrawSurface3 *iface) static ULONG WINAPI ddraw_surface2_AddRef(IDirectDrawSurface2 *iface) { IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface); - TRACE("iface %p.\n", iface); + ULONG refcount = InterlockedIncrement(&This->ref2); - return ddraw_surface7_AddRef(&This->IDirectDrawSurface7_iface); + TRACE("iface %p increasing refcount to %u.\n", iface, refcount); + + if (refcount == 1) + { + ddraw_surface_add_iface(This); + } + + return refcount; } static ULONG WINAPI ddraw_surface1_AddRef(IDirectDrawSurface *iface) @@ -335,7 +342,7 @@ void ddraw_surface_destroy(IDirectDrawSurfaceImpl *This) * because the 2nd surface was addref()ed when the app * called GetAttachedSurface */ - WARN("(%p): Destroying surface with refount %d\n", This, This->ref); + WARN("(%p): Destroying surface with refcounts %d 2: %d\n", This, This->ref, This->ref2); } if (This->wined3d_surface) @@ -522,9 +529,16 @@ static ULONG WINAPI ddraw_surface3_Release(IDirectDrawSurface3 *iface) static ULONG WINAPI ddraw_surface2_Release(IDirectDrawSurface2 *iface) { IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface2(iface); - TRACE("iface %p.\n", iface); + ULONG refcount = InterlockedDecrement(&This->ref2); - return ddraw_surface7_Release(&This->IDirectDrawSurface7_iface); + TRACE("iface %p decreasing refcount to %u.\n", iface, refcount); + + if (refcount == 0) + { + ddraw_surface_release_iface(This); + } + + return refcount; } static ULONG WINAPI ddraw_surface1_Release(IDirectDrawSurface *iface) @@ -755,6 +769,8 @@ static HRESULT WINAPI ddraw_surface2_GetAttachedSurface(IDirectDrawSurface2 *ifa } attachment_impl = impl_from_IDirectDrawSurface7(attachment7); *attachment = &attachment_impl->IDirectDrawSurface2_iface; + ddraw_surface2_AddRef(*attachment); + ddraw_surface7_Release(attachment7); return hr; } diff --git a/dlls/ddraw/tests/dsurface.c b/dlls/ddraw/tests/dsurface.c index 8bc400daeb3..99058ab90ba 100644 --- a/dlls/ddraw/tests/dsurface.c +++ b/dlls/ddraw/tests/dsurface.c @@ -1080,15 +1080,15 @@ static void IFaceRefCount(void) IDirectDrawSurface_QueryInterface(surf, &IID_IDirectDrawSurface2, (void **) &surf2); ref = getRefcount((IUnknown *) surf); - todo_wine ok(ref == 1, "Refcount is %u, expected 1\n", ref); /* Check the ref count is one */ + ok(ref == 1, "Refcount is %u, expected 1\n", ref); /* Check the ref count is one */ ref = getRefcount((IUnknown *) surf2); - todo_wine ok(ref == 1, "Refcount is %u, expected 1\n", ref); /* This should also be one */ + ok(ref == 1, "Refcount is %u, expected 1\n", ref); /* This should also be one */ IDirectDrawSurface_QueryInterface(surf, &IID_IDirectDrawSurface2, (void **) &surf2a); ref = getRefcount((IUnknown *) surf2); - todo_wine ok(ref == 2, "Refcount is %u, expected 2\n", ref); /* Surf2's refcount should be 2 now, but surf should be 1 */ + ok(ref == 2, "Refcount is %u, expected 2\n", ref); /* Surf2's refcount should be 2 now, but surf should be 1 */ ref = getRefcount((IUnknown *) surf); - todo_wine ok(ref == 1, "Refcount is %u, expected 1\n", ref); + ok(ref == 1, "Refcount is %u, expected 1\n", ref); IDirectDrawSurface_QueryInterface(surf, &IID_IDirectDrawSurface3, (void **) &surf3); ref = getRefcount((IUnknown *) surf3); @@ -1142,10 +1142,10 @@ static void IFaceRefCount(void) } ref = IDirectDrawSurface2_Release(surf2); /* Release one of the 2 surf2 interfaces */ - todo_wine ok(ref == 1, "Refcount is %u, expected 1\n", ref); + ok(ref == 1, "Refcount is %u, expected 1\n", ref); ref = IDirectDrawSurface2_Release(surf2a); /* Release the other */ - todo_wine ok(ref == 0, "Refcount is %u, expected 0\n", ref); + ok(ref == 0, "Refcount is %u, expected 0\n", ref); ref = IDirectDrawSurface3_Release(surf3); todo_wine ok(ref == 0, "Refcount is %u, expected 0\n", ref);