ole32: Fix wrap-around bug in tick count comparison.
[wine] / dlls / d3drm / tests / d3drm.c
1 /*
2  * Copyright 2010, 2012 Christian Costa
3  * Copyright 2012 AndrĂ© Hentschel
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 <d3drm.h>
22 #include <initguid.h>
23 #include <d3drmwin.h>
24
25 #include "wine/test.h"
26
27 static HMODULE d3drm_handle = 0;
28
29 static HRESULT (WINAPI * pDirect3DRMCreate)(LPDIRECT3DRM* ppDirect3DRM);
30
31 #define CHECK_REFCOUNT(obj,rc) \
32     { \
33         int rc_new = rc; \
34         int count = get_refcount( (IUnknown *)obj ); \
35         ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
36     }
37
38 #define D3DRM_GET_PROC(func) \
39     p ## func = (void*)GetProcAddress(d3drm_handle, #func); \
40     if(!p ## func) { \
41       trace("GetProcAddress(%s) failed\n", #func); \
42       FreeLibrary(d3drm_handle); \
43       return FALSE; \
44     }
45
46 static BOOL InitFunctionPtrs(void)
47 {
48     d3drm_handle = LoadLibraryA("d3drm.dll");
49
50     if(!d3drm_handle)
51     {
52         skip("Could not load d3drm.dll\n");
53         return FALSE;
54     }
55
56     D3DRM_GET_PROC(Direct3DRMCreate)
57
58     return TRUE;
59 }
60
61 static int get_refcount(IUnknown *object)
62 {
63     IUnknown_AddRef( object );
64     return IUnknown_Release( object );
65 }
66
67 static BOOL match_float(float a, float b)
68 {
69     return (a - b) < 0.000001f;
70 }
71
72 static D3DRMMATRIX4D identity = {
73     { 1.0f, 0.0f, 0.0f, 0.0f },
74     { 0.0f, 1.0f, 0.0f, 0.0f },
75     { 0.0f, 0.0f, 1.0f, 0.0f },
76     { 0.0f, 0.0f, 0.0f, 1.0f }
77 };
78
79 static char data_bad_version[] =
80 "xof 0302txt 0064\n"
81 "Header Object\n"
82 "{\n"
83 "1; 2; 3;\n"
84 "}\n";
85
86 static char data_no_mesh[] =
87 "xof 0302txt 0064\n"
88 "Header Object\n"
89 "{\n"
90 "1; 0; 1;\n"
91 "}\n";
92
93 static char data_ok[] =
94 "xof 0302txt 0064\n"
95 "Header Object\n"
96 "{\n"
97 "1; 0; 1;\n"
98 "}\n"
99 "Mesh Object\n"
100 "{\n"
101 "4;\n"
102 "1.0; 0.0; 0.0;,\n"
103 "0.0; 1.0; 0.0;,\n"
104 "0.0; 0.0; 1.0;,\n"
105 "1.0; 1.0; 1.0;;\n"
106 "3;\n"
107 "3; 0, 1, 2;,\n"
108 "3; 1, 2, 3;,\n"
109 "3; 3, 1, 2;;\n"
110 "}\n";
111
112 static char data_full[] =
113 "xof 0302txt 0064\n"
114 "Header { 1; 0; 1; }\n"
115 "Mesh {\n"
116 " 3;\n"
117 " 0.1; 0.2; 0.3;,\n"
118 " 0.4; 0.5; 0.6;,\n"
119 " 0.7; 0.8; 0.9;;\n"
120 " 1;\n"
121 " 3; 0, 1, 2;;\n"
122 " MeshMaterialList {\n"
123 "  1; 1; 0;\n"
124 "  Material {\n"
125 "   0.0; 1.0; 0.0; 1.0;;\n"
126 "   30.0;\n"
127 "   1.0; 0.0; 0.0;;\n"
128 "   0.5; 0.5; 0.5;;\n"
129 "   TextureFileName {\n"
130 "    \"Texture.bmp\";\n"
131 "   }\n"
132 "  }\n"
133 " }\n"
134 " MeshNormals {\n"
135 "  3;\n"
136 "  1.1; 1.2; 1.3;,\n"
137 "  1.4; 1.5; 1.6;,\n"
138 "  1.7; 1.8; 1.9;;\n"
139 "  1;"
140 "  3; 0, 1, 2;;\n"
141 " }\n"
142 " MeshTextureCoords {\n"
143 "  3;\n"
144 "  0.13; 0.17;,\n"
145 "  0.23; 0.27;,\n"
146 "  0.33; 0.37;;\n"
147 " }\n"
148 "}\n";
149
150 static char data_d3drm_load[] =
151 "xof 0302txt 0064\n"
152 "Header Object\n"
153 "{\n"
154 "1; 0; 1;\n"
155 "}\n"
156 "Mesh Object1\n"
157 "{\n"
158 " 1;\n"
159 " 0.1; 0.2; 0.3;,\n"
160 " 1;\n"
161 " 3; 0, 1, 2;;\n"
162 "}\n"
163 "Mesh Object2\n"
164 "{\n"
165 " 1;\n"
166 " 0.1; 0.2; 0.3;,\n"
167 " 1;\n"
168 " 3; 0, 1, 2;;\n"
169 "}\n"
170 "Frame Scene\n"
171 "{\n"
172 " {Object1}\n"
173 " {Object2}\n"
174 "}\n"
175 "Material\n"
176 "{\n"
177 " 0.1, 0.2, 0.3, 0.4;;\n"
178 " 0.5;\n"
179 " 0.6, 0.7, 0.8;;\n"
180 " 0.9, 1.0, 1.1;;\n"
181 "}\n";
182
183 static char data_frame_mesh_materials[] =
184 "xof 0302txt 0064\n"
185 "Header { 1; 0; 1; }\n"
186 "Frame {\n"
187 " Mesh mesh1 {\n"
188 "  5;\n"
189 "  0.1; 0.2; 0.3;,\n"
190 "  0.4; 0.5; 0.6;,\n"
191 "  0.7; 0.8; 0.9;,\n"
192 "  1.1; 1.2; 1.3;,\n"
193 "  1.4; 1.5; 1.6;;\n"
194 "  6;\n"
195 "  3; 0, 1, 2;,\n"
196 "  3; 0, 2, 1;,\n"
197 "  3; 1, 2, 3;,\n"
198 "  3; 1, 3, 2;,\n"
199 "  3; 2, 3, 4;,\n"
200 "  3; 2, 4, 3;;\n"
201 "  MeshMaterialList {\n"
202 "   3; 6; 0, 1, 1, 2, 2, 2;\n"
203 "   Material mat1 {\n"
204 "    1.0; 0.0; 0.0; 0.1;;\n"
205 "    10.0;\n"
206 "    0.11; 0.12; 0.13;;\n"
207 "    0.14; 0.15; 0.16;;\n"
208 "   }\n"
209 "   Material mat2 {\n"
210 "    0.0; 1.0; 0.0; 0.2;;\n"
211 "    20.0;\n"
212 "    0.21; 0.22; 0.23;;\n"
213 "    0.24; 0.25; 0.26;;\n"
214 "   }\n"
215 "   Material mat3 {\n"
216 "    0.0; 0.0; 1.0; 0.3;;\n"
217 "    30.0;\n"
218 "    0.31; 0.32; 0.33;;\n"
219 "    0.34; 0.35; 0.36;;\n"
220 "   }\n"
221 "  }\n"
222 " }\n"
223 "}\n";
224
225 static void test_MeshBuilder(void)
226 {
227     HRESULT hr;
228     LPDIRECT3DRM pD3DRM;
229     LPDIRECT3DRMMESHBUILDER pMeshBuilder;
230     LPDIRECT3DRMMESH mesh;
231     D3DRMLOADMEMORY info;
232     int val;
233     DWORD val1, val2, val3;
234     D3DVALUE valu, valv;
235     D3DVECTOR v[3];
236     D3DVECTOR n[4];
237     DWORD f[8];
238     char name[10];
239     DWORD size;
240     D3DCOLOR color;
241     CHAR cname[64] = {0};
242
243     hr = pDirect3DRMCreate(&pD3DRM);
244     ok(hr == D3DRM_OK, "Cannot get IDirect3DRM interface (hr = %x)\n", hr);
245
246     hr = IDirect3DRM_CreateMeshBuilder(pD3DRM, &pMeshBuilder);
247     ok(hr == D3DRM_OK, "Cannot get IDirect3DRMMeshBuilder interface (hr = %x)\n", hr);
248
249     hr = IDirect3DRMMeshBuilder_GetClassName(pMeshBuilder, NULL, cname);
250     ok(hr == E_INVALIDARG, "GetClassName failed with %x\n", hr);
251     hr = IDirect3DRMMeshBuilder_GetClassName(pMeshBuilder, NULL, NULL);
252     ok(hr == E_INVALIDARG, "GetClassName failed with %x\n", hr);
253     size = 1;
254     hr = IDirect3DRMMeshBuilder_GetClassName(pMeshBuilder, &size, cname);
255     ok(hr == E_INVALIDARG, "GetClassName failed with %x\n", hr);
256     size = sizeof(cname);
257     hr = IDirect3DRMMeshBuilder_GetClassName(pMeshBuilder, &size, cname);
258     ok(hr == D3DRM_OK, "Cannot get classname (hr = %x)\n", hr);
259     ok(size == sizeof("Builder"), "wrong size: %u\n", size);
260     ok(!strcmp(cname, "Builder"), "Expected cname to be \"Builder\", but got \"%s\"\n", cname);
261
262     info.lpMemory = data_bad_version;
263     info.dSize = strlen(data_bad_version);
264     hr = IDirect3DRMMeshBuilder_Load(pMeshBuilder, &info, NULL, D3DRMLOAD_FROMMEMORY, NULL, NULL);
265     ok(hr == D3DRMERR_BADFILE, "Should have returned D3DRMERR_BADFILE (hr = %x)\n", hr);
266
267     info.lpMemory = data_no_mesh;
268     info.dSize = strlen(data_no_mesh);
269     hr = IDirect3DRMMeshBuilder_Load(pMeshBuilder, &info, NULL, D3DRMLOAD_FROMMEMORY, NULL, NULL);
270     ok(hr == D3DRMERR_NOTFOUND, "Should have returned D3DRMERR_NOTFOUND (hr = %x)\n", hr);
271
272     info.lpMemory = data_ok;
273     info.dSize = strlen(data_ok);
274     hr = IDirect3DRMMeshBuilder_Load(pMeshBuilder, &info, NULL, D3DRMLOAD_FROMMEMORY, NULL, NULL);
275     ok(hr == D3DRM_OK, "Cannot load mesh data (hr = %x)\n", hr);
276
277     size = sizeof(name);
278     hr = IDirect3DRMMeshBuilder_GetName(pMeshBuilder, &size, name);
279     ok(hr == D3DRM_OK, "IDirect3DRMMeshBuilder_GetName returned hr = %x\n", hr);
280     ok(!strcmp(name, "Object"), "Retrieved name '%s' instead of 'Object'\n", name);
281     size = strlen("Object"); /* No space for null character */
282     hr = IDirect3DRMMeshBuilder_GetName(pMeshBuilder, &size, name);
283     ok(hr == E_INVALIDARG, "IDirect3DRMMeshBuilder_GetName returned hr = %x\n", hr);
284     hr = IDirect3DRMMeshBuilder_SetName(pMeshBuilder, NULL);
285     ok(hr == D3DRM_OK, "IDirect3DRMMeshBuilder_SetName returned hr = %x\n", hr);
286     size = sizeof(name);
287     hr = IDirect3DRMMeshBuilder_GetName(pMeshBuilder, &size, name);
288     ok(hr == D3DRM_OK, "IDirect3DRMMeshBuilder_GetName returned hr = %x\n", hr);
289     ok(size == 0, "Size should be 0 instead of %u\n", size);
290     hr = IDirect3DRMMeshBuilder_SetName(pMeshBuilder, "");
291     ok(hr == D3DRM_OK, "IDirect3DRMMeshBuilder_SetName returned hr = %x\n", hr);
292     size = sizeof(name);
293     hr = IDirect3DRMMeshBuilder_GetName(pMeshBuilder, &size, name);
294     ok(hr == D3DRM_OK, "IDirect3DRMMeshBuilder_GetName returned hr = %x\n", hr);
295     ok(!strcmp(name, ""), "Retrieved name '%s' instead of ''\n", name);
296
297     val = IDirect3DRMMeshBuilder_GetVertexCount(pMeshBuilder);
298     ok(val == 4, "Wrong number of vertices %d (must be 4)\n", val);
299
300     val = IDirect3DRMMeshBuilder_GetFaceCount(pMeshBuilder);
301     ok(val == 3, "Wrong number of faces %d (must be 3)\n", val);
302
303     hr = IDirect3DRMMeshBuilder_GetVertices(pMeshBuilder, &val1, NULL, &val2, NULL, &val3, NULL);
304     ok(hr == D3DRM_OK, "Cannot get vertices information (hr = %x)\n", hr);
305     ok(val1 == 4, "Wrong number of vertices %d (must be 4)\n", val1);
306     ok(val2 == 4, "Wrong number of normals %d (must be 4)\n", val2);
307     ok(val3 == 22, "Wrong number of face data bytes %d (must be 22)\n", val3);
308
309     /* Check that Load method generated default normals */
310     hr = IDirect3DRMMeshBuilder_GetVertices(pMeshBuilder, NULL, NULL, &val2, n, NULL, NULL);
311     ok(hr == D3DRM_OK, "Cannot get vertices information (hr = %x)\n", hr);
312     ok(match_float(U1(n[0]).x, 0.577350f),  "Wrong component n[0].x = %f (expected %f)\n", U1(n[0]).x, 0.577350f);
313     ok(match_float(U2(n[0]).y, 0.577350f),  "Wrong component n[0].y = %f (expected %f)\n", U2(n[0]).y, 0.577350f);
314     ok(match_float(U3(n[0]).z, 0.577350f),  "Wrong component n[0].z = %f (expected %f)\n", U3(n[0]).z, 0.577350f);
315     ok(match_float(U1(n[1]).x, -0.229416f), "Wrong component n[1].x = %f (expected %f)\n", U1(n[1]).x, -0.229416f);
316     ok(match_float(U2(n[1]).y, 0.688247f),  "Wrong component n[1].y = %f (expected %f)\n", U2(n[1]).y, 0.688247f);
317     ok(match_float(U3(n[1]).z, 0.688247f),  "Wrong component n[1].z = %f (expected %f)\n", U3(n[1]).z, 0.688247f);
318     ok(match_float(U1(n[2]).x, -0.229416f), "Wrong component n[2].x = %f (expected %f)\n", U1(n[2]).x, -0.229416f);
319     ok(match_float(U2(n[2]).y, 0.688247f),  "Wrong component n[2].y = %f (expected %f)\n", U2(n[2]).y, 0.688247f);
320     ok(match_float(U3(n[2]).z, 0.688247f),  "Wrong component n[2].z = %f (expected %f)\n", U3(n[2]).z, 0.688247f);
321     ok(match_float(U1(n[3]).x, -0.577350f), "Wrong component n[3].x = %f (expected %f)\n", U1(n[3]).x, -0.577350f);
322     ok(match_float(U2(n[3]).y, 0.577350f),  "Wrong component n[3].y = %f (expected %f)\n", U2(n[3]).y, 0.577350f);
323     ok(match_float(U3(n[3]).z, 0.577350f),  "Wrong component n[3].z = %f (expected %f)\n", U3(n[3]).z, 0.577350f);
324
325     /* Check that Load method generated default texture coordinates (0.0f, 0.0f) for each vertex */
326     valu = 1.23f;
327     valv = 3.21f;
328     hr = IDirect3DRMMeshBuilder_GetTextureCoordinates(pMeshBuilder, 0, &valu, &valv);
329     ok(hr == D3DRM_OK, "Cannot get texture coordinates (hr = %x)\n", hr);
330     ok(valu == 0.0f, "Wrong coordinate %f (must be 0.0)\n", valu);
331     ok(valv == 0.0f, "Wrong coordinate %f (must be 0.0)\n", valv);
332     valu = 1.23f;
333     valv = 3.21f;
334     hr = IDirect3DRMMeshBuilder_GetTextureCoordinates(pMeshBuilder, 1, &valu, &valv);
335     ok(hr == D3DRM_OK, "Cannot get texture coordinates (hr = %x)\n", hr);
336     ok(valu == 0.0f, "Wrong coordinate %f (must be 0.0)\n", valu);
337     ok(valv == 0.0f, "Wrong coordinate %f (must be 0.0)\n", valv);
338     valu = 1.23f;
339     valv = 3.21f;
340     hr = IDirect3DRMMeshBuilder_GetTextureCoordinates(pMeshBuilder, 2, &valu, &valv);
341     ok(hr == D3DRM_OK, "Cannot get texture coordinates (hr = %x)\n", hr);
342     ok(valu == 0.0f, "Wrong coordinate %f (must be 0.0)\n", valu);
343     ok(valv == 0.0f, "Wrong coordinate %f (must be 0.0)\n", valv);
344     valu = 1.23f;
345     valv = 3.21f;
346     hr = IDirect3DRMMeshBuilder_GetTextureCoordinates(pMeshBuilder, 3, &valu, &valv);
347     ok(hr == D3DRM_OK, "Cannot get texture coordinates (hr = %x)\n", hr);
348     ok(valu == 0.0f, "Wrong coordinate %f (must be 0.0)\n", valu);
349     ok(valv == 0.0f, "Wrong coordinate %f (must be 0.0)\n", valv);
350     hr = IDirect3DRMMeshBuilder_GetTextureCoordinates(pMeshBuilder, 4, &valu, &valv);
351     ok(hr == D3DRMERR_BADVALUE, "Should fail and return D3DRM_BADVALUE (hr = %x)\n", hr);
352
353     valu = 1.23f;
354     valv = 3.21f;
355     hr = IDirect3DRMMeshBuilder_SetTextureCoordinates(pMeshBuilder, 0, valu, valv);
356     ok(hr == D3DRM_OK, "Cannot set texture coordinates (hr = %x)\n", hr);
357     hr = IDirect3DRMMeshBuilder_SetTextureCoordinates(pMeshBuilder, 4, valu, valv);
358     ok(hr == D3DRMERR_BADVALUE, "Should fail and return D3DRM_BADVALUE (hr = %x)\n", hr);
359
360     valu = 0.0f;
361     valv = 0.0f;
362     hr = IDirect3DRMMeshBuilder_GetTextureCoordinates(pMeshBuilder, 0, &valu, &valv);
363     ok(hr == D3DRM_OK, "Cannot get texture coordinates (hr = %x)\n", hr);
364     ok(valu == 1.23f, "Wrong coordinate %f (must be 1.23)\n", valu);
365     ok(valv == 3.21f, "Wrong coordinate %f (must be 3.21)\n", valv);
366
367     IDirect3DRMMeshBuilder_Release(pMeshBuilder);
368
369     hr = IDirect3DRM_CreateMeshBuilder(pD3DRM, &pMeshBuilder);
370     ok(hr == D3DRM_OK, "Cannot get IDirect3DRMMeshBuilder interface (hr = %x)\n", hr);
371
372     /* No group in mesh when mesh builder is not loaded */
373     hr = IDirect3DRMMeshBuilder_CreateMesh(pMeshBuilder, &mesh);
374     ok(hr == D3DRM_OK, "CreateMesh failed returning hr = %x\n", hr);
375     if (hr == D3DRM_OK)
376     {
377         DWORD nb_groups;
378
379         nb_groups = IDirect3DRMMesh_GetGroupCount(mesh);
380         ok(nb_groups == 0, "GetCroupCount returned %u\n", nb_groups);
381
382         IDirect3DRMMesh_Release(mesh);
383     }
384
385     info.lpMemory = data_full;
386     info.dSize = strlen(data_full);
387     hr = IDirect3DRMMeshBuilder_Load(pMeshBuilder, &info, NULL, D3DRMLOAD_FROMMEMORY, NULL, NULL);
388     ok(hr == D3DRM_OK, "Cannot load mesh data (hr = %x)\n", hr);
389
390     val = IDirect3DRMMeshBuilder_GetVertexCount(pMeshBuilder);
391     ok(val == 3, "Wrong number of vertices %d (must be 3)\n", val);
392
393     val = IDirect3DRMMeshBuilder_GetFaceCount(pMeshBuilder);
394     ok(val == 1, "Wrong number of faces %d (must be 1)\n", val);
395
396     /* Check no buffer size and too small buffer size errors */
397     val1 = 1; val2 = 3; val3 = 8;
398     hr = IDirect3DRMMeshBuilder_GetVertices(pMeshBuilder, &val1, v, &val2, n, &val3, f);
399     ok(hr == D3DRMERR_BADVALUE, "IDirect3DRMMeshBuilder_GetVertices returned %#x\n", hr);
400     hr = IDirect3DRMMeshBuilder_GetVertices(pMeshBuilder, NULL, v, &val2, n, &val3, f);
401     ok(hr == D3DRMERR_BADVALUE, "IDirect3DRMMeshBuilder_GetVertices returned %#x\n", hr);
402     val1 = 3; val2 = 1; val3 = 8;
403     hr = IDirect3DRMMeshBuilder_GetVertices(pMeshBuilder, &val1, v, &val2, n, &val3, f);
404     ok(hr == D3DRMERR_BADVALUE, "IDirect3DRMMeshBuilder_GetVertices returned %#x\n", hr);
405     hr = IDirect3DRMMeshBuilder_GetVertices(pMeshBuilder, &val1, v, NULL, n, &val3, f);
406     ok(hr == D3DRMERR_BADVALUE, "IDirect3DRMMeshBuilder_GetVertices returned %#x\n", hr);
407     val1 = 3; val2 = 3; val3 = 1;
408     hr = IDirect3DRMMeshBuilder_GetVertices(pMeshBuilder, &val1, v, &val2, n, &val3, f);
409     ok(hr == D3DRMERR_BADVALUE, "IDirect3DRMMeshBuilder_GetVertices returned %#x\n", hr);
410     hr = IDirect3DRMMeshBuilder_GetVertices(pMeshBuilder, &val1, v, &val2, n, NULL, f);
411     ok(hr == D3DRMERR_BADVALUE, "IDirect3DRMMeshBuilder_GetVertices returned %#x\n", hr);
412
413     val1 = 3; val2 = 3; val3 = 8;
414     hr = IDirect3DRMMeshBuilder_GetVertices(pMeshBuilder, &val1, v, &val2, n, &val3, f);
415     ok(hr == D3DRM_OK, "Cannot get vertices information (hr = %x)\n", hr);
416     ok(val1 == 3, "Wrong number of vertices %d (must be 3)\n", val1);
417     ok(val2 == 3, "Wrong number of normals %d (must be 3)\n", val2);
418     ok(val3 == 8, "Wrong number of face data bytes %d (must be 8)\n", val3);
419     ok(U1(v[0]).x == 0.1f, "Wrong component v[0].x = %f (expected 0.1)\n", U1(v[0]).x);
420     ok(U2(v[0]).y == 0.2f, "Wrong component v[0].y = %f (expected 0.2)\n", U2(v[0]).y);
421     ok(U3(v[0]).z == 0.3f, "Wrong component v[0].z = %f (expected 0.3)\n", U3(v[0]).z);
422     ok(U1(v[1]).x == 0.4f, "Wrong component v[1].x = %f (expected 0.4)\n", U1(v[1]).x);
423     ok(U2(v[1]).y == 0.5f, "Wrong component v[1].y = %f (expected 0.5)\n", U2(v[1]).y);
424     ok(U3(v[1]).z == 0.6f, "Wrong component v[1].z = %f (expected 0.6)\n", U3(v[1]).z);
425     ok(U1(v[2]).x == 0.7f, "Wrong component v[2].x = %f (expected 0.7)\n", U1(v[2]).x);
426     ok(U2(v[2]).y == 0.8f, "Wrong component v[2].y = %f (expected 0.8)\n", U2(v[2]).y);
427     ok(U3(v[2]).z == 0.9f, "Wrong component v[2].z = %f (expected 0.9)\n", U3(v[2]).z);
428     ok(U1(n[0]).x == 1.1f, "Wrong component n[0].x = %f (expected 1.1)\n", U1(n[0]).x);
429     ok(U2(n[0]).y == 1.2f, "Wrong component n[0].y = %f (expected 1.2)\n", U2(n[0]).y);
430     ok(U3(n[0]).z == 1.3f, "Wrong component n[0].z = %f (expected 1.3)\n", U3(n[0]).z);
431     ok(U1(n[1]).x == 1.4f, "Wrong component n[1].x = %f (expected 1.4)\n", U1(n[1]).x);
432     ok(U2(n[1]).y == 1.5f, "Wrong component n[1].y = %f (expected 1.5)\n", U2(n[1]).y);
433     ok(U3(n[1]).z == 1.6f, "Wrong component n[1].z = %f (expected 1.6)\n", U3(n[1]).z);
434     ok(U1(n[2]).x == 1.7f, "Wrong component n[2].x = %f (expected 1.7)\n", U1(n[2]).x);
435     ok(U2(n[2]).y == 1.8f, "Wrong component n[2].y = %f (expected 1.8)\n", U2(n[2]).y);
436     ok(U3(n[2]).z == 1.9f, "Wrong component n[2].z = %f (expected 1.9)\n", U3(n[2]).z);
437     ok(f[0] == 3 , "Wrong component f[0] = %d (expected 3)\n", f[0]);
438     ok(f[1] == 0 , "Wrong component f[1] = %d (expected 0)\n", f[1]);
439     ok(f[2] == 0 , "Wrong component f[2] = %d (expected 0)\n", f[2]);
440     ok(f[3] == 1 , "Wrong component f[3] = %d (expected 1)\n", f[3]);
441     ok(f[4] == 1 , "Wrong component f[4] = %d (expected 1)\n", f[4]);
442     ok(f[5] == 2 , "Wrong component f[5] = %d (expected 2)\n", f[5]);
443     ok(f[6] == 2 , "Wrong component f[6] = %d (expected 2)\n", f[6]);
444     ok(f[7] == 0 , "Wrong component f[7] = %d (expected 0)\n", f[7]);
445
446     hr = IDirect3DRMMeshBuilder_CreateMesh(pMeshBuilder, &mesh);
447     ok(hr == D3DRM_OK, "CreateMesh failed returning hr = %x\n", hr);
448     if (hr == D3DRM_OK)
449     {
450         DWORD nb_groups;
451         unsigned nb_vertices, nb_faces, nb_face_vertices;
452         DWORD data_size;
453         LPDIRECT3DRMMATERIAL material = (LPDIRECT3DRMMATERIAL)0xdeadbeef;
454         LPDIRECT3DRMTEXTURE texture = (LPDIRECT3DRMTEXTURE)0xdeadbeef;
455         D3DVALUE values[3];
456
457         nb_groups = IDirect3DRMMesh_GetGroupCount(mesh);
458         ok(nb_groups == 1, "GetCroupCount returned %u\n", nb_groups);
459         hr = IDirect3DRMMesh_GetGroup(mesh, 1, &nb_vertices, &nb_faces, &nb_face_vertices, &data_size, NULL);
460         ok(hr == D3DRMERR_BADVALUE, "GetCroup returned hr = %x\n", hr);
461         hr = IDirect3DRMMesh_GetGroup(mesh, 0, &nb_vertices, &nb_faces, &nb_face_vertices, &data_size, NULL);
462         ok(hr == D3DRM_OK, "GetCroup failed returning hr = %x\n", hr);
463         ok(nb_vertices == 3, "Wrong number of vertices %u (must be 3)\n", nb_vertices);
464         ok(nb_faces == 1, "Wrong number of faces %u (must be 1)\n", nb_faces);
465         ok(nb_face_vertices == 3, "Wrong number of vertices per face %u (must be 3)\n", nb_face_vertices);
466         ok(data_size == 3, "Wrong number of face data bytes %u (must be 3)\n", data_size);
467         color = IDirect3DRMMesh_GetGroupColor(mesh, 0);
468         ok(color == 0xff00ff00, "Wrong color returned %#x instead of %#x\n", color, 0xff00ff00);
469         hr = IDirect3DRMMesh_GetGroupTexture(mesh, 0, &texture);
470         ok(hr == D3DRM_OK, "GetCroupTexture failed returning hr = %x\n", hr);
471         ok(texture == NULL, "No texture should be present\n");
472         hr = IDirect3DRMMesh_GetGroupMaterial(mesh, 0, &material);
473         ok(hr == D3DRM_OK, "GetCroupMaterial failed returning hr = %x\n", hr);
474         ok(material != NULL, "No material present\n");
475         if ((hr == D3DRM_OK) && material)
476         {
477             hr = IDirect3DRMMaterial_GetEmissive(material, &values[0], &values[1], &values[2]);
478             ok(hr == D3DRM_OK, "GetMaterialEmissive failed returning hr = %x\n", hr);
479             ok(values[0] == 0.5f, "Emissive red component should be %f instead of %f\n", 0.5f, values[0]);
480             ok(values[1] == 0.5f, "Emissive green component should be %f instead of %f\n", 0.5f, values[1]);
481             ok(values[2] == 0.5f, "Emissive blue component should be %f instead of %f\n", 0.5f, values[2]);
482             hr = IDirect3DRMMaterial_GetSpecular(material, &values[0], &values[1], &values[2]);
483             ok(hr == D3DRM_OK, "GetMaterialEmissive failed returning hr = %x\n", hr);
484             ok(values[0] == 1.0f, "Specular red component should be %f instead of %f\n", 1.0f, values[0]);
485             ok(values[1] == 0.0f, "Specular green component should be %f instead of %f\n", 0.0f, values[1]);
486             ok(values[2] == 0.0f, "Specular blue component should be %f instead of %f\n", 0.0f, values[2]);
487             values[0] = IDirect3DRMMaterial_GetPower(material);
488             ok(values[0] == 30.0f, "Power value should be %f instead of %f\n", 30.0f, values[0]);
489         }
490
491         IDirect3DRMMesh_Release(mesh);
492     }
493
494     hr = IDirect3DRMMeshBuilder_Scale(pMeshBuilder, 2, 3 ,4);
495     ok(hr == D3DRM_OK, "Scale failed returning hr = %x\n", hr);
496
497     hr = IDirect3DRMMeshBuilder_GetVertices(pMeshBuilder, &val1, v, &val2, n, &val3, f);
498     ok(hr == D3DRM_OK, "Cannot get vertices information (hr = %x)\n", hr);
499     ok(val2 == 3, "Wrong number of normals %d (must be 3)\n", val2);
500     ok(val1 == 3, "Wrong number of vertices %d (must be 3)\n", val1);
501     ok(U1(v[0]).x == 0.1f*2, "Wrong component v[0].x = %f (expected %f)\n", U1(v[0]).x, 0.1f*2);
502     ok(U2(v[0]).y == 0.2f*3, "Wrong component v[0].y = %f (expected %f)\n", U2(v[0]).y, 0.2f*3);
503     ok(U3(v[0]).z == 0.3f*4, "Wrong component v[0].z = %f (expected %f)\n", U3(v[0]).z, 0.3f*4);
504     ok(U1(v[1]).x == 0.4f*2, "Wrong component v[1].x = %f (expected %f)\n", U1(v[1]).x, 0.4f*2);
505     ok(U2(v[1]).y == 0.5f*3, "Wrong component v[1].y = %f (expected %f)\n", U2(v[1]).y, 0.5f*3);
506     ok(U3(v[1]).z == 0.6f*4, "Wrong component v[1].z = %f (expected %f)\n", U3(v[1]).z, 0.6f*4);
507     ok(U1(v[2]).x == 0.7f*2, "Wrong component v[2].x = %f (expected %f)\n", U1(v[2]).x, 0.7f*2);
508     ok(U2(v[2]).y == 0.8f*3, "Wrong component v[2].y = %f (expected %f)\n", U2(v[2]).y, 0.8f*3);
509     ok(U3(v[2]).z == 0.9f*4, "Wrong component v[2].z = %f (expected %f)\n", U3(v[2]).z, 0.9f*4);
510     /* Normals are not affected by Scale */
511     ok(U1(n[0]).x == 1.1f, "Wrong component n[0].x = %f (expected %f)\n", U1(n[0]).x, 1.1f);
512     ok(U2(n[0]).y == 1.2f, "Wrong component n[0].y = %f (expected %f)\n", U2(n[0]).y, 1.2f);
513     ok(U3(n[0]).z == 1.3f, "Wrong component n[0].z = %f (expected %f)\n", U3(n[0]).z, 1.3f);
514     ok(U1(n[1]).x == 1.4f, "Wrong component n[1].x = %f (expected %f)\n", U1(n[1]).x, 1.4f);
515     ok(U2(n[1]).y == 1.5f, "Wrong component n[1].y = %f (expected %f)\n", U2(n[1]).y, 1.5f);
516     ok(U3(n[1]).z == 1.6f, "Wrong component n[1].z = %f (expected %f)\n", U3(n[1]).z, 1.6f);
517     ok(U1(n[2]).x == 1.7f, "Wrong component n[2].x = %f (expected %f)\n", U1(n[2]).x, 1.7f);
518     ok(U2(n[2]).y == 1.8f, "Wrong component n[2].y = %f (expected %f)\n", U2(n[2]).y, 1.8f);
519     ok(U3(n[2]).z == 1.9f, "Wrong component n[2].z = %f (expected %f)\n", U3(n[2]).z, 1.9f);
520
521     IDirect3DRMMeshBuilder_Release(pMeshBuilder);
522
523     IDirect3DRM_Release(pD3DRM);
524 }
525
526 static void test_MeshBuilder3(void)
527 {
528     HRESULT hr;
529     LPDIRECT3DRM pD3DRM;
530     LPDIRECT3DRM3 pD3DRM3;
531     LPDIRECT3DRMMESHBUILDER3 pMeshBuilder3;
532     D3DRMLOADMEMORY info;
533     int val;
534     DWORD val1;
535     D3DVALUE valu, valv;
536     DWORD size;
537     CHAR cname[64] = {0};
538
539     hr = pDirect3DRMCreate(&pD3DRM);
540     ok(hr == D3DRM_OK, "Cannot get IDirect3DRM interface (hr = %x)\n", hr);
541
542     hr = IDirect3DRM_QueryInterface(pD3DRM, &IID_IDirect3DRM3, (LPVOID*)&pD3DRM3);
543     if (FAILED(hr))
544     {
545         win_skip("Cannot get IDirect3DRM3 interface (hr = %x), skipping tests\n", hr);
546         IDirect3DRM_Release(pD3DRM);
547         return;
548     }
549
550     hr = IDirect3DRM3_CreateMeshBuilder(pD3DRM3, &pMeshBuilder3);
551     ok(hr == D3DRM_OK, "Cannot get IDirect3DRMMeshBuilder3 interface (hr = %x)\n", hr);
552
553     hr = IDirect3DRMMeshBuilder3_GetClassName(pMeshBuilder3, NULL, cname);
554     ok(hr == E_INVALIDARG, "GetClassName failed with %x\n", hr);
555     hr = IDirect3DRMMeshBuilder3_GetClassName(pMeshBuilder3, NULL, NULL);
556     ok(hr == E_INVALIDARG, "GetClassName failed with %x\n", hr);
557     size = 1;
558     hr = IDirect3DRMMeshBuilder3_GetClassName(pMeshBuilder3, &size, cname);
559     ok(hr == E_INVALIDARG, "GetClassName failed with %x\n", hr);
560     size = sizeof(cname);
561     hr = IDirect3DRMMeshBuilder3_GetClassName(pMeshBuilder3, &size, cname);
562     ok(hr == D3DRM_OK, "Cannot get classname (hr = %x)\n", hr);
563     ok(size == sizeof("Builder"), "wrong size: %u\n", size);
564     ok(!strcmp(cname, "Builder"), "Expected cname to be \"Builder\", but got \"%s\"\n", cname);
565
566     info.lpMemory = data_bad_version;
567     info.dSize = strlen(data_bad_version);
568     hr = IDirect3DRMMeshBuilder3_Load(pMeshBuilder3, &info, NULL, D3DRMLOAD_FROMMEMORY, NULL, NULL);
569     ok(hr == D3DRMERR_BADFILE, "Should have returned D3DRMERR_BADFILE (hr = %x)\n", hr);
570
571     info.lpMemory = data_no_mesh;
572     info.dSize = strlen(data_no_mesh);
573     hr = IDirect3DRMMeshBuilder3_Load(pMeshBuilder3, &info, NULL, D3DRMLOAD_FROMMEMORY, NULL, NULL);
574     ok(hr == D3DRMERR_NOTFOUND, "Should have returned D3DRMERR_NOTFOUND (hr = %x)\n", hr);
575
576     info.lpMemory = data_ok;
577     info.dSize = strlen(data_ok);
578     hr = IDirect3DRMMeshBuilder3_Load(pMeshBuilder3, &info, NULL, D3DRMLOAD_FROMMEMORY, NULL, NULL);
579     ok(hr == D3DRM_OK, "Cannot load mesh data (hr = %x)\n", hr);
580
581     val = IDirect3DRMMeshBuilder3_GetVertexCount(pMeshBuilder3);
582     ok(val == 4, "Wrong number of vertices %d (must be 4)\n", val);
583
584     val = IDirect3DRMMeshBuilder3_GetFaceCount(pMeshBuilder3);
585     ok(val == 3, "Wrong number of faces %d (must be 3)\n", val);
586
587     hr = IDirect3DRMMeshBuilder3_GetVertices(pMeshBuilder3, 0, &val1, NULL);
588     ok(hr == D3DRM_OK, "Cannot get vertices information (hr = %x)\n", hr);
589     ok(val1 == 4, "Wrong number of vertices %d (must be 4)\n", val1);
590
591     /* Check that Load method generated default texture coordinates (0.0f, 0.0f) for each vertex */
592     valu = 1.23f;
593     valv = 3.21f;
594     hr = IDirect3DRMMeshBuilder3_GetTextureCoordinates(pMeshBuilder3, 0, &valu, &valv);
595     ok(hr == D3DRM_OK, "Cannot get texture coordinates (hr = %x)\n", hr);
596     ok(valu == 0.0f, "Wrong coordinate %f (must be 0.0)\n", valu);
597     ok(valv == 0.0f, "Wrong coordinate %f (must be 0.0)\n", valv);
598     valu = 1.23f;
599     valv = 3.21f;
600     hr = IDirect3DRMMeshBuilder3_GetTextureCoordinates(pMeshBuilder3, 1, &valu, &valv);
601     ok(hr == D3DRM_OK, "Cannot get texture coordinates (hr = %x)\n", hr);
602     ok(valu == 0.0f, "Wrong coordinate %f (must be 0.0)\n", valu);
603     ok(valv == 0.0f, "Wrong coordinate %f (must be 0.0)\n", valv);
604     valu = 1.23f;
605     valv = 3.21f;
606     hr = IDirect3DRMMeshBuilder3_GetTextureCoordinates(pMeshBuilder3, 2, &valu, &valv);
607     ok(hr == D3DRM_OK, "Cannot get texture coordinates (hr = %x)\n", hr);
608     ok(valu == 0.0f, "Wrong coordinate %f (must be 0.0)\n", valu);
609     ok(valv == 0.0f, "Wrong coordinate %f (must be 0.0)\n", valv);
610     valu = 1.23f;
611     valv = 3.21f;
612     hr = IDirect3DRMMeshBuilder3_GetTextureCoordinates(pMeshBuilder3, 3, &valu, &valv);
613     ok(hr == D3DRM_OK, "Cannot get texture coordinates (hr = %x)\n", hr);
614     ok(valu == 0.0f, "Wrong coordinate %f (must be 0.0)\n", valu);
615     ok(valv == 0.0f, "Wrong coordinate %f (must be 0.0)\n", valv);
616     hr = IDirect3DRMMeshBuilder3_GetTextureCoordinates(pMeshBuilder3, 4, &valu, &valv);
617     ok(hr == D3DRMERR_BADVALUE, "Should fail and return D3DRM_BADVALUE (hr = %x)\n", hr);
618
619     valu = 1.23f;
620     valv = 3.21f;
621     hr = IDirect3DRMMeshBuilder3_SetTextureCoordinates(pMeshBuilder3, 0, valu, valv);
622     ok(hr == D3DRM_OK, "Cannot set texture coordinates (hr = %x)\n", hr);
623     hr = IDirect3DRMMeshBuilder3_SetTextureCoordinates(pMeshBuilder3, 4, valu, valv);
624     ok(hr == D3DRMERR_BADVALUE, "Should fail and return D3DRM_BADVALUE (hr = %x)\n", hr);
625
626     valu = 0.0f;
627     valv = 0.0f;
628     hr = IDirect3DRMMeshBuilder3_GetTextureCoordinates(pMeshBuilder3, 0, &valu, &valv);
629     ok(hr == D3DRM_OK, "Cannot get texture coordinates (hr = %x)\n", hr);
630     ok(valu == 1.23f, "Wrong coordinate %f (must be 1.23)\n", valu);
631     ok(valv == 3.21f, "Wrong coordinate %f (must be 3.21)\n", valv);
632
633     IDirect3DRMMeshBuilder3_Release(pMeshBuilder3);
634     IDirect3DRM3_Release(pD3DRM3);
635     IDirect3DRM_Release(pD3DRM);
636 }
637
638 static void test_Mesh(void)
639 {
640     HRESULT hr;
641     LPDIRECT3DRM pD3DRM;
642     LPDIRECT3DRMMESH pMesh;
643     DWORD size;
644     CHAR cname[64] = {0};
645
646     hr = pDirect3DRMCreate(&pD3DRM);
647     ok(hr == D3DRM_OK, "Cannot get IDirect3DRM interface (hr = %x)\n", hr);
648
649     hr = IDirect3DRM_CreateMesh(pD3DRM, &pMesh);
650     ok(hr == D3DRM_OK, "Cannot get IDirect3DRMMesh interface (hr = %x)\n", hr);
651
652     hr = IDirect3DRMMesh_GetClassName(pMesh, NULL, cname);
653     ok(hr == E_INVALIDARG, "GetClassName failed with %x\n", hr);
654     hr = IDirect3DRMMesh_GetClassName(pMesh, NULL, NULL);
655     ok(hr == E_INVALIDARG, "GetClassName failed with %x\n", hr);
656     size = 1;
657     hr = IDirect3DRMMesh_GetClassName(pMesh, &size, cname);
658     ok(hr == E_INVALIDARG, "GetClassName failed with %x\n", hr);
659     size = sizeof(cname);
660     hr = IDirect3DRMMesh_GetClassName(pMesh, &size, cname);
661     ok(hr == D3DRM_OK, "Cannot get classname (hr = %x)\n", hr);
662     ok(size == sizeof("Mesh"), "wrong size: %u\n", size);
663     ok(!strcmp(cname, "Mesh"), "Expected cname to be \"Mesh\", but got \"%s\"\n", cname);
664
665     IDirect3DRMMesh_Release(pMesh);
666
667     IDirect3DRM_Release(pD3DRM);
668 }
669
670 static void test_Frame(void)
671 {
672     HRESULT hr;
673     LPDIRECT3DRM pD3DRM;
674     LPDIRECT3DRMFRAME pFrameC;
675     LPDIRECT3DRMFRAME pFrameP1;
676     LPDIRECT3DRMFRAME pFrameP2;
677     LPDIRECT3DRMFRAME pFrameTmp;
678     LPDIRECT3DRMFRAMEARRAY pArray;
679     LPDIRECT3DRMMESHBUILDER pMeshBuilder;
680     LPDIRECT3DRMVISUAL pVisual1;
681     LPDIRECT3DRMVISUAL pVisualTmp;
682     LPDIRECT3DRMVISUALARRAY pVisualArray;
683     LPDIRECT3DRMLIGHT pLight1;
684     LPDIRECT3DRMLIGHT pLightTmp;
685     LPDIRECT3DRMLIGHTARRAY pLightArray;
686     D3DCOLOR color;
687     DWORD count;
688     CHAR cname[64] = {0};
689
690     hr = pDirect3DRMCreate(&pD3DRM);
691     ok(hr == D3DRM_OK, "Cannot get IDirect3DRM interface (hr = %x)\n", hr);
692
693     hr = IDirect3DRM_CreateFrame(pD3DRM, NULL, &pFrameC);
694     ok(hr == D3DRM_OK, "Cannot get IDirect3DRMFrame interface (hr = %x)\n", hr);
695     CHECK_REFCOUNT(pFrameC, 1);
696
697     hr = IDirect3DRMFrame_GetClassName(pFrameC, NULL, cname);
698     ok(hr == E_INVALIDARG, "GetClassName failed with %x\n", hr);
699     hr = IDirect3DRMFrame_GetClassName(pFrameC, NULL, NULL);
700     ok(hr == E_INVALIDARG, "GetClassName failed with %x\n", hr);
701     count = 1;
702     hr = IDirect3DRMFrame_GetClassName(pFrameC, &count, cname);
703     ok(hr == E_INVALIDARG, "GetClassName failed with %x\n", hr);
704     count = sizeof(cname);
705     hr = IDirect3DRMFrame_GetClassName(pFrameC, &count, cname);
706     ok(hr == D3DRM_OK, "Cannot get classname (hr = %x)\n", hr);
707     ok(count == sizeof("Frame"), "wrong size: %u\n", count);
708     ok(!strcmp(cname, "Frame"), "Expected cname to be \"Frame\", but got \"%s\"\n", cname);
709
710     hr = IDirect3DRMFrame_GetParent(pFrameC, NULL);
711     ok(hr == D3DRMERR_BADVALUE, "Should fail and return D3DRM_BADVALUE (hr = %x)\n", hr);
712     pFrameTmp = (void*)0xdeadbeef;
713     hr = IDirect3DRMFrame_GetParent(pFrameC, &pFrameTmp);
714     ok(hr == D3DRM_OK, "Cannot get parent frame (hr = %x)\n", hr);
715     ok(pFrameTmp == NULL, "pFrameTmp = %p\n", pFrameTmp);
716     CHECK_REFCOUNT(pFrameC, 1);
717
718     pArray = NULL;
719     hr = IDirect3DRMFrame_GetChildren(pFrameC, &pArray);
720     ok(hr == D3DRM_OK, "Cannot get children (hr = %x)\n", hr);
721     ok(pArray != NULL, "pArray = %p\n", pArray);
722     if (pArray)
723     {
724         count = IDirect3DRMFrameArray_GetSize(pArray);
725         ok(count == 0, "count = %u\n", count);
726         hr = IDirect3DRMFrameArray_GetElement(pArray, 0, &pFrameTmp);
727         ok(hr == D3DRMERR_BADVALUE, "Should have returned D3DRMERR_BADVALUE (hr = %x)\n", hr);
728         ok(pFrameTmp == NULL, "pFrameTmp = %p\n", pFrameTmp);
729         IDirect3DRMFrameArray_Release(pArray);
730     }
731
732     hr = IDirect3DRM_CreateFrame(pD3DRM, NULL, &pFrameP1);
733     ok(hr == D3DRM_OK, "Cannot get IDirect3DRMFrame interface (hr = %x)\n", hr);
734
735     /* GetParent with NULL pointer */
736     hr = IDirect3DRMFrame_GetParent(pFrameP1, NULL);
737     ok(hr == D3DRMERR_BADVALUE, "Should have returned D3DRMERR_BADVALUE (hr = %x)\n", hr);
738     CHECK_REFCOUNT(pFrameP1, 1);
739
740     /* [Add/Delete]Child with NULL pointer */
741     hr = IDirect3DRMFrame_AddChild(pFrameP1, NULL);
742     ok(hr == D3DRMERR_BADOBJECT, "Should have returned D3DRMERR_BADOBJECT (hr = %x)\n", hr);
743     CHECK_REFCOUNT(pFrameP1, 1);
744
745     hr = IDirect3DRMFrame_DeleteChild(pFrameP1, NULL);
746     ok(hr == D3DRMERR_BADOBJECT, "Should have returned D3DRMERR_BADOBJECT (hr = %x)\n", hr);
747     CHECK_REFCOUNT(pFrameP1, 1);
748
749     /* Add child to first parent */
750     pFrameTmp = (void*)0xdeadbeef;
751     hr = IDirect3DRMFrame_GetParent(pFrameP1, &pFrameTmp);
752     ok(hr == D3DRM_OK, "Cannot get parent frame (hr = %x)\n", hr);
753     ok(pFrameTmp == NULL, "pFrameTmp = %p\n", pFrameTmp);
754
755     hr = IDirect3DRMFrame_AddChild(pFrameP1, pFrameC);
756     ok(hr == D3DRM_OK, "Cannot add child frame (hr = %x)\n", hr);
757     CHECK_REFCOUNT(pFrameP1, 1);
758     CHECK_REFCOUNT(pFrameC, 2);
759
760     pArray = NULL;
761     hr = IDirect3DRMFrame_GetChildren(pFrameP1, &pArray);
762     ok(hr == D3DRM_OK, "Cannot get children (hr = %x)\n", hr);
763     /* In some older version of d3drm, creating IDirect3DRMFrameArray object with GetChildren does not increment refcount of children frames */
764     ok((get_refcount((IUnknown*)pFrameC) == 3) || broken(get_refcount((IUnknown*)pFrameC) == 2),
765             "Invalid refcount. Expected 3 (or 2) got %d\n", get_refcount((IUnknown*)pFrameC));
766     if (pArray)
767     {
768         count = IDirect3DRMFrameArray_GetSize(pArray);
769         ok(count == 1, "count = %u\n", count);
770         hr = IDirect3DRMFrameArray_GetElement(pArray, 0, &pFrameTmp);
771         ok(hr == D3DRM_OK, "Cannot get element (hr = %x)\n", hr);
772         ok(pFrameTmp == pFrameC, "pFrameTmp = %p\n", pFrameTmp);
773         ok((get_refcount((IUnknown*)pFrameC) == 4) || broken(get_refcount((IUnknown*)pFrameC) == 3),
774                 "Invalid refcount. Expected 4 (or 3) got %d\n", get_refcount((IUnknown*)pFrameC));
775         IDirect3DRMFrame_Release(pFrameTmp);
776         ok((get_refcount((IUnknown*)pFrameC) == 3) || broken(get_refcount((IUnknown*)pFrameC) == 2),
777                 "Invalid refcount. Expected 3 (or 2) got %d\n", get_refcount((IUnknown*)pFrameC));
778         IDirect3DRMFrameArray_Release(pArray);
779         CHECK_REFCOUNT(pFrameC, 2);
780     }
781
782     pFrameTmp = (void*)0xdeadbeef;
783     hr = IDirect3DRMFrame_GetParent(pFrameC, &pFrameTmp);
784     ok(hr == D3DRM_OK, "Cannot get parent frame (hr = %x)\n", hr);
785     ok(pFrameTmp == pFrameP1, "pFrameTmp = %p\n", pFrameTmp);
786     CHECK_REFCOUNT(pFrameP1, 2);
787
788     /* Add child to second parent */
789     hr = IDirect3DRM_CreateFrame(pD3DRM, NULL, &pFrameP2);
790     ok(hr == D3DRM_OK, "Cannot get IDirect3DRMFrame interface (hr = %x)\n", hr);
791
792     hr = IDirect3DRMFrame_AddChild(pFrameP2, pFrameC);
793     ok(hr == D3DRM_OK, "Cannot add child frame (hr = %x)\n", hr);
794     CHECK_REFCOUNT(pFrameC, 2);
795
796     pArray = NULL;
797     hr = IDirect3DRMFrame_GetChildren(pFrameP2, &pArray);
798     ok(hr == D3DRM_OK, "Cannot get children (hr = %x)\n", hr);
799     if (pArray)
800     {
801         count = IDirect3DRMFrameArray_GetSize(pArray);
802         ok(count == 1, "count = %u\n", count);
803         hr = IDirect3DRMFrameArray_GetElement(pArray, 0, &pFrameTmp);
804         ok(hr == D3DRM_OK, "Cannot get element (hr = %x)\n", hr);
805         ok(pFrameTmp == pFrameC, "pFrameTmp = %p\n", pFrameTmp);
806         IDirect3DRMFrame_Release(pFrameTmp);
807         IDirect3DRMFrameArray_Release(pArray);
808     }
809
810     pArray = NULL;
811     hr = IDirect3DRMFrame_GetChildren(pFrameP1, &pArray);
812     ok(hr == D3DRM_OK, "Cannot get children (hr = %x)\n", hr);
813     if (pArray)
814     {
815         count = IDirect3DRMFrameArray_GetSize(pArray);
816         ok(count == 0, "count = %u\n", count);
817         pFrameTmp = (void*)0xdeadbeef;
818         hr = IDirect3DRMFrameArray_GetElement(pArray, 0, &pFrameTmp);
819         ok(hr == D3DRMERR_BADVALUE, "Should have returned D3DRMERR_BADVALUE (hr = %x)\n", hr);
820         ok(pFrameTmp == NULL, "pFrameTmp = %p\n", pFrameTmp);
821         IDirect3DRMFrameArray_Release(pArray);
822     }
823
824     pFrameTmp = (void*)0xdeadbeef;
825     hr = IDirect3DRMFrame_GetParent(pFrameC, &pFrameTmp);
826     ok(hr == D3DRM_OK, "Cannot get parent frame (hr = %x)\n", hr);
827     ok(pFrameTmp == pFrameP2, "pFrameTmp = %p\n", pFrameTmp);
828     CHECK_REFCOUNT(pFrameP2, 2);
829     CHECK_REFCOUNT(pFrameC, 2);
830
831     /* Add child again */
832     hr = IDirect3DRMFrame_AddChild(pFrameP2, pFrameC);
833     ok(hr == D3DRM_OK, "Cannot add child frame (hr = %x)\n", hr);
834     CHECK_REFCOUNT(pFrameC, 2);
835
836     pArray = NULL;
837     hr = IDirect3DRMFrame_GetChildren(pFrameP2, &pArray);
838     ok(hr == D3DRM_OK, "Cannot get children (hr = %x)\n", hr);
839     if (pArray)
840     {
841         count = IDirect3DRMFrameArray_GetSize(pArray);
842         ok(count == 1, "count = %u\n", count);
843         hr = IDirect3DRMFrameArray_GetElement(pArray, 0, &pFrameTmp);
844         ok(hr == D3DRM_OK, "Cannot get element (hr = %x)\n", hr);
845         ok(pFrameTmp == pFrameC, "pFrameTmp = %p\n", pFrameTmp);
846         IDirect3DRMFrame_Release(pFrameTmp);
847         IDirect3DRMFrameArray_Release(pArray);
848     }
849
850     /* Delete child */
851     hr = IDirect3DRMFrame_DeleteChild(pFrameP2, pFrameC);
852     ok(hr == D3DRM_OK, "Cannot delete child frame (hr = %x)\n", hr);
853     CHECK_REFCOUNT(pFrameC, 1);
854
855     pArray = NULL;
856     hr = IDirect3DRMFrame_GetChildren(pFrameP2, &pArray);
857     ok(hr == D3DRM_OK, "Cannot get children (hr = %x)\n", hr);
858     if (pArray)
859     {
860         count = IDirect3DRMFrameArray_GetSize(pArray);
861         ok(count == 0, "count = %u\n", count);
862         pFrameTmp = (void*)0xdeadbeef;
863         hr = IDirect3DRMFrameArray_GetElement(pArray, 0, &pFrameTmp);
864         ok(hr == D3DRMERR_BADVALUE, "Should have returned D3DRMERR_BADVALUE (hr = %x)\n", hr);
865         ok(pFrameTmp == NULL, "pFrameTmp = %p\n", pFrameTmp);
866         IDirect3DRMFrameArray_Release(pArray);
867     }
868
869     pFrameTmp = (void*)0xdeadbeef;
870     hr = IDirect3DRMFrame_GetParent(pFrameC, &pFrameTmp);
871     ok(hr == D3DRM_OK, "Cannot get parent frame (hr = %x)\n", hr);
872     ok(pFrameTmp == NULL, "pFrameTmp = %p\n", pFrameTmp);
873
874     /* Add two children */
875     hr = IDirect3DRMFrame_AddChild(pFrameP2, pFrameC);
876     ok(hr == D3DRM_OK, "Cannot add child frame (hr = %x)\n", hr);
877     CHECK_REFCOUNT(pFrameC, 2);
878
879     hr = IDirect3DRMFrame_AddChild(pFrameP2, pFrameP1);
880     ok(hr == D3DRM_OK, "Cannot add child frame (hr = %x)\n", hr);
881     CHECK_REFCOUNT(pFrameP1, 3);
882
883     pArray = NULL;
884     hr = IDirect3DRMFrame_GetChildren(pFrameP2, &pArray);
885     ok(hr == D3DRM_OK, "Cannot get children (hr = %x)\n", hr);
886     if (pArray)
887     {
888         count = IDirect3DRMFrameArray_GetSize(pArray);
889         ok(count == 2, "count = %u\n", count);
890         hr = IDirect3DRMFrameArray_GetElement(pArray, 0, &pFrameTmp);
891         ok(hr == D3DRM_OK, "Cannot get element (hr = %x)\n", hr);
892         ok(pFrameTmp == pFrameC, "pFrameTmp = %p\n", pFrameTmp);
893         IDirect3DRMFrame_Release(pFrameTmp);
894         hr = IDirect3DRMFrameArray_GetElement(pArray, 1, &pFrameTmp);
895         ok(hr == D3DRM_OK, "Cannot get element (hr = %x)\n", hr);
896         ok(pFrameTmp == pFrameP1, "pFrameTmp = %p\n", pFrameTmp);
897         IDirect3DRMFrame_Release(pFrameTmp);
898         IDirect3DRMFrameArray_Release(pArray);
899     }
900
901     /* [Add/Delete]Visual with NULL pointer */
902     hr = IDirect3DRMFrame_AddVisual(pFrameP1, NULL);
903     ok(hr == D3DRMERR_BADOBJECT, "Should have returned D3DRMERR_BADOBJECT (hr = %x)\n", hr);
904     CHECK_REFCOUNT(pFrameP1, 3);
905
906     hr = IDirect3DRMFrame_DeleteVisual(pFrameP1, NULL);
907     ok(hr == D3DRMERR_BADOBJECT, "Should have returned D3DRMERR_BADOBJECT (hr = %x)\n", hr);
908     CHECK_REFCOUNT(pFrameP1, 3);
909
910     /* Create Visual */
911     hr = IDirect3DRM_CreateMeshBuilder(pD3DRM, &pMeshBuilder);
912     ok(hr == D3DRM_OK, "Cannot get IDirect3DRMMeshBuilder interface (hr = %x)\n", hr);
913     pVisual1 = (LPDIRECT3DRMVISUAL)pMeshBuilder;
914
915     /* Add Visual to first parent */
916     hr = IDirect3DRMFrame_AddVisual(pFrameP1, pVisual1);
917     ok(hr == D3DRM_OK, "Cannot add visual (hr = %x)\n", hr);
918     CHECK_REFCOUNT(pFrameP1, 3);
919     CHECK_REFCOUNT(pVisual1, 2);
920
921     pVisualArray = NULL;
922     hr = IDirect3DRMFrame_GetVisuals(pFrameP1, &pVisualArray);
923     ok(hr == D3DRM_OK, "Cannot get visuals (hr = %x)\n", hr);
924     if (pVisualArray)
925     {
926         count = IDirect3DRMVisualArray_GetSize(pVisualArray);
927         ok(count == 1, "count = %u\n", count);
928         hr = IDirect3DRMVisualArray_GetElement(pVisualArray, 0, &pVisualTmp);
929         ok(hr == D3DRM_OK, "Cannot get element (hr = %x)\n", hr);
930         ok(pVisualTmp == pVisual1, "pVisualTmp = %p\n", pVisualTmp);
931         IDirect3DRMVisual_Release(pVisualTmp);
932         IDirect3DRMVisualArray_Release(pVisualArray);
933     }
934
935     /* Delete Visual */
936     hr = IDirect3DRMFrame_DeleteVisual(pFrameP1, pVisual1);
937     ok(hr == D3DRM_OK, "Cannot delete visual (hr = %x)\n", hr);
938     CHECK_REFCOUNT(pFrameP1, 3);
939     IDirect3DRMMeshBuilder_Release(pMeshBuilder);
940
941     /* [Add/Delete]Light with NULL pointer */
942     hr = IDirect3DRMFrame_AddLight(pFrameP1, NULL);
943     ok(hr == D3DRMERR_BADOBJECT, "Should have returned D3DRMERR_BADOBJECT (hr = %x)\n", hr);
944     CHECK_REFCOUNT(pFrameP1, 3);
945
946     hr = IDirect3DRMFrame_DeleteLight(pFrameP1, NULL);
947     ok(hr == D3DRMERR_BADOBJECT, "Should have returned D3DRMERR_BADOBJECT (hr = %x)\n", hr);
948     CHECK_REFCOUNT(pFrameP1, 3);
949
950     /* Create Light */
951     hr = IDirect3DRM_CreateLightRGB(pD3DRM, D3DRMLIGHT_SPOT, 0.1, 0.2, 0.3, &pLight1);
952     ok(hr == D3DRM_OK, "Cannot get IDirect3DRMLight interface (hr = %x)\n", hr);
953
954     /* Add Light to first parent */
955     hr = IDirect3DRMFrame_AddLight(pFrameP1, pLight1);
956     ok(hr == D3DRM_OK, "Cannot add light (hr = %x)\n", hr);
957     CHECK_REFCOUNT(pFrameP1, 3);
958     CHECK_REFCOUNT(pLight1, 2);
959
960     pLightArray = NULL;
961     hr = IDirect3DRMFrame_GetLights(pFrameP1, &pLightArray);
962     ok(hr == D3DRM_OK, "Cannot get lights (hr = %x)\n", hr);
963     if (pLightArray)
964     {
965         count = IDirect3DRMLightArray_GetSize(pLightArray);
966         ok(count == 1, "count = %u\n", count);
967         hr = IDirect3DRMLightArray_GetElement(pLightArray, 0, &pLightTmp);
968         ok(hr == D3DRM_OK, "Cannot get element (hr = %x)\n", hr);
969         ok(pLightTmp == pLight1, "pLightTmp = %p\n", pLightTmp);
970         IDirect3DRMLight_Release(pLightTmp);
971         IDirect3DRMLightArray_Release(pLightArray);
972     }
973
974     /* Delete Light */
975     hr = IDirect3DRMFrame_DeleteLight(pFrameP1, pLight1);
976     ok(hr == D3DRM_OK, "Cannot delete light (hr = %x)\n", hr);
977     CHECK_REFCOUNT(pFrameP1, 3);
978     IDirect3DRMLight_Release(pLight1);
979
980     /* Test SceneBackground on first parent */
981     color = IDirect3DRMFrame_GetSceneBackground(pFrameP1);
982     ok(color == 0xff000000, "wrong color (%x)\n", color);
983
984     hr = IDirect3DRMFrame_SetSceneBackground(pFrameP1, 0xff180587);
985     ok(hr == D3DRM_OK, "Cannot set color (hr = %x)\n", hr);
986     color = IDirect3DRMFrame_GetSceneBackground(pFrameP1);
987     ok(color == 0xff180587, "wrong color (%x)\n", color);
988
989     hr = IDirect3DRMFrame_SetSceneBackgroundRGB(pFrameP1, 0.5, 0.5, 0.5);
990     ok(hr == D3DRM_OK, "Cannot set color (hr = %x)\n", hr);
991     color = IDirect3DRMFrame_GetSceneBackground(pFrameP1);
992     ok(color == 0xff7f7f7f, "wrong color (%x)\n", color);
993
994     /* Cleanup */
995     IDirect3DRMFrame_Release(pFrameP2);
996     CHECK_REFCOUNT(pFrameC, 2);
997     CHECK_REFCOUNT(pFrameP1, 3);
998
999     IDirect3DRMFrame_Release(pFrameC);
1000     IDirect3DRMFrame_Release(pFrameP1);
1001
1002     IDirect3DRM_Release(pD3DRM);
1003 }
1004
1005 static void test_Viewport(void)
1006 {
1007     IDirectDrawClipper *pClipper;
1008     HRESULT hr;
1009     LPDIRECT3DRM pD3DRM;
1010     LPDIRECT3DRMDEVICE pDevice;
1011     LPDIRECT3DRMFRAME pFrame;
1012     LPDIRECT3DRMVIEWPORT pViewport;
1013     GUID driver;
1014     HWND window;
1015     RECT rc;
1016     DWORD size;
1017     CHAR cname[64] = {0};
1018
1019     window = CreateWindowA("static", "d3drm_test", WS_OVERLAPPEDWINDOW, 0, 0, 300, 200, 0, 0, 0, 0);
1020     GetClientRect(window, &rc);
1021
1022     hr = pDirect3DRMCreate(&pD3DRM);
1023     ok(hr == D3DRM_OK, "Cannot get IDirect3DRM interface (hr = %x)\n", hr);
1024
1025     hr = DirectDrawCreateClipper(0, &pClipper, NULL);
1026     ok(hr == DD_OK, "Cannot get IDirectDrawClipper interface (hr = %x)\n", hr);
1027
1028     hr = IDirectDrawClipper_SetHWnd(pClipper, 0, window);
1029     ok(hr == DD_OK, "Cannot set HWnd to Clipper (hr = %x)\n", hr);
1030
1031     memcpy(&driver, &IID_IDirect3DRGBDevice, sizeof(GUID));
1032     hr = IDirect3DRM3_CreateDeviceFromClipper(pD3DRM, pClipper, &driver, rc.right, rc.bottom, &pDevice);
1033     ok(hr == D3DRM_OK, "Cannot get IDirect3DRMDevice interface (hr = %x)\n", hr);
1034
1035     hr = IDirect3DRM_CreateFrame(pD3DRM, NULL, &pFrame);
1036     ok(hr == D3DRM_OK, "Cannot get IDirect3DRMFrame interface (hr = %x)\n", hr);
1037
1038     hr = IDirect3DRM_CreateViewport(pD3DRM, pDevice, pFrame, rc.left, rc.top, rc.right, rc.bottom, &pViewport);
1039     ok(hr == D3DRM_OK, "Cannot get IDirect3DRMViewport interface (hr = %x)\n", hr);
1040
1041     hr = IDirect3DRMViewport_GetClassName(pViewport, NULL, cname);
1042     ok(hr == E_INVALIDARG, "GetClassName failed with %x\n", hr);
1043     hr = IDirect3DRMViewport_GetClassName(pViewport, NULL, NULL);
1044     ok(hr == E_INVALIDARG, "GetClassName failed with %x\n", hr);
1045     size = 1;
1046     hr = IDirect3DRMViewport_GetClassName(pViewport, &size, cname);
1047     ok(hr == E_INVALIDARG, "GetClassName failed with %x\n", hr);
1048     size = sizeof(cname);
1049     hr = IDirect3DRMViewport_GetClassName(pViewport, &size, cname);
1050     ok(hr == D3DRM_OK, "Cannot get classname (hr = %x)\n", hr);
1051     ok(size == sizeof("Viewport"), "wrong size: %u\n", size);
1052     ok(!strcmp(cname, "Viewport"), "Expected cname to be \"Viewport\", but got \"%s\"\n", cname);
1053
1054     IDirect3DRMViewport_Release(pViewport);
1055     IDirect3DRMFrame_Release(pFrame);
1056     IDirect3DRMDevice_Release(pDevice);
1057     IDirectDrawClipper_Release(pClipper);
1058
1059     IDirect3DRM_Release(pD3DRM);
1060     DestroyWindow(window);
1061 }
1062
1063 static void test_Light(void)
1064 {
1065     HRESULT hr;
1066     LPDIRECT3DRM pD3DRM;
1067     LPDIRECT3DRMLIGHT pLight;
1068     D3DRMLIGHTTYPE type;
1069     D3DCOLOR color;
1070     DWORD size;
1071     CHAR cname[64] = {0};
1072
1073     hr = pDirect3DRMCreate(&pD3DRM);
1074     ok(hr == D3DRM_OK, "Cannot get IDirect3DRM interface (hr = %x)\n", hr);
1075
1076     hr = IDirect3DRM_CreateLightRGB(pD3DRM, D3DRMLIGHT_SPOT, 0.5, 0.5, 0.5, &pLight);
1077     ok(hr == D3DRM_OK, "Cannot get IDirect3DRMLight interface (hr = %x)\n", hr);
1078
1079     hr = IDirect3DRMLight_GetClassName(pLight, NULL, cname);
1080     ok(hr == E_INVALIDARG, "GetClassName failed with %x\n", hr);
1081     hr = IDirect3DRMLight_GetClassName(pLight, NULL, NULL);
1082     ok(hr == E_INVALIDARG, "GetClassName failed with %x\n", hr);
1083     size = 1;
1084     hr = IDirect3DRMLight_GetClassName(pLight, &size, cname);
1085     ok(hr == E_INVALIDARG, "GetClassName failed with %x\n", hr);
1086     size = sizeof(cname);
1087     hr = IDirect3DRMLight_GetClassName(pLight, &size, cname);
1088     ok(hr == D3DRM_OK, "Cannot get classname (hr = %x)\n", hr);
1089     ok(size == sizeof("Light"), "wrong size: %u\n", size);
1090     ok(!strcmp(cname, "Light"), "Expected cname to be \"Light\", but got \"%s\"\n", cname);
1091
1092     type = IDirect3DRMLight_GetType(pLight);
1093     ok(type == D3DRMLIGHT_SPOT, "wrong type (%u)\n", type);
1094
1095     color = IDirect3DRMLight_GetColor(pLight);
1096     ok(color == 0xff7f7f7f, "wrong color (%x)\n", color);
1097
1098     hr = IDirect3DRMLight_SetType(pLight, D3DRMLIGHT_POINT);
1099     ok(hr == D3DRM_OK, "Cannot set type (hr = %x)\n", hr);
1100     type = IDirect3DRMLight_GetType(pLight);
1101     ok(type == D3DRMLIGHT_POINT, "wrong type (%u)\n", type);
1102
1103     hr = IDirect3DRMLight_SetColor(pLight, 0xff180587);
1104     ok(hr == D3DRM_OK, "Cannot set color (hr = %x)\n", hr);
1105     color = IDirect3DRMLight_GetColor(pLight);
1106     ok(color == 0xff180587, "wrong color (%x)\n", color);
1107
1108     hr = IDirect3DRMLight_SetColorRGB(pLight, 0.5, 0.5, 0.5);
1109     ok(hr == D3DRM_OK, "Cannot set color (hr = %x)\n", hr);
1110     color = IDirect3DRMLight_GetColor(pLight);
1111     ok(color == 0xff7f7f7f, "wrong color (%x)\n", color);
1112
1113     IDirect3DRMLight_Release(pLight);
1114
1115     IDirect3DRM_Release(pD3DRM);
1116 }
1117
1118 static void test_Material2(void)
1119 {
1120     HRESULT hr;
1121     LPDIRECT3DRM pD3DRM;
1122     LPDIRECT3DRM3 pD3DRM3;
1123     LPDIRECT3DRMMATERIAL2 pMaterial2;
1124     D3DVALUE r, g, b;
1125     DWORD size;
1126     CHAR cname[64] = {0};
1127
1128     hr = pDirect3DRMCreate(&pD3DRM);
1129     ok(hr == D3DRM_OK, "Cannot get IDirect3DRM interface (hr = %x)\n", hr);
1130
1131     hr = IDirect3DRM_QueryInterface(pD3DRM, &IID_IDirect3DRM3, (LPVOID*)&pD3DRM3);
1132     if (FAILED(hr))
1133     {
1134         win_skip("Cannot get IDirect3DRM3 interface (hr = %x), skipping tests\n", hr);
1135         IDirect3DRM_Release(pD3DRM);
1136         return;
1137     }
1138
1139     hr = IDirect3DRM3_CreateMaterial(pD3DRM3, 18.5f, &pMaterial2);
1140     ok(hr == D3DRM_OK, "Cannot get IDirect3DRMMaterial2 interface (hr = %x)\n", hr);
1141
1142     hr = IDirect3DRMMaterial2_GetClassName(pMaterial2, NULL, cname);
1143     ok(hr == E_INVALIDARG, "GetClassName failed with %x\n", hr);
1144     hr = IDirect3DRMMaterial2_GetClassName(pMaterial2, NULL, NULL);
1145     ok(hr == E_INVALIDARG, "GetClassName failed with %x\n", hr);
1146     size = 1;
1147     hr = IDirect3DRMMaterial2_GetClassName(pMaterial2, &size, cname);
1148     ok(hr == E_INVALIDARG, "GetClassName failed with %x\n", hr);
1149     size = sizeof(cname);
1150     hr = IDirect3DRMMaterial2_GetClassName(pMaterial2, &size, cname);
1151     ok(hr == D3DRM_OK, "Cannot get classname (hr = %x)\n", hr);
1152     ok(size == sizeof("Material"), "wrong size: %u\n", size);
1153     ok(!strcmp(cname, "Material"), "Expected cname to be \"Material\", but got \"%s\"\n", cname);
1154
1155     r = IDirect3DRMMaterial2_GetPower(pMaterial2);
1156     ok(r == 18.5f, "wrong power (%f)\n", r);
1157
1158     hr = IDirect3DRMMaterial2_GetEmissive(pMaterial2, &r, &g, &b);
1159     ok(hr == D3DRM_OK, "Cannot get emissive (hr = %x)\n", hr);
1160     ok(r == 0.0f && g == 0.0f && b == 0.0f, "wrong emissive r=%f g=%f b=%f, expected r=0.0 g=0.0 b=0.0\n", r, g, b);
1161
1162     hr = IDirect3DRMMaterial2_GetSpecular(pMaterial2, &r, &g, &b);
1163     ok(hr == D3DRM_OK, "Cannot get emissive (hr = %x)\n", hr);
1164     ok(r == 1.0f && g == 1.0f && b == 1.0f, "wrong specular r=%f g=%f b=%f, expected r=1.0 g=1.0 b=1.0\n", r, g, b);
1165
1166     hr = IDirect3DRMMaterial2_GetAmbient(pMaterial2, &r, &g, &b);
1167     ok(hr == D3DRM_OK, "Cannot get emissive (hr = %x)\n", hr);
1168     ok(r == 0.0f && g == 0.0f && b == 0.0f, "wrong ambient r=%f g=%f b=%f, expected r=0.0 g=0.0 b=0.0\n", r, g, b);
1169
1170     hr = IDirect3DRMMaterial2_SetPower(pMaterial2, 5.87f);
1171     ok(hr == D3DRM_OK, "Cannot set power (hr = %x)\n", hr);
1172     r = IDirect3DRMMaterial2_GetPower(pMaterial2);
1173     ok(r == 5.87f, "wrong power (%f)\n", r);
1174
1175     hr = IDirect3DRMMaterial2_SetEmissive(pMaterial2, 0.5f, 0.5f, 0.5f);
1176     ok(hr == D3DRM_OK, "Cannot set emissive (hr = %x)\n", hr);
1177     hr = IDirect3DRMMaterial2_GetEmissive(pMaterial2, &r, &g, &b);
1178     ok(hr == D3DRM_OK, "Cannot get emissive (hr = %x)\n", hr);
1179     ok(r == 0.5f && g == 0.5f && b == 0.5f, "wrong emissive r=%f g=%f b=%f, expected r=0.5 g=0.5 b=0.5\n", r, g, b);
1180
1181     hr = IDirect3DRMMaterial2_SetSpecular(pMaterial2, 0.6f, 0.6f, 0.6f);
1182     ok(hr == D3DRM_OK, "Cannot set specular (hr = %x)\n", hr);
1183     hr = IDirect3DRMMaterial2_GetSpecular(pMaterial2, &r, &g, &b);
1184     ok(hr == D3DRM_OK, "Cannot get specular (hr = %x)\n", hr);
1185     ok(r == 0.6f && g == 0.6f && b == 0.6f, "wrong specular r=%f g=%f b=%f, expected r=0.6 g=0.6 b=0.6\n", r, g, b);
1186
1187     hr = IDirect3DRMMaterial2_SetAmbient(pMaterial2, 0.7f, 0.7f, 0.7f);
1188     ok(hr == D3DRM_OK, "Cannot set ambient (hr = %x)\n", hr);
1189     hr = IDirect3DRMMaterial2_GetAmbient(pMaterial2, &r, &g, &b);
1190     ok(hr == D3DRM_OK, "Cannot get ambient (hr = %x)\n", hr);
1191     ok(r == 0.7f && g == 0.7f && b == 0.7f, "wrong ambient r=%f g=%f b=%f, expected r=0.7 g=0.7 b=0.7\n", r, g, b);
1192
1193     IDirect3DRMMaterial2_Release(pMaterial2);
1194
1195     IDirect3DRM3_Release(pD3DRM3);
1196     IDirect3DRM_Release(pD3DRM);
1197 }
1198
1199 static void test_Texture(void)
1200 {
1201     HRESULT hr;
1202     LPDIRECT3DRM pD3DRM;
1203     LPDIRECT3DRMTEXTURE pTexture;
1204     D3DRMIMAGE initimg = {
1205         2, 2, 1, 1, 32,
1206         TRUE, 2 * sizeof(DWORD), NULL, NULL,
1207         0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000, 0, NULL
1208     };
1209     DWORD pixel[4] = { 20000, 30000, 10000, 0 };
1210     DWORD size;
1211     CHAR cname[64] = {0};
1212
1213     hr = pDirect3DRMCreate(&pD3DRM);
1214     ok(hr == D3DRM_OK, "Cannot get IDirect3DRM interface (hr = %x)\n", hr);
1215
1216     initimg.buffer1 = &pixel;
1217     hr = IDirect3DRM_CreateTexture(pD3DRM, &initimg, &pTexture);
1218     ok(hr == D3DRM_OK, "Cannot get IDirect3DRMTexture interface (hr = %x)\n", hr);
1219
1220     hr = IDirect3DRMTexture_GetClassName(pTexture, NULL, cname);
1221     ok(hr == E_INVALIDARG, "GetClassName failed with %x\n", hr);
1222     hr = IDirect3DRMTexture_GetClassName(pTexture, NULL, NULL);
1223     ok(hr == E_INVALIDARG, "GetClassName failed with %x\n", hr);
1224     size = 1;
1225     hr = IDirect3DRMTexture_GetClassName(pTexture, &size, cname);
1226     ok(hr == E_INVALIDARG, "GetClassName failed with %x\n", hr);
1227     size = sizeof(cname);
1228     hr = IDirect3DRMTexture_GetClassName(pTexture, &size, cname);
1229     ok(hr == D3DRM_OK, "Cannot get classname (hr = %x)\n", hr);
1230     ok(size == sizeof("Texture"), "wrong size: %u\n", size);
1231     ok(!strcmp(cname, "Texture"), "Expected cname to be \"Texture\", but got \"%s\"\n", cname);
1232
1233     IDirect3DRMTexture_Release(pTexture);
1234
1235     IDirect3DRM_Release(pD3DRM);
1236 }
1237
1238 static void test_Device(void)
1239 {
1240     IDirectDrawClipper *pClipper;
1241     HRESULT hr;
1242     LPDIRECT3DRM pD3DRM;
1243     LPDIRECT3DRMDEVICE pDevice;
1244     LPDIRECT3DRMWINDEVICE pWinDevice;
1245     GUID driver;
1246     HWND window;
1247     RECT rc;
1248     DWORD size;
1249     CHAR cname[64] = {0};
1250
1251     window = CreateWindowA("static", "d3drm_test", WS_OVERLAPPEDWINDOW, 0, 0, 300, 200, 0, 0, 0, 0);
1252     GetClientRect(window, &rc);
1253
1254     hr = pDirect3DRMCreate(&pD3DRM);
1255     ok(hr == D3DRM_OK, "Cannot get IDirect3DRM interface (hr = %x)\n", hr);
1256
1257     hr = DirectDrawCreateClipper(0, &pClipper, NULL);
1258     ok(hr == DD_OK, "Cannot get IDirectDrawClipper interface (hr = %x)\n", hr);
1259
1260     hr = IDirectDrawClipper_SetHWnd(pClipper, 0, window);
1261     ok(hr == DD_OK, "Cannot set HWnd to Clipper (hr = %x)\n", hr);
1262
1263     memcpy(&driver, &IID_IDirect3DRGBDevice, sizeof(GUID));
1264     hr = IDirect3DRM3_CreateDeviceFromClipper(pD3DRM, pClipper, &driver, rc.right, rc.bottom, &pDevice);
1265     ok(hr == D3DRM_OK, "Cannot get IDirect3DRMDevice interface (hr = %x)\n", hr);
1266
1267     hr = IDirect3DRMDevice_GetClassName(pDevice, NULL, cname);
1268     ok(hr == E_INVALIDARG, "GetClassName failed with %x\n", hr);
1269     hr = IDirect3DRMDevice_GetClassName(pDevice, NULL, NULL);
1270     ok(hr == E_INVALIDARG, "GetClassName failed with %x\n", hr);
1271     size = 1;
1272     hr = IDirect3DRMDevice_GetClassName(pDevice, &size, cname);
1273     ok(hr == E_INVALIDARG, "GetClassName failed with %x\n", hr);
1274     size = sizeof(cname);
1275     hr = IDirect3DRMDevice_GetClassName(pDevice, &size, cname);
1276     ok(hr == D3DRM_OK, "Cannot get classname (hr = %x)\n", hr);
1277     ok(size == sizeof("Device"), "wrong size: %u\n", size);
1278     ok(!strcmp(cname, "Device"), "Expected cname to be \"Device\", but got \"%s\"\n", cname);
1279
1280     /* WinDevice */
1281     hr = IDirect3DRMDevice_QueryInterface(pDevice, &IID_IDirect3DRMWinDevice, (LPVOID*)&pWinDevice);
1282     if (FAILED(hr))
1283     {
1284         win_skip("Cannot get IDirect3DRMWinDevice interface (hr = %x), skipping tests\n", hr);
1285         goto cleanup;
1286     }
1287
1288     hr = IDirect3DRMWinDevice_GetClassName(pWinDevice, NULL, cname);
1289     ok(hr == E_INVALIDARG, "GetClassName failed with %x\n", hr);
1290     hr = IDirect3DRMWinDevice_GetClassName(pWinDevice, NULL, NULL);
1291     ok(hr == E_INVALIDARG, "GetClassName failed with %x\n", hr);
1292     size = 1;
1293     hr = IDirect3DRMWinDevice_GetClassName(pWinDevice, &size, cname);
1294     ok(hr == E_INVALIDARG, "GetClassName failed with %x\n", hr);
1295     size = sizeof(cname);
1296     hr = IDirect3DRMWinDevice_GetClassName(pWinDevice, &size, cname);
1297     ok(hr == D3DRM_OK, "Cannot get classname (hr = %x)\n", hr);
1298     ok(size == sizeof("Device"), "wrong size: %u\n", size);
1299     ok(!strcmp(cname, "Device"), "Expected cname to be \"Device\", but got \"%s\"\n", cname);
1300
1301     IDirect3DRMWinDevice_Release(pWinDevice);
1302
1303 cleanup:
1304     IDirect3DRMDevice_Release(pDevice);
1305     IDirectDrawClipper_Release(pClipper);
1306
1307     IDirect3DRM_Release(pD3DRM);
1308     DestroyWindow(window);
1309 }
1310
1311 static void test_frame_transform(void)
1312 {
1313     HRESULT hr;
1314     LPDIRECT3DRM d3drm;
1315     LPDIRECT3DRMFRAME frame;
1316     D3DRMMATRIX4D matrix;
1317
1318     hr = pDirect3DRMCreate(&d3drm);
1319     ok(hr == D3DRM_OK, "Cannot get IDirect3DRM interface (hr = %x)\n", hr);
1320
1321     hr = IDirect3DRM_CreateFrame(d3drm, NULL, &frame);
1322     ok(hr == D3DRM_OK, "Cannot get IDirect3DRMFrame interface (hr = %x)\n", hr);
1323
1324     hr = IDirect3DRMFrame_GetTransform(frame, matrix);
1325     ok(hr == D3DRM_OK, "IDirect3DRMFrame_GetTransform returned hr = %x\n", hr);
1326     ok(!memcmp(matrix, identity, sizeof(D3DRMMATRIX4D)), "Returned matrix is not identity\n");
1327
1328     IDirect3DRM_Release(d3drm);
1329 }
1330
1331 static int nb_objects = 0;
1332 static const GUID* refiids[] =
1333 {
1334     &IID_IDirect3DRMMeshBuilder,
1335     &IID_IDirect3DRMMeshBuilder,
1336     &IID_IDirect3DRMFrame,
1337     &IID_IDirect3DRMMaterial /* Not taken into account and not notified */
1338 };
1339
1340 static void __cdecl object_load_callback(LPDIRECT3DRMOBJECT object, REFIID objectguid, LPVOID arg)
1341 {
1342     ok(object != NULL, "Arg 1 should not be null\n");
1343     ok(IsEqualGUID(objectguid, refiids[nb_objects]), "Arg 2 is incorrect\n");
1344     ok(arg == (LPVOID)0xdeadbeef, "Arg 3 should be 0xdeadbeef (got %p)\n", arg);
1345     nb_objects++;
1346 }
1347
1348 static void test_d3drm_load(void)
1349 {
1350     HRESULT hr;
1351     LPDIRECT3DRM pD3DRM;
1352     D3DRMLOADMEMORY info;
1353     const GUID* req_refiids[] = { &IID_IDirect3DRMMeshBuilder, &IID_IDirect3DRMFrame, &IID_IDirect3DRMMaterial };
1354
1355     hr = pDirect3DRMCreate(&pD3DRM);
1356     ok(hr == D3DRM_OK, "Cannot get IDirect3DRM interface (hr = %x)\n", hr);
1357
1358     info.lpMemory = data_d3drm_load;
1359     info.dSize = strlen(data_d3drm_load);
1360     hr = IDirect3DRM_Load(pD3DRM, &info, NULL, (GUID**)req_refiids, 3, D3DRMLOAD_FROMMEMORY, object_load_callback, (LPVOID)0xdeadbeef, NULL, NULL, NULL);
1361     ok(hr == D3DRM_OK, "Cannot load data (hr = %x)\n", hr);
1362     ok(nb_objects == 3, "Should have loaded 3 objects (got %d)\n", nb_objects);
1363
1364     IDirect3DRM_Release(pD3DRM);
1365 }
1366
1367 IDirect3DRMMeshBuilder *mesh_builder = NULL;
1368
1369 static void __cdecl object_load_callback_frame(IDirect3DRMObject *object, REFIID object_guid, void *arg)
1370 {
1371     HRESULT hr;
1372     IDirect3DRMFrame *frame;
1373     IDirect3DRMVisualArray *array;
1374     IDirect3DRMVisual *visual;
1375     ULONG size;
1376     char name[128];
1377
1378     hr = IDirect3DRMObject_QueryInterface(object, &IID_IDirect3DRMFrame, (void**)&frame);
1379     ok(hr == D3DRM_OK, "IDirect3DRMObject_QueryInterface returned %x\n", hr);
1380
1381     hr = IDirect3DRMFrame_GetVisuals(frame, &array);
1382     ok(hr == D3DRM_OK, "IDirect3DRMFrame_GetVisuals returned %x\n", hr);
1383
1384     size = IDirect3DRMVisualArray_GetSize(array);
1385     ok(size == 1, "Wrong size %u returned, expected 1\n", size);
1386
1387     hr = IDirect3DRMVisualArray_GetElement(array, 0, &visual);
1388     ok(hr == D3DRM_OK, "IDirect3DRMVisualArray_GetElement returned %x\n", hr);
1389
1390     hr = IDirect3DRMVisual_QueryInterface(visual, &IID_IDirect3DRMMeshBuilder, (void**)&mesh_builder);
1391     ok(hr == D3DRM_OK, "IDirect3DRMVisualArray_GetSize returned %x\n", hr);
1392
1393     size = sizeof(name);
1394     hr = IDirect3DRMMeshBuilder_GetName(mesh_builder, &size, name);
1395     ok(hr == D3DRM_OK, "IDirect3DRMMeshBuilder_GetName returned %x\n", hr);
1396     ok(!strcmp(name, "mesh1"), "Wrong name %s, expected mesh1\n", name);
1397
1398     IDirect3DRMVisual_Release(visual);
1399     IDirect3DRMVisualArray_Release(array);
1400     IDirect3DRMFrame_Release(frame);
1401 }
1402
1403 struct {
1404     int vertex_count;
1405     int face_count;
1406     int vertex_per_face;
1407     int face_data_size;
1408     DWORD color;
1409     float power;
1410     float specular[3];
1411     float emissive[3];
1412 } groups[3] = {
1413     { 4, 3, 3, 9, 0x4c0000ff, 30.0f, { 0.31f, 0.32f, 0.33f }, { 0.34f, 0.35f, 0.36f } },
1414     { 4, 2, 3, 6, 0x3300ff00, 20.0f, { 0.21f, 0.22f, 0.23f }, { 0.24f, 0.25f, 0.26f } },
1415     { 3, 1, 3, 3, 0x19ff0000, 10.0f, { 0.11f, 0.12f, 0.13f }, { 0.14f, 0.15f, 0.16f } }
1416 };
1417
1418 static void test_frame_mesh_materials(void)
1419 {
1420     HRESULT hr;
1421     IDirect3DRM *d3drm;
1422     D3DRMLOADMEMORY info;
1423     const GUID *req_refiids[] = { &IID_IDirect3DRMFrame };
1424     IDirect3DRMMesh *mesh;
1425     ULONG size;
1426     IDirect3DRMMaterial *material;
1427     IDirect3DRMTexture *texture;
1428     int i;
1429
1430     hr = pDirect3DRMCreate(&d3drm);
1431     ok(hr == D3DRM_OK, "Direct3DRMCreate returned %x\n", hr);
1432
1433     info.lpMemory = data_frame_mesh_materials;
1434     info.dSize = strlen(data_frame_mesh_materials);
1435     hr = IDirect3DRM_Load(d3drm, &info, NULL, (GUID**)req_refiids, 1, D3DRMLOAD_FROMMEMORY, object_load_callback_frame, (void*)0xdeadbeef, NULL, NULL, NULL);
1436     ok(hr == D3DRM_OK, "Cannot load data (hr = %x)\n", hr);
1437
1438     hr = IDirect3DRMMeshBuilder_CreateMesh(mesh_builder, &mesh);
1439     ok(hr == D3DRM_OK, "IDirect3DRMMeshBuilder_CreateMesh returned %x\n", hr);
1440
1441     size = IDirect3DRMMesh_GetGroupCount(mesh);
1442     ok(size == 3, "Wrong size %u returned, expected 3\n", size);
1443
1444     for (i = 0; i < size; i++)
1445     {
1446         D3DVALUE red, green, blue, power;
1447         D3DCOLOR color;
1448         unsigned vertex_count, face_count, vertex_per_face;
1449         DWORD face_data_size;
1450
1451         hr = IDirect3DRMMesh_GetGroup(mesh, i, &vertex_count, &face_count, &vertex_per_face, &face_data_size, NULL);
1452         ok(hr == D3DRM_OK, "Group %d: IDirect3DRMMesh_GetGroup returned %x\n", i, hr);
1453         ok(vertex_count == groups[i].vertex_count, "Group %d: Wrong vertex count %d, expected %d\n", i, vertex_count, groups[i].vertex_count);
1454         ok(face_count == groups[i].face_count, "Group %d: Wrong face count %d; expected %d\n", i, face_count, groups[i].face_count);
1455         ok(vertex_per_face == groups[i].vertex_per_face, "Group %d: Wrong vertex per face %d, expected %d\n", i, vertex_per_face, groups[i].vertex_per_face);
1456         ok(face_data_size == groups[i].face_data_size, "Group %d: Wrong face data size %d, expected %d\n", i, face_data_size, groups[i].face_data_size);
1457
1458         color = IDirect3DRMMesh_GetGroupColor(mesh, i);
1459         ok(color == groups[i].color, "Group %d: Wrong color %x, expected %x\n", i, color, groups[i].color);
1460
1461         hr = IDirect3DRMMesh_GetGroupMaterial(mesh, i, &material);
1462         ok(hr == D3DRM_OK, "Group %d: IDirect3DRMMesh_GetGroupMaterial returned %x\n", i, hr);
1463         ok(material != NULL, "Group %d: No material\n", i);
1464         power = IDirect3DRMMaterial_GetPower(material);
1465         ok(power == groups[i].power, "Group %d: Wrong power %f, expected %f\n", i, power,  groups[i].power);
1466         hr = IDirect3DRMMaterial_GetSpecular(material, &red, &green, &blue);
1467         ok(hr == D3DRM_OK, "Group %d: IDirect3DRMMaterial_GetSpecular returned %x\n", i, hr);
1468         ok(red == groups[i].specular[0], "Group %d: Wrong specular red %f, expected %f\n", i, red, groups[i].specular[0]);
1469         ok(green == groups[i].specular[1], "Group %d: Wrong specular green %f, pD3DRMexpected %f\n", i, green, groups[i].specular[1]);
1470         ok(blue == groups[i].specular[2], "Group %d: Wrong specular blue %f, expected %f\n", i, blue, groups[i].specular[2]);
1471         hr = IDirect3DRMMaterial_GetEmissive(material, &red, &green, &blue);
1472         ok(hr == D3DRM_OK, "Group %d: IDirect3DRMMaterial_GetEmissive returned %x\n", i, hr);
1473         ok(red == groups[i].emissive[0], "Group %d: Wrong emissive red %f, expected %f\n", i, red, groups[i].emissive[0]);
1474         ok(green == groups[i].emissive[1], "Group %d: Wrong emissive green %f, expected %f\n", i, green, groups[i].emissive[1]);
1475         ok(blue == groups[i].emissive[2], "Group %d: Wrong emissive blue %f, expected %f\n", i, blue, groups[i].emissive[2]);
1476
1477         hr = IDirect3DRMMesh_GetGroupTexture(mesh, i, &texture);
1478         ok(hr == D3DRM_OK, "Group %d: IDirect3DRMMesh_GetGroupTexture returned %x\n", i, hr);
1479         ok(!texture, "Group %d: Unexpected texture\n", i);
1480
1481         if (material)
1482             IDirect3DRMMaterial_Release(material);
1483         if (texture)
1484             IDirect3DRMTexture_Release(texture);
1485     }
1486
1487     IDirect3DRMMesh_Release(mesh);
1488     IDirect3DRMMeshBuilder_Release(mesh_builder);
1489     IDirect3DRM_Release(d3drm);
1490 }
1491
1492 START_TEST(d3drm)
1493 {
1494     if (!InitFunctionPtrs())
1495         return;
1496
1497     test_MeshBuilder();
1498     test_MeshBuilder3();
1499     test_Mesh();
1500     test_Frame();
1501     test_Device();
1502     test_Viewport();
1503     test_Light();
1504     test_Material2();
1505     test_Texture();
1506     test_frame_transform();
1507     test_d3drm_load();
1508     test_frame_mesh_materials();
1509
1510     FreeLibrary(d3drm_handle);
1511 }