[PATCHv3 3/3] d3d9/tests: Add tests for different YUV texture layouts

Martin Storsjo martin at martin.st
Thu Feb 13 06:05:59 CST 2014


There are no public defines for the YV12 and NV12
formats, although they do seem to be supported on
actual D3D on windows, at least on the one machine I
tested on.
---
Applied more of Stefan's change suggestions, hopefully this
is good now.
---
 dlls/d3d9/tests/visual.c | 166 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 166 insertions(+)

diff --git a/dlls/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c
index 2c34999..f809d7d 100644
--- a/dlls/d3d9/tests/visual.c
+++ b/dlls/d3d9/tests/visual.c
@@ -10497,6 +10497,171 @@ static void yuv_color_test(IDirect3DDevice9 *device) {
     IDirect3D9_Release(d3d);
 }
 
+static void yuv_layout_test(IDirect3DDevice9 *device)
+{
+    HRESULT hr;
+    IDirect3DSurface9 *surface = NULL, *target = NULL;
+    unsigned int fmt, i, x, y;
+    D3DFORMAT format;
+    const char *fmt_string;
+    D3DLOCKED_RECT lr;
+    IDirect3D9 *d3d;
+    HRESULT color;
+    DWORD ref_color;
+    BYTE *buf, *chroma_buf, *u_buf, *v_buf;
+    UINT width = 20, height = 16;
+    D3DCAPS9 caps;
+
+    static const struct
+    {
+        DWORD color1, color2;
+        DWORD rgb1, rgb2;
+    }
+    test_data[] =
+    {
+      { 0x000000, 0xffffff, 0x00008800, 0x00ff7dff },
+      { 0xff0000, 0x00ffff, 0x004aff14, 0x00b800ee },
+      { 0x00ff00, 0xff00ff, 0x000024ee, 0x00ffe114 },
+      { 0x0000ff, 0xffff00, 0x00b80000, 0x004affff },
+      { 0xffff00, 0x0000ff, 0x004affff, 0x00b80000 },
+      { 0xff00ff, 0x00ff00, 0x00ffe114, 0x000024ee },
+      { 0x00ffff, 0xff0000, 0x00b800ee, 0x004aff14 },
+      { 0xffffff, 0x000000, 0x00ff7dff, 0x00008800 },
+    };
+
+    static const struct
+    {
+        D3DFORMAT format;
+        const char *str;
+    }
+    formats[] =
+    {
+        { D3DFMT_UYVY, "D3DFMT_UYVY", },
+        { D3DFMT_YUY2, "D3DFMT_YUY2", },
+        { MAKEFOURCC('Y','V','1','2'), "D3DFMT_YV12", },
+        { MAKEFOURCC('N','V','1','2'), "D3DFMT_NV12", },
+    };
+
+    hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
+    ok(SUCCEEDED(hr), "GetDeviceCaps failed, hr %#x.\n", hr);
+    if (caps.TextureCaps & D3DPTEXTURECAPS_POW2
+            && !(caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL))
+    {
+        skip("No NP2 texture support, skipping YUV texture layout test.\n");
+        return;
+    }
+
+    hr = IDirect3DDevice9_GetDirect3D(device, &d3d);
+    ok(hr == D3D_OK, "IDirect3DDevice9_GetDirect3D failed, hr = %#x.\n", hr);
+    hr = IDirect3DDevice9_GetRenderTarget(device, 0, &target);
+    ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderTarget failed, hr = %#x.\n", hr);
+
+    hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX0);
+    ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed, hr = %#x.\n", hr);
+
+    for (fmt = 0; fmt < sizeof(formats)/sizeof(formats[0]); fmt++)
+    {
+        format = formats[fmt].format;
+        fmt_string = formats[fmt].str;
+
+        /* Some (all?) Windows drivers do not support YUV 3D textures, only 2D surfaces in
+         * StretchRect. Thus use StretchRect to draw the YUV surface onto the screen instead
+         * of drawPrimitive. */
+        if (IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0,
+                D3DRTYPE_SURFACE, format) != D3D_OK)
+        {
+            skip("%s is not supported.\n", fmt_string);
+            continue;
+        }
+
+        hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, width, height, format, D3DPOOL_DEFAULT, &surface, NULL);
+        ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed, hr = %#x.\n", hr);
+
+        for (i = 0; i < sizeof(test_data)/sizeof(test_data[0]); i++)
+        {
+            hr = IDirect3DSurface9_LockRect(surface, &lr, NULL, 0);
+            ok(hr == D3D_OK, "IDirect3DSurface9_LockRect failed, hr = %#x.\n", hr);
+            buf = lr.pBits;
+            chroma_buf = buf + lr.Pitch * height;
+            if (format == MAKEFOURCC('Y','V','1','2'))
+            {
+                v_buf = chroma_buf;
+                u_buf = chroma_buf + height / 2 * lr.Pitch/2;
+            }
+            /* Draw the top left quarter of the screen with color1, the rest with color2 */
+            for (y = 0; y < height; y++)
+            {
+                for (x = 0; x < width; x += 2)
+                {
+                    DWORD color = (x < width/2 && y < height/2) ? test_data[i].color1 : test_data[i].color2;
+                    BYTE Y = (color >> 16) & 0xff;
+                    BYTE U = (color >>  8) & 0xff;
+                    BYTE V = (color >>  0) & 0xff;
+                    if (format == D3DFMT_UYVY)
+                    {
+                        buf[y * lr.Pitch + 2 * x + 0] = U;
+                        buf[y * lr.Pitch + 2 * x + 1] = Y;
+                        buf[y * lr.Pitch + 2 * x + 2] = V;
+                        buf[y * lr.Pitch + 2 * x + 3] = Y;
+                    }
+                    else if (format == D3DFMT_YUY2)
+                    {
+                        buf[y * lr.Pitch + 2 * x + 0] = Y;
+                        buf[y * lr.Pitch + 2 * x + 1] = U;
+                        buf[y * lr.Pitch + 2 * x + 2] = Y;
+                        buf[y * lr.Pitch + 2 * x + 3] = V;
+                    }
+                    else if (format == MAKEFOURCC('Y','V','1','2'))
+                    {
+                        buf[y * lr.Pitch + x + 0] = Y;
+                        buf[y * lr.Pitch + x + 1] = Y;
+                        u_buf[(y / 2) * (lr.Pitch / 2) + (x/2)] = U;
+                        v_buf[(y / 2) * (lr.Pitch / 2) + (x/2)] = V;
+                    }
+                    else if (format == MAKEFOURCC('N','V','1','2'))
+                    {
+                        buf[y * lr.Pitch + x + 0] = Y;
+                        buf[y * lr.Pitch + x + 1] = Y;
+                        chroma_buf[(y / 2) * lr.Pitch + 2 * (x/2) + 0] = U;
+                        chroma_buf[(y / 2) * lr.Pitch + 2 * (x/2) + 1] = V;
+                    }
+                }
+            }
+            hr = IDirect3DSurface9_UnlockRect(surface);
+            ok(hr == D3D_OK, "IDirect3DSurface9_UnlockRect failed, hr = %#x.\n", hr);
+
+            hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00000000, 1.0f, 0);
+            ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %#x.\n", hr);
+            hr = IDirect3DDevice9_StretchRect(device, surface, NULL, target, NULL, D3DTEXF_POINT);
+            ok(hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %#x.\n", hr);
+
+            /* Native D3D can't resist filtering the YUY surface, even though we asked it not to
+             * do so above. To prevent running into precision problems, read at points with some
+             * margin within the rect. */
+            for (y = 0; y < 4; y++)
+            {
+                for (x = 0; x < 4; x++)
+                {
+                    UINT xcoord = (1 + 2*x)*640/8;
+                    UINT ycoord = (1 + 2*y)*480/8;
+                    ref_color = (y < 2 && x < 2) ? test_data[i].rgb1 : test_data[i].rgb2;
+                    color = getPixelColor(device, xcoord, ycoord);
+                    ok(color_match(color, ref_color, 18),
+                            "Format %s: Got color %#x for pixel (%d/%d)/(%d/%d), pixel %d %d, expected %#x.\n",
+                            fmt_string, color, x, 4, y, 4, xcoord, ycoord, ref_color);
+                }
+            }
+            hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
+
+            ok(SUCCEEDED(hr), "Present failed with %#x.\n", hr);
+        }
+        IDirect3DSurface9_Release(surface);
+    }
+
+    IDirect3DSurface9_Release(target);
+    IDirect3D9_Release(d3d);
+}
+
 static void texop_range_test(IDirect3DDevice9 *device)
 {
     static const struct {
@@ -15186,6 +15351,7 @@ START_TEST(visual)
     tssargtemp_test(device_ptr);
     np2_stretch_rect_test(device_ptr);
     yuv_color_test(device_ptr);
+    yuv_layout_test(device_ptr);
     zwriteenable_test(device_ptr);
     alphatest_test(device_ptr);
     viewport_test(device_ptr);
-- 
1.8.3.4 (Apple Git-47)




More information about the wine-patches mailing list