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

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


Similar to the D3D2 tests, except for D3D3 specific features:
- Switch to IDirectDrawSurface4, IDirect3DDevice3, IDirect3DMaterial3,
  IDirect3DViewport3 interfaces.
- Use D3DLIGHT2 when setting light properties.
- Switch to D3DFVF_ vertex types, but also test D3DVT_ ones.
- Add an extra FVF vertex type with coords, normals, and colors.
- Also test D3DDP_DONOTLIGHT flag (introduced in D3D3).
---
 dlls/ddraw/tests/visual.c |  249 ++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 248 insertions(+), 1 deletions(-)

diff --git a/dlls/ddraw/tests/visual.c b/dlls/ddraw/tests/visual.c
index 8c919b2..49cd23d 100644
--- a/dlls/ddraw/tests/visual.c
+++ b/dlls/ddraw/tests/visual.c
@@ -2724,6 +2724,253 @@ out:
     return ret;
 }
 
+static void D3D3_DrawPrimitiveTests(void)
+{
+    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[] and is_todo[] arrays bellow.
+       -----------
+       | \ 5| \ 7|
+       |4 \ |6 \ |
+       -----------
+       | \ 1| \ 3|
+       |0 \ |2 \ |
+       ----------- */
+    DWORD expected[] = { GRAY, WHITE, YELLOW2, YELLOW, GREEN, GREEN, BLUE, BLUE };
+    BOOL is_todo[] = { TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE };
+    UINT i, x, y, xgrid[] = {1,2,4,5,1,2,4,5}, ygrid[] = {5,4,5,4,2,1,2,1};
+    IDirect3DLight *Direct3DLight;
+    IDirect3DMaterial3 *Direct3DMaterial3;
+    D3DLIGHT2 light;
+    D3DMATERIAL mat;
+    D3DMATERIALHANDLE hMat;
+    DDBLTFX ddbltfx;
+    RECT rc = { 0, 0 };
+    HRESULT hr;
+    DWORD oldcull, oldlighting, val, color;
+
+    /* Fill entire surface with red. */
+    memset(&ddbltfx, 0, sizeof(ddbltfx));
+    ddbltfx.dwSize = sizeof(ddbltfx);
+    U5(ddbltfx).dwFillColor = RED;
+    hr = IDirectDrawSurface4_Blt(Surface4, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
+    ok(hr == DD_OK, "Blt returned: %08x\n", hr);
+
+    /* Make sure getPixelColor works correctly. */
+    color = D3D3_getPixelColor(DirectDraw4, Surface4, 320, 240);
+    ok(color == RED, "getPixelColor returned: %08x\n", color);
+
+    /* Setup a diffuse directional gray light, perpendicular on the triangles. */
+    hr = IDirect3D3_CreateLight(Direct3D3, &Direct3DLight, NULL);
+    ok(hr == D3D_OK, "CreateLight returned: %08x\n", hr);
+    memset(&light, 0, sizeof(light));
+    light.dwSize = sizeof(light);
+    light.dltType = D3DLIGHT_DIRECTIONAL;
+    light.dcvColor.r = .5f;
+    light.dcvColor.g = .5f;
+    light.dcvColor.b = .5f;
+    light.dcvColor.a = 1.f;
+    light.dvDirection.x = 0.f;
+    light.dvDirection.y = 0.f;
+    light.dvDirection.z = -1.f;
+    light.dwFlags = D3DLIGHT_ACTIVE;
+    hr = IDirect3DLight_SetLight(Direct3DLight, (D3DLIGHT *)&light);
+    ok(hr == D3D_OK, "SetLight returned: %08x\n", hr);
+    hr = IDirect3DViewport3_AddLight(Viewport3, Direct3DLight);
+    ok(hr == D3D_OK, "AddLight returned: %08x\n", hr);
+
+    /* Use a material that reflects only diffuse light. */
+    hr = IDirect3D3_CreateMaterial(Direct3D3, &Direct3DMaterial3, NULL);
+    ok(hr == D3D_OK, "CreateMaterial returned: %08x\n", hr);
+    memset(&mat, 0, sizeof(mat));
+    mat.dwSize = sizeof(mat);
+    mat.dcvDiffuse.r = 1.f;
+    mat.dcvDiffuse.g = 1.f;
+    mat.dcvDiffuse.b = 1.f;
+    mat.dcvDiffuse.a = 1.f;
+    hr = IDirect3DMaterial3_SetMaterial(Direct3DMaterial3, &mat);
+    ok(hr == D3D_OK, "SetMaterial returned: %08x\n", hr);
+    hr = IDirect3DMaterial3_GetHandle(Direct3DMaterial3, Direct3DDevice3, &hMat);
+    ok(hr == D3D_OK, "GetHandle returned: %08x\n", hr);
+    hr = IDirect3DDevice3_SetLightState(Direct3DDevice3, D3DLIGHTSTATE_MATERIAL, hMat);
+    ok(hr == D3D_OK, "SetLightState returned: %08x\n", hr);
+    hr = IDirect3DDevice3_SetLightState(Direct3DDevice3, D3DLIGHTSTATE_COLORVERTEX, TRUE);
+    ok(hr == D3D_OK, "SetLightState returned: %08x\n", hr);
+
+    hr = IDirect3DDevice3_BeginScene(Direct3DDevice3);
+    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 = IDirect3DDevice3_GetRenderState(Direct3DDevice3, D3DRENDERSTATE_CULLMODE, &oldcull);
+        ok(hr == D3D_OK, "GetRenderState returned: %08x\n", hr);
+        hr = IDirect3DDevice3_SetRenderState(Direct3DDevice3, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
+        ok(hr == D3D_OK, "SetRenderState returned: %08x\n", hr);
+
+        /* IDirect3DDevice3 doesn't have D3DRENDERSTATE_LIGHTING, but get/set seem to work w/o any side effects. */
+        hr = IDirect3DDevice3_GetRenderState(Direct3DDevice3, D3DRENDERSTATE_LIGHTING, &oldlighting);
+        ok(hr == D3D_OK, "GetRenderState returned: %08x\n", hr);
+        todo_wine ok(oldlighting == 0xffffffff, "D3DRENDERSTATE_LIGHTING is: %08x\n", oldlighting);
+
+        /* Try to disable lighting -- shouldn't have any effect. */
+        hr = IDirect3DDevice3_SetRenderState(Direct3DDevice3, D3DRENDERSTATE_LIGHTING, FALSE);
+        ok(hr == D3D_OK, "SetRenderState returned: %08x\n", hr);
+        hr = IDirect3DDevice3_GetRenderState(Direct3DDevice3, D3DRENDERSTATE_LIGHTING, &val);
+        ok(hr == D3D_OK, "GetRenderState returned: %08x\n", hr);
+        ok(val == FALSE, "D3DRENDERSTATE_LIGHTING is: %08x\n", val);
+
+        /* Note: IDirect3DDevice3::DrawPrimitive calls with D3DVT_ vertex types should fail. */
+
+        /* Triangle 0 -- D3DFVF_VERTEX (vertices with normals, but without colors). */
+        hr = IDirect3DDevice3_DrawPrimitive(Direct3DDevice3, D3DPT_TRIANGLELIST, D3DVT_VERTEX,
+                                            vertices, 3, D3DDP_WAIT);
+        ok(hr != DDERR_INVALIDPARAMS, "DrawPrimitive returned: %08x\n", hr);
+        hr = IDirect3DDevice3_DrawPrimitive(Direct3DDevice3, 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 = IDirect3DDevice3_DrawPrimitive(Direct3DDevice3, D3DPT_TRIANGLELIST, fvf,
+                                            fvfvertices, 3, D3DDP_WAIT);
+        ok(hr == D3D_OK, "DrawPrimitive returned: %08x\n", hr);
+
+        /* Triangle 4 -- D3DFVF_LVERTEX. */
+        hr = IDirect3DDevice3_DrawPrimitive(Direct3DDevice3, D3DPT_TRIANGLELIST, D3DVT_LVERTEX,
+                                            lvertices, 3, D3DDP_WAIT);
+        ok(hr != DDERR_INVALIDPARAMS, "DrawPrimitive returned: %08x\n", hr);
+        hr = IDirect3DDevice3_DrawPrimitive(Direct3DDevice3, D3DPT_TRIANGLELIST, D3DFVF_LVERTEX,
+                                            lvertices, 3, D3DDP_WAIT);
+        ok(hr == D3D_OK, "DrawPrimitive returned: %08x\n", hr);
+
+        /* Triangle 6 -- D3DFVF_TLVERTEX. */
+        hr = IDirect3DDevice3_DrawPrimitive(Direct3DDevice3, D3DPT_TRIANGLELIST, D3DVT_TLVERTEX,
+                                            tlvertices, 3, D3DDP_WAIT);
+        ok(hr != DDERR_INVALIDPARAMS, "DrawPrimitive returned: %08x\n", hr);
+        hr = IDirect3DDevice3_DrawPrimitive(Direct3DDevice3, D3DPT_TRIANGLELIST, D3DFVF_TLVERTEX,
+                                            tlvertices, 3, D3DDP_WAIT);
+        ok(hr == D3D_OK, "DrawPrimitive returned: %08x\n", hr);
+
+        /* Try to enable lighting -- shouldn't have any effect. */
+        hr = IDirect3DDevice3_SetRenderState(Direct3DDevice3, D3DRENDERSTATE_LIGHTING, TRUE);
+        ok(hr == D3D_OK, "SetRenderState returned: %08x\n", hr);
+        hr = IDirect3DDevice3_GetRenderState(Direct3DDevice3, D3DRENDERSTATE_LIGHTING, &val);
+        ok(hr == D3D_OK, "GetRenderState returned: %08x\n", hr);
+        ok(val == TRUE, "D3DRENDERSTATE_LIGHTING is: %08x\n", val);
+
+        /* Triangle 1 -- D3DFVF_VERTEX with D3DDP_DONOTLIGHT.
+           From DirectX SDK docs: if flag D3DDP_DONOTLIGHT is set and a diffuse or specular
+           component is not specified, the system uses the default color for the missing
+           component (0xFFFFFFFF for diffuse and 0x00000000 for specular). */
+        hr = IDirect3DDevice3_DrawPrimitive(Direct3DDevice3, 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) with D3DDP_DONOTLIGHT. */
+        hr = IDirect3DDevice3_DrawPrimitive(Direct3DDevice3, D3DPT_TRIANGLELIST, fvf,
+                                            fvfvertices + 1, 3, D3DDP_DONOTLIGHT | D3DDP_WAIT);
+        ok(hr == D3D_OK, "DrawPrimitive returned: %08x\n", hr);
+
+        /* Triangle 5 -- D3DFVF_LVERTEX. */
+        hr = IDirect3DDevice3_DrawPrimitive(Direct3DDevice3, D3DPT_TRIANGLELIST, D3DFVF_LVERTEX,
+                                            lvertices + 1, 3, D3DDP_WAIT);
+        ok(hr == D3D_OK, "DrawPrimitive returned: %08x\n", hr);
+
+        /* Triangle 7 -- D3DFVF_TLVERTEX. */
+        hr = IDirect3DDevice3_DrawPrimitive(Direct3DDevice3, D3DPT_TRIANGLELIST, D3DFVF_TLVERTEX,
+                                            tlvertices + 1, 3, D3DDP_WAIT);
+        ok(hr == D3D_OK, "DrawPrimitive returned: %08x\n", hr);
+
+        /* Restore state. */
+        hr = IDirect3DDevice3_SetRenderState(Direct3DDevice3, D3DRENDERSTATE_CULLMODE, oldcull);
+        ok(hr == D3D_OK, "SetRenderState returned: %08x\n", hr);
+        hr = IDirect3DDevice3_SetRenderState(Direct3DDevice3, D3DRENDERSTATE_LIGHTING, oldlighting);
+        ok(hr == D3D_OK, "SetRenderState returned: %08x\n", hr);
+
+        hr = IDirect3DDevice3_EndScene(Direct3DDevice3);
+        ok(hr == D3D_OK, "EndScene returned: %08x\n", hr);
+    }
+
+    /* Blit to window (for debugging, tests read directly from surface). */
+    MapWindowPoints(window, NULL, (POINT *)&rc, 1);
+    rc.right = rc.left + 640;
+    rc.bottom = rc.top + 480;
+
+    memset(&ddbltfx, 0, sizeof(ddbltfx));
+    ddbltfx.dwSize = sizeof(ddbltfx);
+    hr = IDirectDrawSurface4_Blt(Primary4, &rc, Surface4, NULL, DDBLT_WAIT, &ddbltfx);
+    ok(hr == DD_OK, "Blt 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 = D3D3_getPixelColor(DirectDraw4, Surface4, x, y);
+        if (is_todo[i])
+            todo_wine
+            ok(color_match(color, expected[i], 1), "%d: getPixelColor(%d,%d) returned %08x, expected %08x.\n",
+                    i, x, y, color, expected[i]);
+        else
+            ok(color_match(color, expected[i], 1), "%d: getPixelColor(%d,%d) returned %08x, expected %08x.\n",
+                    i, x, y, color, expected[i]);
+    }
+
+    /* Cleanup lights and material. */
+    hr = IDirect3DViewport3_DeleteLight(Viewport3, Direct3DLight);
+    ok(hr == D3D_OK, "DeleteLight returned: %08x\n", hr);
+    IDirect3DLight_Release(Direct3DLight);
+    hr = IDirect3DDevice3_SetLightState(Direct3DDevice3, D3DLIGHTSTATE_MATERIAL, 0);
+    todo_wine
+    ok(hr == D3D_OK, "SetLightState returned: %08x\n", hr);
+    IDirect3DMaterial3_Release(Direct3DMaterial3);
+}
+
 static void D3D3_ViewportClearTest(void)
 {
     HRESULT hr;
@@ -3808,7 +4055,7 @@ cleanup:
         skip("Cannot initialize D3D3, skipping\n");
     }
     else {
-        /* todo */
+        D3D3_DrawPrimitiveTests();
     }
     D3D3_releaseObjects();
 
-- 
1.7.4.1




More information about the wine-patches mailing list