Wine-Devel
By thread
wine-devel@list.winehq.org
By month
Messages by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
July 2015
- 61 participants
- 402 messages
Re: [1/2] ntdll/tests: Add basic tests for RtlQueueWorkItem.
by Grazvydas Ignotas
On Mon, Jul 27, 2015 at 1:33 AM, Sebastian Lackner
<sebastian(a)fds-team.de> wrote:
> On 27.07.2015 00:11, Marvin wrote:
>> Hi,
>>
>> While running your changed tests on Windows, I think I found new failures.
>> Being a bot and all I'm not very good at pattern recognition, so I might be
>> wrong, but could you please double-check?
>> Full results can be found at
>> https://testbot.winehq.org/JobDetails.pl?Key=15580
>>
>> Your paranoid android.
>>
>>
>> === w7u (32 bit threadpool) ===
>> threadpool.c:763: Test failed: WaitForSingleObject returned 258
>> threadpool.c:777: Test failed: WaitForSingleObject returned 0
>> threadpool.c:779: Test failed: threadpool.c:715: Running timer callback
>>
>
> This is unrelated to my tests.
>
> If noone has an idea what is causing these random failures I'll try to increase
> the timeouts a bit (in a separate patch of course) - however, these random issues
> do not occur on a local Windows 7 machine, which makes me suspect that it could
> also be related to testbot issues.
IMHO 1s timeouts are way too low for test machines running on VMs, the
host machine may not have enough resources if multiple VMs are busy,
and the hypervisor may have it's inefficiencies too, especially when
I/O is involved. I don't have any idea how tesbot is set up bit I had
an impression there are lots of VMs running on a single host.
If it was up to me I'd increase those timeouts a lot, to at least 10s
(or even a minute) instead of 1s.
Gražvydas
July 28, 2015
Re: odbccp32: Implement SQLGetPrivateProfileString/W (try 9)
by Nikolay Sivov
On 28.07.2015 12:55, Alistair Leslie-Hughes wrote:
> + if(!defvalue)
> + buff[0] = 0;
> +
> + if (!section || !defvalue || !buff)
> + return 0;
> +
> + if (buff)
> + buff[0] = 0;
This makes no sense.
July 28, 2015
RE: [PATCH] gdi32: check for NULL pointer in GetOutlineTextMetrics (try 2)
by Daniel Lehman
>
>
> === wvistau64 (32 bit font) ===
> The test timed out
>
> === wvistau64 (64 bit font) ===
> The test timed out
These are unrelated to my changes. timeouts in previous runs:
http://test.winehq.org/data/4e6e9a14852298fe8c17f2666a16d5484cbe50b3/vista_…
http://test.winehq.org/data/50d9d187c57448ca3f14de6a8eeb2520179db5b8/vista_…
http://test.winehq.org/data/50d9d187c57448ca3f14de6a8eeb2520179db5b8/vista_…
July 27, 2015
Re: [PATCH] gdi32: check for NULL pointer in GetOutlineTextMetrics (try 2)
by Marvin
Hi,
While running your changed tests on Windows, I think I found new failures.
Being a bot and all I'm not very good at pattern recognition, so I might be
wrong, but could you please double-check?
Full results can be found at
https://testbot.winehq.org/JobDetails.pl?Key=15598
Your paranoid android.
=== wvistau64 (32 bit font) ===
The test timed out
=== wvistau64 (64 bit font) ===
The test timed out
July 27, 2015
Re: [PATCH 3/5] d3dx9: Partially implement D3DXComputeTangentFrameEx().
by Józef Kucia
Hi,
On Mon, Jul 27, 2015 at 7:38 PM, Matteo Bruni <matteo.mystral(a)gmail.com> wrote:
>
> I've got a number of nitpicks but these patches are essentially okay with me.
>
Thanks for the review.
>> +
>> + switch (declaration->Type)
>> + {
>> + case D3DDECLTYPE_FLOAT1:
>> + vec3.x = src[0];
>> + break;
>> + case D3DDECLTYPE_FLOAT2:
>> + vec3.x = src[0];
>> + vec3.y = src[1];
>> + break;
>> + case D3DDECLTYPE_FLOAT3:
>> + case D3DDECLTYPE_FLOAT4:
>> + vec3.x = src[0];
>> + vec3.y = src[1];
>> + vec3.z = src[2];
>> + break;
>> + default:
>> + ERR("Cannot read vec3\n");
>> + break;
>> + }
>
> You could sort the cases the other way around and fallthrough to make
> this part shorter. Again, this is also fine and it's up to you.
>
I was thinking about this but it seems slightly less readable to me.
>> + }
>> +
>> + if ((options & (D3DXTANGENT_WEIGHT_EQUAL | D3DXTANGENT_WEIGHT_BY_AREA)) == (D3DXTANGENT_WEIGHT_EQUAL | D3DXTANGENT_WEIGHT_BY_AREA))
>
> I would store the result of "options & (D3DXTANGENT_WEIGHT_EQUAL |
> D3DXTANGENT_WEIGHT_BY_AREA)" in a variable and use it here and below.
>
Definitely good suggestion.
>> +
>> + for (i = 0; i < num_vertices; i++)
>> + {
>> + const D3DXVECTOR4 zero = {0.0f, 0.0f, 0.0f, 1.0f};
>
> That's a weird zero :) Not sure about a better name though, maybe
> "default_vector"? Also, please make it static.
I was considering "default_vector" but i left it as "zero". I guess I
have a bad taste ;)
>> +
>> + if (isnan(weights[0])) weights[0] = 1.0f;
>> + if (isnan(weights[1])) weights[1] = 1.0f;
>> + if (isnan(weights[2])) weights[2] = 1.0f;
>> + break;
>
> This might cause problems in the (unlikely) case float exceptions are
> enabled. Ideally this case would need to be tested with native and, if
> it doesn't throw exceptions, your code would need to take care of
> that. I don't think this is super critical though, it should be easy
> to figure it out later on if some application crashes here.
I'll test this case.
July 27, 2015
Re: [PATCH] gdi32: check for NULL pointer in GetOutlineTextMetrics
by Nikolay Sivov
On 27.07.2015 21:19, Daniel Lehman wrote:
>
>
Yes, looks like it will access NULL out pointer if cbData != 0. Please
add a test for that, if it returns required buffer size your fix looks
correct to me, if it returns 0 we don't need to call driver at all and
API call itself should be fixed, not a driver.
July 27, 2015
Re: include/d3dcommon.idl: Add missing typedefs
by Matteo Bruni
2015-07-26 3:24 GMT+02:00 Alistair Leslie-Hughes <leslie_alistair(a)hotmail.com>:
> + D3D_SIF_TEXTURE_COMPONENT_0 = 4,
> + D3D_SIF_TEXTURE_COMPONENT_1 = 8,
> + D3D_SIF_TEXTURE_COMPONENTS = 12,
Please use hexadecimal here.
FWIW in the Win 8.1 SDK headers there is also a D3D_SIF_UNUSED enum value.
July 27, 2015
Re: [PATCH 5/5] d3dx9/tests: Add tests for normals computation.
by Matteo Bruni
2015-07-25 11:23 GMT+02:00 Józef Kucia <joseph.kucia(a)gmail.com>:
> ---
> dlls/d3dx9_36/tests/mesh.c | 573 +++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 573 insertions(+)
>
> diff --git a/dlls/d3dx9_36/tests/mesh.c b/dlls/d3dx9_36/tests/mesh.c
> index 2da077a..a5b3c46 100644
> --- a/dlls/d3dx9_36/tests/mesh.c
> +++ b/dlls/d3dx9_36/tests/mesh.c
> @@ -65,6 +65,11 @@ static BOOL compare_vec3(D3DXVECTOR3 u, D3DXVECTOR3 v)
> return ( compare(u.x, v.x) && compare(u.y, v.y) && compare(u.z, v.z) );
> }
>
> +static BOOL compare_vec4(D3DXVECTOR4 u, D3DXVECTOR4 v)
> +{
> + return compare(u.x, v.x) && compare(u.y, v.y) && compare(u.z, v.z) && compare(u.w, v.w);
> +}
> +
> #define check_floats(got, exp, dim) check_floats_(__LINE__, "", got, exp, dim)
> static void check_floats_(int line, const char *prefix, const float *got, const float *exp, int dim)
> {
> @@ -10373,6 +10378,573 @@ static void test_optimize_faces(void)
> "faces when using 16-bit indices. Got %x\n, expected D3DERR_INVALIDCALL\n", hr);
> }
>
> +static HRESULT clear_normals(ID3DXMesh *mesh)
> +{
> + HRESULT hr;
> + BYTE *vertices;
> + size_t normal_size;
> + DWORD i, num_vertices, vertex_stride;
> + const D3DXVECTOR4 normal = {NAN, NAN, NAN, NAN};
> + D3DVERTEXELEMENT9 *normal_declaration = NULL;
> + D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE] = {D3DDECL_END()};
> +
> + if (FAILED(hr = mesh->lpVtbl->GetDeclaration(mesh, declaration)))
> + return hr;
> +
> + for (i = 0; declaration[i].Stream != 0xFF; i++)
> + {
> + if (declaration[i].Usage == D3DDECLUSAGE_NORMAL && declaration[i].UsageIndex == 0)
Style, lowercase hex literal and !var instead of var == 0 are usually
preferred in d3d.
> + {
> + normal_declaration = &declaration[i];
> + break;
> + }
> + }
> +
> + if (!normal_declaration)
> + return D3DERR_INVALIDCALL;
> +
> + if (normal_declaration->Type == D3DDECLTYPE_FLOAT3)
> + {
> + normal_size = sizeof(D3DXVECTOR3);
> + }
> + else if (normal_declaration->Type == D3DDECLTYPE_FLOAT4)
> + {
> + normal_size = sizeof(D3DXVECTOR4);
> + }
> + else
> + {
> + trace("Cannot clear normals\n");
> + return E_NOTIMPL;
> + }
> +
> + num_vertices = mesh->lpVtbl->GetNumVertices(mesh);
> + vertex_stride = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
> +
> + if (FAILED(hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, (void **)&vertices)))
> + return hr;
> +
> + vertices += normal_declaration->Offset;
> +
> + for (i = 0; i < num_vertices; i++, vertices += vertex_stride)
> + memcpy(vertices, &normal, normal_size);
> +
> + return mesh->lpVtbl->UnlockVertexBuffer(mesh);
> +}
> +
> +static void compare_normals(unsigned int line, const char *test_name,
> + ID3DXMesh *mesh, const D3DXVECTOR3 *normals, unsigned int num_normals)
> +{
> + unsigned int i;
> + BYTE *vertices;
> + DWORD num_vertices, vertex_stride;
> + D3DVERTEXELEMENT9 *normal_declaration = NULL;
> + D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE] = {D3DDECL_END()};
> +
> + if (FAILED(mesh->lpVtbl->GetDeclaration(mesh, declaration)))
> + {
> + ok_(__FILE__, line)(0, "%s: Failed to get declaration\n", test_name);
> + return;
> + }
> +
> + for (i = 0; declaration[i].Stream != 0xFF; i++)
> + {
> + if (declaration[i].Usage == D3DDECLUSAGE_NORMAL && declaration[i].UsageIndex == 0)
> + {
> + normal_declaration = &declaration[i];
> + break;
> + }
> + }
> +
> + if (!normal_declaration)
> + {
> + ok_(__FILE__, line)(0, "%s: Mesh has no normals\n", test_name);
> + return;
> + }
> +
> + if (normal_declaration->Type != D3DDECLTYPE_FLOAT3 && normal_declaration->Type != D3DDECLTYPE_FLOAT4)
> + {
> + ok_(__FILE__, line)(0, "%s: Mesh has invalid normals type\n", test_name);
> + return;
> + }
> +
> + num_vertices = mesh->lpVtbl->GetNumVertices(mesh);
> + vertex_stride = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
> +
> + ok_(__FILE__, line)(num_vertices == num_normals, "%s: Expected %u vertices, got %u\n", test_name,
> + num_normals, num_vertices);
> +
> + if (FAILED(mesh->lpVtbl->LockVertexBuffer(mesh, 0, (void **)&vertices)))
> + {
> + ok_(__FILE__, line)(0, "%s: Failed to compare normals\n", test_name);
> + return;
> + }
> +
> + vertices += normal_declaration->Offset;
> +
> + for (i = 0; i < min(num_vertices, num_normals); i++, vertices += vertex_stride)
> + {
> + if (normal_declaration->Type == D3DDECLTYPE_FLOAT3)
> + {
> + const D3DXVECTOR3 *n = (D3DXVECTOR3 *)vertices;
> + ok_(__FILE__, line)(compare_vec3(*n, normals[i]),
> + "%s: normal %2u, expected (%f, %f, %f), got (%f, %f, %f)\n",
> + test_name, i, normals[i].x, normals[i].y, normals[i].z, n->x, n->y, n->z);
> + }
> + else
> + {
> + const D3DXVECTOR4 *n = (D3DXVECTOR4 *)vertices;
> + const D3DXVECTOR4 normal = {normals[i].x, normals[i].y, normals[i].z, 1.0f};
> + ok_(__FILE__, line)(compare_vec4(*n, normal),
> + "%s: normal %2u, expected (%f, %f, %f, %f), got (%f, %f, %f, %f)\n",
> + test_name, i, normals[i].x, normals[i].y, normals[i].z, 1.0f,
> + n->x, n->y, n->z, n->w);
> + }
> + }
> +
> + mesh->lpVtbl->UnlockVertexBuffer(mesh);
> +}
> +
> +static HRESULT compute_normals_D3DXComputeNormals(ID3DXMesh *mesh, const DWORD *adjacency)
> +{
> + return D3DXComputeNormals((ID3DXBaseMesh *)mesh, adjacency);
> +}
> +
> +static HRESULT compute_normals_D3DXComputeTangentFrameEx(ID3DXMesh *mesh, const DWORD *adjacency)
> +{
> + return D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
> + D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS,
> + adjacency, -1.01f, -0.01f, -1.01f, NULL, NULL);
> +}
> +
> +static void test_compute_normals(void)
> +{
> + HRESULT hr;
> + ULONG refcount;
> + ID3DXMesh *mesh, *cloned_mesh;
> + ID3DXBuffer *adjacency;
> + IDirect3DDevice9 *device;
> + struct test_context *test_context;
> + unsigned int i;
> +
> + static const struct compute_normals_func
> + {
> + const char *name;
> + HRESULT (*apply)(ID3DXMesh *mesh, const DWORD *adjacency);
> + }
> + compute_normals_funcs[] =
> + {
> + {"D3DXComputeNormals", compute_normals_D3DXComputeNormals },
> + {"D3DXComputeTangentFramEx", compute_normals_D3DXComputeTangentFrameEx}
Typo.
BTW, I feel like you could push this kind of table-based test
organization further. E.g. also add a couple more variants for
D3DXTANGENT_WEIGHT_BY_AREA and D3DXTANGENT_WEIGHT_EQUAL. You might
have to store the expected results for box and sphere normals in the
table.
Doing that might be more messy than it looks like though, so I'm okay
if you think that's not worth it.
> + };
> +
> + static const D3DXVECTOR3 box_normals[24] =
> + {
> + {-1.0f, 0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f},
> + { 0.0f, 1.0f, 0.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}, { 1.0f, 0.0f, 0.0f}, { 1.0f, 0.0f, 0.0f}, { 1.0f, 0.0f, 0.0f},
> + { 0.0f,-1.0f, 0.0f}, { 0.0f,-1.0f, 0.0f}, { 0.0f,-1.0f, 0.0f}, { 0.0f,-1.0f, 0.0f},
> + { 0.0f, 0.0f, 1.0f}, { 0.0f, 0.0f, 1.0f}, { 0.0f, 0.0f, 1.0f}, { 0.0f, 0.0f, 1.0f},
> + { 0.0f, 0.0f,-1.0f}, { 0.0f, 0.0f,-1.0f}, { 0.0f, 0.0f,-1.0f}, { 0.0f, 0.0f,-1.0f}
> + };
> + float box_normal_component = 1.0f / sqrtf(3.0f);
> + D3DXVECTOR3 box_normals_adjacency[24] =
I think you can still make this const.
> + {
> + {-box_normal_component, -box_normal_component, -box_normal_component},
> + {-box_normal_component, -box_normal_component, box_normal_component},
> + {-box_normal_component, box_normal_component, box_normal_component},
> + {-box_normal_component, box_normal_component, -box_normal_component},
> + {-box_normal_component, box_normal_component, -box_normal_component},
> + {-box_normal_component, box_normal_component, box_normal_component},
> + { box_normal_component, box_normal_component, box_normal_component},
> + { box_normal_component, box_normal_component, -box_normal_component},
> + { box_normal_component, box_normal_component, -box_normal_component},
> + { box_normal_component, box_normal_component, box_normal_component},
> + { box_normal_component, -box_normal_component, box_normal_component},
> + { box_normal_component, -box_normal_component, -box_normal_component},
> + {-box_normal_component, -box_normal_component, box_normal_component},
> + {-box_normal_component, -box_normal_component, -box_normal_component},
> + { box_normal_component, -box_normal_component, -box_normal_component},
> + { box_normal_component, -box_normal_component, box_normal_component},
> + {-box_normal_component, -box_normal_component, box_normal_component},
> + { box_normal_component, -box_normal_component, box_normal_component},
> + { box_normal_component, box_normal_component, box_normal_component},
> + {-box_normal_component, box_normal_component, box_normal_component},
> + {-box_normal_component, -box_normal_component, -box_normal_component},
> + {-box_normal_component, box_normal_component, -box_normal_component},
> + { box_normal_component, box_normal_component, -box_normal_component},
> + { box_normal_component, -box_normal_component, -box_normal_component}
> + };
> + static const D3DXVECTOR3 box_normals_adjacency_area[24] =
> + {
> + {-0.666667f, -0.333333f, -0.666667f}, {-0.333333f, -0.666667f, 0.666667f},
> + {-0.816496f, 0.408248f, 0.408248f}, {-0.408248f, 0.816496f, -0.408248f},
> + {-0.408248f, 0.816496f, -0.408248f}, {-0.816496f, 0.408248f, 0.408248f},
> + { 0.333333f, 0.666667f, 0.666667f}, { 0.666667f, 0.333333f, -0.666667f},
> + { 0.666667f, 0.333333f, -0.666667f}, { 0.333333f, 0.666667f, 0.666667f},
> + { 0.816496f, -0.408248f, 0.408248f}, { 0.408248f, -0.816496f, -0.408248f},
> + {-0.333333f, -0.666667f, 0.666667f}, {-0.666667f, -0.333333f, -0.666667f},
> + { 0.408248f, -0.816496f, -0.408248f}, { 0.816496f, -0.408248f, 0.408248f},
> + {-0.333333f, -0.666667f, 0.666667f}, { 0.816497f, -0.408248f, 0.408248f},
> + { 0.333333f, 0.666667f, 0.666667f}, {-0.816497f, 0.408248f, 0.408248f},
> + {-0.666667f, -0.333333f, -0.666667f}, {-0.408248f, 0.816497f, -0.408248f},
> + { 0.666667f, 0.333333f, -0.666667f}, { 0.408248f, -0.816496f, -0.408248f}
> + };
> + static const D3DXVECTOR3 box_normals_position1f[24] = {{0}};
> + static const D3DXVECTOR3 box_normals_position2f[24] =
> + {
> + {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f},
> + {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, 1.0f},
> + {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f},
> + {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f},
> + {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f},
> + {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f},
> + {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f},
> + {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f}
> + };
> +
> + static const D3DXVECTOR3 sphere_normals[22] =
> + {
> + { 0.000000f, -0.000000f, 1.000000f}, { 0.000000f, 0.582244f, 0.813014f},
> + { 0.582244f, -0.000000f, 0.813014f}, {-0.000000f, -0.582244f, 0.813014f},
> + {-0.582244f, 0.000000f, 0.813014f}, {-0.000000f, 0.890608f, 0.454772f},
> + { 0.890608f, 0.000000f, 0.454772f}, { 0.000000f, -0.890608f, 0.454772f},
> + {-0.890608f, -0.000000f, 0.454772f}, { 0.000000f, 1.000000f, -0.000000f},
> + { 1.000000f, -0.000000f, -0.000000f}, {-0.000000f, -1.000000f, -0.000000f},
> + {-1.000000f, 0.000000f, -0.000000f}, { 0.000000f, 0.890608f, -0.454773f},
> + { 0.890608f, -0.000000f, -0.454772f}, {-0.000000f, -0.890608f, -0.454773f},
> + {-0.890608f, 0.000000f, -0.454773f}, { 0.000000f, 0.582244f, -0.813015f},
> + { 0.582244f, -0.000000f, -0.813015f}, { 0.000000f, -0.582244f, -0.813015f},
> + {-0.582243f, 0.000000f, -0.813015f}, { 0.000000f, 0.000000f, -1.000000f}
> + };
> + static const D3DXVECTOR3 sphere_normals_area[22] =
> + {
> + { 0.000000f, -0.000000f, 1.000000f}, {-0.215311f, 0.554931f, 0.803550f},
> + { 0.554931f, 0.215311f, 0.803550f}, { 0.215311f, -0.554931f, 0.803550f},
> + {-0.554931f, -0.215311f, 0.803550f}, {-0.126638f, 0.872121f, 0.472618f},
> + { 0.872121f, 0.126638f, 0.472618f}, { 0.126638f, -0.872121f, 0.472618f},
> + {-0.872121f, -0.126637f, 0.472618f}, { 0.000000f, 1.000000f, -0.000000f},
> + { 1.000000f, -0.000000f, -0.000000f}, {-0.000000f, -1.000000f, -0.000000f},
> + {-1.000000f, 0.000000f, -0.000000f}, { 0.126638f, 0.872121f, -0.472618f},
> + { 0.872121f, -0.126638f, -0.472618f}, {-0.126638f, -0.872121f, -0.472618f},
> + {-0.872121f, 0.126638f, -0.472618f}, { 0.215311f, 0.554931f, -0.803550f},
> + { 0.554931f, -0.215311f, -0.803550f}, {-0.215311f, -0.554931f, -0.803550f},
> + {-0.554931f, 0.215311f, -0.803550f}, { 0.000000f, 0.000000f, -1.000000f}
> + };
> + static const D3DXVECTOR3 sphere_normals_equal[22] =
> + {
> + { 0.000000f, -0.000000f, 1.000000f}, {-0.134974f, 0.522078f, 0.842150f},
> + { 0.522078f, 0.134974f, 0.842150f}, { 0.134974f, -0.522078f, 0.842150f},
> + {-0.522078f, -0.134974f, 0.842150f}, {-0.026367f, 0.857121f, 0.514440f},
> + { 0.857121f, 0.026367f, 0.514440f}, { 0.026367f, -0.857121f, 0.514440f},
> + {-0.857121f, -0.026367f, 0.514440f}, { 0.000000f, 1.000000f, -0.000000f},
> + { 1.000000f, -0.000000f, -0.000000f}, {-0.000000f, -1.000000f, -0.000000f},
> + {-1.000000f, 0.000000f, -0.000000f}, { 0.026367f, 0.857121f, -0.514440f},
> + { 0.857121f, -0.026367f, -0.514440f}, {-0.026367f, -0.857121f, -0.514440f},
> + {-0.857121f, 0.026367f, -0.514440f}, { 0.134975f, 0.522078f, -0.842150f},
> + { 0.522078f, -0.134975f, -0.842150f}, {-0.134974f, -0.522078f, -0.842150f},
> + {-0.522078f, 0.134974f, -0.842150f}, { 0.000000f, 0.000000f, -1.000000f}
> + };
> +
> + static const D3DVERTEXELEMENT9 position3f_normal1f_declaration[] =
> + {
> + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
> + {0, sizeof(D3DXVECTOR3), D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
> + D3DDECL_END()
> + };
> + static const D3DVERTEXELEMENT9 position3f_normal2f_declaration[] =
> + {
> + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
> + {0, sizeof(D3DXVECTOR3), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
> + D3DDECL_END()
> + };
> + static const D3DVERTEXELEMENT9 normal4f_position3f_declaration[] =
> + {
> + {0, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
> + {0, sizeof(D3DXVECTOR4), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
> + D3DDECL_END()
> + };
Can you check that a 4-component normal placed after the position
gives the same results? It doesn't need to be in the patch if there
are no surprises (and there shouldn't be, this is me being paranoid).
> + static const D3DVERTEXELEMENT9 position1f_normal3f_declaration[] =
> + {
> + {0, 0, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
> + {0, sizeof(float), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
> + D3DDECL_END()
> + };
> + static const D3DVERTEXELEMENT9 position2f_normal3f_declaration[] =
> + {
> + {0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
> + {0, sizeof(D3DXVECTOR2), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
> + D3DDECL_END()
> + };
> + static const D3DVERTEXELEMENT9 position4f_normal3f_declaration[] =
> + {
> + {0, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
> + {0, sizeof(D3DXVECTOR4), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
> + D3DDECL_END()
> + };
> +
> + for (i = 0; i < ARRAY_SIZE(compute_normals_funcs); i++)
> + {
> + hr = compute_normals_funcs[i].apply(NULL, NULL);
> + ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", compute_normals_funcs[i].name, hr);
> + }
> +
> + if (!(test_context = new_test_context()))
> + {
> + skip("Couldn't create test context\n");
> + return;
> + }
> + device = test_context->device;
> +
> + hr = D3DXCreateBox(device, 1.0f, 1.0f, 1.0f, &mesh, &adjacency);
> + ok(SUCCEEDED(hr), "D3DXCreateBox failed %#x\n", hr);
> +
> + /* Check wrong input */
> + hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
> + D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE, NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
> + todo_wine ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr);
> +
> + hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DDECLUSAGE_NORMAL, 0,
> + D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA | D3DXTANGENT_WEIGHT_EQUAL,
> + NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
> + ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr);
> +
> + hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
> + D3DDECLUSAGE_NORMAL, 0, 0, NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
> + todo_wine ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr);
> +
> + hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
> + D3DDECLUSAGE_NORMAL, 1, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS,
> + NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
> + ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr);
> +
> + hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
> + D3DX_DEFAULT, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS,
> + NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
> + ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr);
> +
> + hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
> + D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_CALCULATE_NORMALS,
> + NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
> + todo_wine ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr);
> +
> + for (i = 0; i < ARRAY_SIZE(compute_normals_funcs); i++)
> + {
> + const struct compute_normals_func *func = &compute_normals_funcs[i];
> +
> + /* Mesh without normals */
> + hr = mesh->lpVtbl->CloneMeshFVF(mesh, 0, D3DFVF_XYZ, device, &cloned_mesh);
> + ok(SUCCEEDED(hr), "CloneMeshFVF failed %#x\n", hr);
> +
> + hr = func->apply(cloned_mesh, NULL);
> + ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", func->name, hr);
> +
> + refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
> + ok(!refcount, "Mesh has %u references left\n", refcount);
> +
> + /* Mesh without positions */
> + hr = mesh->lpVtbl->CloneMeshFVF(mesh, 0, D3DFVF_NORMAL, device, &cloned_mesh);
> + ok(SUCCEEDED(hr), "CloneMeshFVF failed %#x\n", hr);
> +
> + hr = func->apply(cloned_mesh, NULL);
> + ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", func->name, hr);
> +
> + refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
> + ok(!refcount, "Mesh has %u references left\n", refcount);
> +
> + /* Mesh with D3DDECLTYPE_FLOAT1 normals */
> + hr = mesh->lpVtbl->CloneMesh(mesh, 0, position3f_normal1f_declaration, device, &cloned_mesh);
> + ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr);
> +
> + hr = func->apply(cloned_mesh, NULL);
> + ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", func->name, hr);
> +
> + refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
> + ok(!refcount, "Mesh has %u references left\n", refcount);
> +
> + /* Mesh with D3DDECLTYPE_FLOAT2 normals */
> + hr = mesh->lpVtbl->CloneMesh(mesh, 0, position3f_normal2f_declaration, device, &cloned_mesh);
> + ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr);
> +
> + hr = func->apply(cloned_mesh, NULL);
> + ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", func->name, hr);
> +
> + refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
> + ok(!refcount, "Mesh has %u references left\n", refcount);
> +
> + /* Mesh without adjacency data */
> + hr = clear_normals(mesh);
> + ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
> +
> + hr = func->apply(mesh, NULL);
> + ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
> +
> + compare_normals(__LINE__, func->name, mesh, box_normals, ARRAY_SIZE(box_normals));
> +
> + /* Mesh with adjacency data */
> + hr = clear_normals(mesh);
> + ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
> +
> + hr = func->apply(mesh, ID3DXBuffer_GetBufferPointer(adjacency));
> + ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
> +
> + compare_normals(__LINE__, func->name, mesh, box_normals_adjacency, ARRAY_SIZE(box_normals_adjacency));
> +
> + /* Mesh with custom vertex format, D3DDECLTYPE_FLOAT4 normals and adjacency */
> + hr = mesh->lpVtbl->CloneMesh(mesh, 0, normal4f_position3f_declaration, device, &cloned_mesh);
> + ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr);
> +
> + hr = clear_normals(cloned_mesh);
> + ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
> +
> + hr = func->apply(cloned_mesh, ID3DXBuffer_GetBufferPointer(adjacency));
> + ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
> +
> + compare_normals(__LINE__, func->name, cloned_mesh, box_normals_adjacency, ARRAY_SIZE(box_normals_adjacency));
> +
> + refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
> + ok(!refcount, "Mesh has %u references left\n", refcount);
> +
> + /* Mesh with D3DDECLTYPE_FLOAT1 positions and D3DDECLTYPE_FLOAT3 normals */
> + hr = mesh->lpVtbl->CloneMesh(mesh, 0, position1f_normal3f_declaration, device, &cloned_mesh);
> + ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr);
> +
> + hr = clear_normals(cloned_mesh);
> + ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
> +
> + hr = func->apply(cloned_mesh, ID3DXBuffer_GetBufferPointer(adjacency));
> + ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
> +
> + compare_normals(__LINE__, func->name, cloned_mesh, box_normals_position1f, ARRAY_SIZE(box_normals_position1f));
> +
> + refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
> + ok(!refcount, "Mesh has %u references left\n", refcount);
> +
> + /* Mesh with D3DDECLTYPE_FLOAT2 positions and D3DDECLTYPE_FLOAT3 normals */
> + hr = mesh->lpVtbl->CloneMesh(mesh, 0, position2f_normal3f_declaration, device, &cloned_mesh);
> + ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr);
> +
> + hr = clear_normals(cloned_mesh);
> + ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
> +
> + hr = func->apply(cloned_mesh, ID3DXBuffer_GetBufferPointer(adjacency));
> + ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
> +
> + compare_normals(__LINE__, func->name, cloned_mesh, box_normals_position2f, ARRAY_SIZE(box_normals_position2f));
> +
> + refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
> + ok(!refcount, "Mesh has %u references left\n", refcount);
> +
> + /* Mesh with D3DDECLTYPE_FLOAT4 positions and D3DDECLTYPE_FLOAT3 normals */
> + hr = mesh->lpVtbl->CloneMesh(mesh, 0, position4f_normal3f_declaration, device, &cloned_mesh);
> + ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr);
> +
> + hr = clear_normals(cloned_mesh);
> + ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
> +
> + hr = func->apply(cloned_mesh, ID3DXBuffer_GetBufferPointer(adjacency));
> + ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
> +
> + compare_normals(__LINE__, func->name, cloned_mesh, box_normals_adjacency, ARRAY_SIZE(box_normals_adjacency));
> +
> + refcount = cloned_mesh->lpVtbl->Release(cloned_mesh);
> + ok(!refcount, "Mesh has %u references left\n", refcount);
> + }
> +
> + hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
> + D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA,
> + NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
> + ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
> +
> + compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, box_normals, ARRAY_SIZE(box_normals));
> +
> + hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
> + D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA,
> + ID3DXBuffer_GetBufferPointer(adjacency), -1.01f, -0.01f, -1.01f, NULL, NULL);
> + ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
> +
> + compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, box_normals_adjacency_area, ARRAY_SIZE(box_normals_adjacency_area));
> +
> + hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
> + D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_EQUAL,
> + NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
> + ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
> +
> + compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, box_normals, ARRAY_SIZE(box_normals));
> +
> + hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
> + D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_EQUAL,
> + ID3DXBuffer_GetBufferPointer(adjacency), -1.01f, -0.01f, -1.01f, NULL, NULL);
> + ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
> +
> + compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, box_normals_adjacency_area, ARRAY_SIZE(box_normals_adjacency_area));
> +
> + refcount = mesh->lpVtbl->Release(mesh);
> + ok(!refcount, "Mesh has %u references left\n", refcount);
> + refcount = ID3DXBuffer_Release(adjacency);
> + ok(!refcount, "Buffer has %u references left\n", refcount);
> +
> + hr = D3DXCreateSphere(device, 1.0f, 4, 6, &mesh, &adjacency);
> + ok(SUCCEEDED(hr), "D3DXCreateSphere failed %#x\n", hr);
> +
> + for (i = 0; i < ARRAY_SIZE(compute_normals_funcs); i++)
> + {
> + const struct compute_normals_func *func = &compute_normals_funcs[i];
> +
> + /* Sphere without adjacency data */
> + hr = clear_normals(mesh);
> + ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
> +
> + hr = func->apply(mesh, NULL);
> + ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
> +
> + compare_normals(__LINE__, func->name, mesh, sphere_normals, ARRAY_SIZE(sphere_normals));
> +
> + /* Sphere with adjacency data */
> + hr = clear_normals(mesh);
> + ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr);
> +
> + hr = func->apply(mesh, ID3DXBuffer_GetBufferPointer(adjacency));
> + ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr);
> +
> + compare_normals(__LINE__, func->name, mesh, sphere_normals, ARRAY_SIZE(sphere_normals));
> + }
> +
> + hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
> + D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA,
> + NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
> + ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
> +
> + compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, sphere_normals_area, ARRAY_SIZE(sphere_normals_area));
> +
> + hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
> + D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA,
> + ID3DXBuffer_GetBufferPointer(adjacency), -1.01f, -0.01f, -1.01f, NULL, NULL);
> + ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
> +
> + compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, sphere_normals_area, ARRAY_SIZE(sphere_normals_area));
> +
> + hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
> + D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_EQUAL,
> + NULL, -1.01f, -0.01f, -1.01f, NULL, NULL);
> + ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
> +
> + compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, sphere_normals_equal, ARRAY_SIZE(sphere_normals_equal));
> +
> + hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0,
> + D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_EQUAL,
> + ID3DXBuffer_GetBufferPointer(adjacency), -1.01f, -0.01f, -1.01f, NULL, NULL);
> + ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr);
> +
> + compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, sphere_normals_equal, ARRAY_SIZE(sphere_normals_equal));
> +
> + refcount = mesh->lpVtbl->Release(mesh);
> + ok(!refcount, "Mesh has %u references left\n", refcount);
> + refcount = ID3DXBuffer_Release(adjacency);
> + ok(!refcount, "Buffer has %u references left\n", refcount);
> +
> + free_test_context(test_context);
> +}
> +
> START_TEST(mesh)
> {
> D3DXBoundProbeTest();
> @@ -10401,4 +10973,5 @@ START_TEST(mesh)
> test_clone_mesh();
> test_valid_mesh();
> test_optimize_faces();
> + test_compute_normals();
> }
> --
> 2.3.6
Looking good otherwise, thanks!
July 27, 2015
Re: [PATCH 3/5] d3dx9: Partially implement D3DXComputeTangentFrameEx().
by Matteo Bruni
Hi,
I've got a number of nitpicks but these patches are essentially okay with me.
2015-07-25 11:23 GMT+02:00 Józef Kucia <joseph.kucia(a)gmail.com>:
> ---
> dlls/d3dx9_36/mesh.c | 235 ++++++++++++++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 232 insertions(+), 3 deletions(-)
>
> diff --git a/dlls/d3dx9_36/mesh.c b/dlls/d3dx9_36/mesh.c
> index 4aeac26..1558b17 100644
> --- a/dlls/d3dx9_36/mesh.c
> +++ b/dlls/d3dx9_36/mesh.c
> @@ -7235,6 +7235,41 @@ error:
> return hr;
> }
>
> +static inline D3DXVECTOR3 *vertex_element_vec3(BYTE *vertices,
> + const D3DVERTEXELEMENT9 *declaration, DWORD vertex_stride, DWORD index)
Better not to include the "inline" specifier, the compiler will inline
the function anyway if it thinks it's a good idea.
> +{
> + return (D3DXVECTOR3 *)(vertices + declaration->Offset + index * vertex_stride);
> +}
> +
> +static inline D3DXVECTOR3 read_vec3(BYTE *vertices, const D3DVERTEXELEMENT9 *declaration,
> + DWORD vertex_stride, DWORD index)
> +{
> + D3DXVECTOR3 vec3 = {0};
> + const float *src = (float *)(vertices + declaration->Offset + index * vertex_stride);
You can just use vertex_element_vec3() here, like e.g.
const D3DXVECTOR3 *src = vertex_element_vec3(vertices, declaration,
vertex_stride, index);
although the source data isn't necessarily a full vec3. Your call.
> +
> + switch (declaration->Type)
> + {
> + case D3DDECLTYPE_FLOAT1:
> + vec3.x = src[0];
> + break;
> + case D3DDECLTYPE_FLOAT2:
> + vec3.x = src[0];
> + vec3.y = src[1];
> + break;
> + case D3DDECLTYPE_FLOAT3:
> + case D3DDECLTYPE_FLOAT4:
> + vec3.x = src[0];
> + vec3.y = src[1];
> + vec3.z = src[2];
> + break;
> + default:
> + ERR("Cannot read vec3\n");
> + break;
> + }
You could sort the cases the other way around and fallthrough to make
this part shorter. Again, this is also fine and it's up to you.
> +
> + return vec3;
> +}
> +
> /*************************************************************************
> * D3DXComputeTangentFrameEx (D3DX9_36.@)
> */
> @@ -7244,15 +7279,209 @@ HRESULT WINAPI D3DXComputeTangentFrameEx(ID3DXMesh *mesh, DWORD texture_in_seman
> const DWORD *adjacency, float partial_edge_threshold, float singular_point_threshold,
> float normal_edge_threshold, ID3DXMesh **mesh_out, ID3DXBuffer **vertex_mapping)
> {
> - FIXME("mesh %p, texture_in_semantic %u, texture_in_index %u, u_partial_out_semantic %u, u_partial_out_index %u, "
> + HRESULT hr;
> + void *indices = NULL;
> + BYTE *vertices = NULL;
> + DWORD *point_reps = NULL;
> + size_t normal_size;
> + BOOL indices_are_32bit;
> + DWORD i, j, num_faces, num_vertices, vertex_stride;
> + D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE] = {D3DDECL_END()};
> + D3DVERTEXELEMENT9 *position_declaration = NULL, *normal_declaration = NULL;
> +
> + TRACE("mesh %p, texture_in_semantic %u, texture_in_index %u, u_partial_out_semantic %u, u_partial_out_index %u, "
> "v_partial_out_semantic %u, v_partial_out_index %u, normal_out_semantic %u, normal_out_index %u, "
> "options %#x, adjacency %p, partial_edge_threshold %f, singular_point_threshold %f, "
> - "normal_edge_threshold %f, mesh_out %p, vertex_mapping %p stub!\n",
> + "normal_edge_threshold %f, mesh_out %p, vertex_mapping %p\n",
> mesh, texture_in_semantic, texture_in_index, u_partial_out_semantic, u_partial_out_index,
> v_partial_out_semantic, v_partial_out_index, normal_out_semantic, normal_out_index, options, adjacency,
> partial_edge_threshold, singular_point_threshold, normal_edge_threshold, mesh_out, vertex_mapping);
>
> - return E_NOTIMPL;
> + if (!mesh)
> + {
> + WARN("mesh is NULL\n");
> + return D3DERR_INVALIDCALL;
> + }
> +
> + if ((options & (D3DXTANGENT_WEIGHT_EQUAL | D3DXTANGENT_WEIGHT_BY_AREA)) == (D3DXTANGENT_WEIGHT_EQUAL | D3DXTANGENT_WEIGHT_BY_AREA))
I would store the result of "options & (D3DXTANGENT_WEIGHT_EQUAL |
D3DXTANGENT_WEIGHT_BY_AREA)" in a variable and use it here and below.
> + {
> + WARN("D3DXTANGENT_WEIGHT_BY_AREA and D3DXTANGENT_WEIGHT_EQUAL are mutally exclusive\n");
> + return D3DERR_INVALIDCALL;
> + }
> +
> + if (u_partial_out_semantic != D3DX_DEFAULT)
> + {
> + FIXME("tangent vectors computation is not supported\n");
> + return E_NOTIMPL;
> + }
> +
> + if (v_partial_out_semantic != D3DX_DEFAULT)
> + {
> + FIXME("binormal vectors computation is not supported\n");
> + return E_NOTIMPL;
> + }
> +
> + if (options & ~(D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_EQUAL | D3DXTANGENT_WEIGHT_BY_AREA))
> + {
> + FIXME("unsupported options %#x\n", options);
> + return E_NOTIMPL;
> + }
> +
> + if (!(options & D3DXTANGENT_CALCULATE_NORMALS))
> + {
> + FIXME("only normals computation is supported\n");
> + return E_NOTIMPL;
> + }
> +
> + if (!(options & D3DXTANGENT_GENERATE_IN_PLACE) || mesh_out || vertex_mapping)
> + {
> + FIXME("only D3DXTANGENT_GENERATE_IN_PLACE is supported\n");
> + return E_NOTIMPL;
> + }
> +
> + if (FAILED(hr = mesh->lpVtbl->GetDeclaration(mesh, declaration)))
> + return hr;
> +
> + for (i = 0; declaration[i].Stream != 0xFF; i++)
Lowercase is preferred for hex literals.
> + {
> + if (declaration[i].Usage == D3DDECLUSAGE_POSITION && declaration[i].UsageIndex == 0)
> + position_declaration = &declaration[i];
> + if (declaration[i].Usage == normal_out_semantic && declaration[i].UsageIndex == normal_out_index)
> + normal_declaration = &declaration[i];
> + }
> +
> + if (!position_declaration || !normal_declaration)
> + return D3DERR_INVALIDCALL;
> +
> + if (normal_declaration->Type == D3DDECLTYPE_FLOAT3)
> + {
> + normal_size = sizeof(D3DXVECTOR3);
> + }
> + else if (normal_declaration->Type == D3DDECLTYPE_FLOAT4)
> + {
> + normal_size = sizeof(D3DXVECTOR4);
> + }
> + else
> + {
> + WARN("unsupported normals type %u\n", normal_declaration->Type);
> + return D3DERR_INVALIDCALL;
> + }
> +
> + num_faces = mesh->lpVtbl->GetNumFaces(mesh);
> + num_vertices = mesh->lpVtbl->GetNumVertices(mesh);
> + vertex_stride = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
> + indices_are_32bit = mesh->lpVtbl->GetOptions(mesh) & D3DXMESH_32BIT;
> +
> + point_reps = HeapAlloc(GetProcessHeap(), 0, num_vertices * sizeof(*point_reps));
> + if (!point_reps)
> + {
> + hr = E_OUTOFMEMORY;
> + goto done;
> + }
> +
> + if (adjacency)
> + {
> + if (FAILED(hr = mesh->lpVtbl->ConvertAdjacencyToPointReps(mesh, adjacency, point_reps)))
> + goto done;
> + }
> + else
> + {
> + for (i = 0; i < num_vertices; i++)
> + point_reps[i] = i;
> + }
> +
> + if (FAILED(hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, &indices)))
> + goto done;
> +
> + if (FAILED(hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, (void **)&vertices)))
> + goto done;
> +
> + for (i = 0; i < num_vertices; i++)
> + {
> + const D3DXVECTOR4 zero = {0.0f, 0.0f, 0.0f, 1.0f};
That's a weird zero :) Not sure about a better name though, maybe
"default_vector"? Also, please make it static.
> + void *normal = vertices + normal_declaration->Offset + i * vertex_stride;
> +
> + memcpy(normal, &zero, normal_size);
> + }
> +
> + for (i = 0; i < num_faces; i++)
> + {
> + float weights[3];
> + D3DXVECTOR3 a, b, cross, face_normal;
> + const DWORD face_indices[3] =
> + {
> + read_ib(indices, indices_are_32bit, 3 * i + 0),
> + read_ib(indices, indices_are_32bit, 3 * i + 1),
> + read_ib(indices, indices_are_32bit, 3 * i + 2)
> + };
> + const D3DXVECTOR3 v0 = read_vec3(vertices, position_declaration, vertex_stride, face_indices[0]);
> + const D3DXVECTOR3 v1 = read_vec3(vertices, position_declaration, vertex_stride, face_indices[1]);
> + const D3DXVECTOR3 v2 = read_vec3(vertices, position_declaration, vertex_stride, face_indices[2]);
> +
> + D3DXVec3Cross(&cross, D3DXVec3Subtract(&a, &v0, &v1), D3DXVec3Subtract(&b, &v0, &v2));
> +
> + switch (options & (D3DXTANGENT_WEIGHT_BY_AREA | D3DXTANGENT_WEIGHT_EQUAL))
> + {
> + case D3DXTANGENT_WEIGHT_EQUAL:
> + weights[0] = weights[1] = weights[2] = 1.0f;
> + break;
> + case D3DXTANGENT_WEIGHT_BY_AREA:
> + weights[0] = weights[1] = weights[2] = D3DXVec3Length(&cross);
> + break;
> + default:
> + weights[0] = acosf(D3DXVec3Dot(&a, &b) / (D3DXVec3Length(&a) * D3DXVec3Length(&b)));
> +
> + D3DXVec3Subtract(&a, &v1, &v0);
> + D3DXVec3Subtract(&b, &v1, &v2);
> + weights[1] = acosf(D3DXVec3Dot(&a, &b) / (D3DXVec3Length(&a) * D3DXVec3Length(&b)));
> +
> + D3DXVec3Subtract(&a, &v2, &v0);
> + D3DXVec3Subtract(&b, &v2, &v1);
> + weights[2] = acosf(D3DXVec3Dot(&a, &b) / (D3DXVec3Length(&a) * D3DXVec3Length(&b)));
> +
> + if (isnan(weights[0])) weights[0] = 1.0f;
> + if (isnan(weights[1])) weights[1] = 1.0f;
> + if (isnan(weights[2])) weights[2] = 1.0f;
> + break;
This might cause problems in the (unlikely) case float exceptions are
enabled. Ideally this case would need to be tested with native and, if
it doesn't throw exceptions, your code would need to take care of
that. I don't think this is super critical though, it should be easy
to figure it out later on if some application crashes here.
> + }
> +
> + D3DXVec3Normalize(&face_normal, &cross);
> +
> + for (j = 0; j < 3; j++)
> + {
> + D3DXVECTOR3 normal;
> + DWORD rep_index = point_reps[face_indices[j]];
> + D3DXVECTOR3 *rep_normal = vertex_element_vec3(vertices, normal_declaration, vertex_stride, rep_index);
> +
> + D3DXVec3Scale(&normal, &face_normal, weights[j]);
> + D3DXVec3Add(rep_normal, rep_normal, &normal);
> + }
> + }
> +
> + for (i = 0; i < num_vertices; i++)
> + {
> + DWORD rep_index = point_reps[i];
> + D3DXVECTOR3 *normal = vertex_element_vec3(vertices, normal_declaration, vertex_stride, i);
> + D3DXVECTOR3 *rep_normal = vertex_element_vec3(vertices, normal_declaration, vertex_stride, rep_index);
> +
> + if (i == rep_index)
> + D3DXVec3Normalize(rep_normal, rep_normal);
> + else
> + *normal = *rep_normal;
> + }
> +
> + hr = D3D_OK;
> +
> +done:
> + if (vertices)
> + mesh->lpVtbl->UnlockVertexBuffer(mesh);
> +
> + if (indices)
> + mesh->lpVtbl->UnlockIndexBuffer(mesh);
> +
> + HeapFree(GetProcessHeap(), 0, point_reps);
> +
> + return hr;
> }
>
> /*************************************************************************
> --
> 2.3.6
>
>
>
July 27, 2015
Prep for Wineconf - testing
by Jeremy White
Hi folks,
Now that I have my room booked, my thoughts turn to what we'll actually
do at Wineconf. And, of course, a Wineconf tradition is for me to lock
everyone in the room, away from the bar, until the test situation improves.
Sadly, despite the best efforts of some people (yay, Huw!), we are still
staring at a range of test failures on Windows. It looks like we've got
XP and 2003 starting to show green, and 2000 and 2008 look tantalizingly
close. Looks like msi timeouts remain a problem.
We had some discussion of throwing some hardware at the problem; I'm
happy to do that, but, afair, it wasn't clear that it would help.
Weren't we going to run an experiment by setting the run queue size to 1
to see if that prevented the msi timeout failures? If changing the run
queue size from n to 1 and buying n machines will 'fix' this, maybe it's
time to do that.
I seem to recall that Francois needed cooperation from Alexandre to run
that experiment - is that right?
Once we think we've got robust Windows tests, then we move on to pursuit
of the the holy grail - having at least two Linux machines capable of
running make test cleanly. (I recall a glorious day when we achieved
that; sadly, that moment didn't last :-/).
So does it make sense to ask people to start daily winetest runs so we
can populate a bit more data? Looks like we've got the CodeWeavers test
boxes, and one from Austin. And I don't see any for Mac :-(.
Cheers,
Jeremy
July 27, 2015