[11/11] ddraw/tests: Add assorted D3D7 DrawPrimitive/visual tests.

Octavian Voicu octavian.voicu at gmail.com
Mon Nov 7 16:27:14 CST 2011


Similar to the D3D3 tests, except for D3D7 specific features:
- Switch to IDirect3DDevice7 interface.
- Use IDirect3DDevice7::Clear instead of Blt with DDBLT_COLORFILL.
- Use D3DLIGHT7/D3DMATERIAL7 for setting lights and materials.
- Test that D3DDP_DONOTLIGHT is ignored and D3DRENDERSTATE_LIGHTING works.

--
Note that this test uses fullscreen mode and rendering is done directly
on the primary surface. Wine doesn't fully support that yet, so nothing
is visible on the screen.
---
 dlls/ddraw/tests/visual.c |  204 +++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 204 insertions(+), 0 deletions(-)

diff --git a/dlls/ddraw/tests/visual.c b/dlls/ddraw/tests/visual.c
index 49cd23d..1a4ae78 100644
--- a/dlls/ddraw/tests/visual.c
+++ b/dlls/ddraw/tests/visual.c
@@ -1132,6 +1132,209 @@ static void rhw_zero_test(IDirect3DDevice7 *device)
     ok(color == 0, "Got color %08x, expected 00000000\n", color);
 }
 
