ddraw/tests: Add a depth read-back test.

Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Henri Verbeet 2018-01-05 18:53:13 +01:00 committed by Alexandre Julliard
parent bc75bec270
commit f427714bf9
4 changed files with 555 additions and 0 deletions

View File

@ -217,6 +217,20 @@ static void destroy_window_thread(struct create_window_thread_param *p)
CloseHandle(p->thread);
}
static IDirectDrawSurface *get_depth_stencil(IDirect3DDevice *device)
{
IDirectDrawSurface *rt, *ret;
DDSCAPS caps = {DDSCAPS_ZBUFFER};
HRESULT hr;
hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
hr = IDirectDrawSurface_GetAttachedSurface(rt, &caps, &ret);
ok(SUCCEEDED(hr) || hr == DDERR_NOTFOUND, "Failed to get the z buffer, hr %#x.\n", hr);
IDirectDrawSurface_Release(rt);
return ret;
}
static HRESULT set_display_mode(IDirectDraw *ddraw, DWORD width, DWORD height)
{
if (SUCCEEDED(IDirectDraw_SetDisplayMode(ddraw, width, height, 32)))
@ -10779,6 +10793,125 @@ done:
DestroyWindow(window);
}
static void test_depth_readback(void)
{
DWORD depth, expected_depth, max_diff, z_depth, z_mask;
IDirect3DExecuteBuffer *execute_buffer;
IDirect3DMaterial *blue_background;
D3DEXECUTEBUFFERDESC exec_desc;
IDirectDrawSurface *rt, *ds;
IDirect3DViewport *viewport;
DDSURFACEDESC surface_desc;
IDirect3DDevice *device;
IDirectDraw *ddraw;
unsigned int x, y;
UINT inst_length;
ULONG refcount;
HWND window;
HRESULT hr;
void *ptr;
static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
static D3DLVERTEX quad[] =
{
{{-1.0f}, {-1.0f}, {0.1f}, 0, {0xff00ff00}},
{{-1.0f}, { 1.0f}, {0.0f}, 0, {0xff00ff00}},
{{ 1.0f}, {-1.0f}, {1.0f}, 0, {0xff00ff00}},
{{ 1.0f}, { 1.0f}, {0.9f}, 0, {0xff00ff00}},
};
window = create_window();
ok(!!window, "Failed to create a window.\n");
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 D3D device, skipping tests.\n");
IDirectDraw_Release(ddraw);
DestroyWindow(window);
return;
}
hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
z_depth = get_device_z_depth(device);
z_mask = 0xffffffff >> (32 - z_depth);
ds = get_depth_stencil(device);
/* Changing depth buffers is hard in d3d1, so we only test with the
* initial depth buffer here. */
blue_background = create_diffuse_material(device, 0.0f, 0.0f, 1.0f, 1.0f);
viewport = create_viewport(device, 0, 0, 640, 480);
viewport_set_background(device, viewport, blue_background);
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, quad, sizeof(quad));
ptr = (BYTE *)exec_desc.lpData + sizeof(quad);
emit_process_vertices(&ptr, D3DPROCESSVERTICES_TRANSFORM, 0, 4);
emit_tquad(&ptr, 0);
emit_end(&ptr);
inst_length = ((BYTE *)ptr - sizeof(quad)) - (BYTE *)exec_desc.lpData;
hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#x.\n", hr);
hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER);
ok(SUCCEEDED(hr), "Failed to clear, 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(quad), inst_length);
hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_UNCLIPPED);
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);
memset(&surface_desc, 0, sizeof(surface_desc));
surface_desc.dwSize = sizeof(surface_desc);
hr = IDirectDrawSurface_Lock(ds, NULL, &surface_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
for (y = 60; y < 480; y += 120)
{
for (x = 80; x < 640; x += 160)
{
ptr = (BYTE *)surface_desc.lpSurface
+ y * U1(surface_desc).lPitch
+ x * (z_depth == 16 ? 2 : 4);
depth = *((DWORD *)ptr) & z_mask;
expected_depth = (x * (0.9 / 640.0) + y * (0.1 / 480.0)) * z_mask;
max_diff = ((0.5f * 0.9f) / 640.0f) * z_mask;
ok(abs(expected_depth - depth) <= max_diff,
"z_depth %u: Got depth 0x%08x (diff %d), expected 0x%08x+/-%u, at %u, %u.\n",
z_depth, depth, expected_depth - depth, expected_depth, max_diff, x, y);
}
}
hr = IDirectDrawSurface_Unlock(ds, NULL);
ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
IDirect3DExecuteBuffer_Release(execute_buffer);
destroy_viewport(device, viewport);
destroy_material(blue_background);
IDirectDrawSurface_Release(ds);
IDirect3DDevice_Release(device);
refcount = IDirectDrawSurface_Release(rt);
ok(!refcount, "Device has %u references left.\n", refcount);
IDirectDraw_Release(ddraw);
DestroyWindow(window);
}
START_TEST(ddraw1)
{
DDDEVICEIDENTIFIER identifier;
@ -10877,4 +11010,5 @@ START_TEST(ddraw1)
test_surface_desc_size();
test_texture_load();
test_ck_operation();
test_depth_readback();
}

