Signed-off-by: Stefan Dösinger <stefan(a)codeweavers.com>
---
dlls/d3d8/tests/visual.c | 483 +++++++++++++++++++++++++++++++++++++++
1 file changed, 483 insertions(+)
diff --git a/dlls/d3d8/tests/visual.c b/dlls/d3d8/tests/visual.c
index df4dd0029a6..29baf07398c 100644
--- a/dlls/d3d8/tests/visual.c
+++ b/dlls/d3d8/tests/visual.c
@@ -11292,6 +11292,488 @@ static void test_dynamic_map_synchronization(void)
DestroyWindow(window);
}
+static void test_filling_convention(void)
+{
+ static const DWORD colour_bottom = 0x00ffff00;
+ static const DWORD colour_clear = 0x000000ff;
+ static const DWORD colour_right = 0x00000000;
+ static const DWORD colour_left = 0x00ff0000;
+ static const DWORD colour_top = 0x0000ff00;
+ IDirect3DSurface8 *rt, *backbuffer, *cur;
+ struct surface_readback rb;
+ IDirect3DDevice8 *device;
+ unsigned int i, j, x, y;
+ DWORD colour, expected;
+ DWORD shader = 0;
+ IDirect3D8 *d3d;
+ ULONG refcount;
+ D3DCAPS8 caps;
+ HWND window;
+ HRESULT hr;
+ BOOL todo;
+
+ static const unsigned int vp_size = 8;
+ const D3DVIEWPORT8 vp = { 0, 0, vp_size, vp_size, 0.0, 1.0 };
+ static const DWORD vs_code[] =
+ {
+ 0xfffe0101, /* vs_1_1 */
+ 0x00000001, 0xc00f0000, 0x90e40000, /* mov oPos, v0 */
+ 0x00000001, 0xd00f0000, 0x90e40005, /* mov oD0, v5 */
+ 0x0000ffff /* end */
+ };
+ static const DWORD decl[] =
+ {
+ D3DVSD_STREAM(0),
+ D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3),
+ D3DVSD_REG(D3DVSDE_DIFFUSE, D3DVSDT_D3DCOLOR),
+ D3DVSD_END()
+ };
+
+ /* This test data follows the examples in MSDN's
+ * "Rasterization Rules (Direct3D 9)" article. */
+ static const float eps = 1.0f / 512.0f;
+ const struct
+ {
+ struct vec3 position;
+ DWORD diffuse;
+ }
+ center_tris[] =
+ {
+ /* left */
+ {{-2.5f / 4.0f, -1.5f / 4.0f, 0.0f}, colour_left},
+ {{-2.5f / 4.0f, 2.5f / 4.0f, 0.0f}, colour_left},
+ {{-1.5f / 4.0f, 0.5f / 4.0f, 0.0f}, colour_left},
+
+ /* top */
+ {{-1.5f / 4.0f, 0.5f / 4.0f, 0.0f}, colour_top},
+ {{-2.5f / 4.0f, 2.5f / 4.0f, 0.0f}, colour_top},
+ {{-0.5f / 4.0f, 2.5f / 4.0f, 0.0f}, colour_top},
+
+ /* right */
+ {{-0.5f / 4.0f, -1.5f / 4.0f, 0.0f}, colour_right},
+ {{-1.5f / 4.0f, 0.5f / 4.0f, 0.0f}, colour_right},
+ {{-0.5f / 4.0f, 2.5f / 4.0f, 0.0f}, colour_right},
+
+ /* bottom */
+ {{-2.5f / 4.0f, -1.5f / 4.0f, 0.0f}, colour_bottom},
+ {{-1.5f / 4.0f, 0.5f / 4.0f, 0.0f}, colour_bottom},
+ {{-0.5f / 4.0f, -1.5f / 4.0f, 0.0f}, colour_bottom},
+
+ },
+ edge_tris[] =
+ {
+ /* left */
+ {{-2.0f / 4.0f, -1.0f / 4.0f, 0.0f}, colour_left},
+ {{-2.0f / 4.0f, 3.0f / 4.0f, 0.0f}, colour_left},
+ {{-1.0f / 4.0f, 1.0f / 4.0f, 0.0f}, colour_left},
+
+ /* top */
+ {{-1.0f / 4.0f, 1.0f / 4.0f, 0.0f}, colour_top},
+ {{-2.0f / 4.0f, 3.0f / 4.0f, 0.0f}, colour_top},
+ {{ 0.0f / 4.0f, 3.0f / 4.0f, 0.0f}, colour_top},
+
+ /* right */
+ {{ 0.0f / 4.0f, -1.0f / 4.0f, 0.0f}, colour_right},
+ {{-1.0f / 4.0f, 1.0f / 4.0f, 0.0f}, colour_right},
+ {{ 0.0f / 4.0f, 3.0f / 4.0f, 0.0f}, colour_right},
+
+ /* bottom */
+ {{-2.0f / 4.0f, -1.0f / 4.0f, 0.0f}, colour_bottom},
+ {{-1.0f / 4.0f, 1.0f / 4.0f, 0.0f}, colour_bottom},
+ {{ 0.0f / 4.0f, -1.0f / 4.0f, 0.0f}, colour_bottom},
+ },
+ nudge_right_tris[] =
+ {
+ /* left */
+ {{eps - 2.0f / 4.0f, -1.0f / 4.0f, 0.0f}, colour_left},
+ {{eps - 2.0f / 4.0f, 3.0f / 4.0f, 0.0f}, colour_left},
+ {{eps - 1.0f / 4.0f, 1.0f / 4.0f, 0.0f}, colour_left},
+
+ /* top */
+ {{eps - 1.0f / 4.0f, 1.0f / 4.0f, 0.0f}, colour_top},
+ {{eps - 2.0f / 4.0f, 3.0f / 4.0f, 0.0f}, colour_top},
+ {{eps - 0.0f / 4.0f, 3.0f / 4.0f, 0.0f}, colour_top},
+
+ /* right */
+ {{eps - 0.0f / 4.0f, -1.0f / 4.0f, 0.0f}, colour_right},
+ {{eps - 1.0f / 4.0f, 1.0f / 4.0f, 0.0f}, colour_right},
+ {{eps - 0.0f / 4.0f, 3.0f / 4.0f, 0.0f}, colour_right},
+
+ /* bottom */
+ {{eps - 2.0f / 4.0f, -1.0f / 4.0f, 0.0f}, colour_bottom},
+ {{eps - 1.0f / 4.0f, 1.0f / 4.0f, 0.0f}, colour_bottom},
+ {{eps - 0.0f / 4.0f, -1.0f / 4.0f, 0.0f}, colour_bottom},
+ },
+ nudge_left_tris[] =
+ {
+ {{-eps - 2.0f / 4.0f, -1.0f / 4.0f, 0.0f}, colour_left},
+ {{-eps - 2.0f / 4.0f, 3.0f / 4.0f, 0.0f}, colour_left},
+ {{-eps - 1.0f / 4.0f, 1.0f / 4.0f, 0.0f}, colour_left},
+
+ /* top */
+ {{-eps - 1.0f / 4.0f, 1.0f / 4.0f, 0.0f}, colour_top},
+ {{-eps - 2.0f / 4.0f, 3.0f / 4.0f, 0.0f}, colour_top},
+ {{-eps - 0.0f / 4.0f, 3.0f / 4.0f, 0.0f}, colour_top},
+
+ /* right */
+ {{-eps - 0.0f / 4.0f, -1.0f / 4.0f, 0.0f}, colour_right},
+ {{-eps - 1.0f / 4.0f, 1.0f / 4.0f, 0.0f}, colour_right},
+ {{-eps - 0.0f / 4.0f, 3.0f / 4.0f, 0.0f}, colour_right},
+
+ /* bottom */
+ {{-eps - 2.0f / 4.0f, -1.0f / 4.0f, 0.0f}, colour_bottom},
+ {{-eps - 1.0f / 4.0f, 1.0f / 4.0f, 0.0f}, colour_bottom},
+ {{-eps - 0.0f / 4.0f, -1.0f / 4.0f, 0.0f}, colour_bottom},
+ },
+ nudge_top_tris[] =
+ {
+ /* left */
+ {{-2.0f / 4.0f, eps - 1.0f / 4.0f, 0.0f}, colour_left},
+ {{-2.0f / 4.0f, eps + 3.0f / 4.0f, 0.0f}, colour_left},
+ {{-1.0f / 4.0f, eps + 1.0f / 4.0f, 0.0f}, colour_left},
+
+ /* top */
+ {{-1.0f / 4.0f, eps + 1.0f / 4.0f, 0.0f}, colour_top},
+ {{-2.0f / 4.0f, eps + 3.0f / 4.0f, 0.0f}, colour_top},
+ {{ 0.0f / 4.0f, eps + 3.0f / 4.0f, 0.0f}, colour_top},
+
+ /* right */
+ {{ 0.0f / 4.0f, eps - 1.0f / 4.0f, 0.0f}, colour_right},
+ {{-1.0f / 4.0f, eps + 1.0f / 4.0f, 0.0f}, colour_right},
+ {{ 0.0f / 4.0f, eps + 3.0f / 4.0f, 0.0f}, colour_right},
+
+ /* bottom */
+ {{-2.0f / 4.0f, eps - 1.0f / 4.0f, 0.0f}, colour_bottom},
+ {{-1.0f / 4.0f, eps + 1.0f / 4.0f, 0.0f}, colour_bottom},
+ {{ 0.0f / 4.0f, eps - 1.0f / 4.0f, 0.0f}, colour_bottom},
+ },
+ nudge_bottom_tris[] =
+ {
+ /* left */
+ {{-2.0f / 4.0f, -eps - 1.0f / 4.0f, 0.0f}, colour_left},
+ {{-2.0f / 4.0f, -eps + 3.0f / 4.0f, 0.0f}, colour_left},
+ {{-1.0f / 4.0f, -eps + 1.0f / 4.0f, 0.0f}, colour_left},
+
+ /* top */
+ {{-1.0f / 4.0f, -eps + 1.0f / 4.0f, 0.0f}, colour_top},
+ {{-2.0f / 4.0f, -eps + 3.0f / 4.0f, 0.0f}, colour_top},
+ {{ 0.0f / 4.0f, -eps + 3.0f / 4.0f, 0.0f}, colour_top},
+
+ /* right */
+ {{ 0.0f / 4.0f, -eps - 1.0f / 4.0f, 0.0f}, colour_right},
+ {{-1.0f / 4.0f, -eps + 1.0f / 4.0f, 0.0f}, colour_right},
+ {{ 0.0f / 4.0f, -eps + 3.0f / 4.0f, 0.0f}, colour_right},
+
+ /* bottom */
+ {{-2.0f / 4.0f, -eps - 1.0f / 4.0f, 0.0f}, colour_bottom},
+ {{-1.0f / 4.0f, -eps + 1.0f / 4.0f, 0.0f}, colour_bottom},
+ {{ 0.0f / 4.0f, -eps - 1.0f / 4.0f, 0.0f}, colour_bottom},
+ };
+
+ const struct
+ {
+ struct vec4 position;
+ DWORD diffuse;
+ }
+ center_tris_t[] =
+ {
+ /* left */
+ {{ 1.5f, 1.5f, 0.0f, 1.0f}, colour_left},
+ {{ 2.5f, 3.5f, 0.0f, 1.0f}, colour_left},
+ {{ 1.5f, 5.5f, 0.0f, 1.0f}, colour_left},
+
+ /* top */
+ {{ 1.5f, 1.5f, 0.0f, 1.0f}, colour_top},
+ {{ 3.5f, 1.5f, 0.0f, 1.0f}, colour_top},
+ {{ 2.5f, 3.5f, 0.0f, 1.0f}, colour_top},
+
+ /* right */
+ {{ 3.5f, 1.5f, 0.0f, 1.0f}, colour_right},
+ {{ 3.5f, 5.5f, 0.0f, 1.0f}, colour_right},
+ {{ 2.5f, 3.5f, 0.0f, 1.0f}, colour_right},
+
+ /* bottom */
+ {{ 2.5f, 3.5f, 0.0f, 1.0f}, colour_bottom},
+ {{ 3.5f, 5.5f, 0.0f, 1.0f}, colour_bottom},
+ {{ 1.5f, 5.5f, 0.0f, 1.0f}, colour_bottom},
+ },
+ edge_tris_t[] =
+ {
+ /* left */
+ {{ 2.0f, 1.0f, 0.0f, 1.0f}, colour_left},
+ {{ 3.0f, 3.0f, 0.0f, 1.0f}, colour_left},
+ {{ 2.0f, 5.0f, 0.0f, 1.0f}, colour_left},
+
+ /* top */
+ {{ 2.0f, 1.0f, 0.0f, 1.0f}, colour_top},
+ {{ 4.0f, 1.0f, 0.0f, 1.0f}, colour_top},
+ {{ 3.0f, 3.0f, 0.0f, 1.0f}, colour_top},
+
+ /* right */
+ {{ 4.0f, 1.0f, 0.0f, 1.0f}, colour_right},
+ {{ 4.0f, 5.0f, 0.0f, 1.0f}, colour_right},
+ {{ 3.0f, 3.0f, 0.0f, 1.0f}, colour_right},
+
+ /* bottom */
+ {{ 3.0f, 3.0f, 0.0f, 1.0f}, colour_bottom},
+ {{ 4.0f, 5.0f, 0.0f, 1.0f}, colour_bottom},
+ {{ 2.0f, 5.0f, 0.0f, 1.0f}, colour_bottom},
+ };
+
+ const struct
+ {
+ const void *geometry;
+ size_t stride;
+ DWORD fvf;
+ const char *expected[8];
+ }
+ tests[] =
+ {
+ {
+ center_tris,
+ sizeof(center_tris[0]),
+ D3DFVF_XYZ | D3DFVF_DIFFUSE,
+ {
+ " ",
+ " ",
+ " TT ",
+ " LR ",
+ " LR ",
+ " BB ",
+ " ",
+ " "
+ }
+ },
+ {
+ edge_tris,
+ sizeof(edge_tris[0]),
+ D3DFVF_XYZ | D3DFVF_DIFFUSE,
+ {
+ " ",
+ " TT ",
+ " LT ",
+ " LR ",
+ " LB ",
+ " ",
+ " ",
+ " "
+ }
+ },
+ {
+ nudge_right_tris,
+ sizeof(nudge_right_tris[0]),
+ D3DFVF_XYZ | D3DFVF_DIFFUSE,
+ {
+ " ",
+ " TT ",
+ " TR ",
+ " LR ",
+ " BR ",
+ " ",
+ " ",
+ " "
+ }
+ },
+ {
+ nudge_left_tris,
+ sizeof(nudge_left_tris[0]),
+ D3DFVF_XYZ | D3DFVF_DIFFUSE,
+ {
+ " ",
+ " TT ",
+ " LT ",
+ " LR ",
+ " LB ",
+ " ",
+ " ",
+ " "
+ }
+ },
+ {
+ nudge_top_tris,
+ sizeof(nudge_top_tris[0]),
+ D3DFVF_XYZ | D3DFVF_DIFFUSE,
+ {
+ " ",
+ " LT ",
+ " LT ",
+ " LB ",
+ " LB ",
+ " ",
+ " ",
+ " "
+ }
+ },
+ {
+ nudge_bottom_tris,
+ sizeof(nudge_bottom_tris[0]),
+ D3DFVF_XYZ | D3DFVF_DIFFUSE,
+ {
+ " ",
+ " ",
+ " LT ",
+ " Lt ",
+ " LB ",
+ " lB ",
+ " ",
+ " "
+ }
+ },
+ {
+ center_tris_t,
+ sizeof(center_tris_t[0]),
+ D3DFVF_XYZRHW | D3DFVF_DIFFUSE,
+ {
+ " ",
+ " ",
+ " TT ",
+ " LR ",
+ " LR ",
+ " BB ",
+ " ",
+ " "
+ }
+ },
+ {
+ edge_tris_t,
+ sizeof(edge_tris_t[0]),
+ D3DFVF_XYZRHW | D3DFVF_DIFFUSE,
+ {
+ " ",
+ " TT ",
+ " LT ",
+ " LR ",
+ " LB ",
+ " ",
+ " ",
+ " "
+ }
+ },
+ };
+
+ window = create_window();
+ d3d = Direct3DCreate8(D3D_SDK_VERSION);
+ ok(!!d3d, "Failed to create a D3D object.\n");
+
+ if (!(device = create_device(d3d, window, window, TRUE)))
+ {
+ skip("Failed to create a 3D device.\n");
+ IDirect3D8_Release(d3d);
+ DestroyWindow(window);
+ return;
+ }
+
+ hr = IDirect3DDevice8_CreateRenderTarget(device, vp_size, vp_size,
+ D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, FALSE, &rt);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+ hr = IDirect3DDevice8_GetBackBuffer(device, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+
+ hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+ if (caps.VertexShaderVersion >= D3DVS_VERSION(1, 1))
+ {
+ hr = IDirect3DDevice8_CreateVertexShader(device, decl, vs_code, &shader, 0);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+ }
+ else
+ skip("Skipping vertex shader codepath in filling convention test.\n");
+
+ hr = IDirect3DDevice8_SetRenderState(device, D3DRS_LIGHTING, FALSE);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+ hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZENABLE, D3DZB_FALSE);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+
+ for (i = 0; i < ARRAY_SIZE(tests); ++i)
+ {
+ /* Run tests with shader and fixed function vertex processing if shaders are
+ * supported. There's no point in running the XYZRHW tests with a VS though. */
+ if (shader && ((tests[i].fvf & D3DFVF_POSITION_MASK) == D3DFVF_XYZ))
+ j = 0;
+ else
+ j = 2;
+
+ for (; j < 4; ++j)
+ {
+ cur = (j & 1) ? rt : backbuffer;
+
+ hr = IDirect3DDevice8_SetVertexShader(device, (j & 2) ? tests[i].fvf : shader);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+
+ hr = IDirect3DDevice8_SetRenderTarget(device, cur, NULL);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+ hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET, colour_clear, 0.0f, 0);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+ hr = IDirect3DDevice8_SetViewport(device, &vp);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+
+ hr = IDirect3DDevice8_BeginScene(device);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+ hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLELIST, 4, tests[i].geometry, tests[i].stride);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+ hr = IDirect3DDevice8_EndScene(device);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+
+ get_rt_readback(cur, &rb);
+ for (y = 0; y < 8; y++)
+ {
+ for (x = 0; x < 8; x++)
+ {
+ todo = FALSE;
+ switch (tests[i].expected[y][x])
+ {
+ case 'l': todo = TRUE;
+ case 'L':
+ expected = colour_left;
+ break;
+ case 't': todo = TRUE;
+ case 'T':
+ expected = colour_top;
+ break;
+ case 'r': todo = TRUE;
+ case 'R':
+ expected = colour_right;
+ break;
+ case 'b': todo = TRUE;
+ case 'B':
+ expected = colour_bottom;
+ break;
+ case ' ':
+ expected = colour_clear;
+ break;
+ default:
+ ok(0, "Unexpected entry in expected test char\n");
+ expected = 0xdeadbeef;
+ }
+ colour = get_readback_color(&rb, x, y);
+ /* The nudge-to-bottom test fails on cards that give us a bottom-left
+ * filling convention. The cause isn't the bottom part of the filling
+ * convention, but because wined3d will nudge geometry to the left to
+ * keep diagonals (the 'R' in test case 'edge_tris') intact. */
+ todo_wine_if(todo && !color_match(colour, expected, 1))
+ ok(color_match(colour, expected, 1), "Got unexpected colour %08x, %ux%u, case %u, j %u.\n",
+ colour, x, y, i, j);
+ }
+ }
+ release_surface_readback(&rb);
+
+ /* IDirect3DDevice8::CopyRects can't stretch, so don't bother making the offscreen surface
+ * visible. Use the d3d9 test if you need to see visual output. */
+ hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
+ ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+ }
+ }
+
+ if (shader)
+ IDirect3DDevice8_DeleteVertexShader(device, shader);
+ IDirect3DSurface8_Release(backbuffer);
+ IDirect3DSurface8_Release(rt);
+ refcount = IDirect3DDevice8_Release(device);
+ ok(!refcount, "Device has %u references left.\n", refcount);
+ IDirect3D8_Release(d3d);
+ DestroyWindow(window);
+}
+
START_TEST(visual)
{
D3DADAPTER_IDENTIFIER8 identifier;
@@ -11371,4 +11853,5 @@ START_TEST(visual)
test_desktop_window();
test_sample_mask();
test_dynamic_map_synchronization();
+ test_filling_convention();
}
--
2.32.0