From: Octavian Voicu Subject: [08/11] ddraw/tests: Add assorted D3D2 DrawPrimitive/visual tests. Message-Id: <1320704834-17156-9-git-send-email-octavian.voicu@gmail.com> Date: Tue, 8 Nov 2011 00:27:11 +0200 Among others, test that D3DRENDERSTATE_LIGHTING is ignored, as it should be (it wasn't introduced until D3D7). --- dlls/ddraw/tests/visual.c | 227 ++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 226 insertions(+), 1 deletions(-) diff --git a/dlls/ddraw/tests/visual.c b/dlls/ddraw/tests/visual.c index 832a9de..32d7de3 100644 --- a/dlls/ddraw/tests/visual.c +++ b/dlls/ddraw/tests/visual.c @@ -2292,6 +2292,231 @@ static void D3D2_releaseObjects(void) window = NULL; } +static void D3D2_DrawPrimitiveTests(void) +{ + enum { + BLACK = 0x000000, + BLUE = 0x0000ff, + GREEN = 0x00ff00, + GRAY = 0x808080, + RED = 0xff0000, + WHITE = 0xffffff + }; + D3DVERTEX vertices1[] = { /* 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} } + }; + D3DVERTEX vertices2[] = { /* bottom-right corner of screen */ + /* x y z nx ny nz tu tv */ + { { 0.f}, {-1.f}, {0.f}, {0.f}, {0.f}, {1.f}, {0.f}, {0.f} }, + { { 1.f}, {-1.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} }, + { { 1.f}, { 0.f}, {0.f}, {0.f}, {0.f}, {1.f}, {0.f}, {0.f} } + }; + 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[] = { WHITE, WHITE, GRAY, GRAY, GREEN, GREEN, BLUE, BLUE }; + BOOL is_todo[] = { FALSE, 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; + IDirect3DMaterial2 *Direct3DMaterial2; + 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 = IDirectDrawSurface_Blt(Surface1, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx); + ok(hr == DD_OK, "Blt returned: %08x\n", hr); + + /* Make sure getPixelColor works correctly. */ + color = D3D1_getPixelColor(DirectDraw1, Surface1, 320, 240); + ok(color == RED, "getPixelColor returned: %08x\n", color); + + /* Setup a diffuse directional gray light, perpendicular on the triangles. */ + hr = IDirect3D2_CreateLight(Direct3D2, &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 = IDirect3DViewport2_AddLight(Viewport2, Direct3DLight); + ok(hr == D3D_OK, "AddLight returned: %08x\n", hr); + + /* Use a material that reflects only diffuse light. */ + hr = IDirect3D2_CreateMaterial(Direct3D2, &Direct3DMaterial2, 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 = IDirect3DMaterial2_SetMaterial(Direct3DMaterial2, &mat); + ok(hr == D3D_OK, "SetMaterial returned: %08x\n", hr); + hr = IDirect3DMaterial2_GetHandle(Direct3DMaterial2, Direct3DDevice2, &hMat); + ok(hr == D3D_OK, "GetHandle returned: %08x\n", hr); + hr = IDirect3DDevice2_SetLightState(Direct3DDevice2, D3DLIGHTSTATE_MATERIAL, hMat); + ok(hr == D3D_OK, "SetLightState returned: %08x\n", hr); + hr = IDirect3DDevice2_SetLightState(Direct3DDevice2, D3DLIGHTSTATE_COLORVERTEX, TRUE); + ok(hr == D3D_OK, "SetLightState returned: %08x\n", hr); + + hr = IDirect3DDevice2_BeginScene(Direct3DDevice2); + 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 = IDirect3DDevice2_GetRenderState(Direct3DDevice2, D3DRENDERSTATE_CULLMODE, &oldcull); + ok(hr == D3D_OK, "GetRenderState returned: %08x\n", hr); + hr = IDirect3DDevice2_SetRenderState(Direct3DDevice2, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE); + ok(hr == D3D_OK, "SetRenderState returned: %08x\n", hr); + + /* IDirect3DDevice2 doesn't have D3DRENDERSTATE_LIGHTING, but get/set seem to work w/o any side effects. */ + hr = IDirect3DDevice2_GetRenderState(Direct3DDevice2, 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 = IDirect3DDevice2_SetRenderState(Direct3DDevice2, D3DRENDERSTATE_LIGHTING, FALSE); + ok(hr == D3D_OK, "SetRenderState returned: %08x\n", hr); + hr = IDirect3DDevice2_GetRenderState(Direct3DDevice2, D3DRENDERSTATE_LIGHTING, &val); + ok(hr == D3D_OK, "GetRenderState returned: %08x\n", hr); + ok(val == FALSE, "D3DRENDERSTATE_LIGHTING is: %08x\n", val); + + /* Triangle 0 -- D3DVT_VERTEX with D3DDP_DONOTLIGHT. + IDirect3DDevice2::DrawPrimitive doesn't have the D3DDP_DONOTLIGHT flag, + it should be ignored. */ + hr = IDirect3DDevice2_DrawPrimitive(Direct3DDevice2, D3DPT_TRIANGLELIST, D3DVT_VERTEX, + vertices1, 3, D3DDP_DONOTLIGHT | D3DDP_WAIT); + ok(hr == D3D_OK, "DrawPrimitive returned: %08x\n", hr); + + /* Triangle 2 -- D3DVT_VERTEX. */ + hr = IDirect3DDevice2_DrawPrimitive(Direct3DDevice2, D3DPT_TRIANGLELIST, D3DVT_VERTEX, + vertices2, 3, D3DDP_WAIT); + ok(hr == D3D_OK, "DrawPrimitive returned: %08x\n", hr); + + /* Triangle 4 -- D3DVT_LVERTEX. */ + hr = IDirect3DDevice2_DrawPrimitive(Direct3DDevice2, D3DPT_TRIANGLELIST, D3DVT_LVERTEX, + lvertices, 3, D3DDP_WAIT); + ok(hr == D3D_OK, "DrawPrimitive returned: %08x\n", hr); + + /* Triangle 6 -- D3DVT_TLVERTEX. */ + hr = IDirect3DDevice2_DrawPrimitive(Direct3DDevice2, D3DPT_TRIANGLELIST, D3DVT_TLVERTEX, + tlvertices, 3, D3DDP_WAIT); + ok(hr == D3D_OK, "DrawPrimitive returned: %08x\n", hr); + + /* Try to enable lighting -- shouldn't have any effect. */ + hr = IDirect3DDevice2_SetRenderState(Direct3DDevice2, D3DRENDERSTATE_LIGHTING, TRUE); + ok(hr == D3D_OK, "SetRenderState returned: %08x\n", hr); + hr = IDirect3DDevice2_GetRenderState(Direct3DDevice2, 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. + IDirect3DDevice2::DrawPrimitive doesn't have the D3DDP_DONOTLIGHT flag, + it should be ignored. */ + hr = IDirect3DDevice2_DrawPrimitive(Direct3DDevice2, D3DPT_TRIANGLELIST, D3DVT_VERTEX, + vertices1 + 1, 3, D3DDP_DONOTLIGHT | D3DDP_WAIT); + ok(hr == D3D_OK, "DrawPrimitive returned: %08x\n", hr); + + /* Triangle 3 -- D3DVT_VERTEX. */ + hr = IDirect3DDevice2_DrawPrimitive(Direct3DDevice2, D3DPT_TRIANGLELIST, D3DVT_VERTEX, + vertices2 + 1, 3, D3DDP_WAIT); + ok(hr == D3D_OK, "DrawPrimitive returned: %08x\n", hr); + + /* Triangle 5 -- D3DVT_LVERTEX. */ + hr = IDirect3DDevice2_DrawPrimitive(Direct3DDevice2, D3DPT_TRIANGLELIST, D3DVT_LVERTEX, + lvertices + 1, 3, D3DDP_WAIT); + ok(hr == D3D_OK, "DrawPrimitive returned: %08x\n", hr); + + /* Triangle 7 -- D3DVT_TLVERTEX. */ + hr = IDirect3DDevice2_DrawPrimitive(Direct3DDevice2, D3DPT_TRIANGLELIST, D3DVT_TLVERTEX, + tlvertices + 1, 3, D3DDP_WAIT); + ok(hr == D3D_OK, "DrawPrimitive returned: %08x\n", hr); + + /* Restore state. */ + hr = IDirect3DDevice2_SetRenderState(Direct3DDevice2, D3DRENDERSTATE_CULLMODE, oldcull); + ok(hr == D3D_OK, "SetRenderState returned: %08x\n", hr); + hr = IDirect3DDevice2_SetRenderState(Direct3DDevice2, D3DRENDERSTATE_LIGHTING, oldlighting); + ok(hr == D3D_OK, "SetRenderState returned: %08x\n", hr); + + hr = IDirect3DDevice2_EndScene(Direct3DDevice2); + 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 = IDirectDrawSurface_Blt(Primary1, &rc, Surface1, 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 = D3D1_getPixelColor(DirectDraw1, Surface1, 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 = IDirect3DViewport2_DeleteLight(Viewport2, Direct3DLight); + ok(hr == D3D_OK, "DeleteLight returned: %08x\n", hr); + IDirect3DLight_Release(Direct3DLight); + hr = IDirect3DDevice2_SetLightState(Direct3DDevice2, D3DLIGHTSTATE_MATERIAL, 0); + todo_wine + ok(hr == D3D_OK, "SetLightState returned: %08x\n", hr); + IDirect3DMaterial2_Release(Direct3DMaterial2); +} + static DWORD D3D3_getPixelColor(IDirectDraw4 *DirectDraw, IDirectDrawSurface4 *Surface, UINT x, UINT y) { DWORD ret; @@ -3430,7 +3655,7 @@ cleanup: skip("Cannot initialize D3D2, skipping\n"); } else { - /* todo */ + D3D2_DrawPrimitiveTests(); } D3D2_releaseObjects(); -- 1.7.4.1