View File

@ -12155,6 +12155,137 @@ done:
DestroyWindow(window);
}
static void test_depth_readback(void)
{
DWORD depth, expected_depth, max_diff;
IDirect3DMaterial2 *blue_background;
IDirectDrawSurface *rt, *ds;
IDirect3DViewport2 *viewport;
DDSURFACEDESC surface_desc;
IDirect3DDevice2 *device;
unsigned int i, x, y;
IDirectDraw2 *ddraw;
ULONG refcount;
HWND window;
HRESULT hr;
void *ptr;
static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
static D3DLVERTEX quad[] =
{
{{-1.0f}, {-1.0f}, {0.1f}, 0, {0xff00ff00}},
{{-1.0f}, { 1.0f}, {0.0f}, 0, {0xff00ff00}},
{{ 1.0f}, {-1.0f}, {1.0f}, 0, {0xff00ff00}},
{{ 1.0f}, { 1.0f}, {0.9f}, 0, {0xff00ff00}},
};
static const struct
{
unsigned int z_depth, z_mask;
}
tests[] =
{
{16, 0x0000ffff},
{24, 0x00ffffff},
{32, 0xffffffff},
};
window = create_window();
ok(!!window, "Failed to create a window.\n");
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 D3D device, skipping tests.\n");
IDirectDraw2_Release(ddraw);
DestroyWindow(window);
return;
}
hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
blue_background = create_diffuse_material(device, 0.0f, 0.0f, 1.0f, 1.0f);
viewport = create_viewport(device, 0, 0, 640, 480);
viewport_set_background(device, viewport, blue_background);
hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
ds = get_depth_stencil(device);
hr = IDirectDrawSurface_DeleteAttachedSurface(rt, 0, ds);
ok(SUCCEEDED(hr), "Failed to detach depth buffer, hr %#x.\n", hr);
IDirectDrawSurface_Release(ds);
for (i = 0; i < ARRAY_SIZE(tests); ++i)
{
memset(&surface_desc, 0, sizeof(surface_desc));
surface_desc.dwSize = sizeof(surface_desc);
surface_desc.dwFlags = DDSD_CAPS | DDSD_ZBUFFERBITDEPTH | DDSD_WIDTH | DDSD_HEIGHT;
surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY;
U2(surface_desc).dwZBufferBitDepth = tests[i].z_depth;
surface_desc.dwWidth = 640;
surface_desc.dwHeight = 480;
hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &ds, NULL);
if (FAILED(hr))
{
skip("Format %u not supported, skipping test.\n", i);
continue;
}
hr = IDirectDrawSurface_AddAttachedSurface(rt, ds);
ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
hr = IDirect3DDevice2_SetRenderTarget(device, rt, 0);
ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER);
ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
hr = IDirect3DDevice2_BeginScene(device);
ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_LVERTEX, quad, 4, 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);
memset(&surface_desc, 0, sizeof(surface_desc));
surface_desc.dwSize = sizeof(surface_desc);
hr = IDirectDrawSurface_Lock(ds, NULL, &surface_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
for (y = 60; y < 480; y += 120)
{
for (x = 80; x < 640; x += 160)
{
ptr = (BYTE *)surface_desc.lpSurface
+ y * U1(surface_desc).lPitch
+ x * (tests[i].z_depth == 16 ? 2 : 4);
depth = *((DWORD *)ptr) & tests[i].z_mask;
expected_depth = (x * (0.9 / 640.0) + y * (0.1 / 480.0)) * tests[i].z_mask;
max_diff = ((0.5f * 0.9f) / 640.0f) * tests[i].z_mask;
ok(abs(expected_depth - depth) <= max_diff,
"Test %u: Got depth 0x%08x (diff %d), expected 0x%08x+/-%u, at %u, %u.\n",
i, depth, expected_depth - depth, expected_depth, max_diff, x, y);
}
}
hr = IDirectDrawSurface_Unlock(ds, NULL);
ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
hr = IDirectDrawSurface_DeleteAttachedSurface(rt, 0, ds);
ok(SUCCEEDED(hr), "Failed to detach depth buffer, hr %#x.\n", hr);
IDirectDrawSurface_Release(ds);
}
destroy_viewport(device, viewport);
destroy_material(blue_background);
IDirectDrawSurface_Release(rt);
refcount = IDirect3DDevice2_Release(device);
ok(!refcount, "Device has %u references left.\n", refcount);
IDirectDraw2_Release(ddraw);
DestroyWindow(window);
}
START_TEST(ddraw2)
{
DDDEVICEIDENTIFIER identifier;
@ -12261,4 +12392,5 @@ START_TEST(ddraw2)
test_display_mode_surface_pixel_format();
test_surface_desc_size();
test_ck_operation();
test_depth_readback();
}

