[PATCH] quartz/vmr9: Allow AdviseSurfaceAllocator() to be called multiple times.
Zebediah Figura
z.figura12 at gmail.com
Thu Jul 23 19:30:16 CDT 2020
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47161
Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
---
dlls/quartz/tests/vmr9.c | 132 ++++++++++++++++++++++++++-------------
dlls/quartz/vmr9.c | 21 ++++++-
2 files changed, 109 insertions(+), 44 deletions(-)
diff --git a/dlls/quartz/tests/vmr9.c b/dlls/quartz/tests/vmr9.c
index d7065280de..c8b35c266d 100644
--- a/dlls/quartz/tests/vmr9.c
+++ b/dlls/quartz/tests/vmr9.c
@@ -2776,28 +2776,40 @@ out:
DestroyWindow(window);
}
-static IVMRSurfaceAllocator9 allocator_iface;
-static IVMRImagePresenter9 presenter_iface;
-static LONG allocator_refcount = 1;
-static D3DFORMAT allocator_format;
-static DWORD allocator_accept_flags;
-static IDirect3DSurface9 *allocator_surfaces[5];
-static IVMRSurfaceAllocatorNotify9 *allocator_notify;
-static unsigned int allocator_got_PresentImage, allocator_got_TerminateDevice;
+struct presenter
+{
+ IVMRSurfaceAllocator9 IVMRSurfaceAllocator9_iface;
+ IVMRImagePresenter9 IVMRImagePresenter9_iface;
+ LONG refcount;
+
+ D3DFORMAT format;
+ DWORD accept_flags;
+ IDirect3DSurface9 *surfaces[5];
+ IVMRSurfaceAllocatorNotify9 *notify;
+ unsigned int got_PresentImage, got_TerminateDevice;
+};
+
+static struct presenter *impl_from_IVMRImagePresenter9(IVMRImagePresenter9 *iface)
+{
+ return CONTAINING_RECORD(iface, struct presenter, IVMRImagePresenter9_iface);
+}
static HRESULT WINAPI presenter_QueryInterface(IVMRImagePresenter9 *iface, REFIID iid, void **out)
{
- return IVMRSurfaceAllocator9_QueryInterface(&allocator_iface, iid, out);
+ struct presenter *presenter = impl_from_IVMRImagePresenter9(iface);
+ return IVMRSurfaceAllocator9_QueryInterface(&presenter->IVMRSurfaceAllocator9_iface, iid, out);
}
static ULONG WINAPI presenter_AddRef(IVMRImagePresenter9 *iface)
{
- return IVMRSurfaceAllocator9_AddRef(&allocator_iface);
+ struct presenter *presenter = impl_from_IVMRImagePresenter9(iface);
+ return IVMRSurfaceAllocator9_AddRef(&presenter->IVMRSurfaceAllocator9_iface);
}
static ULONG WINAPI presenter_Release(IVMRImagePresenter9 *iface)
{
- return IVMRSurfaceAllocator9_Release(&allocator_iface);
+ struct presenter *presenter = impl_from_IVMRImagePresenter9(iface);
+ return IVMRSurfaceAllocator9_Release(&presenter->IVMRSurfaceAllocator9_iface);
}
static HRESULT WINAPI presenter_StartPresenting(IVMRImagePresenter9 *iface, DWORD_PTR cookie)
@@ -2816,7 +2828,9 @@ static HRESULT WINAPI presenter_StopPresenting(IVMRImagePresenter9 *iface, DWORD
static HRESULT WINAPI presenter_PresentImage(IVMRImagePresenter9 *iface, DWORD_PTR cookie, VMR9PresentationInfo *info)
{
+ struct presenter *presenter = impl_from_IVMRImagePresenter9(iface);
static const RECT rect;
+
if (winetest_debug > 1) trace("PresentImage()\n");
ok(cookie == 0xabacab, "Got cookie %#lx.\n", cookie);
todo_wine ok(info->dwFlags == VMR9Sample_TimeValid, "Got flags %#x.\n", info->dwFlags);
@@ -2829,7 +2843,7 @@ static HRESULT WINAPI presenter_PresentImage(IVMRImagePresenter9 *iface, DWORD_P
ok(!info->dwReserved1, "Got dwReserved1 %#x.\n", info->dwReserved1);
ok(!info->dwReserved2, "Got dwReserved2 %#x.\n", info->dwReserved2);
- ++allocator_got_PresentImage;
+ ++presenter->got_PresentImage;
return S_OK;
}
@@ -2843,14 +2857,21 @@ static const IVMRImagePresenter9Vtbl presenter_vtbl =
presenter_PresentImage,
};
+static struct presenter *impl_from_IVMRSurfaceAllocator9(IVMRSurfaceAllocator9 *iface)
+{
+ return CONTAINING_RECORD(iface, struct presenter, IVMRSurfaceAllocator9_iface);
+}
+
static HRESULT WINAPI allocator_QueryInterface(IVMRSurfaceAllocator9 *iface, REFIID iid, void **out)
{
+ struct presenter *presenter = impl_from_IVMRSurfaceAllocator9(iface);
+
if (winetest_debug > 1) trace("QueryInterface(%s)\n", wine_dbgstr_guid(iid));
if (IsEqualGUID(iid, &IID_IVMRImagePresenter9))
{
- *out = &presenter_iface;
- IVMRImagePresenter9_AddRef(&presenter_iface);
+ *out = &presenter->IVMRImagePresenter9_iface;
+ IVMRImagePresenter9_AddRef(&presenter->IVMRImagePresenter9_iface);
return S_OK;
}
ok(!IsEqualGUID(iid, &IID_IVMRSurfaceAllocatorEx9), "Unexpected query for IVMRSurfaceAllocatorEx9.\n");
@@ -2860,17 +2881,21 @@ static HRESULT WINAPI allocator_QueryInterface(IVMRSurfaceAllocator9 *iface, REF
static ULONG WINAPI allocator_AddRef(IVMRSurfaceAllocator9 *iface)
{
- return InterlockedIncrement(&allocator_refcount);
+ struct presenter *presenter = impl_from_IVMRSurfaceAllocator9(iface);
+ return InterlockedIncrement(&presenter->refcount);
}
static ULONG WINAPI allocator_Release(IVMRSurfaceAllocator9 *iface)
{
- return InterlockedDecrement(&allocator_refcount);
+ struct presenter *presenter = impl_from_IVMRSurfaceAllocator9(iface);
+ return InterlockedDecrement(&presenter->refcount);
}
static HRESULT WINAPI allocator_InitializeDevice(IVMRSurfaceAllocator9 *iface,
DWORD_PTR cookie, VMR9AllocationInfo *info, DWORD *buffer_count)
{
+ struct presenter *presenter = impl_from_IVMRSurfaceAllocator9(iface);
+
if (winetest_debug > 1) trace("InitializeDevice(flags %#x, format %u)\n",
info->dwFlags, info->Format);
ok(cookie == 0xabacab, "Got cookie %#lx.\n", cookie);
@@ -2884,33 +2909,37 @@ static HRESULT WINAPI allocator_InitializeDevice(IVMRSurfaceAllocator9 *iface,
ok(info->szNativeSize.cy == 16, "Got native height %d.\n", info->szNativeSize.cy);
todo_wine ok(*buffer_count == 5, "Got buffer count %u.\n", *buffer_count);
- allocator_format = info->Format;
+ presenter->format = info->Format;
- if (info->dwFlags != allocator_accept_flags)
+ if (info->dwFlags != presenter->accept_flags)
return 0xdeadbeef;
- return IVMRSurfaceAllocatorNotify9_AllocateSurfaceHelper(allocator_notify,
- info, buffer_count, allocator_surfaces);
+ return IVMRSurfaceAllocatorNotify9_AllocateSurfaceHelper(presenter->notify,
+ info, buffer_count, presenter->surfaces);
}
static HRESULT WINAPI allocator_TerminateDevice(IVMRSurfaceAllocator9 *iface, DWORD_PTR cookie)
{
+ struct presenter *presenter = impl_from_IVMRSurfaceAllocator9(iface);
+
if (winetest_debug > 1) trace("TerminateDevice()\n");
ok(cookie == 0xabacab, "Got cookie %#lx.\n", cookie);
/* Don't dereference the surfaces here, to mimic How to Survive. */
- ++allocator_got_TerminateDevice;
+ ++presenter->got_TerminateDevice;
return E_NOTIMPL;
}
static HRESULT WINAPI allocator_GetSurface(IVMRSurfaceAllocator9 *iface,
DWORD_PTR cookie, DWORD index, DWORD flags, IDirect3DSurface9 **surface)
{
+ struct presenter *presenter = impl_from_IVMRSurfaceAllocator9(iface);
+
if (winetest_debug > 1) trace("GetSurface(index %u)\n", index);
ok(cookie == 0xabacab, "Got cookie %#lx.\n", cookie);
ok(!flags, "Got flags %#x.\n", flags);
ok(index < 5, "Got index %u.\n", index);
/* Don't reference the surface here, to mimic How to Survive. */
- *surface = allocator_surfaces[index];
+ *surface = presenter->surfaces[index];
return S_OK;
}
@@ -2931,10 +2960,8 @@ static const IVMRSurfaceAllocator9Vtbl allocator_vtbl =
allocator_AdviseNotify,
};
-static IVMRSurfaceAllocator9 allocator_iface = {&allocator_vtbl};
-static IVMRImagePresenter9 presenter_iface = {&presenter_vtbl};
-
-static void test_renderless_present(IFilterGraph2 *graph, IMemInputPin *input)
+static void test_renderless_present(struct presenter *presenter,
+ IFilterGraph2 *graph, IMemInputPin *input)
{
IMediaControl *control;
OAFilterState state;
@@ -2943,7 +2970,7 @@ static void test_renderless_present(IFilterGraph2 *graph, IMemInputPin *input)
IFilterGraph2_QueryInterface(graph, &IID_IMediaControl, (void **)&control);
- allocator_got_PresentImage = 0;
+ presenter->got_PresentImage = 0;
hr = IMediaControl_Pause(control);
ok(hr == S_FALSE, "Got hr %#x.\n", hr);
@@ -2954,13 +2981,13 @@ static void test_renderless_present(IFilterGraph2 *graph, IMemInputPin *input)
* IMediaControl::Run() from a stopped state and expects that
* IMediaControl::GetState() returns S_OK only after PresentImage() has
* been called. */
- ok(allocator_got_PresentImage == 1, "Got %u calls to PresentImage().\n", allocator_got_PresentImage);
+ ok(presenter->got_PresentImage == 1, "Got %u calls to PresentImage().\n", presenter->got_PresentImage);
hr = IMediaControl_Run(control);
ok(hr == S_OK, "Got hr %#x.\n", hr);
hr = join_thread(thread);
ok(hr == S_OK, "Got hr %#x.\n", hr);
- ok(allocator_got_PresentImage == 1, "Got %u calls to PresentImage().\n", allocator_got_PresentImage);
+ ok(presenter->got_PresentImage == 1, "Got %u calls to PresentImage().\n", presenter->got_PresentImage);
hr = IMediaControl_Stop(control);
ok(hr == S_OK, "Got hr %#x.\n", hr);
@@ -2986,6 +3013,13 @@ static void test_renderless_formats(void)
.pbFormat = (BYTE *)&vih,
};
ALLOCATOR_PROPERTIES req_props = {5, 32 * 16 * 4, 1, 0}, ret_props;
+ struct presenter presenter =
+ {
+ .IVMRSurfaceAllocator9_iface.lpVtbl = &allocator_vtbl,
+ .IVMRImagePresenter9_iface.lpVtbl = &presenter_vtbl,
+ .refcount = 1,
+ };
+ struct presenter presenter2 = presenter;
IVMRSurfaceAllocatorNotify9 *notify;
RECT rect = {0, 0, 640, 480};
struct testfilter source;
@@ -3047,10 +3081,11 @@ static void test_renderless_formats(void)
}
ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IVMRSurfaceAllocatorNotify9_AdviseSurfaceAllocator(notify, 0xabacab, &allocator_iface);
+ hr = IVMRSurfaceAllocatorNotify9_AdviseSurfaceAllocator(notify, 0xabacab,
+ &presenter.IVMRSurfaceAllocator9_iface);
ok(hr == S_OK, "Got hr %#x.\n", hr);
- allocator_notify = notify;
+ presenter.notify = notify;
testfilter_init(&source);
graph = create_graph();
@@ -3062,7 +3097,7 @@ static void test_renderless_formats(void)
for (i = 0; i < ARRAY_SIZE(tests); ++i)
{
req_mt.subtype = *tests[i].subtype;
- allocator_accept_flags = tests[i].flags;
+ presenter.accept_flags = tests[i].flags;
hr = IFilterGraph2_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &req_mt);
/* Connection never fails on Native, but Wine currently creates D3D
@@ -3100,10 +3135,14 @@ static void test_renderless_formats(void)
hr = IMemAllocator_Commit(allocator);
ok(hr == S_OK, "Test %u: Got hr %#x.\n", i, hr);
- ok(allocator_format == tests[i].format, "Test %u: Got format %u (%#x).\n",
- i, allocator_format, allocator_format);
+ hr = IVMRSurfaceAllocatorNotify9_AdviseSurfaceAllocator(notify, 0xabacab,
+ &presenter2.IVMRSurfaceAllocator9_iface);
+ ok(hr == VFW_E_WRONG_STATE, "Got hr %#x.\n", hr);
+
+ ok(presenter.format == tests[i].format, "Test %u: Got format %u (%#x).\n",
+ i, presenter.format, presenter.format);
- test_renderless_present(graph, input);
+ test_renderless_present(&presenter, graph, input);
hr = IMemAllocator_Decommit(allocator);
ok(hr == S_OK, "Test %u: Got hr %#x.\n", i, hr);
@@ -3115,6 +3154,9 @@ static void test_renderless_formats(void)
ok(hr == S_OK, "Test %u: Got hr %#x.\n", i, hr);
}
+ hr = IVMRSurfaceAllocatorNotify9_AdviseSurfaceAllocator(notify, 0xabacab, &presenter2.IVMRSurfaceAllocator9_iface);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
ref = IFilterGraph2_Release(graph);
ok(!ref, "Got outstanding refcount %d.\n", ref);
IMemInputPin_Release(input);
@@ -3124,7 +3166,8 @@ out:
IVMRSurfaceAllocatorNotify9_Release(notify);
ref = IBaseFilter_Release(filter);
ok(!ref, "Got outstanding refcount %d.\n", ref);
- ok(allocator_refcount == 1, "Got outstanding refcount %d.\n", allocator_refcount);
+ ok(presenter.refcount == 1, "Got outstanding refcount %d.\n", presenter.refcount);
+ ok(presenter2.refcount == 1, "Got outstanding refcount %d.\n", presenter2.refcount);
ref = IDirect3DDevice9_Release(device);
ok(!ref, "Got outstanding refcount %d.\n", ref);
DestroyWindow(window);
@@ -3279,25 +3322,30 @@ static void test_clipping_window(void)
static void test_surface_allocator_notify_refcount(void)
{
+ struct presenter presenter =
+ {
+ .IVMRSurfaceAllocator9_iface.lpVtbl = &allocator_vtbl,
+ .IVMRImagePresenter9_iface.lpVtbl = &presenter_vtbl,
+ .refcount = 1,
+ };
IBaseFilter *filter = create_vmr9(VMR9Mode_Renderless);
IVMRSurfaceAllocatorNotify9 *notify;
HRESULT hr;
ULONG ref;
- allocator_got_TerminateDevice = 0;
-
set_mixing_mode(filter, 2);
IBaseFilter_QueryInterface(filter, &IID_IVMRSurfaceAllocatorNotify9, (void **)¬ify);
- hr = IVMRSurfaceAllocatorNotify9_AdviseSurfaceAllocator(notify, 0xabacab, &allocator_iface);
+ hr = IVMRSurfaceAllocatorNotify9_AdviseSurfaceAllocator(notify, 0xabacab,
+ &presenter.IVMRSurfaceAllocator9_iface);
ok(hr == S_OK, "Got hr %#x.\n", hr);
ref = IBaseFilter_Release(filter);
ok(!ref, "Got outstanding refcount %d.\n", ref);
- ok(allocator_got_TerminateDevice == 1, "Got %u calls to TerminateDevice().\n",
- allocator_got_TerminateDevice);
- ok(allocator_refcount == 1, "Got outstanding refcount %d.\n", allocator_refcount);
+ ok(presenter.got_TerminateDevice == 1, "Got %u calls to TerminateDevice().\n",
+ presenter.got_TerminateDevice);
+ ok(presenter.refcount == 1, "Got outstanding refcount %d.\n", presenter.refcount);
ref = IVMRSurfaceAllocatorNotify9_Release(notify);
ok(!ref, "Got outstanding refcount %d.\n", ref);
diff --git a/dlls/quartz/vmr9.c b/dlls/quartz/vmr9.c
index 5557a98b29..3b42dd0ed5 100644
--- a/dlls/quartz/vmr9.c
+++ b/dlls/quartz/vmr9.c
@@ -1985,20 +1985,37 @@ static HRESULT WINAPI VMR9SurfaceAllocatorNotify_AdviseSurfaceAllocator(
IVMRSurfaceAllocatorNotify9 *iface, DWORD_PTR cookie, IVMRSurfaceAllocator9 *allocator)
{
struct quartz_vmr *filter = impl_from_IVMRSurfaceAllocatorNotify9(iface);
+ IVMRImagePresenter9 *presenter;
TRACE("filter %p, cookie %#Ix, allocator %p.\n", filter, cookie, allocator);
+ EnterCriticalSection(&filter->renderer.filter.csFilter);
+
filter->cookie = cookie;
- if (filter->presenter)
+ if (filter->renderer.sink.pin.peer)
+ {
+ LeaveCriticalSection(&filter->renderer.filter.csFilter);
+ WARN("Attempt to set allocator while connected; returning VFW_E_WRONG_STATE.\n");
return VFW_E_WRONG_STATE;
+ }
- if (FAILED(IVMRSurfaceAllocator9_QueryInterface(allocator, &IID_IVMRImagePresenter9, (void **)&filter->presenter)))
+ if (FAILED(IVMRSurfaceAllocator9_QueryInterface(allocator, &IID_IVMRImagePresenter9, (void **)&presenter)))
+ {
+ LeaveCriticalSection(&filter->renderer.filter.csFilter);
return E_NOINTERFACE;
+ }
+ if (filter->allocator)
+ {
+ IVMRImagePresenter9_Release(filter->presenter);
+ IVMRSurfaceAllocator9_Release(filter->allocator);
+ }
filter->allocator = allocator;
+ filter->presenter = presenter;
IVMRSurfaceAllocator9_AddRef(allocator);
+ LeaveCriticalSection(&filter->renderer.filter.csFilter);
return S_OK;
}
--
2.27.0
More information about the wine-devel
mailing list