[PATCH 6/6] d3d9/tests: Add tests for different YUV texture layouts

Martin Storsjo martin at martin.st
Tue Feb 11 05:14:59 CST 2014


There are no public defines for the YV12, I420 and NV12
formats, although they do seem to be supported on
actual D3D on windows, at least on the one machine I
tested on.
---
 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..d46693c 100644
--- a/dlls/d3d9/tests/visual.c
+++ b/dlls/d3d9/tests/visual.c
@@ -32,6 +32,10 @@
 #include <d3d9.h>
 #include "wine/test.h"
 
+#define D3DFMT_YV12 MAKEFOURCC('Y','V','1','2')
+#define D3DFMT_I420 MAKEFOURCC('I','4','2','0')
+#define D3DFMT_NV12 MAKEFOURCC('N','V','1','2')
+
 struct vec2
 {
     float x, y;
@@ -10497,6 +10501,167 @@ 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;
+
+    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 },
+    };
+
+    struct
+    {
+        D3DFORMAT format;
+        const char *str;
+    }
+    formats[] =
+    {
+        { D3DFMT_UYVY, "D3DFMT_UYVY", },
+        { D3DFMT_YUY2, "D3DFMT_YUY2", },
+        { D3DFMT_YV12, "D3DFMT_YV12", },
+        { D3DFMT_NV12, "D3DFMT_NV12", },
+        { D3DFMT_I420, "D3DFMT_I420", },
+    };
+
+    hr = IDirect3DDevice9_GetDirect3D(device, &d3d);
+    ok(hr == D3D_OK, "IDirect3DDevice9_GetDirect3D failed, hr = %08x\n", hr);
+    hr = IDirect3DDevice9_GetRenderTarget(device, 0, &target);
+    ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderTarget failed, hr = %08x\n", hr);
+
+    hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX0);
+    ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed, hr = %08x\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, 8, 8, format, D3DPOOL_DEFAULT, &surface, NULL);
+        ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed, hr = %08x\n", hr);
+
+        for (i = 0; i < sizeof(test_data)/sizeof(test_data[0]); i++)
+        {
+
+            memset(&lr, 0, sizeof(lr));
+            hr = IDirect3DSurface9_LockRect(surface, &lr, NULL, 0);
+            ok(hr == D3D_OK, "IDirect3DSurface9_LockRect failed, hr = %08x\n", hr);
+            buf = lr.pBits;
+            chroma_buf = buf + lr.Pitch * 8;
+            switch (format)
+            {
+                case D3DFMT_YV12: v_buf = chroma_buf; u_buf = chroma_buf + 4 * lr.Pitch/2; break;
+                case D3DFMT_I420: u_buf = chroma_buf; v_buf = chroma_buf + 4 * lr.Pitch/2; break;
+                default: break;
+            }
+            /* Draw the top left quarter of the screen with color1, the rest with color2 */
+            for (y = 0; y < 8; y++)
+            {
+                for (x = 0; x < 8; x += 2)
+                {
+                    DWORD color = (x < 4 && y < 4) ? test_data[i].color1 : test_data[i].color2;
+                    BYTE Y = (color >> 16) & 0xff;
+                    BYTE U = (color >>  8) & 0xff;
+                    BYTE V = (color >>  0) & 0xff;
+                    switch (format)
+                    {
+                        case 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;
+                            break;
+                        case 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;
+                            break;
+
+                        case D3DFMT_YV12:
+                        case D3DFMT_I420:
+                            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;
+                            break;
+                        case D3DFMT_NV12:
+                            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;
+                            break;
+
+                        default:
+                            break;
+                    }
+                }
+            }
+            hr = IDirect3DSurface9_UnlockRect(surface);
+            ok(hr == D3D_OK, "IDirect3DSurface9_UnlockRect failed, hr = %08x\n", hr);
+
+            hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0);
+            ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with 0x%08x\n", hr);
+            hr = IDirect3DDevice9_StretchRect(device, surface, NULL, target, NULL, D3DTEXF_POINT);
+            ok(hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with 0x%08x\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++)
+                {
+                    ref_color = (y < 2 && x < 2) ? test_data[i].rgb1 : test_data[i].rgb2;
+                    color = getPixelColor(device, (1 + 2*x)*640/8, (1 + 2*y)*480/8);
+                    ok(color_match(color, ref_color, 18),
+                       "Format %s: Got color 0x%08x for pixel (%d/%d)/(%d/%d), pixel %d %d, expected 0x%08x\n",
+                       fmt_string, color, x, 4, y, 4, (1 + 2*x)*640/8, (1 + 2*y)*480/8, ref_color);
+                }
+            }
+            hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
+
+            ok(SUCCEEDED(hr), "Present failed with 0x%08x\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