diff --git a/dlls/ddraw/ddraw.c b/dlls/ddraw/ddraw.c index c3e1a384493..d039388bd45 100644 --- a/dlls/ddraw/ddraw.c +++ b/dlls/ddraw/ddraw.c @@ -2051,6 +2051,8 @@ static HRESULT WINAPI ddraw4_GetGDISurface(IDirectDraw4 *iface, IDirectDrawSurfa } surface_impl = impl_from_IDirectDrawSurface7(surface7); *surface = &surface_impl->IDirectDrawSurface4_iface; + IDirectDrawSurface4_AddRef(*surface); + IDirectDrawSurface7_Release(surface7); return hr; } @@ -3809,6 +3811,9 @@ static HRESULT CALLBACK EnumSurfacesCallback2Thunk(IDirectDrawSurface7 *surface, IDirectDrawSurfaceImpl *surface_impl = impl_from_IDirectDrawSurface7(surface); struct surfacescallback2_context *cbcontext = context; + IDirectDrawSurface4_AddRef(&surface_impl->IDirectDrawSurface4_iface); + IDirectDrawSurface7_Release(surface); + return cbcontext->func(&surface_impl->IDirectDrawSurface4_iface, surface_desc, cbcontext->context); } @@ -4266,6 +4271,8 @@ static HRESULT WINAPI ddraw4_DuplicateSurface(IDirectDraw4 *iface, IDirectDrawSu } dst_impl = impl_from_IDirectDrawSurface7(dst7); *dst = &dst_impl->IDirectDrawSurface4_iface; + IDirectDrawSurface4_AddRef(*dst); + IDirectDrawSurface7_Release(dst7); return hr; } diff --git a/dlls/ddraw/ddraw_private.h b/dlls/ddraw/ddraw_private.h index 1a8dc2025f8..92dad301612 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, ref3, ref2, iface_count; + LONG ref, ref4, ref3, ref2, iface_count; IUnknown *ifaceToRelease; int version; diff --git a/dlls/ddraw/device.c b/dlls/ddraw/device.c index 96999390953..a019becda18 100644 --- a/dlls/ddraw/device.c +++ b/dlls/ddraw/device.c @@ -1970,6 +1970,8 @@ static HRESULT WINAPI IDirect3DDeviceImpl_3_GetRenderTarget(IDirect3DDevice3 *if if(hr != D3D_OK) return hr; RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7); *RenderTarget = &RenderTargetImpl->IDirectDrawSurface4_iface; + IDirectDrawSurface4_AddRef(*RenderTarget); + IDirectDrawSurface7_Release(RenderTarget7); return D3D_OK; } diff --git a/dlls/ddraw/main.c b/dlls/ddraw/main.c index 37404d82064..8d161f5dce0 100644 --- a/dlls/ddraw/main.c +++ b/dlls/ddraw/main.c @@ -752,14 +752,17 @@ DestroyCallback(IDirectDrawSurface7 *surf, void *context) { IDirectDrawSurfaceImpl *Impl = impl_from_IDirectDrawSurface7(surf); - ULONG ref, ref3, ref2, iface_count; + ULONG ref, ref4, ref3, ref2, iface_count; ref = IDirectDrawSurface7_Release(surf); /* For the EnumSurfaces */ + IDirectDrawSurface4_AddRef(&Impl->IDirectDrawSurface4_iface); + ref4 = IDirectDrawSurface4_Release(&Impl->IDirectDrawSurface4_iface); IDirectDrawSurface3_AddRef(&Impl->IDirectDrawSurface3_iface); ref3 = IDirectDrawSurface3_Release(&Impl->IDirectDrawSurface3_iface); IDirectDrawSurface2_AddRef(&Impl->IDirectDrawSurface2_iface); ref2 = IDirectDrawSurface2_Release(&Impl->IDirectDrawSurface2_iface); - WARN("Surface %p has an reference counts of %d 3: %d 2: %d\n", Impl, ref, ref3, ref2); + WARN("Surface %p has an reference counts of %u 4: %u 3: %u 2: %u\n", + Impl, ref, ref4, ref3, ref2); /* Skip surfaces which are attached somewhere or which are * part of a complex compound. They will get released when destroying diff --git a/dlls/ddraw/surface.c b/dlls/ddraw/surface.c index e391b3d5e14..248aa376543 100644 --- a/dlls/ddraw/surface.c +++ b/dlls/ddraw/surface.c @@ -83,7 +83,7 @@ static HRESULT WINAPI ddraw_surface7_QueryInterface(IDirectDrawSurface7 *iface, } else if (IsEqualGUID(riid, &IID_IDirectDrawSurface4)) { - IUnknown_AddRef(iface); + IDirectDrawSurface4_AddRef(&This->IDirectDrawSurface4_iface); *obj = &This->IDirectDrawSurface4_iface; TRACE("(%p) returning IDirectDrawSurface4 interface at %p\n", This, *obj); return S_OK; @@ -258,9 +258,16 @@ static ULONG WINAPI ddraw_surface7_AddRef(IDirectDrawSurface7 *iface) static ULONG WINAPI ddraw_surface4_AddRef(IDirectDrawSurface4 *iface) { IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface); - TRACE("iface %p.\n", iface); + ULONG refcount = InterlockedIncrement(&This->ref4); - 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_surface3_AddRef(IDirectDrawSurface3 *iface) @@ -349,8 +356,8 @@ void ddraw_surface_destroy(IDirectDrawSurfaceImpl *This) * because the 2nd surface was addref()ed when the app * called GetAttachedSurface */ - WARN("(%p): Destroying surface with refcounts %d 3: %d 2: %d\n", This, This->ref, - This->ref3, This->ref2); + WARN("(%p): Destroying surface with refcounts %d 4: %d 3: %d 2: %d\n", + This, This->ref, This->ref4, This->ref3, This->ref2); } if (This->wined3d_surface) @@ -521,9 +528,16 @@ static ULONG WINAPI ddraw_surface7_Release(IDirectDrawSurface7 *iface) static ULONG WINAPI ddraw_surface4_Release(IDirectDrawSurface4 *iface) { IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface4(iface); - TRACE("iface %p.\n", iface); + ULONG refcount = InterlockedDecrement(&This->ref4); - 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_surface3_Release(IDirectDrawSurface3 *iface) @@ -726,6 +740,8 @@ static HRESULT WINAPI ddraw_surface4_GetAttachedSurface(IDirectDrawSurface4 *ifa } attachment_impl = impl_from_IDirectDrawSurface7(attachment7); *attachment = &attachment_impl->IDirectDrawSurface4_iface; + ddraw_surface4_AddRef(*attachment); + ddraw_surface7_Release(attachment7); return hr; } @@ -2282,6 +2298,9 @@ static HRESULT CALLBACK EnumCallback2(IDirectDrawSurface7 *surface, DDSURFACEDES IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(surface); const struct callback_info2 *info = context; + ddraw_surface4_AddRef(&This->IDirectDrawSurface4_iface); + ddraw_surface7_Release(surface); + return info->callback(&This->IDirectDrawSurface4_iface, surface_desc, info->context); } @@ -5143,11 +5162,19 @@ HRESULT ddraw_surface_init(IDirectDrawSurfaceImpl *surface, IDirectDrawImpl *ddr surface->IDirectDrawGammaControl_iface.lpVtbl = &ddraw_gamma_control_vtbl; 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; + if (version == 4) + { + surface->ref4 = 1; + } + else + { + surface->ref = 1; + } + copy_to_surfacedesc2(&surface->surface_desc, desc); surface->first_attached = surface; diff --git a/dlls/ddraw/tests/dsurface.c b/dlls/ddraw/tests/dsurface.c index 4cfe4695d8c..62532dd1133 100644 --- a/dlls/ddraw/tests/dsurface.c +++ b/dlls/ddraw/tests/dsurface.c @@ -1096,7 +1096,7 @@ static void IFaceRefCount(void) IDirectDrawSurface_QueryInterface(surf, &IID_IDirectDrawSurface4, (void **) &surf4); ref = getRefcount((IUnknown *) surf4); - 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_IDirectDrawSurface7, (void **) &surf7a); ref = getRefcount((IUnknown *) surf7a); @@ -1151,7 +1151,7 @@ static void IFaceRefCount(void) ok(ref == 0, "Refcount is %u, expected 0\n", ref); ref = IDirectDrawSurface4_Release(surf4); - todo_wine ok(ref == 0, "Refcount is %u, expected 0\n", ref); + ok(ref == 0, "Refcount is %u, expected 0\n", ref); ref = IDirectDrawSurface7_Release(surf7a); todo_wine ok(ref == 1, "Refcount is %u, expected 1\n", ref); @@ -3135,9 +3135,9 @@ static void GetDCTest(void) ok(SUCCEEDED(hr), "QueryInterface failed, hr %#x.\n", hr); 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); ref = getRefcount((IUnknown *) surf4); - todo_wine ok(ref == 1, "Refcount is %u, expected 1\n", ref); + ok(ref == 1, "Refcount is %u, expected 1\n", ref); hr = IDirectDrawSurface4_GetDC(surf4, &dc); ok(SUCCEEDED(hr), "GetDC failed, hr %#x.\n", hr); @@ -3150,11 +3150,11 @@ static void GetDCTest(void) ok(tmp == surf, "Expected surface %p, got %p.\n\n", surf, tmp); ref = getRefcount((IUnknown *) surf); - todo_wine ok(ref == 2, "Refcount is %u, expected 2\n", ref); + ok(ref == 2, "Refcount is %u, expected 2\n", ref); ref = getRefcount((IUnknown *) tmp); - todo_wine ok(ref == 2, "Refcount is %u, expected 2\n", ref); + ok(ref == 2, "Refcount is %u, expected 2\n", ref); ref = getRefcount((IUnknown *) surf4); - todo_wine ok(ref == 1, "Refcount is %u, expected 1\n", ref); + ok(ref == 1, "Refcount is %u, expected 1\n", ref); hr = IDirectDrawSurface4_ReleaseDC(surf4, dc); ok(SUCCEEDED(hr), "ReleaseDC failed, hr %#x.\n", hr);