diff --git a/dlls/d3d8/tests/visual.c b/dlls/d3d8/tests/visual.c index c013c1cb236..a7bd449e375 100644 --- a/dlls/d3d8/tests/visual.c +++ b/dlls/d3d8/tests/visual.c @@ -1459,59 +1459,225 @@ static void cnd_test(IDirect3DDevice8 *device) IDirect3DDevice8_DeletePixelShader(device, shader_11); } -static void present_test(IDirect3DDevice8 *device) +static void z_range_test(IDirect3DDevice8 *device) { - struct vertex quad[] = + static const struct vertex quad[] = { - {-1.0f, -1.0f, 0.9f, 0xffff0000}, - {-1.0f, 1.0f, 0.9f, 0xffff0000}, - { 1.0f, -1.0f, 0.1f, 0xffff0000}, - { 1.0f, 1.0f, 0.1f, 0xffff0000}, + {-1.0f, 0.0f, 1.1f, 0xffff0000}, + {-1.0f, 1.0f, 1.1f, 0xffff0000}, + { 1.0f, 0.0f, -1.1f, 0xffff0000}, + { 1.0f, 1.0f, -1.1f, 0xffff0000}, + }; + static const struct vertex quad2[] = + { + {-1.0f, 0.0f, 1.1f, 0xff0000ff}, + {-1.0f, 1.0f, 1.1f, 0xff0000ff}, + { 1.0f, 0.0f, -1.1f, 0xff0000ff}, + { 1.0f, 1.0f, -1.1f, 0xff0000ff}, + }; + static const struct tvertex quad3[] = + { + { 0.0f, 240.0f, 1.1f, 1.0f, 0xffffff00}, + { 0.0f, 480.0f, 1.1f, 1.0f, 0xffffff00}, + {640.0f, 240.0f, -1.1f, 1.0f, 0xffffff00}, + {640.0f, 480.0f, -1.1f, 1.0f, 0xffffff00}, + }; + static const struct tvertex quad4[] = + { + { 0.0f, 240.0f, 1.1f, 1.0f, 0xff00ff00}, + { 0.0f, 480.0f, 1.1f, 1.0f, 0xff00ff00}, + {640.0f, 240.0f, -1.1f, 1.0f, 0xff00ff00}, + {640.0f, 480.0f, -1.1f, 1.0f, 0xff00ff00}, }; HRESULT hr; DWORD color; + DWORD shader; + D3DCAPS8 caps; + static const DWORD shader_code[] = + { + 0xfffe0101, /* vs_1_1 */ + 0x00000001, 0xc00f0000, 0x90e40000, /* mov oPos, v0 */ + 0x00000001, 0xd00f0000, 0xa0e40000, /* mov oD0, c0 */ + 0x0000ffff /* end */ + }; + static const float color_const_1[] = {1.0f, 0.0f, 0.0f, 1.0f}; + static const float color_const_2[] = {0.0f, 0.0f, 1.0f, 1.0f}; + static const DWORD vertex_declaration[] = + { + D3DVSD_STREAM(0), + D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3), + D3DVSD_END() + }; + + hr = IDirect3DDevice8_GetDeviceCaps(device, &caps); + ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr); /* Does the Present clear the depth stencil? Clear the depth buffer with some value != 0, - * then call Present. Then clear the color buffer to make sure it has some defined content - * after the Present with D3DSWAPEFFECT_DISCARD. After that draw a plane that is somewhere cut - * by the depth value. - */ - hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 0.75, 0); - ok(hr == D3D_OK, "IDirect3DDevice8_Clear returned %08x\n", hr); + * then call Present. Then clear the color buffer to make sure it has some defined content + * after the Present with D3DSWAPEFFECT_DISCARD. After that draw a plane that is somewhere cut + * by the depth value. */ + hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 0.75f, 0); + ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr); hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL); - ok(SUCCEEDED(hr), "IDirect3DDevice8_Present returned %#x.\n", hr); - hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.4f, 0); - ok(SUCCEEDED(hr), "IDirect3DDevice8_Clear returned %#x.\n", hr); + ok(SUCCEEDED(hr), "Failed to present, hr %#x.\n", hr); + hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0); + ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr); + hr = IDirect3DDevice8_SetRenderState(device, D3DRS_CLIPPING, TRUE); + ok(SUCCEEDED(hr), "Failed to enable clipping, hr %#x.\n", hr); hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZENABLE, D3DZB_TRUE); - ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState returned %08x\n", hr); + ok(SUCCEEDED(hr), "Failed to enable z test, hr %#x.\n", hr); + hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZWRITEENABLE, FALSE); + ok(SUCCEEDED(hr), "Failed to disable z writes, hr %#x.\n", hr); hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_GREATER); - ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState returned %08x\n", hr); + ok(SUCCEEDED(hr), "Failed to set z function, hr %#x.\n", hr); hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ | D3DFVF_DIFFUSE); - ok(hr == D3D_OK, "IDirect3DDevice8_SetFVF returned %08x\n", hr); + ok(SUCCEEDED(hr), "Failed set FVF, hr %#x.\n", hr); hr = IDirect3DDevice8_BeginScene(device); - ok(hr == D3D_OK, "IDirect3DDevice8_BeginScene failed with %08x\n", hr); - if(hr == D3D_OK) - { - /* No lights are defined... That means, lit vertices should be entirely black */ - hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2 /*PrimCount */, quad, sizeof(quad[0])); - ok(hr == D3D_OK, "IDirect3DDevice8_DrawIndexedPrimitiveUP failed with %08x\n", hr); + ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr); - hr = IDirect3DDevice8_EndScene(device); - ok(hr == D3D_OK, "IDirect3DDevice8_EndScene failed with %08x\n", hr); - } + /* Test the untransformed vertex path */ + hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(quad[0])); + ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr); + hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_LESS); + ok(SUCCEEDED(hr), "Failed to set z function, hr %#x.\n", hr); + hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, sizeof(quad2[0])); + ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr); - hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZENABLE, D3DZB_FALSE); - ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState returned %08x\n", hr); + /* Test the transformed vertex path */ + hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZRHW | D3DFVF_DIFFUSE); + ok(SUCCEEDED(hr), "Failed set FVF, hr %#x.\n", hr); - color = getPixelColor(device, 512, 240); - ok(color == 0x00ffffff, "Present failed: Got color 0x%08x, expected 0x00ffffff.\n", color); - color = getPixelColor(device, 64, 240); - ok(color == 0x00ff0000, "Present failed: Got color 0x%08x, expected 0x00ff0000.\n", color); + hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, sizeof(quad4[0])); + ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr); + hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_GREATER); + ok(SUCCEEDED(hr), "Failed to set z function, hr %#x.\n", hr); + hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, sizeof(quad3[0])); + ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr); + + hr = IDirect3DDevice8_EndScene(device); + ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr); + + /* Do not test the exact corner pixels, but go pretty close to them */ + + /* Clipped because z > 1.0 */ + color = getPixelColor(device, 28, 238); + ok(color_match(color, 0x00ffffff, 0), "Z range failed: Got color 0x%08x, expected 0x00ffffff.\n", color); + color = getPixelColor(device, 28, 241); + if (caps.PrimitiveMiscCaps & D3DPMISCCAPS_CLIPTLVERTS) + ok(color_match(color, 0x00ffffff, 0), "Z range failed: Got color 0x%08x, expected 0x00ffffff.\n", color); + else + ok(color_match(color, 0x00ffff00, 0), "Z range failed: Got color 0x%08x, expected 0x00ffff00.\n", color); + + /* Not clipped, > z buffer clear value(0.75). + * + * On the r500 driver on Windows D3DCMP_GREATER and D3DCMP_GREATEREQUAL are broken for depth + * values > 0.5. The range appears to be distorted, apparently an incoming value of ~0.875 is + * equal to a stored depth buffer value of 0.5. */ + color = getPixelColor(device, 31, 238); + ok(color_match(color, 0x00ff0000, 0), "Z range failed: Got color 0x%08x, expected 0x00ff0000.\n", color); + color = getPixelColor(device, 31, 241); + ok(color_match(color, 0x00ffff00, 0), "Z range failed: Got color 0x%08x, expected 0x00ffff00.\n", color); + color = getPixelColor(device, 100, 238); + ok(color_match(color, 0x00ff0000, 0) || broken(color_match(color, 0x00ffffff, 0)), + "Z range failed: Got color 0x%08x, expected 0x00ff0000.\n", color); + color = getPixelColor(device, 100, 241); + ok(color_match(color, 0x00ffff00, 0) || broken(color_match(color, 0x00ffffff, 0)), + "Z range failed: Got color 0x%08x, expected 0x00ffff00.\n", color); + + /* Not clipped, < z buffer clear value */ + color = getPixelColor(device, 104, 238); + ok(color_match(color, 0x000000ff, 0), "Z range failed: Got color 0x%08x, expected 0x000000ff.\n", color); + color = getPixelColor(device, 104, 241); + ok(color_match(color, 0x0000ff00, 0), "Z range failed: Got color 0x%08x, expected 0x0000ff00.\n", color); + color = getPixelColor(device, 318, 238); + ok(color_match(color, 0x000000ff, 0), "Z range failed: Got color 0x%08x, expected 0x000000ff.\n", color); + color = getPixelColor(device, 318, 241); + ok(color_match(color, 0x0000ff00, 0), "Z range failed: Got color 0x%08x, expected 0x0000ff00.\n", color); + + /* Clipped because z < 0.0 */ + color = getPixelColor(device, 321, 238); + ok(color_match(color, 0x00ffffff, 0), "Z range failed: Got color 0x%08x, expected 0x00ffffff.\n", color); + color = getPixelColor(device, 321, 241); + if (caps.PrimitiveMiscCaps & D3DPMISCCAPS_CLIPTLVERTS) + ok(color_match(color, 0x00ffffff, 0), "Z range failed: Got color 0x%08x, expected 0x00ffffff.\n", color); + else + ok(color_match(color, 0x0000ff00, 0), "Z range failed: Got color 0x%08x, expected 0x00ffffff.\n", color); hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL); - ok(SUCCEEDED(hr), "Present failed (%#08x)\n", hr); + ok(SUCCEEDED(hr), "Failed to present, hr %#x.\n", hr); + + /* Test the shader path */ + if (caps.VertexShaderVersion < D3DVS_VERSION(1, 1)) + { + skip("Vertex shaders not supported\n"); + goto out; + } + hr = IDirect3DDevice8_CreateVertexShader(device, vertex_declaration, shader_code, &shader, 0); + ok(SUCCEEDED(hr), "Failed to create vertex shader, hr %#x.\n", hr); + + hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0); + ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr); + + hr = IDirect3DDevice8_SetVertexShader(device, shader); + ok(SUCCEEDED(hr), "Failed to set vertex shader, hr %#x.\n", hr); + + hr = IDirect3DDevice8_BeginScene(device); + ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr); + + hr = IDirect3DDevice8_SetVertexShaderConstant(device, 0, color_const_1, 1); + ok(SUCCEEDED(hr), "Failed to set vs constant 0, hr %#x.\n", hr); + hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(quad[0])); + ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr); + + hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_LESS); + ok(SUCCEEDED(hr), "Failed to set z function, hr %#x.\n", hr); + hr = IDirect3DDevice8_SetVertexShaderConstant(device, 0, color_const_2, 1); + ok(SUCCEEDED(hr), "Failed to set vs constant 0, hr %#x.\n", hr); + hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, sizeof(quad2[0])); + ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr); + + hr = IDirect3DDevice8_EndScene(device); + ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr); + + hr = IDirect3DDevice8_SetVertexShader(device, 0); + ok(SUCCEEDED(hr), "Failed to set vertex shader, hr %#x.\n", hr); + + hr = IDirect3DDevice8_DeleteVertexShader(device, shader); + ok(SUCCEEDED(hr), "Failed to delete vertex shader, hr %#x.\n", hr); + + /* Z < 1.0 */ + color = getPixelColor(device, 28, 238); + ok(color_match(color, 0x00ffffff, 0), "Z range failed: Got color 0x%08x, expected 0x00ffffff.\n", color); + + /* 1.0 < z < 0.75 */ + color = getPixelColor(device, 31, 238); + ok(color_match(color, 0x00ff0000, 0), "Z range failed: Got color 0x%08x, expected 0x00ff0000.\n", color); + color = getPixelColor(device, 100, 238); + ok(color_match(color, 0x00ff0000, 0) || broken(color_match(color, 0x00ffffff, 0)), + "Z range failed: Got color 0x%08x, expected 0x00ff0000.\n", color); + + /* 0.75 < z < 0.0 */ + color = getPixelColor(device, 104, 238); + ok(color_match(color, 0x000000ff, 0), "Z range failed: Got color 0x%08x, expected 0x000000ff.\n", color); + color = getPixelColor(device, 318, 238); + ok(color_match(color, 0x000000ff, 0), "Z range failed: Got color 0x%08x, expected 0x000000ff.\n", color); + + /* 0.0 < z */ + color = getPixelColor(device, 321, 238); + ok(color_match(color, 0x00ffffff, 0), "Z range failed: Got color 0x%08x, expected 0x00ffffff.\n", color); + + hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL); + ok(SUCCEEDED(hr), "Failed to present, hr %#x.\n", hr); + +out: + hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZENABLE, D3DZB_FALSE); + ok(SUCCEEDED(hr), "Failed to disable z test, hr %#x.\n", hr); + hr = IDirect3DDevice8_SetRenderState(device, D3DRS_CLIPPING, FALSE); + ok(SUCCEEDED(hr), "Failed to disable clipping, hr %#x.\n", hr); + hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZWRITEENABLE, TRUE); + ok(SUCCEEDED(hr), "Failed to enable z writes, hr %#x.\n", hr); } static void test_rcp_rsq(IDirect3DDevice8 *device) @@ -4220,7 +4386,7 @@ START_TEST(visual) lighting_test(device_ptr); clear_test(device_ptr); fog_test(device_ptr); - present_test(device_ptr); + z_range_test(device_ptr); offscreen_test(device_ptr); alpha_test(device_ptr);