For Resident Evil 2 Classic.
These are relatively small and simple patches, but I can certainly cut at 5 or so for the first part.
From: Henri Verbeet hverbeet@locutus.nl
--- dlls/quartz/vmr7.c | 2 +- dlls/quartz/vmr7_presenter.c | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/dlls/quartz/vmr7.c b/dlls/quartz/vmr7.c index 83f8b1d62d3..4263e79d54f 100644 --- a/dlls/quartz/vmr7.c +++ b/dlls/quartz/vmr7.c @@ -255,7 +255,7 @@ static HRESULT vmr_render(struct strmbase_renderer *iface, IMediaSample *sample) copy_plane(&dst, surface_desc.lPitch / 2, surface_desc.dwHeight / 2, &src, src_pitch / 2, height / 2); copy_plane(&dst, surface_desc.lPitch / 2, surface_desc.dwHeight / 2, &src, src_pitch / 2, height / 2); } - else if (height > 0 && bitmap_header->biCompression == BI_RGB) + else if (height > 0 && (bitmap_header->biCompression == BI_RGB || bitmap_header->biCompression == BI_BITFIELDS)) { BYTE *dst = surface_desc.lpSurface; const BYTE *src = data; diff --git a/dlls/quartz/vmr7_presenter.c b/dlls/quartz/vmr7_presenter.c index c244c86236a..90a0b906610 100644 --- a/dlls/quartz/vmr7_presenter.c +++ b/dlls/quartz/vmr7_presenter.c @@ -201,6 +201,16 @@ static HRESULT WINAPI surface_allocator_AllocateSurface(IVMRSurfaceAllocator *if surface_desc.ddpfPixelFormat.dwGBitMask = 0x0000ff00; surface_desc.ddpfPixelFormat.dwBBitMask = 0x000000ff; } + else if (info->lpHdr->biCompression == BI_BITFIELDS) + { + const DWORD *mask = (DWORD *)((BITMAPINFO *)info->lpHdr)->bmiColors; + + surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB; + surface_desc.ddpfPixelFormat.dwRGBBitCount = info->lpHdr->biBitCount; + surface_desc.ddpfPixelFormat.dwRBitMask = mask[0]; + surface_desc.ddpfPixelFormat.dwGBitMask = mask[1]; + surface_desc.ddpfPixelFormat.dwBBitMask = mask[2]; + } else { surface_desc.ddpfPixelFormat.dwFlags = DDPF_FOURCC;
From: Henri Verbeet hverbeet@locutus.nl
--- dlls/quartz/vmr7_presenter.c | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/dlls/quartz/vmr7_presenter.c b/dlls/quartz/vmr7_presenter.c index 90a0b906610..bbfca8ec695 100644 --- a/dlls/quartz/vmr7_presenter.c +++ b/dlls/quartz/vmr7_presenter.c @@ -189,6 +189,14 @@ static HRESULT WINAPI surface_allocator_AllocateSurface(IVMRSurfaceAllocator *if
if (info->lpHdr->biCompression == BI_RGB) { + DDSURFACEDESC2 primary_desc; + + primary_desc.dwSize = sizeof(primary_desc); + if (FAILED(hr = IDirectDrawSurface7_GetSurfaceDesc(presenter->primary, &primary_desc))) + return hr; + if (info->lpHdr->biBitCount != primary_desc.ddpfPixelFormat.dwRGBBitCount) + return E_FAIL; + if (info->lpHdr->biBitCount != 32) { FIXME("Unhandled bit depth %u.\n", info->lpHdr->biBitCount);
From: Matteo Bruni mbruni@codeweavers.com
--- dlls/ddraw/ddraw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/ddraw/ddraw.c b/dlls/ddraw/ddraw.c index 3e66b134a75..fb8895f01b2 100644 --- a/dlls/ddraw/ddraw.c +++ b/dlls/ddraw/ddraw.c @@ -1794,7 +1794,7 @@ static HRESULT WINAPI ddraw7_GetFourCCCodes(IDirectDraw7 *iface, DWORD *NumCodes { WINED3DFMT_YUY2, WINED3DFMT_UYVY, WINED3DFMT_YV12, WINED3DFMT_DXT1, WINED3DFMT_DXT2, WINED3DFMT_DXT3, WINED3DFMT_DXT4, WINED3DFMT_DXT5, - WINED3DFMT_ATI2N, WINED3DFMT_NVHU, WINED3DFMT_NVHS + WINED3DFMT_ATI2N, WINED3DFMT_NVHU, WINED3DFMT_NVHS, WINED3DFMT_NV12, }; struct wined3d_display_mode mode; DWORD count = 0, i, outsize;
From: Henri Verbeet hverbeet@locutus.nl
--- dlls/quartz/vmr7_presenter.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+)
diff --git a/dlls/quartz/vmr7_presenter.c b/dlls/quartz/vmr7_presenter.c index bbfca8ec695..5b758311ba0 100644 --- a/dlls/quartz/vmr7_presenter.c +++ b/dlls/quartz/vmr7_presenter.c @@ -171,6 +171,37 @@ static ULONG WINAPI surface_allocator_Release(IVMRSurfaceAllocator *iface) return IVMRImagePresenter_Release(&presenter->IVMRImagePresenter_iface); }
+static BOOL fourcc_is_supported(IDirectDraw7 *ddraw, DWORD fourcc) +{ + DWORD *codes, count, i; + HRESULT hr; + + if (FAILED(hr = IDirectDraw7_GetFourCCCodes(ddraw, &count, NULL))) + { + ERR("Failed to get FOURCC code count, hr %#lx.\n", hr); + return FALSE; + } + + if (!count || !(codes = calloc(count, sizeof(*codes)))) + return FALSE; + + if (FAILED(hr = IDirectDraw7_GetFourCCCodes(ddraw, &count, codes))) + { + ERR("Failed to get FOURCC codes, hr %#lx.\n", hr); + free(codes); + return FALSE; + } + + for (i = 0; i < count; ++i) + { + if (codes[i] == fourcc) + break; + } + free(codes); + + return i < count; +} + static HRESULT WINAPI surface_allocator_AllocateSurface(IVMRSurfaceAllocator *iface, DWORD_PTR id, VMRALLOCATIONINFO *info, DWORD *count, IDirectDrawSurface7 **surface) { @@ -221,6 +252,9 @@ static HRESULT WINAPI surface_allocator_AllocateSurface(IVMRSurfaceAllocator *if } else { + if (!fourcc_is_supported(presenter->ddraw, info->lpHdr->biCompression)) + return VFW_E_DDRAW_CAPS_NOT_SUITABLE; + surface_desc.ddpfPixelFormat.dwFlags = DDPF_FOURCC; surface_desc.ddpfPixelFormat.dwFourCC = info->lpHdr->biCompression; }
From: Henri Verbeet hverbeet@locutus.nl
--- dlls/quartz/vmr7_presenter.c | 48 ++++++++++++++++++++++++++++++++---- 1 file changed, 43 insertions(+), 5 deletions(-)
diff --git a/dlls/quartz/vmr7_presenter.c b/dlls/quartz/vmr7_presenter.c index 5b758311ba0..72571a299cb 100644 --- a/dlls/quartz/vmr7_presenter.c +++ b/dlls/quartz/vmr7_presenter.c @@ -105,11 +105,47 @@ static HRESULT WINAPI image_presenter_StopPresenting(IVMRImagePresenter *iface, return E_NOTIMPL; }
+static BOOL get_clip_rect(struct vmr7_presenter *presenter, RECT *r) +{ + IDirectDrawClipper *clipper; + RGNDATA *data; + HRESULT hr; + DWORD size; + + if (FAILED(hr = IDirectDrawSurface7_GetClipper(presenter->primary, &clipper))) + return FALSE; + + if (FAILED(hr = IDirectDrawClipper_GetClipList(clipper, NULL, NULL, &size))) + { + IDirectDrawClipper_Release(clipper); + return FALSE; + } + + if (!(data = malloc(size))) + { + IDirectDrawClipper_Release(clipper); + return FALSE; + } + + if (FAILED(hr = IDirectDrawClipper_GetClipList(clipper, NULL, data, &size))) + { + free(data); + IDirectDrawClipper_Release(clipper); + return FALSE; + } + + *r = data->rdh.rcBound; + + free(data); + IDirectDrawClipper_Release(clipper); + + return TRUE; +} + static HRESULT WINAPI image_presenter_PresentImage(IVMRImagePresenter *iface, DWORD_PTR cookie, VMRPRESENTATIONINFO *info) { struct vmr7_presenter *presenter = impl_from_IVMRImagePresenter(iface); - POINT point; HRESULT hr; RECT rect;
@@ -125,10 +161,12 @@ static HRESULT WINAPI image_presenter_PresentImage(IVMRImagePresenter *iface, if (info->dwFlags & VMRSample_SrcDstRectsValid) FIXME("Ignoring src/dst rects.\n");
- GetClientRect(presenter->window, &rect); - point.x = point.y = 0; - ClientToScreen(presenter->window, &point); - OffsetRect(&rect, point.x, point.y); + if (!get_clip_rect(presenter, &rect)) + { + ERR("Failed to get clip rect.\n"); + return E_FAIL; + } + if (FAILED(hr = IDirectDrawSurface7_Blt(presenter->primary, &rect, info->lpSurf, NULL, DDBLT_WAIT, NULL))) ERR("Failed to blit, hr %#lx.\n", hr);
From: Henri Verbeet hverbeet@locutus.nl
--- dlls/quartz/vmr7_presenter.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+)
diff --git a/dlls/quartz/vmr7_presenter.c b/dlls/quartz/vmr7_presenter.c index 72571a299cb..6c6c2f350e1 100644 --- a/dlls/quartz/vmr7_presenter.c +++ b/dlls/quartz/vmr7_presenter.c @@ -146,6 +146,7 @@ static HRESULT WINAPI image_presenter_PresentImage(IVMRImagePresenter *iface, DWORD_PTR cookie, VMRPRESENTATIONINFO *info) { struct vmr7_presenter *presenter = impl_from_IVMRImagePresenter(iface); + SIZE dst_size; HRESULT hr; RECT rect;
@@ -167,6 +168,26 @@ static HRESULT WINAPI image_presenter_PresentImage(IVMRImagePresenter *iface, return E_FAIL; }
+ dst_size.cx = rect.right - rect.left; + dst_size.cy = rect.bottom - rect.top; + + if (info->szAspectRatio.cx * dst_size.cy > dst_size.cx * info->szAspectRatio.cy) + { + unsigned int scaled_height = info->szAspectRatio.cy * dst_size.cx / info->szAspectRatio.cx; + unsigned int offset = (dst_size.cy - scaled_height) / 2; + + rect.top += offset; + rect.bottom -= offset; + } + else if (info->szAspectRatio.cx * dst_size.cy < dst_size.cx * info->szAspectRatio.cy) + { + unsigned int scaled_width = info->szAspectRatio.cx * dst_size.cy / info->szAspectRatio.cy; + unsigned int offset = (dst_size.cx - scaled_width) / 2; + + rect.left += offset; + rect.right -= offset; + } + if (FAILED(hr = IDirectDrawSurface7_Blt(presenter->primary, &rect, info->lpSurf, NULL, DDBLT_WAIT, NULL))) ERR("Failed to blit, hr %#lx.\n", hr);
From: Matteo Bruni mbruni@codeweavers.com
--- dlls/quartz/vmr7_presenter.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/dlls/quartz/vmr7_presenter.c b/dlls/quartz/vmr7_presenter.c index 6c6c2f350e1..7e78b9c5d43 100644 --- a/dlls/quartz/vmr7_presenter.c +++ b/dlls/quartz/vmr7_presenter.c @@ -270,6 +270,12 @@ static HRESULT WINAPI surface_allocator_AllocateSurface(IVMRSurfaceAllocator *if
TRACE("presenter %p, id %#Ix, info %p, count %p, surface %p.\n", presenter, id, info, count, surface);
+ if (info->lpHdr->biSize != sizeof(*info->lpHdr)) + { + WARN("Invalid BITMAPINFOHEADER size %lu.\n", info->lpHdr->biSize); + return DDERR_INVALIDPIXELFORMAT; + } + 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;
From: Matteo Bruni mbruni@codeweavers.com
--- dlls/quartz/tests/vmr7.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
diff --git a/dlls/quartz/tests/vmr7.c b/dlls/quartz/tests/vmr7.c index 9502a994576..3d56bc09a39 100644 --- a/dlls/quartz/tests/vmr7.c +++ b/dlls/quartz/tests/vmr7.c @@ -3870,6 +3870,18 @@ static void test_default_presenter_allocate(void) ref = IDirectDrawSurface7_Release(frontbuffer); ok(!ref, "Got outstanding refcount %ld.\n", ref);
+ info.lpHdr->biCompression = BI_RGB; + frontbuffer = NULL; + hr = IVMRSurfaceAllocator_AllocateSurface(allocator, 0, &info, &count, &frontbuffer); + expect_hr = tests[i].depth == 32 ? DD_OK : E_FAIL; + ok(hr == expect_hr, "Got hr %#lx.\n", hr); + ok(!!frontbuffer == (hr == DD_OK), "Got frontbuffer %p.\n", frontbuffer); + if (frontbuffer) + { + hr = IVMRSurfaceAllocator_FreeSurface(allocator, 0); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + } + winetest_pop_context(); }
From: Matteo Bruni mbruni@codeweavers.com
--- dlls/quartz/tests/vmr7.c | 51 +++++++++++++++++++++++++++++++++------- 1 file changed, 42 insertions(+), 9 deletions(-)
diff --git a/dlls/quartz/tests/vmr7.c b/dlls/quartz/tests/vmr7.c index 3d56bc09a39..e250695596a 100644 --- a/dlls/quartz/tests/vmr7.c +++ b/dlls/quartz/tests/vmr7.c @@ -3685,11 +3685,25 @@ static void test_default_presenter_allocate(void) .biPlanes = 1, };
+ BITMAPV4HEADER bitmap_v4_header = + { + .bV4Size = sizeof(BITMAPV4HEADER), + .bV4Width = 32, + .bV4Height = 16, + .bV4Planes = 1, + .bV4BitCount = 16, + .bV4V4Compression = BI_BITFIELDS, + .bV4RedMask = 0x00ff0000, + .bV4GreenMask = 0x0000ff00, + .bV4BlueMask = 0x000000ff, + .bV4AlphaMask = 0, + }; + static const struct { WORD depth; DWORD compression; - DDPIXELFORMAT format; + BOOL v4; } tests[] = { @@ -3698,6 +3712,8 @@ static void test_default_presenter_allocate(void) {12, mmioFOURCC('Y','V','1','2')}, {16, mmioFOURCC('U','Y','V','Y')}, {16, mmioFOURCC('Y','U','Y','2')}, + {32, BI_BITFIELDS}, + {32, BI_BITFIELDS, TRUE}, };
window = CreateWindowA("static", "quartz_test", WS_OVERLAPPEDWINDOW, 0, 0, @@ -3716,7 +3732,6 @@ static void test_default_presenter_allocate(void) 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) @@ -3725,10 +3740,25 @@ static void test_default_presenter_allocate(void) HRESULT expect_hr; DWORD count = 2;
- winetest_push_context("Compression %#lx, depth %u", tests[i].compression, tests[i].depth); + winetest_push_context("Test %u: Compression %#lx, depth %u", i, tests[i].compression, tests[i].depth);
- bitmap_header.biBitCount = tests[i].depth; - bitmap_header.biCompression = tests[i].compression; + if (tests[i].v4 || tests[i].compression == BI_BITFIELDS) + { + info.lpHdr = (BITMAPINFOHEADER *)&bitmap_v4_header; + bitmap_v4_header.bV4BitCount = tests[i].depth; + bitmap_v4_header.bV4V4Compression = tests[i].compression; + if (tests[i].v4) + bitmap_v4_header.bV4Size = sizeof(bitmap_v4_header); + else + bitmap_v4_header.bV4Size = sizeof(BITMAPINFOHEADER); + } + else + { + bitmap_header.biBitCount = tests[i].depth; + bitmap_header.biCompression = tests[i].compression; + info.lpHdr = &bitmap_header; + bitmap_header.biSize = sizeof(BITMAPINFOHEADER); + }
ddraw = create_ddraw(window);
@@ -3741,7 +3771,7 @@ static void test_default_presenter_allocate(void) desc.dwWidth = desc.dwHeight = 32; desc.dwBackBufferCount = 2; desc.ddpfPixelFormat.dwSize = sizeof(desc.ddpfPixelFormat); - if (tests[i].compression) + if (tests[i].compression != BI_RGB && tests[i].compression != BI_BITFIELDS) { desc.ddpfPixelFormat.dwFlags = DDPF_FOURCC; desc.ddpfPixelFormat.dwFourCC = tests[i].compression; @@ -3769,11 +3799,14 @@ static void test_default_presenter_allocate(void)
IDirectDraw7_Release(ddraw);
+ if (tests[i].v4) + expect_hr = DDERR_INVALIDPIXELFORMAT; hr = IVMRSurfaceAllocator_AllocateSurface(allocator, 0, &info, &count, &frontbuffer); ok(hr == expect_hr, "Got hr %#lx.\n", hr); - if (hr == VFW_E_DDRAW_CAPS_NOT_SUITABLE) + if (FAILED(hr)) { - skip("Format is not supported.\n"); + if (hr == VFW_E_DDRAW_CAPS_NOT_SUITABLE) + skip("Format is not supported.\n"); winetest_pop_context(); continue; } @@ -3794,7 +3827,7 @@ static void test_default_presenter_allocate(void) ok(desc.dwHeight == 16, "Got height %lu.\n", desc.dwHeight); ok(desc.ddpfPixelFormat.dwSize == sizeof(desc.ddpfPixelFormat), "Got size %lu.\n", desc.ddpfPixelFormat.dwSize); - if (tests[i].compression) + if (tests[i].compression != BI_RGB && tests[i].compression != BI_BITFIELDS) { ok(desc.ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Got flags %#lx.\n", desc.ddpfPixelFormat.dwFlags); ok(desc.ddpfPixelFormat.dwFourCC == bitmap_header.biCompression,
This merge request was approved by Matteo Bruni.
Yeah, these aren't too complicated so I don't mind the large series. However:
* 1/9 could use tests; should be easy enough to plug into test_default_presenter_allocate().
* 2/9... wow, that's surprising; it allows BI_BITFIELDS but not 16- or 24-bit BI_RGB. Okay then.
* 3/9 is fine, just want to write that for reference I did check with Helen and the NV11 card does report NV12.
* Why do we need 4/9? Shouldn't it fail CreateSurface()?
* 5/9 is probably fine, although as someone less familiar with how this area works I'd appreciate an explanation of why the current code is wrong. It's not exactly easy to look up, anyway.
* 6/9 should presumably only be applied if the application has called SetAspectRatioMode(VMR_ARMODE_LETTER_BOX). Has it? And if it has, we presumably need to also clear the rest of the surface to black.
* 8/9 would probably make more sense if you just fit it into the table, with depth=16 and depth=24 entries.