From: Octavian Voicu Subject: [11/11] ddraw/tests: Add assorted D3D7 DrawPrimitive/visual tests. Message-Id: <1320704834-17156-12-git-send-email-octavian.voicu@gmail.com> Date: Tue, 8 Nov 2011 00:27:14 +0200 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