[PATCH 4/5] d3d8/tests: Add tests for block-based volume formats.

Stefan Dösinger stefan at codeweavers.com
Thu Sep 19 04:02:56 CDT 2013


---
 dlls/d3d8/tests/device.c | 361 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 361 insertions(+)

diff --git a/dlls/d3d8/tests/device.c b/dlls/d3d8/tests/device.c
index 83cdaf9..c16ee63 100644
--- a/dlls/d3d8/tests/device.c
+++ b/dlls/d3d8/tests/device.c
@@ -5373,6 +5373,366 @@ static void test_create_rt_ds_fail(void)
     DestroyWindow(window);
 }
 
+static void test_volume_blocks(void)
+{
+    IDirect3DDevice8 *device;
+    IDirect3D8 *d3d8;
+    UINT refcount;
+    HWND window;
+    HRESULT hr;
+    D3DCAPS8 caps;
+    IDirect3DVolumeTexture8 *texture;
+    unsigned int w, h, d, i, j;
+    static const struct
+    {
+        D3DFORMAT fmt;
+        const char *name;
+        unsigned int block_width;
+        unsigned int block_height;
+        unsigned int block_depth;
+        unsigned int block_size;
+        BOOL broken;
+        BOOL create_size_checked, core_fmt;
+    }
+    formats[] =
+    {
+        /* Scratch volumes enforce DXTn block locks, unlike their surface counterparts.
+         * ATI2N and YUV blocks are not enforced on any tested card (r200, gtx 460). */
+        {D3DFMT_DXT1,                 "D3DFMT_DXT1", 4, 4, 1, 8,  FALSE, TRUE,  TRUE },
+        {D3DFMT_DXT2,                 "D3DFMT_DXT2", 4, 4, 1, 16, FALSE, TRUE,  TRUE },
+        {D3DFMT_DXT3,                 "D3DFMT_DXT3", 4, 4, 1, 16, FALSE, TRUE,  TRUE },
+        {D3DFMT_DXT4,                 "D3DFMT_DXT4", 4, 4, 1, 16, FALSE, TRUE,  TRUE },
+        {D3DFMT_DXT5,                 "D3DFMT_DXT5", 4, 4, 1, 16, FALSE, TRUE,  TRUE },
+        {D3DFMT_DXT5,                 "D3DFMT_DXT5", 4, 4, 1, 16, FALSE, TRUE,  TRUE },
+        /* ATI2N has 2x2 blocks on all AMD cards and Geforce 7 cards,
+         * which doesn't match the format spec. On newer Nvidia cards
+         * it has the correct 4x4 block size */
+        {MAKEFOURCC('A','T','I','2'), "ATI2N",       4, 4, 1, 16, TRUE,  FALSE, FALSE},
+        {D3DFMT_YUY2,                 "D3DFMT_YUY2", 2, 1, 1, 4,  TRUE,  FALSE, TRUE },
+        {D3DFMT_UYVY,                 "D3DFMT_UYVY", 2, 1, 1, 4,  TRUE,  FALSE, TRUE },
+    };
+    static const struct
+    {
+        D3DPOOL pool;
+        const char *name;
+        BOOL need_driver_support, need_runtime_support;
+    }
+    create_tests[] =
+    {
+        {D3DPOOL_DEFAULT,       "D3DPOOL_DEFAULT",  TRUE,  FALSE},
+        {D3DPOOL_SCRATCH,       "D3DPOOL_SCRATCH",  FALSE, TRUE },
+        {D3DPOOL_SYSTEMMEM,     "D3DPOOL_SYSTEMMEM",TRUE,  FALSE},
+        {D3DPOOL_MANAGED,       "D3DPOOL_MANAGED",  TRUE,  FALSE},
+    };
+    static const struct
+    {
+        unsigned int x, y, z, x2, y2, z2;
+    }
+    offset_tests[] =
+    {
+        {0, 0, 0, 8, 8, 8},
+        {0, 0, 3, 8, 8, 8},
+        {0, 4, 0, 8, 8, 8},
+        {0, 4, 3, 8, 8, 8},
+        {4, 0, 0, 8, 8, 8},
+        {4, 0, 3, 8, 8, 8},
+        {4, 4, 0, 8, 8, 8},
+        {4, 4, 3, 8, 8, 8},
+    };
+    D3DBOX box;
+    D3DLOCKED_BOX locked_box;
+    BYTE *base;
+    INT expected_row_pitch, expected_slice_pitch;
+    BOOL support, support_2d;
+    BOOL pow2;
+    unsigned int offset, expected_offset;
+
+    if (!(d3d8 = pDirect3DCreate8(D3D_SDK_VERSION)))
+    {
+        skip("Failed to create IDirect3D8 object, skipping tests.\n");
+        return;
+    }
+
+    window = CreateWindowA("static", "d3d8_test", WS_OVERLAPPEDWINDOW,
+            0, 0, 640, 480, 0, 0, 0, 0);
+    if (!(device = create_device(d3d8, window, window, TRUE)))
+    {
+        skip("Failed to create a D3D device, skipping tests.\n");
+        IDirect3D8_Release(d3d8);
+        DestroyWindow(window);
+        return;
+    }
+    hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
+    ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
+    pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP_POW2);
+
+    for (i = 0; i < sizeof(formats) / sizeof(*formats); i++)
+    {
+        hr = IDirect3D8_CheckDeviceFormat(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
+                0, D3DRTYPE_VOLUMETEXTURE, formats[i].fmt);
+        support = SUCCEEDED(hr);
+        hr = IDirect3D8_CheckDeviceFormat(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
+                0, D3DRTYPE_TEXTURE, formats[i].fmt);
+        support_2d = SUCCEEDED(hr);
+
+        /* Test creation restrictions */
+        for (w = 1; w <= 8; w++)
+        {
+            for (h = 1; h <= 8; h++)
+            {
+                for (d = 1; d <= 8; d++)
+                {
+                    HRESULT expect_hr;
+                    BOOL size_is_pow2;
+                    BOOL block_aligned = TRUE;
+
+                    if (w & (formats[i].block_width - 1) || h & (formats[i].block_height - 1))
+                        block_aligned = FALSE;
+
+                    size_is_pow2 = !((w & (w - 1)) || (h & (h - 1)) || (d & (d - 1)));
+
+                    for (j = 0; j < sizeof(create_tests) / sizeof(*create_tests); j++)
+                    {
+                        BOOL may_succeed = FALSE;
+                        BOOL todo = FALSE;
+
+                        if (create_tests[j].need_runtime_support && !formats[i].core_fmt && !support)
+                            expect_hr = D3DERR_INVALIDCALL;
+                        else if (formats[i].create_size_checked && !block_aligned)
+                            expect_hr = D3DERR_INVALIDCALL;
+                        else if (pow2 && !size_is_pow2 && create_tests[j].need_driver_support)
+                            expect_hr = D3DERR_INVALIDCALL;
+                        else if (create_tests[j].need_driver_support && !support)
+                        {
+                            todo = support_2d;
+                            expect_hr = D3DERR_INVALIDCALL;
+                        }
+                        else
+                            expect_hr = D3D_OK;
+
+                        texture = (IDirect3DVolumeTexture8 *)0xdeadbeef;
+                        hr = IDirect3DDevice8_CreateVolumeTexture(device, w, h, d, 1, 0,
+                                formats[i].fmt, create_tests[j].pool, &texture);
+
+                        /* Wine knows about ATI2N and happily creates a scratch resource even if GL
+                         * does not support it. Accept scratch creation of extension formats on
+                         * Windows as well if it occurs. We don't really care if e.g. a Windows 7
+                         * on an r200 GPU creates scratch ATI2N texture even though the card doesn't
+                         * support it. */
+                        if (!formats[i].core_fmt && !support && FAILED(expect_hr))
+                            may_succeed = TRUE;
+
+                        if (todo)
+                        {
+                            todo_wine ok(hr == expect_hr || ((SUCCEEDED(hr) && may_succeed)),
+                                    "Got unexpected hr %#x for format %s, pool %s, size %ux%ux%u.\n",
+                                    hr, formats[i].name, create_tests[j].name, w, h, d);
+                        }
+                        else
+                        {
+                            ok(hr == expect_hr || ((SUCCEEDED(hr) && may_succeed)),
+                                    "Got unexpected hr %#x for format %s, pool %s, size %ux%ux%u.\n",
+                                    hr, formats[i].name, create_tests[j].name, w, h, d);
+                        }
+
+                        if (FAILED(hr))
+                            ok(texture == NULL, "Got texture ptr %p, expected NULL.\n", texture);
+                        else
+                            IDirect3DVolumeTexture8_Release(texture);
+                    }
+                }
+            }
+        }
+
+        if (!support && !formats[i].core_fmt)
+            continue;
+
+        hr = IDirect3DDevice8_CreateVolumeTexture(device, 24, 8, 8, 1, 0,
+                formats[i].fmt, D3DPOOL_SCRATCH, &texture);
+        ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
+
+        /* Test lockrect offset */
+        for (j = 0; j < sizeof(offset_tests) / sizeof(*offset_tests); j++)
+        {
+            unsigned int bytes_per_pixel;
+            bytes_per_pixel = formats[i].block_size / (formats[i].block_width * formats[i].block_height);
+
+            hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, NULL, 0);
+            ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
+
+            base = locked_box.pBits;
+            if (formats[i].broken)
+            {
+                expected_row_pitch = bytes_per_pixel * 24;
+            }
+            else
+            {
+                expected_row_pitch = (24 /* tex width */ + formats[i].block_height - 1) / formats[i].block_width
+                        * formats[i].block_size;
+            }
+            ok(locked_box.RowPitch == expected_row_pitch, "Got unexpected row pitch %d for format %s, expected %d.\n",
+                    locked_box.RowPitch, formats[i].name, expected_row_pitch);
+
+            if (formats[i].broken)
+            {
+                expected_slice_pitch = expected_row_pitch * 8;
+            }
+            else
+            {
+                expected_slice_pitch = (8 /* tex height */ + formats[i].block_depth - 1) / formats[i].block_height
+                        * expected_row_pitch;
+            }
+            ok(locked_box.SlicePitch == expected_slice_pitch,
+                    "Got unexpected slice pitch %d for format %s, expected %d.\n",
+                    locked_box.SlicePitch, formats[i].name, expected_slice_pitch);
+
+            hr = IDirect3DVolumeTexture8_UnlockBox(texture, 0);
+            ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x, j %u.\n", hr, j);
+
+            box.Left = offset_tests[j].x;
+            box.Top = offset_tests[j].y;
+            box.Front = offset_tests[j].z;
+            box.Right = offset_tests[j].x2;
+            box.Bottom = offset_tests[j].y2;
+            box.Back = offset_tests[j].z2;
+            hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, &box, 0);
+            ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x, j %u.\n", hr, j);
+
+            offset = (BYTE *)locked_box.pBits - base;
+            if (formats[i].broken)
+            {
+                expected_offset = box.Front * expected_slice_pitch
+                        + box.Top * expected_row_pitch
+                        + box.Left * bytes_per_pixel;
+            }
+            else
+            {
+                expected_offset = (box.Front / formats[i].block_depth) * expected_slice_pitch
+                        + (box.Top / formats[i].block_height) * expected_row_pitch
+                        + (box.Left / formats[i].block_width) * formats[i].block_size;
+            }
+            ok(offset == expected_offset, "Got unexpected offset %u for format %s, expected %u, box start %ux%ux%u.\n",
+                    offset, formats[i].name, expected_offset, box.Left, box.Top, box.Front);
+
+            hr = IDirect3DVolumeTexture8_UnlockBox(texture, 0);
+            ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
+        }
+
+        /* Test partial block locks */
+        box.Front = 0;
+        box.Back = 1;
+        if (formats[i].block_width > 1)
+        {
+            box.Left = formats[i].block_width >> 1;
+            box.Top = 0;
+            box.Right = formats[i].block_width;
+            box.Bottom = formats[i].block_height;
+            hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, &box, 0);
+            ok(FAILED(hr) || broken(formats[i].broken),
+                    "Partial block lock succeeded, expected failure, format %s.\n",
+                    formats[i].name);
+            if (SUCCEEDED(hr))
+            {
+                hr = IDirect3DVolumeTexture8_UnlockBox(texture, 0);
+                ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
+            }
+
+            box.Left = 0;
+            box.Top = 0;
+            box.Right = formats[i].block_width >> 1;
+            box.Bottom = formats[i].block_height;
+            hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, &box, 0);
+            ok(FAILED(hr) || broken(formats[i].broken),
+                    "Partial block lock succeeded, expected failure, format %s.\n",
+                    formats[i].name);
+            if (SUCCEEDED(hr))
+            {
+                hr = IDirect3DVolumeTexture8_UnlockBox(texture, 0);
+                ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
+            }
+        }
+
+        if (formats[i].block_height > 1)
+        {
+            box.Left = 0;
+            box.Top = formats[i].block_height >> 1;
+            box.Right = formats[i].block_width;
+            box.Bottom = formats[i].block_height;
+            hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, &box, 0);
+            ok(FAILED(hr) || broken(formats[i].broken),
+                    "Partial block lock succeeded, expected failure, format %s.\n",
+                    formats[i].name);
+            if (SUCCEEDED(hr))
+            {
+                hr = IDirect3DVolumeTexture8_UnlockBox(texture, 0);
+                ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
+            }
+
+            box.Left = 0;
+            box.Top = 0;
+            box.Right = formats[i].block_width;
+            box.Bottom = formats[i].block_height >> 1;
+            hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, &box, 0);
+            ok(FAILED(hr) || broken(formats[i].broken),
+                    "Partial block lock succeeded, expected failure, format %s.\n",
+                    formats[i].name);
+            if (SUCCEEDED(hr))
+            {
+                hr = IDirect3DVolumeTexture8_UnlockBox(texture, 0);
+                ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
+            }
+        }
+
+        /* Test full block lock */
+        box.Left = 0;
+        box.Top = 0;
+        box.Right = formats[i].block_width;
+        box.Bottom = formats[i].block_height;
+        hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, &box, 0);
+        ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
+        hr = IDirect3DVolumeTexture8_UnlockBox(texture, 0);
+        ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
+
+        IDirect3DVolumeTexture8_Release(texture);
+
+        /* Test mipmap locks. Don't do this with ATI2N, AMD warns that the runtime
+         * does not allocate surfaces smaller than the blocksize properly. */
+        if ((formats[i].block_width > 1 || formats[i].block_height > 1) && formats[i].core_fmt)
+        {
+            hr = IDirect3DDevice8_CreateVolumeTexture(device, formats[i].block_width, formats[i].block_height,
+                    2, 2, 0, formats[i].fmt, D3DPOOL_SCRATCH, &texture);
+
+            hr = IDirect3DVolumeTexture8_LockBox(texture, 1, &locked_box, NULL, 0);
+            ok(SUCCEEDED(hr), "Failed to lock volume texture mipmap, hr %#x.\n", hr);
+            hr = IDirect3DVolumeTexture8_UnlockBox(texture, 1);
+            ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
+
+            box.Left = box.Top = box.Front = 0;
+            box.Right = formats[i].block_width == 1 ? 1 : formats[i].block_width >> 1;
+            box.Bottom = formats[i].block_height == 1 ? 1 : formats[i].block_height >> 1;
+            box.Back = 1;
+            hr = IDirect3DVolumeTexture8_LockBox(texture, 1, &locked_box, &box, 0);
+            ok(SUCCEEDED(hr), "Failed to lock volume texture mipmap, hr %#x.\n", hr);
+            hr = IDirect3DVolumeTexture8_UnlockBox(texture, 1);
+            ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
+
+            box.Right = formats[i].block_width;
+            box.Bottom = formats[i].block_height;
+            hr = IDirect3DVolumeTexture8_LockBox(texture, 1, &locked_box, &box, 0);
+            ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
+            if (SUCCEEDED(hr))
+                IDirect3DVolumeTexture8_UnlockBox(texture, 1);
+
+            IDirect3DVolumeTexture8_Release(texture);
+        }
+    }
+
+    refcount = IDirect3DDevice8_Release(device);
+    ok(!refcount, "Device has %u references left.\n", refcount);
+    IDirect3D8_Release(d3d8);
+    DestroyWindow(window);
+}
+
 START_TEST(device)
 {
     HMODULE d3d8_handle = LoadLibraryA( "d3d8.dll" );
@@ -5453,6 +5813,7 @@ START_TEST(device)
         test_volume_locking();
         test_update_volumetexture();
         test_create_rt_ds_fail();
+        test_volume_blocks();
     }
     UnregisterClassA("d3d8_test_wc", GetModuleHandleA(NULL));
 }
-- 
1.8.1.5




More information about the wine-patches mailing list