ddraw/tests: Make test_depth_readback work on Nvidia GPUs on Windows.

Signed-off-by: Stefan Dösinger <stefan@codeweavers.com>
Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Stefan Dösinger 2018-01-22 17:34:54 +01:00 committed by Alexandre Julliard
parent 23800d67e0
commit d877dce7a2
4 changed files with 73 additions and 9 deletions

View File

@ -10840,6 +10840,18 @@ static void test_depth_readback(void)
ok(!!window, "Failed to create a window.\n"); ok(!!window, "Failed to create a window.\n");
ddraw = create_ddraw(); ddraw = create_ddraw();
ok(!!ddraw, "Failed to create a ddraw object.\n"); ok(!!ddraw, "Failed to create a ddraw object.\n");
if (ddraw_is_nvidia(ddraw))
{
/* ddraw1 only has access to D16 Z buffers (and D24 ones, which are even more
* broken on Nvidia), so don't even attempt to run this test on Nvidia cards
* because some of them have broken D16 readback. See the ddraw7 version of
* this test for a more detailed comment. */
skip("Some Nvidia GPUs have broken D16 readback, skipping.\n");
IDirectDraw_Release(ddraw);
DestroyWindow(window);
return;
}
if (!(device = create_device(ddraw, window, DDSCL_NORMAL))) if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
{ {
skip("Failed to create a D3D device, skipping tests.\n"); skip("Failed to create a D3D device, skipping tests.\n");

View File

@ -12211,7 +12211,7 @@ static void test_set_render_state(void)
static void test_depth_readback(void) static void test_depth_readback(void)
{ {
DWORD depth, expected_depth, max_diff; DWORD depth, expected_depth, max_diff, passed_fmts = 0;
IDirect3DMaterial2 *blue_background; IDirect3DMaterial2 *blue_background;
IDirectDrawSurface *rt, *ds; IDirectDrawSurface *rt, *ds;
IDirect3DViewport2 *viewport; IDirect3DViewport2 *viewport;
@ -12223,6 +12223,7 @@ static void test_depth_readback(void)
HWND window; HWND window;
HRESULT hr; HRESULT hr;
void *ptr; void *ptr;
BOOL all_pass;
static D3DRECT clear_rect = {{0}, {0}, {640}, {480}}; static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
static D3DLVERTEX quad[] = static D3DLVERTEX quad[] =
@ -12307,6 +12308,7 @@ static void test_depth_readback(void)
hr = IDirectDrawSurface_Lock(ds, NULL, &surface_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL); hr = IDirectDrawSurface_Lock(ds, NULL, &surface_desc, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
all_pass = TRUE;
for (y = 60; y < 480; y += 120) for (y = 60; y < 480; y += 120)
{ {
for (x = 80; x < 640; x += 160) for (x = 80; x < 640; x += 160)
@ -12317,20 +12319,30 @@ static void test_depth_readback(void)
depth = *((DWORD *)ptr) & tests[i].z_mask; depth = *((DWORD *)ptr) & tests[i].z_mask;
expected_depth = (x * (0.9 / 640.0) + y * (0.1 / 480.0)) * 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; max_diff = ((0.5f * 0.9f) / 640.0f) * tests[i].z_mask;
ok(abs(expected_depth - depth) <= max_diff, /* The ddraw2 version of this test behaves similarly to the ddraw7 version on Nvidia GPUs,
* except that we only have D16 (broken on geforce 9) and D24X8 (broken on geforce 7) available.
* Accept all nvidia GPUs as broken here, but still expect one of the formats to pass. */
ok(abs(expected_depth - depth) <= max_diff || ddraw_is_nvidia(ddraw),
"Test %u: Got depth 0x%08x (diff %d), expected 0x%08x+/-%u, at %u, %u.\n", "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); i, depth, expected_depth - depth, expected_depth, max_diff, x, y);
if (abs(expected_depth - depth) > max_diff)
all_pass = FALSE;
} }
} }
hr = IDirectDrawSurface_Unlock(ds, NULL); hr = IDirectDrawSurface_Unlock(ds, NULL);
ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
if (all_pass)
passed_fmts++;
hr = IDirectDrawSurface_DeleteAttachedSurface(rt, 0, ds); hr = IDirectDrawSurface_DeleteAttachedSurface(rt, 0, ds);
ok(SUCCEEDED(hr), "Failed to detach depth buffer, hr %#x.\n", hr); ok(SUCCEEDED(hr), "Failed to detach depth buffer, hr %#x.\n", hr);
IDirectDrawSurface_Release(ds); IDirectDrawSurface_Release(ds);
} }
ok(passed_fmts, "Not a single format passed the tests, this is bad even by Nvidia's standards.\n");
destroy_viewport(device, viewport); destroy_viewport(device, viewport);
destroy_material(blue_background); destroy_material(blue_background);
IDirectDrawSurface_Release(rt); IDirectDrawSurface_Release(rt);

View File

@ -14313,7 +14313,7 @@ static void test_map_synchronisation(void)
static void test_depth_readback(void) static void test_depth_readback(void)
{ {
DWORD depth, expected_depth, max_diff; DWORD depth, expected_depth, max_diff, passed_fmts = 0;
IDirectDrawSurface4 *rt, *ds; IDirectDrawSurface4 *rt, *ds;
IDirect3DViewport3 *viewport; IDirect3DViewport3 *viewport;
DDSURFACEDESC2 surface_desc; DDSURFACEDESC2 surface_desc;
@ -14325,6 +14325,7 @@ static void test_depth_readback(void)
HWND window; HWND window;
HRESULT hr; HRESULT hr;
RECT r; RECT r;
BOOL all_pass;
static D3DRECT clear_rect = {{0}, {0}, {640}, {480}}; static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
static struct static struct
@ -14421,6 +14422,7 @@ static void test_depth_readback(void)
hr = IDirect3DDevice3_EndScene(device); hr = IDirect3DDevice3_EndScene(device);
ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr); ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
all_pass = TRUE;
for (y = 60; y < 480; y += 120) for (y = 60; y < 480; y += 120)
{ {
for (x = 80; x < 640; x += 160) for (x = 80; x < 640; x += 160)
@ -14434,21 +14436,32 @@ static void test_depth_readback(void)
depth = *((DWORD *)surface_desc.lpSurface) & tests[i].z_mask; 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; 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; max_diff = ((0.5f * 0.9f) / 640.0f) * tests[i].z_mask;
/* The ddraw4 version of this test behaves similarly to the ddraw7 version on Nvidia GPUs,
* except that Geforce 7 also returns garbage data in D24S8, whereas the ddraw7 version
* returns 0 for that format. Give up on pre-filtering formats, accept Nvidia as generally
* broken here, but still expect at least one format (D16 or D24X8 in practise) to pass. */
todo_wine_if(tests[i].todo) todo_wine_if(tests[i].todo)
ok(abs(expected_depth - depth) <= max_diff, ok(abs(expected_depth - depth) <= max_diff || ddraw_is_nvidia(ddraw),
"Test %u: Got depth 0x%08x (diff %d), expected 0x%08x+/-%u, at %u, %u.\n", "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); i, depth, expected_depth - depth, expected_depth, max_diff, x, y);
if (abs(expected_depth - depth) > max_diff)
all_pass = FALSE;
hr = IDirectDrawSurface4_Unlock(ds, &r); hr = IDirectDrawSurface4_Unlock(ds, &r);
ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
} }
} }
if (all_pass)
passed_fmts++;
hr = IDirectDrawSurface4_DeleteAttachedSurface(rt, 0, ds); hr = IDirectDrawSurface4_DeleteAttachedSurface(rt, 0, ds);
ok(SUCCEEDED(hr), "Failed to detach depth buffer, hr %#x.\n", hr); ok(SUCCEEDED(hr), "Failed to detach depth buffer, hr %#x.\n", hr);
IDirectDrawSurface4_Release(ds); IDirectDrawSurface4_Release(ds);
} }
ok(passed_fmts, "Not a single format passed the tests, this is bad even by Nvidia's standards.\n");
destroy_viewport(device, viewport); destroy_viewport(device, viewport);
IDirectDrawSurface4_Release(rt); IDirectDrawSurface4_Release(rt);
IDirectDraw4_Release(ddraw); IDirectDraw4_Release(ddraw);

View File

@ -13689,7 +13689,7 @@ done:
static void test_depth_readback(void) static void test_depth_readback(void)
{ {
DWORD depth, expected_depth, max_diff; DWORD depth, expected_depth, max_diff, raw_value, passed_fmts = 0;
IDirectDrawSurface7 *rt, *ds; IDirectDrawSurface7 *rt, *ds;
DDSURFACEDESC2 surface_desc; DDSURFACEDESC2 surface_desc;
IDirect3DDevice7 *device; IDirect3DDevice7 *device;
@ -13700,6 +13700,7 @@ static void test_depth_readback(void)
HWND window; HWND window;
HRESULT hr; HRESULT hr;
RECT r; RECT r;
BOOL all_zero, all_one, all_pass;
static struct static struct
{ {
@ -13791,6 +13792,7 @@ static void test_depth_readback(void)
hr = IDirect3DDevice7_EndScene(device); hr = IDirect3DDevice7_EndScene(device);
ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr); ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
all_zero = all_one = all_pass = TRUE;
for (y = 60; y < 480; y += 120) for (y = 60; y < 480; y += 120)
{ {
for (x = 80; x < 640; x += 160) for (x = 80; x < 640; x += 160)
@ -13801,24 +13803,49 @@ static void test_depth_readback(void)
hr = IDirectDrawSurface7_Lock(ds, &r, &surface_desc, DDLOCK_READONLY, NULL); hr = IDirectDrawSurface7_Lock(ds, &r, &surface_desc, DDLOCK_READONLY, NULL);
ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
depth = *((DWORD *)surface_desc.lpSurface) & tests[i].z_mask; raw_value = *((DWORD *)surface_desc.lpSurface);
if (raw_value)
all_zero = FALSE;
if (raw_value != 0x00ffffff)
all_one = FALSE;
depth = raw_value & tests[i].z_mask;
expected_depth = (x * (0.9 / 640.0) + y * (0.1 / 480.0)) * 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; max_diff = ((0.5f * 0.9f) / 640.0f) * tests[i].z_mask;
/* This test is very reliably on AMD, but fails in a number of interesting ways on Nvidia GPUs:
*
* Geforce 7 GPUs work only with D16. D24 and D24S8 return 0, D24X8 broken data.
*
* Geforce 9 GPUs return return broken data for D16 that resembles the expected data in
* the lower 8 bits and has 0xff in the upper 8 bits. D24X8 works, D24 and D24S8 return
* 0x00ffffff.
*
* Geforce GTX 650 has working D16 and D24, but D24S8 returns 0.
*
* Arx Fatalis is broken on the Geforce 9 in the same way it was broken in Wine (bug 43654).
* The !tests[i].s_depth is supposed to rule out D16 on GF9 and D24X8 on GF7. */
todo_wine_if(tests[i].todo) todo_wine_if(tests[i].todo)
ok(abs(expected_depth - depth) <= max_diff, ok(abs(expected_depth - depth) <= max_diff
|| (ddraw_is_nvidia(ddraw) && (all_zero || all_one || !tests[i].s_depth)),
"Test %u: Got depth 0x%08x (diff %d), expected 0x%08x+/-%u, at %u, %u.\n", "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); i, depth, expected_depth - depth, expected_depth, max_diff, x, y);
if (abs(expected_depth - depth) > max_diff)
all_pass = FALSE;
hr = IDirectDrawSurface7_Unlock(ds, &r); hr = IDirectDrawSurface7_Unlock(ds, &r);
ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
} }
} }
if (all_pass)
passed_fmts++;
hr = IDirectDrawSurface7_DeleteAttachedSurface(rt, 0, ds); hr = IDirectDrawSurface7_DeleteAttachedSurface(rt, 0, ds);
ok(SUCCEEDED(hr), "Failed to detach depth buffer, hr %#x.\n", hr); ok(SUCCEEDED(hr), "Failed to detach depth buffer, hr %#x.\n", hr);
IDirectDrawSurface7_Release(ds); IDirectDrawSurface7_Release(ds);
} }
ok(passed_fmts, "Not a single format passed the tests, this is bad even by Nvidia's standards.\n");
IDirectDrawSurface7_Release(rt); IDirectDrawSurface7_Release(rt);
IDirectDraw7_Release(ddraw); IDirectDraw7_Release(ddraw);
IDirect3D7_Release(d3d); IDirect3D7_Release(d3d);