+static void drawprimitive_test(IDirect3DDevice7 *device)
+{
+    enum {
+        BLACK   = 0x000000,
+        BLUE    = 0x0000ff,
+        GREEN   = 0x00ff00,
+        GRAY    = 0x808080,
+        YELLOW2 = 0x808000,
+        RED     = 0xff0000,
+        YELLOW  = 0xffff00,
+        WHITE   = 0xffffff,
+    };
+    D3DVERTEX vertices[] = { /* bottom-left corner of screen */
+        /*    x       y      z     nx     ny     nz     tu     tv */
+        { {-1.f}, {-1.f}, {0.f}, {0.f}, {0.f}, {1.f}, {0.f}, {0.f} },
+        { { 0.f}, {-1.f}, {0.f}, {0.f}, {0.f}, {1.f}, {0.f}, {0.f} },
+        { {-1.f}, { 0.f}, {0.f}, {0.f}, {0.f}, {1.f}, {0.f}, {0.f} },
+        { { 0.f}, { 0.f}, {0.f}, {0.f}, {0.f}, {1.f}, {0.f}, {0.f} }
+    };
+    DWORD fvf = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_SPECULAR;
+    struct {
+        D3DVALUE x;
+        D3DVALUE y;
+        D3DVALUE z;
+        D3DVALUE nx;
+        D3DVALUE ny;
+        D3DVALUE nz;
+        D3DCOLOR diffuse;
+        D3DCOLOR specular;
+    } fvfvertices[] = { /* bottom-right corner of screen */
+        /*  x     y    z   nx   ny   nz    diff    spec */
+        { 0.f, -1.f, 0.f, 0.f, 0.f, 1.f, YELLOW, YELLOW },
+        { 1.f, -1.f, 0.f, 0.f, 0.f, 1.f, YELLOW, YELLOW },
+        { 0.f,  0.f, 0.f, 0.f, 0.f, 1.f, YELLOW, YELLOW },
+        { 1.f,  0.f, 0.f, 0.f, 0.f, 1.f, YELLOW, YELLOW }
+    };
+    D3DLVERTEX lvertices[] = { /* top-left corner of screen */
+        /*    x       y      z   ?    diff     spec     tu     tv */
+        { {-1.f}, { 0.f}, {0.f}, 0, {GREEN}, {GREEN}, {0.f}, {0.f} },
+        { { 0.f}, { 0.f}, {0.f}, 0, {GREEN}, {GREEN}, {0.f}, {0.f} },
+        { {-1.f}, { 1.f}, {0.f}, 0, {GREEN}, {GREEN}, {0.f}, {0.f} },
+        { { 0.f}, { 1.f}, {0.f}, 0, {GREEN}, {GREEN}, {0.f}, {0.f} }
+    };
+    D3DTLVERTEX tlvertices[] = { /* top-right corner of screen */
+        /*    sx       sy     sz    rhw    diff    spec     tu     tv */
+        { {320.f}, {  0.f}, {0.f}, {1.f}, {BLUE}, {BLUE}, {0.f}, {0.f} },
+        { {640.f}, {  0.f}, {0.f}, {1.f}, {BLUE}, {BLUE}, {0.f}, {0.f} },
+        { {320.f}, {240.f}, {0.f}, {1.f}, {BLUE}, {BLUE}, {0.f}, {0.f} },
+        { {640.f}, {240.f}, {0.f}, {1.f}, {BLUE}, {BLUE}, {0.f}, {0.f} }
+    };
+    /* Triangles are drawn on the screen as shown below. Number shown in each
+       triangle is the index for the expected[] array bellow.
+       -----------
+       | \ 5| \ 7|
+       |4 \ |6 \ |
+       -----------
+       | \ 1| \ 3|
+       |0 \ |2 \ |
+       ----------- */
+    DWORD expected[] = { WHITE, GRAY, YELLOW, YELLOW2, GREEN, BLACK, BLUE, BLUE };
+    UINT i, x, y, xgrid[] = {1,2,4,5,1,2,4,5}, ygrid[] = {5,4,5,4,2,1,2,1};
+    D3DLIGHT7 light;
+    D3DMATERIAL7 oldmat, mat;
+    HRESULT hr;
+    DWORD oldcull, oldlighting, val, color;
+
+    /* Setup a diffuse directional gray light, perpendicular on the triangles. */
+    memset(&light, 0, sizeof(D3DLIGHT7));
+    light.dltType = D3DLIGHT_DIRECTIONAL;
+    light.dcvDiffuse.r = .5f;
+    light.dcvDiffuse.g = .5f;
+    light.dcvDiffuse.b = .5f;
+    light.dcvDiffuse.a = 1.f;
+    light.dvDirection.x = 0.f;
+    light.dvDirection.y = 0.f;
+    light.dvDirection.z = -1.f;
+    hr = IDirect3DDevice7_SetLight(device, 0, &light);
+    ok(hr == D3D_OK, "SetLight returned: %08x\n", hr);
+    hr = IDirect3DDevice7_LightEnable(device, 0, TRUE);
+    ok(hr == D3D_OK, "LightEnable returned: %08x\n", hr);
+
+    /* Use a material that reflects only diffuse light. */
+    hr = IDirect3DDevice7_GetMaterial(device, &oldmat);
+    ok(hr == D3D_OK, "GetMaterial returned: %08x\n", hr);
+    memset(&mat, 0, sizeof(mat));
+    mat.dcvDiffuse.r = 1.f;
+    mat.dcvDiffuse.g = 1.f;
+    mat.dcvDiffuse.b = 1.f;
+    mat.dcvDiffuse.a = 1.f;
+    hr = IDirect3DDevice7_SetMaterial(device, &mat);
+    ok(hr == D3D_OK, "SetMaterial returned: %08x\n", hr);
+
+    /* Fill entire surface with red. */
+    hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff000000 | RED, 0.0, 0);
+    ok(hr == D3D_OK, "Clear returned: %08x\n", hr);
+
+    /* Make sure getPixelColor works correctly. */
+    color = getPixelColor(device, 320, 240);
+    ok(color == RED, "getPixelColor returned: %08x\n", color);
+
+    hr = IDirect3DDevice7_BeginScene(device);
+    ok(hr == D3D_OK, "BeginScene returned: %08x\n", hr);
+
+    if (SUCCEEDED(hr)) {
+        /* Don't cull back faces to reduce number of vertices we need to declare. */
+        hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_CULLMODE, &oldcull);
+        ok(hr == D3D_OK, "GetRenderState returned: %08x\n", hr);
+        hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
+        ok(hr == D3D_OK, "SetRenderState returned: %08x\n", hr);
+
+        /* Make sure COLORVERTEX is enabled and DIFFUSEMATERIALSOURCE is COLOR1. */
+        hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_COLORVERTEX, TRUE);
+        ok(hr == D3D_OK, "SetRenderState returned: %08x\n", hr);
+        hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1);
+        ok(hr == D3D_OK, "SetRenderState returned: %08x\n", hr);
+
+        /* Disable lighting initially. */
+        hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_LIGHTING, &oldlighting);
+        ok(hr == D3D_OK, "GetRenderState returned: %08x\n", hr);
+        hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
+        ok(hr == D3D_OK, "SetRenderState returned: %08x\n", hr);
+        hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_LIGHTING, &val);
+        ok(hr == D3D_OK, "GetRenderState returned: %08x\n", hr);
+        ok(val == FALSE, "D3DRENDERSTATE_LIGHTING is: %08x\n", val);
+
+        /* Triangle 0 -- D3DFVF_VERTEX (vertices with normals, but without colors). */
+        hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLELIST, D3DFVF_VERTEX,
+                                            vertices, 3, D3DDP_WAIT);
+        ok(hr == D3D_OK, "DrawPrimitive returned: %08x\n", hr);
+
+        /* Triangle 2 -- custom fvf (vertices with normals and colors). */
+        hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLELIST, fvf,
+                                            fvfvertices, 3, D3DDP_WAIT);
+        ok(hr == D3D_OK, "DrawPrimitive returned: %08x\n", hr);
+
+        /* Triangle 4 -- D3DFVF_LVERTEX. */
+        hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLELIST, D3DFVF_LVERTEX,
+                                            lvertices, 3, D3DDP_WAIT);
+        ok(hr == D3D_OK, "DrawPrimitive returned: %08x\n", hr);
+
+        /* Triangle 6 -- D3DFVF_TLVERTEX. */
+        hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLELIST, D3DFVF_TLVERTEX,
+                                            tlvertices, 3, D3DDP_WAIT);
+        ok(hr == D3D_OK, "DrawPrimitive returned: %08x\n", hr);
+
+        /* Enable lighting. */
+        hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, TRUE);
+        ok(hr == D3D_OK, "SetRenderState returned: %08x\n", hr);
+        hr = IDirect3DDevice7_GetRenderState(device, D3DRENDERSTATE_LIGHTING, &val);
+        ok(hr == D3D_OK, "GetRenderState returned: %08x\n", hr);
+        ok(val == TRUE, "D3DRENDERSTATE_LIGHTING is: %08x\n", val);
+
+        /* Triangle 1 -- D3DVT_VERTEX with D3DDP_DONOTLIGHT.
+           IDirect3DDevice7::DrawPrimitive doesn't have the D3DDP_DONOTLIGHT flag,
+           it should be ignored. */
+        hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLELIST, D3DFVF_VERTEX,
+                                            vertices + 1, 3, D3DDP_DONOTLIGHT | D3DDP_WAIT);
+        ok(hr == D3D_OK, "DrawPrimitive returned: %08x\n", hr);
+
+        /* Triangle 3 -- custom fvf (vertices with normals and colors) */
+        hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLELIST, fvf,
+                                            fvfvertices + 1, 3, D3DDP_WAIT);
+        ok(hr == D3D_OK, "DrawPrimitive returned: %08x\n", hr);
+
+        /* Triangle 5 -- D3DFVF_LVERTEX.
+           It seems D3D7 still applies lighting calculations to D3DFVF_LVERTEX vertices,
+           rendering them black since they have no normals. */
+        hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLELIST, D3DFVF_LVERTEX,
+                                            lvertices + 1, 3, D3DDP_WAIT);
+        ok(hr == D3D_OK, "DrawPrimitive returned: %08x\n", hr);
+
+        /* Triangle 7 -- D3DFVF_TLVERTEX.
+           D3DFVF_TLVERTEX vertices bypass lighting calculations and keep their color values. */
+        hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLELIST, D3DFVF_TLVERTEX,
+                                            tlvertices + 1, 3, D3DDP_WAIT);
+        ok(hr == D3D_OK, "DrawPrimitive returned: %08x\n", hr);
+
+        /* Restore state. */
+        hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CULLMODE, oldcull);
+        ok(hr == D3D_OK, "SetRenderState returned: %08x\n", hr);
+        hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, oldlighting);
+        ok(hr == D3D_OK, "SetRenderState returned: %08x\n", hr);
+
+        hr = IDirect3DDevice7_EndScene(device);
+        ok(hr == D3D_OK, "EndScene returned: %08x\n", hr);
+    }
+
+    for (i = 0; i < 8; i++) {
+        /* Split screen using 5x5 grid points and use those points to sample the triangles. */
+        x = xgrid[i] * 640 / 6;
+        y = ygrid[i] * 480 / 6;
+        color = getPixelColor(device, x, y);
+        ok(color_match(color, expected[i], 1), "%d: getPixelColor(%d,%d) returned %08x, expected %08x.\n",
+                i, x, y, color, expected[i]);
+    }
+
+    /* Disable light and restore material to not interfere with other tests. */
+    hr = IDirect3DDevice7_LightEnable(device, 0, FALSE);
+    ok(hr == D3D_OK, "LightEnable returned: %08x\n", hr);
+    hr = IDirect3DDevice7_SetMaterial(device, &oldmat);
+    ok(hr == D3D_OK, "SetMaterial returned: %08x\n", hr);
+}
+
 static BOOL D3D1_createObjects(void)
 {
     WNDCLASS wc = {0};
@@ -4030,6 +4233,7 @@ START_TEST(visual)
     alpha_test(Direct3DDevice);
     rhw_zero_test(Direct3DDevice);
     cubemap_test(Direct3DDevice);
+    drawprimitive_test(Direct3DDevice);
 
 cleanup:
     releaseObjects(); /* release DX7 interfaces for other tests */
-- 
1.7.4.1




More information about the wine-patches mailing list