From: Elizabeth Figura zfigura@codeweavers.com
--- dlls/ddraw/tests/ddraw1.c | 185 ++++++++++++++++++++++++++++++++++++++ dlls/ddraw/tests/ddraw2.c | 185 ++++++++++++++++++++++++++++++++++++++ dlls/ddraw/tests/ddraw4.c | 185 ++++++++++++++++++++++++++++++++++++++ dlls/ddraw/tests/ddraw7.c | 185 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 740 insertions(+)
diff --git a/dlls/ddraw/tests/ddraw1.c b/dlls/ddraw/tests/ddraw1.c index 205370a8577..e62d9283aaa 100644 --- a/dlls/ddraw/tests/ddraw1.c +++ b/dlls/ddraw/tests/ddraw1.c @@ -20,6 +20,7 @@
#define COBJMACROS
+#include <stdint.h> #include "wine/test.h" #include <limits.h> #include <math.h> @@ -15935,6 +15936,189 @@ static void test_sysmem_x_channel(void) DestroyWindow(window); }
+static void test_yuv_blit(void) +{ + DDSURFACEDESC surface_desc = {sizeof(surface_desc)}; + IDirectDrawSurface *rgb_surface, *yuv_surface; + const unsigned int width = 32, height = 32; + uint8_t *buf, *chroma_buf, *u_buf, *v_buf; + DDBLTFX fx = {.dwSize = sizeof(fx)}; + unsigned int color, refcount; + IDirectDraw *ddraw; + HWND window; + HRESULT hr; + + static const struct + { + uint8_t y, u, v; + uint32_t rgb_full, rgb_reduced; + } + tests[] = + { + {0x10, 0x80, 0x80, 0x000000, 0x101010}, + {0xeb, 0x80, 0x80, 0xffffff, 0xebebeb}, + {0x51, 0x5a, 0xf0, 0xff0000, 0xee0e0e}, + {0x91, 0x36, 0x22, 0x00ff01, 0x0dee0e}, + {0x29, 0xf0, 0x6e, 0x0000ff, 0x100fef}, + {0x7e, 0x80, 0x80, 0x808080, 0x7e7e7e}, + {0x00, 0x80, 0x80, 0x000000, 0x000000}, + {0xff, 0x80, 0x80, 0xffffff, 0xffffff}, + {0x00, 0x00, 0x00, 0x008800, 0x008800}, + {0xff, 0x00, 0x00, 0x4aff14, 0x4cff1c}, + {0x00, 0xff, 0x00, 0x0024ee, 0x0030e1}, + {0x00, 0x00, 0xff, 0xb80000, 0xb20000}, + {0xff, 0xff, 0x00, 0x4affff, 0x4cffff}, + {0xff, 0x00, 0xff, 0xffe114, 0xffd01c}, + {0x00, 0xff, 0xff, 0xb800ee, 0xb200e1}, + {0xff, 0xff, 0xff, 0xff7dff, 0xff78ff}, + }; + + static const struct + { + DWORD fourcc; + const char *str; + } + formats[] = + { + {MAKEFOURCC('U','Y','V','Y'), "UYVY"}, + {MAKEFOURCC('Y','U','Y','2'), "YUY2"}, + {MAKEFOURCC('Y','V','1','2'), "YV12"}, + {MAKEFOURCC('N','V','1','2'), "NV12"}, + }; + + window = create_window(); + ddraw = create_ddraw(); + hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT; + surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + surface_desc.dwWidth = 640; + surface_desc.dwHeight = 480; + init_format_b8g8r8x8(&surface_desc.ddpfPixelFormat); + + hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &rgb_surface, NULL); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + for (unsigned int fmt = 0; fmt < ARRAY_SIZE(formats); fmt++) + { + DWORD format = formats[fmt].fourcc; + + winetest_push_context("format %s", formats[fmt].str); + + surface_desc.dwWidth = width; + surface_desc.dwHeight = height; + surface_desc.ddpfPixelFormat.dwFlags = DDPF_FOURCC; + surface_desc.ddpfPixelFormat.dwFourCC = format; + hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &yuv_surface, NULL); + if (hr != S_OK) + { + skip("Failed to create surface, hr %#lx.\n", hr); + winetest_pop_context(); + continue; + } + + for (unsigned int i = 0; i < ARRAY_SIZE(tests); i++) + { + winetest_push_context("value (%#x,%#x,%#x)", tests[i].y, tests[i].u, tests[i].v); + + hr = IDirectDrawSurface_Lock(yuv_surface, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(hr == D3D_OK, "Got hr %#lx.\n", hr); + buf = surface_desc.lpSurface; + chroma_buf = buf + surface_desc.lPitch * height; + if (format == MAKEFOURCC('Y','V','1','2')) + { + v_buf = chroma_buf; + u_buf = chroma_buf + height / 2 * surface_desc.lPitch / 2; + } + for (unsigned int y = 0; y < height; y++) + { + for (unsigned int x = 0; x < width; x += 2) + { + uint8_t Y = tests[i].y, U = tests[i].u, V = tests[i].v; + if (x < width / 2 && y < height / 2) + Y = U = V = 0x40; + + if (format == MAKEFOURCC('U','Y','V','Y')) + { + buf[y * surface_desc.lPitch + 2 * x + 0] = U; + buf[y * surface_desc.lPitch + 2 * x + 1] = Y; + buf[y * surface_desc.lPitch + 2 * x + 2] = V; + buf[y * surface_desc.lPitch + 2 * x + 3] = Y; + } + else if (format == MAKEFOURCC('Y','U','Y','2')) + { + buf[y * surface_desc.lPitch + 2 * x + 0] = Y; + buf[y * surface_desc.lPitch + 2 * x + 1] = U; + buf[y * surface_desc.lPitch + 2 * x + 2] = Y; + buf[y * surface_desc.lPitch + 2 * x + 3] = V; + } + else if (format == MAKEFOURCC('Y','V','1','2')) + { + buf[y * surface_desc.lPitch + x + 0] = Y; + buf[y * surface_desc.lPitch + x + 1] = Y; + u_buf[(y / 2) * (surface_desc.lPitch / 2) + (x / 2)] = U; + v_buf[(y / 2) * (surface_desc.lPitch / 2) + (x / 2)] = V; + } + else if (format == MAKEFOURCC('N','V','1','2')) + { + buf[y * surface_desc.lPitch + x + 0] = Y; + buf[y * surface_desc.lPitch + x + 1] = Y; + chroma_buf[(y / 2) * surface_desc.lPitch + 2 * (x / 2) + 0] = U; + chroma_buf[(y / 2) * surface_desc.lPitch + 2 * (x / 2) + 1] = V; + } + } + } + hr = IDirectDrawSurface_Unlock(yuv_surface, NULL); + ok(hr == D3D_OK, "Got hr %#lx.\n", hr); + + hr = IDirectDrawSurface_Blt(rgb_surface, NULL, yuv_surface, NULL, DDBLT_WAIT, NULL); + if (hr != D3D_OK) + { + winetest_pop_context(); + skip("Failed to blit, hr %#lx.\n", hr); + break; + } + ok(hr == D3D_OK, "Got hr %#lx.\n", hr); + + hr = IDirectDrawSurface_Lock(rgb_surface, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(hr == D3D_OK, "Got hr %#lx.\n", hr); + + for (unsigned int y = 0; y < 4; y++) + { + for (unsigned int x = 0; x < 4; x++) + { + unsigned int xcoord = (1 + 2 * x) * 640 / 8; + unsigned int ycoord = (1 + 2 * y) * 480 / 8; + + color = ((uint32_t *)((uint8_t *)surface_desc.lpSurface + ycoord * surface_desc.lPitch))[xcoord]; + color &= 0xffffff; + + if (x < 2 && y < 2) + ok(compare_color(color, 0x008400, 1), + "Got color %#x at (%u, %u).\n", color, xcoord, ycoord); + else + ok(compare_color(color, tests[i].rgb_full, 1) + || compare_color(color, tests[i].rgb_reduced, 1), + "Got color %#x at (%u, %u), expected %#x.\n", color, xcoord, ycoord, tests[i].rgb_full); + } + } + hr = IDirectDrawSurface_Unlock(rgb_surface, NULL); + ok(hr == D3D_OK, "Got hr %#lx.\n", hr); + + winetest_pop_context(); + } + + IDirectDrawSurface_Release(yuv_surface); + winetest_pop_context(); + } + + IDirectDrawSurface_Release(rgb_surface); + refcount = IDirectDraw_Release(ddraw); + ok(!refcount, "Device has %u references left.\n", refcount); + DestroyWindow(window); +} + START_TEST(ddraw1) { DDDEVICEIDENTIFIER identifier; @@ -16057,4 +16241,5 @@ START_TEST(ddraw1) test_pinned_sysmem(); test_multiple_devices(); test_sysmem_x_channel(); + test_yuv_blit(); } diff --git a/dlls/ddraw/tests/ddraw2.c b/dlls/ddraw/tests/ddraw2.c index 91565a04dcd..0f11b27c130 100644 --- a/dlls/ddraw/tests/ddraw2.c +++ b/dlls/ddraw/tests/ddraw2.c @@ -21,6 +21,7 @@ #include <math.h>
#define COBJMACROS +#include <stdint.h> #include "wine/test.h" #include <limits.h> #include <math.h> @@ -16967,6 +16968,189 @@ static void test_sysmem_x_channel(void) DestroyWindow(window); }
+static void test_yuv_blit(void) +{ + DDSURFACEDESC surface_desc = {sizeof(surface_desc)}; + IDirectDrawSurface *rgb_surface, *yuv_surface; + const unsigned int width = 32, height = 32; + uint8_t *buf, *chroma_buf, *u_buf, *v_buf; + DDBLTFX fx = {.dwSize = sizeof(fx)}; + unsigned int color, refcount; + IDirectDraw2 *ddraw; + HWND window; + HRESULT hr; + + static const struct + { + uint8_t y, u, v; + uint32_t rgb_full, rgb_reduced; + } + tests[] = + { + {0x10, 0x80, 0x80, 0x000000, 0x101010}, + {0xeb, 0x80, 0x80, 0xffffff, 0xebebeb}, + {0x51, 0x5a, 0xf0, 0xff0000, 0xee0e0e}, + {0x91, 0x36, 0x22, 0x00ff01, 0x0dee0e}, + {0x29, 0xf0, 0x6e, 0x0000ff, 0x100fef}, + {0x7e, 0x80, 0x80, 0x808080, 0x7e7e7e}, + {0x00, 0x80, 0x80, 0x000000, 0x000000}, + {0xff, 0x80, 0x80, 0xffffff, 0xffffff}, + {0x00, 0x00, 0x00, 0x008800, 0x008800}, + {0xff, 0x00, 0x00, 0x4aff14, 0x4cff1c}, + {0x00, 0xff, 0x00, 0x0024ee, 0x0030e1}, + {0x00, 0x00, 0xff, 0xb80000, 0xb20000}, + {0xff, 0xff, 0x00, 0x4affff, 0x4cffff}, + {0xff, 0x00, 0xff, 0xffe114, 0xffd01c}, + {0x00, 0xff, 0xff, 0xb800ee, 0xb200e1}, + {0xff, 0xff, 0xff, 0xff7dff, 0xff78ff}, + }; + + static const struct + { + DWORD fourcc; + const char *str; + } + formats[] = + { + {MAKEFOURCC('U','Y','V','Y'), "UYVY"}, + {MAKEFOURCC('Y','U','Y','2'), "YUY2"}, + {MAKEFOURCC('Y','V','1','2'), "YV12"}, + {MAKEFOURCC('N','V','1','2'), "NV12"}, + }; + + window = create_window(); + ddraw = create_ddraw(); + hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT; + surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + surface_desc.dwWidth = 640; + surface_desc.dwHeight = 480; + init_format_b8g8r8x8(&surface_desc.ddpfPixelFormat); + + hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &rgb_surface, NULL); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + for (unsigned int fmt = 0; fmt < ARRAY_SIZE(formats); fmt++) + { + DWORD format = formats[fmt].fourcc; + + winetest_push_context("format %s", formats[fmt].str); + + surface_desc.dwWidth = width; + surface_desc.dwHeight = height; + surface_desc.ddpfPixelFormat.dwFlags = DDPF_FOURCC; + surface_desc.ddpfPixelFormat.dwFourCC = format; + hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &yuv_surface, NULL); + if (hr != S_OK) + { + skip("Failed to create surface, hr %#lx.\n", hr); + winetest_pop_context(); + continue; + } + + for (unsigned int i = 0; i < ARRAY_SIZE(tests); i++) + { + winetest_push_context("value (%#x,%#x,%#x)", tests[i].y, tests[i].u, tests[i].v); + + hr = IDirectDrawSurface_Lock(yuv_surface, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(hr == D3D_OK, "Got hr %#lx.\n", hr); + buf = surface_desc.lpSurface; + chroma_buf = buf + surface_desc.lPitch * height; + if (format == MAKEFOURCC('Y','V','1','2')) + { + v_buf = chroma_buf; + u_buf = chroma_buf + height / 2 * surface_desc.lPitch / 2; + } + for (unsigned int y = 0; y < height; y++) + { + for (unsigned int x = 0; x < width; x += 2) + { + uint8_t Y = tests[i].y, U = tests[i].u, V = tests[i].v; + if (x < width / 2 && y < height / 2) + Y = U = V = 0x40; + + if (format == MAKEFOURCC('U','Y','V','Y')) + { + buf[y * surface_desc.lPitch + 2 * x + 0] = U; + buf[y * surface_desc.lPitch + 2 * x + 1] = Y; + buf[y * surface_desc.lPitch + 2 * x + 2] = V; + buf[y * surface_desc.lPitch + 2 * x + 3] = Y; + } + else if (format == MAKEFOURCC('Y','U','Y','2')) + { + buf[y * surface_desc.lPitch + 2 * x + 0] = Y; + buf[y * surface_desc.lPitch + 2 * x + 1] = U; + buf[y * surface_desc.lPitch + 2 * x + 2] = Y; + buf[y * surface_desc.lPitch + 2 * x + 3] = V; + } + else if (format == MAKEFOURCC('Y','V','1','2')) + { + buf[y * surface_desc.lPitch + x + 0] = Y; + buf[y * surface_desc.lPitch + x + 1] = Y; + u_buf[(y / 2) * (surface_desc.lPitch / 2) + (x / 2)] = U; + v_buf[(y / 2) * (surface_desc.lPitch / 2) + (x / 2)] = V; + } + else if (format == MAKEFOURCC('N','V','1','2')) + { + buf[y * surface_desc.lPitch + x + 0] = Y; + buf[y * surface_desc.lPitch + x + 1] = Y; + chroma_buf[(y / 2) * surface_desc.lPitch + 2 * (x / 2) + 0] = U; + chroma_buf[(y / 2) * surface_desc.lPitch + 2 * (x / 2) + 1] = V; + } + } + } + hr = IDirectDrawSurface_Unlock(yuv_surface, NULL); + ok(hr == D3D_OK, "Got hr %#lx.\n", hr); + + hr = IDirectDrawSurface_Blt(rgb_surface, NULL, yuv_surface, NULL, DDBLT_WAIT, NULL); + if (hr != D3D_OK) + { + winetest_pop_context(); + skip("Failed to blit, hr %#lx.\n", hr); + break; + } + ok(hr == D3D_OK, "Got hr %#lx.\n", hr); + + hr = IDirectDrawSurface_Lock(rgb_surface, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(hr == D3D_OK, "Got hr %#lx.\n", hr); + + for (unsigned int y = 0; y < 4; y++) + { + for (unsigned int x = 0; x < 4; x++) + { + unsigned int xcoord = (1 + 2 * x) * 640 / 8; + unsigned int ycoord = (1 + 2 * y) * 480 / 8; + + color = ((uint32_t *)((uint8_t *)surface_desc.lpSurface + ycoord * surface_desc.lPitch))[xcoord]; + color &= 0xffffff; + + if (x < 2 && y < 2) + ok(compare_color(color, 0x008400, 1), + "Got color %#x at (%u, %u).\n", color, xcoord, ycoord); + else + ok(compare_color(color, tests[i].rgb_full, 1) + || compare_color(color, tests[i].rgb_reduced, 1), + "Got color %#x at (%u, %u), expected %#x.\n", color, xcoord, ycoord, tests[i].rgb_full); + } + } + hr = IDirectDrawSurface_Unlock(rgb_surface, NULL); + ok(hr == D3D_OK, "Got hr %#lx.\n", hr); + + winetest_pop_context(); + } + + IDirectDrawSurface_Release(yuv_surface); + winetest_pop_context(); + } + + IDirectDrawSurface_Release(rgb_surface); + refcount = IDirectDraw2_Release(ddraw); + ok(!refcount, "Device has %u references left.\n", refcount); + DestroyWindow(window); +} + START_TEST(ddraw2) { DDDEVICEIDENTIFIER identifier; @@ -17095,4 +17279,5 @@ START_TEST(ddraw2) test_multiple_devices(); test_d3d_state_reset(); test_sysmem_x_channel(); + test_yuv_blit(); } diff --git a/dlls/ddraw/tests/ddraw4.c b/dlls/ddraw/tests/ddraw4.c index d55c9b599c8..4571a5426bb 100644 --- a/dlls/ddraw/tests/ddraw4.c +++ b/dlls/ddraw/tests/ddraw4.c @@ -20,6 +20,7 @@
#define COBJMACROS
+#include <stdint.h> #include "wine/test.h" #include <limits.h> #include <math.h> @@ -20040,6 +20041,189 @@ static void test_sysmem_x_channel(void) DestroyWindow(window); }
+static void test_yuv_blit(void) +{ + DDSURFACEDESC2 surface_desc = {sizeof(surface_desc)}; + IDirectDrawSurface4 *rgb_surface, *yuv_surface; + const unsigned int width = 32, height = 32; + uint8_t *buf, *chroma_buf, *u_buf, *v_buf; + DDBLTFX fx = {.dwSize = sizeof(fx)}; + unsigned int color, refcount; + IDirectDraw4 *ddraw; + HWND window; + HRESULT hr; + + static const struct + { + uint8_t y, u, v; + uint32_t rgb_full, rgb_reduced; + } + tests[] = + { + {0x10, 0x80, 0x80, 0x000000, 0x101010}, + {0xeb, 0x80, 0x80, 0xffffff, 0xebebeb}, + {0x51, 0x5a, 0xf0, 0xff0000, 0xee0e0e}, + {0x91, 0x36, 0x22, 0x00ff01, 0x0dee0e}, + {0x29, 0xf0, 0x6e, 0x0000ff, 0x100fef}, + {0x7e, 0x80, 0x80, 0x808080, 0x7e7e7e}, + {0x00, 0x80, 0x80, 0x000000, 0x000000}, + {0xff, 0x80, 0x80, 0xffffff, 0xffffff}, + {0x00, 0x00, 0x00, 0x008800, 0x008800}, + {0xff, 0x00, 0x00, 0x4aff14, 0x4cff1c}, + {0x00, 0xff, 0x00, 0x0024ee, 0x0030e1}, + {0x00, 0x00, 0xff, 0xb80000, 0xb20000}, + {0xff, 0xff, 0x00, 0x4affff, 0x4cffff}, + {0xff, 0x00, 0xff, 0xffe114, 0xffd01c}, + {0x00, 0xff, 0xff, 0xb800ee, 0xb200e1}, + {0xff, 0xff, 0xff, 0xff7dff, 0xff78ff}, + }; + + static const struct + { + DWORD fourcc; + const char *str; + } + formats[] = + { + {MAKEFOURCC('U','Y','V','Y'), "UYVY"}, + {MAKEFOURCC('Y','U','Y','2'), "YUY2"}, + {MAKEFOURCC('Y','V','1','2'), "YV12"}, + {MAKEFOURCC('N','V','1','2'), "NV12"}, + }; + + window = create_window(); + ddraw = create_ddraw(); + hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT; + surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + surface_desc.dwWidth = 640; + surface_desc.dwHeight = 480; + init_format_b8g8r8x8(&surface_desc.ddpfPixelFormat); + + hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &rgb_surface, NULL); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + for (unsigned int fmt = 0; fmt < ARRAY_SIZE(formats); fmt++) + { + DWORD format = formats[fmt].fourcc; + + winetest_push_context("format %s", formats[fmt].str); + + surface_desc.dwWidth = width; + surface_desc.dwHeight = height; + surface_desc.ddpfPixelFormat.dwFlags = DDPF_FOURCC; + surface_desc.ddpfPixelFormat.dwFourCC = format; + hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &yuv_surface, NULL); + if (hr != S_OK) + { + skip("Failed to create surface, hr %#lx.\n", hr); + winetest_pop_context(); + continue; + } + + for (unsigned int i = 0; i < ARRAY_SIZE(tests); i++) + { + winetest_push_context("value (%#x,%#x,%#x)", tests[i].y, tests[i].u, tests[i].v); + + hr = IDirectDrawSurface4_Lock(yuv_surface, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(hr == D3D_OK, "Got hr %#lx.\n", hr); + buf = surface_desc.lpSurface; + chroma_buf = buf + surface_desc.lPitch * height; + if (format == MAKEFOURCC('Y','V','1','2')) + { + v_buf = chroma_buf; + u_buf = chroma_buf + height / 2 * surface_desc.lPitch / 2; + } + for (unsigned int y = 0; y < height; y++) + { + for (unsigned int x = 0; x < width; x += 2) + { + uint8_t Y = tests[i].y, U = tests[i].u, V = tests[i].v; + if (x < width / 2 && y < height / 2) + Y = U = V = 0x40; + + if (format == MAKEFOURCC('U','Y','V','Y')) + { + buf[y * surface_desc.lPitch + 2 * x + 0] = U; + buf[y * surface_desc.lPitch + 2 * x + 1] = Y; + buf[y * surface_desc.lPitch + 2 * x + 2] = V; + buf[y * surface_desc.lPitch + 2 * x + 3] = Y; + } + else if (format == MAKEFOURCC('Y','U','Y','2')) + { + buf[y * surface_desc.lPitch + 2 * x + 0] = Y; + buf[y * surface_desc.lPitch + 2 * x + 1] = U; + buf[y * surface_desc.lPitch + 2 * x + 2] = Y; + buf[y * surface_desc.lPitch + 2 * x + 3] = V; + } + else if (format == MAKEFOURCC('Y','V','1','2')) + { + buf[y * surface_desc.lPitch + x + 0] = Y; + buf[y * surface_desc.lPitch + x + 1] = Y; + u_buf[(y / 2) * (surface_desc.lPitch / 2) + (x / 2)] = U; + v_buf[(y / 2) * (surface_desc.lPitch / 2) + (x / 2)] = V; + } + else if (format == MAKEFOURCC('N','V','1','2')) + { + buf[y * surface_desc.lPitch + x + 0] = Y; + buf[y * surface_desc.lPitch + x + 1] = Y; + chroma_buf[(y / 2) * surface_desc.lPitch + 2 * (x / 2) + 0] = U; + chroma_buf[(y / 2) * surface_desc.lPitch + 2 * (x / 2) + 1] = V; + } + } + } + hr = IDirectDrawSurface4_Unlock(yuv_surface, NULL); + ok(hr == D3D_OK, "Got hr %#lx.\n", hr); + + hr = IDirectDrawSurface4_Blt(rgb_surface, NULL, yuv_surface, NULL, DDBLT_WAIT, NULL); + if (hr != D3D_OK) + { + winetest_pop_context(); + skip("Failed to blit, hr %#lx.\n", hr); + break; + } + ok(hr == D3D_OK, "Got hr %#lx.\n", hr); + + hr = IDirectDrawSurface4_Lock(rgb_surface, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(hr == D3D_OK, "Got hr %#lx.\n", hr); + + for (unsigned int y = 0; y < 4; y++) + { + for (unsigned int x = 0; x < 4; x++) + { + unsigned int xcoord = (1 + 2 * x) * 640 / 8; + unsigned int ycoord = (1 + 2 * y) * 480 / 8; + + color = ((uint32_t *)((uint8_t *)surface_desc.lpSurface + ycoord * surface_desc.lPitch))[xcoord]; + color &= 0xffffff; + + if (x < 2 && y < 2) + ok(compare_color(color, 0x008400, 1), + "Got color %#x at (%u, %u).\n", color, xcoord, ycoord); + else + ok(compare_color(color, tests[i].rgb_full, 1) + || compare_color(color, tests[i].rgb_reduced, 1), + "Got color %#x at (%u, %u), expected %#x.\n", color, xcoord, ycoord, tests[i].rgb_full); + } + } + hr = IDirectDrawSurface4_Unlock(rgb_surface, NULL); + ok(hr == D3D_OK, "Got hr %#lx.\n", hr); + + winetest_pop_context(); + } + + IDirectDrawSurface4_Release(yuv_surface); + winetest_pop_context(); + } + + IDirectDrawSurface4_Release(rgb_surface); + refcount = IDirectDraw4_Release(ddraw); + ok(!refcount, "Device has %u references left.\n", refcount); + DestroyWindow(window); +} + START_TEST(ddraw4) { DDDEVICEIDENTIFIER identifier; @@ -20185,4 +20369,5 @@ START_TEST(ddraw4) test_vb_desc(); test_d3d_state_reset(); test_sysmem_x_channel(); + test_yuv_blit(); } diff --git a/dlls/ddraw/tests/ddraw7.c b/dlls/ddraw/tests/ddraw7.c index e7d66278ad7..d4980250a8c 100644 --- a/dlls/ddraw/tests/ddraw7.c +++ b/dlls/ddraw/tests/ddraw7.c @@ -21,6 +21,7 @@ #define COBJMACROS
#include <stdbool.h> +#include <stdint.h> #include "wine/test.h" #include <limits.h> #include <math.h> @@ -20475,6 +20476,189 @@ static void test_sysmem_x_channel(void) DestroyWindow(window); }
+static void test_yuv_blit(void) +{ + DDSURFACEDESC2 surface_desc = {sizeof(surface_desc)}; + IDirectDrawSurface7 *rgb_surface, *yuv_surface; + const unsigned int width = 32, height = 32; + uint8_t *buf, *chroma_buf, *u_buf, *v_buf; + DDBLTFX fx = {.dwSize = sizeof(fx)}; + unsigned int color, refcount; + IDirectDraw7 *ddraw; + HWND window; + HRESULT hr; + + static const struct + { + uint8_t y, u, v; + uint32_t rgb_full, rgb_reduced; + } + tests[] = + { + {0x10, 0x80, 0x80, 0x000000, 0x101010}, + {0xeb, 0x80, 0x80, 0xffffff, 0xebebeb}, + {0x51, 0x5a, 0xf0, 0xff0000, 0xee0e0e}, + {0x91, 0x36, 0x22, 0x00ff01, 0x0dee0e}, + {0x29, 0xf0, 0x6e, 0x0000ff, 0x100fef}, + {0x7e, 0x80, 0x80, 0x808080, 0x7e7e7e}, + {0x00, 0x80, 0x80, 0x000000, 0x000000}, + {0xff, 0x80, 0x80, 0xffffff, 0xffffff}, + {0x00, 0x00, 0x00, 0x008800, 0x008800}, + {0xff, 0x00, 0x00, 0x4aff14, 0x4cff1c}, + {0x00, 0xff, 0x00, 0x0024ee, 0x0030e1}, + {0x00, 0x00, 0xff, 0xb80000, 0xb20000}, + {0xff, 0xff, 0x00, 0x4affff, 0x4cffff}, + {0xff, 0x00, 0xff, 0xffe114, 0xffd01c}, + {0x00, 0xff, 0xff, 0xb800ee, 0xb200e1}, + {0xff, 0xff, 0xff, 0xff7dff, 0xff78ff}, + }; + + static const struct + { + DWORD fourcc; + const char *str; + } + formats[] = + { + {MAKEFOURCC('U','Y','V','Y'), "UYVY"}, + {MAKEFOURCC('Y','U','Y','2'), "YUY2"}, + {MAKEFOURCC('Y','V','1','2'), "YV12"}, + {MAKEFOURCC('N','V','1','2'), "NV12"}, + }; + + window = create_window(); + ddraw = create_ddraw(); + hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + surface_desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT; + surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + surface_desc.dwWidth = 640; + surface_desc.dwHeight = 480; + init_format_b8g8r8x8(&surface_desc.ddpfPixelFormat); + + hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &rgb_surface, NULL); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + for (unsigned int fmt = 0; fmt < ARRAY_SIZE(formats); fmt++) + { + DWORD format = formats[fmt].fourcc; + + winetest_push_context("format %s", formats[fmt].str); + + surface_desc.dwWidth = width; + surface_desc.dwHeight = height; + surface_desc.ddpfPixelFormat.dwFlags = DDPF_FOURCC; + surface_desc.ddpfPixelFormat.dwFourCC = format; + hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &yuv_surface, NULL); + if (hr != S_OK) + { + skip("Failed to create surface, hr %#lx.\n", hr); + winetest_pop_context(); + continue; + } + + for (unsigned int i = 0; i < ARRAY_SIZE(tests); i++) + { + winetest_push_context("value (%#x,%#x,%#x)", tests[i].y, tests[i].u, tests[i].v); + + hr = IDirectDrawSurface7_Lock(yuv_surface, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(hr == D3D_OK, "Got hr %#lx.\n", hr); + buf = surface_desc.lpSurface; + chroma_buf = buf + surface_desc.lPitch * height; + if (format == MAKEFOURCC('Y','V','1','2')) + { + v_buf = chroma_buf; + u_buf = chroma_buf + height / 2 * surface_desc.lPitch / 2; + } + for (unsigned int y = 0; y < height; y++) + { + for (unsigned int x = 0; x < width; x += 2) + { + uint8_t Y = tests[i].y, U = tests[i].u, V = tests[i].v; + if (x < width / 2 && y < height / 2) + Y = U = V = 0x40; + + if (format == MAKEFOURCC('U','Y','V','Y')) + { + buf[y * surface_desc.lPitch + 2 * x + 0] = U; + buf[y * surface_desc.lPitch + 2 * x + 1] = Y; + buf[y * surface_desc.lPitch + 2 * x + 2] = V; + buf[y * surface_desc.lPitch + 2 * x + 3] = Y; + } + else if (format == MAKEFOURCC('Y','U','Y','2')) + { + buf[y * surface_desc.lPitch + 2 * x + 0] = Y; + buf[y * surface_desc.lPitch + 2 * x + 1] = U; + buf[y * surface_desc.lPitch + 2 * x + 2] = Y; + buf[y * surface_desc.lPitch + 2 * x + 3] = V; + } + else if (format == MAKEFOURCC('Y','V','1','2')) + { + buf[y * surface_desc.lPitch + x + 0] = Y; + buf[y * surface_desc.lPitch + x + 1] = Y; + u_buf[(y / 2) * (surface_desc.lPitch / 2) + (x / 2)] = U; + v_buf[(y / 2) * (surface_desc.lPitch / 2) + (x / 2)] = V; + } + else if (format == MAKEFOURCC('N','V','1','2')) + { + buf[y * surface_desc.lPitch + x + 0] = Y; + buf[y * surface_desc.lPitch + x + 1] = Y; + chroma_buf[(y / 2) * surface_desc.lPitch + 2 * (x / 2) + 0] = U; + chroma_buf[(y / 2) * surface_desc.lPitch + 2 * (x / 2) + 1] = V; + } + } + } + hr = IDirectDrawSurface7_Unlock(yuv_surface, NULL); + ok(hr == D3D_OK, "Got hr %#lx.\n", hr); + + hr = IDirectDrawSurface7_Blt(rgb_surface, NULL, yuv_surface, NULL, DDBLT_WAIT, NULL); + if (hr != D3D_OK) + { + winetest_pop_context(); + skip("Failed to blit, hr %#lx.\n", hr); + break; + } + ok(hr == D3D_OK, "Got hr %#lx.\n", hr); + + hr = IDirectDrawSurface7_Lock(rgb_surface, NULL, &surface_desc, DDLOCK_WAIT, NULL); + ok(hr == D3D_OK, "Got hr %#lx.\n", hr); + + for (unsigned int y = 0; y < 4; y++) + { + for (unsigned int x = 0; x < 4; x++) + { + unsigned int xcoord = (1 + 2 * x) * 640 / 8; + unsigned int ycoord = (1 + 2 * y) * 480 / 8; + + color = ((uint32_t *)((uint8_t *)surface_desc.lpSurface + ycoord * surface_desc.lPitch))[xcoord]; + color &= 0xffffff; + + if (x < 2 && y < 2) + ok(compare_color(color, 0x008400, 1), + "Got color %#x at (%u, %u).\n", color, xcoord, ycoord); + else + ok(compare_color(color, tests[i].rgb_full, 1) + || compare_color(color, tests[i].rgb_reduced, 1), + "Got color %#x at (%u, %u), expected %#x.\n", color, xcoord, ycoord, tests[i].rgb_full); + } + } + hr = IDirectDrawSurface7_Unlock(rgb_surface, NULL); + ok(hr == D3D_OK, "Got hr %#lx.\n", hr); + + winetest_pop_context(); + } + + IDirectDrawSurface7_Release(yuv_surface); + winetest_pop_context(); + } + + IDirectDrawSurface7_Release(rgb_surface); + refcount = IDirectDraw7_Release(ddraw); + ok(!refcount, "Device has %u references left.\n", refcount); + DestroyWindow(window); +} + START_TEST(ddraw7) { DDDEVICEIDENTIFIER2 identifier; @@ -20654,4 +20838,5 @@ START_TEST(ddraw7) test_vb_desc(); test_d3d_state_reset(); test_sysmem_x_channel(); + test_yuv_blit(); }