From: Zebediah Figura zfigura@codeweavers.com
--- dlls/quartz/Makefile.in | 1 + dlls/quartz/main.c | 1 + dlls/quartz/quartz_private.h | 1 + dlls/quartz/quartz_strmif.idl | 6 ++ dlls/quartz/vmr7_presenter.c | 123 ++++++++++++++++++++++++++++++++++ 5 files changed, 132 insertions(+) create mode 100644 dlls/quartz/vmr7_presenter.c
diff --git a/dlls/quartz/Makefile.in b/dlls/quartz/Makefile.in index 90955e73cb4..0670ba95b48 100644 --- a/dlls/quartz/Makefile.in +++ b/dlls/quartz/Makefile.in @@ -19,6 +19,7 @@ SOURCES = \ systemclock.c \ videorenderer.c \ vmr7.c \ + vmr7_presenter.c \ vmr9.c \ window.c
diff --git a/dlls/quartz/main.c b/dlls/quartz/main.c index fc6f39e3859..f52884afb34 100644 --- a/dlls/quartz/main.c +++ b/dlls/quartz/main.c @@ -59,6 +59,7 @@ struct object_creation_info static const struct object_creation_info object_creation[] = { { &CLSID_ACMWrapper, acm_wrapper_create }, + { &CLSID_AllocPresenter, vmr7_presenter_create }, { &CLSID_AsyncReader, async_reader_create }, { &CLSID_AudioRender, dsound_render_create }, { &CLSID_AVIDec, avi_dec_create }, diff --git a/dlls/quartz/quartz_private.h b/dlls/quartz/quartz_private.h index 58d8bb775a9..8a761e540b9 100644 --- a/dlls/quartz/quartz_private.h +++ b/dlls/quartz/quartz_private.h @@ -81,6 +81,7 @@ HRESULT system_clock_create(IUnknown *outer, IUnknown **out); HRESULT seeking_passthrough_create(IUnknown *outer, IUnknown **out); HRESULT video_renderer_create(IUnknown *outer, IUnknown **out); HRESULT video_renderer_default_create(IUnknown *outer, IUnknown **out); +HRESULT vmr7_presenter_create(IUnknown *outer, IUnknown **out); HRESULT vmr7_create(IUnknown *outer, IUnknown **out); HRESULT vmr9_create(IUnknown *outer, IUnknown **out);
diff --git a/dlls/quartz/quartz_strmif.idl b/dlls/quartz/quartz_strmif.idl index b0b43ee2f33..8e2506c80a4 100644 --- a/dlls/quartz/quartz_strmif.idl +++ b/dlls/quartz/quartz_strmif.idl @@ -139,3 +139,9 @@ coclass VideoMixingRenderer { interface IBaseFilter; } uuid(51b4abf3-748f-4e3b-a276-c828330e926a) ] coclass VideoMixingRenderer9 { interface IBaseFilter; } + +[ + threading(both), + uuid(99d54f63-1a69-41ae-aa4d-c976eb3f0713) +] +coclass AllocPresenter {} diff --git a/dlls/quartz/vmr7_presenter.c b/dlls/quartz/vmr7_presenter.c new file mode 100644 index 00000000000..952cb879197 --- /dev/null +++ b/dlls/quartz/vmr7_presenter.c @@ -0,0 +1,123 @@ +/* + * Default allocator-presenter for the VMR7 + * + * Copyright 2023 Zebediah Figura for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "quartz_private.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(quartz); + +struct vmr7_presenter +{ + IVMRImagePresenter IVMRImagePresenter_iface; + LONG refcount; +}; + +static struct vmr7_presenter *impl_from_IVMRImagePresenter(IVMRImagePresenter *iface) +{ + return CONTAINING_RECORD(iface, struct vmr7_presenter, IVMRImagePresenter_iface); +} + +static HRESULT WINAPI image_presenter_QueryInterface(IVMRImagePresenter *iface, REFIID iid, void **out) +{ + struct vmr7_presenter *presenter = impl_from_IVMRImagePresenter(iface); + + TRACE("presenter %p, iid %s, out %p.\n", presenter, debugstr_guid(iid), out); + + if (IsEqualGUID(iid, &IID_IUnknown) || IsEqualGUID(iid, &IID_IVMRImagePresenter)) + *out = iface; + else + { + *out = NULL; + WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown *)*out); + return S_OK; +} + +static ULONG WINAPI image_presenter_AddRef(IVMRImagePresenter *iface) +{ + struct vmr7_presenter *presenter = impl_from_IVMRImagePresenter(iface); + ULONG refcount = InterlockedIncrement(&presenter->refcount); + + TRACE("%p increasing refcount to %lu.\n", presenter, refcount); + return refcount; +} + +static ULONG WINAPI image_presenter_Release(IVMRImagePresenter *iface) +{ + struct vmr7_presenter *presenter = impl_from_IVMRImagePresenter(iface); + ULONG refcount = InterlockedDecrement(&presenter->refcount); + + TRACE("%p decreasing refcount to %lu.\n", presenter, refcount); + if (!refcount) + free(presenter); + return refcount; +} + +static HRESULT WINAPI image_presenter_StartPresenting(IVMRImagePresenter *iface, DWORD_PTR cookie) +{ + FIXME("iface %p, cookie %#Ix, stub!\n", iface, cookie); + return E_NOTIMPL; +} + +static HRESULT WINAPI image_presenter_StopPresenting(IVMRImagePresenter *iface, DWORD_PTR cookie) +{ + FIXME("iface %p, cookie %#Ix, stub!\n", iface, cookie); + return E_NOTIMPL; +} + +static HRESULT WINAPI image_presenter_PresentImage(IVMRImagePresenter *iface, + DWORD_PTR cookie, VMRPRESENTATIONINFO *info) +{ + FIXME("iface %p, cookie %#Ix, info %p, stub!\n", iface, cookie, info); + return E_NOTIMPL; +} + +static const IVMRImagePresenterVtbl image_presenter_vtbl = +{ + image_presenter_QueryInterface, + image_presenter_AddRef, + image_presenter_Release, + image_presenter_StartPresenting, + image_presenter_StopPresenting, + image_presenter_PresentImage, +}; + +HRESULT vmr7_presenter_create(IUnknown *outer, IUnknown **out) +{ + struct vmr7_presenter *object; + + TRACE("outer %p, out %p.\n", outer, out); + + if (outer) + FIXME("Ignoring outer %p.\n", outer); + + if (!(object = calloc(1, sizeof(*object)))) + return E_OUTOFMEMORY; + object->IVMRImagePresenter_iface.lpVtbl = &image_presenter_vtbl; + object->refcount = 1; + + TRACE("Created VMR7 default presenter %p.\n", object); + *out = (IUnknown *)&object->IVMRSurfaceAllocator_iface; + return S_OK; +}
From: Zebediah Figura zfigura@codeweavers.com
--- dlls/quartz/vmr7_presenter.c | 68 ++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+)
diff --git a/dlls/quartz/vmr7_presenter.c b/dlls/quartz/vmr7_presenter.c index 952cb879197..ddb402456f7 100644 --- a/dlls/quartz/vmr7_presenter.c +++ b/dlls/quartz/vmr7_presenter.c @@ -27,6 +27,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(quartz); struct vmr7_presenter { IVMRImagePresenter IVMRImagePresenter_iface; + IVMRSurfaceAllocator IVMRSurfaceAllocator_iface; LONG refcount; };
@@ -43,6 +44,8 @@ static HRESULT WINAPI image_presenter_QueryInterface(IVMRImagePresenter *iface,
if (IsEqualGUID(iid, &IID_IUnknown) || IsEqualGUID(iid, &IID_IVMRImagePresenter)) *out = iface; + else if (IsEqualGUID(iid, &IID_IVMRSurfaceAllocator)) + *out = &presenter->IVMRSurfaceAllocator_iface; else { *out = NULL; @@ -103,6 +106,70 @@ static const IVMRImagePresenterVtbl image_presenter_vtbl = image_presenter_PresentImage, };
+static struct vmr7_presenter *impl_from_IVMRSurfaceAllocator(IVMRSurfaceAllocator *iface) +{ + return CONTAINING_RECORD(iface, struct vmr7_presenter, IVMRSurfaceAllocator_iface); +} + +static HRESULT WINAPI surface_allocator_QueryInterface(IVMRSurfaceAllocator *iface, REFIID iid, void **out) +{ + struct vmr7_presenter *presenter = impl_from_IVMRSurfaceAllocator(iface); + + return IVMRImagePresenter_QueryInterface(&presenter->IVMRImagePresenter_iface, iid, out); +} + +static ULONG WINAPI surface_allocator_AddRef(IVMRSurfaceAllocator *iface) +{ + struct vmr7_presenter *presenter = impl_from_IVMRSurfaceAllocator(iface); + + return IVMRImagePresenter_AddRef(&presenter->IVMRImagePresenter_iface); +} + +static ULONG WINAPI surface_allocator_Release(IVMRSurfaceAllocator *iface) +{ + struct vmr7_presenter *presenter = impl_from_IVMRSurfaceAllocator(iface); + + return IVMRImagePresenter_Release(&presenter->IVMRImagePresenter_iface); +} + +static HRESULT WINAPI surface_allocator_AllocateSurface(IVMRSurfaceAllocator *iface, + DWORD_PTR id, VMRALLOCATIONINFO *info, DWORD *count, IDirectDrawSurface7 **surfaces) +{ + FIXME("iface %p, id %#Ix, info %p, count %p, surfaces %p, stub!\n", iface, id, info, count, surfaces); + return E_NOTIMPL; +} + +static HRESULT WINAPI surface_allocator_FreeSurface(IVMRSurfaceAllocator *iface, DWORD_PTR id) +{ + FIXME("iface %p, id %#Ix, stub!\n", iface, id); + return E_NOTIMPL; +} + +static HRESULT WINAPI surface_allocator_PrepareSurface(IVMRSurfaceAllocator *iface, + DWORD_PTR id, IDirectDrawSurface7 *surface, DWORD flags) +{ + FIXME("iface %p, id %#Ix, surface %p, flags %#lx, stub!\n", iface, id, surface, flags); + return E_NOTIMPL; +} + +static HRESULT WINAPI surface_allocator_AdviseNotify(IVMRSurfaceAllocator *iface, + IVMRSurfaceAllocatorNotify *notify) +{ + FIXME("iface %p, notify %p, stub!\n", iface, notify); + return S_OK; +} + +static const IVMRSurfaceAllocatorVtbl surface_allocator_vtbl = +{ + surface_allocator_QueryInterface, + surface_allocator_AddRef, + surface_allocator_Release, + surface_allocator_AllocateSurface, + surface_allocator_FreeSurface, + surface_allocator_PrepareSurface, + surface_allocator_AdviseNotify, +}; + HRESULT vmr7_presenter_create(IUnknown *outer, IUnknown **out) { struct vmr7_presenter *object; @@ -115,6 +182,7 @@ HRESULT vmr7_presenter_create(IUnknown *outer, IUnknown **out) if (!(object = calloc(1, sizeof(*object)))) return E_OUTOFMEMORY; object->IVMRImagePresenter_iface.lpVtbl = &image_presenter_vtbl; + object->IVMRSurfaceAllocator_iface.lpVtbl = &surface_allocator_vtbl; object->refcount = 1;
TRACE("Created VMR7 default presenter %p.\n", object);
From: Zebediah Figura zfigura@codeweavers.com
Rewrite needs this. --- dlls/quartz/vmr7_presenter.c | 152 +++++++++++++++++++++++++++++++++++ 1 file changed, 152 insertions(+)
diff --git a/dlls/quartz/vmr7_presenter.c b/dlls/quartz/vmr7_presenter.c index ddb402456f7..222e6db6048 100644 --- a/dlls/quartz/vmr7_presenter.c +++ b/dlls/quartz/vmr7_presenter.c @@ -28,6 +28,7 @@ struct vmr7_presenter { IVMRImagePresenter IVMRImagePresenter_iface; IVMRSurfaceAllocator IVMRSurfaceAllocator_iface; + IVMRWindowlessControl IVMRWindowlessControl_iface; LONG refcount; };
@@ -46,6 +47,8 @@ static HRESULT WINAPI image_presenter_QueryInterface(IVMRImagePresenter *iface, *out = iface; else if (IsEqualGUID(iid, &IID_IVMRSurfaceAllocator)) *out = &presenter->IVMRSurfaceAllocator_iface; + else if (IsEqualGUID(iid, &IID_IVMRWindowlessControl)) + *out = &presenter->IVMRWindowlessControl_iface; else { *out = NULL; @@ -170,6 +173,154 @@ static const IVMRSurfaceAllocatorVtbl surface_allocator_vtbl = surface_allocator_AdviseNotify, };
+static struct vmr7_presenter *impl_from_IVMRWindowlessControl(IVMRWindowlessControl *iface) +{ + return CONTAINING_RECORD(iface, struct vmr7_presenter, IVMRWindowlessControl_iface); +} + +static HRESULT WINAPI windowless_control_QueryInterface(IVMRWindowlessControl *iface, REFIID iid, void **out) +{ + struct vmr7_presenter *presenter = impl_from_IVMRWindowlessControl(iface); + + return IVMRImagePresenter_QueryInterface(&presenter->IVMRImagePresenter_iface, iid, out); +} + +static ULONG WINAPI windowless_control_AddRef(IVMRWindowlessControl *iface) +{ + struct vmr7_presenter *presenter = impl_from_IVMRWindowlessControl(iface); + + return IVMRImagePresenter_AddRef(&presenter->IVMRImagePresenter_iface); +} + +static ULONG WINAPI windowless_control_Release(IVMRWindowlessControl *iface) +{ + struct vmr7_presenter *presenter = impl_from_IVMRWindowlessControl(iface); + + return IVMRImagePresenter_Release(&presenter->IVMRImagePresenter_iface); +} + +static HRESULT WINAPI windowless_control_GetNativeVideoSize(IVMRWindowlessControl *iface, + LONG *width, LONG *height, LONG *aspect_width, LONG *aspect_height) +{ + FIXME("iface %p, width %p, height %p, aspect_width %p, aspect_height %p.\n", + iface, width, height, aspect_width, aspect_height); + return E_NOTIMPL; +} + +static HRESULT WINAPI windowless_control_GetMinIdealVideoSize( + IVMRWindowlessControl *iface, LONG *width, LONG *height) +{ + FIXME("iface %p, width %p, height %p, stub!\n", iface, width, height); + return E_NOTIMPL; +} + +static HRESULT WINAPI windowless_control_GetMaxIdealVideoSize( + IVMRWindowlessControl *iface, LONG *width, LONG *height) +{ + FIXME("iface %p, width %p, height %p, stub!\n", iface, width, height); + return E_NOTIMPL; +} + +static HRESULT WINAPI windowless_control_SetVideoPosition( + IVMRWindowlessControl *iface, const RECT *source, const RECT *dest) +{ + FIXME("iface %p, source %s, dest %s, stub!.\n", iface, wine_dbgstr_rect(source), wine_dbgstr_rect(dest)); + return E_NOTIMPL; +} + +static HRESULT WINAPI windowless_control_GetVideoPosition( + IVMRWindowlessControl *iface, RECT *source, RECT *dest) +{ + FIXME("iface %p, source %p, dest %p.\n", iface, source, dest); + return E_NOTIMPL; +} + +static HRESULT WINAPI windowless_control_GetAspectRatioMode( + IVMRWindowlessControl *iface, DWORD *mode) +{ + FIXME("iface %p, mode %p, stub!\n", iface, mode); + return E_NOTIMPL; +} + +static HRESULT WINAPI windowless_control_SetAspectRatioMode( + IVMRWindowlessControl *iface, DWORD mode) +{ + FIXME("iface %p, mode %#lx, stub!\n", iface, mode); + return E_NOTIMPL; +} + +static HRESULT WINAPI windowless_control_SetVideoClippingWindow( + IVMRWindowlessControl *iface, HWND window) +{ + FIXME("iface %p, window %p, stub!.\n", iface, window); + return E_NOTIMPL; +} + +static HRESULT WINAPI windowless_control_RepaintVideo( + IVMRWindowlessControl *iface, HWND window, HDC dc) +{ + FIXME("iface %p, window %p, dc %p, stub!\n", iface, window, dc); + return E_NOTIMPL; +} + +static HRESULT WINAPI windowless_control_DisplayModeChanged(IVMRWindowlessControl *iface) +{ + FIXME("iface %p, stub!\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI windowless_control_GetCurrentImage(IVMRWindowlessControl *iface, BYTE **image) +{ + FIXME("iface %p, image %p, stub!\n", iface, image); + return E_NOTIMPL; +} + +static HRESULT WINAPI windowless_control_SetBorderColor(IVMRWindowlessControl *iface, COLORREF color) +{ + FIXME("iface %p, color %#08lx, stub!\n", iface, color); + return E_NOTIMPL; +} + +static HRESULT WINAPI windowless_control_GetBorderColor(IVMRWindowlessControl *iface, COLORREF *color) +{ + FIXME("iface %p, color %p, stub!\n", iface, color); + return E_NOTIMPL; +} + +static HRESULT WINAPI windowless_control_SetColorKey(IVMRWindowlessControl *iface, COLORREF color) +{ + FIXME("iface %p, color %#08lx, stub!\n", iface, color); + return E_NOTIMPL; +} + +static HRESULT WINAPI windowless_control_GetColorKey(IVMRWindowlessControl *iface, COLORREF *color) +{ + FIXME("iface %p, color %p, stub!\n", iface, color); + return E_NOTIMPL; +} + +static const IVMRWindowlessControlVtbl windowless_control_vtbl = +{ + windowless_control_QueryInterface, + windowless_control_AddRef, + windowless_control_Release, + windowless_control_GetNativeVideoSize, + windowless_control_GetMinIdealVideoSize, + windowless_control_GetMaxIdealVideoSize, + windowless_control_SetVideoPosition, + windowless_control_GetVideoPosition, + windowless_control_GetAspectRatioMode, + windowless_control_SetAspectRatioMode, + windowless_control_SetVideoClippingWindow, + windowless_control_RepaintVideo, + windowless_control_DisplayModeChanged, + windowless_control_GetCurrentImage, + windowless_control_SetBorderColor, + windowless_control_GetBorderColor, + windowless_control_SetColorKey, + windowless_control_GetColorKey, +}; + HRESULT vmr7_presenter_create(IUnknown *outer, IUnknown **out) { struct vmr7_presenter *object; @@ -183,6 +334,7 @@ HRESULT vmr7_presenter_create(IUnknown *outer, IUnknown **out) return E_OUTOFMEMORY; object->IVMRImagePresenter_iface.lpVtbl = &image_presenter_vtbl; object->IVMRSurfaceAllocator_iface.lpVtbl = &surface_allocator_vtbl; + object->IVMRWindowlessControl_iface.lpVtbl = &windowless_control_vtbl; object->refcount = 1;
TRACE("Created VMR7 default presenter %p.\n", object);
From: Zebediah Figura zfigura@codeweavers.com
--- dlls/quartz/Makefile.in | 2 +- dlls/quartz/tests/Makefile.in | 2 +- dlls/quartz/tests/vmr7.c | 173 ++++++++++++++++++++++++++++++++++ dlls/quartz/vmr7_presenter.c | 79 +++++++++++++++- 4 files changed, 249 insertions(+), 7 deletions(-)
diff --git a/dlls/quartz/Makefile.in b/dlls/quartz/Makefile.in index 0670ba95b48..a1859dd58a5 100644 --- a/dlls/quartz/Makefile.in +++ b/dlls/quartz/Makefile.in @@ -1,6 +1,6 @@ MODULE = quartz.dll IMPORTLIB = quartz -IMPORTS = strmiids dxguid strmbase uuid dsound msacm32 msvfw32 ole32 oleaut32 rpcrt4 user32 gdi32 advapi32 winmm +IMPORTS = strmiids dxguid strmbase uuid ddraw dsound msacm32 msvfw32 ole32 oleaut32 rpcrt4 user32 gdi32 advapi32 winmm
SOURCES = \ acmwrapper.c \ diff --git a/dlls/quartz/tests/Makefile.in b/dlls/quartz/tests/Makefile.in index 56a98d138c7..c3b96272fbf 100644 --- a/dlls/quartz/tests/Makefile.in +++ b/dlls/quartz/tests/Makefile.in @@ -1,5 +1,5 @@ TESTDLL = quartz.dll -IMPORTS = strmbase advapi32 d3d9 dsound msdmo msvfw32 ole32 oleaut32 user32 uuid winmm +IMPORTS = strmbase advapi32 d3d9 ddraw dsound msdmo msvfw32 ole32 oleaut32 user32 uuid winmm
SOURCES = \ acmwrapper.c \ diff --git a/dlls/quartz/tests/vmr7.c b/dlls/quartz/tests/vmr7.c index 50e3da462d2..7bdb1e8fa7f 100644 --- a/dlls/quartz/tests/vmr7.c +++ b/dlls/quartz/tests/vmr7.c @@ -3153,6 +3153,178 @@ static void test_unconnected_eos(void) ok(!ref, "Got outstanding refcount %ld.\n", ref); }
+static void test_default_presenter_allocate(void) +{ + IDirectDrawSurface7 *frontbuffer, *backbuffer, *backbuffer2, *backbuffer3; + IDirectDraw7 *ddraw, *prev_ddraw = NULL; + IVMRSurfaceAllocator *allocator; + VMRALLOCATIONINFO info; + DDSURFACEDESC2 desc; + HRESULT hr; + LONG ref; + + BITMAPINFOHEADER bitmap_header = + { + .biSize = sizeof(BITMAPINFOHEADER), + .biWidth = 32, + .biHeight = 16, + .biCompression = mmioFOURCC('Y','U','Y','2'), + .biBitCount = 16, + .biPlanes = 1, + }; + + static const struct + { + WORD depth; + DWORD compression; + DDPIXELFORMAT format; + } + tests[] = + { + {32, BI_RGB}, + {12, mmioFOURCC('N','V','1','2')}, + {12, mmioFOURCC('Y','V','1','2')}, + {16, mmioFOURCC('U','Y','V','Y')}, + {16, mmioFOURCC('Y','U','Y','2')}, + }; + + hr = CoCreateInstance(&CLSID_AllocPresenter, NULL, CLSCTX_INPROC_SERVER, + &IID_IVMRSurfaceAllocator, (void **)&allocator); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IVMRSurfaceAllocator_FreeSurface(allocator, 0); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + info.dwFlags = AMAP_DIRECTED_FLIP | AMAP_ALLOW_SYSMEM; + info.dwMinBuffers = 2; + info.dwMaxBuffers = 2; + info.dwInterlaceFlags = 0; + info.szNativeSize.cx = info.szAspectRatio.cx = 640; + info.szNativeSize.cy = info.szAspectRatio.cy = 480; + info.lpHdr = &bitmap_header; + info.lpPixFmt = NULL; + + for (unsigned int i = 0; i < ARRAY_SIZE(tests); ++i) + { + DWORD count = 2; + + winetest_push_context("Compression %#lx, depth %u", tests[i].compression, tests[i].depth); + + bitmap_header.biBitCount = tests[i].depth; + bitmap_header.biCompression = tests[i].compression; + + hr = IVMRSurfaceAllocator_AllocateSurface(allocator, 0, &info, &count, &frontbuffer); + if (hr == VFW_E_DDRAW_CAPS_NOT_SUITABLE) + { + skip("Format is not supported.\n"); + winetest_pop_context(); + continue; + } + ok(hr == S_OK, "Got hr %#lx.\n", hr); + ok(count == 3, "Got count %lu.\n", count); + + memset(&desc, 0, sizeof(desc)); + desc.dwSize = sizeof(desc); + hr = IDirectDrawSurface7_GetSurfaceDesc(frontbuffer, &desc); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + todo_wine ok(desc.dwFlags == (DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH | DDSD_PIXELFORMAT), + "Got flags %#lx.\n", desc.dwFlags); + todo_wine ok(desc.ddsCaps.dwCaps == (DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN + | DDSCAPS_FRONTBUFFER | DDSCAPS_FLIP), "Got caps %#lx.\n", desc.ddsCaps.dwCaps); + ok(!desc.ddsCaps.dwCaps2, "Got caps2 %#lx.\n", desc.ddsCaps.dwCaps2); + ok(!desc.ddsCaps.dwCaps3, "Got caps2 %#lx.\n", desc.ddsCaps.dwCaps3); + ok(!desc.ddsCaps.dwCaps4, "Got caps2 %#lx.\n", desc.ddsCaps.dwCaps4); + ok(desc.dwWidth == 32, "Got width %lu.\n", desc.dwWidth); + ok(desc.dwHeight == 16, "Got height %lu.\n", desc.dwHeight); + todo_wine_if (tests[i].depth == 12) + ok(desc.lPitch == 32 * tests[i].depth / 8, "Got pitch %lu.\n", desc.lPitch); + ok(desc.ddpfPixelFormat.dwSize == sizeof(desc.ddpfPixelFormat), + "Got size %lu.\n", desc.ddpfPixelFormat.dwSize); + if (tests[i].compression) + { + ok(desc.ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Got flags %#lx.\n", desc.ddpfPixelFormat.dwFlags); + ok(desc.ddpfPixelFormat.dwFourCC == bitmap_header.biCompression, + "Got fourcc %08lx.\n", desc.ddpfPixelFormat.dwFourCC); + } + else + { + ok(desc.ddpfPixelFormat.dwFlags == DDPF_RGB, "Got flags %#lx.\n", desc.ddpfPixelFormat.dwFlags); + ok(desc.ddpfPixelFormat.dwRGBBitCount == 32, "Got depth %lu.\n", desc.ddpfPixelFormat.dwRGBBitCount); + ok(desc.ddpfPixelFormat.dwRBitMask == 0x00ff0000, "Got red mask %#lx.\n", desc.ddpfPixelFormat.dwRBitMask); + ok(desc.ddpfPixelFormat.dwGBitMask == 0x0000ff00, "Got green mask %#lx.\n", desc.ddpfPixelFormat.dwGBitMask); + ok(desc.ddpfPixelFormat.dwBBitMask == 0x000000ff, "Got blue mask %#lx.\n", desc.ddpfPixelFormat.dwBBitMask); + } + + desc.ddsCaps.dwCaps = DDSCAPS_FLIP; + hr = IDirectDrawSurface7_GetAttachedSurface(frontbuffer, &desc.ddsCaps, &backbuffer); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + memset(&desc, 0, sizeof(desc)); + desc.dwSize = sizeof(desc); + hr = IDirectDrawSurface7_GetSurfaceDesc(backbuffer, &desc); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + todo_wine ok(desc.dwFlags == (DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH | DDSD_PIXELFORMAT), + "Got flags %#lx.\n", desc.dwFlags); + todo_wine ok(desc.ddsCaps.dwCaps == (DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN + | DDSCAPS_BACKBUFFER | DDSCAPS_FLIP), "Got caps %#lx.\n", desc.ddsCaps.dwCaps); + + desc.ddsCaps.dwCaps = DDSCAPS_FLIP; + hr = IDirectDrawSurface7_GetAttachedSurface(backbuffer, &desc.ddsCaps, &backbuffer2); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + memset(&desc, 0, sizeof(desc)); + desc.dwSize = sizeof(desc); + hr = IDirectDrawSurface7_GetSurfaceDesc(backbuffer2, &desc); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + todo_wine ok(desc.dwFlags == (DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH | DDSD_PIXELFORMAT), + "Got flags %#lx.\n", desc.dwFlags); + todo_wine ok(desc.ddsCaps.dwCaps == (DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN + | DDSCAPS_FLIP), "Got caps %#lx.\n", desc.ddsCaps.dwCaps); + + desc.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY; + hr = IDirectDrawSurface7_GetAttachedSurface(backbuffer2, &desc.ddsCaps, &backbuffer3); + todo_wine_if (tests[i].compression) ok(hr == S_OK, "Got hr %#lx.\n", hr); + if (hr == S_OK) + { + ok(backbuffer3 == frontbuffer, "Expected only 2 backbuffers.\n"); + IDirectDrawSurface7_Release(backbuffer3); + } + + IDirectDrawSurface7_Release(backbuffer2); + IDirectDrawSurface7_Release(backbuffer); + + hr = IDirectDrawSurface7_GetDDInterface(frontbuffer, (void **)&ddraw); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + if (prev_ddraw) + { + ok(ddraw == prev_ddraw, "Expected the same ddraw object.\n"); + IDirectDraw7_Release(ddraw); + } + else + { + prev_ddraw = ddraw; + } + + /* AllocateSurface does *not* give the application a reference to the + * surface. */ + + IDirectDrawSurface7_AddRef(frontbuffer); + + hr = IVMRSurfaceAllocator_FreeSurface(allocator, 0); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + ref = IDirectDrawSurface7_Release(frontbuffer); + ok(!ref, "Got outstanding refcount %ld.\n", ref); + + winetest_pop_context(); + } + + ref = IVMRSurfaceAllocator_Release(allocator); + ok(!ref, "Got outstanding refcount %ld.\n", ref); + ref = IDirectDraw7_Release(prev_ddraw); + ok(!ref, "Got outstanding refcount %ld.\n", ref); +} + START_TEST(vmr7) { CoInitialize(NULL); @@ -3172,6 +3344,7 @@ START_TEST(vmr7) test_basic_video(); test_windowless_size(); test_unconnected_eos(); + test_default_presenter_allocate();
CoUninitialize(); } diff --git a/dlls/quartz/vmr7_presenter.c b/dlls/quartz/vmr7_presenter.c index 222e6db6048..78d97bd5e10 100644 --- a/dlls/quartz/vmr7_presenter.c +++ b/dlls/quartz/vmr7_presenter.c @@ -30,6 +30,9 @@ struct vmr7_presenter IVMRSurfaceAllocator IVMRSurfaceAllocator_iface; IVMRWindowlessControl IVMRWindowlessControl_iface; LONG refcount; + + IDirectDraw7 *ddraw; + IDirectDrawSurface7 *frontbuffer; };
static struct vmr7_presenter *impl_from_IVMRImagePresenter(IVMRImagePresenter *iface) @@ -76,7 +79,12 @@ static ULONG WINAPI image_presenter_Release(IVMRImagePresenter *iface)
TRACE("%p decreasing refcount to %lu.\n", presenter, refcount); if (!refcount) + { + if (presenter->frontbuffer) + IDirectDrawSurface7_Release(presenter->frontbuffer); + IDirectDraw7_Release(presenter->ddraw); free(presenter); + } return refcount; }
@@ -136,16 +144,66 @@ static ULONG WINAPI surface_allocator_Release(IVMRSurfaceAllocator *iface) }
static HRESULT WINAPI surface_allocator_AllocateSurface(IVMRSurfaceAllocator *iface, - DWORD_PTR id, VMRALLOCATIONINFO *info, DWORD *count, IDirectDrawSurface7 **surfaces) + DWORD_PTR id, VMRALLOCATIONINFO *info, DWORD *count, IDirectDrawSurface7 **surface) { - FIXME("iface %p, id %#Ix, info %p, count %p, surfaces %p, stub!\n", iface, id, info, count, surfaces); - return E_NOTIMPL; + struct vmr7_presenter *presenter = impl_from_IVMRSurfaceAllocator(iface); + DDSURFACEDESC2 surface_desc = {.dwSize = sizeof(surface_desc)}; + HRESULT hr; + + TRACE("presenter %p, id %#Ix, info %p, count %p, surface %p.\n", presenter, id, info, count, surface); + + surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS | DDSD_BACKBUFFERCOUNT; + surface_desc.dwWidth = info->lpHdr->biWidth; + surface_desc.dwHeight = info->lpHdr->biHeight; + surface_desc.ddpfPixelFormat.dwSize = sizeof(surface_desc.ddpfPixelFormat); + surface_desc.ddsCaps.dwCaps = DDSCAPS_FLIP | DDSCAPS_COMPLEX | DDSCAPS_OFFSCREENPLAIN; + surface_desc.dwBackBufferCount = *count; + + if (info->lpHdr->biCompression == BI_RGB) + { + if (info->lpHdr->biBitCount != 32) + { + FIXME("Unhandled bit depth %u.\n", info->lpHdr->biBitCount); + return E_NOTIMPL; + } + + surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB; + surface_desc.ddpfPixelFormat.dwRGBBitCount = 32; + surface_desc.ddpfPixelFormat.dwRBitMask = 0x00ff0000; + surface_desc.ddpfPixelFormat.dwGBitMask = 0x0000ff00; + surface_desc.ddpfPixelFormat.dwBBitMask = 0x000000ff; + } + else + { + surface_desc.ddpfPixelFormat.dwFlags = DDPF_FOURCC; + surface_desc.ddpfPixelFormat.dwFourCC = info->lpHdr->biCompression; + } + + if (FAILED(hr = IDirectDraw7_CreateSurface(presenter->ddraw, + &surface_desc, &presenter->frontbuffer, NULL))) + { + WARN("Failed to create surface, hr %#lx.\n", hr); + return hr; + } + *surface = presenter->frontbuffer; + ++*count; + return S_OK; }
static HRESULT WINAPI surface_allocator_FreeSurface(IVMRSurfaceAllocator *iface, DWORD_PTR id) { - FIXME("iface %p, id %#Ix, stub!\n", iface, id); - return E_NOTIMPL; + struct vmr7_presenter *presenter = impl_from_IVMRSurfaceAllocator(iface); + DDSURFACEDESC2 surface_desc = {.dwSize = sizeof(surface_desc)}; + + TRACE("presenter %p, id %#Ix.\n", presenter, id); + + if (presenter->frontbuffer) + { + IDirectDrawSurface7_Release(presenter->frontbuffer); + presenter->frontbuffer = NULL; + } + + return S_OK; }
static HRESULT WINAPI surface_allocator_PrepareSurface(IVMRSurfaceAllocator *iface, @@ -324,6 +382,7 @@ static const IVMRWindowlessControlVtbl windowless_control_vtbl = HRESULT vmr7_presenter_create(IUnknown *outer, IUnknown **out) { struct vmr7_presenter *object; + HRESULT hr;
TRACE("outer %p, out %p.\n", outer, out);
@@ -337,6 +396,16 @@ HRESULT vmr7_presenter_create(IUnknown *outer, IUnknown **out) object->IVMRWindowlessControl_iface.lpVtbl = &windowless_control_vtbl; object->refcount = 1;
+ if (FAILED(hr = DirectDrawCreateEx(NULL, (void **)&object->ddraw, &IID_IDirectDraw7, NULL))) + { + ERR("Failed to create ddraw object, hr %#lx.\n", hr); + free(object); + return hr; + } + + if (FAILED(hr = IDirectDraw7_SetCooperativeLevel(object->ddraw, NULL, DDSCL_NORMAL))) + ERR("Failed to set cooperative level, hr %#lx.\n", hr); + TRACE("Created VMR7 default presenter %p.\n", object); *out = (IUnknown *)&object->IVMRSurfaceAllocator_iface; return S_OK;
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=140935
Your paranoid android.
=== w8adm (32 bit report) ===
quartz: systemclock.c:223: Test failed: Event should be signaled. systemclock.c:226: Test failed: Got hr 0.
=== w7u_2qxl (32 bit report) ===
quartz: vmr7.c:3232: Test failed: Compression 0, depth 32: Got caps 0x870. vmr7.c:3268: Test failed: Compression 0, depth 32: Got caps 0x854. vmr7.c:3281: Test failed: Compression 0, depth 32: Got caps 0x850. vmr7.c:3286: Test failed: Compression 0, depth 32: Got hr 0x887600ff.
=== w7u_adm (32 bit report) ===
quartz: vmr7.c:3232: Test failed: Compression 0, depth 32: Got caps 0x870. vmr7.c:3268: Test failed: Compression 0, depth 32: Got caps 0x854. vmr7.c:3281: Test failed: Compression 0, depth 32: Got caps 0x850. vmr7.c:3286: Test failed: Compression 0, depth 32: Got hr 0x887600ff.
=== w7u_el (32 bit report) ===
quartz: vmr7.c:3232: Test failed: Compression 0, depth 32: Got caps 0x870. vmr7.c:3268: Test failed: Compression 0, depth 32: Got caps 0x854. vmr7.c:3281: Test failed: Compression 0, depth 32: Got caps 0x850. vmr7.c:3286: Test failed: Compression 0, depth 32: Got hr 0x887600ff.
=== w7pro64 (64 bit report) ===
quartz: vmr7.c:3232: Test failed: Compression 0, depth 32: Got caps 0x870. vmr7.c:3268: Test failed: Compression 0, depth 32: Got caps 0x854. vmr7.c:3281: Test failed: Compression 0, depth 32: Got caps 0x850. vmr7.c:3286: Test failed: Compression 0, depth 32: Got hr 0x887600ff.
=== w11pro64_amd (64 bit report) ===
quartz: vmr7.c:3240: Test failed: Compression 0x3231564e, depth 12: Got pitch 256. vmr7.c:3240: Test failed: Compression 0x32315659, depth 12: Got pitch 256. vmr7.c:3240: Test failed: Compression 0x59565955, depth 16: Got pitch 256. vmr7.c:3240: Test failed: Compression 0x32595559, depth 16: Got pitch 256.