strmbase: do not lock in BaseOutputPinImpl_GetDeliveryBuffer the MemInputPin will...
[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
24 #include "wine/test.h"
25
26 static HMODULE d3drm_handle = 0;
27
28 static HRESULT (WINAPI * pDirect3DRMCreate)(LPDIRECT3DRM* ppDirect3DRM);
29
30 #define CHECK_REFCOUNT(obj,rc) \
31     { \
32         int rc_new = rc; \
33         int count = get_refcount( (IUnknown *)obj ); \
34         ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
35     }
36
37 #define D3DRM_GET_PROC(func) \
38     p ## func = (void*)GetProcAddress(d3drm_handle, #func); \
39     if(!p ## func) { \
40       trace("GetProcAddress(%s) failed\n", #func); \
41       FreeLibrary(d3drm_handle); \
42       return FALSE; \
43     }
44
45 static BOOL InitFunctionPtrs(void)
46 {
47     d3drm_handle = LoadLibraryA("d3drm.dll");
48
49     if(!d3drm_handle)
50     {
51         skip("Could not load d3drm.dll\n");
52         return FALSE;
53     }
54
55     D3DRM_GET_PROC(Direct3DRMCreate)
56
57     return TRUE;
58 }
59
60 static int get_refcount(IUnknown *object)
61 {
62     IUnknown_AddRef( object );
63     return IUnknown_Release( object );
64 }
65
66 static D3DRMMATRIX4D identity = {
67     { 1.0f, 0.0f, 0.0f, 0.0f },
68     { 0.0f, 1.0f, 0.0f, 0.0f },
69     { 0.0f, 0.0f, 1.0f, 0.0f },
70     { 0.0f, 0.0f, 0.0f, 1.0f }
71 };
72
73 static char data_bad_version[] =
74 "xof 0302txt 0064\n"
75 "Header Object\n"
76 "{\n"
77 "1; 2; 3;\n"
78 "}\n";
79
80 static char data_no_mesh[] =
81 "xof 0302txt 0064\n"
82 "Header Object\n"
83 "{\n"
84 "1; 0; 1;\n"
85 "}\n";
86
87 static char data_ok[] =
88 "xof 0302txt 0064\n"
89 "Header Object\n"
90 "{\n"
91 "1; 0; 1;\n"
92 "}\n"
93 "Mesh Object\n"
94 "{\n"
95 "4;\n"
96 "1.0; 0.0; 0.0;,\n"
97 "0.0; 1.0; 0.0;,\n"
98 "0.0; 0.0; 1.0;,\n"
99 "1.0; 1.0; 1.0;;\n"
100 "3;\n"
101 "3; 0, 1, 2;,\n"
102 "3; 1, 2, 3;,\n"
103 "3; 3, 1, 2;;\n"
104 "}\n";
105
106 static char data_full[] =
107 "xof 0302txt 0064\n"
108 "Header { 1; 0; 1; }\n"
109 "Mesh {\n"
110 " 3;\n"
111 " 0.1; 0.2; 0.3;,\n"
112 " 0.4; 0.5; 0.6;,\n"
113 " 0.7; 0.8; 0.9;;\n"
114 " 1;\n"
115 " 3; 0, 1, 2;;\n"
116 " MeshMaterialList {\n"
117 "  1; 1; 0;\n"
118 "  Material {\n"
119 "   0.0; 1.0; 0.0; 1.0;;\n"
120 "   30.0;\n"
121 "   1.0; 0.0; 0.0;;\n"
122 "   0.5; 0.5; 0.5;;\n"
123 "   TextureFileName {\n"
124 "    \"Texture.bmp\";\n"
125 "   }\n"
126 "  }\n"
127 " }\n"
128 " MeshNormals {\n"
129 "  3;\n"
130 "  1.1; 1.2; 1.3;,\n"
131 "  1.4; 1.5; 1.6;,\n"
132 "  1.7; 1.8; 1.9;;\n"
133 "  1;"
134 "  3; 0, 1, 2;;\n"
135 " }\n"
136 " MeshTextureCoords {\n"
137 "  3;\n"
138 "  0.13; 0.17;,\n"
139 "  0.23; 0.27;,\n"
140 "  0.33; 0.37;;\n"
141 " }\n"
142 "}\n";
143
144 static char data_d3drm_load[] =
145 "xof 0302txt 0064\n"
146 "Header Object\n"
147 "{\n"
148 "1; 0; 1;\n"
149 "}\n"
150 "Mesh Object1\n"
151 "{\n"
152 " 1;\n"
153 " 0.1; 0.2; 0.3;,\n"
154 " 1;\n"
155 " 3; 0, 1, 2;;\n"
156 "}\n"
157 "Mesh Object2\n"
158 "{\n"
159 " 1;\n"
160 " 0.1; 0.2; 0.3;,\n"
161 " 1;\n"
162 " 3; 0, 1, 2;;\n"
163 "}\n"
164 "Frame Scene\n"
165 "{\n"
166 " {Object1}\n"
167 " {Object2}\n"
168 "}\n";
169
170 static void test_MeshBuilder(void)
171 {
172     HRESULT hr;
173     LPDIRECT3DRM pD3DRM;
174     LPDIRECT3DRMMESHBUILDER pMeshBuilder;
175     D3DRMLOADMEMORY info;
176     int val;
177     DWORD val1, val2, val3;
178     D3DVALUE valu, valv;
179     D3DVECTOR v[3];
180     D3DVECTOR n[3];
181     DWORD f[8];
182
183     hr = pDirect3DRMCreate(&pD3DRM);
184     ok(hr == D3DRM_OK, "Cannot get IDirect3DRM interface (hr = %x)\n", hr);
185
186     hr = IDirect3DRM_CreateMeshBuilder(pD3DRM, &pMeshBuilder);
187     ok(hr == D3DRM_OK, "Cannot get IDirect3DRMMeshBuilder interface (hr = %x)\n", hr);
188
189     info.lpMemory = data_bad_version;
190     info.dSize = strlen(data_bad_version);
191     hr = IDirect3DRMMeshBuilder_Load(pMeshBuilder, &info, NULL, D3DRMLOAD_FROMMEMORY, NULL, NULL);
192     ok(hr == D3DRMERR_BADFILE, "Should have returned D3DRMERR_BADFILE (hr = %x)\n", hr);
193
194     info.lpMemory = data_no_mesh;
195     info.dSize = strlen(data_no_mesh);
196     hr = IDirect3DRMMeshBuilder_Load(pMeshBuilder, &info, NULL, D3DRMLOAD_FROMMEMORY, NULL, NULL);
197     ok(hr == D3DRMERR_NOTFOUND, "Should have returned D3DRMERR_NOTFOUND (hr = %x)\n", hr);
198
199     info.lpMemory = data_ok;
200     info.dSize = strlen(data_ok);
201     hr = IDirect3DRMMeshBuilder_Load(pMeshBuilder, &info, NULL, D3DRMLOAD_FROMMEMORY, NULL, NULL);
202     ok(hr == D3DRM_OK, "Cannot load mesh data (hr = %x)\n", hr);
203
204     val = IDirect3DRMMeshBuilder_GetVertexCount(pMeshBuilder);
205     ok(val == 4, "Wrong number of vertices %d (must be 4)\n", val);
206
207     val = IDirect3DRMMeshBuilder_GetFaceCount(pMeshBuilder);
208     ok(val == 3, "Wrong number of faces %d (must be 3)\n", val);
209
210     hr = IDirect3DRMMeshBuilder_GetVertices(pMeshBuilder, &val1, NULL, &val2, NULL, &val3, NULL);
211     ok(hr == D3DRM_OK, "Cannot get vertices information (hr = %x)\n", hr);
212     ok(val1 == 4, "Wrong number of vertices %d (must be 4)\n", val1);
213     todo_wine ok(val2 == 4, "Wrong number of normals %d (must be 4)\n", val2);
214     ok(val3 == 22, "Wrong number of face data bytes %d (must be 22)\n", val3);
215
216     /* Check that Load method generated default texture coordinates (0.0f, 0.0f) for each vertex */
217     valu = 1.23f;
218     valv = 3.21f;
219     hr = IDirect3DRMMeshBuilder_GetTextureCoordinates(pMeshBuilder, 0, &valu, &valv);
220     ok(hr == D3DRM_OK, "Cannot get texture coordinates (hr = %x)\n", hr);
221     ok(valu == 0.0f, "Wrong coordinate %f (must be 0.0)\n", valu);
222     ok(valv == 0.0f, "Wrong coordinate %f (must be 0.0)\n", valv);
223     valu = 1.23f;
224     valv = 3.21f;
225     hr = IDirect3DRMMeshBuilder_GetTextureCoordinates(pMeshBuilder, 1, &valu, &valv);
226     ok(hr == D3DRM_OK, "Cannot get texture coordinates (hr = %x)\n", hr);
227     ok(valu == 0.0f, "Wrong coordinate %f (must be 0.0)\n", valu);
228     ok(valv == 0.0f, "Wrong coordinate %f (must be 0.0)\n", valv);
229     valu = 1.23f;
230     valv = 3.21f;
231     hr = IDirect3DRMMeshBuilder_GetTextureCoordinates(pMeshBuilder, 2, &valu, &valv);
232     ok(hr == D3DRM_OK, "Cannot get texture coordinates (hr = %x)\n", hr);
233     ok(valu == 0.0f, "Wrong coordinate %f (must be 0.0)\n", valu);
234     ok(valv == 0.0f, "Wrong coordinate %f (must be 0.0)\n", valv);
235     valu = 1.23f;
236     valv = 3.21f;
237     hr = IDirect3DRMMeshBuilder_GetTextureCoordinates(pMeshBuilder, 3, &valu, &valv);
238     ok(hr == D3DRM_OK, "Cannot get texture coordinates (hr = %x)\n", hr);
239     ok(valu == 0.0f, "Wrong coordinate %f (must be 0.0)\n", valu);
240     ok(valv == 0.0f, "Wrong coordinate %f (must be 0.0)\n", valv);
241     hr = IDirect3DRMMeshBuilder_GetTextureCoordinates(pMeshBuilder, 4, &valu, &valv);
242     ok(hr == D3DRMERR_BADVALUE, "Should fail and return D3DRM_BADVALUE (hr = %x)\n", hr);
243
244     valu = 1.23f;
245     valv = 3.21f;
246     hr = IDirect3DRMMeshBuilder_SetTextureCoordinates(pMeshBuilder, 0, valu, valv);
247     ok(hr == D3DRM_OK, "Cannot set texture coordinates (hr = %x)\n", hr);
248     hr = IDirect3DRMMeshBuilder_SetTextureCoordinates(pMeshBuilder, 4, valu, valv);
249     ok(hr == D3DRMERR_BADVALUE, "Should fail and return D3DRM_BADVALUE (hr = %x)\n", hr);
250
251     valu = 0.0f;
252     valv = 0.0f;
253     hr = IDirect3DRMMeshBuilder_GetTextureCoordinates(pMeshBuilder, 0, &valu, &valv);
254     ok(hr == D3DRM_OK, "Cannot get texture coordinates (hr = %x)\n", hr);
255     ok(valu == 1.23f, "Wrong coordinate %f (must be 1.23)\n", valu);
256     ok(valv == 3.21f, "Wrong coordinate %f (must be 3.21)\n", valv);
257
258     IDirect3DRMMeshBuilder_Release(pMeshBuilder);
259
260     hr = IDirect3DRM_CreateMeshBuilder(pD3DRM, &pMeshBuilder);
261     ok(hr == D3DRM_OK, "Cannot get IDirect3DRMMeshBuilder interface (hr = %x)\n", hr);
262
263     info.lpMemory = data_full;
264     info.dSize = strlen(data_full);
265     hr = IDirect3DRMMeshBuilder_Load(pMeshBuilder, &info, NULL, D3DRMLOAD_FROMMEMORY, NULL, NULL);
266     ok(hr == D3DRM_OK, "Cannot load mesh data (hr = %x)\n", hr);
267
268     val = IDirect3DRMMeshBuilder_GetVertexCount(pMeshBuilder);
269     ok(val == 3, "Wrong number of vertices %d (must be 3)\n", val);
270
271     val = IDirect3DRMMeshBuilder_GetFaceCount(pMeshBuilder);
272     ok(val == 1, "Wrong number of faces %d (must be 1)\n", val);
273
274     hr = IDirect3DRMMeshBuilder_GetVertices(pMeshBuilder, &val1, v, &val2, n, &val3, f);
275     ok(hr == D3DRM_OK, "Cannot get vertices information (hr = %x)\n", hr);
276     ok(val1 == 3, "Wrong number of vertices %d (must be 3)\n", val1);
277     ok(val2 == 3, "Wrong number of normals %d (must be 3)\n", val2);
278     ok(val3 == 8, "Wrong number of face data bytes %d (must be 8)\n", val3);
279     ok(U1(v[0]).x == 0.1f, "Wrong component v[0].x = %f (expected 0.1)\n", U1(v[0]).x);
280     ok(U2(v[0]).y == 0.2f, "Wrong component v[0].y = %f (expected 0.2)\n", U2(v[0]).y);
281     ok(U3(v[0]).z == 0.3f, "Wrong component v[0].z = %f (expected 0.3)\n", U3(v[0]).z);
282     ok(U1(v[1]).x == 0.4f, "Wrong component v[1].x = %f (expected 0.4)\n", U1(v[1]).x);
283     ok(U2(v[1]).y == 0.5f, "Wrong component v[1].y = %f (expected 0.5)\n", U2(v[1]).y);
284     ok(U3(v[1]).z == 0.6f, "Wrong component v[1].z = %f (expected 0.6)\n", U3(v[1]).z);
285     ok(U1(v[2]).x == 0.7f, "Wrong component v[2].x = %f (expected 0.7)\n", U1(v[2]).x);
286     ok(U2(v[2]).y == 0.8f, "Wrong component v[2].y = %f (expected 0.8)\n", U2(v[2]).y);
287     ok(U3(v[2]).z == 0.9f, "Wrong component v[2].z = %f (expected 0.9)\n", U3(v[2]).z);
288     ok(U1(n[0]).x == 1.1f, "Wrong component n[0].x = %f (expected 1.1)\n", U1(n[0]).x);
289     ok(U2(n[0]).y == 1.2f, "Wrong component n[0].y = %f (expected 1.2)\n", U2(n[0]).y);
290     ok(U3(n[0]).z == 1.3f, "Wrong component n[0].z = %f (expected 1.3)\n", U3(n[0]).z);
291     ok(U1(n[1]).x == 1.4f, "Wrong component n[1].x = %f (expected 1.4)\n", U1(n[1]).x);
292     ok(U2(n[1]).y == 1.5f, "Wrong component n[1].y = %f (expected 1.5)\n", U2(n[1]).y);
293     ok(U3(n[1]).z == 1.6f, "Wrong component n[1].z = %f (expected 1.6)\n", U3(n[1]).z);
294     ok(U1(n[2]).x == 1.7f, "Wrong component n[2].x = %f (expected 1.7)\n", U1(n[2]).x);
295     ok(U2(n[2]).y == 1.8f, "Wrong component n[2].y = %f (expected 1.8)\n", U2(n[2]).y);
296     ok(U3(n[2]).z == 1.9f, "Wrong component n[2].z = %f (expected 1.9)\n", U3(n[2]).z);
297     ok(f[0] == 3 , "Wrong component f[0] = %d (expected 3)\n", f[0]);
298     ok(f[1] == 0 , "Wrong component f[1] = %d (expected 0)\n", f[1]);
299     ok(f[2] == 0 , "Wrong component f[2] = %d (expected 0)\n", f[2]);
300     ok(f[3] == 1 , "Wrong component f[3] = %d (expected 1)\n", f[3]);
301     ok(f[4] == 1 , "Wrong component f[4] = %d (expected 1)\n", f[4]);
302     ok(f[5] == 2 , "Wrong component f[5] = %d (expected 2)\n", f[5]);
303     ok(f[6] == 2 , "Wrong component f[6] = %d (expected 2)\n", f[6]);
304     ok(f[7] == 0 , "Wrong component f[7] = %d (expected 0)\n", f[7]);
305
306     IDirect3DRMMeshBuilder_Release(pMeshBuilder);
307
308     IDirect3DRM_Release(pD3DRM);
309 }
310
311 static void test_MeshBuilder3(void)
312 {
313     HRESULT hr;
314     LPDIRECT3DRM pD3DRM;
315     LPDIRECT3DRM3 pD3DRM3;
316     LPDIRECT3DRMMESHBUILDER3 pMeshBuilder3;
317     D3DRMLOADMEMORY info;
318     int val;
319     DWORD val1;
320     D3DVALUE valu, valv;
321
322     hr = pDirect3DRMCreate(&pD3DRM);
323     ok(hr == D3DRM_OK, "Cannot get IDirect3DRM interface (hr = %x)\n", hr);
324
325     hr = IDirect3DRM_QueryInterface(pD3DRM, &IID_IDirect3DRM3, (LPVOID*)&pD3DRM3);
326     if (FAILED(hr))
327     {
328         win_skip("Cannot get IDirect3DRM3 interface (hr = %x), skipping tests\n", hr);
329         IDirect3DRM_Release(pD3DRM);
330         return;
331     }
332
333     hr = IDirect3DRM3_CreateMeshBuilder(pD3DRM3, &pMeshBuilder3);
334     ok(hr == D3DRM_OK, "Cannot get IDirect3DRMMeshBuilder3 interface (hr = %x)\n", hr);
335
336     info.lpMemory = data_bad_version;
337     info.dSize = strlen(data_bad_version);
338     hr = IDirect3DRMMeshBuilder3_Load(pMeshBuilder3, &info, NULL, D3DRMLOAD_FROMMEMORY, NULL, NULL);
339     ok(hr == D3DRMERR_BADFILE, "Should have returned D3DRMERR_BADFILE (hr = %x)\n", hr);
340
341     info.lpMemory = data_no_mesh;
342     info.dSize = strlen(data_no_mesh);
343     hr = IDirect3DRMMeshBuilder3_Load(pMeshBuilder3, &info, NULL, D3DRMLOAD_FROMMEMORY, NULL, NULL);
344     ok(hr == D3DRMERR_NOTFOUND, "Should have returned D3DRMERR_NOTFOUND (hr = %x)\n", hr);
345
346     info.lpMemory = data_ok;
347     info.dSize = strlen(data_ok);
348     hr = IDirect3DRMMeshBuilder3_Load(pMeshBuilder3, &info, NULL, D3DRMLOAD_FROMMEMORY, NULL, NULL);
349     ok(hr == D3DRM_OK, "Cannot load mesh data (hr = %x)\n", hr);
350
351     val = IDirect3DRMMeshBuilder3_GetVertexCount(pMeshBuilder3);
352     ok(val == 4, "Wrong number of vertices %d (must be 4)\n", val);
353
354     val = IDirect3DRMMeshBuilder3_GetFaceCount(pMeshBuilder3);
355     ok(val == 3, "Wrong number of faces %d (must be 3)\n", val);
356
357     hr = IDirect3DRMMeshBuilder3_GetVertices(pMeshBuilder3, 0, &val1, NULL);
358     ok(hr == D3DRM_OK, "Cannot get vertices information (hr = %x)\n", hr);
359     ok(val1 == 4, "Wrong number of vertices %d (must be 4)\n", val1);
360
361     /* Check that Load method generated default texture coordinates (0.0f, 0.0f) for each vertex */
362     valu = 1.23f;
363     valv = 3.21f;
364     hr = IDirect3DRMMeshBuilder3_GetTextureCoordinates(pMeshBuilder3, 0, &valu, &valv);
365     ok(hr == D3DRM_OK, "Cannot get texture coordinates (hr = %x)\n", hr);
366     ok(valu == 0.0f, "Wrong coordinate %f (must be 0.0)\n", valu);
367     ok(valv == 0.0f, "Wrong coordinate %f (must be 0.0)\n", valv);
368     valu = 1.23f;
369     valv = 3.21f;
370     hr = IDirect3DRMMeshBuilder3_GetTextureCoordinates(pMeshBuilder3, 1, &valu, &valv);
371     ok(hr == D3DRM_OK, "Cannot get texture coordinates (hr = %x)\n", hr);
372     ok(valu == 0.0f, "Wrong coordinate %f (must be 0.0)\n", valu);
373     ok(valv == 0.0f, "Wrong coordinate %f (must be 0.0)\n", valv);
374     valu = 1.23f;
375     valv = 3.21f;
376     hr = IDirect3DRMMeshBuilder3_GetTextureCoordinates(pMeshBuilder3, 2, &valu, &valv);
377     ok(hr == D3DRM_OK, "Cannot get texture coordinates (hr = %x)\n", hr);
378     ok(valu == 0.0f, "Wrong coordinate %f (must be 0.0)\n", valu);
379     ok(valv == 0.0f, "Wrong coordinate %f (must be 0.0)\n", valv);
380     valu = 1.23f;
381     valv = 3.21f;
382     hr = IDirect3DRMMeshBuilder3_GetTextureCoordinates(pMeshBuilder3, 3, &valu, &valv);
383     ok(hr == D3DRM_OK, "Cannot get texture coordinates (hr = %x)\n", hr);
384     ok(valu == 0.0f, "Wrong coordinate %f (must be 0.0)\n", valu);
385     ok(valv == 0.0f, "Wrong coordinate %f (must be 0.0)\n", valv);
386     hr = IDirect3DRMMeshBuilder3_GetTextureCoordinates(pMeshBuilder3, 4, &valu, &valv);
387     ok(hr == D3DRMERR_BADVALUE, "Should fail and return D3DRM_BADVALUE (hr = %x)\n", hr);
388
389     valu = 1.23f;
390     valv = 3.21f;
391     hr = IDirect3DRMMeshBuilder3_SetTextureCoordinates(pMeshBuilder3, 0, valu, valv);
392     ok(hr == D3DRM_OK, "Cannot set texture coordinates (hr = %x)\n", hr);
393     hr = IDirect3DRMMeshBuilder3_SetTextureCoordinates(pMeshBuilder3, 4, valu, valv);
394     ok(hr == D3DRMERR_BADVALUE, "Should fail and return D3DRM_BADVALUE (hr = %x)\n", hr);
395
396     valu = 0.0f;
397     valv = 0.0f;
398     hr = IDirect3DRMMeshBuilder3_GetTextureCoordinates(pMeshBuilder3, 0, &valu, &valv);
399     ok(hr == D3DRM_OK, "Cannot get texture coordinates (hr = %x)\n", hr);
400     ok(valu == 1.23f, "Wrong coordinate %f (must be 1.23)\n", valu);
401     ok(valv == 3.21f, "Wrong coordinate %f (must be 3.21)\n", valv);
402
403     IDirect3DRMMeshBuilder3_Release(pMeshBuilder3);
404     IDirect3DRM3_Release(pD3DRM3);
405     IDirect3DRM_Release(pD3DRM);
406 }
407
408 static void test_Frame(void)
409 {
410     HRESULT hr;
411     LPDIRECT3DRM pD3DRM;
412     LPDIRECT3DRMFRAME pFrameC;
413     LPDIRECT3DRMFRAME pFrameP1;
414     LPDIRECT3DRMFRAME pFrameP2;
415     LPDIRECT3DRMFRAME pFrameTmp;
416     LPDIRECT3DRMFRAMEARRAY pArray;
417     LPDIRECT3DRMMESHBUILDER pMeshBuilder;
418     LPDIRECT3DRMVISUAL pVisual1;
419     LPDIRECT3DRMVISUAL pVisualTmp;
420     LPDIRECT3DRMVISUALARRAY pVisualArray;
421     LPDIRECT3DRMLIGHT pLight1;
422     LPDIRECT3DRMLIGHT pLightTmp;
423     LPDIRECT3DRMLIGHTARRAY pLightArray;
424     DWORD count;
425
426     hr = pDirect3DRMCreate(&pD3DRM);
427     ok(hr == D3DRM_OK, "Cannot get IDirect3DRM interface (hr = %x)\n", hr);
428
429     hr = IDirect3DRM_CreateFrame(pD3DRM, NULL, &pFrameC);
430     ok(hr == D3DRM_OK, "Cannot get IDirect3DRMFrame interface (hr = %x)\n", hr);
431     CHECK_REFCOUNT(pFrameC, 1);
432
433     hr = IDirect3DRMFrame_GetParent(pFrameC, NULL);
434     ok(hr == D3DRMERR_BADVALUE, "Should fail and return D3DRM_BADVALUE (hr = %x)\n", hr);
435     pFrameTmp = (void*)0xdeadbeef;
436     hr = IDirect3DRMFrame_GetParent(pFrameC, &pFrameTmp);
437     ok(hr == D3DRM_OK, "Cannot get parent frame (hr = %x)\n", hr);
438     ok(pFrameTmp == NULL, "pFrameTmp = %p\n", pFrameTmp);
439     CHECK_REFCOUNT(pFrameC, 1);
440
441     pArray = NULL;
442     hr = IDirect3DRMFrame_GetChildren(pFrameC, &pArray);
443     ok(hr == D3DRM_OK, "Cannot get children (hr = %x)\n", hr);
444     ok(pArray != NULL, "pArray = %p\n", pArray);
445     if (pArray)
446     {
447         count = IDirect3DRMFrameArray_GetSize(pArray);
448         ok(count == 0, "count = %u\n", count);
449         hr = IDirect3DRMFrameArray_GetElement(pArray, 0, &pFrameTmp);
450         ok(hr == D3DRMERR_BADVALUE, "Should have returned D3DRMERR_BADVALUE (hr = %x)\n", hr);
451         ok(pFrameTmp == NULL, "pFrameTmp = %p\n", pFrameTmp);
452         IDirect3DRMFrameArray_Release(pArray);
453     }
454
455     hr = IDirect3DRM_CreateFrame(pD3DRM, NULL, &pFrameP1);
456     ok(hr == D3DRM_OK, "Cannot get IDirect3DRMFrame interface (hr = %x)\n", hr);
457
458     /* GetParent with NULL pointer */
459     hr = IDirect3DRMFrame_GetParent(pFrameP1, NULL);
460     ok(hr == D3DRMERR_BADVALUE, "Should have returned D3DRMERR_BADVALUE (hr = %x)\n", hr);
461     CHECK_REFCOUNT(pFrameP1, 1);
462
463     /* [Add/Delete]Child with NULL pointer */
464     hr = IDirect3DRMFrame_AddChild(pFrameP1, NULL);
465     ok(hr == D3DRMERR_BADOBJECT, "Should have returned D3DRMERR_BADOBJECT (hr = %x)\n", hr);
466     CHECK_REFCOUNT(pFrameP1, 1);
467
468     hr = IDirect3DRMFrame_DeleteChild(pFrameP1, NULL);
469     ok(hr == D3DRMERR_BADOBJECT, "Should have returned D3DRMERR_BADOBJECT (hr = %x)\n", hr);
470     CHECK_REFCOUNT(pFrameP1, 1);
471
472     /* Add child to first parent */
473     pFrameTmp = (void*)0xdeadbeef;
474     hr = IDirect3DRMFrame_GetParent(pFrameP1, &pFrameTmp);
475     ok(hr == D3DRM_OK, "Cannot get parent frame (hr = %x)\n", hr);
476     ok(pFrameTmp == NULL, "pFrameTmp = %p\n", pFrameTmp);
477
478     hr = IDirect3DRMFrame_AddChild(pFrameP1, pFrameC);
479     ok(hr == D3DRM_OK, "Cannot add child frame (hr = %x)\n", hr);
480     CHECK_REFCOUNT(pFrameP1, 1);
481     CHECK_REFCOUNT(pFrameC, 2);
482
483     pArray = NULL;
484     hr = IDirect3DRMFrame_GetChildren(pFrameP1, &pArray);
485     ok(hr == D3DRM_OK, "Cannot get children (hr = %x)\n", hr);
486     /* In some older version of d3drm, creating IDirect3DRMFrameArray object with GetChildren does not increment refcount of children frames */
487     ok((get_refcount((IUnknown*)pFrameC) == 3) || broken(get_refcount((IUnknown*)pFrameC) == 2), "Invalid refcount. Expected 3 (or 2) got %d\n", get_refcount((IUnknown*)pFrameC)); \
488     if (pArray)
489     {
490         count = IDirect3DRMFrameArray_GetSize(pArray);
491         ok(count == 1, "count = %u\n", count);
492         hr = IDirect3DRMFrameArray_GetElement(pArray, 0, &pFrameTmp);
493         ok(hr == D3DRM_OK, "Cannot get element (hr = %x)\n", hr);
494         ok(pFrameTmp == pFrameC, "pFrameTmp = %p\n", pFrameTmp);
495         ok((get_refcount((IUnknown*)pFrameC) == 4) || broken(get_refcount((IUnknown*)pFrameC) == 3), "Invalid refcount. Expected 4 (or 3) got %d\n", get_refcount((IUnknown*)pFrameC)); \
496         IDirect3DRMFrame_Release(pFrameTmp);
497         ok((get_refcount((IUnknown*)pFrameC) == 3) || broken(get_refcount((IUnknown*)pFrameC) == 2), "Invalid refcount. Expected 3 (or 2) got %d\n", get_refcount((IUnknown*)pFrameC)); \
498         IDirect3DRMFrameArray_Release(pArray);
499         CHECK_REFCOUNT(pFrameC, 2);
500     }
501
502     pFrameTmp = (void*)0xdeadbeef;
503     hr = IDirect3DRMFrame_GetParent(pFrameC, &pFrameTmp);
504     ok(hr == D3DRM_OK, "Cannot get parent frame (hr = %x)\n", hr);
505     ok(pFrameTmp == pFrameP1, "pFrameTmp = %p\n", pFrameTmp);
506     CHECK_REFCOUNT(pFrameP1, 2);
507
508     /* Add child to second parent */
509     hr = IDirect3DRM_CreateFrame(pD3DRM, NULL, &pFrameP2);
510     ok(hr == D3DRM_OK, "Cannot get IDirect3DRMFrame interface (hr = %x)\n", hr);
511
512     hr = IDirect3DRMFrame_AddChild(pFrameP2, pFrameC);
513     ok(hr == D3DRM_OK, "Cannot add child frame (hr = %x)\n", hr);
514     CHECK_REFCOUNT(pFrameC, 2);
515
516     pArray = NULL;
517     hr = IDirect3DRMFrame_GetChildren(pFrameP2, &pArray);
518     ok(hr == D3DRM_OK, "Cannot get children (hr = %x)\n", hr);
519     if (pArray)
520     {
521         count = IDirect3DRMFrameArray_GetSize(pArray);
522         ok(count == 1, "count = %u\n", count);
523         hr = IDirect3DRMFrameArray_GetElement(pArray, 0, &pFrameTmp);
524         ok(hr == D3DRM_OK, "Cannot get element (hr = %x)\n", hr);
525         ok(pFrameTmp == pFrameC, "pFrameTmp = %p\n", pFrameTmp);
526         IDirect3DRMFrame_Release(pFrameTmp);
527         IDirect3DRMFrameArray_Release(pArray);
528     }
529
530     pArray = NULL;
531     hr = IDirect3DRMFrame_GetChildren(pFrameP1, &pArray);
532     ok(hr == D3DRM_OK, "Cannot get children (hr = %x)\n", hr);
533     if (pArray)
534     {
535         count = IDirect3DRMFrameArray_GetSize(pArray);
536         ok(count == 0, "count = %u\n", count);
537         pFrameTmp = (void*)0xdeadbeef;
538         hr = IDirect3DRMFrameArray_GetElement(pArray, 0, &pFrameTmp);
539         ok(hr == D3DRMERR_BADVALUE, "Should have returned D3DRMERR_BADVALUE (hr = %x)\n", hr);
540         ok(pFrameTmp == NULL, "pFrameTmp = %p\n", pFrameTmp);
541         IDirect3DRMFrameArray_Release(pArray);
542     }
543
544     pFrameTmp = (void*)0xdeadbeef;
545     hr = IDirect3DRMFrame_GetParent(pFrameC, &pFrameTmp);
546     ok(hr == D3DRM_OK, "Cannot get parent frame (hr = %x)\n", hr);
547     ok(pFrameTmp == pFrameP2, "pFrameTmp = %p\n", pFrameTmp);
548     CHECK_REFCOUNT(pFrameP2, 2);
549     CHECK_REFCOUNT(pFrameC, 2);
550
551     /* Add child again */
552     hr = IDirect3DRMFrame_AddChild(pFrameP2, pFrameC);
553     ok(hr == D3DRM_OK, "Cannot add child frame (hr = %x)\n", hr);
554     CHECK_REFCOUNT(pFrameC, 2);
555
556     pArray = NULL;
557     hr = IDirect3DRMFrame_GetChildren(pFrameP2, &pArray);
558     ok(hr == D3DRM_OK, "Cannot get children (hr = %x)\n", hr);
559     if (pArray)
560     {
561         count = IDirect3DRMFrameArray_GetSize(pArray);
562         ok(count == 1, "count = %u\n", count);
563         hr = IDirect3DRMFrameArray_GetElement(pArray, 0, &pFrameTmp);
564         ok(hr == D3DRM_OK, "Cannot get element (hr = %x)\n", hr);
565         ok(pFrameTmp == pFrameC, "pFrameTmp = %p\n", pFrameTmp);
566         IDirect3DRMFrame_Release(pFrameTmp);
567         IDirect3DRMFrameArray_Release(pArray);
568     }
569
570     /* Delete child */
571     hr = IDirect3DRMFrame_DeleteChild(pFrameP2, pFrameC);
572     ok(hr == D3DRM_OK, "Cannot delete child frame (hr = %x)\n", hr);
573     CHECK_REFCOUNT(pFrameC, 1);
574
575     pArray = NULL;
576     hr = IDirect3DRMFrame_GetChildren(pFrameP2, &pArray);
577     ok(hr == D3DRM_OK, "Cannot get children (hr = %x)\n", hr);
578     if (pArray)
579     {
580         count = IDirect3DRMFrameArray_GetSize(pArray);
581         ok(count == 0, "count = %u\n", count);
582         pFrameTmp = (void*)0xdeadbeef;
583         hr = IDirect3DRMFrameArray_GetElement(pArray, 0, &pFrameTmp);
584         ok(hr == D3DRMERR_BADVALUE, "Should have returned D3DRMERR_BADVALUE (hr = %x)\n", hr);
585         ok(pFrameTmp == NULL, "pFrameTmp = %p\n", pFrameTmp);
586         IDirect3DRMFrameArray_Release(pArray);
587     }
588
589     pFrameTmp = (void*)0xdeadbeef;
590     hr = IDirect3DRMFrame_GetParent(pFrameC, &pFrameTmp);
591     ok(hr == D3DRM_OK, "Cannot get parent frame (hr = %x)\n", hr);
592     ok(pFrameTmp == NULL, "pFrameTmp = %p\n", pFrameTmp);
593
594     /* Add two children */
595     hr = IDirect3DRMFrame_AddChild(pFrameP2, pFrameC);
596     ok(hr == D3DRM_OK, "Cannot add child frame (hr = %x)\n", hr);
597     CHECK_REFCOUNT(pFrameC, 2);
598
599     hr = IDirect3DRMFrame_AddChild(pFrameP2, pFrameP1);
600     ok(hr == D3DRM_OK, "Cannot add child frame (hr = %x)\n", hr);
601     CHECK_REFCOUNT(pFrameP1, 3);
602
603     pArray = NULL;
604     hr = IDirect3DRMFrame_GetChildren(pFrameP2, &pArray);
605     ok(hr == D3DRM_OK, "Cannot get children (hr = %x)\n", hr);
606     if (pArray)
607     {
608         count = IDirect3DRMFrameArray_GetSize(pArray);
609         ok(count == 2, "count = %u\n", count);
610         hr = IDirect3DRMFrameArray_GetElement(pArray, 0, &pFrameTmp);
611         ok(hr == D3DRM_OK, "Cannot get element (hr = %x)\n", hr);
612         ok(pFrameTmp == pFrameC, "pFrameTmp = %p\n", pFrameTmp);
613         IDirect3DRMFrame_Release(pFrameTmp);
614         hr = IDirect3DRMFrameArray_GetElement(pArray, 1, &pFrameTmp);
615         ok(hr == D3DRM_OK, "Cannot get element (hr = %x)\n", hr);
616         ok(pFrameTmp == pFrameP1, "pFrameTmp = %p\n", pFrameTmp);
617         IDirect3DRMFrame_Release(pFrameTmp);
618         IDirect3DRMFrameArray_Release(pArray);
619     }
620
621     /* [Add/Delete]Visual with NULL pointer */
622     hr = IDirect3DRMFrame_AddVisual(pFrameP1, NULL);
623     ok(hr == D3DRMERR_BADOBJECT, "Should have returned D3DRMERR_BADOBJECT (hr = %x)\n", hr);
624     CHECK_REFCOUNT(pFrameP1, 3);
625
626     hr = IDirect3DRMFrame_DeleteVisual(pFrameP1, NULL);
627     ok(hr == D3DRMERR_BADOBJECT, "Should have returned D3DRMERR_BADOBJECT (hr = %x)\n", hr);
628     CHECK_REFCOUNT(pFrameP1, 3);
629
630     /* Create Visual */
631     hr = IDirect3DRM_CreateMeshBuilder(pD3DRM, &pMeshBuilder);
632     ok(hr == D3DRM_OK, "Cannot get IDirect3DRMMeshBuilder interface (hr = %x)\n", hr);
633     pVisual1 = (LPDIRECT3DRMVISUAL)pMeshBuilder;
634
635     /* Add Visual to first parent */
636     hr = IDirect3DRMFrame_AddVisual(pFrameP1, pVisual1);
637     ok(hr == D3DRM_OK, "Cannot add visual (hr = %x)\n", hr);
638     CHECK_REFCOUNT(pFrameP1, 3);
639     CHECK_REFCOUNT(pVisual1, 2);
640
641     pVisualArray = NULL;
642     hr = IDirect3DRMFrame_GetVisuals(pFrameP1, &pVisualArray);
643     todo_wine ok(hr == D3DRM_OK, "Cannot get visuals (hr = %x)\n", hr);
644     if (pVisualArray)
645     {
646         count = IDirect3DRMVisualArray_GetSize(pVisualArray);
647         ok(count == 1, "count = %u\n", count);
648         hr = IDirect3DRMVisualArray_GetElement(pVisualArray, 0, &pVisualTmp);
649         ok(hr == D3DRM_OK, "Cannot get element (hr = %x)\n", hr);
650         ok(pVisualTmp == pVisual1, "pVisualTmp = %p\n", pVisualTmp);
651         IDirect3DRMVisual_Release(pVisualTmp);
652         IDirect3DRMVisualArray_Release(pVisualArray);
653     }
654
655     /* Delete Visual */
656     hr = IDirect3DRMFrame_DeleteVisual(pFrameP1, pVisual1);
657     ok(hr == D3DRM_OK, "Cannot delete visual (hr = %x)\n", hr);
658     CHECK_REFCOUNT(pFrameP1, 3);
659     IDirect3DRMMeshBuilder_Release(pMeshBuilder);
660
661     /* [Add/Delete]Light with NULL pointer */
662     hr = IDirect3DRMFrame_AddLight(pFrameP1, NULL);
663     ok(hr == D3DRMERR_BADOBJECT, "Should have returned D3DRMERR_BADOBJECT (hr = %x)\n", hr);
664     CHECK_REFCOUNT(pFrameP1, 3);
665
666     hr = IDirect3DRMFrame_DeleteLight(pFrameP1, NULL);
667     ok(hr == D3DRMERR_BADOBJECT, "Should have returned D3DRMERR_BADOBJECT (hr = %x)\n", hr);
668     CHECK_REFCOUNT(pFrameP1, 3);
669
670     /* Create Light */
671     hr = IDirect3DRM_CreateLightRGB(pD3DRM, D3DRMLIGHT_SPOT, 0.1, 0.2, 0.3, &pLight1);
672     ok(hr == D3DRM_OK, "Cannot get IDirect3DRMLight interface (hr = %x)\n", hr);
673
674     /* Add Light to first parent */
675     hr = IDirect3DRMFrame_AddLight(pFrameP1, pLight1);
676     ok(hr == D3DRM_OK, "Cannot add light (hr = %x)\n", hr);
677     CHECK_REFCOUNT(pFrameP1, 3);
678     CHECK_REFCOUNT(pLight1, 2);
679
680     pLightArray = NULL;
681     hr = IDirect3DRMFrame_GetLights(pFrameP1, &pLightArray);
682     todo_wine ok(hr == D3DRM_OK, "Cannot get lights (hr = %x)\n", hr);
683     if (pLightArray)
684     {
685         count = IDirect3DRMLightArray_GetSize(pLightArray);
686         ok(count == 1, "count = %u\n", count);
687         hr = IDirect3DRMLightArray_GetElement(pLightArray, 0, &pLightTmp);
688         ok(hr == D3DRM_OK, "Cannot get element (hr = %x)\n", hr);
689         ok(pLightTmp == pLight1, "pLightTmp = %p\n", pLightTmp);
690         IDirect3DRMLight_Release(pLightTmp);
691         IDirect3DRMLightArray_Release(pLightArray);
692     }
693
694     /* Delete Light */
695     hr = IDirect3DRMFrame_DeleteLight(pFrameP1, pLight1);
696     ok(hr == D3DRM_OK, "Cannot delete light (hr = %x)\n", hr);
697     CHECK_REFCOUNT(pFrameP1, 3);
698     IDirect3DRMLight_Release(pLight1);
699
700     /* Cleanup */
701     IDirect3DRMFrame_Release(pFrameP2);
702     CHECK_REFCOUNT(pFrameC, 2);
703     CHECK_REFCOUNT(pFrameP1, 3);
704
705     IDirect3DRMFrame_Release(pFrameC);
706     IDirect3DRMFrame_Release(pFrameP1);
707
708     IDirect3DRM_Release(pD3DRM);
709 }
710
711 static void test_Light(void)
712 {
713     HRESULT hr;
714     LPDIRECT3DRM pD3DRM;
715     LPDIRECT3DRMLIGHT pLight;
716     D3DRMLIGHTTYPE type;
717     D3DCOLOR color;
718
719     hr = pDirect3DRMCreate(&pD3DRM);
720     ok(hr == D3DRM_OK, "Cannot get IDirect3DRM interface (hr = %x)\n", hr);
721
722     hr = IDirect3DRM_CreateLightRGB(pD3DRM, D3DRMLIGHT_SPOT, 0.5, 0.5, 0.5, &pLight);
723     ok(hr == D3DRM_OK, "Cannot get IDirect3DRMLight interface (hr = %x)\n", hr);
724
725     type = IDirect3DRMLight_GetType(pLight);
726     todo_wine ok(type == D3DRMLIGHT_SPOT, "wrong type (%u)\n", type);
727
728     color = IDirect3DRMLight_GetColor(pLight);
729     todo_wine ok(color == 0xff7f7f7f, "wrong color (%x)\n", color);
730
731     hr = IDirect3DRMLight_SetType(pLight, D3DRMLIGHT_POINT);
732     todo_wine ok(hr == D3DRM_OK, "Cannot set type (hr = %x)\n", hr);
733     type = IDirect3DRMLight_GetType(pLight);
734     todo_wine ok(type == D3DRMLIGHT_POINT, "wrong type (%u)\n", type);
735
736     hr = IDirect3DRMLight_SetColor(pLight, 0xff180587);
737     todo_wine ok(hr == D3DRM_OK, "Cannot set color (hr = %x)\n", hr);
738     color = IDirect3DRMLight_GetColor(pLight);
739     todo_wine ok(color == 0xff180587, "wrong color (%x)\n", color);
740
741     hr = IDirect3DRMLight_SetColorRGB(pLight, 0.5, 0.5, 0.5);
742     todo_wine ok(hr == D3DRM_OK, "Cannot set color (hr = %x)\n", hr);
743     color = IDirect3DRMLight_GetColor(pLight);
744     todo_wine ok(color == 0xff7f7f7f, "wrong color (%x)\n", color);
745
746     IDirect3DRMLight_Release(pLight);
747
748     IDirect3DRM_Release(pD3DRM);
749 }
750
751 static void test_frame_transform(void)
752 {
753     HRESULT hr;
754     LPDIRECT3DRM d3drm;
755     LPDIRECT3DRMFRAME frame;
756     D3DRMMATRIX4D matrix;
757
758     hr = pDirect3DRMCreate(&d3drm);
759     ok(hr == D3DRM_OK, "Cannot get IDirect3DRM interface (hr = %x)\n", hr);
760
761     hr = IDirect3DRM_CreateFrame(d3drm, NULL, &frame);
762     ok(hr == D3DRM_OK, "Cannot get IDirect3DRMFrame interface (hr = %x)\n", hr);
763
764     hr = IDirect3DRMFrame_GetTransform(frame, matrix);
765     ok(hr == D3DRM_OK, "IDirect3DRMFrame_GetTransform returned hr = %x\n", hr);
766     ok(!memcmp(matrix, identity, sizeof(D3DRMMATRIX4D)), "Returned matrix is not identity\n");
767
768     IDirect3DRM_Release(d3drm);
769 }
770
771 static int nb_objects = 0;
772 static const GUID* refiids[] =
773 {
774     &IID_IDirect3DRMMeshBuilder,
775     &IID_IDirect3DRMMeshBuilder,
776     &IID_IDirect3DRMFrame
777 };
778
779 static void __cdecl object_load_callback(LPDIRECT3DRMOBJECT object, REFIID objectguid, LPVOID arg)
780 {
781     ok(object != NULL, "Arg 1 should not be null\n");
782     ok(IsEqualGUID(objectguid, refiids[nb_objects]), "Arg 2 is incorrect\n");
783     ok(arg == (LPVOID)0xdeadbeef, "Arg 3 should be 0xdeadbeef (got %p)\n", arg);
784     nb_objects++;
785 }
786
787 static void test_d3drm_load(void)
788 {
789     HRESULT hr;
790     LPDIRECT3DRM pD3DRM;
791     D3DRMLOADMEMORY info;
792     const GUID* req_refiids[] = { &IID_IDirect3DRMMeshBuilder, &IID_IDirect3DRMFrame };
793
794     hr = pDirect3DRMCreate(&pD3DRM);
795     ok(hr == D3DRM_OK, "Cannot get IDirect3DRM interface (hr = %x)\n", hr);
796
797     info.lpMemory = data_d3drm_load;
798     info.dSize = strlen(data_d3drm_load);
799     hr = IDirect3DRM_Load(pD3DRM, &info, NULL, (GUID**)req_refiids, 2, D3DRMLOAD_FROMMEMORY, object_load_callback, (LPVOID)0xdeadbeef, NULL, NULL, NULL);
800     ok(hr == D3DRM_OK, "Cannot load data (hr = %x)\n", hr);
801     ok(nb_objects == 3, "Should have loaded 3 objects (got %d)\n", nb_objects);
802
803     IDirect3DRM_Release(pD3DRM);
804 }
805
806 START_TEST(d3drm)
807 {
808     if (!InitFunctionPtrs())
809         return;
810
811     test_MeshBuilder();
812     test_MeshBuilder3();
813     test_Frame();
814     test_Light();
815     test_frame_transform();
816     test_d3drm_load();
817
818     FreeLibrary(d3drm_handle);
819 }