quartz/vmr9: Track the IVMRSurfaceAllocatorNotify9 reference count separately.

Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Zebediah Figura 2020-05-04 18:05:22 -05:00 committed by Alexandre Julliard
parent 05adf7bed2
commit 9181a12e62
2 changed files with 36 additions and 9 deletions

View File

@ -3271,10 +3271,10 @@ static void test_surface_allocator_notify_refcount(void)
ok(hr == S_OK, "Got hr %#x.\n", hr);
ref = IBaseFilter_Release(filter);
todo_wine ok(!ref, "Got outstanding refcount %d.\n", ref);
ok(!ref, "Got outstanding refcount %d.\n", ref);
todo_wine ok(allocator_got_TerminateDevice == 1, "Got %u calls to TerminateDevice().\n",
allocator_got_TerminateDevice);
todo_wine ok(allocator_refcount == 1, "Got outstanding refcount %d.\n", allocator_refcount);
ok(allocator_refcount == 1, "Got outstanding refcount %d.\n", allocator_refcount);
ref = IVMRSurfaceAllocatorNotify9_Release(notify);
ok(!ref, "Got outstanding refcount %d.\n", ref);

View File

@ -56,6 +56,12 @@ struct quartz_vmr
IVMRWindowlessControl IVMRWindowlessControl_iface;
IVMRWindowlessControl9 IVMRWindowlessControl9_iface;
/* Devil May Cry 3 releases the last IBaseFilter reference while still
* holding an IVMRSurfaceAllocatorNotify9 reference, and depends on
* IVMRSurfaceAllocator9::TerminateDevice() being called as a result.
* Native uses a separate reference count for IVMRSurfaceAllocatorNotify9. */
LONG IVMRSurfaceAllocatorNotify9_refcount;
IOverlay IOverlay_iface;
IVMRSurfaceAllocatorEx9 *allocator;
@ -571,12 +577,23 @@ static HRESULT WINAPI VMR9_BreakConnect(struct strmbase_renderer *This)
return hr;
}
static void vmr_free(struct quartz_vmr *filter)
{
free(filter);
InterlockedDecrement(&object_locks);
}
static void vmr_destroy(struct strmbase_renderer *iface)
{
struct quartz_vmr *filter = impl_from_IBaseFilter(&iface->filter.IBaseFilter_iface);
video_window_cleanup(&filter->baseControlWindow);
/* Devil May Cry 3 releases the IVMRSurfaceAllocatorNotify9 interface from
* TerminateDevice(). Artificially increase the reference count so that we
* don't free the filter yet. */
InterlockedIncrement(&filter->renderer.filter.refcount);
if (filter->allocator)
IVMRSurfaceAllocatorEx9_Release(filter->allocator);
if (filter->presenter)
@ -592,9 +609,8 @@ static void vmr_destroy(struct strmbase_renderer *iface)
CloseHandle(filter->run_event);
FreeLibrary(filter->hD3d9);
strmbase_renderer_cleanup(&filter->renderer);
free(filter);
InterlockedDecrement(&object_locks);
if (!filter->IVMRSurfaceAllocatorNotify9_refcount)
vmr_free(filter);
}
static HRESULT vmr_query_interface(struct strmbase_renderer *iface, REFIID iid, void **out)
@ -2044,14 +2060,25 @@ static HRESULT WINAPI VMR9SurfaceAllocatorNotify_QueryInterface(IVMRSurfaceAlloc
static ULONG WINAPI VMR9SurfaceAllocatorNotify_AddRef(IVMRSurfaceAllocatorNotify9 *iface)
{
struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
return IUnknown_AddRef(This->renderer.filter.outer_unk);
struct quartz_vmr *filter = impl_from_IVMRSurfaceAllocatorNotify9(iface);
ULONG refcount = InterlockedIncrement(&filter->IVMRSurfaceAllocatorNotify9_refcount);
TRACE("%p increasing refcount to %u.\n", iface, refcount);
return refcount;
}
static ULONG WINAPI VMR9SurfaceAllocatorNotify_Release(IVMRSurfaceAllocatorNotify9 *iface)
{
struct quartz_vmr *This = impl_from_IVMRSurfaceAllocatorNotify9(iface);
return IUnknown_Release(This->renderer.filter.outer_unk);
struct quartz_vmr *filter = impl_from_IVMRSurfaceAllocatorNotify9(iface);
ULONG refcount = InterlockedDecrement(&filter->IVMRSurfaceAllocatorNotify9_refcount);
TRACE("%p decreasing refcount to %u.\n", iface, refcount);
if (!refcount && !filter->renderer.filter.refcount)
vmr_free(filter);
return refcount;
}
static HRESULT WINAPI VMR9SurfaceAllocatorNotify_AdviseSurfaceAllocator(IVMRSurfaceAllocatorNotify9 *iface, DWORD_PTR id, IVMRSurfaceAllocator9 *alloc)