View File

@ -14207,6 +14207,153 @@ static void test_map_synchronisation(void)
DestroyWindow(window);
}
static void test_depth_readback(void)
{
DWORD depth, expected_depth, max_diff;
IDirectDrawSurface4 *rt, *ds;
IDirect3DViewport3 *viewport;
DDSURFACEDESC2 surface_desc;
IDirect3DDevice3 *device;
unsigned int i, x, y;
IDirectDraw4 *ddraw;
IDirect3D3 *d3d;
ULONG refcount;
HWND window;
HRESULT hr;
RECT r;
static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
static struct
{
struct vec3 position;
DWORD diffuse;
}
quad[] =
{
{{-1.0f, -1.0f, 0.1f}, 0xff00ff00},
{{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
{{ 1.0f, -1.0f, 1.0f}, 0xff00ff00},
{{ 1.0f, 1.0f, 0.9f}, 0xff00ff00},
};
static const struct
{
unsigned int z_depth, s_depth, z_mask, s_mask;
BOOL todo;
}
tests[] =
{
{16, 0, 0x0000ffff, 0x00000000},
{24, 0, 0x00ffffff, 0x00000000},
{32, 0, 0x00ffffff, 0x00000000},
{32, 8, 0x00ffffff, 0xff000000, TRUE},
{32, 0, 0xffffffff, 0x00000000},
};
window = create_window();
ok(!!window, "Failed to create a window.\n");
if (!(device = create_device(window, DDSCL_NORMAL)))
{
skip("Failed to create a D3D device, skipping tests.\n");
DestroyWindow(window);
return;
}
hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#x.\n", hr);
hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
ok(SUCCEEDED(hr), "Failed to get ddraw 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 = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
ds = get_depth_stencil(device);
hr = IDirectDrawSurface4_DeleteAttachedSurface(rt, 0, ds);
ok(SUCCEEDED(hr), "Failed to detach depth buffer, hr %#x.\n", hr);
IDirectDrawSurface4_Release(ds);
for (i = 0; i < ARRAY_SIZE(tests); ++i)
{
memset(&surface_desc, 0, sizeof(surface_desc));
surface_desc.dwSize = sizeof(surface_desc);
surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY;
U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
if (tests[i].s_depth)
U4(surface_desc).ddpfPixelFormat.dwFlags |= DDPF_STENCILBUFFER;
U1(U4(surface_desc).ddpfPixelFormat).dwZBufferBitDepth = tests[i].z_depth;
U2(U4(surface_desc).ddpfPixelFormat).dwStencilBitDepth = tests[i].s_depth;
U3(U4(surface_desc).ddpfPixelFormat).dwZBitMask = tests[i].z_mask;
U4(U4(surface_desc).ddpfPixelFormat).dwStencilBitMask = tests[i].s_mask;
surface_desc.dwWidth = 640;
surface_desc.dwHeight = 480;
hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &ds, NULL);
if (FAILED(hr))
{
skip("Format %u not supported, skipping test.\n", i);
continue;
}
hr = IDirectDrawSurface_AddAttachedSurface(rt, ds);
ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
hr = IDirect3DDevice3_SetRenderTarget(device, rt, 0);
ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect,
D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff0000ff, 1.0f, 0);
ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
hr = IDirect3DDevice3_BeginScene(device);
ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE, quad, 4, 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);
for (y = 60; y < 480; y += 120)
{
for (x = 80; x < 640; x += 160)
{
SetRect(&r, x, y, x + 1, y + 1);
memset(&surface_desc, 0, sizeof(surface_desc));
surface_desc.dwSize = sizeof(surface_desc);
hr = IDirectDrawSurface4_Lock(ds, &r, &surface_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
depth = *((DWORD *)surface_desc.lpSurface) & tests[i].z_mask;
expected_depth = (x * (0.9 / 640.0) + y * (0.1 / 480.0)) * tests[i].z_mask;
max_diff = ((0.5f * 0.9f) / 640.0f) * tests[i].z_mask;
todo_wine_if(tests[i].todo)
ok(abs(expected_depth - depth) <= max_diff,
"Test %u: Got depth 0x%08x (diff %d), expected 0x%08x+/-%u, at %u, %u.\n",
i, depth, expected_depth - depth, expected_depth, max_diff, x, y);
hr = IDirectDrawSurface4_Unlock(ds, &r);
ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
}
}
hr = IDirectDrawSurface4_DeleteAttachedSurface(rt, 0, ds);
ok(SUCCEEDED(hr), "Failed to detach depth buffer, hr %#x.\n", hr);
IDirectDrawSurface4_Release(ds);
}
destroy_viewport(device, viewport);
IDirectDrawSurface4_Release(rt);
IDirectDraw4_Release(ddraw);
IDirect3D3_Release(d3d);
refcount = IDirect3DDevice3_Release(device);
ok(!refcount, "Device has %u references left.\n", refcount);
DestroyWindow(window);
}
START_TEST(ddraw4)
{
DDDEVICEIDENTIFIER identifier;
@ -14326,4 +14473,5 @@ START_TEST(ddraw4)
test_vb_refcount();
test_compute_sphere_visibility();
test_map_synchronisation();
test_depth_readback();
}

View File

@ -13585,6 +13585,146 @@ done:
DestroyWindow(window);
}
static void test_depth_readback(void)
{
DWORD depth, expected_depth, max_diff;
IDirectDrawSurface7 *rt, *ds;
DDSURFACEDESC2 surface_desc;
IDirect3DDevice7 *device;
unsigned int i, x, y;
IDirectDraw7 *ddraw;
IDirect3D7 *d3d;
ULONG refcount;
HWND window;
HRESULT hr;
RECT r;
static struct
{
struct vec3 position;
DWORD diffuse;
}
quad[] =
{
{{-1.0f, -1.0f, 0.1f}, 0xff00ff00},
{{-1.0f, 1.0f, 0.0f}, 0xff00ff00},
{{ 1.0f, -1.0f, 1.0f}, 0xff00ff00},
{{ 1.0f, 1.0f, 0.9f}, 0xff00ff00},
};
static const struct
{
unsigned int z_depth, s_depth, z_mask, s_mask;
BOOL todo;
}
tests[] =
{
{16, 0, 0x0000ffff, 0x00000000},
{24, 0, 0x00ffffff, 0x00000000},
{32, 0, 0x00ffffff, 0x00000000},
{32, 8, 0x00ffffff, 0xff000000, TRUE},
{32, 0, 0xffffffff, 0x00000000},
};
window = create_window();
ok(!!window, "Failed to create a window.\n");
if (!(device = create_device(window, DDSCL_NORMAL)))
{
skip("Failed to create a D3D device, skipping tests.\n");
DestroyWindow(window);
return;
}
hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr);
hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
ds = get_depth_stencil(device);
hr = IDirectDrawSurface7_DeleteAttachedSurface(rt, 0, ds);
ok(SUCCEEDED(hr), "Failed to detach depth buffer, hr %#x.\n", hr);
IDirectDrawSurface7_Release(ds);
for (i = 0; i < ARRAY_SIZE(tests); ++i)
{
memset(&surface_desc, 0, sizeof(surface_desc));
surface_desc.dwSize = sizeof(surface_desc);
surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT;
surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY;
U4(surface_desc).ddpfPixelFormat.dwSize = sizeof(U4(surface_desc).ddpfPixelFormat);
U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
if (tests[i].s_depth)
U4(surface_desc).ddpfPixelFormat.dwFlags |= DDPF_STENCILBUFFER;
U1(U4(surface_desc).ddpfPixelFormat).dwZBufferBitDepth = tests[i].z_depth;
U2(U4(surface_desc).ddpfPixelFormat).dwStencilBitDepth = tests[i].s_depth;
U3(U4(surface_desc).ddpfPixelFormat).dwZBitMask = tests[i].z_mask;
U4(U4(surface_desc).ddpfPixelFormat).dwStencilBitMask = tests[i].s_mask;
surface_desc.dwWidth = 640;
surface_desc.dwHeight = 480;
hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &ds, NULL);
if (FAILED(hr))
{
skip("Format %u not supported, skipping test.\n", i);
continue;
}
hr = IDirectDrawSurface_AddAttachedSurface(rt, ds);
ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x.\n", hr);
hr = IDirect3DDevice7_SetRenderTarget(device, rt, 0);
ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff0000ff, 1.0f, 0);
ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
hr = IDirect3DDevice7_BeginScene(device);
ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE, quad, 4, 0);
ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
hr = IDirect3DDevice7_EndScene(device);
ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
for (y = 60; y < 480; y += 120)
{
for (x = 80; x < 640; x += 160)
{
SetRect(&r, x, y, x + 1, y + 1);
memset(&surface_desc, 0, sizeof(surface_desc));
surface_desc.dwSize = sizeof(surface_desc);
hr = IDirectDrawSurface7_Lock(ds, &r, &surface_desc, DDLOCK_READONLY, NULL);
ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
depth = *((DWORD *)surface_desc.lpSurface) & tests[i].z_mask;
expected_depth = (x * (0.9 / 640.0) + y * (0.1 / 480.0)) * tests[i].z_mask;
max_diff = ((0.5f * 0.9f) / 640.0f) * tests[i].z_mask;
todo_wine_if(tests[i].todo)
ok(abs(expected_depth - depth) <= max_diff,
"Test %u: Got depth 0x%08x (diff %d), expected 0x%08x+/-%u, at %u, %u.\n",
i, depth, expected_depth - depth, expected_depth, max_diff, x, y);
hr = IDirectDrawSurface7_Unlock(ds, &r);
ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
}
}
hr = IDirectDrawSurface7_DeleteAttachedSurface(rt, 0, ds);
ok(SUCCEEDED(hr), "Failed to detach depth buffer, hr %#x.\n", hr);
IDirectDrawSurface7_Release(ds);
}
IDirectDrawSurface7_Release(rt);
IDirectDraw7_Release(ddraw);
IDirect3D7_Release(d3d);
refcount = IDirect3DDevice7_Release(device);
ok(!refcount, "Device has %u references left.\n", refcount);
DestroyWindow(window);
}
START_TEST(ddraw7)
{
DDDEVICEIDENTIFIER2 identifier;
@ -13714,4 +13854,5 @@ START_TEST(ddraw7)
test_compute_sphere_visibility();
test_clip_planes_limits();
test_map_synchronisation();
test_depth_readback();
}