usp10: Fix glyph comparsion between tests.
[wine] / dlls / d3d9 / tests / vertexdeclaration.c
1 /*
2  * Copyright (C) 2005 Henri Verbeet
3  * Copyright (C) 2006 Ivan Gyurdiev
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18  */
19
20 #define COBJMACROS
21 #include <d3d9.h>
22 #include "wine/test.h"
23
24 static HMODULE d3d9_handle = 0;
25
26 #define VDECL_CHECK(fcall) \
27     if(fcall != S_OK) \
28         trace(" Test failed on line #%d\n", __LINE__);
29
30 static HWND create_window(void)
31 {
32     WNDCLASS wc = {0};
33     wc.lpfnWndProc = &DefWindowProc;
34     wc.lpszClassName = "d3d9_test_wc";
35     RegisterClass(&wc);
36
37     return CreateWindow("d3d9_test_wc", "d3d9_test",
38             0, 0, 0, 0, 0, 0, 0, 0, 0);
39 }
40
41 static IDirect3DDevice9 *init_d3d9(void)
42 {
43     IDirect3D9 * (__stdcall * d3d9_create)(UINT SDKVersion) = 0;
44     IDirect3D9 *d3d9_ptr = 0;
45     IDirect3DDevice9 *device_ptr = 0;
46     D3DPRESENT_PARAMETERS present_parameters;
47     HRESULT hres;
48
49     d3d9_create = (void *)GetProcAddress(d3d9_handle, "Direct3DCreate9");
50     ok(d3d9_create != NULL, "Failed to get address of Direct3DCreate9\n");
51     if (!d3d9_create) return NULL;
52     
53     d3d9_ptr = d3d9_create(D3D_SDK_VERSION);
54     ok(d3d9_ptr != NULL, "Failed to create IDirect3D9 object\n");
55     if (!d3d9_ptr) return NULL;
56
57     ZeroMemory(&present_parameters, sizeof(present_parameters));
58     present_parameters.Windowed = TRUE;
59     present_parameters.hDeviceWindow = create_window();
60     present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
61
62     hres = IDirect3D9_CreateDevice(d3d9_ptr, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, NULL, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device_ptr);
63     ok(hres == D3D_OK, "IDirect3D_CreateDevice returned: 0x%lx\n", hres);
64
65     return device_ptr;
66 }
67
68 static int get_refcount(IUnknown *object)
69 {
70     IUnknown_AddRef(object);
71     return IUnknown_Release(object);
72 }
73
74 static IDirect3DVertexDeclaration9 *test_create_vertex_declaration(IDirect3DDevice9 *device_ptr, D3DVERTEXELEMENT9 *vertex_decl)
75 {
76     IDirect3DVertexDeclaration9 *decl_ptr = 0;
77     HRESULT hret = 0;
78
79     hret = IDirect3DDevice9_CreateVertexDeclaration(device_ptr, vertex_decl, &decl_ptr);
80     ok(hret == D3D_OK && decl_ptr != NULL, "CreateVertexDeclaration returned: hret 0x%lx, decl_ptr %p. "
81         "Expected hret 0x%lx, decl_ptr != %p. Aborting.\n", hret, decl_ptr, D3D_OK, NULL);
82
83     return decl_ptr;
84 }
85
86 static void test_get_set_vertex_declaration(IDirect3DDevice9 *device_ptr, IDirect3DVertexDeclaration9 *decl_ptr)
87 {
88     IDirect3DVertexDeclaration9 *current_decl_ptr = 0;
89     HRESULT hret = 0;
90     int decl_refcount = 0;
91     int i = 0;
92     
93     /* SetVertexDeclaration should not touch the declaration's refcount. */
94     i = get_refcount((IUnknown *)decl_ptr);
95     hret = IDirect3DDevice9_SetVertexDeclaration(device_ptr, decl_ptr);
96     decl_refcount = get_refcount((IUnknown *)decl_ptr);
97     ok(hret == D3D_OK && decl_refcount == i, "SetVertexDeclaration returned: hret 0x%lx, refcount %d. "
98         "Expected hret 0x%lx, refcount %d.\n", hret, decl_refcount, D3D_OK, i);
99     
100     /* GetVertexDeclaration should increase the declaration's refcount by one. */
101     i = decl_refcount+1;
102     hret = IDirect3DDevice9_GetVertexDeclaration(device_ptr, &current_decl_ptr);
103     decl_refcount = get_refcount((IUnknown *)decl_ptr);
104     ok(hret == D3D_OK && decl_refcount == i && current_decl_ptr == decl_ptr, 
105         "GetVertexDeclaration returned: hret 0x%lx, current_decl_ptr %p refcount %d. "
106         "Expected hret 0x%lx, current_decl_ptr %p, refcount %d.\n", hret, current_decl_ptr, decl_refcount, D3D_OK, decl_ptr, i);
107 }
108
109 static void test_get_declaration(IDirect3DVertexDeclaration9 *decl_ptr, D3DVERTEXELEMENT9 *vertex_decl, UINT expected_num_elements)
110 {
111     int i;
112     UINT num_elements = 0;
113     D3DVERTEXELEMENT9 *decl = 0;
114     HRESULT hret = 0;
115
116     /* First test only getting the number of elements */
117     num_elements = 0x1337c0de;
118     hret = IDirect3DVertexDeclaration9_GetDeclaration(decl_ptr, NULL, &num_elements);
119     ok(hret == D3D_OK && num_elements == expected_num_elements,
120             "GetDeclaration returned: hret 0x%lx, num_elements %d. "
121             "Expected hret 0x%lx, num_elements %d.\n", hret, num_elements, D3D_OK, expected_num_elements);
122
123     num_elements = 0;
124     hret = IDirect3DVertexDeclaration9_GetDeclaration(decl_ptr, NULL, &num_elements);
125     ok(hret == D3D_OK && num_elements == expected_num_elements,
126             "GetDeclaration returned: hret 0x%lx, num_elements %d. "
127             "Expected hret 0x%lx, num_elements %d.\n", hret, num_elements, D3D_OK, expected_num_elements);
128
129     /* Also test the returned data */
130     decl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(D3DVERTEXELEMENT9) * expected_num_elements);
131
132     num_elements = 0x1337c0de;
133     hret = IDirect3DVertexDeclaration9_GetDeclaration(decl_ptr, decl, &num_elements);
134     ok(hret == D3D_OK && num_elements == expected_num_elements,
135             "GetDeclaration returned: hret 0x%lx, num_elements %d. "
136             "Expected hret 0x%lx, num_elements %d.\n", hret, num_elements, D3D_OK, expected_num_elements);
137     i = memcmp(decl, vertex_decl, sizeof(vertex_decl));
138     ok (!i, "Original and returned vertexdeclarations are not the same\n");
139     ZeroMemory(decl, sizeof(D3DVERTEXELEMENT9) * expected_num_elements);
140
141     num_elements = 0;
142     hret = IDirect3DVertexDeclaration9_GetDeclaration(decl_ptr, decl, &num_elements);
143     ok(hret == D3D_OK && num_elements == expected_num_elements,
144             "GetDeclaration returned: hret 0x%lx, num_elements %d. "
145             "Expected hret 0x%lx, num_elements %d.\n", hret, num_elements, D3D_OK, expected_num_elements);
146     i = memcmp(decl, vertex_decl, sizeof(vertex_decl));
147     ok (!i, "Original and returned vertexdeclarations are not the same\n");
148
149     HeapFree(GetProcessHeap(), 0, decl);
150 }
151
152 /* FIXME: also write a test, which shows that attempting to set
153  * an invalid vertex declaration returns E_FAIL */
154
155 static HRESULT test_fvf_to_decl(
156     IDirect3DDevice9* device,
157     IDirect3DVertexDeclaration9* default_decl,
158     DWORD test_fvf,
159     CONST D3DVERTEXELEMENT9 expected_elements[],
160     D3DVERTEXELEMENT9* result_elements_ptr,
161     UINT expected_size,
162     char object_should_change) 
163 {
164
165     HRESULT hr;
166     IDirect3DVertexDeclaration9 *result_decl = NULL;
167     UINT result_size = 12345;
168
169     /* Set a default declaration to make sure it is changed */
170     hr = IDirect3DDevice9_SetVertexDeclaration ( device, default_decl );
171     ok (SUCCEEDED(hr), "SetVertexDeclaration returned %#lx, expected %#lx\n", hr, D3D_OK);
172     if (FAILED(hr)) goto fail;
173
174     /* Set an FVF */
175     hr = IDirect3DDevice9_SetFVF( device, test_fvf);
176     ok(SUCCEEDED(hr), "SetFVF returned %#lx, expected %#lx\n", hr, D3D_OK);
177     if (FAILED(hr)) goto fail;
178
179     /* Check if the declaration object changed underneath */
180     hr = IDirect3DDevice9_GetVertexDeclaration ( device, &result_decl);
181     ok(SUCCEEDED(hr), "GetVertexDeclaration returned %#lx, expected %#lx\n", hr, D3D_OK);
182     if (FAILED(hr)) goto fail;
183     if (object_should_change) {
184        ok(result_decl != default_decl, "result declaration matches original\n");
185        if (result_decl == default_decl) goto fail;
186     } else {
187        ok(result_decl == default_decl, "result declaration does not match original\n");
188        if (result_decl != default_decl) goto fail;
189     }
190
191     /* Declaration content/size test */
192     ok(result_decl != NULL, "result declaration was null\n");
193     if (result_decl == NULL) 
194         goto fail;
195     else { 
196
197         int status;
198
199         /* Check if the size changed, and abort if it did */
200         hr = IDirect3DVertexDeclaration9_GetDeclaration( result_decl, NULL, &result_size );
201         ok(SUCCEEDED(hr), "GetDeclaration returned %#lx, expected %#lx\n", hr, D3D_OK);
202         if (FAILED(hr)) goto fail;
203         ok(result_size == expected_size, "result declaration size: %d, "
204             "expected: %d\n", result_size, expected_size);
205         if (result_size != expected_size) goto fail;
206
207         /* Check the actual elements. Write it them in a caller-allocated array of the correct size
208          * That's fine, since we aborted above if the size didn't match the caller's expectations */
209         hr = IDirect3DVertexDeclaration9_GetDeclaration( result_decl, result_elements_ptr, &result_size );
210         ok(SUCCEEDED(hr), "GetDeclaration returned %#lx, expected %#lx\n", hr, D3D_OK);
211         if (FAILED(hr)) goto fail;
212
213         ok(result_size == expected_size, "result declaration size: %d, "
214             "expected: %d\n", result_size, expected_size);
215         if (result_size != expected_size) goto fail;
216         
217         status = memcmp(expected_elements, result_elements_ptr, expected_size * sizeof(D3DVERTEXELEMENT9));  
218         ok(!status, "result declaration differs from expected\n");
219         if (status) {
220             unsigned int i;
221
222             for (i = 0; i < expected_size; i++) { 
223
224                  trace(
225                      "Stream = %d, Offset = %d, Type = %d, "
226                      "Method = %d, Usage = %d, UsageIndex = %d\n", 
227                      result_elements_ptr[i].Stream,
228                      result_elements_ptr[i].Offset,
229                      result_elements_ptr[i].Type,
230                      result_elements_ptr[i].Method,
231                      result_elements_ptr[i].Usage,
232                      result_elements_ptr[i].UsageIndex);
233             }
234             goto fail;
235         }
236     }
237
238     if (result_decl) IUnknown_Release( result_decl );
239     return S_OK;    
240
241     fail:
242     if (result_decl) IUnknown_Release( result_decl );
243     return E_FAIL;
244 }
245
246 static HRESULT test_decl_to_fvf(
247     IDirect3DDevice9* device,
248     DWORD default_fvf,
249     CONST D3DVERTEXELEMENT9 test_decl[],
250     DWORD test_fvf)
251 {
252
253     HRESULT hr;
254     IDirect3DVertexDeclaration9 *vdecl = NULL;
255
256     DWORD result_fvf = 0xdeadbeef;
257
258     /* Set a default FVF of SPECULAR and DIFFUSE to make sure it is changed back to 0 */
259     hr = IDirect3DDevice9_SetFVF( device, default_fvf);
260     ok(SUCCEEDED(hr), "SetFVF returned %#lx, expected %#lx\n", hr, D3D_OK);
261     if (FAILED(hr)) goto fail;
262
263     /* Create a testing declaration */
264     hr = IDirect3DDevice9_CreateVertexDeclaration( device, test_decl, &vdecl );
265     ok(SUCCEEDED(hr), "CreateVertexDeclaration returned %#lx, expected %#lx\n", hr, D3D_OK);
266     if (FAILED(hr)) goto fail;
267
268     /* Set the declaration */
269     hr = IDirect3DDevice9_SetVertexDeclaration ( device, vdecl );
270     ok (SUCCEEDED(hr), "SetVertexDeclaration returned %#lx, expected %#lx\n", hr, D3D_OK);
271     if (FAILED(hr)) goto fail;
272
273     /* Check the FVF */
274     hr = IDirect3DDevice9_GetFVF( device, &result_fvf);
275     ok(SUCCEEDED(hr), "GetFVF returned %#lx, expected %#lx\n", hr, D3D_OK);
276     if (FAILED(hr)) goto fail;
277     todo_wine {
278        ok(test_fvf == result_fvf, "result FVF was: %#lx, expected: %#lx\n", result_fvf, test_fvf);
279     }
280     if (test_fvf != result_fvf) goto fail;
281
282     IDirect3DDevice9_SetVertexDeclaration ( device, NULL );
283     if (vdecl) IUnknown_Release( vdecl );
284     return S_OK;
285
286     fail:
287     IDirect3DDevice9_SetVertexDeclaration ( device, NULL );
288     if (vdecl) IUnknown_Release( vdecl );
289     return E_FAIL;
290 }
291
292 static void test_fvf_decl_conversion(IDirect3DDevice9 *pDevice)
293 {
294
295     HRESULT hr;
296     D3DVERTEXELEMENT9 result_buffer[MAXD3DDECLLENGTH];
297     unsigned int i;
298
299     IDirect3DVertexDeclaration9* default_decl = NULL;
300     DWORD default_fvf = D3DFVF_SPECULAR | D3DFVF_DIFFUSE;
301     D3DVERTEXELEMENT9 default_elements[] =
302         { { 0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0 },
303           { 0, 4, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1 }, D3DDECL_END() };
304
305     /* Create a default declaration and FVF that does not match any of the tests */
306     hr = IDirect3DDevice9_CreateVertexDeclaration( pDevice, default_elements, &default_decl );
307     ok(SUCCEEDED(hr), "CreateVertexDeclaration returned %#lx, expected %#lx\n", hr, D3D_OK);
308     if (FAILED(hr)) goto cleanup;
309
310     /* Test conversions from vertex declaration to an FVF.
311      * For some reason those seem to occur only for POSITION/POSITIONT,
312      * Otherwise the FVF is forced to 0 - maybe this is configuration specific */
313     {
314         CONST D3DVERTEXELEMENT9 test_buffer[] =
315             { { 0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 }, D3DDECL_END() };
316         VDECL_CHECK(test_decl_to_fvf(pDevice, default_fvf, test_buffer, D3DFVF_XYZ));
317     }
318     {
319         CONST D3DVERTEXELEMENT9 test_buffer[] =
320             { { 0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITIONT, 0 }, D3DDECL_END() };
321         VDECL_CHECK(test_decl_to_fvf(pDevice, default_fvf, test_buffer, D3DFVF_XYZRHW));
322     }
323     for (i = 0; i < 4; i++) {
324         CONST D3DVERTEXELEMENT9 test_buffer[] =
325             { { 0, 0, D3DDECLTYPE_FLOAT1+i, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, D3DDECL_END() };
326         VDECL_CHECK(test_decl_to_fvf(pDevice, default_fvf, test_buffer, 0));
327     }
328     {
329         CONST D3DVERTEXELEMENT9 test_buffer[] = 
330             { { 0, 0, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0}, D3DDECL_END() };
331         VDECL_CHECK(test_decl_to_fvf(pDevice, default_fvf, test_buffer, 0));
332     }
333     {
334         CONST D3DVERTEXELEMENT9 test_buffer[] =
335             { { 0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0 }, D3DDECL_END() };
336         VDECL_CHECK(test_decl_to_fvf(pDevice, default_fvf, test_buffer, 0));
337     }
338     {
339         CONST D3DVERTEXELEMENT9 test_buffer[] =
340             { { 0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0 }, D3DDECL_END() };
341         VDECL_CHECK(test_decl_to_fvf(pDevice, default_fvf, test_buffer, 0));
342     }
343     {
344         CONST D3DVERTEXELEMENT9 test_buffer[] =
345             { { 0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0 }, D3DDECL_END() };
346         VDECL_CHECK(test_decl_to_fvf(pDevice, default_fvf, test_buffer, 0));
347     }
348     {
349         CONST D3DVERTEXELEMENT9 test_buffer[] =
350             { { 0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1 }, D3DDECL_END() };
351         VDECL_CHECK(test_decl_to_fvf(pDevice, default_fvf, test_buffer, 0));
352     }
353
354     /* Make sure textures of different sizes work */
355     {
356         CONST D3DVERTEXELEMENT9 test_buffer[] =
357             { { 0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0 }, D3DDECL_END() };
358         VDECL_CHECK(test_decl_to_fvf(pDevice, default_fvf, test_buffer, 0));
359     }
360     {
361         CONST D3DVERTEXELEMENT9 test_buffer[] =
362             { { 0, 0, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0 }, D3DDECL_END() };
363         VDECL_CHECK(test_decl_to_fvf(pDevice, default_fvf, test_buffer, 0));
364     }
365     {
366         CONST D3DVERTEXELEMENT9 test_buffer[] =
367             { { 0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 0 }, D3DDECL_END() };
368         VDECL_CHECK(test_decl_to_fvf(pDevice, default_fvf, test_buffer, 0));
369     }
370     {
371         CONST D3DVERTEXELEMENT9 test_buffer[] =
372             { { 0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 0 }, D3DDECL_END() };
373         VDECL_CHECK(test_decl_to_fvf(pDevice, default_fvf, test_buffer, 0));
374     }
375
376     /* Make sure the TEXCOORD index works correctly - try several textures */
377     {
378         CONST D3DVERTEXELEMENT9 test_buffer[] =
379             { { 0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0 },
380               { 0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 1 },
381               { 0, 16, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 2 },
382               { 0, 24, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 3 }, D3DDECL_END() };
383         VDECL_CHECK(test_decl_to_fvf(pDevice, default_fvf, test_buffer, 0));
384     }
385
386     /* No FVF mapping available */
387     {
388         CONST D3DVERTEXELEMENT9 test_buffer[] =
389             { { 0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 1 }, D3DDECL_END() };
390         VDECL_CHECK(test_decl_to_fvf(pDevice, default_fvf, test_buffer, 0));
391     }
392     {
393         CONST D3DVERTEXELEMENT9 test_buffer[] =
394             { { 0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 1 }, D3DDECL_END() };
395         VDECL_CHECK(test_decl_to_fvf(pDevice, default_fvf, test_buffer, 0));
396     }
397
398     /* Try empty declaration */
399     {
400         CONST D3DVERTEXELEMENT9 test_buffer[] = { D3DDECL_END() };
401         VDECL_CHECK(test_decl_to_fvf(pDevice, default_fvf, test_buffer, 0));
402     }
403
404     /* Now try a combination test */
405     {
406         CONST D3DVERTEXELEMENT9 test_buffer[] =
407             { { 0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITIONT, 0 },
408               { 0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0 },
409               { 0, 24, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0 },
410               { 0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1 },
411               { 0, 32, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0 },
412               { 0, 44, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 1 }, D3DDECL_END() };
413         VDECL_CHECK(test_decl_to_fvf(pDevice, default_fvf, test_buffer, 0));
414     }
415
416     /* Test conversions from FVF to a vertex declaration 
417      * These seem to always occur internally. A new declaration object is created if necessary */
418
419     {
420         CONST D3DVERTEXELEMENT9 test_buffer[] =
421             { { 0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 }, D3DDECL_END() };
422         VDECL_CHECK(test_fvf_to_decl(pDevice, default_decl, D3DFVF_XYZ, test_buffer, result_buffer, 2, 1));
423     }
424     {
425         CONST D3DVERTEXELEMENT9 test_buffer[] =
426           { { 0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITIONT, 0 }, D3DDECL_END() };
427         VDECL_CHECK(test_fvf_to_decl(pDevice, default_decl, D3DFVF_XYZRHW, test_buffer, result_buffer, 2, 1));
428     }
429     {
430         CONST D3DVERTEXELEMENT9 test_buffer[] =
431             { { 0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
432               { 0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0 },
433               { 0, 28, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0 }, D3DDECL_END() };
434         VDECL_CHECK(test_fvf_to_decl(pDevice, default_decl, D3DFVF_XYZB5 | D3DFVF_LASTBETA_UBYTE4,
435             test_buffer, result_buffer, 4, 1));
436     }
437     {
438         CONST D3DVERTEXELEMENT9 test_buffer[] =
439             { { 0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
440               { 0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0 },
441               { 0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0 }, D3DDECL_END() };
442         VDECL_CHECK(test_fvf_to_decl(pDevice, default_decl, D3DFVF_XYZB5 | D3DFVF_LASTBETA_D3DCOLOR,
443            test_buffer, result_buffer, 4, 1));
444     }
445     {
446         CONST D3DVERTEXELEMENT9 test_buffer[] =
447             { { 0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
448               { 0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0 },
449               { 0, 28, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDINDICES, 0 }, D3DDECL_END() };
450         VDECL_CHECK(test_fvf_to_decl(pDevice, default_decl, D3DFVF_XYZB5, test_buffer, result_buffer, 4, 1));
451     }
452     {
453         CONST D3DVERTEXELEMENT9 test_buffer[] =
454             { { 0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
455               { 0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0 }, D3DDECL_END() };
456         VDECL_CHECK(test_fvf_to_decl(pDevice, default_decl, D3DFVF_XYZB1, test_buffer, result_buffer, 3, 1));
457     }
458     {
459         CONST D3DVERTEXELEMENT9 test_buffer[] =
460             { { 0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
461               { 0, 12, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0 }, D3DDECL_END() };
462         VDECL_CHECK(test_fvf_to_decl(pDevice, default_decl, D3DFVF_XYZB1 | D3DFVF_LASTBETA_UBYTE4,
463             test_buffer, result_buffer, 3, 1));
464     }
465     {
466         CONST D3DVERTEXELEMENT9 test_buffer[] =
467             { { 0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
468               { 0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0 }, D3DDECL_END() };
469         VDECL_CHECK(test_fvf_to_decl(pDevice, default_decl, D3DFVF_XYZB1 | D3DFVF_LASTBETA_D3DCOLOR,
470             test_buffer, result_buffer, 3, 1));
471     }
472     {
473          CONST D3DVERTEXELEMENT9 test_buffer[] =
474              { { 0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
475                { 0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0 }, D3DDECL_END() };
476          VDECL_CHECK(test_fvf_to_decl(pDevice, default_decl, D3DFVF_XYZB2, test_buffer, result_buffer, 3, 1));
477     }
478     {
479          CONST D3DVERTEXELEMENT9 test_buffer[] =
480              { { 0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
481                { 0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0 },
482                { 0, 16, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0 }, D3DDECL_END() };
483          VDECL_CHECK(test_fvf_to_decl(pDevice, default_decl, D3DFVF_XYZB2 | D3DFVF_LASTBETA_UBYTE4,
484              test_buffer, result_buffer, 4, 1));
485      }
486      {
487          CONST D3DVERTEXELEMENT9 test_buffer[] =
488              { { 0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
489                { 0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDWEIGHT, 0 },
490                { 0, 16, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0 }, D3DDECL_END() };
491          VDECL_CHECK(test_fvf_to_decl(pDevice, default_decl, D3DFVF_XYZB2 | D3DFVF_LASTBETA_D3DCOLOR,
492              test_buffer, result_buffer, 4, 1));
493      }
494      {
495         CONST D3DVERTEXELEMENT9 test_buffer[] =
496             { { 0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
497               { 0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0 }, D3DDECL_END() };
498         VDECL_CHECK(test_fvf_to_decl(pDevice, default_decl, D3DFVF_XYZB3, test_buffer, result_buffer, 3, 1));
499     }
500     {
501         CONST D3DVERTEXELEMENT9 test_buffer[] =
502             { { 0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
503               { 0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0 },
504               { 0, 20, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0 }, D3DDECL_END() };
505         VDECL_CHECK(test_fvf_to_decl(pDevice, default_decl, D3DFVF_XYZB3 | D3DFVF_LASTBETA_UBYTE4,
506             test_buffer, result_buffer, 4, 1));
507     }
508     {
509         CONST D3DVERTEXELEMENT9 test_buffer[] =
510             { { 0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
511               { 0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0 },
512               { 0, 20, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0 }, D3DDECL_END() };
513         VDECL_CHECK(test_fvf_to_decl(pDevice, default_decl, D3DFVF_XYZB3 | D3DFVF_LASTBETA_D3DCOLOR,
514             test_buffer, result_buffer, 4, 1));
515     }
516     {
517         CONST D3DVERTEXELEMENT9 test_buffer[] =
518             { { 0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
519               { 0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0 }, D3DDECL_END() };
520         VDECL_CHECK(test_fvf_to_decl(pDevice, default_decl, D3DFVF_XYZB4, test_buffer, result_buffer, 3, 1));
521     }
522     {
523         CONST D3DVERTEXELEMENT9 test_buffer[] =
524             { { 0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
525               { 0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0 },
526               { 0, 24, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0 }, D3DDECL_END() };
527         VDECL_CHECK(test_fvf_to_decl(pDevice, default_decl, D3DFVF_XYZB4 | D3DFVF_LASTBETA_UBYTE4,
528             test_buffer, result_buffer, 4, 1));
529     }
530     {
531         CONST D3DVERTEXELEMENT9 test_buffer[] =
532             { { 0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
533               { 0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0 },
534               { 0, 24, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0 }, D3DDECL_END() };
535         VDECL_CHECK(test_fvf_to_decl(pDevice, default_decl, D3DFVF_XYZB4 | D3DFVF_LASTBETA_D3DCOLOR,
536             test_buffer, result_buffer, 4, 1));
537     }
538     {
539         CONST D3DVERTEXELEMENT9 test_buffer[] =
540             { { 0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0 }, D3DDECL_END() };
541         VDECL_CHECK(test_fvf_to_decl(pDevice, default_decl, D3DFVF_NORMAL, test_buffer, result_buffer, 2, 1));
542     }
543     {
544         CONST D3DVERTEXELEMENT9 test_buffer[] =
545             { { 0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0 }, D3DDECL_END() };
546         VDECL_CHECK(test_fvf_to_decl(pDevice, default_decl, D3DFVF_PSIZE, test_buffer, result_buffer, 2, 1));
547     }
548     {
549         CONST D3DVERTEXELEMENT9 test_buffer[] =
550             { { 0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0 }, D3DDECL_END() };
551         VDECL_CHECK(test_fvf_to_decl(pDevice, default_decl, D3DFVF_DIFFUSE, test_buffer, result_buffer, 2, 1));
552     }
553     {
554         CONST D3DVERTEXELEMENT9 test_buffer[] =
555             { { 0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1 }, D3DDECL_END() };
556         VDECL_CHECK(test_fvf_to_decl(pDevice, default_decl, D3DFVF_SPECULAR, test_buffer, result_buffer, 2, 1));
557     }
558
559     /* Make sure textures of different sizes work */
560     {
561         CONST D3DVERTEXELEMENT9 test_buffer[] =
562             { { 0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0 }, D3DDECL_END() };
563         VDECL_CHECK(test_fvf_to_decl(pDevice, default_decl, D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEX1,
564            test_buffer, result_buffer, 2, 1));
565     }
566     {
567         CONST D3DVERTEXELEMENT9 test_buffer[] =
568             { { 0, 0, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0 }, D3DDECL_END() };
569         VDECL_CHECK(test_fvf_to_decl(pDevice, default_decl, D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEX1,
570            test_buffer, result_buffer, 2, 1));
571     }
572     {
573         CONST D3DVERTEXELEMENT9 test_buffer[] =
574             { { 0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 0 }, D3DDECL_END() };
575         VDECL_CHECK(test_fvf_to_decl(pDevice, default_decl, D3DFVF_TEXCOORDSIZE3(0) | D3DFVF_TEX1,
576            test_buffer, result_buffer, 2, 1));
577     }
578     {
579         CONST D3DVERTEXELEMENT9 test_buffer[] =
580             { { 0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 0 }, D3DDECL_END() };
581         VDECL_CHECK(test_fvf_to_decl(pDevice, default_decl, D3DFVF_TEXCOORDSIZE4(0) | D3DFVF_TEX1,
582            test_buffer, result_buffer, 2, 1));
583     }
584
585     /* Make sure the TEXCOORD index works correctly - try several textures */
586     {
587         CONST D3DVERTEXELEMENT9 test_buffer[] =
588             { { 0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0 },
589               { 0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 1 },
590               { 0, 16, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 2 },
591               { 0, 24, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 3 }, D3DDECL_END() };
592         VDECL_CHECK(test_fvf_to_decl(pDevice, default_decl,
593             D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEXCOORDSIZE3(1) | D3DFVF_TEXCOORDSIZE2(2) |
594             D3DFVF_TEXCOORDSIZE4(3) | D3DFVF_TEX4, test_buffer, result_buffer, 5, 1));
595     }
596
597     /* Now try a combination test  */
598     {
599        CONST D3DVERTEXELEMENT9 test_buffer[] =
600                 { { 0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
601                   { 0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0 },
602                   { 0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0 },
603                   { 0, 32, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1 },
604                   { 0, 36, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0 },
605                   { 0, 44, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 1 }, D3DDECL_END() };
606        VDECL_CHECK(test_fvf_to_decl(pDevice, default_decl, D3DFVF_XYZB4 | D3DFVF_SPECULAR | D3DFVF_DIFFUSE |
607            D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEXCOORDSIZE3(1) | D3DFVF_TEX2, test_buffer, result_buffer, 7, 1));
608     }
609
610     /* Setting the FVF to 0 should result in no change to the default decl */
611     VDECL_CHECK(test_fvf_to_decl(pDevice, default_decl, 0, default_elements, result_buffer, 3, 0));
612
613     cleanup:
614     IDirect3DDevice9_SetVertexDeclaration ( pDevice, NULL );
615     if ( default_decl ) IUnknown_Release (default_decl);
616 }
617
618 START_TEST(vertexdeclaration)
619 {
620     static D3DVERTEXELEMENT9 simple_decl[] = {
621         { 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
622         D3DDECL_END()};
623     UINT simple_decl_num_elements = sizeof(simple_decl) / sizeof(*simple_decl);
624     IDirect3DDevice9 *device_ptr = 0;
625     IDirect3DVertexDeclaration9 *decl_ptr = 0;
626
627     d3d9_handle = LoadLibraryA("d3d9.dll");
628     if (!d3d9_handle)
629     {
630         trace("Could not load d3d9.dll, skipping tests\n");
631         return;
632     }
633
634     device_ptr = init_d3d9();
635     if (!device_ptr)
636     {
637         trace("Failed to initialise d3d9, aborting test.\n");
638         return;
639     }
640
641     decl_ptr = test_create_vertex_declaration(device_ptr, simple_decl);
642     if (!decl_ptr)
643     {
644         trace("Failed to create a vertex declaration, aborting test.\n");
645         return;
646     }
647
648     test_get_set_vertex_declaration(device_ptr, decl_ptr);
649     test_get_declaration(decl_ptr, simple_decl, simple_decl_num_elements);
650     test_fvf_decl_conversion(device_ptr);
651 }