From: Henri Verbeet Subject: [PATCH 1/5] ddraw/tests: Rewrite yv12_test(). Message-Id: <1454704263-30101-1-git-send-email-hverbeet@codeweavers.com> Date: Fri, 5 Feb 2016 21:30:59 +0100 Signed-off-by: Henri Verbeet --- dlls/ddraw/tests/ddraw1.c | 136 ++++++++++++++++++++++++++++++++++++++++++++- dlls/ddraw/tests/ddraw2.c | 136 ++++++++++++++++++++++++++++++++++++++++++++- dlls/ddraw/tests/ddraw4.c | 136 ++++++++++++++++++++++++++++++++++++++++++++- dlls/ddraw/tests/ddraw7.c | 136 ++++++++++++++++++++++++++++++++++++++++++++- dlls/ddraw/tests/overlay.c | 101 --------------------------------- 5 files changed, 540 insertions(+), 105 deletions(-) diff --git a/dlls/ddraw/tests/ddraw1.c b/dlls/ddraw/tests/ddraw1.c index dcadaf5..fdb9945 100644 --- a/dlls/ddraw/tests/ddraw1.c +++ b/dlls/ddraw/tests/ddraw1.c @@ -1,7 +1,7 @@ /* * Copyright 2005 Antoine Chavasse (a.chavasse@gmail.com) + * Copyright 2008, 2011, 2012-2013 Stefan Dösinger for CodeWeavers * Copyright 2011-2014 Henri Verbeet for CodeWeavers - * Copyright 2012-2013 Stefan Dösinger for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -45,6 +45,27 @@ static BOOL compare_color(D3DCOLOR c1, D3DCOLOR c2, BYTE max_diff) return TRUE; } +static IDirectDrawSurface *create_overlay(IDirectDraw *ddraw, + unsigned int width, unsigned int height, DWORD format) +{ + IDirectDrawSurface *surface; + DDSURFACEDESC desc; + + memset(&desc, 0, sizeof(desc)); + desc.dwSize = sizeof(desc); + desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT; + desc.dwWidth = width; + desc.dwHeight = height; + desc.ddsCaps.dwCaps = DDSCAPS_OVERLAY; + desc.ddpfPixelFormat.dwSize = sizeof(desc.ddpfPixelFormat); + desc.ddpfPixelFormat.dwFlags = DDPF_FOURCC; + desc.ddpfPixelFormat.dwFourCC = format; + + if (FAILED(IDirectDraw_CreateSurface(ddraw, &desc, &surface, NULL))) + return NULL; + return surface; +} + static DWORD WINAPI create_window_thread_proc(void *param) { struct create_window_thread_param *p = param; @@ -8200,6 +8221,118 @@ done: DestroyWindow(window); } +static void test_yv12_overlay(void) +{ + IDirectDrawSurface *src_surface, *dst_surface; + RECT rect = {13, 17, 14, 18}; + unsigned int offset, y; + unsigned char *base; + DDSURFACEDESC desc; + IDirectDraw *ddraw; + HWND window; + HRESULT hr; + + window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW, + 0, 0, 640, 480, 0, 0, 0, 0); + ddraw = create_ddraw(); + ok(!!ddraw, "Failed to create a ddraw object.\n"); + hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL); + ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr); + + if (!(src_surface = create_overlay(ddraw, 256, 256, MAKEFOURCC('Y','V','1','2')))) + { + skip("Failed to create a YV12 overlay, skipping test.\n"); + goto done; + } + + memset(&desc, 0, sizeof(desc)); + desc.dwSize = sizeof(desc); + hr = IDirectDrawSurface_Lock(src_surface, NULL, &desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + + ok(desc.dwFlags == (DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS | DDSD_PITCH), + "Got unexpected flags %#x.\n", desc.dwFlags); + ok(desc.ddsCaps.dwCaps == (DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM | DDSCAPS_HWCODEC) + || desc.ddsCaps.dwCaps == (DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM), + "Got unexpected caps %#x.\n", desc.ddsCaps.dwCaps); + ok(desc.dwWidth == 256, "Got unexpected width %u.\n", desc.dwWidth); + ok(desc.dwHeight == 256, "Got unexpected height %u.\n", desc.dwHeight); + /* The overlay pitch seems to have 256 byte alignment. */ + ok(!(U1(desc).lPitch & 0xff), "Got unexpected pitch %u.\n", U1(desc).lPitch); + + /* Fill the surface with some data for the blit test. */ + base = desc.lpSurface; + /* Luminance */ + for (y = 0; y < desc.dwHeight; ++y) + { + memset(base + U1(desc).lPitch * y, 0x10, desc.dwWidth); + } + /* V */ + for (; y < desc.dwHeight + desc.dwHeight / 4; ++y) + { + memset(base + U1(desc).lPitch * y, 0x20, desc.dwWidth); + } + /* U */ + for (; y < desc.dwHeight + desc.dwHeight / 2; ++y) + { + memset(base + U1(desc).lPitch * y, 0x30, desc.dwWidth); + } + + hr = IDirectDrawSurface_Unlock(src_surface, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + /* YV12 uses 2x2 blocks with 6 bytes per block (4*Y, 1*U, 1*V). Unlike + * other block-based formats like DXT the entire Y channel is stored in + * one big chunk of memory, followed by the chroma channels. So partial + * locks do not really make sense. Show that they are allowed nevertheless + * and the offset points into the luminance data. */ + hr = IDirectDrawSurface_Lock(src_surface, &rect, &desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + offset = ((const unsigned char *)desc.lpSurface - base); + ok(offset == rect.top * U1(desc).lPitch + rect.left, "Got unexpected offset %u, expected %u.\n", + offset, rect.top * U1(desc).lPitch + rect.left); + hr = IDirectDrawSurface_Unlock(src_surface, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + if (!(dst_surface = create_overlay(ddraw, 256, 256, MAKEFOURCC('Y','V','1','2')))) + { + /* Windows XP with a Radeon X1600 GPU refuses to create a second + * overlay surface, DDERR_NOOVERLAYHW, making the blit tests moot. */ + skip("Failed to create a second YV12 surface, skipping blit test.\n"); + IDirectDrawSurface_Release(src_surface); + goto done; + } + + hr = IDirectDrawSurface_Blt(dst_surface, NULL, src_surface, NULL, DDBLT_WAIT, NULL); + /* VMware rejects YV12 blits. This behavior has not been seen on real + * hardware yet, so mark it broken. */ + ok(SUCCEEDED(hr) || broken(hr == E_NOTIMPL), "Failed to blit, hr %#x.\n", hr); + + if (SUCCEEDED(hr)) + { + memset(&desc, 0, sizeof(desc)); + desc.dwSize = sizeof(desc); + hr = IDirectDrawSurface_Lock(dst_surface, NULL, &desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + + base = desc.lpSurface; + ok(base[0] == 0x10, "Got unexpected Y data 0x%02x.\n", base[0]); + base += desc.dwHeight * U1(desc).lPitch; + todo_wine ok(base[0] == 0x20, "Got unexpected V data 0x%02x.\n", base[0]); + base += desc.dwHeight / 4 * U1(desc).lPitch; + todo_wine ok(base[0] == 0x30, "Got unexpected U data 0x%02x.\n", base[0]); + + hr = IDirectDrawSurface_Unlock(dst_surface, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + } + + IDirectDrawSurface_Release(dst_surface); + IDirectDrawSurface_Release(src_surface); +done: + IDirectDraw_Release(ddraw); + DestroyWindow(window); +} + START_TEST(ddraw1) { IDirectDraw *ddraw; @@ -8273,4 +8406,5 @@ START_TEST(ddraw1) test_range_colorkey(); test_shademode(); test_lockrect_invalid(); + test_yv12_overlay(); } diff --git a/dlls/ddraw/tests/ddraw2.c b/dlls/ddraw/tests/ddraw2.c index 62f1974..f0ba90c 100644 --- a/dlls/ddraw/tests/ddraw2.c +++ b/dlls/ddraw/tests/ddraw2.c @@ -1,7 +1,7 @@ /* * Copyright 2005 Antoine Chavasse (a.chavasse@gmail.com) + * Copyright 2008, 2011, 2012-2014 Stefan Dösinger for CodeWeavers * Copyright 2011-2014 Henri Verbeet for CodeWeavers - * Copyright 2012-2014 Stefan Dösinger for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -47,6 +47,27 @@ static BOOL compare_color(D3DCOLOR c1, D3DCOLOR c2, BYTE max_diff) return TRUE; } +static IDirectDrawSurface *create_overlay(IDirectDraw2 *ddraw, + unsigned int width, unsigned int height, DWORD format) +{ + IDirectDrawSurface *surface; + DDSURFACEDESC desc; + + memset(&desc, 0, sizeof(desc)); + desc.dwSize = sizeof(desc); + desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT; + desc.dwWidth = width; + desc.dwHeight = height; + desc.ddsCaps.dwCaps = DDSCAPS_OVERLAY; + desc.ddpfPixelFormat.dwSize = sizeof(desc.ddpfPixelFormat); + desc.ddpfPixelFormat.dwFlags = DDPF_FOURCC; + desc.ddpfPixelFormat.dwFourCC = format; + + if (FAILED(IDirectDraw2_CreateSurface(ddraw, &desc, &surface, NULL))) + return NULL; + return surface; +} + static DWORD WINAPI create_window_thread_proc(void *param) { struct create_window_thread_param *p = param; @@ -9307,6 +9328,118 @@ done: DestroyWindow(window); } +static void test_yv12_overlay(void) +{ + IDirectDrawSurface *src_surface, *dst_surface; + RECT rect = {13, 17, 14, 18}; + unsigned int offset, y; + unsigned char *base; + IDirectDraw2 *ddraw; + DDSURFACEDESC desc; + HWND window; + HRESULT hr; + + window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW, + 0, 0, 640, 480, 0, 0, 0, 0); + ddraw = create_ddraw(); + ok(!!ddraw, "Failed to create a ddraw object.\n"); + hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL); + ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr); + + if (!(src_surface = create_overlay(ddraw, 256, 256, MAKEFOURCC('Y','V','1','2')))) + { + skip("Failed to create a YV12 overlay, skipping test.\n"); + goto done; + } + + memset(&desc, 0, sizeof(desc)); + desc.dwSize = sizeof(desc); + hr = IDirectDrawSurface_Lock(src_surface, NULL, &desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + + ok(desc.dwFlags == (DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS | DDSD_PITCH), + "Got unexpected flags %#x.\n", desc.dwFlags); + ok(desc.ddsCaps.dwCaps == (DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM | DDSCAPS_HWCODEC) + || desc.ddsCaps.dwCaps == (DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM), + "Got unexpected caps %#x.\n", desc.ddsCaps.dwCaps); + ok(desc.dwWidth == 256, "Got unexpected width %u.\n", desc.dwWidth); + ok(desc.dwHeight == 256, "Got unexpected height %u.\n", desc.dwHeight); + /* The overlay pitch seems to have 256 byte alignment. */ + ok(!(U1(desc).lPitch & 0xff), "Got unexpected pitch %u.\n", U1(desc).lPitch); + + /* Fill the surface with some data for the blit test. */ + base = desc.lpSurface; + /* Luminance */ + for (y = 0; y < desc.dwHeight; ++y) + { + memset(base + U1(desc).lPitch * y, 0x10, desc.dwWidth); + } + /* V */ + for (; y < desc.dwHeight + desc.dwHeight / 4; ++y) + { + memset(base + U1(desc).lPitch * y, 0x20, desc.dwWidth); + } + /* U */ + for (; y < desc.dwHeight + desc.dwHeight / 2; ++y) + { + memset(base + U1(desc).lPitch * y, 0x30, desc.dwWidth); + } + + hr = IDirectDrawSurface_Unlock(src_surface, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + /* YV12 uses 2x2 blocks with 6 bytes per block (4*Y, 1*U, 1*V). Unlike + * other block-based formats like DXT the entire Y channel is stored in + * one big chunk of memory, followed by the chroma channels. So partial + * locks do not really make sense. Show that they are allowed nevertheless + * and the offset points into the luminance data. */ + hr = IDirectDrawSurface_Lock(src_surface, &rect, &desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + offset = ((const unsigned char *)desc.lpSurface - base); + ok(offset == rect.top * U1(desc).lPitch + rect.left, "Got unexpected offset %u, expected %u.\n", + offset, rect.top * U1(desc).lPitch + rect.left); + hr = IDirectDrawSurface_Unlock(src_surface, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + if (!(dst_surface = create_overlay(ddraw, 256, 256, MAKEFOURCC('Y','V','1','2')))) + { + /* Windows XP with a Radeon X1600 GPU refuses to create a second + * overlay surface, DDERR_NOOVERLAYHW, making the blit tests moot. */ + skip("Failed to create a second YV12 surface, skipping blit test.\n"); + IDirectDrawSurface_Release(src_surface); + goto done; + } + + hr = IDirectDrawSurface_Blt(dst_surface, NULL, src_surface, NULL, DDBLT_WAIT, NULL); + /* VMware rejects YV12 blits. This behavior has not been seen on real + * hardware yet, so mark it broken. */ + ok(SUCCEEDED(hr) || broken(hr == E_NOTIMPL), "Failed to blit, hr %#x.\n", hr); + + if (SUCCEEDED(hr)) + { + memset(&desc, 0, sizeof(desc)); + desc.dwSize = sizeof(desc); + hr = IDirectDrawSurface_Lock(dst_surface, NULL, &desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + + base = desc.lpSurface; + ok(base[0] == 0x10, "Got unexpected Y data 0x%02x.\n", base[0]); + base += desc.dwHeight * U1(desc).lPitch; + todo_wine ok(base[0] == 0x20, "Got unexpected V data 0x%02x.\n", base[0]); + base += desc.dwHeight / 4 * U1(desc).lPitch; + todo_wine ok(base[0] == 0x30, "Got unexpected U data 0x%02x.\n", base[0]); + + hr = IDirectDrawSurface_Unlock(dst_surface, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + } + + IDirectDrawSurface_Release(dst_surface); + IDirectDrawSurface_Release(src_surface); +done: + IDirectDraw2_Release(ddraw); + DestroyWindow(window); +} + START_TEST(ddraw2) { IDirectDraw2 *ddraw; @@ -9387,4 +9520,5 @@ START_TEST(ddraw2) test_range_colorkey(); test_shademode(); test_lockrect_invalid(); + test_yv12_overlay(); } diff --git a/dlls/ddraw/tests/ddraw4.c b/dlls/ddraw/tests/ddraw4.c index 9239930..08a1a4c 100644 --- a/dlls/ddraw/tests/ddraw4.c +++ b/dlls/ddraw/tests/ddraw4.c @@ -1,7 +1,7 @@ /* * Copyright 2005 Antoine Chavasse (a.chavasse@gmail.com) + * Copyright 2008, 2011, 2012-2014 Stefan Dösinger for CodeWeavers * Copyright 2011-2014 Henri Verbeet for CodeWeavers - * Copyright 2012-2014 Stefan Dösinger for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -86,6 +86,27 @@ static BOOL compare_color(D3DCOLOR c1, D3DCOLOR c2, BYTE max_diff) return TRUE; } +static IDirectDrawSurface4 *create_overlay(IDirectDraw4 *ddraw, + unsigned int width, unsigned int height, DWORD format) +{ + IDirectDrawSurface4 *surface; + DDSURFACEDESC2 desc; + + memset(&desc, 0, sizeof(desc)); + desc.dwSize = sizeof(desc); + desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT; + desc.dwWidth = width; + desc.dwHeight = height; + desc.ddsCaps.dwCaps = DDSCAPS_OVERLAY; + U4(desc).ddpfPixelFormat.dwSize = sizeof(U4(desc).ddpfPixelFormat); + U4(desc).ddpfPixelFormat.dwFlags = DDPF_FOURCC; + U4(desc).ddpfPixelFormat.dwFourCC = format; + + if (FAILED(IDirectDraw4_CreateSurface(ddraw, &desc, &surface, NULL))) + return NULL; + return surface; +} + static DWORD WINAPI create_window_thread_proc(void *param) { struct create_window_thread_param *p = param; @@ -10482,6 +10503,118 @@ done: DestroyWindow(window); } +static void test_yv12_overlay(void) +{ + IDirectDrawSurface4 *src_surface, *dst_surface; + RECT rect = {13, 17, 14, 18}; + unsigned int offset, y; + DDSURFACEDESC2 desc; + unsigned char *base; + IDirectDraw4 *ddraw; + HWND window; + HRESULT hr; + + window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW, + 0, 0, 640, 480, 0, 0, 0, 0); + ddraw = create_ddraw(); + ok(!!ddraw, "Failed to create a ddraw object.\n"); + hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL); + ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr); + + if (!(src_surface = create_overlay(ddraw, 256, 256, MAKEFOURCC('Y','V','1','2')))) + { + skip("Failed to create a YV12 overlay, skipping test.\n"); + goto done; + } + + memset(&desc, 0, sizeof(desc)); + desc.dwSize = sizeof(desc); + hr = IDirectDrawSurface4_Lock(src_surface, NULL, &desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + + ok(desc.dwFlags == (DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS | DDSD_PITCH), + "Got unexpected flags %#x.\n", desc.dwFlags); + ok(desc.ddsCaps.dwCaps == (DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM | DDSCAPS_HWCODEC) + || desc.ddsCaps.dwCaps == (DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM), + "Got unexpected caps %#x.\n", desc.ddsCaps.dwCaps); + ok(desc.dwWidth == 256, "Got unexpected width %u.\n", desc.dwWidth); + ok(desc.dwHeight == 256, "Got unexpected height %u.\n", desc.dwHeight); + /* The overlay pitch seems to have 256 byte alignment. */ + ok(!(U1(desc).lPitch & 0xff), "Got unexpected pitch %u.\n", U1(desc).lPitch); + + /* Fill the surface with some data for the blit test. */ + base = desc.lpSurface; + /* Luminance */ + for (y = 0; y < desc.dwHeight; ++y) + { + memset(base + U1(desc).lPitch * y, 0x10, desc.dwWidth); + } + /* V */ + for (; y < desc.dwHeight + desc.dwHeight / 4; ++y) + { + memset(base + U1(desc).lPitch * y, 0x20, desc.dwWidth); + } + /* U */ + for (; y < desc.dwHeight + desc.dwHeight / 2; ++y) + { + memset(base + U1(desc).lPitch * y, 0x30, desc.dwWidth); + } + + hr = IDirectDrawSurface4_Unlock(src_surface, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + /* YV12 uses 2x2 blocks with 6 bytes per block (4*Y, 1*U, 1*V). Unlike + * other block-based formats like DXT the entire Y channel is stored in + * one big chunk of memory, followed by the chroma channels. So partial + * locks do not really make sense. Show that they are allowed nevertheless + * and the offset points into the luminance data. */ + hr = IDirectDrawSurface4_Lock(src_surface, &rect, &desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + offset = ((const unsigned char *)desc.lpSurface - base); + ok(offset == rect.top * U1(desc).lPitch + rect.left, "Got unexpected offset %u, expected %u.\n", + offset, rect.top * U1(desc).lPitch + rect.left); + hr = IDirectDrawSurface4_Unlock(src_surface, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + if (!(dst_surface = create_overlay(ddraw, 256, 256, MAKEFOURCC('Y','V','1','2')))) + { + /* Windows XP with a Radeon X1600 GPU refuses to create a second + * overlay surface, DDERR_NOOVERLAYHW, making the blit tests moot. */ + skip("Failed to create a second YV12 surface, skipping blit test.\n"); + IDirectDrawSurface4_Release(src_surface); + goto done; + } + + hr = IDirectDrawSurface4_Blt(dst_surface, NULL, src_surface, NULL, DDBLT_WAIT, NULL); + /* VMware rejects YV12 blits. This behavior has not been seen on real + * hardware yet, so mark it broken. */ + ok(SUCCEEDED(hr) || broken(hr == E_NOTIMPL), "Failed to blit, hr %#x.\n", hr); + + if (SUCCEEDED(hr)) + { + memset(&desc, 0, sizeof(desc)); + desc.dwSize = sizeof(desc); + hr = IDirectDrawSurface4_Lock(dst_surface, NULL, &desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + + base = desc.lpSurface; + ok(base[0] == 0x10, "Got unexpected Y data 0x%02x.\n", base[0]); + base += desc.dwHeight * U1(desc).lPitch; + todo_wine ok(base[0] == 0x20, "Got unexpected V data 0x%02x.\n", base[0]); + base += desc.dwHeight / 4 * U1(desc).lPitch; + todo_wine ok(base[0] == 0x30, "Got unexpected U data 0x%02x.\n", base[0]); + + hr = IDirectDrawSurface4_Unlock(dst_surface, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + } + + IDirectDrawSurface4_Release(dst_surface); + IDirectDrawSurface4_Release(src_surface); +done: + IDirectDraw4_Release(ddraw); + DestroyWindow(window); +} + START_TEST(ddraw4) { IDirectDraw4 *ddraw; @@ -10569,4 +10702,5 @@ START_TEST(ddraw4) test_range_colorkey(); test_shademode(); test_lockrect_invalid(); + test_yv12_overlay(); } diff --git a/dlls/ddraw/tests/ddraw7.c b/dlls/ddraw/tests/ddraw7.c index 34167c1..9b5c698 100644 --- a/dlls/ddraw/tests/ddraw7.c +++ b/dlls/ddraw/tests/ddraw7.c @@ -1,6 +1,6 @@ /* * Copyright 2005 Antoine Chavasse (a.chavasse@gmail.com) - * Copyright 2006, 2012-2014 Stefan Dösinger for CodeWeavers + * Copyright 2006, 2008, 2011, 2012-2014 Stefan Dösinger for CodeWeavers * Copyright 2011-2014 Henri Verbeet for CodeWeavers * * This library is free software; you can redistribute it and/or @@ -100,6 +100,27 @@ static ULONG get_refcount(IUnknown *iface) return IUnknown_Release(iface); } +static IDirectDrawSurface7 *create_overlay(IDirectDraw7 *ddraw, + unsigned int width, unsigned int height, DWORD format) +{ + IDirectDrawSurface7 *surface; + DDSURFACEDESC2 desc; + + memset(&desc, 0, sizeof(desc)); + desc.dwSize = sizeof(desc); + desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT; + desc.dwWidth = width; + desc.dwHeight = height; + desc.ddsCaps.dwCaps = DDSCAPS_OVERLAY; + U4(desc).ddpfPixelFormat.dwSize = sizeof(U4(desc).ddpfPixelFormat); + U4(desc).ddpfPixelFormat.dwFlags = DDPF_FOURCC; + U4(desc).ddpfPixelFormat.dwFourCC = format; + + if (FAILED(IDirectDraw7_CreateSurface(ddraw, &desc, &surface, NULL))) + return NULL; + return surface; +} + static DWORD WINAPI create_window_thread_proc(void *param) { struct create_window_thread_param *p = param; @@ -10761,6 +10782,118 @@ done: DestroyWindow(window); } +static void test_yv12_overlay(void) +{ + IDirectDrawSurface7 *src_surface, *dst_surface; + RECT rect = {13, 17, 14, 18}; + unsigned int offset, y; + DDSURFACEDESC2 desc; + unsigned char *base; + IDirectDraw7 *ddraw; + HWND window; + HRESULT hr; + + window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW, + 0, 0, 640, 480, 0, 0, 0, 0); + ddraw = create_ddraw(); + ok(!!ddraw, "Failed to create a ddraw object.\n"); + hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL); + ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr); + + if (!(src_surface = create_overlay(ddraw, 256, 256, MAKEFOURCC('Y','V','1','2')))) + { + skip("Failed to create a YV12 overlay, skipping test.\n"); + goto done; + } + + memset(&desc, 0, sizeof(desc)); + desc.dwSize = sizeof(desc); + hr = IDirectDrawSurface7_Lock(src_surface, NULL, &desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + + ok(desc.dwFlags == (DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS | DDSD_PITCH), + "Got unexpected flags %#x.\n", desc.dwFlags); + ok(desc.ddsCaps.dwCaps == (DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM | DDSCAPS_HWCODEC) + || desc.ddsCaps.dwCaps == (DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM), + "Got unexpected caps %#x.\n", desc.ddsCaps.dwCaps); + ok(desc.dwWidth == 256, "Got unexpected width %u.\n", desc.dwWidth); + ok(desc.dwHeight == 256, "Got unexpected height %u.\n", desc.dwHeight); + /* The overlay pitch seems to have 256 byte alignment. */ + ok(!(U1(desc).lPitch & 0xff), "Got unexpected pitch %u.\n", U1(desc).lPitch); + + /* Fill the surface with some data for the blit test. */ + base = desc.lpSurface; + /* Luminance */ + for (y = 0; y < desc.dwHeight; ++y) + { + memset(base + U1(desc).lPitch * y, 0x10, desc.dwWidth); + } + /* V */ + for (; y < desc.dwHeight + desc.dwHeight / 4; ++y) + { + memset(base + U1(desc).lPitch * y, 0x20, desc.dwWidth); + } + /* U */ + for (; y < desc.dwHeight + desc.dwHeight / 2; ++y) + { + memset(base + U1(desc).lPitch * y, 0x30, desc.dwWidth); + } + + hr = IDirectDrawSurface7_Unlock(src_surface, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + /* YV12 uses 2x2 blocks with 6 bytes per block (4*Y, 1*U, 1*V). Unlike + * other block-based formats like DXT the entire Y channel is stored in + * one big chunk of memory, followed by the chroma channels. So partial + * locks do not really make sense. Show that they are allowed nevertheless + * and the offset points into the luminance data. */ + hr = IDirectDrawSurface7_Lock(src_surface, &rect, &desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + offset = ((const unsigned char *)desc.lpSurface - base); + ok(offset == rect.top * U1(desc).lPitch + rect.left, "Got unexpected offset %u, expected %u.\n", + offset, rect.top * U1(desc).lPitch + rect.left); + hr = IDirectDrawSurface7_Unlock(src_surface, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + if (!(dst_surface = create_overlay(ddraw, 256, 256, MAKEFOURCC('Y','V','1','2')))) + { + /* Windows XP with a Radeon X1600 GPU refuses to create a second + * overlay surface, DDERR_NOOVERLAYHW, making the blit tests moot. */ + skip("Failed to create a second YV12 surface, skipping blit test.\n"); + IDirectDrawSurface7_Release(src_surface); + goto done; + } + + hr = IDirectDrawSurface7_Blt(dst_surface, NULL, src_surface, NULL, DDBLT_WAIT, NULL); + /* VMware rejects YV12 blits. This behavior has not been seen on real + * hardware yet, so mark it broken. */ + ok(SUCCEEDED(hr) || broken(hr == E_NOTIMPL), "Failed to blit, hr %#x.\n", hr); + + if (SUCCEEDED(hr)) + { + memset(&desc, 0, sizeof(desc)); + desc.dwSize = sizeof(desc); + hr = IDirectDrawSurface7_Lock(dst_surface, NULL, &desc, DDLOCK_WAIT, NULL); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + + base = desc.lpSurface; + ok(base[0] == 0x10, "Got unexpected Y data 0x%02x.\n", base[0]); + base += desc.dwHeight * U1(desc).lPitch; + todo_wine ok(base[0] == 0x20, "Got unexpected V data 0x%02x.\n", base[0]); + base += desc.dwHeight / 4 * U1(desc).lPitch; + todo_wine ok(base[0] == 0x30, "Got unexpected U data 0x%02x.\n", base[0]); + + hr = IDirectDrawSurface7_Unlock(dst_surface, NULL); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + } + + IDirectDrawSurface7_Release(dst_surface); + IDirectDrawSurface7_Release(src_surface); +done: + IDirectDraw7_Release(ddraw); + DestroyWindow(window); +} + START_TEST(ddraw7) { HMODULE module = GetModuleHandleA("ddraw.dll"); @@ -10859,4 +10992,5 @@ START_TEST(ddraw7) test_range_colorkey(); test_shademode(); test_lockrect_invalid(); + test_yv12_overlay(); } diff --git a/dlls/ddraw/tests/overlay.c b/dlls/ddraw/tests/overlay.c index 7e22cca..ecea63e 100644 --- a/dlls/ddraw/tests/overlay.c +++ b/dlls/ddraw/tests/overlay.c @@ -191,106 +191,6 @@ static void offscreen_test(void) { IDirectDrawSurface7_Release(overlay); } -static void yv12_test(void) -{ - HRESULT hr; - DDSURFACEDESC2 desc; - IDirectDrawSurface7 *surface, *dst; - char *base; - RECT rect = {13, 17, 14, 18}; - unsigned int offset, y; - - surface = create_overlay(256, 256, MAKEFOURCC('Y','V','1','2')); - if(!surface) { - skip("YV12 surfaces not available\n"); - return; - } - - memset(&desc, 0, sizeof(desc)); - desc.dwSize = sizeof(desc); - hr = IDirectDrawSurface7_Lock(surface, NULL, &desc, 0, NULL); - ok(hr == DD_OK, "IDirectDrawSurface7_Lock returned 0x%08x, expected DD_OK\n", hr); - - ok(desc.dwFlags == (DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS | DDSD_PITCH), - "Unexpected desc.dwFlags 0x%08x\n", desc.dwFlags); - ok(desc.ddsCaps.dwCaps == (DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM) || - desc.ddsCaps.dwCaps == (DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM | DDSCAPS_HWCODEC), - "Unexpected desc.ddsCaps.dwCaps 0x%08x\n", desc.ddsCaps.dwCaps); - ok(desc.dwWidth == 256 && desc.dwHeight == 256, "Expected size 256x256, got %ux%u\n", - desc.dwWidth, desc.dwHeight); - /* The overlay pitch seems to have 256 byte alignment */ - ok((U1(desc).lPitch & 0xff) == 0, "Expected 256 byte aligned pitch, got %u\n", U1(desc).lPitch); - - /* Fill the surface with some data for the blit test */ - base = desc.lpSurface; - /* Luminance */ - for (y = 0; y < desc.dwHeight; y++) - { - memset(base + U1(desc).lPitch * y, 0x10, desc.dwWidth); - } - /* V */ - for (; y < desc.dwHeight + desc.dwHeight / 4; y++) - { - memset(base + U1(desc).lPitch * y, 0x20, desc.dwWidth); - } - /* U */ - for (; y < desc.dwHeight + desc.dwHeight / 2; y++) - { - memset(base + U1(desc).lPitch * y, 0x30, desc.dwWidth); - } - - hr = IDirectDrawSurface7_Unlock(surface, NULL); - ok(hr == DD_OK, "IDirectDrawSurface7_Unlock returned 0x%08x, expected DD_OK\n", hr); - - /* YV12 uses 2x2 blocks with 6 bytes per block(4*Y, 1*U, 1*V). Unlike other block-based formats like DXT - * the entire Y channel is stored in one big chunk of memory, followed by the chroma channels. So - * partial locks do not really make sense. Show that they are allowed nevertheless and the offset points - * into the luminance data */ - hr = IDirectDrawSurface7_Lock(surface, &rect, &desc, 0, NULL); - ok(hr == DD_OK, "Partial lock of a YV12 surface returned 0x%08x, expected DD_OK\n", hr); - offset = ((const char *) desc.lpSurface - base); - ok(offset == rect.top * U1(desc).lPitch + rect.left, "Expected %u byte offset from partial lock, got %u\n", - rect.top * U1(desc).lPitch + rect.left, offset); - hr = IDirectDrawSurface7_Unlock(surface, NULL); - ok(hr == DD_OK, "IDirectDrawSurface7_Unlock returned 0x%08x, expected DD_OK\n", hr); - - dst = create_overlay(256, 256, MAKEFOURCC('Y','V','1','2')); - if (!dst) - { - /* Windows XP with a Radeon X1600 GPU refuses to create a second overlay surface, - * DDERR_NOOVERLAYHW, making the blit tests moot */ - skip("Could not create a second YV12 surface, skipping blit test\n"); - goto cleanup; - } - - hr = IDirectDrawSurface7_Blt(dst, NULL, surface, NULL, 0, NULL); - /* VMware rejects YV12 blits. This behavior has not been seen on real hardware yet, so mark it broken */ - ok(hr == DD_OK || broken(hr == E_NOTIMPL), - "IDirectDrawSurface7_Blt returned 0x%08x, expected DD_OK\n", hr); - - if (SUCCEEDED(hr)) - { - memset(&desc, 0, sizeof(desc)); - desc.dwSize = sizeof(desc); - hr = IDirectDrawSurface7_Lock(dst, NULL, &desc, 0, NULL); - ok(hr == DD_OK, "IDirectDrawSurface7_Lock returned 0x%08x, expected DD_OK\n", hr); - - base = desc.lpSurface; - ok(base[0] == 0x10, "Y data is 0x%02x, expected 0x10\n", base[0]); - base += desc.dwHeight * U1(desc).lPitch; - todo_wine ok(base[0] == 0x20, "V data is 0x%02x, expected 0x20\n", base[0]); - base += desc.dwHeight / 4 * U1(desc).lPitch; - todo_wine ok(base[0] == 0x30, "U data is 0x%02x, expected 0x30\n", base[0]); - - hr = IDirectDrawSurface7_Unlock(dst, NULL); - ok(hr == DD_OK, "IDirectDrawSurface7_Unlock returned 0x%08x, expected DD_OK\n", hr); - } - - IDirectDrawSurface7_Release(dst); -cleanup: - IDirectDrawSurface7_Release(surface); -} - START_TEST(overlay) { if(CreateDirectDraw() == FALSE) { @@ -300,7 +200,6 @@ START_TEST(overlay) rectangle_settings(); offscreen_test(); - yv12_test(); if(primary) IDirectDrawSurface7_Release(primary); if(ddraw) IDirectDraw7_Release(ddraw); -- 2.1.4