ddraw/tests: Port the lighting test to the previous d3d versions.

This commit is contained in:
Matteo Bruni 2015-04-21 15:11:21 +02:00 committed by Alexandre Julliard
parent 319e7fb201
commit b6717dc2e3
3 changed files with 914 additions and 0 deletions

View File

@ -146,6 +146,21 @@ static void emit_process_vertices(void **ptr, DWORD flags, WORD base_idx, DWORD
*ptr = pv + 1;
}
static void emit_set_ts(void **ptr, D3DTRANSFORMSTATETYPE state, DWORD value)
{
D3DINSTRUCTION *inst = *ptr;
D3DSTATE *ts = (D3DSTATE *)(inst + 1);
inst->bOpcode = D3DOP_STATETRANSFORM;
inst->bSize = sizeof(*ts);
inst->wCount = 1;
U1(*ts).dtstTransformStateType = state;
U2(*ts).dwArg[0] = value;
*ptr = ts + 1;
}
static void emit_set_ls(void **ptr, D3DLIGHTSTATETYPE state, DWORD value)
{
D3DINSTRUCTION *inst = *ptr;
@ -200,6 +215,30 @@ static void emit_tquad(void **ptr, WORD base_idx)
*ptr = tri;
}
static void emit_tquad_tlist(void **ptr, WORD base_idx)
{
D3DINSTRUCTION *inst = *ptr;
D3DTRIANGLE *tri = (D3DTRIANGLE *)(inst + 1);
inst->bOpcode = D3DOP_TRIANGLE;
inst->bSize = sizeof(*tri);
inst->wCount = 2;
U1(*tri).v1 = base_idx;
U2(*tri).v2 = base_idx + 1;
U3(*tri).v3 = base_idx + 2;
tri->wFlags = D3DTRIFLAG_START;
++tri;
U1(*tri).v1 = base_idx + 2;
U2(*tri).v2 = base_idx + 3;
U3(*tri).v3 = base_idx;
tri->wFlags = D3DTRIFLAG_START;
++tri;
*ptr = tri;
}
static void emit_end(void **ptr)
{
D3DINSTRUCTION *inst = *ptr;
@ -5310,6 +5349,334 @@ static void test_material(void)
DestroyWindow(window);
}
static void test_lighting(void)
{
static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
static D3DMATRIX mat =
{
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f,
},
mat_singular =
{
1.0f, 0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.5f, 1.0f,
},
mat_transf =
{
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
-1.0f, 0.0f, 0.0f, 0.0f,
10.f, 10.0f, 10.0f, 1.0f,
},
mat_nonaffine =
{
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, -1.0f,
10.f, 10.0f, 10.0f, 0.0f,
};
static D3DLVERTEX unlitquad[] =
{
{{-1.0f}, {-1.0f}, {0.1f}, 0, {0xffff0000}, {0}, {0.0f}, {0.0f}},
{{-1.0f}, { 0.0f}, {0.1f}, 0, {0xffff0000}, {0}, {0.0f}, {0.0f}},
{{ 0.0f}, { 0.0f}, {0.1f}, 0, {0xffff0000}, {0}, {0.0f}, {0.0f}},
{{ 0.0f}, {-1.0f}, {0.1f}, 0, {0xffff0000}, {0}, {0.0f}, {0.0f}},
},
litquad[] =
{
{{-1.0f}, { 0.0f}, {0.1f}, 0, {0xff00ff00}, {0}, {0.0f}, {0.0f}},
{{-1.0f}, { 1.0f}, {0.1f}, 0, {0xff00ff00}, {0}, {0.0f}, {0.0f}},
{{ 0.0f}, { 1.0f}, {0.1f}, 0, {0xff00ff00}, {0}, {0.0f}, {0.0f}},
{{ 0.0f}, { 0.0f}, {0.1f}, 0, {0xff00ff00}, {0}, {0.0f}, {0.0f}},
};
static D3DVERTEX unlitnquad[] =
{
{{0.0f}, {-1.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
{{0.0f}, { 0.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
{{1.0f}, { 0.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
{{1.0f}, {-1.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
},
litnquad[] =
{
{{0.0f}, { 0.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
{{0.0f}, { 1.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
{{1.0f}, { 1.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
{{1.0f}, { 0.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
},
nquad[] =
{
{{-1.0f}, {-1.0f}, {0.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
{{-1.0f}, { 1.0f}, {0.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
{{ 1.0f}, { 1.0f}, {0.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
{{ 1.0f}, {-1.0f}, {0.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
},
rotatedquad[] =
{
{{-10.0f}, {-11.0f}, {11.0f}, {-1.0f}, {0.0f}, {0.0f}, {0.0f}, {0.0f}},
{{-10.0f}, { -9.0f}, {11.0f}, {-1.0f}, {0.0f}, {0.0f}, {0.0f}, {0.0f}},
{{-10.0f}, { -9.0f}, { 9.0f}, {-1.0f}, {0.0f}, {0.0f}, {0.0f}, {0.0f}},
{{-10.0f}, {-11.0f}, { 9.0f}, {-1.0f}, {0.0f}, {0.0f}, {0.0f}, {0.0f}},
},
translatedquad[] =
{
{{-11.0f}, {-11.0f}, {-10.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
{{-11.0f}, { -9.0f}, {-10.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
{{ -9.0f}, { -9.0f}, {-10.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
{{ -9.0f}, {-11.0f}, {-10.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
};
static const struct
{
D3DMATRIX *world_matrix;
void *quad;
DWORD expected;
const char *message;
}
tests[] =
{
{&mat, nquad, 0x000000ff, "Lit quad with light"},
{&mat_singular, nquad, 0x000000b4, "Lit quad with singular world matrix"},
{&mat_transf, rotatedquad, 0x000000ff, "Lit quad with transformation matrix"},
{&mat_nonaffine, translatedquad, 0x000000ff, "Lit quad with non-affine matrix"},
};
HWND window;
IDirect3D *d3d;
IDirect3DDevice *device;
IDirectDraw *ddraw;
IDirectDrawSurface *rt;
IDirect3DViewport *viewport;
IDirect3DMaterial *material;
IDirect3DLight *light;
IDirect3DExecuteBuffer *execute_buffer;
D3DEXECUTEBUFFERDESC exec_desc;
D3DMATERIALHANDLE mat_handle;
D3DMATRIXHANDLE world_handle, view_handle, proj_handle;
D3DLIGHT light_desc;
HRESULT hr;
D3DCOLOR color;
void *ptr;
UINT inst_length;
ULONG refcount;
unsigned int i;
window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
0, 0, 640, 480, 0, 0, 0, 0);
ddraw = create_ddraw();
ok(!!ddraw, "Failed to create a ddraw object.\n");
if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
{
skip("Failed to create a 3D device, skipping test.\n");
DestroyWindow(window);
return;
}
hr = IDirect3DDevice_GetDirect3D(device, &d3d);
ok(SUCCEEDED(hr), "Failed to get D3D interface, hr %#x.\n", hr);
hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
viewport = create_viewport(device, 0, 0, 640, 480);
material = create_diffuse_material(device, 1.0f, 1.0f, 1.0f, 1.0f);
viewport_set_background(device, viewport, material);
hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
hr = IDirect3DDevice_CreateMatrix(device, &world_handle);
ok(hr == D3D_OK, "Creating a matrix object failed, hr %#x.\n", hr);
hr = IDirect3DDevice_SetMatrix(device, world_handle, &mat);
ok(hr == D3D_OK, "Setting a matrix object failed, hr %#x.\n", hr);
hr = IDirect3DDevice_CreateMatrix(device, &view_handle);
ok(hr == D3D_OK, "Creating a matrix object failed, hr %#x.\n", hr);
hr = IDirect3DDevice_SetMatrix(device, view_handle, &mat);
ok(hr == D3D_OK, "Setting a matrix object failed, hr %#x.\n", hr);
hr = IDirect3DDevice_CreateMatrix(device, &proj_handle);
ok(hr == D3D_OK, "Creating a matrix object failed, hr %#x.\n", hr);
hr = IDirect3DDevice_SetMatrix(device, proj_handle, &mat);
ok(hr == D3D_OK, "Setting a matrix object failed, hr %#x.\n", hr);
memset(&exec_desc, 0, sizeof(exec_desc));
exec_desc.dwSize = sizeof(exec_desc);
exec_desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
exec_desc.dwBufferSize = 1024;
exec_desc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
hr = IDirect3DDevice_CreateExecuteBuffer(device, &exec_desc, &execute_buffer, NULL);
ok(SUCCEEDED(hr), "Failed to create execute buffer, hr %#x.\n", hr);
hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#x.\n", hr);
memcpy(exec_desc.lpData, unlitquad, sizeof(unlitquad));
ptr = ((BYTE *)exec_desc.lpData) + sizeof(unlitquad);
emit_set_ts(&ptr, D3DTRANSFORMSTATE_WORLD, world_handle);
emit_set_ts(&ptr, D3DTRANSFORMSTATE_VIEW, view_handle);
emit_set_ts(&ptr, D3DTRANSFORMSTATE_PROJECTION, proj_handle);
emit_set_rs(&ptr, D3DRENDERSTATE_CLIPPING, FALSE);
emit_set_rs(&ptr, D3DRENDERSTATE_ZENABLE, FALSE);
emit_set_rs(&ptr, D3DRENDERSTATE_FOGENABLE, FALSE);
emit_set_rs(&ptr, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
emit_process_vertices(&ptr, D3DPROCESSVERTICES_TRANSFORM, 0, 4);
emit_tquad_tlist(&ptr, 0);
emit_end(&ptr);
inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
inst_length -= sizeof(unlitquad);
hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#x.\n", hr);
hr = IDirect3DDevice_BeginScene(device);
ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
set_execute_data(execute_buffer, 4, sizeof(unlitquad), inst_length);
hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#x.\n", hr);
memcpy(exec_desc.lpData, litquad, sizeof(litquad));
ptr = ((BYTE *)exec_desc.lpData) + sizeof(litquad);
emit_process_vertices(&ptr, D3DPROCESSVERTICES_TRANSFORM, 0, 4);
emit_tquad_tlist(&ptr, 0);
emit_end(&ptr);
inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
inst_length -= sizeof(litquad);
hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#x.\n", hr);
set_execute_data(execute_buffer, 4, sizeof(litquad), inst_length);
hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#x.\n", hr);
memcpy(exec_desc.lpData, unlitnquad, sizeof(unlitnquad));
ptr = ((BYTE *)exec_desc.lpData) + sizeof(unlitnquad);
emit_process_vertices(&ptr, D3DPROCESSVERTICES_TRANSFORMLIGHT, 0, 4);
emit_tquad_tlist(&ptr, 0);
emit_end(&ptr);
inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
inst_length -= sizeof(unlitnquad);
hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#x.\n", hr);
set_execute_data(execute_buffer, 4, sizeof(unlitnquad), inst_length);
hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#x.\n", hr);
memcpy(exec_desc.lpData, litnquad, sizeof(litnquad));
ptr = ((BYTE *)exec_desc.lpData) + sizeof(litnquad);
emit_process_vertices(&ptr, D3DPROCESSVERTICES_TRANSFORMLIGHT, 0, 4);
emit_tquad_tlist(&ptr, 0);
emit_end(&ptr);
inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
inst_length -= sizeof(litnquad);
hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#x.\n", hr);
set_execute_data(execute_buffer, 4, sizeof(litnquad), inst_length);
hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
hr = IDirect3DDevice_EndScene(device);
ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
color = get_surface_color(rt, 160, 360);
ok(color == 0x00ff0000, "Unlit quad without normals has color 0x%08x.\n", color);
color = get_surface_color(rt, 160, 120);
ok(color == 0x0000ff00, "Lit quad without normals has color 0x%08x.\n", color);
color = get_surface_color(rt, 480, 360);
ok(color == 0x00ffffff, "Unlit quad with normals has color 0x%08x.\n", color);
color = get_surface_color(rt, 480, 120);
ok(color == 0x00ffffff, "Lit quad with normals has color 0x%08x.\n", color);
hr = IDirect3DMaterial_GetHandle(material, device, &mat_handle);
ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
hr = IDirect3D_CreateLight(d3d, &light, NULL);
ok(SUCCEEDED(hr), "Failed to create a light object, hr %#x.\n", hr);
memset(&light_desc, 0, sizeof(light_desc));
light_desc.dwSize = sizeof(light_desc);
light_desc.dltType = D3DLIGHT_DIRECTIONAL;
U1(U(light_desc).dcvColor).r = 0.0f;
U2(U(light_desc).dcvColor).g = 0.0f;
U3(U(light_desc).dcvColor).b = 1.0f;
U4(U(light_desc).dcvColor).a = 1.0f;
light_desc.dvDirection.z = 1.0f;
hr = IDirect3DLight_SetLight(light, &light_desc);
ok(SUCCEEDED(hr), "Failed to set light, hr %#x.\n", hr);
hr = IDirect3DViewport_AddLight(viewport, light);
ok(SUCCEEDED(hr), "Failed to add a light to the viewport, hr %#x.\n", hr);
for (i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i)
{
hr = IDirect3DDevice_SetMatrix(device, world_handle, tests[i].world_matrix);
ok(hr == D3D_OK, "Setting a matrix object failed, hr %#x.\n", hr);
hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
hr = IDirect3DDevice_BeginScene(device);
ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#x.\n", hr);
memcpy(exec_desc.lpData, tests[i].quad, sizeof(nquad));
ptr = ((BYTE *)exec_desc.lpData) + sizeof(nquad);
emit_set_ls(&ptr, D3DLIGHTSTATE_MATERIAL, mat_handle);
emit_process_vertices(&ptr, D3DPROCESSVERTICES_TRANSFORMLIGHT, 0, 4);
emit_tquad_tlist(&ptr, 0);
emit_end(&ptr);
inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
inst_length -= sizeof(nquad);
hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#x.\n", hr);
set_execute_data(execute_buffer, 4, sizeof(nquad), inst_length);
hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_CLIPPED);
ok(SUCCEEDED(hr), "Failed to execute exec buffer, hr %#x.\n", hr);
hr = IDirect3DDevice_EndScene(device);
ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
color = get_surface_color(rt, 320, 240);
todo_wine ok(color == tests[i].expected, "%s has color 0x%08x.\n", tests[i].message, color);
}
IDirect3DExecuteBuffer_Release(execute_buffer);
IDirect3DDevice_DeleteMatrix(device, world_handle);
IDirect3DDevice_DeleteMatrix(device, view_handle);
IDirect3DDevice_DeleteMatrix(device, proj_handle);
hr = IDirect3DViewport_DeleteLight(viewport, light);
ok(SUCCEEDED(hr), "Failed to remove a light from the viewport, hr %#x.\n", hr);
IDirect3DLight_Release(light);
destroy_material(material);
destroy_viewport(device, viewport);
IDirectDrawSurface_Release(rt);
refcount = IDirect3DDevice_Release(device);
ok(!refcount, "Device has %u references left.\n", refcount);
IDirect3D_Release(d3d);
refcount = IDirectDraw_Release(ddraw);
ok(!refcount, "Ddraw object has %u references left.\n", refcount);
DestroyWindow(window);
}
static void test_palette_gdi(void)
{
IDirectDrawSurface *surface, *primary;
@ -6929,6 +7296,7 @@ START_TEST(ddraw1)
test_palette_complex();
test_p8_rgb_blit();
test_material();
test_lighting();
test_palette_gdi();
test_palette_alpha();
test_lost_device();

View File

@ -6384,6 +6384,273 @@ static void test_material(void)
DestroyWindow(window);
}
static void test_lighting(void)
{
static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
static D3DMATRIX mat =
{
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f,
},
mat_singular =
{
1.0f, 0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.5f, 1.0f,
},
mat_transf =
{
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
-1.0f, 0.0f, 0.0f, 0.0f,
10.f, 10.0f, 10.0f, 1.0f,
},
mat_nonaffine =
{
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, -1.0f,
10.f, 10.0f, 10.0f, 0.0f,
};
static D3DLVERTEX unlitquad[] =
{
{{-1.0f}, {-1.0f}, {0.1f}, 0, {0xffff0000}, {0}, {0.0f}, {0.0f}},
{{-1.0f}, { 0.0f}, {0.1f}, 0, {0xffff0000}, {0}, {0.0f}, {0.0f}},
{{ 0.0f}, { 0.0f}, {0.1f}, 0, {0xffff0000}, {0}, {0.0f}, {0.0f}},
{{ 0.0f}, {-1.0f}, {0.1f}, 0, {0xffff0000}, {0}, {0.0f}, {0.0f}},
},
litquad[] =
{
{{-1.0f}, { 0.0f}, {0.1f}, 0, {0xff00ff00}, {0}, {0.0f}, {0.0f}},
{{-1.0f}, { 1.0f}, {0.1f}, 0, {0xff00ff00}, {0}, {0.0f}, {0.0f}},
{{ 0.0f}, { 1.0f}, {0.1f}, 0, {0xff00ff00}, {0}, {0.0f}, {0.0f}},
{{ 0.0f}, { 0.0f}, {0.1f}, 0, {0xff00ff00}, {0}, {0.0f}, {0.0f}},
};
static D3DVERTEX unlitnquad[] =
{
{{0.0f}, {-1.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
{{0.0f}, { 0.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
{{1.0f}, { 0.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
{{1.0f}, {-1.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
},
litnquad[] =
{
{{0.0f}, { 0.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
{{0.0f}, { 1.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
{{1.0f}, { 1.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
{{1.0f}, { 0.0f}, {0.1f}, {1.0f}, {1.0f}, {1.0f}, {0.0f}, {0.0f}},
},
nquad[] =
{
{{-1.0f}, {-1.0f}, {0.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
{{-1.0f}, { 1.0f}, {0.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
{{ 1.0f}, { 1.0f}, {0.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
{{ 1.0f}, {-1.0f}, {0.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
},
rotatedquad[] =
{
{{-10.0f}, {-11.0f}, {11.0f}, {-1.0f}, {0.0f}, {0.0f}, {0.0f}, {0.0f}},
{{-10.0f}, { -9.0f}, {11.0f}, {-1.0f}, {0.0f}, {0.0f}, {0.0f}, {0.0f}},
{{-10.0f}, { -9.0f}, { 9.0f}, {-1.0f}, {0.0f}, {0.0f}, {0.0f}, {0.0f}},
{{-10.0f}, {-11.0f}, { 9.0f}, {-1.0f}, {0.0f}, {0.0f}, {0.0f}, {0.0f}},
},
translatedquad[] =
{
{{-11.0f}, {-11.0f}, {-10.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
{{-11.0f}, { -9.0f}, {-10.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
{{ -9.0f}, { -9.0f}, {-10.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
{{ -9.0f}, {-11.0f}, {-10.0f}, {0.0f}, {0.0f}, {-1.0f}, {0.0f}, {0.0f}},
};
static WORD indices[] = {0, 1, 2, 2, 3, 0};
static const struct
{
D3DMATRIX *world_matrix;
void *quad;
DWORD expected;
const char *message;
}
tests[] =
{
{&mat, nquad, 0x000000ff, "Lit quad with light"},
{&mat_singular, nquad, 0x000000b4, "Lit quad with singular world matrix"},
{&mat_transf, rotatedquad, 0x000000ff, "Lit quad with transformation matrix"},
{&mat_nonaffine, translatedquad, 0x000000ff, "Lit quad with non-affine matrix"},
};
HWND window;
IDirect3D2 *d3d;
IDirect3DDevice2 *device;
IDirectDraw2 *ddraw;
IDirectDrawSurface *rt;
IDirect3DViewport2 *viewport;
IDirect3DMaterial2 *material;
IDirect3DLight *light;
D3DMATERIALHANDLE mat_handle;
D3DLIGHT2 light_desc;
HRESULT hr;
D3DCOLOR color;
ULONG refcount;
unsigned int i;
window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
0, 0, 640, 480, 0, 0, 0, 0);
ddraw = create_ddraw();
ok(!!ddraw, "Failed to create a ddraw object.\n");
if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
{
skip("Failed to create a 3D device, skipping test.\n");
DestroyWindow(window);
return;
}
hr = IDirect3DDevice2_GetDirect3D(device, &d3d);
ok(SUCCEEDED(hr), "Failed to get D3D interface, hr %#x.\n", hr);
hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
viewport = create_viewport(device, 0, 0, 640, 480);
hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
material = create_diffuse_material(device, 1.0f, 1.0f, 1.0f, 1.0f);
viewport_set_background(device, viewport, material);
hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
ok(SUCCEEDED(hr), "Failed to set view transform, hr %#x.\n", hr);
hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
ok(SUCCEEDED(hr), "Failed to disable clipping, hr %#x.\n", hr);
hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
ok(SUCCEEDED(hr), "Failed to disable zbuffer, hr %#x.\n", hr);
hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
ok(SUCCEEDED(hr), "Failed to disable culling, hr %#x.\n", hr);
hr = IDirect3DDevice2_BeginScene(device);
ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
/* There is no D3DRENDERSTATE_LIGHTING on ddraw < 7. */
hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
hr = IDirect3DDevice2_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, D3DVT_LVERTEX, unlitquad,
4, indices, 6, 0);
ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_LIGHTING, TRUE);
ok(SUCCEEDED(hr), "Failed to enable lighting, hr %#x.\n", hr);
hr = IDirect3DDevice2_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, D3DVT_LVERTEX, litquad,
4, indices, 6, 0);
ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
hr = IDirect3DDevice2_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, D3DVT_VERTEX, unlitnquad,
4, indices, 6, 0);
ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_LIGHTING, TRUE);
ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
hr = IDirect3DDevice2_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, D3DVT_VERTEX, litnquad,
4, indices, 6, 0);
ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
hr = IDirect3DDevice2_EndScene(device);
ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
color = get_surface_color(rt, 160, 360);
ok(color == 0x00ff0000, "Unlit quad without normals has color 0x%08x.\n", color);
color = get_surface_color(rt, 160, 120);
ok(color == 0x0000ff00, "Lit quad without normals has color 0x%08x.\n", color);
color = get_surface_color(rt, 480, 360);
ok(color == 0x00ffffff, "Unlit quad with normals has color 0x%08x.\n", color);
color = get_surface_color(rt, 480, 120);
ok(color == 0x00ffffff, "Lit quad with normals has color 0x%08x.\n", color);
hr = IDirect3DMaterial2_GetHandle(material, device, &mat_handle);
ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
hr = IDirect3DDevice2_SetLightState(device, D3DLIGHTSTATE_MATERIAL, mat_handle);
ok(SUCCEEDED(hr), "Failed to set material state, hr %#x.\n", hr);
hr = IDirect3D2_CreateLight(d3d, &light, NULL);
ok(SUCCEEDED(hr), "Failed to create a light object, hr %#x.\n", hr);
memset(&light_desc, 0, sizeof(light_desc));
light_desc.dwSize = sizeof(light_desc);
light_desc.dltType = D3DLIGHT_DIRECTIONAL;
U1(U(light_desc).dcvColor).r = 0.0f;
U2(U(light_desc).dcvColor).g = 0.0f;
U3(U(light_desc).dcvColor).b = 1.0f;
U4(U(light_desc).dcvColor).a = 1.0f;
light_desc.dvDirection.z = 1.0f;
hr = IDirect3DLight_SetLight(light, (D3DLIGHT *)&light_desc);
ok(SUCCEEDED(hr), "Failed to set light, hr %#x.\n", hr);
hr = IDirect3DViewport2_AddLight(viewport, light);
ok(SUCCEEDED(hr), "Failed to add a light to the viewport, hr %#x.\n", hr);
hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
hr = IDirect3DDevice2_BeginScene(device);
ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
hr = IDirect3DDevice2_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, D3DVT_VERTEX, nquad,
4, indices, 6, 0);
ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
hr = IDirect3DDevice2_EndScene(device);
ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
color = get_surface_color(rt, 320, 240);
ok(color == 0x00000000, "Lit quad with no light has color 0x%08x.\n", color);
light_desc.dwFlags = D3DLIGHT_ACTIVE;
hr = IDirect3DLight_SetLight(light, (D3DLIGHT *)&light_desc);
ok(SUCCEEDED(hr), "Failed to set light, hr %#x.\n", hr);
for (i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i)
{
hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_WORLD, tests[i].world_matrix);
ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
hr = IDirect3DDevice2_BeginScene(device);
ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
hr = IDirect3DDevice2_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, D3DVT_VERTEX,
tests[i].quad, 4, indices, 6, 0);
ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
hr = IDirect3DDevice2_EndScene(device);
ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
color = get_surface_color(rt, 320, 240);
ok(color == tests[i].expected, "%s has color 0x%08x.\n", tests[i].message, color);
}
IDirect3DLight_Release(light);
destroy_material(material);
destroy_viewport(device, viewport);
IDirectDrawSurface2_Release(rt);
refcount = IDirect3DDevice2_Release(device);
ok(!refcount, "Device has %u references left.\n", refcount);
IDirect3D2_Release(d3d);
IDirectDraw2_Release(ddraw);
ok(!refcount, "Ddraw object has %u references left.\n", refcount);
DestroyWindow(window);
}
static void test_palette_gdi(void)
{
IDirectDrawSurface *surface, *primary;
@ -7948,6 +8215,7 @@ START_TEST(ddraw2)
test_palette_complex();
test_p8_rgb_blit();
test_material();
test_lighting();
test_palette_gdi();
test_palette_alpha();
test_lost_device();

View File

@ -3725,6 +3725,283 @@ static void test_draw_strided(void)
DestroyWindow(window);
}
static void test_lighting(void)
{
static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
static D3DMATRIX mat =
{
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f,
},
mat_singular =
{
1.0f, 0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.5f, 1.0f,
},
mat_transf =
{
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
-1.0f, 0.0f, 0.0f, 0.0f,
10.f, 10.0f, 10.0f, 1.0f,
},
mat_nonaffine =
{
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, -1.0f,
10.f, 10.0f, 10.0f, 0.0f,
};
static struct
{
struct vec3 position;
DWORD diffuse;
}
unlitquad[] =
{
{{-1.0f, -1.0f, 0.1f}, 0xffff0000},
{{-1.0f, 0.0f, 0.1f}, 0xffff0000},
{{ 0.0f, 0.0f, 0.1f}, 0xffff0000},
{{ 0.0f, -1.0f, 0.1f}, 0xffff0000},
},
litquad[] =
{
{{-1.0f, 0.0f, 0.1f}, 0xff00ff00},
{{-1.0f, 1.0f, 0.1f}, 0xff00ff00},
{{ 0.0f, 1.0f, 0.1f}, 0xff00ff00},
{{ 0.0f, 0.0f, 0.1f}, 0xff00ff00},
};
static struct
{
struct vec3 position;
struct vec3 normal;
DWORD diffuse;
}
unlitnquad[] =
{
{{0.0f, -1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
{{0.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
{{1.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
{{1.0f, -1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
},
litnquad[] =
{
{{0.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xffffff00},
{{0.0f, 1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xffffff00},
{{1.0f, 1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xffffff00},
{{1.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xffffff00},
},
nquad[] =
{
{{-1.0f, -1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
{{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
{{ 1.0f, 1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
{{ 1.0f, -1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
},
rotatedquad[] =
{
{{-10.0f, -11.0f, 11.0f}, {-1.0f, 0.0f, 0.0f}, 0xff0000ff},
{{-10.0f, -9.0f, 11.0f}, {-1.0f, 0.0f, 0.0f}, 0xff0000ff},
{{-10.0f, -9.0f, 9.0f}, {-1.0f, 0.0f, 0.0f}, 0xff0000ff},
{{-10.0f, -11.0f, 9.0f}, {-1.0f, 0.0f, 0.0f}, 0xff0000ff},
},
translatedquad[] =
{
{{-11.0f, -11.0f, -10.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
{{-11.0f, -9.0f, -10.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
{{ -9.0f, -9.0f, -10.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
{{ -9.0f, -11.0f, -10.0f}, {0.0f, 0.0f, -1.0f}, 0xff0000ff},
};
static WORD indices[] = {0, 1, 2, 2, 3, 0};
static const struct
{
D3DMATRIX *world_matrix;
void *quad;
DWORD expected;
const char *message;
}
tests[] =
{
{&mat, nquad, 0x000000ff, "Lit quad with light"},
{&mat_singular, nquad, 0x000000b4, "Lit quad with singular world matrix"},
{&mat_transf, rotatedquad, 0x000000ff, "Lit quad with transformation matrix"},
{&mat_nonaffine, translatedquad, 0x000000ff, "Lit quad with non-affine matrix"},
};
HWND window;
IDirect3D3 *d3d;
IDirect3DDevice3 *device;
IDirectDrawSurface4 *rt;
IDirect3DViewport3 *viewport;
IDirect3DMaterial3 *material;
IDirect3DLight *light;
D3DMATERIALHANDLE mat_handle;
D3DLIGHT2 light_desc;
HRESULT hr;
DWORD fvf = D3DFVF_XYZ | D3DFVF_DIFFUSE;
DWORD nfvf = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_NORMAL;
D3DCOLOR color;
ULONG refcount;
unsigned int i;
window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
0, 0, 640, 480, 0, 0, 0, 0);
if (!(device = create_device(window, DDSCL_NORMAL)))
{
skip("Failed to create a 3D device, skipping test.\n");
DestroyWindow(window);
return;
}
hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
ok(SUCCEEDED(hr), "Failed to get D3D interface, hr %#x.\n", hr);
hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
viewport = create_viewport(device, 0, 0, 640, 480);
hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
ok(SUCCEEDED(hr), "Failed to set world transformation, hr %#x.\n", hr);
hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
ok(SUCCEEDED(hr), "Failed to set view transformation, hr %#x.\n", hr);
hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
ok(SUCCEEDED(hr), "Failed to set projection transformation, hr %#x.\n", hr);
hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
ok(SUCCEEDED(hr), "Failed to disable clipping, hr %#x.\n", hr);
hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
ok(SUCCEEDED(hr), "Failed to disable zbuffer, hr %#x.\n", hr);
hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_STENCILENABLE, FALSE);
ok(SUCCEEDED(hr), "Failed to disable stencil buffer, hr %#x.\n", hr);
hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
ok(SUCCEEDED(hr), "Failed to disable culling, hr %#x.\n", hr);
hr = IDirect3DDevice3_BeginScene(device);
ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
/* There is no D3DRENDERSTATE_LIGHTING on ddraw < 7. */
hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, fvf, unlitquad, 4,
indices, 6, 0);
ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LIGHTING, TRUE);
ok(SUCCEEDED(hr), "Failed to enable lighting, hr %#x.\n", hr);
hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, fvf, litquad, 4,
indices, 6, 0);
ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, nfvf, unlitnquad, 4,
indices, 6, 0);
ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LIGHTING, TRUE);
ok(SUCCEEDED(hr), "Failed to enable lighting, hr %#x.\n", hr);
hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, nfvf, litnquad, 4,
indices, 6, 0);
ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
hr = IDirect3DDevice3_EndScene(device);
ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
color = get_surface_color(rt, 160, 360);
ok(color == 0x00ff0000, "Unlit quad without normals has color 0x%08x.\n", color);
color = get_surface_color(rt, 160, 120);
ok(color == 0x0000ff00, "Lit quad without normals has color 0x%08x.\n", color);
color = get_surface_color(rt, 480, 360);
ok(color == 0x000000ff, "Unlit quad with normals has color 0x%08x.\n", color);
color = get_surface_color(rt, 480, 120);
ok(color == 0x00ffff00, "Lit quad with normals has color 0x%08x.\n", color);
material = create_diffuse_material(device, 0.0f, 1.0f, 0.0f, 0.0f);
hr = IDirect3DMaterial3_GetHandle(material, device, &mat_handle);
ok(SUCCEEDED(hr), "Failed to set material state, hr %#x.\n", hr);
hr = IDirect3DDevice3_SetLightState(device, D3DLIGHTSTATE_MATERIAL, mat_handle);
ok(SUCCEEDED(hr), "Failed to set material state, hr %#x.\n", hr);
hr = IDirect3D3_CreateLight(d3d, &light, NULL);
ok(SUCCEEDED(hr), "Failed to create a light object, hr %#x.\n", hr);
memset(&light_desc, 0, sizeof(light_desc));
light_desc.dwSize = sizeof(light_desc);
light_desc.dltType = D3DLIGHT_DIRECTIONAL;
U1(U(light_desc).dcvColor).r = 1.0f;
U2(U(light_desc).dcvColor).g = 1.0f;
U3(U(light_desc).dcvColor).b = 1.0f;
U4(U(light_desc).dcvColor).a = 1.0f;
light_desc.dvDirection.z = 1.0f;
hr = IDirect3DLight_SetLight(light, (D3DLIGHT *)&light_desc);
ok(SUCCEEDED(hr), "Failed to set light, hr %#x.\n", hr);
hr = IDirect3DViewport3_AddLight(viewport, light);
ok(SUCCEEDED(hr), "Failed to add a light to the viewport, hr %#x.\n", hr);
hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
hr = IDirect3DDevice3_BeginScene(device);
ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, nfvf, nquad,
4, indices, 6, 0);
ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
hr = IDirect3DDevice3_EndScene(device);
ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
color = get_surface_color(rt, 320, 240);
ok(color == 0x00000000, "Lit quad with no light has color 0x%08x.\n", color);
light_desc.dwFlags = D3DLIGHT_ACTIVE;
hr = IDirect3DLight_SetLight(light, (D3DLIGHT *)&light_desc);
ok(SUCCEEDED(hr), "Failed to set light, hr %#x.\n", hr);
for (i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i)
{
hr = IDirect3DDevice3_SetTransform(device, D3DTRANSFORMSTATE_WORLD, tests[i].world_matrix);
ok(SUCCEEDED(hr), "Failed to set world transformation, hr %#x.\n", hr);
hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
hr = IDirect3DDevice3_BeginScene(device);
ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
hr = IDirect3DDevice3_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, nfvf, tests[i].quad,
4, indices, 6, 0);
ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
hr = IDirect3DDevice3_EndScene(device);
ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
color = get_surface_color(rt, 320, 240);
ok(color == tests[i].expected, "%s has color 0x%08x.\n", tests[i].message, color);
}
hr = IDirect3DViewport3_DeleteLight(viewport, light);
ok(SUCCEEDED(hr), "Failed to remove a light from the viewport, hr %#x.\n", hr);
IDirect3DLight_Release(light);
destroy_material(material);
IDirect3DViewport3_Release(viewport);
IDirectDrawSurface4_Release(rt);
refcount = IDirect3DDevice3_Release(device);
ok(!refcount, "Device has %u references left.\n", refcount);
IDirect3D3_Release(d3d);
DestroyWindow(window);
}
static void test_clear_rect_count(void)
{
IDirectDrawSurface4 *rt;
@ -8860,6 +9137,7 @@ START_TEST(ddraw4)
test_vb_discard();
test_coop_level_multi_window();
test_draw_strided();
test_lighting();
test_clear_rect_count();
test_coop_level_versions();
test_lighting_interface_versions();