diff --git a/dlls/d3d8/tests/visual.c b/dlls/d3d8/tests/visual.c index ee4656f5ada..41165a71708 100644 --- a/dlls/d3d8/tests/visual.c +++ b/dlls/d3d8/tests/visual.c @@ -6345,6 +6345,516 @@ done: DestroyWindow(window); } +static BOOL point_match(IDirect3DDevice8 *device, UINT x, UINT y, UINT r) +{ + D3DCOLOR color; + + color = D3DCOLOR_ARGB(0x00, 0xff, 0xff, 0xff); + if (!color_match(getPixelColor(device, x + r, y), color, 1)) + return FALSE; + if (!color_match(getPixelColor(device, x - r, y), color, 1)) + return FALSE; + if (!color_match(getPixelColor(device, x, y + r), color, 1)) + return FALSE; + if (!color_match(getPixelColor(device, x, y - r), color, 1)) + return FALSE; + + ++r; + color = D3DCOLOR_ARGB(0x00, 0x00, 0x00, 0xff); + if (!color_match(getPixelColor(device, x + r, y), color, 1)) + return FALSE; + if (!color_match(getPixelColor(device, x - r, y), color, 1)) + return FALSE; + if (!color_match(getPixelColor(device, x, y + r), color, 1)) + return FALSE; + if (!color_match(getPixelColor(device, x, y - r), color, 1)) + return FALSE; + + return TRUE; +} + +static void test_pointsize(void) +{ + static const float a = 0.5f, b = 0.5f, c = 0.5f; + float ptsize, ptsizemax_orig, ptsizemin_orig; + IDirect3DSurface8 *rt, *backbuffer, *depthstencil; + IDirect3DTexture8 *tex1, *tex2; + IDirect3DDevice8 *device; + DWORD vs, ps; + D3DLOCKED_RECT lr; + IDirect3D8 *d3d; + D3DCOLOR color; + ULONG refcount; + D3DCAPS8 caps; + HWND window; + HRESULT hr; + unsigned int i, j; + + static const DWORD tex1_data[4] = {0x00ff0000, 0x00ff0000, 0x00000000, 0x00000000}; + static const DWORD tex2_data[4] = {0x00000000, 0x0000ff00, 0x00000000, 0x0000ff00}; + static const float vertices[] = + { + 64.0f, 64.0f, 0.1f, + 128.0f, 64.0f, 0.1f, + 192.0f, 64.0f, 0.1f, + 256.0f, 64.0f, 0.1f, + 320.0f, 64.0f, 0.1f, + 384.0f, 64.0f, 0.1f, + 448.0f, 64.0f, 0.1f, + 512.0f, 64.0f, 0.1f, + }; + static const struct + { + float x, y, z; + float point_size; + } + vertex_pointsize = {64.0f, 64.0f, 0.1f, 48.0f}, + vertex_pointsize_scaled = {64.0f, 64.0f, 0.1f, 24.0f}, + vertex_pointsize_zero = {64.0f, 64.0f, 0.1f, 0.0f}; + static const DWORD decl[] = + { + D3DVSD_STREAM(0), + D3DVSD_REG(0, D3DVSDT_FLOAT3), /* position */ + D3DVSD_END() + }, + decl_psize[] = + { + D3DVSD_STREAM(0), + D3DVSD_REG(0, D3DVSDT_FLOAT3), /* position, v0 */ + D3DVSD_REG(1, D3DVSDT_FLOAT1), /* point size, v1 */ + D3DVSD_END() + }; + static const DWORD vshader_code[] = + { + 0xfffe0101, /* vs_1_1 */ + 0x00000005, 0x800f0000, 0x90000000, 0xa0e40000, /* mul r0, v0.x, c0 */ + 0x00000004, 0x800f0000, 0x90550000, 0xa0e40001, 0x80e40000, /* mad r0, v0.y, c1, r0 */ + 0x00000004, 0x800f0000, 0x90aa0000, 0xa0e40002, 0x80e40000, /* mad r0, v0.z, c2, r0 */ + 0x00000004, 0xc00f0000, 0x90ff0000, 0xa0e40003, 0x80e40000, /* mad oPos, v0.w, c3, r0 */ + 0x0000ffff + }; + static const DWORD vshader_psize_code[] = + { + 0xfffe0101, /* vs_1_1 */ + 0x00000005, 0x800f0000, 0x90000000, 0xa0e40000, /* mul r0, v0.x, c0 */ + 0x00000004, 0x800f0000, 0x90550000, 0xa0e40001, 0x80e40000, /* mad r0, v0.y, c1, r0 */ + 0x00000004, 0x800f0000, 0x90aa0000, 0xa0e40002, 0x80e40000, /* mad r0, v0.z, c2, r0 */ + 0x00000004, 0xc00f0000, 0x90ff0000, 0xa0e40003, 0x80e40000, /* mad oPos, v0.w, c3, r0 */ + 0x00000001, 0xc00f0002, 0x90000001, /* mov oPts, v1.x */ + 0x0000ffff + }; + static const DWORD pshader_code[] = + { + 0xffff0101, /* ps_1_1 */ + 0x00000042, 0xb00f0000, /* tex t0 */ + 0x00000042, 0xb00f0001, /* tex t1 */ + 0x00000002, 0x800f0000, 0xb0e40000, 0xb0e40001, /* add r0, t0, t1 */ + 0x0000ffff + }; + static const struct test_shader + { + DWORD version; + const DWORD *code; + } + novs = {0, NULL}, + vs1 = {D3DVS_VERSION(1, 1), vshader_code}, + vs1_psize = {D3DVS_VERSION(1, 1), vshader_psize_code}, + nops = {0, NULL}, + ps1 = {D3DPS_VERSION(1, 1), pshader_code}; + static const struct + { + const DWORD *decl; + const struct test_shader *vs; + const struct test_shader *ps; + DWORD accepted_fvf; + unsigned int nonscaled_size, scaled_size; + } + test_setups[] = + { + {NULL, &novs, &nops, D3DFVF_XYZ, 32, 62}, + {decl, &vs1, &ps1, D3DFVF_XYZ, 32, 32}, + {NULL, &novs, &ps1, D3DFVF_XYZ, 32, 62}, + {decl, &vs1, &nops, D3DFVF_XYZ, 32, 32}, + /* {NULL, &novs, &nops, D3DFVF_XYZ | D3DFVF_PSIZE, 48, 48}, */ + {decl_psize, &vs1_psize, &ps1, D3DFVF_XYZ | D3DFVF_PSIZE, 48, 24}, + }; + static const struct + { + BOOL zero_size; + BOOL scale; + BOOL override_min; + DWORD fvf; + const void *vertex_data; + unsigned int vertex_size; + } + tests[] = + { + {FALSE, FALSE, FALSE, D3DFVF_XYZ, vertices, sizeof(float) * 3}, + {FALSE, TRUE, FALSE, D3DFVF_XYZ, vertices, sizeof(float) * 3}, + {FALSE, FALSE, TRUE, D3DFVF_XYZ, vertices, sizeof(float) * 3}, + {TRUE, FALSE, FALSE, D3DFVF_XYZ, vertices, sizeof(float) * 3}, + {FALSE, FALSE, FALSE, D3DFVF_XYZ | D3DFVF_PSIZE, &vertex_pointsize, sizeof(vertex_pointsize)}, + {FALSE, TRUE, FALSE, D3DFVF_XYZ | D3DFVF_PSIZE, &vertex_pointsize_scaled, sizeof(vertex_pointsize_scaled)}, + {FALSE, FALSE, TRUE, D3DFVF_XYZ | D3DFVF_PSIZE, &vertex_pointsize, sizeof(vertex_pointsize)}, + {TRUE, FALSE, FALSE, D3DFVF_XYZ | D3DFVF_PSIZE, &vertex_pointsize_zero, sizeof(vertex_pointsize_zero)}, + }; + /* Transforms the coordinate system [-1.0;1.0]x[1.0;-1.0] to + * [0.0;0.0]x[640.0;480.0]. Z is untouched. */ + D3DMATRIX matrix = + {{{ + 2.0f / 640.0f, 0.0f, 0.0f, 0.0f, + 0.0f, -2.0f / 480.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + -1.0f, 1.0f, 0.0f, 1.0f, + }}}; + + window = CreateWindowA("static", "d3d8_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE, + 0, 0, 640, 480, NULL, NULL, NULL, NULL); + d3d = Direct3DCreate8(D3D_SDK_VERSION); + ok(!!d3d, "Failed to create a D3D object.\n"); + if (!(device = create_device(d3d, window, window, TRUE))) + { + skip("Failed to create a D3D device, skipping tests.\n"); + goto done; + } + + hr = IDirect3DDevice8_GetDeviceCaps(device, &caps); + ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr); + if (caps.MaxPointSize < 32.0f) + { + skip("MaxPointSize %f < 32.0, skipping.\n", caps.MaxPointSize); + IDirect3DDevice8_Release(device); + goto done; + } + + hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff0000ff, 1.0f, 0); + ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr); + hr = IDirect3DDevice8_SetRenderState(device, D3DRS_LIGHTING, FALSE); + ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr); + hr = IDirect3DDevice8_SetTransform(device, D3DTS_PROJECTION, &matrix); + ok(SUCCEEDED(hr), "Failed to set projection matrix, hr %#x.\n", hr); + hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ); + ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr); + + hr = IDirect3DDevice8_BeginScene(device); + ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr); + + ptsize = 15.0f; + hr = IDirect3DDevice8_SetRenderState(device, D3DRS_POINTSIZE, *(DWORD *)&ptsize); + ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr); + hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, &vertices[0], sizeof(float) * 3); + ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr); + + ptsize = 31.0f; + hr = IDirect3DDevice8_SetRenderState(device, D3DRS_POINTSIZE, *(DWORD *)&ptsize); + ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr); + hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, &vertices[3], sizeof(float) * 3); + ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr); + + ptsize = 30.75f; + hr = IDirect3DDevice8_SetRenderState(device, D3DRS_POINTSIZE, *(DWORD *)&ptsize); + ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr); + hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, &vertices[6], sizeof(float) * 3); + ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr); + + if (caps.MaxPointSize >= 63.0f) + { + ptsize = 63.0f; + hr = IDirect3DDevice8_SetRenderState(device, D3DRS_POINTSIZE, *(DWORD *)&ptsize); + ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr); + hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, &vertices[9], sizeof(float) * 3); + ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr); + + ptsize = 62.75f; + hr = IDirect3DDevice8_SetRenderState(device, D3DRS_POINTSIZE, *(DWORD *)&ptsize); + ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr); + hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, &vertices[15], sizeof(float) * 3); + ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr); + } + + ptsize = 1.0f; + hr = IDirect3DDevice8_SetRenderState(device, D3DRS_POINTSIZE, *(DWORD *)&ptsize); + ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr); + hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, &vertices[12], sizeof(float) * 3); + ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr); + + hr = IDirect3DDevice8_GetRenderState(device, D3DRS_POINTSIZE_MAX, (DWORD *)&ptsizemax_orig); + ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr); + hr = IDirect3DDevice8_GetRenderState(device, D3DRS_POINTSIZE_MIN, (DWORD *)&ptsizemin_orig); + ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr); + + /* What happens if point scaling is disabled, and POINTSIZE_MAX < POINTSIZE? */ + ptsize = 15.0f; + hr = IDirect3DDevice8_SetRenderState(device, D3DRS_POINTSIZE, *(DWORD *)&ptsize); + ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr); + ptsize = 1.0f; + hr = IDirect3DDevice8_SetRenderState(device, D3DRS_POINTSIZE_MAX, *(DWORD *)&ptsize); + ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr); + hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, &vertices[18], sizeof(float) * 3); + ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr); + + hr = IDirect3DDevice8_SetRenderState(device, D3DRS_POINTSIZE_MAX, *(DWORD *)&ptsizemax_orig); + ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr); + + /* pointsize < pointsize_min < pointsize_max? + * pointsize = 1.0, pointsize_min = 15.0, pointsize_max = default(usually 64.0) */ + ptsize = 1.0f; + hr = IDirect3DDevice8_SetRenderState(device, D3DRS_POINTSIZE, *(DWORD *)&ptsize); + ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr); + ptsize = 15.0f; + hr = IDirect3DDevice8_SetRenderState(device, D3DRS_POINTSIZE_MIN, *(DWORD *)&ptsize); + ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr); + hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, &vertices[21], sizeof(float) * 3); + ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr); + + hr = IDirect3DDevice8_SetRenderState(device, D3DRS_POINTSIZE_MIN, *(DWORD *)&ptsizemin_orig); + ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr); + + hr = IDirect3DDevice8_EndScene(device); + ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr); + + ok(point_match(device, 64, 64, 7), "point_match(64, 64, 7) failed, expected point size 15.\n"); + ok(point_match(device, 128, 64, 15), "point_match(128, 64, 15) failed, expected point size 31.\n"); + ok(point_match(device, 192, 64, 15), "point_match(192, 64, 15) failed, expected point size 31.\n"); + + if (caps.MaxPointSize >= 63.0f) + { + ok(point_match(device, 256, 64, 31), "point_match(256, 64, 31) failed, expected point size 63.\n"); + ok(point_match(device, 384, 64, 31), "point_match(384, 64, 31) failed, expected point size 63.\n"); + } + + ok(point_match(device, 320, 64, 0), "point_match(320, 64, 0) failed, expected point size 1.\n"); + /* ptsize = 15, ptsize_max = 1 --> point has size 1 */ + ok(point_match(device, 448, 64, 0), "point_match(448, 64, 0) failed, expected point size 1.\n"); + /* ptsize = 1, ptsize_max = default(64), ptsize_min = 15 --> point has size 15 */ + ok(point_match(device, 512, 64, 7), "point_match(512, 64, 7) failed, expected point size 15.\n"); + + IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL); + + /* The following code tests point sprites with two textures, to see if each texture coordinate unit + * generates texture coordinates for the point(result: Yes, it does) + * + * However, not all GL implementations support point sprites(they need GL_ARB_point_sprite), but there + * is no point sprite cap bit in d3d because native d3d software emulates point sprites. Until the + * SW emulation is implemented in wined3d, this test will fail on GL drivers that does not support them. + */ + hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff0000ff, 1.0f, 0); + ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr); + + hr = IDirect3DDevice8_CreateTexture(device, 2, 2, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &tex1); + ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); + hr = IDirect3DDevice8_CreateTexture(device, 2, 2, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &tex2); + ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); + memset(&lr, 0, sizeof(lr)); + hr = IDirect3DTexture8_LockRect(tex1, 0, &lr, NULL, 0); + ok(SUCCEEDED(hr), "Failed to lock texture, hr %#x.\n", hr); + memcpy(lr.pBits, tex1_data, sizeof(tex1_data)); + hr = IDirect3DTexture8_UnlockRect(tex1, 0); + ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x.\n", hr); + memset(&lr, 0, sizeof(lr)); + hr = IDirect3DTexture8_LockRect(tex2, 0, &lr, NULL, 0); + ok(SUCCEEDED(hr), "Failed to lock texture, hr %#x.\n", hr); + memcpy(lr.pBits, tex2_data, sizeof(tex2_data)); + hr = IDirect3DTexture8_UnlockRect(tex2, 0); + ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x.\n", hr); + hr = IDirect3DDevice8_SetTexture(device, 0, (IDirect3DBaseTexture8 *)tex1); + ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr); + hr = IDirect3DDevice8_SetTexture(device, 1, (IDirect3DBaseTexture8 *)tex2); + ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr); + hr = IDirect3DDevice8_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); + ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr); + hr = IDirect3DDevice8_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE); + ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr); + hr = IDirect3DDevice8_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_ADD); + ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr); + hr = IDirect3DDevice8_SetTextureStageState(device, 1, D3DTSS_COLORARG1, D3DTA_TEXTURE); + ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr); + hr = IDirect3DDevice8_SetTextureStageState(device, 1, D3DTSS_COLORARG2, D3DTA_CURRENT); + ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr); + + hr = IDirect3DDevice8_SetRenderState(device, D3DRS_POINTSPRITEENABLE, TRUE); + ok(SUCCEEDED(hr), "Failed to enable point sprites, hr %#x.\n", hr); + ptsize = 32.0f; + hr = IDirect3DDevice8_SetRenderState(device, D3DRS_POINTSIZE, *(DWORD *)&ptsize); + ok(SUCCEEDED(hr), "Failed to set point size, hr %#x.\n", hr); + + hr = IDirect3DDevice8_BeginScene(device); + ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr); + hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, &vertices[0], sizeof(float) * 3); + 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); + + color = getPixelColor(device, 64 - 4, 64 - 4); + ok(color == 0x00ff0000, "pSprite: Pixel (64 - 4),(64 - 4) has color 0x%08x, expected 0x00ff0000\n", color); + color = getPixelColor(device, 64 - 4, 64 + 4); + ok(color == 0x00000000, "pSprite: Pixel (64 - 4),(64 + 4) has color 0x%08x, expected 0x00000000\n", color); + color = getPixelColor(device, 64 + 4, 64 + 4); + ok(color == 0x0000ff00, "pSprite: Pixel (64 + 4),(64 + 4) has color 0x%08x, expected 0x0000ff00\n", color); + color = getPixelColor(device, 64 + 4, 64 - 4); + ok(color == 0x00ffff00, "pSprite: Pixel (64 + 4),(64 - 4) has color 0x%08x, expected 0x00ffff00\n", color); + IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL); + + U(matrix).m[0][0] = 1.0f / 64.0f; + U(matrix).m[1][1] = -1.0f / 64.0f; + hr = IDirect3DDevice8_SetTransform(device, D3DTS_PROJECTION, &matrix); + ok(SUCCEEDED(hr), "Failed to set projection matrix, hr %#x.\n", hr); + + hr = IDirect3DDevice8_GetRenderTarget(device, &backbuffer); + ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr); + hr = IDirect3DDevice8_GetDepthStencilSurface(device, &depthstencil); + ok(SUCCEEDED(hr), "Failed to get depth / stencil buffer, hr %#x.\n", hr); + + hr = IDirect3DDevice8_CreateRenderTarget(device, 128, 128, D3DFMT_A8R8G8B8, + D3DMULTISAMPLE_NONE, TRUE, &rt); + ok(SUCCEEDED(hr), "Failed to create a render target, hr %#x.\n", hr); + + hr = IDirect3DDevice8_SetRenderState(device, D3DRS_POINTSCALE_A, *(DWORD *)&a); + ok(SUCCEEDED(hr), "Failed setting point scale attenuation coefficient, hr %#x.\n", hr); + hr = IDirect3DDevice8_SetRenderState(device, D3DRS_POINTSCALE_B, *(DWORD *)&b); + ok(SUCCEEDED(hr), "Failed setting point scale attenuation coefficient, hr %#x.\n", hr); + hr = IDirect3DDevice8_SetRenderState(device, D3DRS_POINTSCALE_C, *(DWORD *)&c); + ok(SUCCEEDED(hr), "Failed setting point scale attenuation coefficient, hr %#x.\n", hr); + hr = IDirect3DDevice8_SetVertexShaderConstant(device, 0, &S(U(matrix))._11, 4); + ok(SUCCEEDED(hr), "Failed to set vertex shader constants, hr %#x.\n", hr); + + if (caps.MaxPointSize < 63.0f) + { + skip("MaxPointSize %f < 63.0, skipping some tests.\n", caps.MaxPointSize); + goto cleanup; + } + + hr = IDirect3DDevice8_SetRenderTarget(device, rt, depthstencil); + ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr); + + for (i = 0; i < sizeof(test_setups) / sizeof(test_setups[0]); ++i) + { + if (caps.VertexShaderVersion < test_setups[i].vs->version + || caps.PixelShaderVersion < test_setups[i].ps->version) + { + skip("Vertex / pixel shader version not supported, skipping test.\n"); + continue; + } + if (test_setups[i].vs->code) + { + hr = IDirect3DDevice8_CreateVertexShader(device, test_setups[i].decl, test_setups[i].vs->code, &vs, 0); + ok(SUCCEEDED(hr), "Failed to create vertex shader, hr %#x (case %u).\n", hr, i); + } + else + { + vs = 0; + } + if (test_setups[i].ps->code) + { + hr = IDirect3DDevice8_CreatePixelShader(device, test_setups[i].ps->code, &ps); + ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x (case %u).\n", hr, i); + } + else + { + ps = 0; + } + + hr = IDirect3DDevice8_SetVertexShader(device, vs ? vs : test_setups[i].accepted_fvf); + ok(SUCCEEDED(hr), "Failed to set vertex shader, hr %#x.\n", hr); + hr = IDirect3DDevice8_SetPixelShader(device, ps); + ok(SUCCEEDED(hr), "Failed to set pixel shader, hr %#x.\n", hr); + + for (j = 0; j < sizeof(tests) / sizeof(tests[0]); ++j) + { + unsigned int size = tests[j].override_min ? 63 : tests[j].zero_size ? 0 : tests[j].scale + ? test_setups[i].scaled_size : test_setups[i].nonscaled_size; + + if (test_setups[i].accepted_fvf != tests[j].fvf) + continue; + + ptsize = tests[j].zero_size ? 0.0f : 32.0f; + hr = IDirect3DDevice8_SetRenderState(device, D3DRS_POINTSIZE, *(DWORD *)&ptsize); + ok(SUCCEEDED(hr), "Failed to set pointsize, hr %#x.\n", hr); + + ptsize = tests[j].override_min ? 63.0f : tests[j].zero_size ? 0.0f : ptsizemin_orig; + hr = IDirect3DDevice8_SetRenderState(device, D3DRS_POINTSIZE_MIN, *(DWORD *)&ptsize); + ok(SUCCEEDED(hr), "Failed to set minimum pointsize, hr %#x.\n", hr); + + hr = IDirect3DDevice8_SetRenderState(device, D3DRS_POINTSCALEENABLE, tests[j].scale); + ok(SUCCEEDED(hr), "Failed setting point scale state, hr %#x.\n", hr); + + hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff00ffff, 1.0f, 0); + ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr); + + hr = IDirect3DDevice8_BeginScene(device); + ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr); + hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, + tests[j].vertex_data, tests[j].vertex_size); + 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); + + if (tests[j].zero_size) + { + /* Technically 0 pointsize is undefined in OpenGL but in practice it seems like + * it does the "useful" thing on all the drivers I tried. */ + /* On WARP it does draw some pixels, most of the time. */ + color = getPixelColor(device, 64, 64); + ok(color_match(color, 0x0000ffff, 0) + || broken(color_match(color, 0x00ff0000, 0)) + || broken(color_match(color, 0x00ffff00, 0)) + || broken(color_match(color, 0x00000000, 0)) + || broken(color_match(color, 0x0000ff00, 0)), + "Got unexpected color 0x%08x (case %u, %u, size %u).\n", color, i, j, size); + } + else + { + color = getPixelColor(device, 64 - size / 2 + 1, 64 - size / 2 + 1); + ok(color_match(color, 0x00ff0000, 0), + "Got unexpected color 0x%08x (case %u, %u, size %u).\n", color, i, j, size); + color = getPixelColor(device, 64 + size / 2 - 1, 64 - size / 2 + 1); + ok(color_match(color, 0x00ffff00, 0), + "Got unexpected color 0x%08x (case %u, %u, size %u).\n", color, i, j, size); + color = getPixelColor(device, 64 - size / 2 + 1, 64 + size / 2 - 1); + ok(color_match(color, 0x00000000, 0), + "Got unexpected color 0x%08x (case %u, %u, size %u).\n", color, i, j, size); + color = getPixelColor(device, 64 + size / 2 - 1, 64 + size / 2 - 1); + ok(color_match(color, 0x0000ff00, 0), + "Got unexpected color 0x%08x (case %u, %u, size %u).\n", color, i, j, size); + + color = getPixelColor(device, 64 - size / 2 - 1, 64 - size / 2 - 1); + ok(color_match(color, 0x0000ffff, 0), + "Got unexpected color 0x%08x (case %u, %u, size %u).\n", color, i, j, size); + color = getPixelColor(device, 64 + size / 2 + 1, 64 - size / 2 - 1); + ok(color_match(color, 0x0000ffff, 0), + "Got unexpected color 0x%08x (case %u, %u, size %u).\n", color, i, j, size); + color = getPixelColor(device, 64 - size / 2 - 1, 64 + size / 2 + 1); + ok(color_match(color, 0x0000ffff, 0), + "Got unexpected color 0x%08x (case %u, %u, size %u).\n", color, i, j, size); + color = getPixelColor(device, 64 + size / 2 + 1, 64 + size / 2 + 1); + ok(color_match(color, 0x0000ffff, 0), + "Got unexpected color 0x%08x (case %u, %u, size %u).\n", color, i, j, size); + } + } + IDirect3DDevice8_SetVertexShader(device, 0); + IDirect3DDevice8_SetPixelShader(device, 0); + if (vs) + IDirect3DDevice8_DeleteVertexShader(device, vs); + if (ps) + IDirect3DDevice8_DeletePixelShader(device, ps); + } + hr = IDirect3DDevice8_SetRenderTarget(device, backbuffer, depthstencil); + ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr); + +cleanup: + IDirect3DSurface8_Release(backbuffer); + IDirect3DSurface8_Release(depthstencil); + IDirect3DSurface8_Release(rt); + + IDirect3DTexture8_Release(tex1); + IDirect3DTexture8_Release(tex2); + refcount = IDirect3DDevice8_Release(device); + ok(!refcount, "Device has %u references left.\n", refcount); +done: + IDirect3D8_Release(d3d); + DestroyWindow(window); +} + START_TEST(visual) { D3DADAPTER_IDENTIFIER8 identifier; @@ -6400,4 +6910,5 @@ START_TEST(visual) test_negative_fixedfunction_fog(); test_table_fog_zw(); test_signed_formats(); + test_pointsize(); }